summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--ChangeLog932
-rw-r--r--INSTALL43
-rw-r--r--Makefile.in90
-rw-r--r--PROTOCOL52
-rw-r--r--README4
-rw-r--r--auth-bsdauth.c9
-rw-r--r--auth-chall.c6
-rw-r--r--auth-krb5.c1
-rw-r--r--auth-options.c17
-rw-r--r--auth-passwd.c3
-rw-r--r--auth-rh-rsa.c3
-rw-r--r--auth-rhosts.c4
-rw-r--r--auth-rsa.c7
-rw-r--r--auth.c22
-rw-r--r--auth.h5
-rw-r--r--auth1.c5
-rw-r--r--auth2-chall.c1
-rw-r--r--auth2-gss.c1
-rw-r--r--auth2-hostbased.c3
-rw-r--r--auth2-kbdint.c3
-rw-r--r--auth2-none.c6
-rw-r--r--auth2-passwd.c3
-rw-r--r--auth2-pubkey.c8
-rw-r--r--auth2.c5
-rw-r--r--authfd.c22
-rw-r--r--authfile.c1395
-rw-r--r--authfile.h59
-rw-r--r--bufaux.c340
-rw-r--r--bufbn.c210
-rw-r--r--bufec.c106
-rw-r--r--buffer.c245
-rw-r--r--buffer.h68
-rw-r--r--canohost.c12
-rw-r--r--chacha.h2
-rw-r--r--channels.c693
-rw-r--r--channels.h31
-rw-r--r--cipher-3des1.c57
-rw-r--r--cipher-aesctr.c78
-rw-r--r--cipher-aesctr.h35
-rw-r--r--cipher-chachapoly.c31
-rw-r--r--cipher-chachapoly.h4
-rw-r--r--cipher.c407
-rw-r--r--cipher.h59
-rw-r--r--clientloop.c82
-rw-r--r--compat.c2
-rw-r--r--compat.h2
-rw-r--r--config.h.in18
-rwxr-xr-xconfigure193
-rw-r--r--configure.ac85
-rw-r--r--consolekit.c1
-rw-r--r--contrib/caldera/openssh.spec5
-rw-r--r--contrib/cygwin/README3
-rw-r--r--contrib/cygwin/ssh-host-config198
-rw-r--r--contrib/redhat/openssh.spec5
-rw-r--r--contrib/suse/openssh.spec5
-rw-r--r--debian/.git-dpm6
-rw-r--r--debian/changelog45
-rw-r--r--debian/patches/auth-log-verbosity.patch14
-rw-r--r--debian/patches/authorized-keys-man-symlink.patch6
-rw-r--r--debian/patches/consolekit.patch67
-rw-r--r--debian/patches/curve25519-sha256-bignum-encoding.patch161
-rw-r--r--debian/patches/debian-banner.patch50
-rw-r--r--debian/patches/debian-config.patch12
-rw-r--r--debian/patches/dnssec-sshfp.patch8
-rw-r--r--debian/patches/doc-hash-tab-completion.patch6
-rw-r--r--debian/patches/doc-upstart.patch6
-rw-r--r--debian/patches/gnome-ssh-askpass2-icon.patch2
-rw-r--r--debian/patches/gssapi.patch283
-rw-r--r--debian/patches/helpful-wait-terminate.patch4
-rw-r--r--debian/patches/keepalive-extensions.patch36
-rw-r--r--debian/patches/lintian-symlink-pickiness.patch6
-rw-r--r--debian/patches/mention-ssh-keygen-on-keychange.patch8
-rw-r--r--debian/patches/no-openssl-version-check.patch41
-rw-r--r--debian/patches/no-openssl-version-status.patch62
-rw-r--r--debian/patches/openbsd-docs.patch20
-rw-r--r--debian/patches/package-versioning.patch14
-rw-r--r--debian/patches/quieter-signals.patch6
-rw-r--r--debian/patches/restore-tcp-wrappers.patch172
-rw-r--r--debian/patches/scp-quoting.patch4
-rw-r--r--debian/patches/selinux-role.patch66
-rw-r--r--debian/patches/series5
-rw-r--r--debian/patches/shell-path.patch8
-rw-r--r--debian/patches/sigstop.patch6
-rw-r--r--debian/patches/ssh-agent-setgid.patch8
-rw-r--r--debian/patches/ssh-argv0.patch6
-rw-r--r--debian/patches/ssh-vulnkey-compat.patch10
-rw-r--r--debian/patches/ssh1-keepalive.patch8
-rw-r--r--debian/patches/sshfp_with_server_cert_upstr83
-rw-r--r--debian/patches/syslog-level-silent.patch6
-rw-r--r--debian/patches/user-group-modes.patch42
-rw-r--r--defines.h27
-rw-r--r--digest-libc.c27
-rw-r--r--digest-openssl.c60
-rw-r--r--digest.h8
-rw-r--r--dns.c9
-rw-r--r--dns.h5
-rw-r--r--entropy.c5
-rw-r--r--gss-serv-krb5.c1
-rw-r--r--gss-serv.c6
-rw-r--r--hmac.h5
-rw-r--r--hostfile.c9
-rw-r--r--kex.c18
-rw-r--r--kex.h2
-rw-r--r--kexc25519.c2
-rw-r--r--kexgsss.c1
-rw-r--r--key.c2751
-rw-r--r--key.h188
-rw-r--r--krl.c15
-rw-r--r--mac.c5
-rw-r--r--misc.c85
-rw-r--r--misc.h31
-rw-r--r--moduli.04
-rw-r--r--monitor.c33
-rw-r--r--monitor_fdpass.c11
-rw-r--r--monitor_wrap.c12
-rw-r--r--mux.c275
-rw-r--r--myproposal.h103
-rw-r--r--openbsd-compat/Makefile.in4
-rw-r--r--openbsd-compat/arc4random.c4
-rw-r--r--openbsd-compat/bsd-cygwin_util.c16
-rw-r--r--openbsd-compat/bsd-cygwin_util.h6
-rw-r--r--openbsd-compat/bsd-snprintf.c4
-rw-r--r--openbsd-compat/explicit_bzero.c26
-rw-r--r--openbsd-compat/kludge-fd_set.c28
-rw-r--r--openbsd-compat/openbsd-compat.h18
-rw-r--r--openbsd-compat/openssl-compat.c166
-rw-r--r--openbsd-compat/openssl-compat.h121
-rw-r--r--openbsd-compat/port-uw.c1
-rw-r--r--openbsd-compat/regress/Makefile.in6
-rw-r--r--openbsd-compat/regress/opensslvertest.c70
-rwxr-xr-xopensshd.init.in4
-rw-r--r--packet.c70
-rw-r--r--packet.h5
-rw-r--r--platform.c3
-rw-r--r--poly1305.h2
-rw-r--r--readconf.c235
-rw-r--r--readconf.h25
-rw-r--r--regress/Makefile12
-rw-r--r--regress/connect-privsep.sh4
-rw-r--r--regress/dhgex.sh6
-rw-r--r--regress/forwarding.sh22
-rw-r--r--regress/integrity.sh13
-rw-r--r--regress/kextype.sh7
-rw-r--r--regress/krl.sh5
-rw-r--r--regress/login-timeout.sh3
-rw-r--r--regress/multiplex.sh76
-rw-r--r--regress/proxy-connect.sh29
-rw-r--r--regress/rekey.sh20
-rw-r--r--regress/test-exec.sh11
-rw-r--r--regress/try-ciphers.sh7
-rw-r--r--regress/unittests/Makefile5
-rw-r--r--regress/unittests/Makefile.inc59
-rw-r--r--regress/unittests/sshbuf/Makefile14
-rw-r--r--regress/unittests/sshbuf/test_sshbuf.c240
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_fixed.c126
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_fuzz.c127
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_basic.c484
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_crypto.c409
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c130
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_misc.c138
-rw-r--r--regress/unittests/sshbuf/tests.c28
-rw-r--r--regress/unittests/sshkey/Makefile13
-rw-r--r--regress/unittests/sshkey/common.c84
-rw-r--r--regress/unittests/sshkey/common.h16
-rwxr-xr-xregress/unittests/sshkey/mktestdata.sh190
-rw-r--r--regress/unittests/sshkey/test_file.c457
-rw-r--r--regress/unittests/sshkey/test_fuzz.c406
-rw-r--r--regress/unittests/sshkey/test_sshkey.c357
-rw-r--r--regress/unittests/sshkey/testdata/dsa_112
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.param.g1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.param.priv1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.param.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1_pw15
-rw-r--r--regress/unittests/sshkey/testdata/dsa_212
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/dsa_n12
-rw-r--r--regress/unittests/sshkey/testdata/dsa_n_pw22
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_15
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.param.curve1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.param.priv1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.param.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1_pw8
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_27
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.param.curve1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.param.priv1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.param.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_n5
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_n_pw9
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_17
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1_pw8
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_27
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/pw1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1bin0 -> 421 bytes
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1.param.n1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1_pwbin0 -> 421 bytes
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_2bin0 -> 981 bytes
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_2.param.n1
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_112
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1-cert.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1-cert.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.param.n1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.param.p1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.param.q1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1_pw15
-rw-r--r--regress/unittests/sshkey/testdata/rsa_227
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.fp1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.fp.bb1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.param.n1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.param.p1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.param.q1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.pub1
-rw-r--r--regress/unittests/sshkey/testdata/rsa_n12
-rw-r--r--regress/unittests/sshkey/testdata/rsa_n_pw14
-rw-r--r--regress/unittests/sshkey/tests.c27
-rw-r--r--regress/unittests/test_helper/Makefile13
-rw-r--r--regress/unittests/test_helper/fuzz.c378
-rw-r--r--regress/unittests/test_helper/test_helper.c471
-rw-r--r--regress/unittests/test_helper/test_helper.h292
-rw-r--r--rijndael.c170
-rw-r--r--rijndael.h25
-rw-r--r--roaming_client.c5
-rw-r--r--rsa.c113
-rw-r--r--rsa.h6
-rw-r--r--sandbox-seccomp-filter.c7
-rw-r--r--sandbox-systrace.c12
-rw-r--r--scp.017
-rw-r--r--scp.114
-rw-r--r--scp.c10
-rw-r--r--servconf.c67
-rw-r--r--servconf.h6
-rw-r--r--serverloop.c109
-rw-r--r--session.c55
-rw-r--r--sftp-client.c41
-rw-r--r--sftp-client.h6
-rw-r--r--sftp-server.011
-rw-r--r--sftp-server.810
-rw-r--r--sftp-server.c14
-rw-r--r--sftp.031
-rw-r--r--sftp.137
-rw-r--r--sftp.c66
-rw-r--r--ssh-add.04
-rw-r--r--ssh-add.c28
-rw-r--r--ssh-agent.053
-rw-r--r--ssh-agent.153
-rw-r--r--ssh-agent.c78
-rw-r--r--ssh-dss.c238
-rw-r--r--ssh-ecdsa.c232
-rw-r--r--ssh-ed25519.c183
-rw-r--r--ssh-keygen.018
-rw-r--r--ssh-keygen.116
-rw-r--r--ssh-keygen.c194
-rw-r--r--ssh-keyscan.013
-rw-r--r--ssh-keyscan.115
-rw-r--r--ssh-keyscan.c11
-rw-r--r--ssh-keysign.04
-rw-r--r--ssh-keysign.c17
-rw-r--r--ssh-pkcs11-client.c4
-rw-r--r--ssh-pkcs11-helper.04
-rw-r--r--ssh-pkcs11-helper.c8
-rw-r--r--ssh-pkcs11.c4
-rw-r--r--ssh-pkcs11.h6
-rw-r--r--ssh-rsa.c260
-rw-r--r--ssh.044
-rw-r--r--ssh.135
-rw-r--r--ssh.c143
-rw-r--r--ssh_config.0117
-rw-r--r--ssh_config.5126
-rw-r--r--sshbuf-getput-basic.c421
-rw-r--r--sshbuf-getput-crypto.c237
-rw-r--r--sshbuf-misc.c135
-rw-r--r--sshbuf.c406
-rw-r--r--sshbuf.h336
-rw-r--r--sshconnect.c31
-rw-r--r--sshconnect1.c20
-rw-r--r--sshconnect2.c13
-rw-r--r--sshd.026
-rw-r--r--sshd.825
-rw-r--r--sshd.c62
-rw-r--r--sshd_config.0125
-rw-r--r--sshd_config.5194
-rw-r--r--ssherr.c131
-rw-r--r--ssherr.h80
-rw-r--r--sshkey.c3857
-rw-r--r--sshkey.h233
-rw-r--r--sshlogin.c3
-rw-r--r--sshpty.c13
-rw-r--r--umac.c59
-rw-r--r--version.h4
320 files changed, 17917 insertions, 7663 deletions
diff --git a/ChangeLog b/ChangeLog
index 38de846ff..63aeae556 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,934 @@
120131006
2 - (djm) Release OpenSSH-6.7
3
420141003
5 - (djm) [sshd_config.5] typo; from Iain Morgan
6
720141001
8 - (djm) [openbsd-compat/Makefile.in openbsd-compat/kludge-fd_set.c]
9 [openbsd-compat/openbsd-compat.h] Kludge around bad glibc
10 _FORTIFY_SOURCE check that doesn't grok heap-allocated fd_sets;
11 ok dtucker@
12
1320140910
14 - (djm) [sandbox-seccomp-filter.c] Allow mremap and exit for DietLibc;
15 patch from Felix von Leitner; ok dtucker
16
1720140908
18 - (dtucker) [INSTALL] Update info about egd. ok djm@
19
2020140904
21 - (djm) [openbsd-compat/arc4random.c] Zero seed after keying PRNG
22
2320140903
24 - (djm) [defines.h sshbuf.c] Move __predict_true|false to defines.h and
25 conditionalise to avoid duplicate definition.
26 - (djm) [contrib/cygwin/ssh-host-config] Fix old code leading to
27 permissions/ACLs; from Corinna Vinschen
28
2920140830
30 - (djm) [openbsd-compat/openssl-compat.h] add
31 OPENSSL_[RD]SA_MAX_MODULUS_BITS defines for OpenSSL that lacks them
32 - (djm) [misc.c] Missing newline between functions
33 - (djm) [openbsd-compat/openssl-compat.h] add include guard
34 - (djm) [Makefile.in] Make TEST_SHELL a variable; "good idea" tim@
35
3620140827
37 - (djm) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c]
38 [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c]
39 [regress/unittests/sshkey/common.c]
40 [regress/unittests/sshkey/test_file.c]
41 [regress/unittests/sshkey/test_fuzz.c]
42 [regress/unittests/sshkey/test_sshkey.c] Don't include openssl/ec.h
43 on !ECC OpenSSL systems
44 - (djm) [monitor.c sshd.c] SIGXFSZ needs to be ignored in postauth
45 monitor, not preauth; bz#2263
46 - (djm) [openbsd-compat/explicit_bzero.c] implement explicit_bzero()
47 using memset_s() where possible; improve fallback to indirect bzero
48 via a volatile pointer to give it more of a chance to avoid being
49 optimised away.
50
5120140825
52 - (djm) [bufec.c] Skip this file on !ECC OpenSSL
53 - (djm) [INSTALL] Recommend libcrypto be built -fPIC, mention LibreSSL,
54 update OpenSSL version requirement.
55
5620140824
57 - (djm) [sftp-server.c] Some systems (e.g. Irix) have prctl() but not
58 PR_SET_DUMPABLE, so adjust ifdef; reported by Tom Christensen
59
6020140823
61 - (djm) [sshd.c] Ignore SIGXFSZ in preauth monitor child; can explode on
62 lastlog writing on platforms with high UIDs; bz#2263
63 - (djm) [configure.ac] We now require a working vsnprintf everywhere (not
64 just for systems that lack asprintf); check for it always and extend
65 test to catch more brokenness. Fixes builds on Solaris <= 9
66
6720140822
68 - (djm) [configure.ac] include leading zero characters in OpenSSL version
69 number; fixes test for unsupported versions
70 - (djm) [sshbuf-getput-crypto.c] Fix compilation when OpenSSL lacks ECC
71 - (djm) [openbsd-compat/bsd-snprintf.c] Fix compilation failure (prototype/
72 definition mismatch) and warning for broken/missing snprintf case.
73 - (djm) [configure.ac] double braces to appease autoconf
74
7520140821
76 - (djm) [Makefile.in] fix reference to libtest_helper.a in sshkey test too.
77 - (djm) [key.h] Fix ifdefs for no-ECC OpenSSL
78 - (djm) [regress/unittests/test_helper/test_helper.c] Fix for systems that
79 don't set __progname. Diagnosed by Tom Christensen.
80
8120140820
82 - (djm) [configure.ac] Check OpenSSL version is supported at configure time;
83 suggested by Kevin Brott
84 - (djm) [Makefile.in] refer to libtest_helper.a by explicit path rather than
85 -L/-l; fixes linking problems on some platforms
86 - (djm) [sshkey.h] Fix compilation when OpenSSL lacks ECC
87 - (djm) [contrib/cygwin/README] Correct build instructions; from Corinna
88
8920140819
90 - (djm) [serverloop.c] Fix syntax error on Cygwin; from Corinna Vinschen
91 - (djm) [sshbuf.h] Fix compilation on systems without OPENSSL_HAS_ECC.
92 - (djm) [ssh-dss.c] Include openssl/dsa.h for DSA_SIG
93 - (djm) [INSTALL contrib/caldera/openssh.spec contrib/cygwin/README]
94 [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Remove mentions
95 of TCP wrappers.
96
9720140811
98 - (djm) [myproposal.h] Make curve25519 KEX dependent on
99 HAVE_EVP_SHA256 instead of OPENSSL_HAS_ECC.
100
10120140810
102 - (djm) [README contrib/caldera/openssh.spec]
103 [contrib/redhat/openssh.spec contrib/suse/openssh.spec] Update versions
104
10520140801
106 - (djm) [regress/multiplex.sh] Skip test for non-OpenBSD netcat. We need
107 a better solution, but this will have to do for now.
108 - (djm) [regress/multiplex.sh] Instruct nc not to quit as soon as stdin
109 is closed; avoid regress failures when stdin is /dev/null
110 - (djm) [regress/multiplex.sh] Use -d (detach stdin) flag to disassociate
111 nc from stdin, it's more portable
112
11320140730
114 - OpenBSD CVS Sync
115 - millert@cvs.openbsd.org 2014/07/24 22:57:10
116 [ssh.1]
117 Mention UNIX-domain socket forwarding too. OK jmc@ deraadt@
118 - dtucker@cvs.openbsd.org 2014/07/25 21:22:03
119 [ssh-agent.c]
120 Clear buffer used for handling messages. This prevents keys being
121 left in memory after they have been expired or deleted in some cases
122 (but note that ssh-agent is setgid so you would still need root to
123 access them). Pointed out by Kevin Burns, ok deraadt
124 - schwarze@cvs.openbsd.org 2014/07/28 15:40:08
125 [sftp-server.8 sshd_config.5]
126 some systems no longer need /dev/log;
127 issue noticed by jirib;
128 ok deraadt
129
13020140725
131 - (djm) [regress/multiplex.sh] restore incorrectly deleted line;
132 pointed out by Christian Hesse
133
13420140722
135 - (djm) [regress/multiplex.sh] ssh mux master lost -N somehow;
136 put it back
137 - (djm) [regress/multiplex.sh] change the test for still-open Unix
138 domain sockets to be robust against nc implementations that produce
139 error messages.
140 - (dtucker) [regress/unittests/sshkey/test_{file,fuzz,sshkey}.c] Wrap ecdsa-
141 specific tests inside OPENSSL_HAS_ECC.
142 - (dtucker) OpenBSD CVS Sync
143 - dtucker@cvs.openbsd.org 2014/07/22 01:18:50
144 [key.c]
145 Prevent spam from key_load_private_pem during hostbased auth. ok djm@
146 - guenther@cvs.openbsd.org 2014/07/22 07:13:42
147 [umac.c]
148 Convert from <sys/endian.h> to the shiney new <endian.h>
149 ok dtucker@, who also confirmed that -portable handles this already
150 (ID sync only, includes.h pulls in endian.h if available.)
151 - djm@cvs.openbsd.org 2014/07/22 01:32:12
152 [regress/multiplex.sh]
153 change the test for still-open Unix domain sockets to be robust against
154 nc implementations that produce error messages. from -portable
155 (Id sync only)
156 - dtucker@cvs.openbsd.org 2014/07/22 23:23:22
157 [regress/unittests/sshkey/mktestdata.sh]
158 Sign test certs with ed25519 instead of ecdsa so that they'll work in
159 -portable on platforms that don't have ECDSA in their OpenSSL. ok djm
160 - dtucker@cvs.openbsd.org 2014/07/22 23:57:40
161 [regress/unittests/sshkey/mktestdata.sh]
162 Add $OpenBSD tag to make syncs easier
163 - dtucker@cvs.openbsd.org 2014/07/22 23:35:38
164 [regress/unittests/sshkey/testdata/*]
165 Regenerate test keys with certs signed with ed25519 instead of ecdsa.
166 These can be used in -portable on platforms that don't support ECDSA.
167
16820140721
169 - OpenBSD CVS Sync
170 - millert@cvs.openbsd.org 2014/07/15 15:54:15
171 [forwarding.sh multiplex.sh]
172 Add support for Unix domain socket forwarding. A remote TCP port
173 may be forwarded to a local Unix domain socket and vice versa or
174 both ends may be a Unix domain socket. This is a reimplementation
175 of the streamlocal patches by William Ahern from:
176 http://www.25thandclement.com/~william/projects/streamlocal.html
177 OK djm@ markus@
178 - (djm) [regress/multiplex.sh] Not all netcat accept the -N option.
179 - (dtucker) [sshkey.c] ifdef out unused variable when compiling without
180 OPENSSL_HAS_ECC.
181
18220140721
183 - (dtucker) [cipher.c openbsd-compat/openssl-compat.h] Restore the bits
184 needed to build AES CTR mode against OpenSSL 0.9.8f and above. ok djm
185 - (dtucker) [regress/unittests/sshkey/
186 {common,test_file,test_fuzz,test_sshkey}.c] Wrap stdint.h includes in
187 ifdefs.
188
18920140719
190 - (tim) [openbsd-compat/port-uw.c] Include misc.h for fwd_opts, used
191 in servconf.h.
192
19320140718
194 - OpenBSD CVS Sync
195 - millert@cvs.openbsd.org 2014/07/15 15:54:14
196 [PROTOCOL auth-options.c auth-passwd.c auth-rh-rsa.c auth-rhosts.c]
197 [auth-rsa.c auth.c auth1.c auth2-hostbased.c auth2-kbdint.c auth2-none.c]
198 [auth2-passwd.c auth2-pubkey.c auth2.c canohost.c channels.c channels.h]
199 [clientloop.c misc.c misc.h monitor.c mux.c packet.c readconf.c]
200 [readconf.h servconf.c servconf.h serverloop.c session.c ssh-agent.c]
201 [ssh.c ssh_config.5 sshconnect.c sshconnect1.c sshconnect2.c sshd.c]
202 [sshd_config.5 sshlogin.c]
203 Add support for Unix domain socket forwarding. A remote TCP port
204 may be forwarded to a local Unix domain socket and vice versa or
205 both ends may be a Unix domain socket. This is a reimplementation
206 of the streamlocal patches by William Ahern from:
207 http://www.25thandclement.com/~william/projects/streamlocal.html
208 OK djm@ markus@
209 - jmc@cvs.openbsd.org 2014/07/16 14:48:57
210 [ssh.1]
211 add the streamlocal* options to ssh's -o list; millert says they're
212 irrelevant for scp/sftp;
213 ok markus millert
214 - djm@cvs.openbsd.org 2014/07/17 00:10:56
215 [sandbox-systrace.c]
216 ifdef SYS_sendsyslog so this will compile without patching on -stable
217 - djm@cvs.openbsd.org 2014/07/17 00:10:18
218 [mux.c]
219 preserve errno across syscall
220 - djm@cvs.openbsd.org 2014/07/17 00:12:03
221 [key.c]
222 silence "incorrect passphrase" error spam; reported and ok dtucker@
223 - djm@cvs.openbsd.org 2014/07/17 07:22:19
224 [mux.c ssh.c]
225 reflect stdio-forward ("ssh -W host:port ...") failures in exit status.
226 previously we were always returning 0. bz#2255 reported by Brendan
227 Germain; ok dtucker
228 - djm@cvs.openbsd.org 2014/07/18 02:46:01
229 [ssh-agent.c]
230 restore umask around listener socket creation (dropped in streamlocal patch
231 merge)
232 - (dtucker) [auth2-gss.c gss-serv-krb5.c] Include misc.h for fwd_opts, used
233 in servconf.h.
234 - (dtucker) [Makefile.in] Add a t-exec target to run just the executable
235 tests.
236 - (dtucker) [key.c sshkey.c] Put new ecdsa bits inside ifdef OPENSSL_HAS_ECC.
237
23820140717
239 - (djm) [digest-openssl.c] Preserve array order when disabling digests.
240 Reported by Petr Lautrbach.
241 - OpenBSD CVS Sync
242 - deraadt@cvs.openbsd.org 2014/07/11 08:09:54
243 [sandbox-systrace.c]
244 Permit use of SYS_sendsyslog from inside the sandbox. Clock is ticking,
245 update your kernels and sshd soon.. libc will start using sendsyslog()
246 in about 4 days.
247 - tedu@cvs.openbsd.org 2014/07/11 13:54:34
248 [myproposal.h]
249 by popular demand, add back hamc-sha1 to server proposal for better compat
250 with many clients still in use. ok deraadt
251
25220140715
253 - (djm) [configure.ac] Delay checks for arc4random* until after libcrypto
254 has been located; fixes builds agains libressl-portable
255
25620140711
257 - OpenBSD CVS Sync
258 - benno@cvs.openbsd.org 2014/07/09 14:15:56
259 [ssh-add.c]
260 fix ssh-add crash while loading more than one key
261 ok markus@
262
26320140709
264 - OpenBSD CVS Sync
265 - djm@cvs.openbsd.org 2014/07/07 08:19:12
266 [ssh_config.5]
267 mention that ProxyCommand is executed using shell "exec" to avoid
268 a lingering process; bz#1977
269 - djm@cvs.openbsd.org 2014/07/09 01:45:10
270 [sftp.c]
271 more useful error message when GLOB_NOSPACE occurs;
272 bz#2254, patch from Orion Poplawski
273 - djm@cvs.openbsd.org 2014/07/09 03:02:15
274 [key.c]
275 downgrade more error() to debug() to better match what old authfile.c
276 did; suppresses spurious errors with hostbased authentication enabled
277 - djm@cvs.openbsd.org 2014/07/06 07:42:03
278 [multiplex.sh test-exec.sh]
279 add a hook to the cleanup() function to kill $SSH_PID if it is set
280
281 use it to kill the mux master started in multiplex.sh (it was being left
282 around on fatal failures)
283 - djm@cvs.openbsd.org 2014/07/07 08:15:26
284 [multiplex.sh]
285 remove forced-fatal that I stuck in there to test the new cleanup
286 logic and forgot to remove...
287
28820140706
289 - OpenBSD CVS Sync
290 - djm@cvs.openbsd.org 2014/07/03 23:18:35
291 [authfile.h]
292 remove leakmalloc droppings
293 - djm@cvs.openbsd.org 2014/07/05 23:11:48
294 [channels.c]
295 fix remote-forward cancel regression; ok markus@
296
29720140704
298 - OpenBSD CVS Sync
299 - jsing@cvs.openbsd.org 2014/07/03 12:42:16
300 [cipher-chachapoly.c]
301 Call chacha_ivsetup() immediately before chacha_encrypt_bytes() - this
302 makes it easier to verify that chacha_encrypt_bytes() is only called once
303 per chacha_ivsetup() call.
304 ok djm@
305 - djm@cvs.openbsd.org 2014/07/03 22:23:46
306 [sshconnect.c]
307 when rekeying, skip file/DNS lookup if it is the same as the key sent
308 during initial key exchange. bz#2154 patch from Iain Morgan; ok markus@
309 - djm@cvs.openbsd.org 2014/07/03 22:33:41
310 [channels.c]
311 allow explicit ::1 and 127.0.0.1 forwarding bind addresses when
312 GatewayPorts=no; allows client to choose address family;
313 bz#2222 ok markus@
314 - djm@cvs.openbsd.org 2014/07/03 22:40:43
315 [servconf.c servconf.h session.c sshd.8 sshd_config.5]
316 Add a sshd_config PermitUserRC option to control whether ~/.ssh/rc is
317 executed, mirroring the no-user-rc authorized_keys option;
318 bz#2160; ok markus@
319
32020140703
321 - (djm) [digest-openssl.c configure.ac] Disable RIPEMD160 if libcrypto
322 doesn't support it.
323 - (djm) [monitor_fdpass.c] Use sys/poll.h if poll.h doesn't exist;
324 bz#2237
325 - OpenBSD CVS Sync
326 - djm@cvs.openbsd.org 2014/07/03 01:45:38
327 [sshkey.c]
328 make Ed25519 keys' title fit properly in the randomart border; bz#2247
329 based on patch from Christian Hesse
330 - djm@cvs.openbsd.org 2014/07/03 03:11:03
331 [ssh-agent.c]
332 Only cleanup agent socket in the main agent process and not in any
333 subprocesses it may have started (e.g. forked askpass). Fixes
334 agent sockets being zapped when askpass processes fatal();
335 bz#2236 patch from Dmitry V. Levin
336 - djm@cvs.openbsd.org 2014/07/03 03:15:01
337 [ssh-add.c]
338 make stdout line-buffered; saves partial output getting lost when
339 ssh-add fatal()s part-way through (e.g. when listing keys from an
340 agent that supports key types that ssh-add doesn't);
341 bz#2234, reported by Phil Pennock
342 - djm@cvs.openbsd.org 2014/07/03 03:26:43
343 [digest-openssl.c]
344 use EVP_Digest() for one-shot hash instead of creating, updating,
345 finalising and destroying a context.
346 bz#2231, based on patch from Timo Teras
347 - djm@cvs.openbsd.org 2014/07/03 03:34:09
348 [gss-serv.c session.c ssh-keygen.c]
349 standardise on NI_MAXHOST for gethostname() string lengths; about
350 1/2 the cases were using it already. Fixes bz#2239 en passant
351 - djm@cvs.openbsd.org 2014/07/03 03:47:27
352 [ssh-keygen.c]
353 When hashing or removing hosts using ssh-keygen, don't choke on
354 @revoked markers and don't remove @cert-authority markers;
355 bz#2241, reported by mlindgren AT runelind.net
356 - djm@cvs.openbsd.org 2014/07/03 04:36:45
357 [digest.h]
358 forward-declare struct sshbuf so consumers don't need to include sshbuf.h
359 - djm@cvs.openbsd.org 2014/07/03 05:32:36
360 [ssh_config.5]
361 mention '%%' escape sequence in HostName directives and how it may
362 be used to specify IPv6 link-local addresses
363 - djm@cvs.openbsd.org 2014/07/03 05:38:17
364 [ssh.1]
365 document that -g will only work in the multiplexed case if applied to
366 the mux master
367 - djm@cvs.openbsd.org 2014/07/03 06:39:19
368 [ssh.c ssh_config.5]
369 Add a %C escape sequence for LocalCommand and ControlPath that expands
370 to a unique identifer based on a has of the tuple of (local host,
371 remote user, hostname, port).
372
373 Helps avoid exceeding sockaddr_un's miserly pathname limits for mux
374 control paths.
375
376 bz#2220, based on patch from mancha1 AT zoho.com; ok markus@
377 - jmc@cvs.openbsd.org 2014/07/03 07:45:27
378 [ssh_config.5]
379 escape %C since groff thinks it part of an Rs/Re block;
380 - djm@cvs.openbsd.org 2014/07/03 11:16:55
381 [auth.c auth.h auth1.c auth2.c]
382 make the "Too many authentication failures" message include the
383 user, source address, port and protocol in a format similar to the
384 authentication success / failure messages; bz#2199, ok dtucker
385
38620140702
387 - OpenBSD CVS Sync
388 - deraadt@cvs.openbsd.org 2014/06/13 08:26:29
389 [sandbox-systrace.c]
390 permit SYS_getentropy
391 from matthew
392 - matthew@cvs.openbsd.org 2014/06/18 02:59:13
393 [sandbox-systrace.c]
394 Now that we have a dedicated getentropy(2) system call for
395 arc4random(3), we can disallow __sysctl(2) in OpenSSH's systrace
396 sandbox.
397
398 ok djm
399 - naddy@cvs.openbsd.org 2014/06/18 15:42:09
400 [sshbuf-getput-crypto.c]
401 The ssh_get_bignum functions must accept the same range of bignums
402 the corresponding ssh_put_bignum functions create. This fixes the
403 use of 16384-bit RSA keys (bug reported by Eivind Evensen).
404 ok djm@
405 - djm@cvs.openbsd.org 2014/06/24 00:52:02
406 [krl.c]
407 fix bug in KRL generation: multiple consecutive revoked certificate
408 serial number ranges could be serialised to an invalid format.
409
410 Readers of a broken KRL caused by this bug will fail closed, so no
411 should-have-been-revoked key will be accepted.
412 - djm@cvs.openbsd.org 2014/06/24 01:13:21
413 [Makefile.in auth-bsdauth.c auth-chall.c auth-options.c auth-rsa.c
414 [auth2-none.c auth2-pubkey.c authfile.c authfile.h cipher-3des1.c
415 [cipher-chachapoly.c cipher-chachapoly.h cipher.c cipher.h
416 [digest-libc.c digest-openssl.c digest.h dns.c entropy.c hmac.h
417 [hostfile.c key.c key.h krl.c monitor.c packet.c rsa.c rsa.h
418 [ssh-add.c ssh-agent.c ssh-dss.c ssh-ecdsa.c ssh-ed25519.c
419 [ssh-keygen.c ssh-pkcs11-client.c ssh-pkcs11-helper.c ssh-pkcs11.c
420 [ssh-rsa.c sshbuf-misc.c sshbuf.h sshconnect.c sshconnect1.c
421 [sshconnect2.c sshd.c sshkey.c sshkey.h
422 [openbsd-compat/openssl-compat.c openbsd-compat/openssl-compat.h]
423 New key API: refactor key-related functions to be more library-like,
424 existing API is offered as a set of wrappers.
425
426 with and ok markus@
427
428 Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
429 Dempsky and Ron Bowes for a detailed review a few months ago.
430 NB. This commit also removes portable OpenSSH support for OpenSSL
431 <0.9.8e.
432 - djm@cvs.openbsd.org 2014/06/24 02:19:48
433 [ssh.c]
434 don't fatal() when hostname canonicalisation fails with a
435 ProxyCommand in use; continue and allow the ProxyCommand to
436 connect anyway (e.g. to a host with a name outside the DNS
437 behind a bastion)
438 - djm@cvs.openbsd.org 2014/06/24 02:21:01
439 [scp.c]
440 when copying local->remote fails during read, don't send uninitialised
441 heap to the remote end. Reported by Jann Horn
442 - deraadt@cvs.openbsd.org 2014/06/25 14:16:09
443 [sshbuf.c]
444 unblock SIGSEGV before raising it
445 ok djm
446 - markus@cvs.openbsd.org 2014/06/27 16:41:56
447 [channels.c channels.h clientloop.c ssh.c]
448 fix remote fwding with same listen port but different listen address
449 with gerhard@, ok djm@
450 - markus@cvs.openbsd.org 2014/06/27 18:50:39
451 [ssh-add.c]
452 fix loading of private keys
453 - djm@cvs.openbsd.org 2014/06/30 12:54:39
454 [key.c]
455 suppress spurious error message when loading key with a passphrase;
456 reported by kettenis@ ok markus@
457 - djm@cvs.openbsd.org 2014/07/02 04:59:06
458 [cipher-3des1.c]
459 fix ssh protocol 1 on the server that regressed with the sshkey change
460 (sometimes fatal() after auth completed), make file return useful status
461 codes.
462 NB. Id sync only for these two. They were bundled into the sshkey merge
463 above, since it was easier to sync the entire file and then apply
464 portable-specific changed atop it.
465 - djm@cvs.openbsd.org 2014/04/30 05:32:00
466 [regress/Makefile]
467 unit tests for new buffer API; including basic fuzz testing
468 NB. Id sync only.
469 - djm@cvs.openbsd.org 2014/05/21 07:04:21
470 [regress/integrity.sh]
471 when failing because of unexpected output, show the offending output
472 - djm@cvs.openbsd.org 2014/06/24 01:04:43
473 [regress/krl.sh]
474 regress test for broken consecutive revoked serial number ranges
475 - djm@cvs.openbsd.org 2014/06/24 01:14:17
476 [Makefile.in regress/Makefile regress/unittests/Makefile]
477 [regress/unittests/sshkey/Makefile]
478 [regress/unittests/sshkey/common.c]
479 [regress/unittests/sshkey/common.h]
480 [regress/unittests/sshkey/mktestdata.sh]
481 [regress/unittests/sshkey/test_file.c]
482 [regress/unittests/sshkey/test_fuzz.c]
483 [regress/unittests/sshkey/test_sshkey.c]
484 [regress/unittests/sshkey/tests.c]
485 [regress/unittests/sshkey/testdata/dsa_1]
486 [regress/unittests/sshkey/testdata/dsa_1-cert.fp]
487 [regress/unittests/sshkey/testdata/dsa_1-cert.pub]
488 [regress/unittests/sshkey/testdata/dsa_1.fp]
489 [regress/unittests/sshkey/testdata/dsa_1.fp.bb]
490 [regress/unittests/sshkey/testdata/dsa_1.param.g]
491 [regress/unittests/sshkey/testdata/dsa_1.param.priv]
492 [regress/unittests/sshkey/testdata/dsa_1.param.pub]
493 [regress/unittests/sshkey/testdata/dsa_1.pub]
494 [regress/unittests/sshkey/testdata/dsa_1_pw]
495 [regress/unittests/sshkey/testdata/dsa_2]
496 [regress/unittests/sshkey/testdata/dsa_2.fp]
497 [regress/unittests/sshkey/testdata/dsa_2.fp.bb]
498 [regress/unittests/sshkey/testdata/dsa_2.pub]
499 [regress/unittests/sshkey/testdata/dsa_n]
500 [regress/unittests/sshkey/testdata/dsa_n_pw]
501 [regress/unittests/sshkey/testdata/ecdsa_1]
502 [regress/unittests/sshkey/testdata/ecdsa_1-cert.fp]
503 [regress/unittests/sshkey/testdata/ecdsa_1-cert.pub]
504 [regress/unittests/sshkey/testdata/ecdsa_1.fp]
505 [regress/unittests/sshkey/testdata/ecdsa_1.fp.bb]
506 [regress/unittests/sshkey/testdata/ecdsa_1.param.curve]
507 [regress/unittests/sshkey/testdata/ecdsa_1.param.priv]
508 [regress/unittests/sshkey/testdata/ecdsa_1.param.pub]
509 [regress/unittests/sshkey/testdata/ecdsa_1.pub]
510 [regress/unittests/sshkey/testdata/ecdsa_1_pw]
511 [regress/unittests/sshkey/testdata/ecdsa_2]
512 [regress/unittests/sshkey/testdata/ecdsa_2.fp]
513 [regress/unittests/sshkey/testdata/ecdsa_2.fp.bb]
514 [regress/unittests/sshkey/testdata/ecdsa_2.param.curve]
515 [regress/unittests/sshkey/testdata/ecdsa_2.param.priv]
516 [regress/unittests/sshkey/testdata/ecdsa_2.param.pub]
517 [regress/unittests/sshkey/testdata/ecdsa_2.pub]
518 [regress/unittests/sshkey/testdata/ecdsa_n]
519 [regress/unittests/sshkey/testdata/ecdsa_n_pw]
520 [regress/unittests/sshkey/testdata/ed25519_1]
521 [regress/unittests/sshkey/testdata/ed25519_1-cert.fp]
522 [regress/unittests/sshkey/testdata/ed25519_1-cert.pub]
523 [regress/unittests/sshkey/testdata/ed25519_1.fp]
524 [regress/unittests/sshkey/testdata/ed25519_1.fp.bb]
525 [regress/unittests/sshkey/testdata/ed25519_1.pub]
526 [regress/unittests/sshkey/testdata/ed25519_1_pw]
527 [regress/unittests/sshkey/testdata/ed25519_2]
528 [regress/unittests/sshkey/testdata/ed25519_2.fp]
529 [regress/unittests/sshkey/testdata/ed25519_2.fp.bb]
530 [regress/unittests/sshkey/testdata/ed25519_2.pub]
531 [regress/unittests/sshkey/testdata/pw]
532 [regress/unittests/sshkey/testdata/rsa1_1]
533 [regress/unittests/sshkey/testdata/rsa1_1.fp]
534 [regress/unittests/sshkey/testdata/rsa1_1.fp.bb]
535 [regress/unittests/sshkey/testdata/rsa1_1.param.n]
536 [regress/unittests/sshkey/testdata/rsa1_1.pub]
537 [regress/unittests/sshkey/testdata/rsa1_1_pw]
538 [regress/unittests/sshkey/testdata/rsa1_2]
539 [regress/unittests/sshkey/testdata/rsa1_2.fp]
540 [regress/unittests/sshkey/testdata/rsa1_2.fp.bb]
541 [regress/unittests/sshkey/testdata/rsa1_2.param.n]
542 [regress/unittests/sshkey/testdata/rsa1_2.pub]
543 [regress/unittests/sshkey/testdata/rsa_1]
544 [regress/unittests/sshkey/testdata/rsa_1-cert.fp]
545 [regress/unittests/sshkey/testdata/rsa_1-cert.pub]
546 [regress/unittests/sshkey/testdata/rsa_1.fp]
547 [regress/unittests/sshkey/testdata/rsa_1.fp.bb]
548 [regress/unittests/sshkey/testdata/rsa_1.param.n]
549 [regress/unittests/sshkey/testdata/rsa_1.param.p]
550 [regress/unittests/sshkey/testdata/rsa_1.param.q]
551 [regress/unittests/sshkey/testdata/rsa_1.pub]
552 [regress/unittests/sshkey/testdata/rsa_1_pw]
553 [regress/unittests/sshkey/testdata/rsa_2]
554 [regress/unittests/sshkey/testdata/rsa_2.fp]
555 [regress/unittests/sshkey/testdata/rsa_2.fp.bb]
556 [regress/unittests/sshkey/testdata/rsa_2.param.n]
557 [regress/unittests/sshkey/testdata/rsa_2.param.p]
558 [regress/unittests/sshkey/testdata/rsa_2.param.q]
559 [regress/unittests/sshkey/testdata/rsa_2.pub]
560 [regress/unittests/sshkey/testdata/rsa_n]
561 [regress/unittests/sshkey/testdata/rsa_n_pw]
562 unit and fuzz tests for new key API
563 - (djm) [sshkey.c] Conditionalise inclusion of util.h
564 - (djm) [regress/Makefile] fix execution of sshkey unit/fuzz test
565
56620140618
567 - (tim) [openssh/session.c] Work around to get chroot sftp working on UnixWare
568
56920140617
570 - (dtucker) [entropy.c openbsd-compat/openssl-compat.{c,h}
571 openbsd-compat/regress/{.cvsignore,Makefile.in,opensslvertest.c}]
572 Move the OpenSSL header/library version test into its own function and add
573 tests for it. Fix it to allow fix version upgrades (but not downgrades).
574 Prompted by chl@ via OpenSMTPD (issue #462) and Debian (bug #748150).
575 ok djm@ chl@
576
57720140616
578 - (dtucker) [defines.h] Fix undef of _PATH_MAILDIR. From rak at debian via
579 OpenSMTPD and chl@
580
58120140612
582 - (dtucker) [configure.ac] Remove tcpwrappers support, support has already
583 been removed from sshd.c.
584
58520140611
586 - (dtucker) [defines.h] Add va_copy if we don't already have it, taken from
587 openbsd-compat/bsd-asprintf.c.
588 - (dtucker) [regress/unittests/sshbuf/*.c regress/unittests/test_helper/*]
589 Wrap stdlib.h include an ifdef for platforms that don't have it.
590 - (tim) [regress/unittests/test_helper/test_helper.h] Add includes.h for
591 u_intXX_t types.
592
59320140610
594 - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
595 regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] Only do NISTP256
596 curve tests if OpenSSL has them.
597 - (dtucker) [myprosal.h] Don't include curve25519-sha256@libssh.org in
598 the proposal if the version of OpenSSL we're using doesn't support ECC.
599 - (dtucker) [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c] ifdef
600 ECC variable too.
601 - (dtucker) OpenBSD CVS Sync
602 - djm@cvs.openbsd.org 2014/06/05 22:17:50
603 [sshconnect2.c]
604 fix inverted test that caused PKCS#11 keys that were explicitly listed
605 not to be preferred. Reported by Dirk-Willem van Gulik
606 - dtucker@cvs.openbsd.org 2014/06/10 21:46:11
607 [sshbuf.h]
608 Group ECC functions together to make things a little easier in -portable.
609 "doesn't bother me" deraadt@
610 - (dtucker) [sshbuf.h] Only declare ECC functions if building without
611 OpenSSL or if OpenSSL has ECC.
612 - (dtucker) [openbsd-compat/arc4random.c] Use explicit_bzero instead of an
613 assigment that might get optimized out. ok djm@
614 - (dtucker) [bufaux.c bufbn.c bufec.c buffer.c] Pull in includes.h for
615 compat stuff, specifically whether or not OpenSSL has ECC.
616
61720140527
618 - (djm) [cipher.c] Fix merge botch.
619 - (djm) [contrib/cygwin/ssh-host-config] Updated Cygwin ssh-host-config
620 from Corinna Vinschen, fixing a number of bugs and preparing for
621 Cygwin 1.7.30.
622 - (djm) [configure.ac openbsd-compat/bsd-cygwin_util.c]
623 [openbsd-compat/bsd-cygwin_util.h] On Cygwin, determine privilege
624 separation user at runtime, since it may need to be a domain account.
625 Patch from Corinna Vinschen.
626
62720140522
628 - (djm) [Makefile.in] typo in path
629
63020140521
631 - (djm) [commit configure.ac defines.h sshpty.c] don't attempt to use
632 vhangup on Linux. It doens't work for non-root users, and for them
633 it just messes up the tty settings.
634 - (djm) [misc.c] Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC
635 when it is available. It takes into account time spent suspended,
636 thereby ensuring timeouts (e.g. for expiring agent keys) fire
637 correctly. bz#2228 reported by John Haxby
638
63920140519
640 - (djm) [rijndael.c rijndael.h] Sync with newly-ressurected versions ine
641 OpenBSD
642 - OpenBSD CVS Sync
643 - logan@cvs.openbsd.org 2014/04/20 09:24:26
644 [dns.c dns.h ssh-keygen.c]
645 Add support for SSHFP DNS records for ED25519 key types.
646 OK from djm@
647 - logan@cvs.openbsd.org 2014/04/21 14:36:16
648 [sftp-client.c sftp-client.h sftp.c]
649 Implement sftp upload resume support.
650 OK from djm@, with input from guenther@, mlarkin@ and
651 okan@
652 - logan@cvs.openbsd.org 2014/04/22 10:07:12
653 [sftp.c]
654 Sort the sftp command list.
655 OK from djm@
656 - logan@cvs.openbsd.org 2014/04/22 12:42:04
657 [sftp.1]
658 Document sftp upload resume.
659 OK from djm@, with feedback from okan@.
660 - jmc@cvs.openbsd.org 2014/04/22 14:16:30
661 [sftp.1]
662 zap eol whitespace;
663 - djm@cvs.openbsd.org 2014/04/23 12:42:34
664 [readconf.c]
665 don't record duplicate IdentityFiles
666 - djm@cvs.openbsd.org 2014/04/28 03:09:18
667 [authfile.c bufaux.c buffer.h channels.c krl.c mux.c packet.c packet.h]
668 [ssh-keygen.c]
669 buffer_get_string_ptr's return should be const to remind
670 callers that futzing with it will futz with the actual buffer
671 contents
672 - djm@cvs.openbsd.org 2014/04/29 13:10:30
673 [clientloop.c serverloop.c]
674 bz#1818 - don't send channel success/failre replies on channels that
675 have sent a close already; analysis and patch from Simon Tatham;
676 ok markus@
677 - markus@cvs.openbsd.org 2014/04/29 18:01:49
678 [auth.c authfd.c authfile.c bufaux.c cipher.c cipher.h hostfile.c]
679 [kex.c key.c mac.c monitor.c monitor_wrap.c myproposal.h packet.c]
680 [roaming_client.c ssh-agent.c ssh-keygen.c ssh-keyscan.c ssh-keysign.c]
681 [ssh-pkcs11.h ssh.c sshconnect.c sshconnect2.c sshd.c]
682 make compiling against OpenSSL optional (make OPENSSL=no);
683 reduces algorithms to curve25519, aes-ctr, chacha, ed25519;
684 allows us to explore further options; with and ok djm
685 - dtucker@cvs.openbsd.org 2014/04/29 19:58:50
686 [sftp.c]
687 Move nulling of variable next to where it's freed. ok markus@
688 - dtucker@cvs.openbsd.org 2014/04/29 20:36:51
689 [sftp.c]
690 Don't attempt to append a nul quote char to the filename. Should prevent
691 fatal'ing with "el_insertstr failed" when there's a single quote char
692 somewhere in the string. bz#2238, ok markus@
693 - djm@cvs.openbsd.org 2014/04/30 05:29:56
694 [bufaux.c bufbn.c bufec.c buffer.c buffer.h sshbuf-getput-basic.c]
695 [sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c sshbuf.h ssherr.c]
696 [ssherr.h]
697 New buffer API; the first installment of the conversion/replacement
698 of OpenSSH's internals to make them usable as a standalone library.
699
700 This includes a set of wrappers to make it compatible with the
701 existing buffer API so replacement can occur incrementally.
702
703 With and ok markus@
704
705 Thanks also to Ben Hawkes, David Tomaschik, Ivan Fratric, Matthew
706 Dempsky and Ron Bowes for a detailed review.
707 - naddy@cvs.openbsd.org 2014/04/30 19:07:48
708 [mac.c myproposal.h umac.c]
709 UMAC can use our local fallback implementation of AES when OpenSSL isn't
710 available. Glue code straight from Ted Krovetz's original umac.c.
711 ok markus@
712 - djm@cvs.openbsd.org 2014/05/02 03:27:54
713 [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c]
714 [misc.h poly1305.h ssh-pkcs11.c defines.h]
715 revert __bounded change; it causes way more problems for portable than
716 it solves; pointed out by dtucker@
717 - markus@cvs.openbsd.org 2014/05/03 17:20:34
718 [monitor.c packet.c packet.h]
719 unbreak compression, by re-init-ing the compression code in the
720 post-auth child. the new buffer code is more strict, and requires
721 buffer_init() while the old code was happy after a bzero();
722 originally from djm@
723 - logan@cvs.openbsd.org 2014/05/05 07:02:30
724 [sftp.c]
725 Zap extra whitespace.
726
727 OK from djm@ and dtucker@
728 - (djm) [configure.ac] Unconditionally define WITH_OPENSSL until we write
729 portability glue to support building without libcrypto
730 - (djm) [Makefile.in configure.ac sshbuf-getput-basic.c]
731 [sshbuf-getput-crypto.c sshbuf.c] compilation and portability fixes
732 - OpenBSD CVS Sync
733 - djm@cvs.openbsd.org 2014/03/13 20:44:49
734 [login-timeout.sh]
735 this test is a sorry mess of race conditions; add another sleep
736 to avoid a failure on slow machines (at least until I find a
737 better way)
738 - djm@cvs.openbsd.org 2014/04/21 22:15:37
739 [dhgex.sh integrity.sh kextype.sh rekey.sh try-ciphers.sh]
740 repair regress tests broken by server-side default cipher/kex/mac changes
741 by ensuring that the option under test is included in the server's
742 algorithm list
743 - dtucker@cvs.openbsd.org 2014/05/03 18:46:14
744 [proxy-connect.sh]
745 Add tests for with and without compression, with and without privsep.
746 - logan@cvs.openbsd.org 2014/05/04 10:40:59
747 [connect-privsep.sh]
748 Remove the Z flag from the list of malloc options as it
749 was removed from malloc.c 10 days ago.
750
751 OK from miod@
752 - (djm) [regress/unittests/Makefile]
753 [regress/unittests/Makefile.inc]
754 [regress/unittests/sshbuf/Makefile]
755 [regress/unittests/sshbuf/test_sshbuf.c]
756 [regress/unittests/sshbuf/test_sshbuf_fixed.c]
757 [regress/unittests/sshbuf/test_sshbuf_fuzz.c]
758 [regress/unittests/sshbuf/test_sshbuf_getput_basic.c]
759 [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c]
760 [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c]
761 [regress/unittests/sshbuf/test_sshbuf_misc.c]
762 [regress/unittests/sshbuf/tests.c]
763 [regress/unittests/test_helper/Makefile]
764 [regress/unittests/test_helper/fuzz.c]
765 [regress/unittests/test_helper/test_helper.c]
766 [regress/unittests/test_helper/test_helper.h]
767 Import new unit tests from OpenBSD; not yet hooked up to build.
768 - (djm) [regress/Makefile Makefile.in]
769 [regress/unittests/sshbuf/test_sshbuf.c
770 [regress/unittests/sshbuf/test_sshbuf_fixed.c]
771 [regress/unittests/sshbuf/test_sshbuf_fuzz.c]
772 [regress/unittests/sshbuf/test_sshbuf_getput_basic.c]
773 [regress/unittests/sshbuf/test_sshbuf_getput_crypto.c]
774 [regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c]
775 [regress/unittests/sshbuf/test_sshbuf_misc.c]
776 [regress/unittests/sshbuf/tests.c]
777 [regress/unittests/test_helper/fuzz.c]
778 [regress/unittests/test_helper/test_helper.c]
779 Hook new unit tests into the build and "make tests"
780 - (djm) [sshbuf.c] need __predict_false
781
78220140430
783 - (dtucker) [defines.h] Define __GNUC_PREREQ__ macro if we don't already
784 have it. Only attempt to use __attribute__(__bounded__) for gcc.
785
78620140420
787 - OpenBSD CVS Sync
788 - djm@cvs.openbsd.org 2014/03/03 22:22:30
789 [session.c]
790 ignore enviornment variables with embedded '=' or '\0' characters;
791 spotted by Jann Horn; ok deraadt@
792 Id sync only - portable already has this.
793 - djm@cvs.openbsd.org 2014/03/12 04:44:58
794 [ssh-keyscan.c]
795 scan for Ed25519 keys by default too
796 - djm@cvs.openbsd.org 2014/03/12 04:50:32
797 [auth-bsdauth.c ssh-keygen.c]
798 don't count on things that accept arguments by reference to clear
799 things for us on error; most things do, but it's unsafe form.
800 - djm@cvs.openbsd.org 2014/03/12 04:51:12
801 [authfile.c]
802 correct test that kdf name is not "none" or "bcrypt"
803 - naddy@cvs.openbsd.org 2014/03/12 13:06:59
804 [ssh-keyscan.1]
805 scan for Ed25519 keys by default too
806 - deraadt@cvs.openbsd.org 2014/03/15 17:28:26
807 [ssh-agent.c ssh-keygen.1 ssh-keygen.c]
808 Improve usage() and documentation towards the standard form.
809 In particular, this line saves a lot of man page reading time.
810 usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
811 [-N new_passphrase] [-C comment] [-f output_keyfile]
812 ok schwarze jmc
813 - tedu@cvs.openbsd.org 2014/03/17 19:44:10
814 [ssh.1]
815 old descriptions of des and blowfish are old. maybe ok deraadt
816 - tedu@cvs.openbsd.org 2014/03/19 14:42:44
817 [scp.1]
818 there is no need for rcp anymore
819 ok deraadt millert
820 - markus@cvs.openbsd.org 2014/03/25 09:40:03
821 [myproposal.h]
822 trimm default proposals.
823
824 This commit removes the weaker pre-SHA2 hashes, the broken ciphers
825 (arcfour), and the broken modes (CBC) from the default configuration
826 (the patch only changes the default, all the modes are still available
827 for the config files).
828
829 ok djm@, reminded by tedu@ & naddy@ and discussed with many
830 - deraadt@cvs.openbsd.org 2014/03/26 17:16:26
831 [myproposal.h]
832 The current sharing of myproposal[] between both client and server code
833 makes the previous diff highly unpallatable. We want to go in that
834 direction for the server, but not for the client. Sigh.
835 Brought up by naddy.
836 - markus@cvs.openbsd.org 2014/03/27 23:01:27
837 [myproposal.h ssh-keyscan.c sshconnect2.c sshd.c]
838 disable weak proposals in sshd, but keep them in ssh; ok djm@
839 - djm@cvs.openbsd.org 2014/03/26 04:55:35
840 [chacha.h cipher-chachapoly.h digest.h hmac.h kex.h kexc25519.c
841 [misc.h poly1305.h ssh-pkcs11.c]
842 use __bounded(...) attribute recently added to sys/cdefs.h instead of
843 longform __attribute__(__bounded(...));
844
845 for brevity and a warning free compilation with llvm/clang
846 - tedu@cvs.openbsd.org 2014/03/26 19:58:37
847 [sshd.8 sshd.c]
848 remove libwrap support. ok deraadt djm mfriedl
849 - naddy@cvs.openbsd.org 2014/03/28 05:17:11
850 [ssh_config.5 sshd_config.5]
851 sync available and default algorithms, improve algorithm list formatting
852 help from jmc@ and schwarze@, ok deraadt@
853 - jmc@cvs.openbsd.org 2014/03/31 13:39:34
854 [ssh-keygen.1]
855 the text for the -K option was inserted in the wrong place in -r1.108;
856 fix From: Matthew Clarke
857 - djm@cvs.openbsd.org 2014/04/01 02:05:27
858 [ssh-keysign.c]
859 include fingerprint of key not found
860 use arc4random_buf() instead of loop+arc4random()
861 - djm@cvs.openbsd.org 2014/04/01 03:34:10
862 [sshconnect.c]
863 When using VerifyHostKeyDNS with a DNSSEC resolver, down-convert any
864 certificate keys to plain keys and attempt SSHFP resolution.
865
866 Prevents a server from skipping SSHFP lookup and forcing a new-hostkey
867 dialog by offering only certificate keys.
868
869 Reported by mcv21 AT cam.ac.uk
870 - djm@cvs.openbsd.org 2014/04/01 05:32:57
871 [packet.c]
872 demote a debug3 to PACKET_DEBUG; ok markus@
873 - djm@cvs.openbsd.org 2014/04/12 04:55:53
874 [sshd.c]
875 avoid crash at exit: check that pmonitor!=NULL before dereferencing;
876 bz#2225, patch from kavi AT juniper.net
877 - djm@cvs.openbsd.org 2014/04/16 23:22:45
878 [bufaux.c]
879 skip leading zero bytes in buffer_put_bignum2_from_string();
880 reported by jan AT mojzis.com; ok markus@
881 - djm@cvs.openbsd.org 2014/04/16 23:28:12
882 [ssh-agent.1]
883 remove the identity files from this manpage - ssh-agent doesn't deal
884 with them at all and the same information is duplicated in ssh-add.1
885 (which does deal with them); prodded by deraadt@
886 - djm@cvs.openbsd.org 2014/04/18 23:52:25
887 [compat.c compat.h sshconnect2.c sshd.c version.h]
888 OpenSSH 6.5 and 6.6 have a bug that causes ~0.2% of connections
889 using the curve25519-sha256@libssh.org KEX exchange method to fail
890 when connecting with something that implements the spec properly.
891
892 Disable this KEX method when speaking to one of the affected
893 versions.
894
895 reported by Aris Adamantiadis; ok markus@
896 - djm@cvs.openbsd.org 2014/04/19 05:54:59
897 [compat.c]
898 missing wildcard; pointed out by naddy@
899 - tedu@cvs.openbsd.org 2014/04/19 14:53:48
900 [ssh-keysign.c sshd.c]
901 Delete futile calls to RAND_seed. ok djm
902 NB. Id sync only. This only applies to OpenBSD's libcrypto slashathon
903 - tedu@cvs.openbsd.org 2014/04/19 18:15:16
904 [sshd.8]
905 remove some really old rsh references
906 - tedu@cvs.openbsd.org 2014/04/19 18:42:19
907 [ssh.1]
908 delete .xr to hosts.equiv. there's still an unfortunate amount of
909 documentation referring to rhosts equivalency in here.
910 - djm@cvs.openbsd.org 2014/04/20 02:30:25
911 [misc.c misc.h umac.c]
912 use get/put_u32 to load values rather than *((UINT32 *)p) that breaks on
913 strict-alignment architectures; reported by and ok stsp@
914 - djm@cvs.openbsd.org 2014/04/20 02:49:32
915 [compat.c]
916 add a canonical 6.6 + curve25519 bignum fix fake version that I can
917 recommend people use ahead of the openssh-6.7 release
918
91920140401
920 - (djm) On platforms that support it, use prctl() to prevent sftp-server
921 from accessing /proc/self/{mem,maps}; patch from jann AT thejh.net
922 - (djm) Use full release (e.g. 6.5p1) in debug output rather than just
923 version. From des@des.no
924
92520140317
926 - (djm) [sandbox-seccomp-filter.c] Soft-fail stat() syscalls. Add XXX to
927 remind myself to add sandbox violation logging via the log socket.
928
92920140314
930 - (tim) [opensshd.init.in] Add support for ed25519
931
120140313 93220140313
2 - (djm) Release OpenSSH 6.6 933 - (djm) Release OpenSSH 6.6
3 934
@@ -2884,4 +3815,3 @@
2884 [contrib/suse/openssh.spec] Update for release 6.0 3815 [contrib/suse/openssh.spec] Update for release 6.0
2885 - (djm) [README] Update URL to release notes. 3816 - (djm) [README] Update URL to release notes.
2886 - (djm) Release openssh-6.0 3817 - (djm) Release openssh-6.0
2887
diff --git a/INSTALL b/INSTALL
index 576723048..cbbb2df59 100644
--- a/INSTALL
+++ b/INSTALL
@@ -1,22 +1,26 @@
11. Prerequisites 11. Prerequisites
2---------------- 2----------------
3 3
4You will need working installations of Zlib and OpenSSL. 4You will need working installations of Zlib and libcrypto (LibreSSL /
5OpenSSL)
5 6
6Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems): 7Zlib 1.1.4 or 1.2.1.2 or greater (ealier 1.2.x versions have problems):
7http://www.gzip.org/zlib/ 8http://www.gzip.org/zlib/
8 9
9OpenSSL 0.9.6 or greater: 10libcrypto (LibreSSL or OpenSSL >= 0.9.8f)
10http://www.openssl.org/ 11LibreSSL http://www.libressl.org/ ; or
12OpenSSL http://www.openssl.org/
11 13
12(OpenSSL 0.9.5a is partially supported, but some ciphers (SSH protocol 1 14LibreSSL/OpenSSL should be compiled as a position-independent library
13Blowfish) do not work correctly.) 15(i.e. with -fPIC) otherwise OpenSSH will not be able to link with it.
16If you must use a non-position-independent libcrypto, then you may need
17to configure OpenSSH --without-pie.
14 18
15The remaining items are optional. 19The remaining items are optional.
16 20
17NB. If you operating system supports /dev/random, you should configure 21NB. If you operating system supports /dev/random, you should configure
18OpenSSL to use it. OpenSSH relies on OpenSSL's direct support of 22libcrypto (LibreSSL/OpenSSL) to use it. OpenSSH relies on libcrypto's
19/dev/random, or failing that, either prngd or egd 23direct support of /dev/random, or failing that, either prngd or egd
20 24
21PRNGD: 25PRNGD:
22 26
@@ -27,10 +31,10 @@ http://prngd.sourceforge.net/
27 31
28EGD: 32EGD:
29 33
30The Entropy Gathering Daemon (EGD) is supported if you have a system which 34If the kernel lacks /dev/random the Entropy Gathering Daemon (EGD) is
31lacks /dev/random and don't want to use OpenSSH's internal entropy collection. 35supported only if libcrypto supports it.
32 36
33http://www.lothar.com/tech/crypto/ 37http://egd.sourceforge.net/
34 38
35PAM: 39PAM:
36 40
@@ -55,15 +59,6 @@ passphrase requester. This is maintained separately at:
55 59
56http://www.jmknoble.net/software/x11-ssh-askpass/ 60http://www.jmknoble.net/software/x11-ssh-askpass/
57 61
58TCP Wrappers:
59
60If you wish to use the TCP wrappers functionality you will need at least
61tcpd.h and libwrap.a, either in the standard include and library paths,
62or in the directory specified by --with-tcp-wrappers. Version 7.6 is
63known to work.
64
65http://ftp.porcupine.org/pub/security/index.html
66
67S/Key Libraries: 62S/Key Libraries:
68 63
69If you wish to use --with-skey then you will need the library below 64If you wish to use --with-skey then you will need the library below
@@ -180,9 +175,6 @@ Integration Architecture. The default for OSF1 machines is enable.
180--with-skey=PATH will enable S/Key one time password support. You will 175--with-skey=PATH will enable S/Key one time password support. You will
181need the S/Key libraries and header files installed for this to work. 176need the S/Key libraries and header files installed for this to work.
182 177
183--with-tcp-wrappers will enable TCP Wrappers (/etc/hosts.allow|deny)
184support.
185
186--with-md5-passwords will enable the use of MD5 passwords. Enable this 178--with-md5-passwords will enable the use of MD5 passwords. Enable this
187if your operating system uses MD5 passwords and the system crypt() does 179if your operating system uses MD5 passwords and the system crypt() does
188not support them directly (see the crypt(3/3c) man page). If enabled, the 180not support them directly (see the crypt(3/3c) man page). If enabled, the
@@ -204,10 +196,11 @@ created.
204 196
205--with-xauth=PATH specifies the location of the xauth binary 197--with-xauth=PATH specifies the location of the xauth binary
206 198
207--with-ssl-dir=DIR allows you to specify where your OpenSSL libraries 199--with-ssl-dir=DIR allows you to specify where your Libre/OpenSSL
200libraries
208are installed. 201are installed.
209 202
210--with-ssl-engine enables OpenSSL's (hardware) ENGINE support 203--with-ssl-engine enables Libre/OpenSSL's (hardware) ENGINE support
211 204
212--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to 205--with-4in6 Check for IPv4 in IPv6 mapped addresses and convert them to
213real (AF_INET) IPv4 addresses. Works around some quirks on Linux. 206real (AF_INET) IPv4 addresses. Works around some quirks on Linux.
@@ -266,4 +259,4 @@ Please refer to the "reporting bugs" section of the webpage at
266http://www.openssh.com/ 259http://www.openssh.com/
267 260
268 261
269$Id: INSTALL,v 1.88 2013/03/07 01:33:35 dtucker Exp $ 262$Id: INSTALL,v 1.91 2014/09/09 02:23:11 dtucker Exp $
diff --git a/Makefile.in b/Makefile.in
index 7d192bb7c..4eab574a7 100644
--- a/Makefile.in
+++ b/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.356 2014/02/04 00:12:56 djm Exp $ 1# $Id: Makefile.in,v 1.365 2014/08/30 06:23:07 djm Exp $
2 2
3# uncomment if you run a non bourne compatable shell. Ie. csh 3# uncomment if you run a non bourne compatable shell. Ie. csh
4#SHELL = @SH@ 4#SHELL = @SH@
@@ -29,6 +29,7 @@ SSH_PKCS11_HELPER=$(libexecdir)/ssh-pkcs11-helper
29PRIVSEP_PATH=@PRIVSEP_PATH@ 29PRIVSEP_PATH=@PRIVSEP_PATH@
30SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@ 30SSH_PRIVSEP_USER=@SSH_PRIVSEP_USER@
31STRIP_OPT=@STRIP_OPT@ 31STRIP_OPT=@STRIP_OPT@
32TEST_SHELL=@TEST_SHELL@
32 33
33PATHS= -DSSHDIR=\"$(sysconfdir)\" \ 34PATHS= -DSSHDIR=\"$(sysconfdir)\" \
34 -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \ 35 -D_PATH_SSH_PROGRAM=\"$(SSH_PROGRAM)\" \
@@ -63,7 +64,16 @@ MANFMT=@MANFMT@
63 64
64TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT) 65TARGETS=ssh$(EXEEXT) sshd$(EXEEXT) ssh-add$(EXEEXT) ssh-keygen$(EXEEXT) ssh-keyscan${EXEEXT} ssh-keysign${EXEEXT} ssh-pkcs11-helper$(EXEEXT) ssh-agent$(EXEEXT) scp$(EXEEXT) sftp-server$(EXEEXT) sftp$(EXEEXT)
65 66
66LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ 67LIBOPENSSH_OBJS=\
68 ssherr.o \
69 sshbuf.o \
70 sshkey.o \
71 sshbuf-getput-basic.o \
72 sshbuf-misc.o \
73 sshbuf-getput-crypto.o
74
75LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
76 authfd.o authfile.o bufaux.o bufbn.o buffer.o \
67 canohost.o channels.o cipher.o cipher-aes.o \ 77 canohost.o channels.o cipher.o cipher-aes.o \
68 cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \ 78 cipher-bf1.o cipher-ctr.o cipher-3des1.o cleanup.o \
69 compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \ 79 compat.o compress.o crc32.o deattack.o fatal.o hostfile.o \
@@ -137,7 +147,7 @@ $(SSHOBJS): Makefile.in config.h
137$(SSHDOBJS): Makefile.in config.h 147$(SSHDOBJS): Makefile.in config.h
138 148
139.c.o: 149.c.o:
140 $(CC) $(CFLAGS) $(CPPFLAGS) -c $< 150 $(CC) $(CFLAGS) $(CPPFLAGS) -c $< -o $@
141 151
142LIBCOMPAT=openbsd-compat/libopenbsd-compat.a 152LIBCOMPAT=openbsd-compat/libopenbsd-compat.a
143$(LIBCOMPAT): always 153$(LIBCOMPAT): always
@@ -216,6 +226,12 @@ umac128.o: umac.c
216clean: regressclean 226clean: regressclean
217 rm -f *.o *.a $(TARGETS) logintest config.cache config.log 227 rm -f *.o *.a $(TARGETS) logintest config.cache config.log
218 rm -f *.out core survey 228 rm -f *.out core survey
229 rm -f regress/unittests/test_helper/*.a
230 rm -f regress/unittests/test_helper/*.o
231 rm -f regress/unittests/sshbuf/*.o
232 rm -f regress/unittests/sshbuf/test_sshbuf
233 rm -f regress/unittests/sshkey/*.o
234 rm -f regress/unittests/sshkey/test_sshkey
219 (cd openbsd-compat && $(MAKE) clean) 235 (cd openbsd-compat && $(MAKE) clean)
220 236
221distclean: regressclean 237distclean: regressclean
@@ -224,6 +240,12 @@ distclean: regressclean
224 rm -f Makefile buildpkg.sh config.h config.status 240 rm -f Makefile buildpkg.sh config.h config.status
225 rm -f survey.sh openbsd-compat/regress/Makefile *~ 241 rm -f survey.sh openbsd-compat/regress/Makefile *~
226 rm -rf autom4te.cache 242 rm -rf autom4te.cache
243 rm -f regress/unittests/test_helper/*.a
244 rm -f regress/unittests/test_helper/*.o
245 rm -f regress/unittests/sshbuf/*.o
246 rm -f regress/unittests/sshbuf/test_sshbuf
247 rm -f regress/unittests/sshkey/*.o
248 rm -f regress/unittests/sshkey/test_sshkey
227 (cd openbsd-compat && $(MAKE) distclean) 249 (cd openbsd-compat && $(MAKE) distclean)
228 if test -d pkg ; then \ 250 if test -d pkg ; then \
229 rm -fr pkg ; \ 251 rm -fr pkg ; \
@@ -397,23 +419,71 @@ uninstall:
397 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 419 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
398 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1 420 -rm -f $(DESTDIR)$(mandir)/$(mansubdir)1/slogin.1
399 421
400regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c 422regress-prep:
401 [ -d `pwd`/regress ] || mkdir -p `pwd`/regress 423 [ -d `pwd`/regress ] || mkdir -p `pwd`/regress
424 [ -d `pwd`/regress/unittests ] || mkdir -p `pwd`/regress/unittests
425 [ -d `pwd`/regress/unittests/test_helper ] || \
426 mkdir -p `pwd`/regress/unittests/test_helper
427 [ -d `pwd`/regress/unittests/sshbuf ] || \
428 mkdir -p `pwd`/regress/unittests/sshbuf
429 [ -d `pwd`/regress/unittests/sshkey ] || \
430 mkdir -p `pwd`/regress/unittests/sshkey
402 [ -f `pwd`/regress/Makefile ] || \ 431 [ -f `pwd`/regress/Makefile ] || \
403 ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile 432 ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
433
434regress/modpipe$(EXEEXT): $(srcdir)/regress/modpipe.c
404 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ 435 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
405 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) 436 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
406 437
407regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c 438regress/setuid-allowed$(EXEEXT): $(srcdir)/regress/setuid-allowed.c
408 [ -d `pwd`/regress ] || mkdir -p `pwd`/regress
409 [ -f `pwd`/regress/Makefile ] || \
410 ln -s `cd $(srcdir) && pwd`/regress/Makefile `pwd`/regress/Makefile
411 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \ 439 $(CC) $(CFLAGS) $(CPPFLAGS) -o $@ $? \
412 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS) 440 $(LDFLAGS) -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
413 441
414tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$(EXEEXT) 442UNITTESTS_TEST_HELPER_OBJS=\
443 regress/unittests/test_helper/test_helper.o \
444 regress/unittests/test_helper/fuzz.o
445
446regress/unittests/test_helper/libtest_helper.a: ${UNITTESTS_TEST_HELPER_OBJS}
447 $(AR) rv $@ $(UNITTESTS_TEST_HELPER_OBJS)
448 $(RANLIB) $@
449
450UNITTESTS_TEST_SSHBUF_OBJS=\
451 regress/unittests/sshbuf/tests.o \
452 regress/unittests/sshbuf/test_sshbuf.o \
453 regress/unittests/sshbuf/test_sshbuf_getput_basic.o \
454 regress/unittests/sshbuf/test_sshbuf_getput_crypto.o \
455 regress/unittests/sshbuf/test_sshbuf_misc.o \
456 regress/unittests/sshbuf/test_sshbuf_fuzz.o \
457 regress/unittests/sshbuf/test_sshbuf_getput_fuzz.o \
458 regress/unittests/sshbuf/test_sshbuf_fixed.o
459
460regress/unittests/sshbuf/test_sshbuf$(EXEEXT): ${UNITTESTS_TEST_SSHBUF_OBJS} \
461 regress/unittests/test_helper/libtest_helper.a libssh.a
462 $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHBUF_OBJS) \
463 regress/unittests/test_helper/libtest_helper.a \
464 -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
465
466UNITTESTS_TEST_SSHKEY_OBJS=\
467 regress/unittests/sshkey/test_fuzz.o \
468 regress/unittests/sshkey/tests.o \
469 regress/unittests/sshkey/common.o \
470 regress/unittests/sshkey/test_file.o \
471 regress/unittests/sshkey/test_sshkey.o
472
473regress/unittests/sshkey/test_sshkey$(EXEEXT): ${UNITTESTS_TEST_SSHKEY_OBJS} \
474 regress/unittests/test_helper/libtest_helper.a libssh.a
475 $(LD) -o $@ $(LDFLAGS) $(UNITTESTS_TEST_SSHKEY_OBJS) \
476 regress/unittests/test_helper/libtest_helper.a \
477 -lssh -lopenbsd-compat -lssh -lopenbsd-compat $(LIBS)
478
479REGRESS_BINARIES=\
480 regress/modpipe$(EXEEXT) \
481 regress/setuid-allowed$(EXEEXT) \
482 regress/unittests/sshbuf/test_sshbuf$(EXEEXT) \
483 regress/unittests/sshkey/test_sshkey$(EXEEXT)
484
485tests interop-tests t-exec: regress-prep $(TARGETS) $(REGRESS_BINARIES)
415 BUILDDIR=`pwd`; \ 486 BUILDDIR=`pwd`; \
416 TEST_SHELL="@TEST_SHELL@"; \
417 TEST_SSH_SCP="$${BUILDDIR}/scp"; \ 487 TEST_SSH_SCP="$${BUILDDIR}/scp"; \
418 TEST_SSH_SSH="$${BUILDDIR}/ssh"; \ 488 TEST_SSH_SSH="$${BUILDDIR}/ssh"; \
419 TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \ 489 TEST_SSH_SSHD="$${BUILDDIR}/sshd"; \
@@ -437,7 +507,6 @@ tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$
437 OBJ="$${BUILDDIR}/regress/" \ 507 OBJ="$${BUILDDIR}/regress/" \
438 PATH="$${BUILDDIR}:$${PATH}" \ 508 PATH="$${BUILDDIR}:$${PATH}" \
439 TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \ 509 TEST_ENV=MALLOC_OPTIONS="@TEST_MALLOC_OPTIONS@" \
440 TEST_SHELL="$${TEST_SHELL}" \
441 TEST_SSH_SCP="$${TEST_SSH_SCP}" \ 510 TEST_SSH_SCP="$${TEST_SSH_SCP}" \
442 TEST_SSH_SSH="$${TEST_SSH_SSH}" \ 511 TEST_SSH_SSH="$${TEST_SSH_SSH}" \
443 TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \ 512 TEST_SSH_SSHD="$${TEST_SSH_SSHD}" \
@@ -453,6 +522,7 @@ tests interop-tests: $(TARGETS) regress/modpipe$(EXEEXT) regress/setuid-allowed$
453 TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \ 522 TEST_SSH_CONCH="$${TEST_SSH_CONCH}" \
454 TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \ 523 TEST_SSH_IPV6="$${TEST_SSH_IPV6}" \
455 TEST_SSH_ECC="$${TEST_SSH_ECC}" \ 524 TEST_SSH_ECC="$${TEST_SSH_ECC}" \
525 TEST_SHELL="${TEST_SHELL}" \
456 EXEEXT="$(EXEEXT)" \ 526 EXEEXT="$(EXEEXT)" \
457 $@ && echo all tests passed 527 $@ && echo all tests passed
458 528
diff --git a/PROTOCOL b/PROTOCOL
index 4a5088f90..aa59f584e 100644
--- a/PROTOCOL
+++ b/PROTOCOL
@@ -232,6 +232,56 @@ The contents of the "data" field for layer 2 packets is:
232The "frame" field contains an IEEE 802.3 Ethernet frame, including 232The "frame" field contains an IEEE 802.3 Ethernet frame, including
233header. 233header.
234 234
2352.4. connection: Unix domain socket forwarding
236
237OpenSSH supports local and remote Unix domain socket forwarding
238using the "streamlocal" extension. Forwarding is initiated as per
239TCP sockets but with a single path instead of a host and port.
240
241Similar to direct-tcpip, direct-streamlocal is sent by the client
242to request that the server make a connection to a Unix domain socket.
243
244 byte SSH_MSG_CHANNEL_OPEN
245 string "direct-streamlocal@openssh.com"
246 uint32 sender channel
247 uint32 initial window size
248 uint32 maximum packet size
249 string socket path
250 string reserved for future use
251
252Similar to forwarded-tcpip, forwarded-streamlocal is sent by the
253server when the client has previously send the server a streamlocal-forward
254GLOBAL_REQUEST.
255
256 byte SSH_MSG_CHANNEL_OPEN
257 string "forwarded-streamlocal@openssh.com"
258 uint32 sender channel
259 uint32 initial window size
260 uint32 maximum packet size
261 string socket path
262 string reserved for future use
263
264The reserved field is not currently defined and is ignored on the
265remote end. It is intended to be used in the future to pass
266information about the socket file, such as ownership and mode.
267The client currently sends the empty string for this field.
268
269Similar to tcpip-forward, streamlocal-forward is sent by the client
270to request remote forwarding of a Unix domain socket.
271
272 byte SSH2_MSG_GLOBAL_REQUEST
273 string "streamlocal-forward@openssh.com"
274 boolean TRUE
275 string socket path
276
277Similar to cancel-tcpip-forward, cancel-streamlocal-forward is sent
278by the client cancel the forwarding of a Unix domain socket.
279
280 byte SSH2_MSG_GLOBAL_REQUEST
281 string "cancel-streamlocal-forward@openssh.com"
282 boolean FALSE
283 string socket path
284
2353. SFTP protocol changes 2853. SFTP protocol changes
236 286
2373.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK 2873.1. sftp: Reversal of arguments to SSH_FXP_SYMLINK
@@ -356,4 +406,4 @@ respond with a SSH_FXP_STATUS message.
356This extension is advertised in the SSH_FXP_VERSION hello with version 406This extension is advertised in the SSH_FXP_VERSION hello with version
357"1". 407"1".
358 408
359$OpenBSD: PROTOCOL,v 1.23 2013/12/01 23:19:05 djm Exp $ 409$OpenBSD: PROTOCOL,v 1.24 2014/07/15 15:54:14 millert Exp $
diff --git a/README b/README
index 368dca59c..b21441ae0 100644
--- a/README
+++ b/README
@@ -1,4 +1,4 @@
1See http://www.openssh.com/txt/release-6.6 for the release notes. 1See http://www.openssh.com/txt/release-6.7 for the release notes.
2 2
3- A Japanese translation of this document and of the OpenSSH FAQ is 3- A Japanese translation of this document and of the OpenSSH FAQ is
4- available at http://www.unixuser.org/~haruyama/security/openssh/index.html 4- available at http://www.unixuser.org/~haruyama/security/openssh/index.html
@@ -62,4 +62,4 @@ References -
62[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9 62[6] http://www.openbsd.org/cgi-bin/man.cgi?query=style&sektion=9
63[7] http://www.openssh.com/faq.html 63[7] http://www.openssh.com/faq.html
64 64
65$Id: README,v 1.86 2014/02/27 23:03:53 djm Exp $ 65$Id: README,v 1.87 2014/08/10 01:35:06 djm Exp $
diff --git a/auth-bsdauth.c b/auth-bsdauth.c
index 0b3262b49..37ff893e6 100644
--- a/auth-bsdauth.c
+++ b/auth-bsdauth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-bsdauth.c,v 1.11 2007/09/21 08:15:29 djm Exp $ */ 1/* $OpenBSD: auth-bsdauth.c,v 1.13 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -26,6 +26,8 @@
26#include "includes.h" 26#include "includes.h"
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29#include <stdarg.h>
30#include <stdio.h>
29 31
30#include <stdarg.h> 32#include <stdarg.h>
31 33
@@ -54,6 +56,11 @@ bsdauth_query(void *ctx, char **name, char **infotxt,
54 Authctxt *authctxt = ctx; 56 Authctxt *authctxt = ctx;
55 char *challenge = NULL; 57 char *challenge = NULL;
56 58
59 *infotxt = NULL;
60 *numprompts = 0;
61 *prompts = NULL;
62 *echo_on = NULL;
63
57 if (authctxt->as != NULL) { 64 if (authctxt->as != NULL) {
58 debug2("bsdauth_query: try reuse session"); 65 debug2("bsdauth_query: try reuse session");
59 challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE); 66 challenge = auth_getitem(authctxt->as, AUTHV_CHALLENGE);
diff --git a/auth-chall.c b/auth-chall.c
index 0005aa88b..5c26a403d 100644
--- a/auth-chall.c
+++ b/auth-chall.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-chall.c,v 1.13 2013/05/17 00:13:13 djm Exp $ */ 1/* $OpenBSD: auth-chall.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -26,6 +26,9 @@
26#include "includes.h" 26#include "includes.h"
27 27
28#include <sys/types.h> 28#include <sys/types.h>
29#include <stdarg.h>
30#include <stdlib.h>
31#include <stdio.h>
29 32
30#include <stdarg.h> 33#include <stdarg.h>
31 34
@@ -34,6 +37,7 @@
34#include "hostfile.h" 37#include "hostfile.h"
35#include "auth.h" 38#include "auth.h"
36#include "log.h" 39#include "log.h"
40#include "misc.h"
37#include "servconf.h" 41#include "servconf.h"
38 42
39/* limited protocol v1 interface to kbd-interactive authentication */ 43/* limited protocol v1 interface to kbd-interactive authentication */
diff --git a/auth-krb5.c b/auth-krb5.c
index 69a1a53e2..ec4786924 100644
--- a/auth-krb5.c
+++ b/auth-krb5.c
@@ -40,6 +40,7 @@
40#include "packet.h" 40#include "packet.h"
41#include "log.h" 41#include "log.h"
42#include "buffer.h" 42#include "buffer.h"
43#include "misc.h"
43#include "servconf.h" 44#include "servconf.h"
44#include "uidswap.h" 45#include "uidswap.h"
45#include "key.h" 46#include "key.h"
diff --git a/auth-options.c b/auth-options.c
index df6133037..d4d22d7a5 100644
--- a/auth-options.c
+++ b/auth-options.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-options.c,v 1.62 2013/12/19 00:27:57 djm Exp $ */ 1/* $OpenBSD: auth-options.c,v 1.64 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -26,9 +26,9 @@
26#include "log.h" 26#include "log.h"
27#include "canohost.h" 27#include "canohost.h"
28#include "buffer.h" 28#include "buffer.h"
29#include "misc.h"
29#include "channels.h" 30#include "channels.h"
30#include "servconf.h" 31#include "servconf.h"
31#include "misc.h"
32#include "key.h" 32#include "key.h"
33#include "auth-options.h" 33#include "auth-options.h"
34#include "hostfile.h" 34#include "hostfile.h"
@@ -339,6 +339,7 @@ auth_parse_options(struct passwd *pw, char *opts, char *file, u_long linenum)
339 patterns[i] = '\0'; 339 patterns[i] = '\0';
340 opts++; 340 opts++;
341 p = patterns; 341 p = patterns;
342 /* XXX - add streamlocal support */
342 host = hpdelim(&p); 343 host = hpdelim(&p);
343 if (host == NULL || strlen(host) >= NI_MAXHOST) { 344 if (host == NULL || strlen(host) >= NI_MAXHOST) {
344 debug("%.100s, line %lu: Bad permitopen " 345 debug("%.100s, line %lu: Bad permitopen "
@@ -603,8 +604,8 @@ auth_cert_options(Key *k, struct passwd *pw)
603 604
604 if (key_cert_is_legacy(k)) { 605 if (key_cert_is_legacy(k)) {
605 /* All options are in the one field for v00 certs */ 606 /* All options are in the one field for v00 certs */
606 if (parse_option_list(buffer_ptr(&k->cert->critical), 607 if (parse_option_list(buffer_ptr(k->cert->critical),
607 buffer_len(&k->cert->critical), pw, 608 buffer_len(k->cert->critical), pw,
608 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1, 609 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS, 1,
609 &cert_no_port_forwarding_flag, 610 &cert_no_port_forwarding_flag,
610 &cert_no_agent_forwarding_flag, 611 &cert_no_agent_forwarding_flag,
@@ -616,14 +617,14 @@ auth_cert_options(Key *k, struct passwd *pw)
616 return -1; 617 return -1;
617 } else { 618 } else {
618 /* Separate options and extensions for v01 certs */ 619 /* Separate options and extensions for v01 certs */
619 if (parse_option_list(buffer_ptr(&k->cert->critical), 620 if (parse_option_list(buffer_ptr(k->cert->critical),
620 buffer_len(&k->cert->critical), pw, 621 buffer_len(k->cert->critical), pw,
621 OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL, 622 OPTIONS_CRITICAL, 1, NULL, NULL, NULL, NULL, NULL,
622 &cert_forced_command, 623 &cert_forced_command,
623 &cert_source_address_done) == -1) 624 &cert_source_address_done) == -1)
624 return -1; 625 return -1;
625 if (parse_option_list(buffer_ptr(&k->cert->extensions), 626 if (parse_option_list(buffer_ptr(k->cert->extensions),
626 buffer_len(&k->cert->extensions), pw, 627 buffer_len(k->cert->extensions), pw,
627 OPTIONS_EXTENSIONS, 1, 628 OPTIONS_EXTENSIONS, 1,
628 &cert_no_port_forwarding_flag, 629 &cert_no_port_forwarding_flag,
629 &cert_no_agent_forwarding_flag, 630 &cert_no_agent_forwarding_flag,
diff --git a/auth-passwd.c b/auth-passwd.c
index 68bbd18dd..63ccf3cab 100644
--- a/auth-passwd.c
+++ b/auth-passwd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-passwd.c,v 1.43 2007/09/21 08:15:29 djm Exp $ */ 1/* $OpenBSD: auth-passwd.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -48,6 +48,7 @@
48#include "packet.h" 48#include "packet.h"
49#include "buffer.h" 49#include "buffer.h"
50#include "log.h" 50#include "log.h"
51#include "misc.h"
51#include "servconf.h" 52#include "servconf.h"
52#include "key.h" 53#include "key.h"
53#include "hostfile.h" 54#include "hostfile.h"
diff --git a/auth-rh-rsa.c b/auth-rh-rsa.c
index b21a0f4a2..b7fd064e7 100644
--- a/auth-rh-rsa.c
+++ b/auth-rh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-rh-rsa.c,v 1.43 2010/03/04 10:36:03 djm Exp $ */ 1/* $OpenBSD: auth-rh-rsa.c,v 1.44 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -24,6 +24,7 @@
24#include "uidswap.h" 24#include "uidswap.h"
25#include "log.h" 25#include "log.h"
26#include "buffer.h" 26#include "buffer.h"
27#include "misc.h"
27#include "servconf.h" 28#include "servconf.h"
28#include "key.h" 29#include "key.h"
29#include "hostfile.h" 30#include "hostfile.h"
diff --git a/auth-rhosts.c b/auth-rhosts.c
index f20278797..11fcca643 100644
--- a/auth-rhosts.c
+++ b/auth-rhosts.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-rhosts.c,v 1.44 2010/03/07 11:57:13 dtucker Exp $ */ 1/* $OpenBSD: auth-rhosts.c,v 1.45 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,12 +34,12 @@
34#include "uidswap.h" 34#include "uidswap.h"
35#include "pathnames.h" 35#include "pathnames.h"
36#include "log.h" 36#include "log.h"
37#include "misc.h"
37#include "servconf.h" 38#include "servconf.h"
38#include "canohost.h" 39#include "canohost.h"
39#include "key.h" 40#include "key.h"
40#include "hostfile.h" 41#include "hostfile.h"
41#include "auth.h" 42#include "auth.h"
42#include "misc.h"
43 43
44/* import */ 44/* import */
45extern ServerOptions options; 45extern ServerOptions options;
diff --git a/auth-rsa.c b/auth-rsa.c
index 260ce2f98..5d7bdcbfc 100644
--- a/auth-rsa.c
+++ b/auth-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth-rsa.c,v 1.86 2014/01/27 19:18:54 markus Exp $ */ 1/* $OpenBSD: auth-rsa.c,v 1.88 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,6 +35,7 @@
35#include "buffer.h" 35#include "buffer.h"
36#include "pathnames.h" 36#include "pathnames.h"
37#include "log.h" 37#include "log.h"
38#include "misc.h"
38#include "servconf.h" 39#include "servconf.h"
39#include "key.h" 40#include "key.h"
40#include "auth-options.h" 41#include "auth-options.h"
@@ -45,7 +46,6 @@
45#endif 46#endif
46#include "monitor_wrap.h" 47#include "monitor_wrap.h"
47#include "ssh.h" 48#include "ssh.h"
48#include "misc.h"
49 49
50#include "digest.h" 50#include "digest.h"
51 51
@@ -144,7 +144,8 @@ auth_rsa_challenge_dialog(Key *key)
144 challenge = PRIVSEP(auth_rsa_generate_challenge(key)); 144 challenge = PRIVSEP(auth_rsa_generate_challenge(key));
145 145
146 /* Encrypt the challenge with the public key. */ 146 /* Encrypt the challenge with the public key. */
147 rsa_public_encrypt(encrypted_challenge, challenge, key->rsa); 147 if (rsa_public_encrypt(encrypted_challenge, challenge, key->rsa) != 0)
148 fatal("%s: rsa_public_encrypt failed", __func__);
148 149
149 /* Send the encrypted challenge to the client. */ 150 /* Send the encrypted challenge to the client. */
150 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE); 151 packet_start(SSH_SMSG_AUTH_RSA_CHALLENGE);
diff --git a/auth.c b/auth.c
index 0c45f0954..18de51a29 100644
--- a/auth.c
+++ b/auth.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.c,v 1.103 2013/05/19 02:42:42 djm Exp $ */ 1/* $OpenBSD: auth.c,v 1.106 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -56,6 +56,7 @@
56#include "groupaccess.h" 56#include "groupaccess.h"
57#include "log.h" 57#include "log.h"
58#include "buffer.h" 58#include "buffer.h"
59#include "misc.h"
59#include "servconf.h" 60#include "servconf.h"
60#include "key.h" 61#include "key.h"
61#include "hostfile.h" 62#include "hostfile.h"
@@ -63,7 +64,6 @@
63#include "auth-options.h" 64#include "auth-options.h"
64#include "canohost.h" 65#include "canohost.h"
65#include "uidswap.h" 66#include "uidswap.h"
66#include "misc.h"
67#include "packet.h" 67#include "packet.h"
68#include "loginrec.h" 68#include "loginrec.h"
69#ifdef GSSAPI 69#ifdef GSSAPI
@@ -326,6 +326,20 @@ auth_log(Authctxt *authctxt, int authenticated, int partial,
326#endif 326#endif
327} 327}
328 328
329
330void
331auth_maxtries_exceeded(Authctxt *authctxt)
332{
333 packet_disconnect("Too many authentication failures for "
334 "%s%.100s from %.200s port %d %s",
335 authctxt->valid ? "" : "invalid user ",
336 authctxt->user,
337 get_remote_ipaddr(),
338 get_remote_port(),
339 compat20 ? "ssh2" : "ssh1");
340 /* NOTREACHED */
341}
342
329/* 343/*
330 * Check whether root logins are disallowed. 344 * Check whether root logins are disallowed.
331 */ 345 */
@@ -656,6 +670,7 @@ getpwnamallow(const char *user)
656int 670int
657auth_key_is_revoked(Key *key) 671auth_key_is_revoked(Key *key)
658{ 672{
673#ifdef WITH_OPENSSL
659 char *key_fp; 674 char *key_fp;
660 675
661 if (options.revoked_keys_file == NULL) 676 if (options.revoked_keys_file == NULL)
@@ -668,6 +683,7 @@ auth_key_is_revoked(Key *key)
668 default: 683 default:
669 goto revoked; 684 goto revoked;
670 } 685 }
686#endif
671 debug3("%s: treating %s as a key list", __func__, 687 debug3("%s: treating %s as a key list", __func__,
672 options.revoked_keys_file); 688 options.revoked_keys_file);
673 switch (key_in_file(key, options.revoked_keys_file, 0)) { 689 switch (key_in_file(key, options.revoked_keys_file, 0)) {
@@ -679,6 +695,7 @@ auth_key_is_revoked(Key *key)
679 error("Revoked keys file is unreadable: refusing public key " 695 error("Revoked keys file is unreadable: refusing public key "
680 "authentication"); 696 "authentication");
681 return 1; 697 return 1;
698#ifdef WITH_OPENSSL
682 case 1: 699 case 1:
683 revoked: 700 revoked:
684 /* Key revoked */ 701 /* Key revoked */
@@ -687,6 +704,7 @@ auth_key_is_revoked(Key *key)
687 "%s key %s ", key_type(key), key_fp); 704 "%s key %s ", key_type(key), key_fp);
688 free(key_fp); 705 free(key_fp);
689 return 1; 706 return 1;
707#endif
690 } 708 }
691 fatal("key_in_file returned junk"); 709 fatal("key_in_file returned junk");
692} 710}
diff --git a/auth.h b/auth.h
index 79e4ea53a..f099e9807 100644
--- a/auth.h
+++ b/auth.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth.h,v 1.77 2014/01/29 06:18:35 djm Exp $ */ 1/* $OpenBSD: auth.h,v 1.78 2014/07/03 11:16:55 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -155,6 +155,7 @@ void auth_info(Authctxt *authctxt, const char *, ...)
155 __attribute__((__format__ (printf, 2, 3))) 155 __attribute__((__format__ (printf, 2, 3)))
156 __attribute__((__nonnull__ (2))); 156 __attribute__((__nonnull__ (2)));
157void auth_log(Authctxt *, int, int, const char *, const char *); 157void auth_log(Authctxt *, int, int, const char *, const char *);
158void auth_maxtries_exceeded(Authctxt *) __attribute__((noreturn));
158void userauth_finish(Authctxt *, int, const char *, const char *); 159void userauth_finish(Authctxt *, int, const char *, const char *);
159int auth_root_allowed(const char *); 160int auth_root_allowed(const char *);
160 161
@@ -211,8 +212,6 @@ struct passwd *fakepw(void);
211 212
212int sys_auth_passwd(Authctxt *, const char *); 213int sys_auth_passwd(Authctxt *, const char *);
213 214
214#define AUTH_FAIL_MSG "Too many authentication failures for %.100s"
215
216#define SKEY_PROMPT "\nS/Key Password: " 215#define SKEY_PROMPT "\nS/Key Password: "
217 216
218#if defined(KRB5) && !defined(HEIMDAL) 217#if defined(KRB5) && !defined(HEIMDAL)
diff --git a/auth1.c b/auth1.c
index c70739080..52b17dbef 100644
--- a/auth1.c
+++ b/auth1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth1.c,v 1.80 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: auth1.c,v 1.82 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -27,6 +27,7 @@
27#include "packet.h" 27#include "packet.h"
28#include "buffer.h" 28#include "buffer.h"
29#include "log.h" 29#include "log.h"
30#include "misc.h"
30#include "servconf.h" 31#include "servconf.h"
31#include "compat.h" 32#include "compat.h"
32#include "key.h" 33#include "key.h"
@@ -363,7 +364,7 @@ do_authloop(Authctxt *authctxt)
363#ifdef SSH_AUDIT_EVENTS 364#ifdef SSH_AUDIT_EVENTS
364 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); 365 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
365#endif 366#endif
366 packet_disconnect(AUTH_FAIL_MSG, authctxt->user); 367 auth_maxtries_exceeded(authctxt);
367 } 368 }
368 369
369 packet_start(SSH_SMSG_FAILURE); 370 packet_start(SSH_SMSG_FAILURE);
diff --git a/auth2-chall.c b/auth2-chall.c
index 980250a91..ea4eb6952 100644
--- a/auth2-chall.c
+++ b/auth2-chall.c
@@ -41,6 +41,7 @@
41#include "packet.h" 41#include "packet.h"
42#include "dispatch.h" 42#include "dispatch.h"
43#include "log.h" 43#include "log.h"
44#include "misc.h"
44#include "servconf.h" 45#include "servconf.h"
45 46
46/* import */ 47/* import */
diff --git a/auth2-gss.c b/auth2-gss.c
index 3ff2d726b..284f364b0 100644
--- a/auth2-gss.c
+++ b/auth2-gss.c
@@ -40,6 +40,7 @@
40#include "log.h" 40#include "log.h"
41#include "dispatch.h" 41#include "dispatch.h"
42#include "buffer.h" 42#include "buffer.h"
43#include "misc.h"
43#include "servconf.h" 44#include "servconf.h"
44#include "packet.h" 45#include "packet.h"
45#include "ssh-gss.h" 46#include "ssh-gss.h"
diff --git a/auth2-hostbased.c b/auth2-hostbased.c
index 488008f62..6787e4ca4 100644
--- a/auth2-hostbased.c
+++ b/auth2-hostbased.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-hostbased.c,v 1.17 2013/12/30 23:52:27 djm Exp $ */ 1/* $OpenBSD: auth2-hostbased.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -36,6 +36,7 @@
36#include "packet.h" 36#include "packet.h"
37#include "buffer.h" 37#include "buffer.h"
38#include "log.h" 38#include "log.h"
39#include "misc.h"
39#include "servconf.h" 40#include "servconf.h"
40#include "compat.h" 41#include "compat.h"
41#include "key.h" 42#include "key.h"
diff --git a/auth2-kbdint.c b/auth2-kbdint.c
index c39bdc62d..bf75c6059 100644
--- a/auth2-kbdint.c
+++ b/auth2-kbdint.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-kbdint.c,v 1.6 2013/05/17 00:13:13 djm Exp $ */ 1/* $OpenBSD: auth2-kbdint.c,v 1.7 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -36,6 +36,7 @@
36#include "auth.h" 36#include "auth.h"
37#include "log.h" 37#include "log.h"
38#include "buffer.h" 38#include "buffer.h"
39#include "misc.h"
39#include "servconf.h" 40#include "servconf.h"
40 41
41/* import */ 42/* import */
diff --git a/auth2-none.c b/auth2-none.c
index c8c6c74a9..e71e2219c 100644
--- a/auth2-none.c
+++ b/auth2-none.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-none.c,v 1.16 2010/06/25 08:46:17 djm Exp $ */ 1/* $OpenBSD: auth2-none.c,v 1.18 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -30,9 +30,10 @@
30#include <sys/uio.h> 30#include <sys/uio.h>
31 31
32#include <fcntl.h> 32#include <fcntl.h>
33#include <stdarg.h>
34#include <string.h> 33#include <string.h>
35#include <unistd.h> 34#include <unistd.h>
35#include <stdarg.h>
36#include <stdio.h>
36 37
37#include "atomicio.h" 38#include "atomicio.h"
38#include "xmalloc.h" 39#include "xmalloc.h"
@@ -42,6 +43,7 @@
42#include "packet.h" 43#include "packet.h"
43#include "log.h" 44#include "log.h"
44#include "buffer.h" 45#include "buffer.h"
46#include "misc.h"
45#include "servconf.h" 47#include "servconf.h"
46#include "compat.h" 48#include "compat.h"
47#include "ssh2.h" 49#include "ssh2.h"
diff --git a/auth2-passwd.c b/auth2-passwd.c
index 707680cd0..b638e8715 100644
--- a/auth2-passwd.c
+++ b/auth2-passwd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-passwd.c,v 1.11 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: auth2-passwd.c,v 1.12 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -41,6 +41,7 @@
41#include "ssh-gss.h" 41#include "ssh-gss.h"
42#endif 42#endif
43#include "monitor_wrap.h" 43#include "monitor_wrap.h"
44#include "misc.h"
44#include "servconf.h" 45#include "servconf.h"
45 46
46/* import */ 47/* import */
diff --git a/auth2-pubkey.c b/auth2-pubkey.c
index 7c5692750..f78b046b8 100644
--- a/auth2-pubkey.c
+++ b/auth2-pubkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2-pubkey.c,v 1.39 2013/12/30 23:52:27 djm Exp $ */ 1/* $OpenBSD: auth2-pubkey.c,v 1.41 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -48,6 +48,7 @@
48#include "packet.h" 48#include "packet.h"
49#include "buffer.h" 49#include "buffer.h"
50#include "log.h" 50#include "log.h"
51#include "misc.h"
51#include "servconf.h" 52#include "servconf.h"
52#include "compat.h" 53#include "compat.h"
53#include "key.h" 54#include "key.h"
@@ -61,7 +62,6 @@
61#include "ssh-gss.h" 62#include "ssh-gss.h"
62#endif 63#endif
63#include "monitor_wrap.h" 64#include "monitor_wrap.h"
64#include "misc.h"
65#include "authfile.h" 65#include "authfile.h"
66#include "match.h" 66#include "match.h"
67 67
@@ -230,7 +230,7 @@ pubkey_auth_info(Authctxt *authctxt, const Key *key, const char *fmt, ...)
230} 230}
231 231
232static int 232static int
233match_principals_option(const char *principal_list, struct KeyCert *cert) 233match_principals_option(const char *principal_list, struct sshkey_cert *cert)
234{ 234{
235 char *result; 235 char *result;
236 u_int i; 236 u_int i;
@@ -250,7 +250,7 @@ match_principals_option(const char *principal_list, struct KeyCert *cert)
250} 250}
251 251
252static int 252static int
253match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) 253match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
254{ 254{
255 FILE *f; 255 FILE *f;
256 char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts; 256 char line[SSH_MAX_PUBKEY_BYTES], *cp, *ep, *line_opts;
diff --git a/auth2.c b/auth2.c
index 70f29250d..fa1a5886d 100644
--- a/auth2.c
+++ b/auth2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: auth2.c,v 1.130 2014/01/29 06:18:35 djm Exp $ */ 1/* $OpenBSD: auth2.c,v 1.132 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -41,6 +41,7 @@
41#include "packet.h" 41#include "packet.h"
42#include "log.h" 42#include "log.h"
43#include "buffer.h" 43#include "buffer.h"
44#include "misc.h"
44#include "servconf.h" 45#include "servconf.h"
45#include "compat.h" 46#include "compat.h"
46#include "key.h" 47#include "key.h"
@@ -370,7 +371,7 @@ userauth_finish(Authctxt *authctxt, int authenticated, const char *method,
370#ifdef SSH_AUDIT_EVENTS 371#ifdef SSH_AUDIT_EVENTS
371 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES)); 372 PRIVSEP(audit_event(SSH_LOGIN_EXCEED_MAXTRIES));
372#endif 373#endif
373 packet_disconnect(AUTH_FAIL_MSG, authctxt->user); 374 auth_maxtries_exceeded(authctxt);
374 } 375 }
375 methods = authmethods_get(authctxt); 376 methods = authmethods_get(authctxt);
376 debug3("%s: failure partial=%d next methods=\"%s\"", __func__, 377 debug3("%s: failure partial=%d next methods=\"%s\"", __func__,
diff --git a/authfd.c b/authfd.c
index cea3f97b4..2d5a8dd5b 100644
--- a/authfd.c
+++ b/authfd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: authfd.c,v 1.92 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: authfd.c,v 1.93 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -41,9 +41,6 @@
41#include <sys/un.h> 41#include <sys/un.h>
42#include <sys/socket.h> 42#include <sys/socket.h>
43 43
44#include <openssl/evp.h>
45#include <openssl/crypto.h>
46
47#include <fcntl.h> 44#include <fcntl.h>
48#include <stdlib.h> 45#include <stdlib.h>
49#include <signal.h> 46#include <signal.h>
@@ -313,8 +310,10 @@ ssh_get_first_identity(AuthenticationConnection *auth, char **comment, int versi
313Key * 310Key *
314ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version) 311ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int version)
315{ 312{
313#ifdef WITH_SSH1
316 int keybits; 314 int keybits;
317 u_int bits; 315 u_int bits;
316#endif
318 u_char *blob; 317 u_char *blob;
319 u_int blen; 318 u_int blen;
320 Key *key = NULL; 319 Key *key = NULL;
@@ -328,6 +327,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
328 * error if the packet is too short or contains corrupt data. 327 * error if the packet is too short or contains corrupt data.
329 */ 328 */
330 switch (version) { 329 switch (version) {
330#ifdef WITH_SSH1
331 case 1: 331 case 1:
332 key = key_new(KEY_RSA1); 332 key = key_new(KEY_RSA1);
333 bits = buffer_get_int(&auth->identities); 333 bits = buffer_get_int(&auth->identities);
@@ -339,6 +339,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
339 logit("Warning: identity keysize mismatch: actual %d, announced %u", 339 logit("Warning: identity keysize mismatch: actual %d, announced %u",
340 BN_num_bits(key->rsa->n), bits); 340 BN_num_bits(key->rsa->n), bits);
341 break; 341 break;
342#endif
342 case 2: 343 case 2:
343 blob = buffer_get_string(&auth->identities, &blen); 344 blob = buffer_get_string(&auth->identities, &blen);
344 *comment = buffer_get_string(&auth->identities, NULL); 345 *comment = buffer_get_string(&auth->identities, NULL);
@@ -361,6 +362,7 @@ ssh_get_next_identity(AuthenticationConnection *auth, char **comment, int versio
361 * supported) and 1 corresponding to protocol version 1.1. 362 * supported) and 1 corresponding to protocol version 1.1.
362 */ 363 */
363 364
365#ifdef WITH_SSH1
364int 366int
365ssh_decrypt_challenge(AuthenticationConnection *auth, 367ssh_decrypt_challenge(AuthenticationConnection *auth,
366 Key* key, BIGNUM *challenge, 368 Key* key, BIGNUM *challenge,
@@ -410,6 +412,7 @@ ssh_decrypt_challenge(AuthenticationConnection *auth,
410 buffer_free(&buffer); 412 buffer_free(&buffer);
411 return success; 413 return success;
412} 414}
415#endif
413 416
414/* ask agent to sign data, returns -1 on error, 0 on success */ 417/* ask agent to sign data, returns -1 on error, 0 on success */
415int 418int
@@ -457,6 +460,7 @@ ssh_agent_sign(AuthenticationConnection *auth,
457 460
458/* Encode key for a message to the agent. */ 461/* Encode key for a message to the agent. */
459 462
463#ifdef WITH_SSH1
460static void 464static void
461ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment) 465ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
462{ 466{
@@ -470,6 +474,7 @@ ssh_encode_identity_rsa1(Buffer *b, RSA *key, const char *comment)
470 buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */ 474 buffer_put_bignum(b, key->p); /* ssh key->q, SSL key->p */
471 buffer_put_cstring(b, comment); 475 buffer_put_cstring(b, comment);
472} 476}
477#endif
473 478
474static void 479static void
475ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment) 480ssh_encode_identity_ssh2(Buffer *b, Key *key, const char *comment)
@@ -493,6 +498,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
493 buffer_init(&msg); 498 buffer_init(&msg);
494 499
495 switch (key->type) { 500 switch (key->type) {
501#ifdef WITH_SSH1
496 case KEY_RSA1: 502 case KEY_RSA1:
497 type = constrained ? 503 type = constrained ?
498 SSH_AGENTC_ADD_RSA_ID_CONSTRAINED : 504 SSH_AGENTC_ADD_RSA_ID_CONSTRAINED :
@@ -500,6 +506,8 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
500 buffer_put_char(&msg, type); 506 buffer_put_char(&msg, type);
501 ssh_encode_identity_rsa1(&msg, key->rsa, comment); 507 ssh_encode_identity_rsa1(&msg, key->rsa, comment);
502 break; 508 break;
509#endif
510#ifdef WITH_OPENSSL
503 case KEY_RSA: 511 case KEY_RSA:
504 case KEY_RSA_CERT: 512 case KEY_RSA_CERT:
505 case KEY_RSA_CERT_V00: 513 case KEY_RSA_CERT_V00:
@@ -508,6 +516,7 @@ ssh_add_identity_constrained(AuthenticationConnection *auth, Key *key,
508 case KEY_DSA_CERT_V00: 516 case KEY_DSA_CERT_V00:
509 case KEY_ECDSA: 517 case KEY_ECDSA:
510 case KEY_ECDSA_CERT: 518 case KEY_ECDSA_CERT:
519#endif
511 case KEY_ED25519: 520 case KEY_ED25519:
512 case KEY_ED25519_CERT: 521 case KEY_ED25519_CERT:
513 type = constrained ? 522 type = constrained ?
@@ -552,12 +561,15 @@ ssh_remove_identity(AuthenticationConnection *auth, Key *key)
552 561
553 buffer_init(&msg); 562 buffer_init(&msg);
554 563
564#ifdef WITH_SSH1
555 if (key->type == KEY_RSA1) { 565 if (key->type == KEY_RSA1) {
556 buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY); 566 buffer_put_char(&msg, SSH_AGENTC_REMOVE_RSA_IDENTITY);
557 buffer_put_int(&msg, BN_num_bits(key->rsa->n)); 567 buffer_put_int(&msg, BN_num_bits(key->rsa->n));
558 buffer_put_bignum(&msg, key->rsa->e); 568 buffer_put_bignum(&msg, key->rsa->e);
559 buffer_put_bignum(&msg, key->rsa->n); 569 buffer_put_bignum(&msg, key->rsa->n);
560 } else if (key->type != KEY_UNSPEC) { 570 } else
571#endif
572 if (key->type != KEY_UNSPEC) {
561 key_to_blob(key, &blob, &blen); 573 key_to_blob(key, &blob, &blen);
562 buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY); 574 buffer_put_char(&msg, SSH2_AGENTC_REMOVE_IDENTITY);
563 buffer_put_string(&msg, blob, blen); 575 buffer_put_string(&msg, blob, blen);
diff --git a/authfile.c b/authfile.c
index d7eaa9dec..e93d86738 100644
--- a/authfile.c
+++ b/authfile.c
@@ -1,18 +1,5 @@
1/* $OpenBSD: authfile.c,v 1.103 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: authfile.c,v 1.107 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * This file contains functions for reading and writing identity files, and
7 * for reading the passphrase from the user.
8 *
9 * As far as I am concerned, the code I have written for this software
10 * can be used freely for any purpose. Any derived versions of this
11 * software must be clearly marked as such, and if the derived work is
12 * incompatible with the protocol description in the RFC file, it must be
13 * called by a name other than "ssh" or "Secure Shell".
14 *
15 *
16 * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
17 * 4 *
18 * Redistribution and use in source and binary forms, with or without 5 * Redistribution and use in source and binary forms, with or without
@@ -43,30 +30,15 @@
43#include <sys/param.h> 30#include <sys/param.h>
44#include <sys/uio.h> 31#include <sys/uio.h>
45 32
46#include <openssl/err.h>
47#include <openssl/evp.h>
48#include <openssl/pem.h>
49
50/* compatibility with old or broken OpenSSL versions */
51#include "openbsd-compat/openssl-compat.h"
52
53#include "crypto_api.h"
54
55#include <errno.h> 33#include <errno.h>
56#include <fcntl.h> 34#include <fcntl.h>
57#include <stdarg.h>
58#include <stdio.h> 35#include <stdio.h>
36#include <stdarg.h>
59#include <stdlib.h> 37#include <stdlib.h>
60#include <string.h> 38#include <string.h>
61#include <unistd.h> 39#include <unistd.h>
62 40
63#ifdef HAVE_UTIL_H
64#include <util.h>
65#endif
66
67#include "xmalloc.h"
68#include "cipher.h" 41#include "cipher.h"
69#include "buffer.h"
70#include "key.h" 42#include "key.h"
71#include "ssh.h" 43#include "ssh.h"
72#include "log.h" 44#include "log.h"
@@ -74,903 +46,159 @@
74#include "rsa.h" 46#include "rsa.h"
75#include "misc.h" 47#include "misc.h"
76#include "atomicio.h" 48#include "atomicio.h"
77#include "uuencode.h" 49#include "sshbuf.h"
78 50#include "ssherr.h"
79/* openssh private key file format */
80#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
81#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
82#define KDFNAME "bcrypt"
83#define AUTH_MAGIC "openssh-key-v1"
84#define SALT_LEN 16
85#define DEFAULT_CIPHERNAME "aes256-cbc"
86#define DEFAULT_ROUNDS 16
87 51
88#define MAX_KEY_FILE_SIZE (1024 * 1024) 52#define MAX_KEY_FILE_SIZE (1024 * 1024)
89 53
90/* Version identification string for SSH v1 identity files. */
91static const char authfile_id_string[] =
92 "SSH PRIVATE KEY FILE FORMAT 1.1\n";
93
94static int
95key_private_to_blob2(Key *prv, Buffer *blob, const char *passphrase,
96 const char *comment, const char *ciphername, int rounds)
97{
98 u_char *key, *cp, salt[SALT_LEN];
99 size_t keylen, ivlen, blocksize, authlen;
100 u_int len, check;
101 int i, n;
102 const Cipher *c;
103 Buffer encoded, b, kdf;
104 CipherContext ctx;
105 const char *kdfname = KDFNAME;
106
107 if (rounds <= 0)
108 rounds = DEFAULT_ROUNDS;
109 if (passphrase == NULL || !strlen(passphrase)) {
110 ciphername = "none";
111 kdfname = "none";
112 } else if (ciphername == NULL)
113 ciphername = DEFAULT_CIPHERNAME;
114 else if (cipher_number(ciphername) != SSH_CIPHER_SSH2)
115 fatal("invalid cipher");
116
117 if ((c = cipher_by_name(ciphername)) == NULL)
118 fatal("unknown cipher name");
119 buffer_init(&kdf);
120 blocksize = cipher_blocksize(c);
121 keylen = cipher_keylen(c);
122 ivlen = cipher_ivlen(c);
123 authlen = cipher_authlen(c);
124 key = xcalloc(1, keylen + ivlen);
125 if (strcmp(kdfname, "none") != 0) {
126 arc4random_buf(salt, SALT_LEN);
127 if (bcrypt_pbkdf(passphrase, strlen(passphrase),
128 salt, SALT_LEN, key, keylen + ivlen, rounds) < 0)
129 fatal("bcrypt_pbkdf failed");
130 buffer_put_string(&kdf, salt, SALT_LEN);
131 buffer_put_int(&kdf, rounds);
132 }
133 cipher_init(&ctx, c, key, keylen, key + keylen , ivlen, 1);
134 explicit_bzero(key, keylen + ivlen);
135 free(key);
136
137 buffer_init(&encoded);
138 buffer_append(&encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC));
139 buffer_put_cstring(&encoded, ciphername);
140 buffer_put_cstring(&encoded, kdfname);
141 buffer_put_string(&encoded, buffer_ptr(&kdf), buffer_len(&kdf));
142 buffer_put_int(&encoded, 1); /* number of keys */
143 key_to_blob(prv, &cp, &len); /* public key */
144 buffer_put_string(&encoded, cp, len);
145
146 explicit_bzero(cp, len);
147 free(cp);
148
149 buffer_free(&kdf);
150
151 /* set up the buffer that will be encrypted */
152 buffer_init(&b);
153
154 /* Random check bytes */
155 check = arc4random();
156 buffer_put_int(&b, check);
157 buffer_put_int(&b, check);
158
159 /* append private key and comment*/
160 key_private_serialize(prv, &b);
161 buffer_put_cstring(&b, comment);
162
163 /* padding */
164 i = 0;
165 while (buffer_len(&b) % blocksize)
166 buffer_put_char(&b, ++i & 0xff);
167
168 /* length */
169 buffer_put_int(&encoded, buffer_len(&b));
170
171 /* encrypt */
172 cp = buffer_append_space(&encoded, buffer_len(&b) + authlen);
173 if (cipher_crypt(&ctx, 0, cp, buffer_ptr(&b), buffer_len(&b), 0,
174 authlen) != 0)
175 fatal("%s: cipher_crypt failed", __func__);
176 buffer_free(&b);
177 cipher_cleanup(&ctx);
178
179 /* uuencode */
180 len = 2 * buffer_len(&encoded);
181 cp = xmalloc(len);
182 n = uuencode(buffer_ptr(&encoded), buffer_len(&encoded),
183 (char *)cp, len);
184 if (n < 0)
185 fatal("%s: uuencode", __func__);
186
187 buffer_clear(blob);
188 buffer_append(blob, MARK_BEGIN, sizeof(MARK_BEGIN) - 1);
189 for (i = 0; i < n; i++) {
190 buffer_put_char(blob, cp[i]);
191 if (i % 70 == 69)
192 buffer_put_char(blob, '\n');
193 }
194 if (i % 70 != 69)
195 buffer_put_char(blob, '\n');
196 buffer_append(blob, MARK_END, sizeof(MARK_END) - 1);
197 free(cp);
198
199 return buffer_len(blob);
200}
201
202static Key *
203key_parse_private2(Buffer *blob, int type, const char *passphrase,
204 char **commentp)
205{
206 u_char *key = NULL, *cp, *salt = NULL, pad, last;
207 char *comment = NULL, *ciphername = NULL, *kdfname = NULL, *kdfp;
208 u_int keylen = 0, ivlen, blocksize, slen, klen, len, rounds, nkeys;
209 u_int check1, check2, m1len, m2len;
210 size_t authlen;
211 const Cipher *c;
212 Buffer b, encoded, copy, kdf;
213 CipherContext ctx;
214 Key *k = NULL;
215 int dlen, ret, i;
216
217 buffer_init(&b);
218 buffer_init(&kdf);
219 buffer_init(&encoded);
220 buffer_init(&copy);
221
222 /* uudecode */
223 m1len = sizeof(MARK_BEGIN) - 1;
224 m2len = sizeof(MARK_END) - 1;
225 cp = buffer_ptr(blob);
226 len = buffer_len(blob);
227 if (len < m1len || memcmp(cp, MARK_BEGIN, m1len)) {
228 debug("%s: missing begin marker", __func__);
229 goto out;
230 }
231 cp += m1len;
232 len -= m1len;
233 while (len) {
234 if (*cp != '\n' && *cp != '\r')
235 buffer_put_char(&encoded, *cp);
236 last = *cp;
237 len--;
238 cp++;
239 if (last == '\n') {
240 if (len >= m2len && !memcmp(cp, MARK_END, m2len)) {
241 buffer_put_char(&encoded, '\0');
242 break;
243 }
244 }
245 }
246 if (!len) {
247 debug("%s: no end marker", __func__);
248 goto out;
249 }
250 len = buffer_len(&encoded);
251 if ((cp = buffer_append_space(&copy, len)) == NULL) {
252 error("%s: buffer_append_space", __func__);
253 goto out;
254 }
255 if ((dlen = uudecode(buffer_ptr(&encoded), cp, len)) < 0) {
256 error("%s: uudecode failed", __func__);
257 goto out;
258 }
259 if ((u_int)dlen > len) {
260 error("%s: crazy uudecode length %d > %u", __func__, dlen, len);
261 goto out;
262 }
263 buffer_consume_end(&copy, len - dlen);
264 if (buffer_len(&copy) < sizeof(AUTH_MAGIC) ||
265 memcmp(buffer_ptr(&copy), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
266 error("%s: bad magic", __func__);
267 goto out;
268 }
269 buffer_consume(&copy, sizeof(AUTH_MAGIC));
270
271 ciphername = buffer_get_cstring_ret(&copy, NULL);
272 if (ciphername == NULL ||
273 (c = cipher_by_name(ciphername)) == NULL) {
274 error("%s: unknown cipher name", __func__);
275 goto out;
276 }
277 if ((passphrase == NULL || !strlen(passphrase)) &&
278 strcmp(ciphername, "none") != 0) {
279 /* passphrase required */
280 goto out;
281 }
282 kdfname = buffer_get_cstring_ret(&copy, NULL);
283 if (kdfname == NULL ||
284 (!strcmp(kdfname, "none") && !strcmp(kdfname, "bcrypt"))) {
285 error("%s: unknown kdf name", __func__);
286 goto out;
287 }
288 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
289 error("%s: cipher %s requires kdf", __func__, ciphername);
290 goto out;
291 }
292 /* kdf options */
293 kdfp = buffer_get_string_ptr_ret(&copy, &klen);
294 if (kdfp == NULL) {
295 error("%s: kdf options not set", __func__);
296 goto out;
297 }
298 if (klen > 0) {
299 if ((cp = buffer_append_space(&kdf, klen)) == NULL) {
300 error("%s: kdf alloc failed", __func__);
301 goto out;
302 }
303 memcpy(cp, kdfp, klen);
304 }
305 /* number of keys */
306 if (buffer_get_int_ret(&nkeys, &copy) < 0) {
307 error("%s: key counter missing", __func__);
308 goto out;
309 }
310 if (nkeys != 1) {
311 error("%s: only one key supported", __func__);
312 goto out;
313 }
314 /* pubkey */
315 if ((cp = buffer_get_string_ret(&copy, &len)) == NULL) {
316 error("%s: pubkey not found", __func__);
317 goto out;
318 }
319 free(cp); /* XXX check pubkey against decrypted private key */
320
321 /* size of encrypted key blob */
322 len = buffer_get_int(&copy);
323 blocksize = cipher_blocksize(c);
324 authlen = cipher_authlen(c);
325 if (len < blocksize) {
326 error("%s: encrypted data too small", __func__);
327 goto out;
328 }
329 if (len % blocksize) {
330 error("%s: length not multiple of blocksize", __func__);
331 goto out;
332 }
333
334 /* setup key */
335 keylen = cipher_keylen(c);
336 ivlen = cipher_ivlen(c);
337 key = xcalloc(1, keylen + ivlen);
338 if (!strcmp(kdfname, "bcrypt")) {
339 if ((salt = buffer_get_string_ret(&kdf, &slen)) == NULL) {
340 error("%s: salt not set", __func__);
341 goto out;
342 }
343 if (buffer_get_int_ret(&rounds, &kdf) < 0) {
344 error("%s: rounds not set", __func__);
345 goto out;
346 }
347 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
348 key, keylen + ivlen, rounds) < 0) {
349 error("%s: bcrypt_pbkdf failed", __func__);
350 goto out;
351 }
352 }
353
354 cp = buffer_append_space(&b, len);
355 cipher_init(&ctx, c, key, keylen, key + keylen, ivlen, 0);
356 ret = cipher_crypt(&ctx, 0, cp, buffer_ptr(&copy), len, 0, authlen);
357 cipher_cleanup(&ctx);
358 buffer_consume(&copy, len);
359
360 /* fail silently on decryption errors */
361 if (ret != 0) {
362 debug("%s: decrypt failed", __func__);
363 goto out;
364 }
365
366 if (buffer_len(&copy) != 0) {
367 error("%s: key blob has trailing data (len = %u)", __func__,
368 buffer_len(&copy));
369 goto out;
370 }
371
372 /* check bytes */
373 if (buffer_get_int_ret(&check1, &b) < 0 ||
374 buffer_get_int_ret(&check2, &b) < 0) {
375 error("check bytes missing");
376 goto out;
377 }
378 if (check1 != check2) {
379 debug("%s: decrypt failed: 0x%08x != 0x%08x", __func__,
380 check1, check2);
381 goto out;
382 }
383
384 k = key_private_deserialize(&b);
385
386 /* comment */
387 comment = buffer_get_cstring_ret(&b, NULL);
388
389 i = 0;
390 while (buffer_len(&b)) {
391 if (buffer_get_char_ret(&pad, &b) == -1 ||
392 pad != (++i & 0xff)) {
393 error("%s: bad padding", __func__);
394 key_free(k);
395 k = NULL;
396 goto out;
397 }
398 }
399
400 if (k && commentp) {
401 *commentp = comment;
402 comment = NULL;
403 }
404
405 /* XXX decode pubkey and check against private */
406 out:
407 free(ciphername);
408 free(kdfname);
409 free(salt);
410 free(comment);
411 if (key)
412 explicit_bzero(key, keylen + ivlen);
413 free(key);
414 buffer_free(&encoded);
415 buffer_free(&copy);
416 buffer_free(&kdf);
417 buffer_free(&b);
418 return k;
419}
420
421/*
422 * Serialises the authentication (private) key to a blob, encrypting it with
423 * passphrase. The identification of the blob (lowest 64 bits of n) will
424 * precede the key to provide identification of the key without needing a
425 * passphrase.
426 */
427static int
428key_private_rsa1_to_blob(Key *key, Buffer *blob, const char *passphrase,
429 const char *comment)
430{
431 Buffer buffer, encrypted;
432 u_char buf[100], *cp;
433 int i, cipher_num;
434 CipherContext ciphercontext;
435 const Cipher *cipher;
436 u_int32_t rnd;
437
438 /*
439 * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
440 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
441 */
442 cipher_num = (strcmp(passphrase, "") == 0) ?
443 SSH_CIPHER_NONE : SSH_AUTHFILE_CIPHER;
444 if ((cipher = cipher_by_number(cipher_num)) == NULL)
445 fatal("save_private_key_rsa: bad cipher");
446
447 /* This buffer is used to built the secret part of the private key. */
448 buffer_init(&buffer);
449
450 /* Put checkbytes for checking passphrase validity. */
451 rnd = arc4random();
452 buf[0] = rnd & 0xff;
453 buf[1] = (rnd >> 8) & 0xff;
454 buf[2] = buf[0];
455 buf[3] = buf[1];
456 buffer_append(&buffer, buf, 4);
457
458 /*
459 * Store the private key (n and e will not be stored because they
460 * will be stored in plain text, and storing them also in encrypted
461 * format would just give known plaintext).
462 */
463 buffer_put_bignum(&buffer, key->rsa->d);
464 buffer_put_bignum(&buffer, key->rsa->iqmp);
465 buffer_put_bignum(&buffer, key->rsa->q); /* reverse from SSL p */
466 buffer_put_bignum(&buffer, key->rsa->p); /* reverse from SSL q */
467
468 /* Pad the part to be encrypted until its size is a multiple of 8. */
469 while (buffer_len(&buffer) % 8 != 0)
470 buffer_put_char(&buffer, 0);
471
472 /* This buffer will be used to contain the data in the file. */
473 buffer_init(&encrypted);
474
475 /* First store keyfile id string. */
476 for (i = 0; authfile_id_string[i]; i++)
477 buffer_put_char(&encrypted, authfile_id_string[i]);
478 buffer_put_char(&encrypted, 0);
479
480 /* Store cipher type. */
481 buffer_put_char(&encrypted, cipher_num);
482 buffer_put_int(&encrypted, 0); /* For future extension */
483
484 /* Store public key. This will be in plain text. */
485 buffer_put_int(&encrypted, BN_num_bits(key->rsa->n));
486 buffer_put_bignum(&encrypted, key->rsa->n);
487 buffer_put_bignum(&encrypted, key->rsa->e);
488 buffer_put_cstring(&encrypted, comment);
489
490 /* Allocate space for the private part of the key in the buffer. */
491 cp = buffer_append_space(&encrypted, buffer_len(&buffer));
492
493 cipher_set_key_string(&ciphercontext, cipher, passphrase,
494 CIPHER_ENCRYPT);
495 if (cipher_crypt(&ciphercontext, 0, cp,
496 buffer_ptr(&buffer), buffer_len(&buffer), 0, 0) != 0)
497 fatal("%s: cipher_crypt failed", __func__);
498 cipher_cleanup(&ciphercontext);
499 explicit_bzero(&ciphercontext, sizeof(ciphercontext));
500
501 /* Destroy temporary data. */
502 explicit_bzero(buf, sizeof(buf));
503 buffer_free(&buffer);
504
505 buffer_append(blob, buffer_ptr(&encrypted), buffer_len(&encrypted));
506 buffer_free(&encrypted);
507
508 return 1;
509}
510
511/* convert SSH v2 key in OpenSSL PEM format */
512static int
513key_private_pem_to_blob(Key *key, Buffer *blob, const char *_passphrase,
514 const char *comment)
515{
516 int success = 0;
517 int blen, len = strlen(_passphrase);
518 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
519#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
520 const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
521#else
522 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
523#endif
524 const u_char *bptr;
525 BIO *bio;
526
527 if (len > 0 && len <= 4) {
528 error("passphrase too short: have %d bytes, need > 4", len);
529 return 0;
530 }
531 if ((bio = BIO_new(BIO_s_mem())) == NULL) {
532 error("%s: BIO_new failed", __func__);
533 return 0;
534 }
535 switch (key->type) {
536 case KEY_DSA:
537 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
538 cipher, passphrase, len, NULL, NULL);
539 break;
540#ifdef OPENSSL_HAS_ECC
541 case KEY_ECDSA:
542 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
543 cipher, passphrase, len, NULL, NULL);
544 break;
545#endif
546 case KEY_RSA:
547 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
548 cipher, passphrase, len, NULL, NULL);
549 break;
550 }
551 if (success) {
552 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0)
553 success = 0;
554 else
555 buffer_append(blob, bptr, blen);
556 }
557 BIO_free(bio);
558 return success;
559}
560
561/* Save a key blob to a file */ 54/* Save a key blob to a file */
562static int 55static int
563key_save_private_blob(Buffer *keybuf, const char *filename) 56sshkey_save_private_blob(struct sshbuf *keybuf, const char *filename)
564{ 57{
565 int fd; 58 int fd, oerrno;
566 59
567 if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0) { 60 if ((fd = open(filename, O_WRONLY | O_CREAT | O_TRUNC, 0600)) < 0)
568 error("open %s failed: %s.", filename, strerror(errno)); 61 return SSH_ERR_SYSTEM_ERROR;
569 return 0; 62 if (atomicio(vwrite, fd, (u_char *)sshbuf_ptr(keybuf),
570 } 63 sshbuf_len(keybuf)) != sshbuf_len(keybuf)) {
571 if (atomicio(vwrite, fd, buffer_ptr(keybuf), 64 oerrno = errno;
572 buffer_len(keybuf)) != buffer_len(keybuf)) {
573 error("write to key file %s failed: %s", filename,
574 strerror(errno));
575 close(fd); 65 close(fd);
576 unlink(filename); 66 unlink(filename);
577 return 0; 67 errno = oerrno;
68 return SSH_ERR_SYSTEM_ERROR;
578 } 69 }
579 close(fd); 70 close(fd);
580 return 1; 71 return 0;
581}
582
583/* Serialise "key" to buffer "blob" */
584static int
585key_private_to_blob(Key *key, Buffer *blob, const char *passphrase,
586 const char *comment, int force_new_format, const char *new_format_cipher,
587 int new_format_rounds)
588{
589 switch (key->type) {
590 case KEY_RSA1:
591 return key_private_rsa1_to_blob(key, blob, passphrase, comment);
592 case KEY_DSA:
593 case KEY_ECDSA:
594 case KEY_RSA:
595 if (force_new_format) {
596 return key_private_to_blob2(key, blob, passphrase,
597 comment, new_format_cipher, new_format_rounds);
598 }
599 return key_private_pem_to_blob(key, blob, passphrase, comment);
600 case KEY_ED25519:
601 return key_private_to_blob2(key, blob, passphrase,
602 comment, new_format_cipher, new_format_rounds);
603 default:
604 error("%s: cannot save key type %d", __func__, key->type);
605 return 0;
606 }
607} 72}
608 73
609int 74int
610key_save_private(Key *key, const char *filename, const char *passphrase, 75sshkey_save_private(struct sshkey *key, const char *filename,
611 const char *comment, int force_new_format, const char *new_format_cipher, 76 const char *passphrase, const char *comment,
612 int new_format_rounds) 77 int force_new_format, const char *new_format_cipher, int new_format_rounds)
613{ 78{
614 Buffer keyblob; 79 struct sshbuf *keyblob = NULL;
615 int success = 0; 80 int r;
616 81
617 buffer_init(&keyblob); 82 if ((keyblob = sshbuf_new()) == NULL)
618 if (!key_private_to_blob(key, &keyblob, passphrase, comment, 83 return SSH_ERR_ALLOC_FAIL;
619 force_new_format, new_format_cipher, new_format_rounds)) 84 if ((r = sshkey_private_to_fileblob(key, keyblob, passphrase, comment,
85 force_new_format, new_format_cipher, new_format_rounds)) != 0)
620 goto out; 86 goto out;
621 if (!key_save_private_blob(&keyblob, filename)) 87 if ((r = sshkey_save_private_blob(keyblob, filename)) != 0)
622 goto out; 88 goto out;
623 success = 1; 89 r = 0;
624 out: 90 out:
625 buffer_free(&keyblob); 91 sshbuf_free(keyblob);
626 return success; 92 return r;
627}
628
629/*
630 * Parse the public, unencrypted portion of a RSA1 key.
631 */
632static Key *
633key_parse_public_rsa1(Buffer *blob, char **commentp)
634{
635 Key *pub;
636 Buffer copy;
637
638 /* Check that it is at least big enough to contain the ID string. */
639 if (buffer_len(blob) < sizeof(authfile_id_string)) {
640 debug3("Truncated RSA1 identifier");
641 return NULL;
642 }
643
644 /*
645 * Make sure it begins with the id string. Consume the id string
646 * from the buffer.
647 */
648 if (memcmp(buffer_ptr(blob), authfile_id_string,
649 sizeof(authfile_id_string)) != 0) {
650 debug3("Incorrect RSA1 identifier");
651 return NULL;
652 }
653 buffer_init(&copy);
654 buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
655 buffer_consume(&copy, sizeof(authfile_id_string));
656
657 /* Skip cipher type and reserved data. */
658 (void) buffer_get_char(&copy); /* cipher type */
659 (void) buffer_get_int(&copy); /* reserved */
660
661 /* Read the public key from the buffer. */
662 (void) buffer_get_int(&copy);
663 pub = key_new(KEY_RSA1);
664 buffer_get_bignum(&copy, pub->rsa->n);
665 buffer_get_bignum(&copy, pub->rsa->e);
666 if (commentp)
667 *commentp = buffer_get_string(&copy, NULL);
668 /* The encrypted private part is not parsed by this function. */
669 buffer_free(&copy);
670
671 return pub;
672} 93}
673 94
674/* Load a key from a fd into a buffer */ 95/* Load a key from a fd into a buffer */
675int 96int
676key_load_file(int fd, const char *filename, Buffer *blob) 97sshkey_load_file(int fd, const char *filename, struct sshbuf *blob)
677{ 98{
678 u_char buf[1024]; 99 u_char buf[1024];
679 size_t len; 100 size_t len;
680 struct stat st; 101 struct stat st;
102 int r;
681 103
682 if (fstat(fd, &st) < 0) { 104 if (fstat(fd, &st) < 0)
683 error("%s: fstat of key file %.200s%sfailed: %.100s", __func__, 105 return SSH_ERR_SYSTEM_ERROR;
684 filename == NULL ? "" : filename,
685 filename == NULL ? "" : " ",
686 strerror(errno));
687 return 0;
688 }
689 if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && 106 if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
690 st.st_size > MAX_KEY_FILE_SIZE) { 107 st.st_size > MAX_KEY_FILE_SIZE)
691 toobig: 108 return SSH_ERR_INVALID_FORMAT;
692 error("%s: key file %.200s%stoo large", __func__,
693 filename == NULL ? "" : filename,
694 filename == NULL ? "" : " ");
695 return 0;
696 }
697 buffer_clear(blob);
698 for (;;) { 109 for (;;) {
699 if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) { 110 if ((len = atomicio(read, fd, buf, sizeof(buf))) == 0) {
700 if (errno == EPIPE) 111 if (errno == EPIPE)
701 break; 112 break;
702 debug("%s: read from key file %.200s%sfailed: %.100s", 113 r = SSH_ERR_SYSTEM_ERROR;
703 __func__, filename == NULL ? "" : filename, 114 goto out;
704 filename == NULL ? "" : " ", strerror(errno));
705 buffer_clear(blob);
706 explicit_bzero(buf, sizeof(buf));
707 return 0;
708 } 115 }
709 buffer_append(blob, buf, len); 116 if ((r = sshbuf_put(blob, buf, len)) != 0)
710 if (buffer_len(blob) > MAX_KEY_FILE_SIZE) { 117 goto out;
711 buffer_clear(blob); 118 if (sshbuf_len(blob) > MAX_KEY_FILE_SIZE) {
712 explicit_bzero(buf, sizeof(buf)); 119 r = SSH_ERR_INVALID_FORMAT;
713 goto toobig; 120 goto out;
714 } 121 }
715 } 122 }
716 explicit_bzero(buf, sizeof(buf));
717 if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 && 123 if ((st.st_mode & (S_IFSOCK|S_IFCHR|S_IFIFO)) == 0 &&
718 st.st_size != buffer_len(blob)) { 124 st.st_size != (off_t)sshbuf_len(blob)) {
719 debug("%s: key file %.200s%schanged size while reading", 125 r = SSH_ERR_FILE_CHANGED;
720 __func__, filename == NULL ? "" : filename, 126 goto out;
721 filename == NULL ? "" : " ");
722 buffer_clear(blob);
723 return 0;
724 } 127 }
128 r = 0;
725 129
726 return 1; 130 out:
131 explicit_bzero(buf, sizeof(buf));
132 if (r != 0)
133 sshbuf_reset(blob);
134 return r;
727} 135}
728 136
137#ifdef WITH_SSH1
729/* 138/*
730 * Loads the public part of the ssh v1 key file. Returns NULL if an error was 139 * Loads the public part of the ssh v1 key file. Returns NULL if an error was
731 * encountered (the file does not exist or is not readable), and the key 140 * encountered (the file does not exist or is not readable), and the key
732 * otherwise. 141 * otherwise.
733 */ 142 */
734static Key * 143static int
735key_load_public_rsa1(int fd, const char *filename, char **commentp) 144sshkey_load_public_rsa1(int fd, const char *filename,
145 struct sshkey **keyp, char **commentp)
736{ 146{
737 Buffer buffer; 147 struct sshbuf *b = NULL;
738 Key *pub; 148 int r;
739
740 buffer_init(&buffer);
741 if (!key_load_file(fd, filename, &buffer)) {
742 buffer_free(&buffer);
743 return NULL;
744 }
745 149
746 pub = key_parse_public_rsa1(&buffer, commentp); 150 *keyp = NULL;
747 if (pub == NULL) 151 if (commentp != NULL)
748 debug3("Could not load \"%s\" as a RSA1 public key", filename); 152 *commentp = NULL;
749 buffer_free(&buffer);
750 return pub;
751}
752
753/* load public key from private-key file, works only for SSH v1 */
754Key *
755key_load_public_type(int type, const char *filename, char **commentp)
756{
757 Key *pub;
758 int fd;
759 153
760 if (type == KEY_RSA1) { 154 if ((b = sshbuf_new()) == NULL)
761 fd = open(filename, O_RDONLY); 155 return SSH_ERR_ALLOC_FAIL;
762 if (fd < 0) 156 if ((r = sshkey_load_file(fd, filename, b)) != 0)
763 return NULL; 157 goto out;
764 pub = key_load_public_rsa1(fd, filename, commentp); 158 if ((r = sshkey_parse_public_rsa1_fileblob(b, keyp, commentp)) != 0)
765 close(fd); 159 goto out;
766 return pub; 160 r = 0;
767 } 161 out:
768 return NULL; 162 sshbuf_free(b);
163 return r;
769} 164}
165#endif /* WITH_SSH1 */
770 166
771static Key * 167#ifdef WITH_OPENSSL
772key_parse_private_rsa1(Buffer *blob, const char *passphrase, char **commentp) 168/* XXX Deprecate? */
169int
170sshkey_load_private_pem(int fd, int type, const char *passphrase,
171 struct sshkey **keyp, char **commentp)
773{ 172{
774 int check1, check2, cipher_type; 173 struct sshbuf *buffer = NULL;
775 Buffer decrypted; 174 int r;
776 u_char *cp;
777 CipherContext ciphercontext;
778 const Cipher *cipher;
779 Key *prv = NULL;
780 Buffer copy;
781
782 /* Check that it is at least big enough to contain the ID string. */
783 if (buffer_len(blob) < sizeof(authfile_id_string)) {
784 debug3("Truncated RSA1 identifier");
785 return NULL;
786 }
787
788 /*
789 * Make sure it begins with the id string. Consume the id string
790 * from the buffer.
791 */
792 if (memcmp(buffer_ptr(blob), authfile_id_string,
793 sizeof(authfile_id_string)) != 0) {
794 debug3("Incorrect RSA1 identifier");
795 return NULL;
796 }
797 buffer_init(&copy);
798 buffer_append(&copy, buffer_ptr(blob), buffer_len(blob));
799 buffer_consume(&copy, sizeof(authfile_id_string));
800
801 /* Read cipher type. */
802 cipher_type = buffer_get_char(&copy);
803 (void) buffer_get_int(&copy); /* Reserved data. */
804
805 /* Read the public key from the buffer. */
806 (void) buffer_get_int(&copy);
807 prv = key_new_private(KEY_RSA1);
808
809 buffer_get_bignum(&copy, prv->rsa->n);
810 buffer_get_bignum(&copy, prv->rsa->e);
811 if (commentp)
812 *commentp = buffer_get_string(&copy, NULL);
813 else
814 (void)buffer_get_string_ptr(&copy, NULL);
815 175
816 /* Check that it is a supported cipher. */ 176 *keyp = NULL;
817 cipher = cipher_by_number(cipher_type);
818 if (cipher == NULL) {
819 debug("Unsupported RSA1 cipher %d", cipher_type);
820 buffer_free(&copy);
821 goto fail;
822 }
823 /* Initialize space for decrypted data. */
824 buffer_init(&decrypted);
825 cp = buffer_append_space(&decrypted, buffer_len(&copy));
826
827 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
828 cipher_set_key_string(&ciphercontext, cipher, passphrase,
829 CIPHER_DECRYPT);
830 if (cipher_crypt(&ciphercontext, 0, cp,
831 buffer_ptr(&copy), buffer_len(&copy), 0, 0) != 0)
832 fatal("%s: cipher_crypt failed", __func__);
833 cipher_cleanup(&ciphercontext);
834 explicit_bzero(&ciphercontext, sizeof(ciphercontext));
835 buffer_free(&copy);
836
837 check1 = buffer_get_char(&decrypted);
838 check2 = buffer_get_char(&decrypted);
839 if (check1 != buffer_get_char(&decrypted) ||
840 check2 != buffer_get_char(&decrypted)) {
841 if (strcmp(passphrase, "") != 0)
842 debug("Bad passphrase supplied for RSA1 key");
843 /* Bad passphrase. */
844 buffer_free(&decrypted);
845 goto fail;
846 }
847 /* Read the rest of the private key. */
848 buffer_get_bignum(&decrypted, prv->rsa->d);
849 buffer_get_bignum(&decrypted, prv->rsa->iqmp); /* u */
850 /* in SSL and SSH v1 p and q are exchanged */
851 buffer_get_bignum(&decrypted, prv->rsa->q); /* p */
852 buffer_get_bignum(&decrypted, prv->rsa->p); /* q */
853
854 /* calculate p-1 and q-1 */
855 rsa_generate_additional_parameters(prv->rsa);
856
857 buffer_free(&decrypted);
858
859 /* enable blinding */
860 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
861 error("%s: RSA_blinding_on failed", __func__);
862 goto fail;
863 }
864 return prv;
865
866fail:
867 if (commentp != NULL) 177 if (commentp != NULL)
868 free(*commentp); 178 *commentp = NULL;
869 key_free(prv);
870 return NULL;
871}
872
873static Key *
874key_parse_private_pem(Buffer *blob, int type, const char *passphrase,
875 char **commentp)
876{
877 EVP_PKEY *pk = NULL;
878 Key *prv = NULL;
879 char *name = "<no key>";
880 BIO *bio;
881 179
882 if ((bio = BIO_new_mem_buf(buffer_ptr(blob), 180 if ((buffer = sshbuf_new()) == NULL)
883 buffer_len(blob))) == NULL) { 181 return SSH_ERR_ALLOC_FAIL;
884 error("%s: BIO_new_mem_buf failed", __func__); 182 if ((r = sshkey_load_file(fd, NULL, buffer)) != 0)
885 return NULL; 183 goto out;
886 } 184 if ((r = sshkey_parse_private_pem_fileblob(buffer, type, passphrase,
887 185 keyp, commentp)) != 0)
888 pk = PEM_read_bio_PrivateKey(bio, NULL, NULL, (char *)passphrase); 186 goto out;
889 BIO_free(bio); 187 r = 0;
890 if (pk == NULL) { 188 out:
891 debug("%s: PEM_read_PrivateKey failed", __func__); 189 sshbuf_free(buffer);
892 (void)ERR_get_error(); 190 return r;
893 } else if (pk->type == EVP_PKEY_RSA &&
894 (type == KEY_UNSPEC||type==KEY_RSA)) {
895 prv = key_new(KEY_UNSPEC);
896 prv->rsa = EVP_PKEY_get1_RSA(pk);
897 prv->type = KEY_RSA;
898 name = "rsa w/o comment";
899#ifdef DEBUG_PK
900 RSA_print_fp(stderr, prv->rsa, 8);
901#endif
902 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
903 error("%s: RSA_blinding_on failed", __func__);
904 key_free(prv);
905 prv = NULL;
906 }
907 } else if (pk->type == EVP_PKEY_DSA &&
908 (type == KEY_UNSPEC||type==KEY_DSA)) {
909 prv = key_new(KEY_UNSPEC);
910 prv->dsa = EVP_PKEY_get1_DSA(pk);
911 prv->type = KEY_DSA;
912 name = "dsa w/o comment";
913#ifdef DEBUG_PK
914 DSA_print_fp(stderr, prv->dsa, 8);
915#endif
916#ifdef OPENSSL_HAS_ECC
917 } else if (pk->type == EVP_PKEY_EC &&
918 (type == KEY_UNSPEC||type==KEY_ECDSA)) {
919 prv = key_new(KEY_UNSPEC);
920 prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
921 prv->type = KEY_ECDSA;
922 if ((prv->ecdsa_nid = key_ecdsa_key_to_nid(prv->ecdsa)) == -1 ||
923 key_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
924 key_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
925 EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
926 key_ec_validate_private(prv->ecdsa) != 0) {
927 error("%s: bad ECDSA key", __func__);
928 key_free(prv);
929 prv = NULL;
930 }
931 name = "ecdsa w/o comment";
932#ifdef DEBUG_PK
933 if (prv != NULL && prv->ecdsa != NULL)
934 key_dump_ec_key(prv->ecdsa);
935#endif
936#endif /* OPENSSL_HAS_ECC */
937 } else {
938 error("%s: PEM_read_PrivateKey: mismatch or "
939 "unknown EVP_PKEY save_type %d", __func__, pk->save_type);
940 }
941 if (pk != NULL)
942 EVP_PKEY_free(pk);
943 if (prv != NULL && commentp)
944 *commentp = xstrdup(name);
945 debug("read PEM private key done: type %s",
946 prv ? key_type(prv) : "<unknown>");
947 return prv;
948}
949
950Key *
951key_load_private_pem(int fd, int type, const char *passphrase,
952 char **commentp)
953{
954 Buffer buffer;
955 Key *prv;
956
957 buffer_init(&buffer);
958 if (!key_load_file(fd, NULL, &buffer)) {
959 buffer_free(&buffer);
960 return NULL;
961 }
962 prv = key_parse_private_pem(&buffer, type, passphrase, commentp);
963 buffer_free(&buffer);
964 return prv;
965} 191}
192#endif /* WITH_OPENSSL */
966 193
194/* XXX remove error() calls from here? */
967int 195int
968key_perm_ok(int fd, const char *filename) 196sshkey_perm_ok(int fd, const char *filename)
969{ 197{
970 struct stat st; 198 struct stat st;
971 199
972 if (fstat(fd, &st) < 0) 200 if (fstat(fd, &st) < 0)
973 return 0; 201 return SSH_ERR_SYSTEM_ERROR;
974 /* 202 /*
975 * if a key owned by the user is accessed, then we check the 203 * if a key owned by the user is accessed, then we check the
976 * permissions of the file. if the key owned by a different user, 204 * permissions of the file. if the key owned by a different user,
@@ -985,298 +213,311 @@ key_perm_ok(int fd, const char *filename)
985 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@"); 213 error("@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@");
986 error("Permissions 0%3.3o for '%s' are too open.", 214 error("Permissions 0%3.3o for '%s' are too open.",
987 (u_int)st.st_mode & 0777, filename); 215 (u_int)st.st_mode & 0777, filename);
988 error("It is required that your private key files are NOT accessible by others."); 216 error("It is recommended that your private key files are NOT accessible by others.");
989 error("This private key will be ignored."); 217 error("This private key will be ignored.");
990 return 0; 218 return SSH_ERR_KEY_BAD_PERMISSIONS;
991 } 219 }
992 return 1; 220 return 0;
993} 221}
994 222
995static Key * 223/* XXX kill perm_ok now that we have SSH_ERR_KEY_BAD_PERMISSIONS? */
996key_parse_private_type(Buffer *blob, int type, const char *passphrase, 224int
997 char **commentp) 225sshkey_load_private_type(int type, const char *filename, const char *passphrase,
226 struct sshkey **keyp, char **commentp, int *perm_ok)
998{ 227{
999 Key *k; 228 int fd, r;
229 struct sshbuf *buffer = NULL;
1000 230
1001 switch (type) { 231 *keyp = NULL;
1002 case KEY_RSA1: 232 if (commentp != NULL)
1003 return key_parse_private_rsa1(blob, passphrase, commentp); 233 *commentp = NULL;
1004 case KEY_DSA:
1005 case KEY_ECDSA:
1006 case KEY_RSA:
1007 return key_parse_private_pem(blob, type, passphrase, commentp);
1008 case KEY_ED25519:
1009 return key_parse_private2(blob, type, passphrase, commentp);
1010 case KEY_UNSPEC:
1011 if ((k = key_parse_private2(blob, type, passphrase, commentp)))
1012 return k;
1013 return key_parse_private_pem(blob, type, passphrase, commentp);
1014 default:
1015 error("%s: cannot parse key type %d", __func__, type);
1016 break;
1017 }
1018 return NULL;
1019}
1020
1021Key *
1022key_load_private_type(int type, const char *filename, const char *passphrase,
1023 char **commentp, int *perm_ok)
1024{
1025 int fd;
1026 Key *ret;
1027 Buffer buffer;
1028 234
1029 fd = open(filename, O_RDONLY); 235 if ((fd = open(filename, O_RDONLY)) < 0) {
1030 if (fd < 0) {
1031 debug("could not open key file '%s': %s", filename,
1032 strerror(errno));
1033 if (perm_ok != NULL) 236 if (perm_ok != NULL)
1034 *perm_ok = 0; 237 *perm_ok = 0;
1035 return NULL; 238 return SSH_ERR_SYSTEM_ERROR;
1036 } 239 }
1037 if (!key_perm_ok(fd, filename)) { 240 if (sshkey_perm_ok(fd, filename) != 0) {
1038 if (perm_ok != NULL) 241 if (perm_ok != NULL)
1039 *perm_ok = 0; 242 *perm_ok = 0;
1040 error("bad permissions: ignore key: %s", filename); 243 r = SSH_ERR_KEY_BAD_PERMISSIONS;
1041 close(fd); 244 goto out;
1042 return NULL;
1043 } 245 }
1044 if (perm_ok != NULL) 246 if (perm_ok != NULL)
1045 *perm_ok = 1; 247 *perm_ok = 1;
1046 248
1047 buffer_init(&buffer); 249 if ((buffer = sshbuf_new()) == NULL) {
1048 if (!key_load_file(fd, filename, &buffer)) { 250 r = SSH_ERR_ALLOC_FAIL;
1049 buffer_free(&buffer); 251 goto out;
1050 close(fd);
1051 return NULL;
1052 } 252 }
253 if ((r = sshkey_load_file(fd, filename, buffer)) != 0)
254 goto out;
255 if ((r = sshkey_parse_private_fileblob_type(buffer, type, passphrase,
256 keyp, commentp)) != 0)
257 goto out;
258 r = 0;
259 out:
1053 close(fd); 260 close(fd);
1054 ret = key_parse_private_type(&buffer, type, passphrase, commentp); 261 if (buffer != NULL)
1055 buffer_free(&buffer); 262 sshbuf_free(buffer);
1056 return ret; 263 return r;
1057} 264}
1058 265
1059Key * 266/* XXX this is almost identical to sshkey_load_private_type() */
1060key_parse_private(Buffer *buffer, const char *filename, 267int
1061 const char *passphrase, char **commentp) 268sshkey_load_private(const char *filename, const char *passphrase,
269 struct sshkey **keyp, char **commentp)
1062{ 270{
1063 Key *pub, *prv; 271 struct sshbuf *buffer = NULL;
1064 272 int r, fd;
1065 /* it's a SSH v1 key if the public key part is readable */
1066 pub = key_parse_public_rsa1(buffer, commentp);
1067 if (pub == NULL) {
1068 prv = key_parse_private_type(buffer, KEY_UNSPEC,
1069 passphrase, NULL);
1070 /* use the filename as a comment for PEM */
1071 if (commentp && prv)
1072 *commentp = xstrdup(filename);
1073 } else {
1074 key_free(pub);
1075 /* key_parse_public_rsa1() has already loaded the comment */
1076 prv = key_parse_private_type(buffer, KEY_RSA1, passphrase,
1077 NULL);
1078 }
1079 return prv;
1080}
1081 273
1082Key * 274 *keyp = NULL;
1083key_load_private(const char *filename, const char *passphrase, 275 if (commentp != NULL)
1084 char **commentp) 276 *commentp = NULL;
1085{
1086 Key *prv;
1087 Buffer buffer;
1088 int fd;
1089 277
1090 fd = open(filename, O_RDONLY); 278 if ((fd = open(filename, O_RDONLY)) < 0)
1091 if (fd < 0) { 279 return SSH_ERR_SYSTEM_ERROR;
1092 debug("could not open key file '%s': %s", filename, 280 if (sshkey_perm_ok(fd, filename) != 0) {
1093 strerror(errno)); 281 r = SSH_ERR_KEY_BAD_PERMISSIONS;
1094 return NULL; 282 goto out;
1095 }
1096 if (!key_perm_ok(fd, filename)) {
1097 error("bad permissions: ignore key: %s", filename);
1098 close(fd);
1099 return NULL;
1100 } 283 }
1101 284
1102 buffer_init(&buffer); 285 if ((buffer = sshbuf_new()) == NULL) {
1103 if (!key_load_file(fd, filename, &buffer)) { 286 r = SSH_ERR_ALLOC_FAIL;
1104 buffer_free(&buffer); 287 goto out;
1105 close(fd);
1106 return NULL;
1107 } 288 }
289 if ((r = sshkey_load_file(fd, filename, buffer)) != 0 ||
290 (r = sshkey_parse_private_fileblob(buffer, passphrase, filename,
291 keyp, commentp)) != 0)
292 goto out;
293 r = 0;
294 out:
1108 close(fd); 295 close(fd);
1109 296 if (buffer != NULL)
1110 prv = key_parse_private(&buffer, filename, passphrase, commentp); 297 sshbuf_free(buffer);
1111 buffer_free(&buffer); 298 return r;
1112 return prv;
1113} 299}
1114 300
1115static int 301static int
1116key_try_load_public(Key *k, const char *filename, char **commentp) 302sshkey_try_load_public(struct sshkey *k, const char *filename, char **commentp)
1117{ 303{
1118 FILE *f; 304 FILE *f;
1119 char line[SSH_MAX_PUBKEY_BYTES]; 305 char line[SSH_MAX_PUBKEY_BYTES];
1120 char *cp; 306 char *cp;
1121 u_long linenum = 0; 307 u_long linenum = 0;
308 int r;
1122 309
1123 f = fopen(filename, "r"); 310 if (commentp != NULL)
1124 if (f != NULL) { 311 *commentp = NULL;
1125 while (read_keyfile_line(f, filename, line, sizeof(line), 312 if ((f = fopen(filename, "r")) == NULL)
1126 &linenum) != -1) { 313 return SSH_ERR_SYSTEM_ERROR;
1127 cp = line; 314 while (read_keyfile_line(f, filename, line, sizeof(line),
1128 switch (*cp) { 315 &linenum) != -1) {
1129 case '#': 316 cp = line;
1130 case '\n': 317 switch (*cp) {
1131 case '\0': 318 case '#':
1132 continue; 319 case '\n':
1133 } 320 case '\0':
1134 /* Abort loading if this looks like a private key */ 321 continue;
1135 if (strncmp(cp, "-----BEGIN", 10) == 0) 322 }
1136 break; 323 /* Abort loading if this looks like a private key */
1137 /* Skip leading whitespace. */ 324 if (strncmp(cp, "-----BEGIN", 10) == 0 ||
1138 for (; *cp && (*cp == ' ' || *cp == '\t'); cp++) 325 strcmp(cp, "SSH PRIVATE KEY FILE") == 0)
1139 ; 326 break;
1140 if (*cp) { 327 /* Skip leading whitespace. */
1141 if (key_read(k, &cp) == 1) { 328 for (; *cp && (*cp == ' ' || *cp == '\t'); cp++)
1142 cp[strcspn(cp, "\r\n")] = '\0'; 329 ;
1143 if (commentp) { 330 if (*cp) {
1144 *commentp = xstrdup(*cp ? 331 if ((r = sshkey_read(k, &cp)) == 0) {
1145 cp : filename); 332 cp[strcspn(cp, "\r\n")] = '\0';
1146 } 333 if (commentp) {
1147 fclose(f); 334 *commentp = strdup(*cp ?
1148 return 1; 335 cp : filename);
336 if (*commentp == NULL)
337 r = SSH_ERR_ALLOC_FAIL;
1149 } 338 }
339 fclose(f);
340 return r;
1150 } 341 }
1151 } 342 }
1152 fclose(f);
1153 } 343 }
1154 return 0; 344 fclose(f);
345 return SSH_ERR_INVALID_FORMAT;
1155} 346}
1156 347
1157/* load public key from ssh v1 private or any pubkey file */ 348/* load public key from ssh v1 private or any pubkey file */
1158Key * 349int
1159key_load_public(const char *filename, char **commentp) 350sshkey_load_public(const char *filename, struct sshkey **keyp, char **commentp)
1160{ 351{
1161 Key *pub; 352 struct sshkey *pub = NULL;
1162 char file[MAXPATHLEN]; 353 char file[MAXPATHLEN];
354 int r, fd;
355
356 if (keyp != NULL)
357 *keyp = NULL;
358 if (commentp != NULL)
359 *commentp = NULL;
1163 360
361 if ((fd = open(filename, O_RDONLY)) < 0)
362 goto skip;
363#ifdef WITH_SSH1
1164 /* try rsa1 private key */ 364 /* try rsa1 private key */
1165 pub = key_load_public_type(KEY_RSA1, filename, commentp); 365 r = sshkey_load_public_rsa1(fd, filename, keyp, commentp);
1166 if (pub != NULL) 366 close(fd);
1167 return pub; 367 switch (r) {
368 case SSH_ERR_INTERNAL_ERROR:
369 case SSH_ERR_ALLOC_FAIL:
370 case SSH_ERR_INVALID_ARGUMENT:
371 case SSH_ERR_SYSTEM_ERROR:
372 case 0:
373 return r;
374 }
375#endif /* WITH_SSH1 */
1168 376
377 /* try ssh2 public key */
378 if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
379 return SSH_ERR_ALLOC_FAIL;
380 if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
381 if (keyp != NULL)
382 *keyp = pub;
383 return 0;
384 }
385 sshkey_free(pub);
386
387#ifdef WITH_SSH1
1169 /* try rsa1 public key */ 388 /* try rsa1 public key */
1170 pub = key_new(KEY_RSA1); 389 if ((pub = sshkey_new(KEY_RSA1)) == NULL)
1171 if (key_try_load_public(pub, filename, commentp) == 1) 390 return SSH_ERR_ALLOC_FAIL;
1172 return pub; 391 if ((r = sshkey_try_load_public(pub, filename, commentp)) == 0) {
1173 key_free(pub); 392 if (keyp != NULL)
393 *keyp = pub;
394 return 0;
395 }
396 sshkey_free(pub);
397#endif /* WITH_SSH1 */
1174 398
1175 /* try ssh2 public key */ 399 skip:
1176 pub = key_new(KEY_UNSPEC); 400 /* try .pub suffix */
1177 if (key_try_load_public(pub, filename, commentp) == 1) 401 if ((pub = sshkey_new(KEY_UNSPEC)) == NULL)
1178 return pub; 402 return SSH_ERR_ALLOC_FAIL;
403 r = SSH_ERR_ALLOC_FAIL; /* in case strlcpy or strlcat fail */
1179 if ((strlcpy(file, filename, sizeof file) < sizeof(file)) && 404 if ((strlcpy(file, filename, sizeof file) < sizeof(file)) &&
1180 (strlcat(file, ".pub", sizeof file) < sizeof(file)) && 405 (strlcat(file, ".pub", sizeof file) < sizeof(file)) &&
1181 (key_try_load_public(pub, file, commentp) == 1)) 406 (r = sshkey_try_load_public(pub, file, commentp)) == 0) {
1182 return pub; 407 if (keyp != NULL)
1183 key_free(pub); 408 *keyp = pub;
1184 return NULL; 409 return 0;
410 }
411 sshkey_free(pub);
412 return r;
1185} 413}
1186 414
1187/* Load the certificate associated with the named private key */ 415/* Load the certificate associated with the named private key */
1188Key * 416int
1189key_load_cert(const char *filename) 417sshkey_load_cert(const char *filename, struct sshkey **keyp)
1190{ 418{
1191 Key *pub; 419 struct sshkey *pub = NULL;
1192 char *file; 420 char *file = NULL;
421 int r = SSH_ERR_INTERNAL_ERROR;
1193 422
1194 pub = key_new(KEY_UNSPEC); 423 *keyp = NULL;
1195 xasprintf(&file, "%s-cert.pub", filename); 424
1196 if (key_try_load_public(pub, file, NULL) == 1) { 425 if (asprintf(&file, "%s-cert.pub", filename) == -1)
1197 free(file); 426 return SSH_ERR_ALLOC_FAIL;
1198 return pub; 427
428 if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
429 goto out;
1199 } 430 }
1200 free(file); 431 if ((r = sshkey_try_load_public(pub, file, NULL)) != 0)
1201 key_free(pub); 432 goto out;
1202 return NULL; 433
434 *keyp = pub;
435 pub = NULL;
436 r = 0;
437
438 out:
439 if (file != NULL)
440 free(file);
441 if (pub != NULL)
442 sshkey_free(pub);
443 return r;
1203} 444}
1204 445
1205/* Load private key and certificate */ 446/* Load private key and certificate */
1206Key * 447int
1207key_load_private_cert(int type, const char *filename, const char *passphrase, 448sshkey_load_private_cert(int type, const char *filename, const char *passphrase,
1208 int *perm_ok) 449 struct sshkey **keyp, int *perm_ok)
1209{ 450{
1210 Key *key, *pub; 451 struct sshkey *key = NULL, *cert = NULL;
452 int r;
453
454 *keyp = NULL;
1211 455
1212 switch (type) { 456 switch (type) {
457#ifdef WITH_OPENSSL
1213 case KEY_RSA: 458 case KEY_RSA:
1214 case KEY_DSA: 459 case KEY_DSA:
1215 case KEY_ECDSA: 460 case KEY_ECDSA:
1216 case KEY_ED25519: 461 case KEY_ED25519:
462#endif /* WITH_OPENSSL */
463 case KEY_UNSPEC:
1217 break; 464 break;
1218 default: 465 default:
1219 error("%s: unsupported key type", __func__); 466 return SSH_ERR_KEY_TYPE_UNKNOWN;
1220 return NULL;
1221 } 467 }
1222 468
1223 if ((key = key_load_private_type(type, filename, 469 if ((r = sshkey_load_private_type(type, filename,
1224 passphrase, NULL, perm_ok)) == NULL) 470 passphrase, &key, NULL, perm_ok)) != 0 ||
1225 return NULL; 471 (r = sshkey_load_cert(filename, &cert)) != 0)
1226 472 goto out;
1227 if ((pub = key_load_cert(filename)) == NULL) {
1228 key_free(key);
1229 return NULL;
1230 }
1231 473
1232 /* Make sure the private key matches the certificate */ 474 /* Make sure the private key matches the certificate */
1233 if (key_equal_public(key, pub) == 0) { 475 if (sshkey_equal_public(key, cert) == 0) {
1234 error("%s: certificate does not match private key %s", 476 r = SSH_ERR_KEY_CERT_MISMATCH;
1235 __func__, filename); 477 goto out;
1236 } else if (key_to_certified(key, key_cert_is_legacy(pub)) != 0) {
1237 error("%s: key_to_certified failed", __func__);
1238 } else {
1239 key_cert_copy(pub, key);
1240 key_free(pub);
1241 return key;
1242 } 478 }
1243 479
1244 key_free(key); 480 if ((r = sshkey_to_certified(key, sshkey_cert_is_legacy(cert))) != 0 ||
1245 key_free(pub); 481 (r = sshkey_cert_copy(cert, key)) != 0)
1246 return NULL; 482 goto out;
483 r = 0;
484 *keyp = key;
485 key = NULL;
486 out:
487 if (key != NULL)
488 sshkey_free(key);
489 if (cert != NULL)
490 sshkey_free(cert);
491 return r;
1247} 492}
1248 493
1249/* 494/*
1250 * Returns 1 if the specified "key" is listed in the file "filename", 495 * Returns success if the specified "key" is listed in the file "filename",
1251 * 0 if the key is not listed or -1 on error. 496 * SSH_ERR_KEY_NOT_FOUND: if the key is not listed or another error.
1252 * If strict_type is set then the key type must match exactly, 497 * If strict_type is set then the key type must match exactly,
1253 * otherwise a comparison that ignores certficiate data is performed. 498 * otherwise a comparison that ignores certficiate data is performed.
1254 */ 499 */
1255int 500int
1256key_in_file(Key *key, const char *filename, int strict_type) 501sshkey_in_file(struct sshkey *key, const char *filename, int strict_type)
1257{ 502{
1258 FILE *f; 503 FILE *f;
1259 char line[SSH_MAX_PUBKEY_BYTES]; 504 char line[SSH_MAX_PUBKEY_BYTES];
1260 char *cp; 505 char *cp;
1261 u_long linenum = 0; 506 u_long linenum = 0;
1262 int ret = 0; 507 int r = 0;
1263 Key *pub; 508 struct sshkey *pub = NULL;
1264 int (*key_compare)(const Key *, const Key *) = strict_type ? 509 int (*sshkey_compare)(const struct sshkey *, const struct sshkey *) =
1265 key_equal : key_equal_public; 510 strict_type ? sshkey_equal : sshkey_equal_public;
1266 511
1267 if ((f = fopen(filename, "r")) == NULL) { 512 if ((f = fopen(filename, "r")) == NULL) {
1268 if (errno == ENOENT) { 513 if (errno == ENOENT)
1269 debug("%s: keyfile \"%s\" missing", __func__, filename); 514 return SSH_ERR_KEY_NOT_FOUND;
1270 return 0; 515 else
1271 } else { 516 return SSH_ERR_SYSTEM_ERROR;
1272 error("%s: could not open keyfile \"%s\": %s", __func__,
1273 filename, strerror(errno));
1274 return -1;
1275 }
1276 } 517 }
1277 518
1278 while (read_keyfile_line(f, filename, line, sizeof(line), 519 while (read_keyfile_line(f, filename, line, sizeof(line),
1279 &linenum) != -1) { 520 &linenum) != -1) {
1280 cp = line; 521 cp = line;
1281 522
1282 /* Skip leading whitespace. */ 523 /* Skip leading whitespace. */
@@ -1291,18 +532,24 @@ key_in_file(Key *key, const char *filename, int strict_type)
1291 continue; 532 continue;
1292 } 533 }
1293 534
1294 pub = key_new(KEY_UNSPEC); 535 if ((pub = sshkey_new(KEY_UNSPEC)) == NULL) {
1295 if (key_read(pub, &cp) != 1) { 536 r = SSH_ERR_ALLOC_FAIL;
1296 key_free(pub); 537 goto out;
1297 continue;
1298 } 538 }
1299 if (key_compare(key, pub)) { 539 if ((r = sshkey_read(pub, &cp)) != 0)
1300 ret = 1; 540 goto out;
1301 key_free(pub); 541 if (sshkey_compare(key, pub)) {
1302 break; 542 r = 0;
543 goto out;
1303 } 544 }
1304 key_free(pub); 545 sshkey_free(pub);
546 pub = NULL;
1305 } 547 }
548 r = SSH_ERR_KEY_NOT_FOUND;
549 out:
550 if (pub != NULL)
551 sshkey_free(pub);
1306 fclose(f); 552 fclose(f);
1307 return ret; 553 return r;
1308} 554}
555
diff --git a/authfile.h b/authfile.h
index 8ba1c2dbe..03bc3958c 100644
--- a/authfile.h
+++ b/authfile.h
@@ -1,32 +1,47 @@
1/* $OpenBSD: authfile.h,v 1.17 2013/12/06 13:34:54 markus Exp $ */ 1/* $OpenBSD: authfile.h,v 1.19 2014/07/03 23:18:35 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 2000, 2013 Markus Friedl. All rights reserved.
5 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * All rights reserved
7 * 5 *
8 * As far as I am concerned, the code I have written for this software 6 * Redistribution and use in source and binary forms, with or without
9 * can be used freely for any purpose. Any derived versions of this 7 * modification, are permitted provided that the following conditions
10 * software must be clearly marked as such, and if the derived work is 8 * are met:
11 * incompatible with the protocol description in the RFC file, it must be 9 * 1. Redistributions of source code must retain the above copyright
12 * called by a name other than "ssh" or "Secure Shell". 10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
13 */ 25 */
14 26
15#ifndef AUTHFILE_H 27#ifndef AUTHFILE_H
16#define AUTHFILE_H 28#define AUTHFILE_H
17 29
18int key_save_private(Key *, const char *, const char *, const char *, 30struct sshbuf;
19 int, const char *, int); 31struct sshkey;
20int key_load_file(int, const char *, Buffer *); 32
21Key *key_load_cert(const char *); 33int sshkey_save_private(struct sshkey *, const char *,
22Key *key_load_public(const char *, char **); 34 const char *, const char *, int, const char *, int);
23Key *key_load_public_type(int, const char *, char **); 35int sshkey_load_file(int, const char *, struct sshbuf *);
24Key *key_parse_private(Buffer *, const char *, const char *, char **); 36int sshkey_load_cert(const char *, struct sshkey **);
25Key *key_load_private(const char *, const char *, char **); 37int sshkey_load_public(const char *, struct sshkey **, char **);
26Key *key_load_private_cert(int, const char *, const char *, int *); 38int sshkey_load_private(const char *, const char *, struct sshkey **, char **);
27Key *key_load_private_type(int, const char *, const char *, char **, int *); 39int sshkey_load_private_cert(int, const char *, const char *,
28Key *key_load_private_pem(int, int, const char *, char **); 40 struct sshkey **, int *);
29int key_perm_ok(int, const char *); 41int sshkey_load_private_type(int, const char *, const char *,
30int key_in_file(Key *, const char *, int); 42 struct sshkey **, char **, int *);
43int sshkey_load_private_pem(int, int, const char *, struct sshkey **, char **);
44int sshkey_perm_ok(int, const char *);
45int sshkey_in_file(struct sshkey *, const char *, int);
31 46
32#endif 47#endif
diff --git a/bufaux.c b/bufaux.c
index f6a6f2ab2..3976896a9 100644
--- a/bufaux.c
+++ b/bufaux.c
@@ -1,70 +1,40 @@
1/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */ 1/* $OpenBSD: bufaux.c,v 1.60 2014/04/30 05:29:56 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * Auxiliary functions for storing and retrieving various data types to/from
7 * Buffers.
8 * 4 *
9 * As far as I am concerned, the code I have written for this software 5 * Permission to use, copy, modify, and distribute this software for any
10 * can be used freely for any purpose. Any derived versions of this 6 * purpose with or without fee is hereby granted, provided that the above
11 * software must be clearly marked as such, and if the derived work is 7 * copyright notice and this permission notice appear in all copies.
12 * incompatible with the protocol description in the RFC file, it must be
13 * called by a name other than "ssh" or "Secure Shell".
14 * 8 *
15 * 9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
16 * SSH2 packet format added by Markus Friedl 10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
17 * Copyright (c) 2000 Markus Friedl. All rights reserved. 11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
18 * 12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
19 * Redistribution and use in source and binary forms, with or without 13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
20 * modification, are permitted provided that the following conditions 14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
21 * are met: 15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
30 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
31 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
33 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */ 16 */
39 17
18/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
19
40#include "includes.h" 20#include "includes.h"
41 21
42#include <sys/types.h> 22#include <sys/types.h>
43 23
44#include <openssl/bn.h>
45
46#include <string.h>
47#include <stdarg.h>
48#include <stdlib.h>
49
50#include "xmalloc.h"
51#include "buffer.h" 24#include "buffer.h"
52#include "log.h" 25#include "log.h"
53#include "misc.h" 26#include "ssherr.h"
54
55/*
56 * Returns integers from the buffer (msb first).
57 */
58 27
59int 28int
60buffer_get_short_ret(u_short *ret, Buffer *buffer) 29buffer_get_short_ret(u_short *v, Buffer *buffer)
61{ 30{
62 u_char buf[2]; 31 int ret;
63 32
64 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) 33 if ((ret = sshbuf_get_u16(buffer, v)) != 0) {
65 return (-1); 34 error("%s: %s", __func__, ssh_err(ret));
66 *ret = get_u16(buf); 35 return -1;
67 return (0); 36 }
37 return 0;
68} 38}
69 39
70u_short 40u_short
@@ -73,21 +43,21 @@ buffer_get_short(Buffer *buffer)
73 u_short ret; 43 u_short ret;
74 44
75 if (buffer_get_short_ret(&ret, buffer) == -1) 45 if (buffer_get_short_ret(&ret, buffer) == -1)
76 fatal("buffer_get_short: buffer error"); 46 fatal("%s: buffer error", __func__);
77 47
78 return (ret); 48 return (ret);
79} 49}
80 50
81int 51int
82buffer_get_int_ret(u_int *ret, Buffer *buffer) 52buffer_get_int_ret(u_int *v, Buffer *buffer)
83{ 53{
84 u_char buf[4]; 54 int ret;
85 55
86 if (buffer_get_ret(buffer, (char *) buf, 4) == -1) 56 if ((ret = sshbuf_get_u32(buffer, v)) != 0) {
87 return (-1); 57 error("%s: %s", __func__, ssh_err(ret));
88 if (ret != NULL) 58 return -1;
89 *ret = get_u32(buf); 59 }
90 return (0); 60 return 0;
91} 61}
92 62
93u_int 63u_int
@@ -96,21 +66,21 @@ buffer_get_int(Buffer *buffer)
96 u_int ret; 66 u_int ret;
97 67
98 if (buffer_get_int_ret(&ret, buffer) == -1) 68 if (buffer_get_int_ret(&ret, buffer) == -1)
99 fatal("buffer_get_int: buffer error"); 69 fatal("%s: buffer error", __func__);
100 70
101 return (ret); 71 return (ret);
102} 72}
103 73
104int 74int
105buffer_get_int64_ret(u_int64_t *ret, Buffer *buffer) 75buffer_get_int64_ret(u_int64_t *v, Buffer *buffer)
106{ 76{
107 u_char buf[8]; 77 int ret;
108 78
109 if (buffer_get_ret(buffer, (char *) buf, 8) == -1) 79 if ((ret = sshbuf_get_u64(buffer, v)) != 0) {
110 return (-1); 80 error("%s: %s", __func__, ssh_err(ret));
111 if (ret != NULL) 81 return -1;
112 *ret = get_u64(buf); 82 }
113 return (0); 83 return 0;
114} 84}
115 85
116u_int64_t 86u_int64_t
@@ -119,78 +89,52 @@ buffer_get_int64(Buffer *buffer)
119 u_int64_t ret; 89 u_int64_t ret;
120 90
121 if (buffer_get_int64_ret(&ret, buffer) == -1) 91 if (buffer_get_int64_ret(&ret, buffer) == -1)
122 fatal("buffer_get_int: buffer error"); 92 fatal("%s: buffer error", __func__);
123 93
124 return (ret); 94 return (ret);
125} 95}
126 96
127/*
128 * Stores integers in the buffer, msb first.
129 */
130void 97void
131buffer_put_short(Buffer *buffer, u_short value) 98buffer_put_short(Buffer *buffer, u_short value)
132{ 99{
133 char buf[2]; 100 int ret;
134 101
135 put_u16(buf, value); 102 if ((ret = sshbuf_put_u16(buffer, value)) != 0)
136 buffer_append(buffer, buf, 2); 103 fatal("%s: %s", __func__, ssh_err(ret));
137} 104}
138 105
139void 106void
140buffer_put_int(Buffer *buffer, u_int value) 107buffer_put_int(Buffer *buffer, u_int value)
141{ 108{
142 char buf[4]; 109 int ret;
143 110
144 put_u32(buf, value); 111 if ((ret = sshbuf_put_u32(buffer, value)) != 0)
145 buffer_append(buffer, buf, 4); 112 fatal("%s: %s", __func__, ssh_err(ret));
146} 113}
147 114
148void 115void
149buffer_put_int64(Buffer *buffer, u_int64_t value) 116buffer_put_int64(Buffer *buffer, u_int64_t value)
150{ 117{
151 char buf[8]; 118 int ret;
152 119
153 put_u64(buf, value); 120 if ((ret = sshbuf_put_u64(buffer, value)) != 0)
154 buffer_append(buffer, buf, 8); 121 fatal("%s: %s", __func__, ssh_err(ret));
155} 122}
156 123
157/*
158 * Returns an arbitrary binary string from the buffer. The string cannot
159 * be longer than 256k. The returned value points to memory allocated
160 * with xmalloc; it is the responsibility of the calling function to free
161 * the data. If length_ptr is non-NULL, the length of the returned data
162 * will be stored there. A null character will be automatically appended
163 * to the returned string, and is not counted in length.
164 */
165void * 124void *
166buffer_get_string_ret(Buffer *buffer, u_int *length_ptr) 125buffer_get_string_ret(Buffer *buffer, u_int *length_ptr)
167{ 126{
127 size_t len;
128 int ret;
168 u_char *value; 129 u_char *value;
169 u_int len;
170 130
171 /* Get the length. */ 131 if ((ret = sshbuf_get_string(buffer, &value, &len)) != 0) {
172 if (buffer_get_int_ret(&len, buffer) != 0) { 132 error("%s: %s", __func__, ssh_err(ret));
173 error("buffer_get_string_ret: cannot extract length"); 133 return NULL;
174 return (NULL);
175 }
176 if (len > 256 * 1024) {
177 error("buffer_get_string_ret: bad string length %u", len);
178 return (NULL);
179 }
180 /* Allocate space for the string. Add one byte for a null character. */
181 value = xmalloc(len + 1);
182 /* Get the string. */
183 if (buffer_get_ret(buffer, value, len) == -1) {
184 error("buffer_get_string_ret: buffer_get failed");
185 free(value);
186 return (NULL);
187 } 134 }
188 /* Append a null character to make processing easier. */ 135 if (length_ptr != NULL)
189 value[len] = '\0'; 136 *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
190 /* Optionally return the length of the string. */ 137 return value;
191 if (length_ptr)
192 *length_ptr = len;
193 return (value);
194} 138}
195 139
196void * 140void *
@@ -199,31 +143,24 @@ buffer_get_string(Buffer *buffer, u_int *length_ptr)
199 void *ret; 143 void *ret;
200 144
201 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL) 145 if ((ret = buffer_get_string_ret(buffer, length_ptr)) == NULL)
202 fatal("buffer_get_string: buffer error"); 146 fatal("%s: buffer error", __func__);
203 return (ret); 147 return (ret);
204} 148}
205 149
206char * 150char *
207buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr) 151buffer_get_cstring_ret(Buffer *buffer, u_int *length_ptr)
208{ 152{
209 u_int length; 153 size_t len;
210 char *cp, *ret = buffer_get_string_ret(buffer, &length); 154 int ret;
155 char *value;
211 156
212 if (ret == NULL) 157 if ((ret = sshbuf_get_cstring(buffer, &value, &len)) != 0) {
158 error("%s: %s", __func__, ssh_err(ret));
213 return NULL; 159 return NULL;
214 if ((cp = memchr(ret, '\0', length)) != NULL) {
215 /* XXX allow \0 at end-of-string for a while, remove later */
216 if (cp == ret + length - 1)
217 error("buffer_get_cstring_ret: string contains \\0");
218 else {
219 explicit_bzero(ret, length);
220 free(ret);
221 return NULL;
222 }
223 } 160 }
224 if (length_ptr != NULL) 161 if (length_ptr != NULL)
225 *length_ptr = length; 162 *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
226 return ret; 163 return value;
227} 164}
228 165
229char * 166char *
@@ -232,162 +169,91 @@ buffer_get_cstring(Buffer *buffer, u_int *length_ptr)
232 char *ret; 169 char *ret;
233 170
234 if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL) 171 if ((ret = buffer_get_cstring_ret(buffer, length_ptr)) == NULL)
235 fatal("buffer_get_cstring: buffer error"); 172 fatal("%s: buffer error", __func__);
236 return ret; 173 return ret;
237} 174}
238 175
239void * 176const void *
240buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr) 177buffer_get_string_ptr_ret(Buffer *buffer, u_int *length_ptr)
241{ 178{
242 void *ptr; 179 size_t len;
243 u_int len; 180 int ret;
181 const u_char *value;
244 182
245 if (buffer_get_int_ret(&len, buffer) != 0) 183 if ((ret = sshbuf_get_string_direct(buffer, &value, &len)) != 0) {
246 return NULL; 184 error("%s: %s", __func__, ssh_err(ret));
247 if (len > 256 * 1024) {
248 error("buffer_get_string_ptr: bad string length %u", len);
249 return NULL; 185 return NULL;
250 } 186 }
251 ptr = buffer_ptr(buffer); 187 if (length_ptr != NULL)
252 buffer_consume(buffer, len); 188 *length_ptr = len; /* Safe: sshbuf never stores len > 2^31 */
253 if (length_ptr) 189 return value;
254 *length_ptr = len;
255 return (ptr);
256} 190}
257 191
258void * 192const void *
259buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr) 193buffer_get_string_ptr(Buffer *buffer, u_int *length_ptr)
260{ 194{
261 void *ret; 195 const void *ret;
262 196
263 if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL) 197 if ((ret = buffer_get_string_ptr_ret(buffer, length_ptr)) == NULL)
264 fatal("buffer_get_string_ptr: buffer error"); 198 fatal("%s: buffer error", __func__);
265 return (ret); 199 return (ret);
266} 200}
267 201
268/*
269 * Stores and arbitrary binary string in the buffer.
270 */
271void 202void
272buffer_put_string(Buffer *buffer, const void *buf, u_int len) 203buffer_put_string(Buffer *buffer, const void *buf, u_int len)
273{ 204{
274 buffer_put_int(buffer, len); 205 int ret;
275 buffer_append(buffer, buf, len); 206
207 if ((ret = sshbuf_put_string(buffer, buf, len)) != 0)
208 fatal("%s: %s", __func__, ssh_err(ret));
276} 209}
210
277void 211void
278buffer_put_cstring(Buffer *buffer, const char *s) 212buffer_put_cstring(Buffer *buffer, const char *s)
279{ 213{
280 if (s == NULL) 214 int ret;
281 fatal("buffer_put_cstring: s == NULL"); 215
282 buffer_put_string(buffer, s, strlen(s)); 216 if ((ret = sshbuf_put_cstring(buffer, s)) != 0)
217 fatal("%s: %s", __func__, ssh_err(ret));
283} 218}
284 219
285/*
286 * Returns a character from the buffer (0 - 255).
287 */
288int 220int
289buffer_get_char_ret(u_char *ret, Buffer *buffer) 221buffer_get_char_ret(char *v, Buffer *buffer)
290{ 222{
291 if (buffer_get_ret(buffer, ret, 1) == -1) { 223 int ret;
292 error("buffer_get_char_ret: buffer_get_ret failed"); 224
293 return (-1); 225 if ((ret = sshbuf_get_u8(buffer, (u_char *)v)) != 0) {
226 error("%s: %s", __func__, ssh_err(ret));
227 return -1;
294 } 228 }
295 return (0); 229 return 0;
296} 230}
297 231
298int 232int
299buffer_get_char(Buffer *buffer) 233buffer_get_char(Buffer *buffer)
300{ 234{
301 u_char ch; 235 char ch;
302 236
303 if (buffer_get_char_ret(&ch, buffer) == -1) 237 if (buffer_get_char_ret(&ch, buffer) == -1)
304 fatal("buffer_get_char: buffer error"); 238 fatal("%s: buffer error", __func__);
305 return ch; 239 return (u_char) ch;
306} 240}
307 241
308/*
309 * Stores a character in the buffer.
310 */
311void 242void
312buffer_put_char(Buffer *buffer, int value) 243buffer_put_char(Buffer *buffer, int value)
313{ 244{
314 char ch = value; 245 int ret;
315 246
316 buffer_append(buffer, &ch, 1); 247 if ((ret = sshbuf_put_u8(buffer, value)) != 0)
248 fatal("%s: %s", __func__, ssh_err(ret));
317} 249}
318 250
319/* Pseudo bignum functions */
320
321void *
322buffer_get_bignum2_as_string_ret(Buffer *buffer, u_int *length_ptr)
323{
324 u_int len;
325 u_char *bin, *p, *ret;
326
327 if ((p = bin = buffer_get_string_ret(buffer, &len)) == NULL) {
328 error("%s: invalid bignum", __func__);
329 return NULL;
330 }
331
332 if (len > 0 && (bin[0] & 0x80)) {
333 error("%s: negative numbers not supported", __func__);
334 free(bin);
335 return NULL;
336 }
337 if (len > 8 * 1024) {
338 error("%s: cannot handle BN of size %d", __func__, len);
339 free(bin);
340 return NULL;
341 }
342 /* Skip zero prefix on numbers with the MSB set */
343 if (len > 1 && bin[0] == 0x00 && (bin[1] & 0x80) != 0) {
344 p++;
345 len--;
346 }
347 ret = xmalloc(len);
348 memcpy(ret, p, len);
349 explicit_bzero(p, len);
350 free(bin);
351 return ret;
352}
353
354void *
355buffer_get_bignum2_as_string(Buffer *buffer, u_int *l)
356{
357 void *ret = buffer_get_bignum2_as_string_ret(buffer, l);
358
359 if (ret == NULL)
360 fatal("%s: buffer error", __func__);
361 return ret;
362}
363
364/*
365 * Stores a string using the bignum encoding rules (\0 pad if MSB set).
366 */
367void 251void
368buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l) 252buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
369{ 253{
370 u_char *buf, *p; 254 int ret;
371 int pad = 0;
372
373 if (l > 8 * 1024)
374 fatal("%s: length %u too long", __func__, l);
375 /* Skip leading zero bytes */
376 for (; l > 0 && *s == 0; l--, s++)
377 ;
378 p = buf = xmalloc(l + 1);
379 /*
380 * If most significant bit is set then prepend a zero byte to
381 * avoid interpretation as a negative number.
382 */
383 if (l > 0 && (s[0] & 0x80) != 0) {
384 *p++ = '\0';
385 pad = 1;
386 }
387 memcpy(p, s, l);
388 buffer_put_string(buffer, buf, l + pad);
389 explicit_bzero(buf, l + pad);
390 free(buf);
391}
392 255
256 if ((ret = sshbuf_put_bignum2_bytes(buffer, s, l)) != 0)
257 fatal("%s: %s", __func__, ssh_err(ret));
258}
393 259
diff --git a/bufbn.c b/bufbn.c
index 1d2e01266..b7f7cb122 100644
--- a/bufbn.c
+++ b/bufbn.c
@@ -1,229 +1,103 @@
1/* $OpenBSD: bufbn.c,v 1.11 2014/02/27 08:25:09 djm Exp $*/ 1/* $OpenBSD: bufbn.c,v 1.12 2014/04/30 05:29:56 djm Exp $ */
2
2/* 3/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved
6 * Auxiliary functions for storing and retrieving various data types to/from
7 * Buffers.
8 *
9 * As far as I am concerned, the code I have written for this software
10 * can be used freely for any purpose. Any derived versions of this
11 * software must be clearly marked as such, and if the derived work is
12 * incompatible with the protocol description in the RFC file, it must be
13 * called by a name other than "ssh" or "Secure Shell".
14 *
15 *
16 * SSH2 packet format added by Markus Friedl
17 * Copyright (c) 2000 Markus Friedl. All rights reserved.
18 * 5 *
19 * Redistribution and use in source and binary forms, with or without 6 * Permission to use, copy, modify, and distribute this software for any
20 * modification, are permitted provided that the following conditions 7 * purpose with or without fee is hereby granted, provided that the above
21 * are met: 8 * copyright notice and this permission notice appear in all copies.
22 * 1. Redistributions of source code must retain the above copyright
23 * notice, this list of conditions and the following disclaimer.
24 * 2. Redistributions in binary form must reproduce the above copyright
25 * notice, this list of conditions and the following disclaimer in the
26 * documentation and/or other materials provided with the distribution.
27 * 9 *
28 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
29 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
30 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
31 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
32 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
33 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
34 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
35 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
36 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
37 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
38 */ 17 */
39 18
19/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
20
40#include "includes.h" 21#include "includes.h"
41 22
42#include <sys/types.h> 23#include <sys/types.h>
43 24
44#include <openssl/bn.h>
45
46#include <string.h>
47#include <stdarg.h>
48#include <stdlib.h>
49
50#include "xmalloc.h"
51#include "buffer.h" 25#include "buffer.h"
52#include "log.h" 26#include "log.h"
53#include "misc.h" 27#include "ssherr.h"
54 28
55/*
56 * Stores an BIGNUM in the buffer with a 2-byte msb first bit count, followed
57 * by (bits+7)/8 bytes of binary data, msb first.
58 */
59int 29int
60buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value) 30buffer_put_bignum_ret(Buffer *buffer, const BIGNUM *value)
61{ 31{
62 int bits = BN_num_bits(value); 32 int ret;
63 int bin_size = (bits + 7) / 8;
64 u_char *buf = xmalloc(bin_size);
65 int oi;
66 char msg[2];
67
68 /* Get the value of in binary */
69 oi = BN_bn2bin(value, buf);
70 if (oi != bin_size) {
71 error("buffer_put_bignum_ret: BN_bn2bin() failed: oi %d != bin_size %d",
72 oi, bin_size);
73 free(buf);
74 return (-1);
75 }
76
77 /* Store the number of bits in the buffer in two bytes, msb first. */
78 put_u16(msg, bits);
79 buffer_append(buffer, msg, 2);
80 /* Store the binary data. */
81 buffer_append(buffer, buf, oi);
82
83 explicit_bzero(buf, bin_size);
84 free(buf);
85 33
86 return (0); 34 if ((ret = sshbuf_put_bignum1(buffer, value)) != 0) {
35 error("%s: %s", __func__, ssh_err(ret));
36 return -1;
37 }
38 return 0;
87} 39}
88 40
89void 41void
90buffer_put_bignum(Buffer *buffer, const BIGNUM *value) 42buffer_put_bignum(Buffer *buffer, const BIGNUM *value)
91{ 43{
92 if (buffer_put_bignum_ret(buffer, value) == -1) 44 if (buffer_put_bignum_ret(buffer, value) == -1)
93 fatal("buffer_put_bignum: buffer error"); 45 fatal("%s: buffer error", __func__);
94} 46}
95 47
96/*
97 * Retrieves a BIGNUM from the buffer.
98 */
99int 48int
100buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value) 49buffer_get_bignum_ret(Buffer *buffer, BIGNUM *value)
101{ 50{
102 u_int bits, bytes; 51 int ret;
103 u_char buf[2], *bin;
104 52
105 /* Get the number of bits. */ 53 if ((ret = sshbuf_get_bignum1(buffer, value)) != 0) {
106 if (buffer_get_ret(buffer, (char *) buf, 2) == -1) { 54 error("%s: %s", __func__, ssh_err(ret));
107 error("buffer_get_bignum_ret: invalid length"); 55 return -1;
108 return (-1);
109 } 56 }
110 bits = get_u16(buf); 57 return 0;
111 if (bits > 65535-7) {
112 error("buffer_get_bignum_ret: cannot handle BN of size %d",
113 bits);
114 return (-1);
115 }
116 /* Compute the number of binary bytes that follow. */
117 bytes = (bits + 7) / 8;
118 if (bytes > 8 * 1024) {
119 error("buffer_get_bignum_ret: cannot handle BN of size %d", bytes);
120 return (-1);
121 }
122 if (buffer_len(buffer) < bytes) {
123 error("buffer_get_bignum_ret: input buffer too small");
124 return (-1);
125 }
126 bin = buffer_ptr(buffer);
127 if (BN_bin2bn(bin, bytes, value) == NULL) {
128 error("buffer_get_bignum_ret: BN_bin2bn failed");
129 return (-1);
130 }
131 if (buffer_consume_ret(buffer, bytes) == -1) {
132 error("buffer_get_bignum_ret: buffer_consume failed");
133 return (-1);
134 }
135 return (0);
136} 58}
137 59
138void 60void
139buffer_get_bignum(Buffer *buffer, BIGNUM *value) 61buffer_get_bignum(Buffer *buffer, BIGNUM *value)
140{ 62{
141 if (buffer_get_bignum_ret(buffer, value) == -1) 63 if (buffer_get_bignum_ret(buffer, value) == -1)
142 fatal("buffer_get_bignum: buffer error"); 64 fatal("%s: buffer error", __func__);
143} 65}
144 66
145/*
146 * Stores a BIGNUM in the buffer in SSH2 format.
147 */
148int 67int
149buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value) 68buffer_put_bignum2_ret(Buffer *buffer, const BIGNUM *value)
150{ 69{
151 u_int bytes; 70 int ret;
152 u_char *buf; 71
153 int oi; 72 if ((ret = sshbuf_put_bignum2(buffer, value)) != 0) {
154 u_int hasnohigh = 0; 73 error("%s: %s", __func__, ssh_err(ret));
155 74 return -1;
156 if (BN_is_zero(value)) {
157 buffer_put_int(buffer, 0);
158 return 0;
159 }
160 if (value->neg) {
161 error("buffer_put_bignum2_ret: negative numbers not supported");
162 return (-1);
163 }
164 bytes = BN_num_bytes(value) + 1; /* extra padding byte */
165 if (bytes < 2) {
166 error("buffer_put_bignum2_ret: BN too small");
167 return (-1);
168 }
169 buf = xmalloc(bytes);
170 buf[0] = 0x00;
171 /* Get the value of in binary */
172 oi = BN_bn2bin(value, buf+1);
173 if (oi < 0 || (u_int)oi != bytes - 1) {
174 error("buffer_put_bignum2_ret: BN_bn2bin() failed: "
175 "oi %d != bin_size %d", oi, bytes);
176 free(buf);
177 return (-1);
178 } 75 }
179 hasnohigh = (buf[1] & 0x80) ? 0 : 1; 76 return 0;
180 buffer_put_string(buffer, buf+hasnohigh, bytes-hasnohigh);
181 explicit_bzero(buf, bytes);
182 free(buf);
183 return (0);
184} 77}
185 78
186void 79void
187buffer_put_bignum2(Buffer *buffer, const BIGNUM *value) 80buffer_put_bignum2(Buffer *buffer, const BIGNUM *value)
188{ 81{
189 if (buffer_put_bignum2_ret(buffer, value) == -1) 82 if (buffer_put_bignum2_ret(buffer, value) == -1)
190 fatal("buffer_put_bignum2: buffer error"); 83 fatal("%s: buffer error", __func__);
191} 84}
192 85
193int 86int
194buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value) 87buffer_get_bignum2_ret(Buffer *buffer, BIGNUM *value)
195{ 88{
196 u_int len; 89 int ret;
197 u_char *bin;
198 90
199 if ((bin = buffer_get_string_ret(buffer, &len)) == NULL) { 91 if ((ret = sshbuf_get_bignum2(buffer, value)) != 0) {
200 error("buffer_get_bignum2_ret: invalid bignum"); 92 error("%s: %s", __func__, ssh_err(ret));
201 return (-1); 93 return -1;
202 }
203
204 if (len > 0 && (bin[0] & 0x80)) {
205 error("buffer_get_bignum2_ret: negative numbers not supported");
206 free(bin);
207 return (-1);
208 }
209 if (len > 8 * 1024) {
210 error("buffer_get_bignum2_ret: cannot handle BN of size %d",
211 len);
212 free(bin);
213 return (-1);
214 }
215 if (BN_bin2bn(bin, len, value) == NULL) {
216 error("buffer_get_bignum2_ret: BN_bin2bn failed");
217 free(bin);
218 return (-1);
219 } 94 }
220 free(bin); 95 return 0;
221 return (0);
222} 96}
223 97
224void 98void
225buffer_get_bignum2(Buffer *buffer, BIGNUM *value) 99buffer_get_bignum2(Buffer *buffer, BIGNUM *value)
226{ 100{
227 if (buffer_get_bignum2_ret(buffer, value) == -1) 101 if (buffer_get_bignum2_ret(buffer, value) == -1)
228 fatal("buffer_get_bignum2: buffer error"); 102 fatal("%s: buffer error", __func__);
229} 103}
diff --git a/bufec.c b/bufec.c
index 89482b906..749ce9d4c 100644
--- a/bufec.c
+++ b/bufec.c
@@ -1,6 +1,7 @@
1/* $OpenBSD: bufec.c,v 1.3 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: bufec.c,v 1.4 2014/04/30 05:29:56 djm Exp $ */
2
2/* 3/*
3 * Copyright (c) 2010 Damien Miller <djm@mindrot.org> 4 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
4 * 5 *
5 * Permission to use, copy, modify, and distribute this software for any 6 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above 7 * purpose with or without fee is hereby granted, provided that the above
@@ -15,73 +16,29 @@
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */ 17 */
17 18
18#include "includes.h" 19/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
19 20
20#ifdef OPENSSL_HAS_ECC 21#include "includes.h"
21 22
22#include <sys/types.h> 23#include <sys/types.h>
23 24
24#include <openssl/bn.h>
25#include <openssl/ec.h>
26
27#include <string.h>
28#include <stdarg.h>
29
30#include "xmalloc.h"
31#include "buffer.h" 25#include "buffer.h"
32#include "log.h" 26#include "log.h"
33#include "misc.h" 27#include "ssherr.h"
34 28
35/* 29#ifdef OPENSSL_HAS_ECC
36 * Maximum supported EC GFp field length is 528 bits. SEC1 uncompressed
37 * encoding represents this as two bitstring points that should each
38 * be no longer than the field length, SEC1 specifies a 1 byte
39 * point type header.
40 * Being paranoid here may insulate us to parsing problems in
41 * EC_POINT_oct2point.
42 */
43#define BUFFER_MAX_ECPOINT_LEN ((528*2 / 8) + 1)
44 30
45/*
46 * Append an EC_POINT to the buffer as a string containing a SEC1 encoded
47 * uncompressed point. Fortunately OpenSSL handles the gory details for us.
48 */
49int 31int
50buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, 32buffer_put_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
51 const EC_POINT *point) 33 const EC_POINT *point)
52{ 34{
53 u_char *buf = NULL; 35 int ret;
54 size_t len;
55 BN_CTX *bnctx;
56 int ret = -1;
57 36
58 /* Determine length */ 37 if ((ret = sshbuf_put_ec(buffer, point, curve)) != 0) {
59 if ((bnctx = BN_CTX_new()) == NULL) 38 error("%s: %s", __func__, ssh_err(ret));
60 fatal("%s: BN_CTX_new failed", __func__); 39 return -1;
61 len = EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
62 NULL, 0, bnctx);
63 if (len > BUFFER_MAX_ECPOINT_LEN) {
64 error("%s: giant EC point: len = %lu (max %u)",
65 __func__, (u_long)len, BUFFER_MAX_ECPOINT_LEN);
66 goto out;
67 }
68 /* Convert */
69 buf = xmalloc(len);
70 if (EC_POINT_point2oct(curve, point, POINT_CONVERSION_UNCOMPRESSED,
71 buf, len, bnctx) != len) {
72 error("%s: EC_POINT_point2oct length mismatch", __func__);
73 goto out;
74 }
75 /* Append */
76 buffer_put_string(buffer, buf, len);
77 ret = 0;
78 out:
79 if (buf != NULL) {
80 explicit_bzero(buf, len);
81 free(buf);
82 } 40 }
83 BN_CTX_free(bnctx); 41 return 0;
84 return ret;
85} 42}
86 43
87void 44void
@@ -96,43 +53,13 @@ int
96buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve, 53buffer_get_ecpoint_ret(Buffer *buffer, const EC_GROUP *curve,
97 EC_POINT *point) 54 EC_POINT *point)
98{ 55{
99 u_char *buf; 56 int ret;
100 u_int len;
101 BN_CTX *bnctx;
102 int ret = -1;
103 57
104 if ((buf = buffer_get_string_ret(buffer, &len)) == NULL) { 58 if ((ret = sshbuf_get_ec(buffer, point, curve)) != 0) {
105 error("%s: invalid point", __func__); 59 error("%s: %s", __func__, ssh_err(ret));
106 return -1; 60 return -1;
107 } 61 }
108 if ((bnctx = BN_CTX_new()) == NULL) 62 return 0;
109 fatal("%s: BN_CTX_new failed", __func__);
110 if (len > BUFFER_MAX_ECPOINT_LEN) {
111 error("%s: EC_POINT too long: %u > max %u", __func__,
112 len, BUFFER_MAX_ECPOINT_LEN);
113 goto out;
114 }
115 if (len == 0) {
116 error("%s: EC_POINT buffer is empty", __func__);
117 goto out;
118 }
119 if (buf[0] != POINT_CONVERSION_UNCOMPRESSED) {
120 error("%s: EC_POINT is in an incorrect form: "
121 "0x%02x (want 0x%02x)", __func__, buf[0],
122 POINT_CONVERSION_UNCOMPRESSED);
123 goto out;
124 }
125 if (EC_POINT_oct2point(curve, point, buf, len, bnctx) != 1) {
126 error("buffer_get_bignum2_ret: BN_bin2bn failed");
127 goto out;
128 }
129 /* EC_POINT_oct2point verifies that the point is on the curve for us */
130 ret = 0;
131 out:
132 BN_CTX_free(bnctx);
133 explicit_bzero(buf, len);
134 free(buf);
135 return ret;
136} 63}
137 64
138void 65void
@@ -144,3 +71,4 @@ buffer_get_ecpoint(Buffer *buffer, const EC_GROUP *curve,
144} 71}
145 72
146#endif /* OPENSSL_HAS_ECC */ 73#endif /* OPENSSL_HAS_ECC */
74
diff --git a/buffer.c b/buffer.c
index d240f6753..c5f708ab2 100644
--- a/buffer.c
+++ b/buffer.c
@@ -1,253 +1,118 @@
1/* $OpenBSD: buffer.c,v 1.35 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: buffer.c,v 1.36 2014/04/30 05:29:56 djm Exp $ */
2
2/* 3/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 5 *
5 * All rights reserved 6 * Permission to use, copy, modify, and distribute this software for any
6 * Functions for manipulating fifo buffers (that can grow if needed). 7 * purpose with or without fee is hereby granted, provided that the above
8 * copyright notice and this permission notice appear in all copies.
7 * 9 *
8 * As far as I am concerned, the code I have written for this software 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * can be used freely for any purpose. Any derived versions of this 11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * software must be clearly marked as such, and if the derived work is 12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * incompatible with the protocol description in the RFC file, it must be 13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * called by a name other than "ssh" or "Secure Shell". 14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
13 */ 17 */
14 18
15#include "includes.h" 19/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
16 20
17#include <sys/param.h> 21#include "includes.h"
18 22
19#include <stdio.h> 23#include <sys/types.h>
20#include <string.h>
21#include <stdarg.h>
22#include <stdlib.h>
23 24
24#include "xmalloc.h"
25#include "buffer.h" 25#include "buffer.h"
26#include "log.h" 26#include "log.h"
27 27#include "ssherr.h"
28#define BUFFER_MAX_CHUNK 0x100000
29#define BUFFER_MAX_LEN 0xa00000
30#define BUFFER_ALLOCSZ 0x008000
31
32/* Initializes the buffer structure. */
33
34void
35buffer_init(Buffer *buffer)
36{
37 const u_int len = 4096;
38
39 buffer->alloc = 0;
40 buffer->buf = xmalloc(len);
41 buffer->alloc = len;
42 buffer->offset = 0;
43 buffer->end = 0;
44}
45
46/* Frees any memory used for the buffer. */
47
48void
49buffer_free(Buffer *buffer)
50{
51 if (buffer->alloc > 0) {
52 explicit_bzero(buffer->buf, buffer->alloc);
53 buffer->alloc = 0;
54 free(buffer->buf);
55 }
56}
57
58/*
59 * Clears any data from the buffer, making it empty. This does not actually
60 * zero the memory.
61 */
62
63void
64buffer_clear(Buffer *buffer)
65{
66 buffer->offset = 0;
67 buffer->end = 0;
68}
69
70/* Appends data to the buffer, expanding it if necessary. */
71 28
72void 29void
73buffer_append(Buffer *buffer, const void *data, u_int len) 30buffer_append(Buffer *buffer, const void *data, u_int len)
74{ 31{
75 void *p; 32 int ret;
76 p = buffer_append_space(buffer, len);
77 memcpy(p, data, len);
78}
79 33
80static int 34 if ((ret = sshbuf_put(buffer, data, len)) != 0)
81buffer_compact(Buffer *buffer) 35 fatal("%s: %s", __func__, ssh_err(ret));
82{
83 /*
84 * If the buffer is quite empty, but all data is at the end, move the
85 * data to the beginning.
86 */
87 if (buffer->offset > MIN(buffer->alloc, BUFFER_MAX_CHUNK)) {
88 memmove(buffer->buf, buffer->buf + buffer->offset,
89 buffer->end - buffer->offset);
90 buffer->end -= buffer->offset;
91 buffer->offset = 0;
92 return (1);
93 }
94 return (0);
95} 36}
96 37
97/*
98 * Appends space to the buffer, expanding the buffer if necessary. This does
99 * not actually copy the data into the buffer, but instead returns a pointer
100 * to the allocated region.
101 */
102
103void * 38void *
104buffer_append_space(Buffer *buffer, u_int len) 39buffer_append_space(Buffer *buffer, u_int len)
105{ 40{
106 u_int newlen; 41 int ret;
107 void *p; 42 u_char *p;
108 43
109 if (len > BUFFER_MAX_CHUNK) 44 if ((ret = sshbuf_reserve(buffer, len, &p)) != 0)
110 fatal("buffer_append_space: len %u not supported", len); 45 fatal("%s: %s", __func__, ssh_err(ret));
111 46 return p;
112 /* If the buffer is empty, start using it from the beginning. */
113 if (buffer->offset == buffer->end) {
114 buffer->offset = 0;
115 buffer->end = 0;
116 }
117restart:
118 /* If there is enough space to store all data, store it now. */
119 if (buffer->end + len < buffer->alloc) {
120 p = buffer->buf + buffer->end;
121 buffer->end += len;
122 return p;
123 }
124
125 /* Compact data back to the start of the buffer if necessary */
126 if (buffer_compact(buffer))
127 goto restart;
128
129 /* Increase the size of the buffer and retry. */
130 newlen = roundup(buffer->alloc + len, BUFFER_ALLOCSZ);
131 if (newlen > BUFFER_MAX_LEN)
132 fatal("buffer_append_space: alloc %u not supported",
133 newlen);
134 buffer->buf = xrealloc(buffer->buf, 1, newlen);
135 buffer->alloc = newlen;
136 goto restart;
137 /* NOTREACHED */
138} 47}
139 48
140/*
141 * Check whether an allocation of 'len' will fit in the buffer
142 * This must follow the same math as buffer_append_space
143 */
144int 49int
145buffer_check_alloc(Buffer *buffer, u_int len) 50buffer_check_alloc(Buffer *buffer, u_int len)
146{ 51{
147 if (buffer->offset == buffer->end) { 52 int ret = sshbuf_check_reserve(buffer, len);
148 buffer->offset = 0;
149 buffer->end = 0;
150 }
151 restart:
152 if (buffer->end + len < buffer->alloc)
153 return (1);
154 if (buffer_compact(buffer))
155 goto restart;
156 if (roundup(buffer->alloc + len, BUFFER_ALLOCSZ) <= BUFFER_MAX_LEN)
157 return (1);
158 return (0);
159}
160
161/* Returns the number of bytes of data in the buffer. */
162 53
163u_int 54 if (ret == 0)
164buffer_len(const Buffer *buffer) 55 return 1;
165{ 56 if (ret == SSH_ERR_NO_BUFFER_SPACE)
166 return buffer->end - buffer->offset; 57 return 0;
58 fatal("%s: %s", __func__, ssh_err(ret));
167} 59}
168 60
169/* Gets data from the beginning of the buffer. */
170
171int 61int
172buffer_get_ret(Buffer *buffer, void *buf, u_int len) 62buffer_get_ret(Buffer *buffer, void *buf, u_int len)
173{ 63{
174 if (len > buffer->end - buffer->offset) { 64 int ret;
175 error("buffer_get_ret: trying to get more bytes %d than in buffer %d", 65
176 len, buffer->end - buffer->offset); 66 if ((ret = sshbuf_get(buffer, buf, len)) != 0) {
177 return (-1); 67 error("%s: %s", __func__, ssh_err(ret));
68 return -1;
178 } 69 }
179 memcpy(buf, buffer->buf + buffer->offset, len); 70 return 0;
180 buffer->offset += len;
181 return (0);
182} 71}
183 72
184void 73void
185buffer_get(Buffer *buffer, void *buf, u_int len) 74buffer_get(Buffer *buffer, void *buf, u_int len)
186{ 75{
187 if (buffer_get_ret(buffer, buf, len) == -1) 76 if (buffer_get_ret(buffer, buf, len) == -1)
188 fatal("buffer_get: buffer error"); 77 fatal("%s: buffer error", __func__);
189} 78}
190 79
191/* Consumes the given number of bytes from the beginning of the buffer. */
192
193int 80int
194buffer_consume_ret(Buffer *buffer, u_int bytes) 81buffer_consume_ret(Buffer *buffer, u_int bytes)
195{ 82{
196 if (bytes > buffer->end - buffer->offset) { 83 int ret = sshbuf_consume(buffer, bytes);
197 error("buffer_consume_ret: trying to get more bytes than in buffer"); 84
198 return (-1); 85 if (ret == 0)
199 } 86 return 0;
200 buffer->offset += bytes; 87 if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
201 return (0); 88 return -1;
89 fatal("%s: %s", __func__, ssh_err(ret));
202} 90}
203 91
204void 92void
205buffer_consume(Buffer *buffer, u_int bytes) 93buffer_consume(Buffer *buffer, u_int bytes)
206{ 94{
207 if (buffer_consume_ret(buffer, bytes) == -1) 95 if (buffer_consume_ret(buffer, bytes) == -1)
208 fatal("buffer_consume: buffer error"); 96 fatal("%s: buffer error", __func__);
209} 97}
210 98
211/* Consumes the given number of bytes from the end of the buffer. */
212
213int 99int
214buffer_consume_end_ret(Buffer *buffer, u_int bytes) 100buffer_consume_end_ret(Buffer *buffer, u_int bytes)
215{ 101{
216 if (bytes > buffer->end - buffer->offset) 102 int ret = sshbuf_consume_end(buffer, bytes);
217 return (-1); 103
218 buffer->end -= bytes; 104 if (ret == 0)
219 return (0); 105 return 0;
106 if (ret == SSH_ERR_MESSAGE_INCOMPLETE)
107 return -1;
108 fatal("%s: %s", __func__, ssh_err(ret));
220} 109}
221 110
222void 111void
223buffer_consume_end(Buffer *buffer, u_int bytes) 112buffer_consume_end(Buffer *buffer, u_int bytes)
224{ 113{
225 if (buffer_consume_end_ret(buffer, bytes) == -1) 114 if (buffer_consume_end_ret(buffer, bytes) == -1)
226 fatal("buffer_consume_end: trying to get more bytes than in buffer"); 115 fatal("%s: buffer error", __func__);
227}
228
229/* Returns a pointer to the first used byte in the buffer. */
230
231void *
232buffer_ptr(const Buffer *buffer)
233{
234 return buffer->buf + buffer->offset;
235} 116}
236 117
237/* Dumps the contents of the buffer to stderr. */
238 118
239void
240buffer_dump(const Buffer *buffer)
241{
242 u_int i;
243 u_char *ucp = buffer->buf;
244
245 for (i = buffer->offset; i < buffer->end; i++) {
246 fprintf(stderr, "%02x", ucp[i]);
247 if ((i-buffer->offset)%16==15)
248 fprintf(stderr, "\r\n");
249 else if ((i-buffer->offset)%2==1)
250 fprintf(stderr, " ");
251 }
252 fprintf(stderr, "\r\n");
253}
diff --git a/buffer.h b/buffer.h
index 7df8a38fa..9d853edf2 100644
--- a/buffer.h
+++ b/buffer.h
@@ -1,57 +1,58 @@
1/* $OpenBSD: buffer.h,v 1.23 2014/01/12 08:13:13 djm Exp $ */ 1/* $OpenBSD: buffer.h,v 1.25 2014/04/30 05:29:56 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Copyright (c) 2012 Damien Miller <djm@mindrot.org>
5 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
6 * All rights reserved
7 * Code for manipulating FIFO buffers.
8 * 5 *
9 * As far as I am concerned, the code I have written for this software 6 * Permission to use, copy, modify, and distribute this software for any
10 * can be used freely for any purpose. Any derived versions of this 7 * purpose with or without fee is hereby granted, provided that the above
11 * software must be clearly marked as such, and if the derived work is 8 * copyright notice and this permission notice appear in all copies.
12 * incompatible with the protocol description in the RFC file, it must be 9 *
13 * called by a name other than "ssh" or "Secure Shell". 10 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
11 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
12 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
13 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
14 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
15 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
16 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
14 */ 17 */
15 18
19/* Emulation wrappers for legacy OpenSSH buffer API atop sshbuf */
20
16#ifndef BUFFER_H 21#ifndef BUFFER_H
17#define BUFFER_H 22#define BUFFER_H
18 23
19typedef struct { 24#include "sshbuf.h"
20 u_char *buf; /* Buffer for data. */ 25
21 u_int alloc; /* Number of bytes allocated for data. */ 26typedef struct sshbuf Buffer;
22 u_int offset; /* Offset of first byte containing data. */
23 u_int end; /* Offset of last byte containing data. */
24} Buffer;
25 27
26void buffer_init(Buffer *); 28#define buffer_init(b) sshbuf_init(b)
27void buffer_clear(Buffer *); 29#define buffer_clear(b) sshbuf_reset(b)
28void buffer_free(Buffer *); 30#define buffer_free(b) sshbuf_free(b)
31#define buffer_dump(b) sshbuf_dump(b, stderr)
29 32
30u_int buffer_len(const Buffer *); 33/* XXX cast is safe: sshbuf never stores more than len 2^31 */
31void *buffer_ptr(const Buffer *); 34#define buffer_len(b) ((u_int) sshbuf_len(b))
35#define buffer_ptr(b) sshbuf_mutable_ptr(b)
32 36
33void buffer_append(Buffer *, const void *, u_int); 37void buffer_append(Buffer *, const void *, u_int);
34void *buffer_append_space(Buffer *, u_int); 38void *buffer_append_space(Buffer *, u_int);
35
36int buffer_check_alloc(Buffer *, u_int); 39int buffer_check_alloc(Buffer *, u_int);
37
38void buffer_get(Buffer *, void *, u_int); 40void buffer_get(Buffer *, void *, u_int);
39 41
40void buffer_consume(Buffer *, u_int); 42void buffer_consume(Buffer *, u_int);
41void buffer_consume_end(Buffer *, u_int); 43void buffer_consume_end(Buffer *, u_int);
42 44
43void buffer_dump(const Buffer *);
44 45
45int buffer_get_ret(Buffer *, void *, u_int); 46int buffer_get_ret(Buffer *, void *, u_int);
46int buffer_consume_ret(Buffer *, u_int); 47int buffer_consume_ret(Buffer *, u_int);
47int buffer_consume_end_ret(Buffer *, u_int); 48int buffer_consume_end_ret(Buffer *, u_int);
48 49
49#include <openssl/bn.h> 50#include <openssl/bn.h>
50
51void buffer_put_bignum(Buffer *, const BIGNUM *); 51void buffer_put_bignum(Buffer *, const BIGNUM *);
52void buffer_put_bignum2(Buffer *, const BIGNUM *); 52void buffer_put_bignum2(Buffer *, const BIGNUM *);
53void buffer_get_bignum(Buffer *, BIGNUM *); 53void buffer_get_bignum(Buffer *, BIGNUM *);
54void buffer_get_bignum2(Buffer *, BIGNUM *); 54void buffer_get_bignum2(Buffer *, BIGNUM *);
55void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int);
55 56
56u_short buffer_get_short(Buffer *); 57u_short buffer_get_short(Buffer *);
57void buffer_put_short(Buffer *, u_short); 58void buffer_put_short(Buffer *, u_short);
@@ -66,13 +67,12 @@ int buffer_get_char(Buffer *);
66void buffer_put_char(Buffer *, int); 67void buffer_put_char(Buffer *, int);
67 68
68void *buffer_get_string(Buffer *, u_int *); 69void *buffer_get_string(Buffer *, u_int *);
69void *buffer_get_string_ptr(Buffer *, u_int *); 70const void *buffer_get_string_ptr(Buffer *, u_int *);
70void buffer_put_string(Buffer *, const void *, u_int); 71void buffer_put_string(Buffer *, const void *, u_int);
71char *buffer_get_cstring(Buffer *, u_int *); 72char *buffer_get_cstring(Buffer *, u_int *);
72void buffer_put_cstring(Buffer *, const char *); 73void buffer_put_cstring(Buffer *, const char *);
73 74
74#define buffer_skip_string(b) \ 75#define buffer_skip_string(b) (void)buffer_get_string_ptr(b, NULL);
75 do { u_int l = buffer_get_int(b); buffer_consume(b, l); } while (0)
76 76
77int buffer_put_bignum_ret(Buffer *, const BIGNUM *); 77int buffer_put_bignum_ret(Buffer *, const BIGNUM *);
78int buffer_get_bignum_ret(Buffer *, BIGNUM *); 78int buffer_get_bignum_ret(Buffer *, BIGNUM *);
@@ -83,20 +83,16 @@ int buffer_get_int_ret(u_int *, Buffer *);
83int buffer_get_int64_ret(u_int64_t *, Buffer *); 83int buffer_get_int64_ret(u_int64_t *, Buffer *);
84void *buffer_get_string_ret(Buffer *, u_int *); 84void *buffer_get_string_ret(Buffer *, u_int *);
85char *buffer_get_cstring_ret(Buffer *, u_int *); 85char *buffer_get_cstring_ret(Buffer *, u_int *);
86void *buffer_get_string_ptr_ret(Buffer *, u_int *); 86const void *buffer_get_string_ptr_ret(Buffer *, u_int *);
87int buffer_get_char_ret(u_char *, Buffer *); 87int buffer_get_char_ret(char *, Buffer *);
88
89void *buffer_get_bignum2_as_string_ret(Buffer *, u_int *);
90void *buffer_get_bignum2_as_string(Buffer *, u_int *);
91void buffer_put_bignum2_from_string(Buffer *, const u_char *, u_int);
92 88
93#ifdef OPENSSL_HAS_ECC 89#ifdef OPENSSL_HAS_ECC
94#include <openssl/ec.h> 90#include <openssl/ec.h>
95
96int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *); 91int buffer_put_ecpoint_ret(Buffer *, const EC_GROUP *, const EC_POINT *);
97void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *); 92void buffer_put_ecpoint(Buffer *, const EC_GROUP *, const EC_POINT *);
98int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *); 93int buffer_get_ecpoint_ret(Buffer *, const EC_GROUP *, EC_POINT *);
99void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *); 94void buffer_get_ecpoint(Buffer *, const EC_GROUP *, EC_POINT *);
100#endif 95#endif
101 96
102#endif /* BUFFER_H */ 97#endif /* BUFFER_H */
98
diff --git a/canohost.c b/canohost.c
index a61a8c94d..a3e3bbff8 100644
--- a/canohost.c
+++ b/canohost.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: canohost.c,v 1.70 2014/01/19 04:17:29 dtucker Exp $ */ 1/* $OpenBSD: canohost.c,v 1.71 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -16,6 +16,7 @@
16 16
17#include <sys/types.h> 17#include <sys/types.h>
18#include <sys/socket.h> 18#include <sys/socket.h>
19#include <sys/un.h>
19 20
20#include <netinet/in.h> 21#include <netinet/in.h>
21#include <arpa/inet.h> 22#include <arpa/inet.h>
@@ -262,6 +263,11 @@ get_socket_address(int sock, int remote, int flags)
262 if (addr.ss_family == AF_INET6) 263 if (addr.ss_family == AF_INET6)
263 addrlen = sizeof(struct sockaddr_in6); 264 addrlen = sizeof(struct sockaddr_in6);
264 265
266 if (addr.ss_family == AF_UNIX) {
267 /* Get the Unix domain socket path. */
268 return xstrdup(((struct sockaddr_un *)&addr)->sun_path);
269 }
270
265 ipv64_normalise_mapped(&addr, &addrlen); 271 ipv64_normalise_mapped(&addr, &addrlen);
266 272
267 /* Get the address in ascii. */ 273 /* Get the address in ascii. */
@@ -384,6 +390,10 @@ get_sock_port(int sock, int local)
384 if (from.ss_family == AF_INET6) 390 if (from.ss_family == AF_INET6)
385 fromlen = sizeof(struct sockaddr_in6); 391 fromlen = sizeof(struct sockaddr_in6);
386 392
393 /* Unix domain sockets don't have a port number. */
394 if (from.ss_family == AF_UNIX)
395 return 0;
396
387 /* Return port number. */ 397 /* Return port number. */
388 if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0, 398 if ((r = getnameinfo((struct sockaddr *)&from, fromlen, NULL, 0,
389 strport, sizeof(strport), NI_NUMERICSERV)) != 0) 399 strport, sizeof(strport), NI_NUMERICSERV)) != 0)
diff --git a/chacha.h b/chacha.h
index 4ef42cc70..40eaf2d90 100644
--- a/chacha.h
+++ b/chacha.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: chacha.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ 1/* $OpenBSD: chacha.h,v 1.3 2014/05/02 03:27:54 djm Exp $ */
2 2
3/* 3/*
4chacha-merged.c version 20080118 4chacha-merged.c version 20080118
diff --git a/channels.c b/channels.c
index 9efe89c9c..d67fdf48b 100644
--- a/channels.c
+++ b/channels.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.c,v 1.331 2014/02/26 20:29:29 djm Exp $ */ 1/* $OpenBSD: channels.c,v 1.336 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -42,6 +42,7 @@
42#include "includes.h" 42#include "includes.h"
43 43
44#include <sys/types.h> 44#include <sys/types.h>
45#include <sys/stat.h>
45#include <sys/ioctl.h> 46#include <sys/ioctl.h>
46#include <sys/un.h> 47#include <sys/un.h>
47#include <sys/socket.h> 48#include <sys/socket.h>
@@ -107,10 +108,15 @@ static int channel_max_fd = 0;
107 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local 108 * a corrupt remote server from accessing arbitrary TCP/IP ports on our local
108 * network (which might be behind a firewall). 109 * network (which might be behind a firewall).
109 */ 110 */
111/* XXX: streamlocal wants a path instead of host:port */
112/* Overload host_to_connect; we could just make this match Forward */
113/* XXX - can we use listen_host instead of listen_path? */
110typedef struct { 114typedef struct {
111 char *host_to_connect; /* Connect to 'host'. */ 115 char *host_to_connect; /* Connect to 'host'. */
112 u_short port_to_connect; /* Connect to 'port'. */ 116 int port_to_connect; /* Connect to 'port'. */
113 u_short listen_port; /* Remote side should listen port number. */ 117 char *listen_host; /* Remote side should listen address. */
118 char *listen_path; /* Remote side should listen path. */
119 int listen_port; /* Remote side should listen port. */
114} ForwardPermission; 120} ForwardPermission;
115 121
116/* List of all permitted host/port pairs to connect by the user. */ 122/* List of all permitted host/port pairs to connect by the user. */
@@ -473,6 +479,8 @@ channel_stop_listening(void)
473 case SSH_CHANNEL_PORT_LISTENER: 479 case SSH_CHANNEL_PORT_LISTENER:
474 case SSH_CHANNEL_RPORT_LISTENER: 480 case SSH_CHANNEL_RPORT_LISTENER:
475 case SSH_CHANNEL_X11_LISTENER: 481 case SSH_CHANNEL_X11_LISTENER:
482 case SSH_CHANNEL_UNIX_LISTENER:
483 case SSH_CHANNEL_RUNIX_LISTENER:
476 channel_close_fd(&c->sock); 484 channel_close_fd(&c->sock);
477 channel_free(c); 485 channel_free(c);
478 break; 486 break;
@@ -535,6 +543,8 @@ channel_still_open(void)
535 case SSH_CHANNEL_CONNECTING: 543 case SSH_CHANNEL_CONNECTING:
536 case SSH_CHANNEL_ZOMBIE: 544 case SSH_CHANNEL_ZOMBIE:
537 case SSH_CHANNEL_ABANDONED: 545 case SSH_CHANNEL_ABANDONED:
546 case SSH_CHANNEL_UNIX_LISTENER:
547 case SSH_CHANNEL_RUNIX_LISTENER:
538 continue; 548 continue;
539 case SSH_CHANNEL_LARVAL: 549 case SSH_CHANNEL_LARVAL:
540 if (!compat20) 550 if (!compat20)
@@ -581,6 +591,8 @@ channel_find_open(void)
581 case SSH_CHANNEL_CONNECTING: 591 case SSH_CHANNEL_CONNECTING:
582 case SSH_CHANNEL_ZOMBIE: 592 case SSH_CHANNEL_ZOMBIE:
583 case SSH_CHANNEL_ABANDONED: 593 case SSH_CHANNEL_ABANDONED:
594 case SSH_CHANNEL_UNIX_LISTENER:
595 case SSH_CHANNEL_RUNIX_LISTENER:
584 continue; 596 continue;
585 case SSH_CHANNEL_LARVAL: 597 case SSH_CHANNEL_LARVAL:
586 case SSH_CHANNEL_AUTH_SOCKET: 598 case SSH_CHANNEL_AUTH_SOCKET:
@@ -631,6 +643,8 @@ channel_open_message(void)
631 case SSH_CHANNEL_ABANDONED: 643 case SSH_CHANNEL_ABANDONED:
632 case SSH_CHANNEL_MUX_CLIENT: 644 case SSH_CHANNEL_MUX_CLIENT:
633 case SSH_CHANNEL_MUX_LISTENER: 645 case SSH_CHANNEL_MUX_LISTENER:
646 case SSH_CHANNEL_UNIX_LISTENER:
647 case SSH_CHANNEL_RUNIX_LISTENER:
634 continue; 648 continue;
635 case SSH_CHANNEL_LARVAL: 649 case SSH_CHANNEL_LARVAL:
636 case SSH_CHANNEL_OPENING: 650 case SSH_CHANNEL_OPENING:
@@ -1386,7 +1400,6 @@ channel_post_x11_listener(Channel *c, fd_set *readset, fd_set *writeset)
1386static void 1400static void
1387port_open_helper(Channel *c, char *rtype) 1401port_open_helper(Channel *c, char *rtype)
1388{ 1402{
1389 int direct;
1390 char buf[1024]; 1403 char buf[1024];
1391 char *local_ipaddr = get_local_ipaddr(c->sock); 1404 char *local_ipaddr = get_local_ipaddr(c->sock);
1392 int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1); 1405 int local_port = c->sock == -1 ? 65536 : get_sock_port(c->sock, 1);
@@ -1400,8 +1413,6 @@ port_open_helper(Channel *c, char *rtype)
1400 remote_port = 65535; 1413 remote_port = 65535;
1401 } 1414 }
1402 1415
1403 direct = (strcmp(rtype, "direct-tcpip") == 0);
1404
1405 snprintf(buf, sizeof buf, 1416 snprintf(buf, sizeof buf,
1406 "%s: listening port %d for %.100s port %d, " 1417 "%s: listening port %d for %.100s port %d, "
1407 "connect from %.200s port %d to %.100s port %d", 1418 "connect from %.200s port %d to %.100s port %d",
@@ -1417,18 +1428,29 @@ port_open_helper(Channel *c, char *rtype)
1417 packet_put_int(c->self); 1428 packet_put_int(c->self);
1418 packet_put_int(c->local_window_max); 1429 packet_put_int(c->local_window_max);
1419 packet_put_int(c->local_maxpacket); 1430 packet_put_int(c->local_maxpacket);
1420 if (direct) { 1431 if (strcmp(rtype, "direct-tcpip") == 0) {
1421 /* target host, port */ 1432 /* target host, port */
1422 packet_put_cstring(c->path); 1433 packet_put_cstring(c->path);
1423 packet_put_int(c->host_port); 1434 packet_put_int(c->host_port);
1435 } else if (strcmp(rtype, "direct-streamlocal@openssh.com") == 0) {
1436 /* target path */
1437 packet_put_cstring(c->path);
1438 } else if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1439 /* listen path */
1440 packet_put_cstring(c->path);
1424 } else { 1441 } else {
1425 /* listen address, port */ 1442 /* listen address, port */
1426 packet_put_cstring(c->path); 1443 packet_put_cstring(c->path);
1427 packet_put_int(local_port); 1444 packet_put_int(local_port);
1428 } 1445 }
1429 /* originator host and port */ 1446 if (strcmp(rtype, "forwarded-streamlocal@openssh.com") == 0) {
1430 packet_put_cstring(remote_ipaddr); 1447 /* reserved for future owner/mode info */
1431 packet_put_int((u_int)remote_port); 1448 packet_put_cstring("");
1449 } else {
1450 /* originator host and port */
1451 packet_put_cstring(remote_ipaddr);
1452 packet_put_int((u_int)remote_port);
1453 }
1432 packet_send(); 1454 packet_send();
1433 } else { 1455 } else {
1434 packet_start(SSH_MSG_PORT_OPEN); 1456 packet_start(SSH_MSG_PORT_OPEN);
@@ -1478,14 +1500,18 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1478 if (c->type == SSH_CHANNEL_RPORT_LISTENER) { 1500 if (c->type == SSH_CHANNEL_RPORT_LISTENER) {
1479 nextstate = SSH_CHANNEL_OPENING; 1501 nextstate = SSH_CHANNEL_OPENING;
1480 rtype = "forwarded-tcpip"; 1502 rtype = "forwarded-tcpip";
1503 } else if (c->type == SSH_CHANNEL_RUNIX_LISTENER) {
1504 nextstate = SSH_CHANNEL_OPENING;
1505 rtype = "forwarded-streamlocal@openssh.com";
1506 } else if (c->host_port == PORT_STREAMLOCAL) {
1507 nextstate = SSH_CHANNEL_OPENING;
1508 rtype = "direct-streamlocal@openssh.com";
1509 } else if (c->host_port == 0) {
1510 nextstate = SSH_CHANNEL_DYNAMIC;
1511 rtype = "dynamic-tcpip";
1481 } else { 1512 } else {
1482 if (c->host_port == 0) { 1513 nextstate = SSH_CHANNEL_OPENING;
1483 nextstate = SSH_CHANNEL_DYNAMIC; 1514 rtype = "direct-tcpip";
1484 rtype = "dynamic-tcpip";
1485 } else {
1486 nextstate = SSH_CHANNEL_OPENING;
1487 rtype = "direct-tcpip";
1488 }
1489 } 1515 }
1490 1516
1491 addrlen = sizeof(addr); 1517 addrlen = sizeof(addr);
@@ -1498,7 +1524,8 @@ channel_post_port_listener(Channel *c, fd_set *readset, fd_set *writeset)
1498 c->notbefore = monotime() + 1; 1524 c->notbefore = monotime() + 1;
1499 return; 1525 return;
1500 } 1526 }
1501 set_nodelay(newsock); 1527 if (c->host_port != PORT_STREAMLOCAL)
1528 set_nodelay(newsock);
1502 nc = channel_new(rtype, nextstate, newsock, newsock, -1, 1529 nc = channel_new(rtype, nextstate, newsock, newsock, -1,
1503 c->local_window_max, c->local_maxpacket, 0, rtype, 1); 1530 c->local_window_max, c->local_maxpacket, 0, rtype, 1);
1504 nc->listening_port = c->listening_port; 1531 nc->listening_port = c->listening_port;
@@ -1987,6 +2014,8 @@ channel_handler_init_20(void)
1987 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open; 2014 channel_pre[SSH_CHANNEL_X11_OPEN] = &channel_pre_x11_open;
1988 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener; 2015 channel_pre[SSH_CHANNEL_PORT_LISTENER] = &channel_pre_listener;
1989 channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener; 2016 channel_pre[SSH_CHANNEL_RPORT_LISTENER] = &channel_pre_listener;
2017 channel_pre[SSH_CHANNEL_UNIX_LISTENER] = &channel_pre_listener;
2018 channel_pre[SSH_CHANNEL_RUNIX_LISTENER] = &channel_pre_listener;
1990 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener; 2019 channel_pre[SSH_CHANNEL_X11_LISTENER] = &channel_pre_listener;
1991 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener; 2020 channel_pre[SSH_CHANNEL_AUTH_SOCKET] = &channel_pre_listener;
1992 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting; 2021 channel_pre[SSH_CHANNEL_CONNECTING] = &channel_pre_connecting;
@@ -1997,6 +2026,8 @@ channel_handler_init_20(void)
1997 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open; 2026 channel_post[SSH_CHANNEL_OPEN] = &channel_post_open;
1998 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener; 2027 channel_post[SSH_CHANNEL_PORT_LISTENER] = &channel_post_port_listener;
1999 channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener; 2028 channel_post[SSH_CHANNEL_RPORT_LISTENER] = &channel_post_port_listener;
2029 channel_post[SSH_CHANNEL_UNIX_LISTENER] = &channel_post_port_listener;
2030 channel_post[SSH_CHANNEL_RUNIX_LISTENER] = &channel_post_port_listener;
2000 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener; 2031 channel_post[SSH_CHANNEL_X11_LISTENER] = &channel_post_x11_listener;
2001 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener; 2032 channel_post[SSH_CHANNEL_AUTH_SOCKET] = &channel_post_auth_listener;
2002 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting; 2033 channel_post[SSH_CHANNEL_CONNECTING] = &channel_post_connecting;
@@ -2315,7 +2346,7 @@ void
2315channel_input_data(int type, u_int32_t seq, void *ctxt) 2346channel_input_data(int type, u_int32_t seq, void *ctxt)
2316{ 2347{
2317 int id; 2348 int id;
2318 char *data; 2349 const u_char *data;
2319 u_int data_len, win_len; 2350 u_int data_len, win_len;
2320 Channel *c; 2351 Channel *c;
2321 2352
@@ -2637,7 +2668,7 @@ channel_input_port_open(int type, u_int32_t seq, void *ctxt)
2637 originator_string = xstrdup("unknown (remote did not supply name)"); 2668 originator_string = xstrdup("unknown (remote did not supply name)");
2638 } 2669 }
2639 packet_check_eom(); 2670 packet_check_eom();
2640 c = channel_connect_to(host, host_port, 2671 c = channel_connect_to_port(host, host_port,
2641 "connected socket", originator_string); 2672 "connected socket", originator_string);
2642 free(originator_string); 2673 free(originator_string);
2643 free(host); 2674 free(host);
@@ -2700,23 +2731,24 @@ channel_set_af(int af)
2700 * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR 2731 * "0.0.0.0" -> wildcard v4/v6 if SSH_OLD_FORWARD_ADDR
2701 * "" (empty string), "*" -> wildcard v4/v6 2732 * "" (empty string), "*" -> wildcard v4/v6
2702 * "localhost" -> loopback v4/v6 2733 * "localhost" -> loopback v4/v6
2734 * "127.0.0.1" / "::1" -> accepted even if gateway_ports isn't set
2703 */ 2735 */
2704static const char * 2736static const char *
2705channel_fwd_bind_addr(const char *listen_addr, int *wildcardp, 2737channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2706 int is_client, int gateway_ports) 2738 int is_client, struct ForwardOptions *fwd_opts)
2707{ 2739{
2708 const char *addr = NULL; 2740 const char *addr = NULL;
2709 int wildcard = 0; 2741 int wildcard = 0;
2710 2742
2711 if (listen_addr == NULL) { 2743 if (listen_addr == NULL) {
2712 /* No address specified: default to gateway_ports setting */ 2744 /* No address specified: default to gateway_ports setting */
2713 if (gateway_ports) 2745 if (fwd_opts->gateway_ports)
2714 wildcard = 1; 2746 wildcard = 1;
2715 } else if (gateway_ports || is_client) { 2747 } else if (fwd_opts->gateway_ports || is_client) {
2716 if (((datafellows & SSH_OLD_FORWARD_ADDR) && 2748 if (((datafellows & SSH_OLD_FORWARD_ADDR) &&
2717 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) || 2749 strcmp(listen_addr, "0.0.0.0") == 0 && is_client == 0) ||
2718 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 || 2750 *listen_addr == '\0' || strcmp(listen_addr, "*") == 0 ||
2719 (!is_client && gateway_ports == 1)) { 2751 (!is_client && fwd_opts->gateway_ports == 1)) {
2720 wildcard = 1; 2752 wildcard = 1;
2721 /* 2753 /*
2722 * Notify client if they requested a specific listen 2754 * Notify client if they requested a specific listen
@@ -2729,9 +2761,20 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2729 "\"%s\" overridden by server " 2761 "\"%s\" overridden by server "
2730 "GatewayPorts", listen_addr); 2762 "GatewayPorts", listen_addr);
2731 } 2763 }
2732 } 2764 } else if (strcmp(listen_addr, "localhost") != 0 ||
2733 else if (strcmp(listen_addr, "localhost") != 0) 2765 strcmp(listen_addr, "127.0.0.1") == 0 ||
2766 strcmp(listen_addr, "::1") == 0) {
2767 /* Accept localhost address when GatewayPorts=yes */
2734 addr = listen_addr; 2768 addr = listen_addr;
2769 }
2770 } else if (strcmp(listen_addr, "127.0.0.1") == 0 ||
2771 strcmp(listen_addr, "::1") == 0) {
2772 /*
2773 * If a specific IPv4/IPv6 localhost address has been
2774 * requested then accept it even if gateway_ports is in
2775 * effect. This allows the client to prefer IPv4 or IPv6.
2776 */
2777 addr = listen_addr;
2735 } 2778 }
2736 if (wildcardp != NULL) 2779 if (wildcardp != NULL)
2737 *wildcardp = wildcard; 2780 *wildcardp = wildcard;
@@ -2739,9 +2782,8 @@ channel_fwd_bind_addr(const char *listen_addr, int *wildcardp,
2739} 2782}
2740 2783
2741static int 2784static int
2742channel_setup_fwd_listener(int type, const char *listen_addr, 2785channel_setup_fwd_listener_tcpip(int type, struct Forward *fwd,
2743 u_short listen_port, int *allocated_listen_port, 2786 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
2744 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2745{ 2787{
2746 Channel *c; 2788 Channel *c;
2747 int sock, r, success = 0, wildcard = 0, is_client; 2789 int sock, r, success = 0, wildcard = 0, is_client;
@@ -2751,7 +2793,7 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2751 in_port_t *lport_p; 2793 in_port_t *lport_p;
2752 2794
2753 host = (type == SSH_CHANNEL_RPORT_LISTENER) ? 2795 host = (type == SSH_CHANNEL_RPORT_LISTENER) ?
2754 listen_addr : host_to_connect; 2796 fwd->listen_host : fwd->connect_host;
2755 is_client = (type == SSH_CHANNEL_PORT_LISTENER); 2797 is_client = (type == SSH_CHANNEL_PORT_LISTENER);
2756 2798
2757 if (host == NULL) { 2799 if (host == NULL) {
@@ -2764,9 +2806,9 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2764 } 2806 }
2765 2807
2766 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */ 2808 /* Determine the bind address, cf. channel_fwd_bind_addr() comment */
2767 addr = channel_fwd_bind_addr(listen_addr, &wildcard, 2809 addr = channel_fwd_bind_addr(fwd->listen_host, &wildcard,
2768 is_client, gateway_ports); 2810 is_client, fwd_opts);
2769 debug3("channel_setup_fwd_listener: type %d wildcard %d addr %s", 2811 debug3("%s: type %d wildcard %d addr %s", __func__,
2770 type, wildcard, (addr == NULL) ? "NULL" : addr); 2812 type, wildcard, (addr == NULL) ? "NULL" : addr);
2771 2813
2772 /* 2814 /*
@@ -2777,15 +2819,14 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2777 hints.ai_family = IPv4or6; 2819 hints.ai_family = IPv4or6;
2778 hints.ai_flags = wildcard ? AI_PASSIVE : 0; 2820 hints.ai_flags = wildcard ? AI_PASSIVE : 0;
2779 hints.ai_socktype = SOCK_STREAM; 2821 hints.ai_socktype = SOCK_STREAM;
2780 snprintf(strport, sizeof strport, "%d", listen_port); 2822 snprintf(strport, sizeof strport, "%d", fwd->listen_port);
2781 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) { 2823 if ((r = getaddrinfo(addr, strport, &hints, &aitop)) != 0) {
2782 if (addr == NULL) { 2824 if (addr == NULL) {
2783 /* This really shouldn't happen */ 2825 /* This really shouldn't happen */
2784 packet_disconnect("getaddrinfo: fatal error: %s", 2826 packet_disconnect("getaddrinfo: fatal error: %s",
2785 ssh_gai_strerror(r)); 2827 ssh_gai_strerror(r));
2786 } else { 2828 } else {
2787 error("channel_setup_fwd_listener: " 2829 error("%s: getaddrinfo(%.64s): %s", __func__, addr,
2788 "getaddrinfo(%.64s): %s", addr,
2789 ssh_gai_strerror(r)); 2830 ssh_gai_strerror(r));
2790 } 2831 }
2791 return 0; 2832 return 0;
@@ -2809,13 +2850,13 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2809 * If allocating a port for -R forwards, then use the 2850 * If allocating a port for -R forwards, then use the
2810 * same port for all address families. 2851 * same port for all address families.
2811 */ 2852 */
2812 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && 2853 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
2813 allocated_listen_port != NULL && *allocated_listen_port > 0) 2854 allocated_listen_port != NULL && *allocated_listen_port > 0)
2814 *lport_p = htons(*allocated_listen_port); 2855 *lport_p = htons(*allocated_listen_port);
2815 2856
2816 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop), 2857 if (getnameinfo(ai->ai_addr, ai->ai_addrlen, ntop, sizeof(ntop),
2817 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 2858 strport, sizeof(strport), NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
2818 error("channel_setup_fwd_listener: getnameinfo failed"); 2859 error("%s: getnameinfo failed", __func__);
2819 continue; 2860 continue;
2820 } 2861 }
2821 /* Create a port to listen for the host. */ 2862 /* Create a port to listen for the host. */
@@ -2852,10 +2893,10 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2852 } 2893 }
2853 2894
2854 /* 2895 /*
2855 * listen_port == 0 requests a dynamically allocated port - 2896 * fwd->listen_port == 0 requests a dynamically allocated port -
2856 * record what we got. 2897 * record what we got.
2857 */ 2898 */
2858 if (type == SSH_CHANNEL_RPORT_LISTENER && listen_port == 0 && 2899 if (type == SSH_CHANNEL_RPORT_LISTENER && fwd->listen_port == 0 &&
2859 allocated_listen_port != NULL && 2900 allocated_listen_port != NULL &&
2860 *allocated_listen_port == 0) { 2901 *allocated_listen_port == 0) {
2861 *allocated_listen_port = get_sock_port(sock, 1); 2902 *allocated_listen_port = get_sock_port(sock, 1);
@@ -2868,24 +2909,98 @@ channel_setup_fwd_listener(int type, const char *listen_addr,
2868 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT, 2909 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2869 0, "port listener", 1); 2910 0, "port listener", 1);
2870 c->path = xstrdup(host); 2911 c->path = xstrdup(host);
2871 c->host_port = port_to_connect; 2912 c->host_port = fwd->connect_port;
2872 c->listening_addr = addr == NULL ? NULL : xstrdup(addr); 2913 c->listening_addr = addr == NULL ? NULL : xstrdup(addr);
2873 if (listen_port == 0 && allocated_listen_port != NULL && 2914 if (fwd->listen_port == 0 && allocated_listen_port != NULL &&
2874 !(datafellows & SSH_BUG_DYNAMIC_RPORT)) 2915 !(datafellows & SSH_BUG_DYNAMIC_RPORT))
2875 c->listening_port = *allocated_listen_port; 2916 c->listening_port = *allocated_listen_port;
2876 else 2917 else
2877 c->listening_port = listen_port; 2918 c->listening_port = fwd->listen_port;
2878 success = 1; 2919 success = 1;
2879 } 2920 }
2880 if (success == 0) 2921 if (success == 0)
2881 error("channel_setup_fwd_listener: cannot listen to port: %d", 2922 error("%s: cannot listen to port: %d", __func__,
2882 listen_port); 2923 fwd->listen_port);
2883 freeaddrinfo(aitop); 2924 freeaddrinfo(aitop);
2884 return success; 2925 return success;
2885} 2926}
2886 2927
2887int 2928static int
2888channel_cancel_rport_listener(const char *host, u_short port) 2929channel_setup_fwd_listener_streamlocal(int type, struct Forward *fwd,
2930 struct ForwardOptions *fwd_opts)
2931{
2932 struct sockaddr_un sunaddr;
2933 const char *path;
2934 Channel *c;
2935 int port, sock;
2936 mode_t omask;
2937
2938 switch (type) {
2939 case SSH_CHANNEL_UNIX_LISTENER:
2940 if (fwd->connect_path != NULL) {
2941 if (strlen(fwd->connect_path) > sizeof(sunaddr.sun_path)) {
2942 error("Local connecting path too long: %s",
2943 fwd->connect_path);
2944 return 0;
2945 }
2946 path = fwd->connect_path;
2947 port = PORT_STREAMLOCAL;
2948 } else {
2949 if (fwd->connect_host == NULL) {
2950 error("No forward host name.");
2951 return 0;
2952 }
2953 if (strlen(fwd->connect_host) >= NI_MAXHOST) {
2954 error("Forward host name too long.");
2955 return 0;
2956 }
2957 path = fwd->connect_host;
2958 port = fwd->connect_port;
2959 }
2960 break;
2961 case SSH_CHANNEL_RUNIX_LISTENER:
2962 path = fwd->listen_path;
2963 port = PORT_STREAMLOCAL;
2964 break;
2965 default:
2966 error("%s: unexpected channel type %d", __func__, type);
2967 return 0;
2968 }
2969
2970 if (fwd->listen_path == NULL) {
2971 error("No forward path name.");
2972 return 0;
2973 }
2974 if (strlen(fwd->listen_path) > sizeof(sunaddr.sun_path)) {
2975 error("Local listening path too long: %s", fwd->listen_path);
2976 return 0;
2977 }
2978
2979 debug3("%s: type %d path %s", __func__, type, fwd->listen_path);
2980
2981 /* Start a Unix domain listener. */
2982 omask = umask(fwd_opts->streamlocal_bind_mask);
2983 sock = unix_listener(fwd->listen_path, SSH_LISTEN_BACKLOG,
2984 fwd_opts->streamlocal_bind_unlink);
2985 umask(omask);
2986 if (sock < 0)
2987 return 0;
2988
2989 debug("Local forwarding listening on path %s.", fwd->listen_path);
2990
2991 /* Allocate a channel number for the socket. */
2992 c = channel_new("unix listener", type, sock, sock, -1,
2993 CHAN_TCP_WINDOW_DEFAULT, CHAN_TCP_PACKET_DEFAULT,
2994 0, "unix listener", 1);
2995 c->path = xstrdup(path);
2996 c->host_port = port;
2997 c->listening_port = PORT_STREAMLOCAL;
2998 c->listening_addr = xstrdup(fwd->listen_path);
2999 return 1;
3000}
3001
3002static int
3003channel_cancel_rport_listener_tcpip(const char *host, u_short port)
2889{ 3004{
2890 u_int i; 3005 u_int i;
2891 int found = 0; 3006 int found = 0;
@@ -2904,13 +3019,44 @@ channel_cancel_rport_listener(const char *host, u_short port)
2904 return (found); 3019 return (found);
2905} 3020}
2906 3021
3022static int
3023channel_cancel_rport_listener_streamlocal(const char *path)
3024{
3025 u_int i;
3026 int found = 0;
3027
3028 for (i = 0; i < channels_alloc; i++) {
3029 Channel *c = channels[i];
3030 if (c == NULL || c->type != SSH_CHANNEL_RUNIX_LISTENER)
3031 continue;
3032 if (c->path == NULL)
3033 continue;
3034 if (strcmp(c->path, path) == 0) {
3035 debug2("%s: close channel %d", __func__, i);
3036 channel_free(c);
3037 found = 1;
3038 }
3039 }
3040
3041 return (found);
3042}
3043
2907int 3044int
2908channel_cancel_lport_listener(const char *lhost, u_short lport, 3045channel_cancel_rport_listener(struct Forward *fwd)
2909 int cport, int gateway_ports) 3046{
3047 if (fwd->listen_path != NULL)
3048 return channel_cancel_rport_listener_streamlocal(fwd->listen_path);
3049 else
3050 return channel_cancel_rport_listener_tcpip(fwd->listen_host, fwd->listen_port);
3051}
3052
3053static int
3054channel_cancel_lport_listener_tcpip(const char *lhost, u_short lport,
3055 int cport, struct ForwardOptions *fwd_opts)
2910{ 3056{
2911 u_int i; 3057 u_int i;
2912 int found = 0; 3058 int found = 0;
2913 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, gateway_ports); 3059 const char *addr = channel_fwd_bind_addr(lhost, NULL, 1, fwd_opts);
2914 3060
2915 for (i = 0; i < channels_alloc; i++) { 3061 for (i = 0; i < channels_alloc; i++) {
2916 Channel *c = channels[i]; 3062 Channel *c = channels[i];
@@ -2939,24 +3085,68 @@ channel_cancel_lport_listener(const char *lhost, u_short lport,
2939 return (found); 3085 return (found);
2940} 3086}
2941 3087
3088static int
3089channel_cancel_lport_listener_streamlocal(const char *path)
3090{
3091 u_int i;
3092 int found = 0;
3093
3094 if (path == NULL) {
3095 error("%s: no path specified.", __func__);
3096 return 0;
3097 }
3098
3099 for (i = 0; i < channels_alloc; i++) {
3100 Channel *c = channels[i];
3101 if (c == NULL || c->type != SSH_CHANNEL_UNIX_LISTENER)
3102 continue;
3103 if (c->listening_addr == NULL)
3104 continue;
3105 if (strcmp(c->listening_addr, path) == 0) {
3106 debug2("%s: close channel %d", __func__, i);
3107 channel_free(c);
3108 found = 1;
3109 }
3110 }
3111
3112 return (found);
3113}
3114
3115int
3116channel_cancel_lport_listener(struct Forward *fwd, int cport, struct ForwardOptions *fwd_opts)
3117{
3118 if (fwd->listen_path != NULL)
3119 return channel_cancel_lport_listener_streamlocal(fwd->listen_path);
3120 else
3121 return channel_cancel_lport_listener_tcpip(fwd->listen_host, fwd->listen_port, cport, fwd_opts);
3122}
3123
2942/* protocol local port fwd, used by ssh (and sshd in v1) */ 3124/* protocol local port fwd, used by ssh (and sshd in v1) */
2943int 3125int
2944channel_setup_local_fwd_listener(const char *listen_host, u_short listen_port, 3126channel_setup_local_fwd_listener(struct Forward *fwd, struct ForwardOptions *fwd_opts)
2945 const char *host_to_connect, u_short port_to_connect, int gateway_ports)
2946{ 3127{
2947 return channel_setup_fwd_listener(SSH_CHANNEL_PORT_LISTENER, 3128 if (fwd->listen_path != NULL) {
2948 listen_host, listen_port, NULL, host_to_connect, port_to_connect, 3129 return channel_setup_fwd_listener_streamlocal(
2949 gateway_ports); 3130 SSH_CHANNEL_UNIX_LISTENER, fwd, fwd_opts);
3131 } else {
3132 return channel_setup_fwd_listener_tcpip(SSH_CHANNEL_PORT_LISTENER,
3133 fwd, NULL, fwd_opts);
3134 }
2950} 3135}
2951 3136
2952/* protocol v2 remote port fwd, used by sshd */ 3137/* protocol v2 remote port fwd, used by sshd */
2953int 3138int
2954channel_setup_remote_fwd_listener(const char *listen_address, 3139channel_setup_remote_fwd_listener(struct Forward *fwd,
2955 u_short listen_port, int *allocated_listen_port, int gateway_ports) 3140 int *allocated_listen_port, struct ForwardOptions *fwd_opts)
2956{ 3141{
2957 return channel_setup_fwd_listener(SSH_CHANNEL_RPORT_LISTENER, 3142 if (fwd->listen_path != NULL) {
2958 listen_address, listen_port, allocated_listen_port, 3143 return channel_setup_fwd_listener_streamlocal(
2959 NULL, 0, gateway_ports); 3144 SSH_CHANNEL_RUNIX_LISTENER, fwd, fwd_opts);
3145 } else {
3146 return channel_setup_fwd_listener_tcpip(
3147 SSH_CHANNEL_RPORT_LISTENER, fwd, allocated_listen_port,
3148 fwd_opts);
3149 }
2960} 3150}
2961 3151
2962/* 3152/*
@@ -2987,27 +3177,32 @@ channel_rfwd_bind_host(const char *listen_host)
2987 * channel_update_permitted_opens(). 3177 * channel_update_permitted_opens().
2988 */ 3178 */
2989int 3179int
2990channel_request_remote_forwarding(const char *listen_host, u_short listen_port, 3180channel_request_remote_forwarding(struct Forward *fwd)
2991 const char *host_to_connect, u_short port_to_connect)
2992{ 3181{
2993 int type, success = 0, idx = -1; 3182 int type, success = 0, idx = -1;
2994 3183
2995 /* Send the forward request to the remote side. */ 3184 /* Send the forward request to the remote side. */
2996 if (compat20) { 3185 if (compat20) {
2997 packet_start(SSH2_MSG_GLOBAL_REQUEST); 3186 packet_start(SSH2_MSG_GLOBAL_REQUEST);
2998 packet_put_cstring("tcpip-forward"); 3187 if (fwd->listen_path != NULL) {
2999 packet_put_char(1); /* boolean: want reply */ 3188 packet_put_cstring("streamlocal-forward@openssh.com");
3000 packet_put_cstring(channel_rfwd_bind_host(listen_host)); 3189 packet_put_char(1); /* boolean: want reply */
3001 packet_put_int(listen_port); 3190 packet_put_cstring(fwd->listen_path);
3191 } else {
3192 packet_put_cstring("tcpip-forward");
3193 packet_put_char(1); /* boolean: want reply */
3194 packet_put_cstring(channel_rfwd_bind_host(fwd->listen_host));
3195 packet_put_int(fwd->listen_port);
3196 }
3002 packet_send(); 3197 packet_send();
3003 packet_write_wait(); 3198 packet_write_wait();
3004 /* Assume that server accepts the request */ 3199 /* Assume that server accepts the request */
3005 success = 1; 3200 success = 1;
3006 } else { 3201 } else if (fwd->listen_path == NULL) {
3007 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST); 3202 packet_start(SSH_CMSG_PORT_FORWARD_REQUEST);
3008 packet_put_int(listen_port); 3203 packet_put_int(fwd->listen_port);
3009 packet_put_cstring(host_to_connect); 3204 packet_put_cstring(fwd->connect_host);
3010 packet_put_int(port_to_connect); 3205 packet_put_int(fwd->connect_port);
3011 packet_send(); 3206 packet_send();
3012 packet_write_wait(); 3207 packet_write_wait();
3013 3208
@@ -3024,25 +3219,102 @@ channel_request_remote_forwarding(const char *listen_host, u_short listen_port,
3024 packet_disconnect("Protocol error for port forward request:" 3219 packet_disconnect("Protocol error for port forward request:"
3025 "received packet type %d.", type); 3220 "received packet type %d.", type);
3026 } 3221 }
3222 } else {
3223 logit("Warning: Server does not support remote stream local forwarding.");
3027 } 3224 }
3028 if (success) { 3225 if (success) {
3029 /* Record that connection to this host/port is permitted. */ 3226 /* Record that connection to this host/port is permitted. */
3030 permitted_opens = xrealloc(permitted_opens, 3227 permitted_opens = xrealloc(permitted_opens,
3031 num_permitted_opens + 1, sizeof(*permitted_opens)); 3228 num_permitted_opens + 1, sizeof(*permitted_opens));
3032 idx = num_permitted_opens++; 3229 idx = num_permitted_opens++;
3033 permitted_opens[idx].host_to_connect = xstrdup(host_to_connect); 3230 if (fwd->connect_path != NULL) {
3034 permitted_opens[idx].port_to_connect = port_to_connect; 3231 permitted_opens[idx].host_to_connect =
3035 permitted_opens[idx].listen_port = listen_port; 3232 xstrdup(fwd->connect_path);
3233 permitted_opens[idx].port_to_connect =
3234 PORT_STREAMLOCAL;
3235 } else {
3236 permitted_opens[idx].host_to_connect =
3237 xstrdup(fwd->connect_host);
3238 permitted_opens[idx].port_to_connect =
3239 fwd->connect_port;
3240 }
3241 if (fwd->listen_path != NULL) {
3242 permitted_opens[idx].listen_host = NULL;
3243 permitted_opens[idx].listen_path =
3244 xstrdup(fwd->listen_path);
3245 permitted_opens[idx].listen_port = PORT_STREAMLOCAL;
3246 } else {
3247 permitted_opens[idx].listen_host =
3248 fwd->listen_host ? xstrdup(fwd->listen_host) : NULL;
3249 permitted_opens[idx].listen_path = NULL;
3250 permitted_opens[idx].listen_port = fwd->listen_port;
3251 }
3036 } 3252 }
3037 return (idx); 3253 return (idx);
3038} 3254}
3039 3255
3256static int
3257open_match(ForwardPermission *allowed_open, const char *requestedhost,
3258 int requestedport)
3259{
3260 if (allowed_open->host_to_connect == NULL)
3261 return 0;
3262 if (allowed_open->port_to_connect != FWD_PERMIT_ANY_PORT &&
3263 allowed_open->port_to_connect != requestedport)
3264 return 0;
3265 if (strcmp(allowed_open->host_to_connect, requestedhost) != 0)
3266 return 0;
3267 return 1;
3268}
3269
3270/*
3271 * Note that in the listen host/port case
3272 * we don't support FWD_PERMIT_ANY_PORT and
3273 * need to translate between the configured-host (listen_host)
3274 * and what we've sent to the remote server (channel_rfwd_bind_host)
3275 */
3276static int
3277open_listen_match_tcpip(ForwardPermission *allowed_open,
3278 const char *requestedhost, u_short requestedport, int translate)
3279{
3280 const char *allowed_host;
3281
3282 if (allowed_open->host_to_connect == NULL)
3283 return 0;
3284 if (allowed_open->listen_port != requestedport)
3285 return 0;
3286 if (!translate && allowed_open->listen_host == NULL &&
3287 requestedhost == NULL)
3288 return 1;
3289 allowed_host = translate ?
3290 channel_rfwd_bind_host(allowed_open->listen_host) :
3291 allowed_open->listen_host;
3292 if (allowed_host == NULL ||
3293 strcmp(allowed_host, requestedhost) != 0)
3294 return 0;
3295 return 1;
3296}
3297
3298static int
3299open_listen_match_streamlocal(ForwardPermission *allowed_open,
3300 const char *requestedpath)
3301{
3302 if (allowed_open->host_to_connect == NULL)
3303 return 0;
3304 if (allowed_open->listen_port != PORT_STREAMLOCAL)
3305 return 0;
3306 if (allowed_open->listen_path == NULL ||
3307 strcmp(allowed_open->listen_path, requestedpath) != 0)
3308 return 0;
3309 return 1;
3310}
3311
3040/* 3312/*
3041 * Request cancellation of remote forwarding of connection host:port from 3313 * Request cancellation of remote forwarding of connection host:port from
3042 * local side. 3314 * local side.
3043 */ 3315 */
3044int 3316static int
3045channel_request_rforward_cancel(const char *host, u_short port) 3317channel_request_rforward_cancel_tcpip(const char *host, u_short port)
3046{ 3318{
3047 int i; 3319 int i;
3048 3320
@@ -3050,8 +3322,7 @@ channel_request_rforward_cancel(const char *host, u_short port)
3050 return -1; 3322 return -1;
3051 3323
3052 for (i = 0; i < num_permitted_opens; i++) { 3324 for (i = 0; i < num_permitted_opens; i++) {
3053 if (permitted_opens[i].host_to_connect != NULL && 3325 if (open_listen_match_tcpip(&permitted_opens[i], host, port, 0))
3054 permitted_opens[i].listen_port == port)
3055 break; 3326 break;
3056 } 3327 }
3057 if (i >= num_permitted_opens) { 3328 if (i >= num_permitted_opens) {
@@ -3069,9 +3340,64 @@ channel_request_rforward_cancel(const char *host, u_short port)
3069 permitted_opens[i].port_to_connect = 0; 3340 permitted_opens[i].port_to_connect = 0;
3070 free(permitted_opens[i].host_to_connect); 3341 free(permitted_opens[i].host_to_connect);
3071 permitted_opens[i].host_to_connect = NULL; 3342 permitted_opens[i].host_to_connect = NULL;
3343 free(permitted_opens[i].listen_host);
3344 permitted_opens[i].listen_host = NULL;
3345 permitted_opens[i].listen_path = NULL;
3346
3347 return 0;
3348}
3349
3350/*
3351 * Request cancellation of remote forwarding of Unix domain socket
3352 * path from local side.
3353 */
3354static int
3355channel_request_rforward_cancel_streamlocal(const char *path)
3356{
3357 int i;
3358
3359 if (!compat20)
3360 return -1;
3361
3362 for (i = 0; i < num_permitted_opens; i++) {
3363 if (open_listen_match_streamlocal(&permitted_opens[i], path))
3364 break;
3365 }
3366 if (i >= num_permitted_opens) {
3367 debug("%s: requested forward not found", __func__);
3368 return -1;
3369 }
3370 packet_start(SSH2_MSG_GLOBAL_REQUEST);
3371 packet_put_cstring("cancel-streamlocal-forward@openssh.com");
3372 packet_put_char(0);
3373 packet_put_cstring(path);
3374 packet_send();
3375
3376 permitted_opens[i].listen_port = 0;
3377 permitted_opens[i].port_to_connect = 0;
3378 free(permitted_opens[i].host_to_connect);
3379 permitted_opens[i].host_to_connect = NULL;
3380 permitted_opens[i].listen_host = NULL;
3381 free(permitted_opens[i].listen_path);
3382 permitted_opens[i].listen_path = NULL;
3072 3383
3073 return 0; 3384 return 0;
3074} 3385}
3386
3387/*
3388 * Request cancellation of remote forwarding of a connection from local side.
3389 */
3390int
3391channel_request_rforward_cancel(struct Forward *fwd)
3392{
3393 if (fwd->listen_path != NULL) {
3394 return (channel_request_rforward_cancel_streamlocal(
3395 fwd->listen_path));
3396 } else {
3397 return (channel_request_rforward_cancel_tcpip(fwd->listen_host,
3398 fwd->listen_port ? fwd->listen_port : fwd->allocated_port));
3399 }
3400}
3075 3401
3076/* 3402/*
3077 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates 3403 * This is called after receiving CHANNEL_FORWARDING_REQUEST. This initates
@@ -3079,36 +3405,35 @@ channel_request_rforward_cancel(const char *host, u_short port)
3079 * message if there was an error). 3405 * message if there was an error).
3080 */ 3406 */
3081int 3407int
3082channel_input_port_forward_request(int is_root, int gateway_ports) 3408channel_input_port_forward_request(int is_root, struct ForwardOptions *fwd_opts)
3083{ 3409{
3084 u_short port, host_port;
3085 int success = 0; 3410 int success = 0;
3086 char *hostname; 3411 struct Forward fwd;
3087 3412
3088 /* Get arguments from the packet. */ 3413 /* Get arguments from the packet. */
3089 port = packet_get_int(); 3414 memset(&fwd, 0, sizeof(fwd));
3090 hostname = packet_get_string(NULL); 3415 fwd.listen_port = packet_get_int();
3091 host_port = packet_get_int(); 3416 fwd.connect_host = packet_get_string(NULL);
3417 fwd.connect_port = packet_get_int();
3092 3418
3093#ifndef HAVE_CYGWIN 3419#ifndef HAVE_CYGWIN
3094 /* 3420 /*
3095 * Check that an unprivileged user is not trying to forward a 3421 * Check that an unprivileged user is not trying to forward a
3096 * privileged port. 3422 * privileged port.
3097 */ 3423 */
3098 if (port < IPPORT_RESERVED && !is_root) 3424 if (fwd.listen_port < IPPORT_RESERVED && !is_root)
3099 packet_disconnect( 3425 packet_disconnect(
3100 "Requested forwarding of port %d but user is not root.", 3426 "Requested forwarding of port %d but user is not root.",
3101 port); 3427 fwd.listen_port);
3102 if (host_port == 0) 3428 if (fwd.connect_port == 0)
3103 packet_disconnect("Dynamic forwarding denied."); 3429 packet_disconnect("Dynamic forwarding denied.");
3104#endif 3430#endif
3105 3431
3106 /* Initiate forwarding */ 3432 /* Initiate forwarding */
3107 success = channel_setup_local_fwd_listener(NULL, port, hostname, 3433 success = channel_setup_local_fwd_listener(&fwd, fwd_opts);
3108 host_port, gateway_ports);
3109 3434
3110 /* Free the argument string. */ 3435 /* Free the argument string. */
3111 free(hostname); 3436 free(fwd.connect_host);
3112 3437
3113 return (success ? 0 : -1); 3438 return (success ? 0 : -1);
3114} 3439}
@@ -3134,6 +3459,9 @@ channel_add_permitted_opens(char *host, int port)
3134 num_permitted_opens + 1, sizeof(*permitted_opens)); 3459 num_permitted_opens + 1, sizeof(*permitted_opens));
3135 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host); 3460 permitted_opens[num_permitted_opens].host_to_connect = xstrdup(host);
3136 permitted_opens[num_permitted_opens].port_to_connect = port; 3461 permitted_opens[num_permitted_opens].port_to_connect = port;
3462 permitted_opens[num_permitted_opens].listen_host = NULL;
3463 permitted_opens[num_permitted_opens].listen_path = NULL;
3464 permitted_opens[num_permitted_opens].listen_port = 0;
3137 num_permitted_opens++; 3465 num_permitted_opens++;
3138 3466
3139 all_opens_permitted = 0; 3467 all_opens_permitted = 0;
@@ -3165,6 +3493,10 @@ channel_update_permitted_opens(int idx, int newport)
3165 permitted_opens[idx].port_to_connect = 0; 3493 permitted_opens[idx].port_to_connect = 0;
3166 free(permitted_opens[idx].host_to_connect); 3494 free(permitted_opens[idx].host_to_connect);
3167 permitted_opens[idx].host_to_connect = NULL; 3495 permitted_opens[idx].host_to_connect = NULL;
3496 free(permitted_opens[idx].listen_host);
3497 permitted_opens[idx].listen_host = NULL;
3498 free(permitted_opens[idx].listen_path);
3499 permitted_opens[idx].listen_path = NULL;
3168 } 3500 }
3169} 3501}
3170 3502
@@ -3178,6 +3510,9 @@ channel_add_adm_permitted_opens(char *host, int port)
3178 permitted_adm_opens[num_adm_permitted_opens].host_to_connect 3510 permitted_adm_opens[num_adm_permitted_opens].host_to_connect
3179 = xstrdup(host); 3511 = xstrdup(host);
3180 permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port; 3512 permitted_adm_opens[num_adm_permitted_opens].port_to_connect = port;
3513 permitted_adm_opens[num_adm_permitted_opens].listen_host = NULL;
3514 permitted_adm_opens[num_adm_permitted_opens].listen_path = NULL;
3515 permitted_adm_opens[num_adm_permitted_opens].listen_port = 0;
3181 return ++num_adm_permitted_opens; 3516 return ++num_adm_permitted_opens;
3182} 3517}
3183 3518
@@ -3195,8 +3530,11 @@ channel_clear_permitted_opens(void)
3195{ 3530{
3196 int i; 3531 int i;
3197 3532
3198 for (i = 0; i < num_permitted_opens; i++) 3533 for (i = 0; i < num_permitted_opens; i++) {
3199 free(permitted_opens[i].host_to_connect); 3534 free(permitted_opens[i].host_to_connect);
3535 free(permitted_opens[i].listen_host);
3536 free(permitted_opens[i].listen_path);
3537 }
3200 free(permitted_opens); 3538 free(permitted_opens);
3201 permitted_opens = NULL; 3539 permitted_opens = NULL;
3202 num_permitted_opens = 0; 3540 num_permitted_opens = 0;
@@ -3207,8 +3545,11 @@ channel_clear_adm_permitted_opens(void)
3207{ 3545{
3208 int i; 3546 int i;
3209 3547
3210 for (i = 0; i < num_adm_permitted_opens; i++) 3548 for (i = 0; i < num_adm_permitted_opens; i++) {
3211 free(permitted_adm_opens[i].host_to_connect); 3549 free(permitted_adm_opens[i].host_to_connect);
3550 free(permitted_adm_opens[i].listen_host);
3551 free(permitted_adm_opens[i].listen_path);
3552 }
3212 free(permitted_adm_opens); 3553 free(permitted_adm_opens);
3213 permitted_adm_opens = NULL; 3554 permitted_adm_opens = NULL;
3214 num_adm_permitted_opens = 0; 3555 num_adm_permitted_opens = 0;
@@ -3246,30 +3587,32 @@ permitopen_port(const char *p)
3246 return -1; 3587 return -1;
3247} 3588}
3248 3589
3249static int
3250port_match(u_short allowedport, u_short requestedport)
3251{
3252 if (allowedport == FWD_PERMIT_ANY_PORT ||
3253 allowedport == requestedport)
3254 return 1;
3255 return 0;
3256}
3257
3258/* Try to start non-blocking connect to next host in cctx list */ 3590/* Try to start non-blocking connect to next host in cctx list */
3259static int 3591static int
3260connect_next(struct channel_connect *cctx) 3592connect_next(struct channel_connect *cctx)
3261{ 3593{
3262 int sock, saved_errno; 3594 int sock, saved_errno;
3263 char ntop[NI_MAXHOST], strport[NI_MAXSERV]; 3595 struct sockaddr_un *sunaddr;
3596 char ntop[NI_MAXHOST], strport[MAX(NI_MAXSERV,sizeof(sunaddr->sun_path))];
3264 3597
3265 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) { 3598 for (; cctx->ai; cctx->ai = cctx->ai->ai_next) {
3266 if (cctx->ai->ai_family != AF_INET && 3599 switch (cctx->ai->ai_family) {
3267 cctx->ai->ai_family != AF_INET6) 3600 case AF_UNIX:
3268 continue; 3601 /* unix:pathname instead of host:port */
3269 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen, 3602 sunaddr = (struct sockaddr_un *)cctx->ai->ai_addr;
3270 ntop, sizeof(ntop), strport, sizeof(strport), 3603 strlcpy(ntop, "unix", sizeof(ntop));
3271 NI_NUMERICHOST|NI_NUMERICSERV) != 0) { 3604 strlcpy(strport, sunaddr->sun_path, sizeof(strport));
3272 error("connect_next: getnameinfo failed"); 3605 break;
3606 case AF_INET:
3607 case AF_INET6:
3608 if (getnameinfo(cctx->ai->ai_addr, cctx->ai->ai_addrlen,
3609 ntop, sizeof(ntop), strport, sizeof(strport),
3610 NI_NUMERICHOST|NI_NUMERICSERV) != 0) {
3611 error("connect_next: getnameinfo failed");
3612 continue;
3613 }
3614 break;
3615 default:
3273 continue; 3616 continue;
3274 } 3617 }
3275 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype, 3618 if ((sock = socket(cctx->ai->ai_family, cctx->ai->ai_socktype,
@@ -3292,10 +3635,11 @@ connect_next(struct channel_connect *cctx)
3292 errno = saved_errno; 3635 errno = saved_errno;
3293 continue; /* fail -- try next */ 3636 continue; /* fail -- try next */
3294 } 3637 }
3638 if (cctx->ai->ai_family != AF_UNIX)
3639 set_nodelay(sock);
3295 debug("connect_next: host %.100s ([%.100s]:%s) " 3640 debug("connect_next: host %.100s ([%.100s]:%s) "
3296 "in progress, fd=%d", cctx->host, ntop, strport, sock); 3641 "in progress, fd=%d", cctx->host, ntop, strport, sock);
3297 cctx->ai = cctx->ai->ai_next; 3642 cctx->ai = cctx->ai->ai_next;
3298 set_nodelay(sock);
3299 return sock; 3643 return sock;
3300 } 3644 }
3301 return -1; 3645 return -1;
@@ -3305,14 +3649,18 @@ static void
3305channel_connect_ctx_free(struct channel_connect *cctx) 3649channel_connect_ctx_free(struct channel_connect *cctx)
3306{ 3650{
3307 free(cctx->host); 3651 free(cctx->host);
3308 if (cctx->aitop) 3652 if (cctx->aitop) {
3309 freeaddrinfo(cctx->aitop); 3653 if (cctx->aitop->ai_family == AF_UNIX)
3654 free(cctx->aitop);
3655 else
3656 freeaddrinfo(cctx->aitop);
3657 }
3310 memset(cctx, 0, sizeof(*cctx)); 3658 memset(cctx, 0, sizeof(*cctx));
3311} 3659}
3312 3660
3313/* Return CONNECTING channel to remote host, port */ 3661/* Return CONNECTING channel to remote host:port or local socket path */
3314static Channel * 3662static Channel *
3315connect_to(const char *host, u_short port, char *ctype, char *rname) 3663connect_to(const char *name, int port, char *ctype, char *rname)
3316{ 3664{
3317 struct addrinfo hints; 3665 struct addrinfo hints;
3318 int gaierr; 3666 int gaierr;
@@ -3322,23 +3670,51 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
3322 Channel *c; 3670 Channel *c;
3323 3671
3324 memset(&cctx, 0, sizeof(cctx)); 3672 memset(&cctx, 0, sizeof(cctx));
3325 memset(&hints, 0, sizeof(hints)); 3673
3326 hints.ai_family = IPv4or6; 3674 if (port == PORT_STREAMLOCAL) {
3327 hints.ai_socktype = SOCK_STREAM; 3675 struct sockaddr_un *sunaddr;
3328 snprintf(strport, sizeof strport, "%d", port); 3676 struct addrinfo *ai;
3329 if ((gaierr = getaddrinfo(host, strport, &hints, &cctx.aitop)) != 0) { 3677
3330 error("connect_to %.100s: unknown host (%s)", host, 3678 if (strlen(name) > sizeof(sunaddr->sun_path)) {
3331 ssh_gai_strerror(gaierr)); 3679 error("%.100s: %.100s", name, strerror(ENAMETOOLONG));
3332 return NULL; 3680 return (NULL);
3681 }
3682
3683 /*
3684 * Fake up a struct addrinfo for AF_UNIX connections.
3685 * channel_connect_ctx_free() must check ai_family
3686 * and use free() not freeaddirinfo() for AF_UNIX.
3687 */
3688 ai = xmalloc(sizeof(*ai) + sizeof(*sunaddr));
3689 memset(ai, 0, sizeof(*ai) + sizeof(*sunaddr));
3690 ai->ai_addr = (struct sockaddr *)(ai + 1);
3691 ai->ai_addrlen = sizeof(*sunaddr);
3692 ai->ai_family = AF_UNIX;
3693 ai->ai_socktype = SOCK_STREAM;
3694 ai->ai_protocol = PF_UNSPEC;
3695 sunaddr = (struct sockaddr_un *)ai->ai_addr;
3696 sunaddr->sun_family = AF_UNIX;
3697 strlcpy(sunaddr->sun_path, name, sizeof(sunaddr->sun_path));
3698 cctx.aitop = ai;
3699 } else {
3700 memset(&hints, 0, sizeof(hints));
3701 hints.ai_family = IPv4or6;
3702 hints.ai_socktype = SOCK_STREAM;
3703 snprintf(strport, sizeof strport, "%d", port);
3704 if ((gaierr = getaddrinfo(name, strport, &hints, &cctx.aitop)) != 0) {
3705 error("connect_to %.100s: unknown host (%s)", name,
3706 ssh_gai_strerror(gaierr));
3707 return NULL;
3708 }
3333 } 3709 }
3334 3710
3335 cctx.host = xstrdup(host); 3711 cctx.host = xstrdup(name);
3336 cctx.port = port; 3712 cctx.port = port;
3337 cctx.ai = cctx.aitop; 3713 cctx.ai = cctx.aitop;
3338 3714
3339 if ((sock = connect_next(&cctx)) == -1) { 3715 if ((sock = connect_next(&cctx)) == -1) {
3340 error("connect to %.100s port %d failed: %s", 3716 error("connect to %.100s port %d failed: %s",
3341 host, port, strerror(errno)); 3717 name, port, strerror(errno));
3342 channel_connect_ctx_free(&cctx); 3718 channel_connect_ctx_free(&cctx);
3343 return NULL; 3719 return NULL;
3344 } 3720 }
@@ -3349,13 +3725,14 @@ connect_to(const char *host, u_short port, char *ctype, char *rname)
3349} 3725}
3350 3726
3351Channel * 3727Channel *
3352channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname) 3728channel_connect_by_listen_address(const char *listen_host,
3729 u_short listen_port, char *ctype, char *rname)
3353{ 3730{
3354 int i; 3731 int i;
3355 3732
3356 for (i = 0; i < num_permitted_opens; i++) { 3733 for (i = 0; i < num_permitted_opens; i++) {
3357 if (permitted_opens[i].host_to_connect != NULL && 3734 if (open_listen_match_tcpip(&permitted_opens[i], listen_host,
3358 port_match(permitted_opens[i].listen_port, listen_port)) { 3735 listen_port, 1)) {
3359 return connect_to( 3736 return connect_to(
3360 permitted_opens[i].host_to_connect, 3737 permitted_opens[i].host_to_connect,
3361 permitted_opens[i].port_to_connect, ctype, rname); 3738 permitted_opens[i].port_to_connect, ctype, rname);
@@ -3366,29 +3743,45 @@ channel_connect_by_listen_address(u_short listen_port, char *ctype, char *rname)
3366 return NULL; 3743 return NULL;
3367} 3744}
3368 3745
3746Channel *
3747channel_connect_by_listen_path(const char *path, char *ctype, char *rname)
3748{
3749 int i;
3750
3751 for (i = 0; i < num_permitted_opens; i++) {
3752 if (open_listen_match_streamlocal(&permitted_opens[i], path)) {
3753 return connect_to(
3754 permitted_opens[i].host_to_connect,
3755 permitted_opens[i].port_to_connect, ctype, rname);
3756 }
3757 }
3758 error("WARNING: Server requests forwarding for unknown path %.100s",
3759 path);
3760 return NULL;
3761}
3762
3369/* Check if connecting to that port is permitted and connect. */ 3763/* Check if connecting to that port is permitted and connect. */
3370Channel * 3764Channel *
3371channel_connect_to(const char *host, u_short port, char *ctype, char *rname) 3765channel_connect_to_port(const char *host, u_short port, char *ctype, char *rname)
3372{ 3766{
3373 int i, permit, permit_adm = 1; 3767 int i, permit, permit_adm = 1;
3374 3768
3375 permit = all_opens_permitted; 3769 permit = all_opens_permitted;
3376 if (!permit) { 3770 if (!permit) {
3377 for (i = 0; i < num_permitted_opens; i++) 3771 for (i = 0; i < num_permitted_opens; i++)
3378 if (permitted_opens[i].host_to_connect != NULL && 3772 if (open_match(&permitted_opens[i], host, port)) {
3379 port_match(permitted_opens[i].port_to_connect, port) &&
3380 strcmp(permitted_opens[i].host_to_connect, host) == 0)
3381 permit = 1; 3773 permit = 1;
3774 break;
3775 }
3382 } 3776 }
3383 3777
3384 if (num_adm_permitted_opens > 0) { 3778 if (num_adm_permitted_opens > 0) {
3385 permit_adm = 0; 3779 permit_adm = 0;
3386 for (i = 0; i < num_adm_permitted_opens; i++) 3780 for (i = 0; i < num_adm_permitted_opens; i++)
3387 if (permitted_adm_opens[i].host_to_connect != NULL && 3781 if (open_match(&permitted_adm_opens[i], host, port)) {
3388 port_match(permitted_adm_opens[i].port_to_connect, port) &&
3389 strcmp(permitted_adm_opens[i].host_to_connect, host)
3390 == 0)
3391 permit_adm = 1; 3782 permit_adm = 1;
3783 break;
3784 }
3392 } 3785 }
3393 3786
3394 if (!permit || !permit_adm) { 3787 if (!permit || !permit_adm) {
@@ -3399,6 +3792,38 @@ channel_connect_to(const char *host, u_short port, char *ctype, char *rname)
3399 return connect_to(host, port, ctype, rname); 3792 return connect_to(host, port, ctype, rname);
3400} 3793}
3401 3794
3795/* Check if connecting to that path is permitted and connect. */
3796Channel *
3797channel_connect_to_path(const char *path, char *ctype, char *rname)
3798{
3799 int i, permit, permit_adm = 1;
3800
3801 permit = all_opens_permitted;
3802 if (!permit) {
3803 for (i = 0; i < num_permitted_opens; i++)
3804 if (open_match(&permitted_opens[i], path, PORT_STREAMLOCAL)) {
3805 permit = 1;
3806 break;
3807 }
3808 }
3809
3810 if (num_adm_permitted_opens > 0) {
3811 permit_adm = 0;
3812 for (i = 0; i < num_adm_permitted_opens; i++)
3813 if (open_match(&permitted_adm_opens[i], path, PORT_STREAMLOCAL)) {
3814 permit_adm = 1;
3815 break;
3816 }
3817 }
3818
3819 if (!permit || !permit_adm) {
3820 logit("Received request to connect to path %.100s, "
3821 "but the request was denied.", path);
3822 return NULL;
3823 }
3824 return connect_to(path, PORT_STREAMLOCAL, ctype, rname);
3825}
3826
3402void 3827void
3403channel_send_window_changes(void) 3828channel_send_window_changes(void)
3404{ 3829{
diff --git a/channels.h b/channels.h
index 4fab9d7c4..a000c98e5 100644
--- a/channels.h
+++ b/channels.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: channels.h,v 1.113 2013/06/07 15:37:52 dtucker Exp $ */ 1/* $OpenBSD: channels.h,v 1.115 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -56,7 +56,9 @@
56#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */ 56#define SSH_CHANNEL_MUX_LISTENER 15 /* Listener for mux conn. */
57#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */ 57#define SSH_CHANNEL_MUX_CLIENT 16 /* Conn. to mux slave */
58#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */ 58#define SSH_CHANNEL_ABANDONED 17 /* Abandoned session, eg mux */
59#define SSH_CHANNEL_MAX_TYPE 18 59#define SSH_CHANNEL_UNIX_LISTENER 18 /* Listening on a domain socket. */
60#define SSH_CHANNEL_RUNIX_LISTENER 19 /* Listening to a R-style domain socket. */
61#define SSH_CHANNEL_MAX_TYPE 20
60 62
61#define CHANNEL_CANCEL_PORT_STATIC -1 63#define CHANNEL_CANCEL_PORT_STATIC -1
62 64
@@ -254,6 +256,8 @@ char *channel_open_message(void);
254int channel_find_open(void); 256int channel_find_open(void);
255 257
256/* tcp forwarding */ 258/* tcp forwarding */
259struct Forward;
260struct ForwardOptions;
257void channel_set_af(int af); 261void channel_set_af(int af);
258void channel_permit_all_opens(void); 262void channel_permit_all_opens(void);
259void channel_add_permitted_opens(char *, int); 263void channel_add_permitted_opens(char *, int);
@@ -263,18 +267,19 @@ void channel_update_permitted_opens(int, int);
263void channel_clear_permitted_opens(void); 267void channel_clear_permitted_opens(void);
264void channel_clear_adm_permitted_opens(void); 268void channel_clear_adm_permitted_opens(void);
265void channel_print_adm_permitted_opens(void); 269void channel_print_adm_permitted_opens(void);
266int channel_input_port_forward_request(int, int); 270int channel_input_port_forward_request(int, struct ForwardOptions *);
267Channel *channel_connect_to(const char *, u_short, char *, char *); 271Channel *channel_connect_to_port(const char *, u_short, char *, char *);
272Channel *channel_connect_to_path(const char *, char *, char *);
268Channel *channel_connect_stdio_fwd(const char*, u_short, int, int); 273Channel *channel_connect_stdio_fwd(const char*, u_short, int, int);
269Channel *channel_connect_by_listen_address(u_short, char *, char *); 274Channel *channel_connect_by_listen_address(const char *, u_short,
270int channel_request_remote_forwarding(const char *, u_short, 275 char *, char *);
271 const char *, u_short); 276Channel *channel_connect_by_listen_path(const char *, char *, char *);
272int channel_setup_local_fwd_listener(const char *, u_short, 277int channel_request_remote_forwarding(struct Forward *);
273 const char *, u_short, int); 278int channel_setup_local_fwd_listener(struct Forward *, struct ForwardOptions *);
274int channel_request_rforward_cancel(const char *host, u_short port); 279int channel_request_rforward_cancel(struct Forward *);
275int channel_setup_remote_fwd_listener(const char *, u_short, int *, int); 280int channel_setup_remote_fwd_listener(struct Forward *, int *, struct ForwardOptions *);
276int channel_cancel_rport_listener(const char *, u_short); 281int channel_cancel_rport_listener(struct Forward *);
277int channel_cancel_lport_listener(const char *, u_short, int, int); 282int channel_cancel_lport_listener(struct Forward *, int, struct ForwardOptions *);
278int permitopen_port(const char *); 283int permitopen_port(const char *);
279 284
280/* x11 forwarding */ 285/* x11 forwarding */
diff --git a/cipher-3des1.c b/cipher-3des1.c
index b2823592b..2753f9a0e 100644
--- a/cipher-3des1.c
+++ b/cipher-3des1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher-3des1.c,v 1.10 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: cipher-3des1.c,v 1.11 2014/07/02 04:59:06 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2003 Markus Friedl. All rights reserved. 3 * Copyright (c) 2003 Markus Friedl. All rights reserved.
4 * 4 *
@@ -29,13 +29,11 @@
29 29
30#include <openssl/evp.h> 30#include <openssl/evp.h>
31 31
32#include <stdarg.h>
33#include <string.h> 32#include <string.h>
34 33
35#include "xmalloc.h" 34#include "xmalloc.h"
36#include "log.h" 35#include "log.h"
37 36#include "ssherr.h"
38#include "openbsd-compat/openssl-compat.h"
39 37
40/* 38/*
41 * This is used by SSH1: 39 * This is used by SSH1:
@@ -57,7 +55,7 @@ struct ssh1_3des_ctx
57}; 55};
58 56
59const EVP_CIPHER * evp_ssh1_3des(void); 57const EVP_CIPHER * evp_ssh1_3des(void);
60void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); 58int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
61 59
62static int 60static int
63ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv, 61ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
@@ -67,11 +65,12 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
67 u_char *k1, *k2, *k3; 65 u_char *k1, *k2, *k3;
68 66
69 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 67 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) {
70 c = xcalloc(1, sizeof(*c)); 68 if ((c = calloc(1, sizeof(*c))) == NULL)
69 return 0;
71 EVP_CIPHER_CTX_set_app_data(ctx, c); 70 EVP_CIPHER_CTX_set_app_data(ctx, c);
72 } 71 }
73 if (key == NULL) 72 if (key == NULL)
74 return (1); 73 return 1;
75 if (enc == -1) 74 if (enc == -1)
76 enc = ctx->encrypt; 75 enc = ctx->encrypt;
77 k1 = k2 = k3 = (u_char *) key; 76 k1 = k2 = k3 = (u_char *) key;
@@ -85,44 +84,29 @@ ssh1_3des_init(EVP_CIPHER_CTX *ctx, const u_char *key, const u_char *iv,
85 EVP_CIPHER_CTX_init(&c->k1); 84 EVP_CIPHER_CTX_init(&c->k1);
86 EVP_CIPHER_CTX_init(&c->k2); 85 EVP_CIPHER_CTX_init(&c->k2);
87 EVP_CIPHER_CTX_init(&c->k3); 86 EVP_CIPHER_CTX_init(&c->k3);
88#ifdef SSH_OLD_EVP
89 EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc);
90 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc);
91 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc);
92#else
93 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 || 87 if (EVP_CipherInit(&c->k1, EVP_des_cbc(), k1, NULL, enc) == 0 ||
94 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 || 88 EVP_CipherInit(&c->k2, EVP_des_cbc(), k2, NULL, !enc) == 0 ||
95 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) { 89 EVP_CipherInit(&c->k3, EVP_des_cbc(), k3, NULL, enc) == 0) {
96 explicit_bzero(c, sizeof(*c)); 90 explicit_bzero(c, sizeof(*c));
97 free(c); 91 free(c);
98 EVP_CIPHER_CTX_set_app_data(ctx, NULL); 92 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
99 return (0); 93 return 0;
100 } 94 }
101#endif 95 return 1;
102 return (1);
103} 96}
104 97
105static int 98static int
106ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, 99ssh1_3des_cbc(EVP_CIPHER_CTX *ctx, u_char *dest, const u_char *src, size_t len)
107 LIBCRYPTO_EVP_INL_TYPE len)
108{ 100{
109 struct ssh1_3des_ctx *c; 101 struct ssh1_3des_ctx *c;
110 102
111 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL) { 103 if ((c = EVP_CIPHER_CTX_get_app_data(ctx)) == NULL)
112 error("ssh1_3des_cbc: no context"); 104 return 0;
113 return (0);
114 }
115#ifdef SSH_OLD_EVP
116 EVP_Cipher(&c->k1, dest, (u_char *)src, len);
117 EVP_Cipher(&c->k2, dest, dest, len);
118 EVP_Cipher(&c->k3, dest, dest, len);
119#else
120 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 || 105 if (EVP_Cipher(&c->k1, dest, (u_char *)src, len) == 0 ||
121 EVP_Cipher(&c->k2, dest, dest, len) == 0 || 106 EVP_Cipher(&c->k2, dest, dest, len) == 0 ||
122 EVP_Cipher(&c->k3, dest, dest, len) == 0) 107 EVP_Cipher(&c->k3, dest, dest, len) == 0)
123 return (0); 108 return 0;
124#endif 109 return 1;
125 return (1);
126} 110}
127 111
128static int 112static int
@@ -138,29 +122,28 @@ ssh1_3des_cleanup(EVP_CIPHER_CTX *ctx)
138 free(c); 122 free(c);
139 EVP_CIPHER_CTX_set_app_data(ctx, NULL); 123 EVP_CIPHER_CTX_set_app_data(ctx, NULL);
140 } 124 }
141 return (1); 125 return 1;
142} 126}
143 127
144void 128int
145ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len) 129ssh1_3des_iv(EVP_CIPHER_CTX *evp, int doset, u_char *iv, int len)
146{ 130{
147 struct ssh1_3des_ctx *c; 131 struct ssh1_3des_ctx *c;
148 132
149 if (len != 24) 133 if (len != 24)
150 fatal("%s: bad 3des iv length: %d", __func__, len); 134 return SSH_ERR_INVALID_ARGUMENT;
151 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL) 135 if ((c = EVP_CIPHER_CTX_get_app_data(evp)) == NULL)
152 fatal("%s: no 3des context", __func__); 136 return SSH_ERR_INTERNAL_ERROR;
153 if (doset) { 137 if (doset) {
154 debug3("%s: Installed 3DES IV", __func__);
155 memcpy(c->k1.iv, iv, 8); 138 memcpy(c->k1.iv, iv, 8);
156 memcpy(c->k2.iv, iv + 8, 8); 139 memcpy(c->k2.iv, iv + 8, 8);
157 memcpy(c->k3.iv, iv + 16, 8); 140 memcpy(c->k3.iv, iv + 16, 8);
158 } else { 141 } else {
159 debug3("%s: Copying 3DES IV", __func__);
160 memcpy(iv, c->k1.iv, 8); 142 memcpy(iv, c->k1.iv, 8);
161 memcpy(iv + 8, c->k2.iv, 8); 143 memcpy(iv + 8, c->k2.iv, 8);
162 memcpy(iv + 16, c->k3.iv, 8); 144 memcpy(iv + 16, c->k3.iv, 8);
163 } 145 }
146 return 0;
164} 147}
165 148
166const EVP_CIPHER * 149const EVP_CIPHER *
@@ -176,8 +159,6 @@ evp_ssh1_3des(void)
176 ssh1_3des.init = ssh1_3des_init; 159 ssh1_3des.init = ssh1_3des_init;
177 ssh1_3des.cleanup = ssh1_3des_cleanup; 160 ssh1_3des.cleanup = ssh1_3des_cleanup;
178 ssh1_3des.do_cipher = ssh1_3des_cbc; 161 ssh1_3des.do_cipher = ssh1_3des_cbc;
179#ifndef SSH_OLD_EVP
180 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH; 162 ssh1_3des.flags = EVP_CIPH_CBC_MODE | EVP_CIPH_VARIABLE_LENGTH;
181#endif 163 return &ssh1_3des;
182 return (&ssh1_3des);
183} 164}
diff --git a/cipher-aesctr.c b/cipher-aesctr.c
new file mode 100644
index 000000000..a4cf61e41
--- /dev/null
+++ b/cipher-aesctr.c
@@ -0,0 +1,78 @@
1/* $OpenBSD: cipher-aesctr.c,v 1.1 2014/04/29 15:39:33 markus Exp $ */
2/*
3 * Copyright (c) 2003 Markus Friedl <markus@openbsd.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <sys/types.h>
19#include <string.h>
20
21#include "cipher-aesctr.h"
22
23/*
24 * increment counter 'ctr',
25 * the counter is of size 'len' bytes and stored in network-byte-order.
26 * (LSB at ctr[len-1], MSB at ctr[0])
27 */
28static __inline__ void
29aesctr_inc(u8 *ctr, u32 len)
30{
31 ssize_t i;
32
33#ifndef CONSTANT_TIME_INCREMENT
34 for (i = len - 1; i >= 0; i--)
35 if (++ctr[i]) /* continue on overflow */
36 return;
37#else
38 u8 x, add = 1;
39
40 for (i = len - 1; i >= 0; i--) {
41 ctr[i] += add;
42 /* constant time for: x = ctr[i] ? 1 : 0 */
43 x = ctr[i];
44 x = (x | (x >> 4)) & 0xf;
45 x = (x | (x >> 2)) & 0x3;
46 x = (x | (x >> 1)) & 0x1;
47 add *= (x^1);
48 }
49#endif
50}
51
52void
53aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits)
54{
55 x->rounds = rijndaelKeySetupEnc(x->ek, k, kbits);
56}
57
58void
59aesctr_ivsetup(aesctr_ctx *x,const u8 *iv)
60{
61 memcpy(x->ctr, iv, AES_BLOCK_SIZE);
62}
63
64void
65aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes)
66{
67 u32 n = 0;
68 u8 buf[AES_BLOCK_SIZE];
69
70 while ((bytes--) > 0) {
71 if (n == 0) {
72 rijndaelEncrypt(x->ek, x->rounds, x->ctr, buf);
73 aesctr_inc(x->ctr, AES_BLOCK_SIZE);
74 }
75 *(c++) = *(m++) ^ buf[n];
76 n = (n + 1) % AES_BLOCK_SIZE;
77 }
78}
diff --git a/cipher-aesctr.h b/cipher-aesctr.h
new file mode 100644
index 000000000..85d55bba2
--- /dev/null
+++ b/cipher-aesctr.h
@@ -0,0 +1,35 @@
1/* $OpenBSD: cipher-aesctr.h,v 1.1 2014/04/29 15:39:33 markus Exp $ */
2/*
3 * Copyright (c) 2014 Markus Friedl
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef OPENSSH_AESCTR_H
19#define OPENSSH_AESCTR_H
20
21#include "rijndael.h"
22
23#define AES_BLOCK_SIZE 16
24
25typedef struct aesctr_ctx {
26 int rounds; /* keylen-dependent #rounds */
27 u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
28 u8 ctr[AES_BLOCK_SIZE]; /* counter */
29} aesctr_ctx;
30
31void aesctr_keysetup(aesctr_ctx *x,const u8 *k,u32 kbits,u32 ivbits);
32void aesctr_ivsetup(aesctr_ctx *x,const u8 *iv);
33void aesctr_encrypt_bytes(aesctr_ctx *x,const u8 *m,u8 *c,u32 bytes);
34
35#endif
diff --git a/cipher-chachapoly.c b/cipher-chachapoly.c
index 251b94ec8..8665b41a3 100644
--- a/cipher-chachapoly.c
+++ b/cipher-chachapoly.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: cipher-chachapoly.c,v 1.4 2014/01/31 16:39:19 tedu Exp $ */ 17/* $OpenBSD: cipher-chachapoly.c,v 1.6 2014/07/03 12:42:16 jsing Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -24,16 +24,18 @@
24#include <stdio.h> /* needed for misc.h */ 24#include <stdio.h> /* needed for misc.h */
25 25
26#include "log.h" 26#include "log.h"
27#include "misc.h" 27#include "sshbuf.h"
28#include "ssherr.h"
28#include "cipher-chachapoly.h" 29#include "cipher-chachapoly.h"
29 30
30void chachapoly_init(struct chachapoly_ctx *ctx, 31int chachapoly_init(struct chachapoly_ctx *ctx,
31 const u_char *key, u_int keylen) 32 const u_char *key, u_int keylen)
32{ 33{
33 if (keylen != (32 + 32)) /* 2 x 256 bit keys */ 34 if (keylen != (32 + 32)) /* 2 x 256 bit keys */
34 fatal("%s: invalid keylen %u", __func__, keylen); 35 return SSH_ERR_INVALID_ARGUMENT;
35 chacha_keysetup(&ctx->main_ctx, key, 256); 36 chacha_keysetup(&ctx->main_ctx, key, 256);
36 chacha_keysetup(&ctx->header_ctx, key + 32, 256); 37 chacha_keysetup(&ctx->header_ctx, key + 32, 256);
38 return 0;
37} 39}
38 40
39/* 41/*
@@ -52,33 +54,37 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
52 u_char seqbuf[8]; 54 u_char seqbuf[8];
53 const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */ 55 const u_char one[8] = { 1, 0, 0, 0, 0, 0, 0, 0 }; /* NB little-endian */
54 u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN]; 56 u_char expected_tag[POLY1305_TAGLEN], poly_key[POLY1305_KEYLEN];
55 int r = -1; 57 int r = SSH_ERR_INTERNAL_ERROR;
56 58
57 /* 59 /*
58 * Run ChaCha20 once to generate the Poly1305 key. The IV is the 60 * Run ChaCha20 once to generate the Poly1305 key. The IV is the
59 * packet sequence number. 61 * packet sequence number.
60 */ 62 */
61 memset(poly_key, 0, sizeof(poly_key)); 63 memset(poly_key, 0, sizeof(poly_key));
62 put_u64(seqbuf, seqnr); 64 POKE_U64(seqbuf, seqnr);
63 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL); 65 chacha_ivsetup(&ctx->main_ctx, seqbuf, NULL);
64 chacha_encrypt_bytes(&ctx->main_ctx, 66 chacha_encrypt_bytes(&ctx->main_ctx,
65 poly_key, poly_key, sizeof(poly_key)); 67 poly_key, poly_key, sizeof(poly_key));
66 /* Set Chacha's block counter to 1 */
67 chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
68 68
69 /* If decrypting, check tag before anything else */ 69 /* If decrypting, check tag before anything else */
70 if (!do_encrypt) { 70 if (!do_encrypt) {
71 const u_char *tag = src + aadlen + len; 71 const u_char *tag = src + aadlen + len;
72 72
73 poly1305_auth(expected_tag, src, aadlen + len, poly_key); 73 poly1305_auth(expected_tag, src, aadlen + len, poly_key);
74 if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) 74 if (timingsafe_bcmp(expected_tag, tag, POLY1305_TAGLEN) != 0) {
75 r = SSH_ERR_MAC_INVALID;
75 goto out; 76 goto out;
77 }
76 } 78 }
79
77 /* Crypt additional data */ 80 /* Crypt additional data */
78 if (aadlen) { 81 if (aadlen) {
79 chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); 82 chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
80 chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen); 83 chacha_encrypt_bytes(&ctx->header_ctx, src, dest, aadlen);
81 } 84 }
85
86 /* Set Chacha's block counter to 1 */
87 chacha_ivsetup(&ctx->main_ctx, seqbuf, one);
82 chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen, 88 chacha_encrypt_bytes(&ctx->main_ctx, src + aadlen,
83 dest + aadlen, len); 89 dest + aadlen, len);
84 90
@@ -88,7 +94,6 @@ chachapoly_crypt(struct chachapoly_ctx *ctx, u_int seqnr, u_char *dest,
88 poly_key); 94 poly_key);
89 } 95 }
90 r = 0; 96 r = 0;
91
92 out: 97 out:
93 explicit_bzero(expected_tag, sizeof(expected_tag)); 98 explicit_bzero(expected_tag, sizeof(expected_tag));
94 explicit_bzero(seqbuf, sizeof(seqbuf)); 99 explicit_bzero(seqbuf, sizeof(seqbuf));
@@ -104,11 +109,11 @@ chachapoly_get_length(struct chachapoly_ctx *ctx,
104 u_char buf[4], seqbuf[8]; 109 u_char buf[4], seqbuf[8];
105 110
106 if (len < 4) 111 if (len < 4)
107 return -1; /* Insufficient length */ 112 return SSH_ERR_MESSAGE_INCOMPLETE;
108 put_u64(seqbuf, seqnr); 113 POKE_U64(seqbuf, seqnr);
109 chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL); 114 chacha_ivsetup(&ctx->header_ctx, seqbuf, NULL);
110 chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4); 115 chacha_encrypt_bytes(&ctx->header_ctx, cp, buf, 4);
111 *plenp = get_u32(buf); 116 *plenp = PEEK_U32(buf);
112 return 0; 117 return 0;
113} 118}
114 119
diff --git a/cipher-chachapoly.h b/cipher-chachapoly.h
index 1628693b2..b7072be7d 100644
--- a/cipher-chachapoly.h
+++ b/cipher-chachapoly.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher-chachapoly.h,v 1.1 2013/11/21 00:45:44 djm Exp $ */ 1/* $OpenBSD: cipher-chachapoly.h,v 1.4 2014/06/24 01:13:21 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) Damien Miller 2013 <djm@mindrot.org> 4 * Copyright (c) Damien Miller 2013 <djm@mindrot.org>
@@ -28,7 +28,7 @@ struct chachapoly_ctx {
28 struct chacha_ctx main_ctx, header_ctx; 28 struct chacha_ctx main_ctx, header_ctx;
29}; 29};
30 30
31void chachapoly_init(struct chachapoly_ctx *cpctx, 31int chachapoly_init(struct chachapoly_ctx *cpctx,
32 const u_char *key, u_int keylen) 32 const u_char *key, u_int keylen)
33 __attribute__((__bounded__(__buffer__, 2, 3))); 33 __attribute__((__bounded__(__buffer__, 2, 3)));
34int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr, 34int chachapoly_crypt(struct chachapoly_ctx *cpctx, u_int seqnr,
diff --git a/cipher.c b/cipher.c
index 53d9b4fb7..638ca2d97 100644
--- a/cipher.c
+++ b/cipher.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.c,v 1.97 2014/02/07 06:55:54 djm Exp $ */ 1/* $OpenBSD: cipher.c,v 1.99 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -43,21 +43,21 @@
43#include <stdarg.h> 43#include <stdarg.h>
44#include <stdio.h> 44#include <stdio.h>
45 45
46#include "xmalloc.h"
47#include "log.h"
48#include "misc.h"
49#include "cipher.h" 46#include "cipher.h"
50#include "buffer.h" 47#include "misc.h"
48#include "sshbuf.h"
49#include "ssherr.h"
51#include "digest.h" 50#include "digest.h"
52 51
53/* compatibility with old or broken OpenSSL versions */
54#include "openbsd-compat/openssl-compat.h" 52#include "openbsd-compat/openssl-compat.h"
55 53
54#ifdef WITH_SSH1
56extern const EVP_CIPHER *evp_ssh1_bf(void); 55extern const EVP_CIPHER *evp_ssh1_bf(void);
57extern const EVP_CIPHER *evp_ssh1_3des(void); 56extern const EVP_CIPHER *evp_ssh1_3des(void);
58extern void ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int); 57extern int ssh1_3des_iv(EVP_CIPHER_CTX *, int, u_char *, int);
58#endif
59 59
60struct Cipher { 60struct sshcipher {
61 char *name; 61 char *name;
62 int number; /* for ssh1 only */ 62 int number; /* for ssh1 only */
63 u_int block_size; 63 u_int block_size;
@@ -68,15 +68,23 @@ struct Cipher {
68 u_int flags; 68 u_int flags;
69#define CFLAG_CBC (1<<0) 69#define CFLAG_CBC (1<<0)
70#define CFLAG_CHACHAPOLY (1<<1) 70#define CFLAG_CHACHAPOLY (1<<1)
71#define CFLAG_AESCTR (1<<2)
72#define CFLAG_NONE (1<<3)
73#ifdef WITH_OPENSSL
71 const EVP_CIPHER *(*evptype)(void); 74 const EVP_CIPHER *(*evptype)(void);
75#else
76 void *ignored;
77#endif
72}; 78};
73 79
74static const struct Cipher ciphers[] = { 80static const struct sshcipher ciphers[] = {
75 { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null }, 81#ifdef WITH_SSH1
76 { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc }, 82 { "des", SSH_CIPHER_DES, 8, 8, 0, 0, 0, 1, EVP_des_cbc },
77 { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des }, 83 { "3des", SSH_CIPHER_3DES, 8, 16, 0, 0, 0, 1, evp_ssh1_3des },
78 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf }, 84 { "blowfish", SSH_CIPHER_BLOWFISH, 8, 32, 0, 0, 0, 1, evp_ssh1_bf },
79 85#endif /* WITH_SSH1 */
86#ifdef WITH_OPENSSL
87 { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, 0, EVP_enc_null },
80 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc }, 88 { "3des-cbc", SSH_CIPHER_SSH2, 8, 24, 0, 0, 0, 1, EVP_des_ede3_cbc },
81 { "blowfish-cbc", 89 { "blowfish-cbc",
82 SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc }, 90 SSH_CIPHER_SSH2, 8, 16, 0, 0, 0, 1, EVP_bf_cbc },
@@ -93,26 +101,33 @@ static const struct Cipher ciphers[] = {
93 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr }, 101 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, 0, EVP_aes_128_ctr },
94 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr }, 102 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, 0, EVP_aes_192_ctr },
95 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr }, 103 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, 0, EVP_aes_256_ctr },
96#ifdef OPENSSL_HAVE_EVPGCM 104# ifdef OPENSSL_HAVE_EVPGCM
97 { "aes128-gcm@openssh.com", 105 { "aes128-gcm@openssh.com",
98 SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm }, 106 SSH_CIPHER_SSH2, 16, 16, 12, 16, 0, 0, EVP_aes_128_gcm },
99 { "aes256-gcm@openssh.com", 107 { "aes256-gcm@openssh.com",
100 SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm }, 108 SSH_CIPHER_SSH2, 16, 32, 12, 16, 0, 0, EVP_aes_256_gcm },
101#endif 109# endif /* OPENSSL_HAVE_EVPGCM */
110#else /* WITH_OPENSSL */
111 { "aes128-ctr", SSH_CIPHER_SSH2, 16, 16, 0, 0, 0, CFLAG_AESCTR, NULL },
112 { "aes192-ctr", SSH_CIPHER_SSH2, 16, 24, 0, 0, 0, CFLAG_AESCTR, NULL },
113 { "aes256-ctr", SSH_CIPHER_SSH2, 16, 32, 0, 0, 0, CFLAG_AESCTR, NULL },
114 { "none", SSH_CIPHER_NONE, 8, 0, 0, 0, 0, CFLAG_NONE, NULL },
115#endif /* WITH_OPENSSL */
102 { "chacha20-poly1305@openssh.com", 116 { "chacha20-poly1305@openssh.com",
103 SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL }, 117 SSH_CIPHER_SSH2, 8, 64, 0, 16, 0, CFLAG_CHACHAPOLY, NULL },
118
104 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL } 119 { NULL, SSH_CIPHER_INVALID, 0, 0, 0, 0, 0, 0, NULL }
105}; 120};
106 121
107/*--*/ 122/*--*/
108 123
109/* Returns a list of supported ciphers separated by the specified char. */ 124/* Returns a comma-separated list of supported ciphers. */
110char * 125char *
111cipher_alg_list(char sep, int auth_only) 126cipher_alg_list(char sep, int auth_only)
112{ 127{
113 char *ret = NULL; 128 char *tmp, *ret = NULL;
114 size_t nlen, rlen = 0; 129 size_t nlen, rlen = 0;
115 const Cipher *c; 130 const struct sshcipher *c;
116 131
117 for (c = ciphers; c->name != NULL; c++) { 132 for (c = ciphers; c->name != NULL; c++) {
118 if (c->number != SSH_CIPHER_SSH2) 133 if (c->number != SSH_CIPHER_SSH2)
@@ -122,7 +137,11 @@ cipher_alg_list(char sep, int auth_only)
122 if (ret != NULL) 137 if (ret != NULL)
123 ret[rlen++] = sep; 138 ret[rlen++] = sep;
124 nlen = strlen(c->name); 139 nlen = strlen(c->name);
125 ret = xrealloc(ret, 1, rlen + nlen + 2); 140 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
141 free(ret);
142 return NULL;
143 }
144 ret = tmp;
126 memcpy(ret + rlen, c->name, nlen + 1); 145 memcpy(ret + rlen, c->name, nlen + 1);
127 rlen += nlen; 146 rlen += nlen;
128 } 147 }
@@ -130,19 +149,19 @@ cipher_alg_list(char sep, int auth_only)
130} 149}
131 150
132u_int 151u_int
133cipher_blocksize(const Cipher *c) 152cipher_blocksize(const struct sshcipher *c)
134{ 153{
135 return (c->block_size); 154 return (c->block_size);
136} 155}
137 156
138u_int 157u_int
139cipher_keylen(const Cipher *c) 158cipher_keylen(const struct sshcipher *c)
140{ 159{
141 return (c->key_len); 160 return (c->key_len);
142} 161}
143 162
144u_int 163u_int
145cipher_seclen(const Cipher *c) 164cipher_seclen(const struct sshcipher *c)
146{ 165{
147 if (strcmp("3des-cbc", c->name) == 0) 166 if (strcmp("3des-cbc", c->name) == 0)
148 return 14; 167 return 14;
@@ -150,13 +169,13 @@ cipher_seclen(const Cipher *c)
150} 169}
151 170
152u_int 171u_int
153cipher_authlen(const Cipher *c) 172cipher_authlen(const struct sshcipher *c)
154{ 173{
155 return (c->auth_len); 174 return (c->auth_len);
156} 175}
157 176
158u_int 177u_int
159cipher_ivlen(const Cipher *c) 178cipher_ivlen(const struct sshcipher *c)
160{ 179{
161 /* 180 /*
162 * Default is cipher block size, except for chacha20+poly1305 that 181 * Default is cipher block size, except for chacha20+poly1305 that
@@ -167,13 +186,13 @@ cipher_ivlen(const Cipher *c)
167} 186}
168 187
169u_int 188u_int
170cipher_get_number(const Cipher *c) 189cipher_get_number(const struct sshcipher *c)
171{ 190{
172 return (c->number); 191 return (c->number);
173} 192}
174 193
175u_int 194u_int
176cipher_is_cbc(const Cipher *c) 195cipher_is_cbc(const struct sshcipher *c)
177{ 196{
178 return (c->flags & CFLAG_CBC) != 0; 197 return (c->flags & CFLAG_CBC) != 0;
179} 198}
@@ -190,20 +209,20 @@ cipher_mask_ssh1(int client)
190 return mask; 209 return mask;
191} 210}
192 211
193const Cipher * 212const struct sshcipher *
194cipher_by_name(const char *name) 213cipher_by_name(const char *name)
195{ 214{
196 const Cipher *c; 215 const struct sshcipher *c;
197 for (c = ciphers; c->name != NULL; c++) 216 for (c = ciphers; c->name != NULL; c++)
198 if (strcmp(c->name, name) == 0) 217 if (strcmp(c->name, name) == 0)
199 return c; 218 return c;
200 return NULL; 219 return NULL;
201} 220}
202 221
203const Cipher * 222const struct sshcipher *
204cipher_by_number(int id) 223cipher_by_number(int id)
205{ 224{
206 const Cipher *c; 225 const struct sshcipher *c;
207 for (c = ciphers; c->name != NULL; c++) 226 for (c = ciphers; c->name != NULL; c++)
208 if (c->number == id) 227 if (c->number == id)
209 return c; 228 return c;
@@ -214,23 +233,22 @@ cipher_by_number(int id)
214int 233int
215ciphers_valid(const char *names) 234ciphers_valid(const char *names)
216{ 235{
217 const Cipher *c; 236 const struct sshcipher *c;
218 char *cipher_list, *cp; 237 char *cipher_list, *cp;
219 char *p; 238 char *p;
220 239
221 if (names == NULL || strcmp(names, "") == 0) 240 if (names == NULL || strcmp(names, "") == 0)
222 return 0; 241 return 0;
223 cipher_list = cp = xstrdup(names); 242 if ((cipher_list = cp = strdup(names)) == NULL)
243 return 0;
224 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0'; 244 for ((p = strsep(&cp, CIPHER_SEP)); p && *p != '\0';
225 (p = strsep(&cp, CIPHER_SEP))) { 245 (p = strsep(&cp, CIPHER_SEP))) {
226 c = cipher_by_name(p); 246 c = cipher_by_name(p);
227 if (c == NULL || c->number != SSH_CIPHER_SSH2) { 247 if (c == NULL || c->number != SSH_CIPHER_SSH2) {
228 debug("bad cipher %s [%s]", p, names);
229 free(cipher_list); 248 free(cipher_list);
230 return 0; 249 return 0;
231 } 250 }
232 } 251 }
233 debug3("ciphers ok: [%s]", names);
234 free(cipher_list); 252 free(cipher_list);
235 return 1; 253 return 1;
236} 254}
@@ -243,7 +261,7 @@ ciphers_valid(const char *names)
243int 261int
244cipher_number(const char *name) 262cipher_number(const char *name)
245{ 263{
246 const Cipher *c; 264 const struct sshcipher *c;
247 if (name == NULL) 265 if (name == NULL)
248 return -1; 266 return -1;
249 for (c = ciphers; c->name != NULL; c++) 267 for (c = ciphers; c->name != NULL; c++)
@@ -255,90 +273,104 @@ cipher_number(const char *name)
255char * 273char *
256cipher_name(int id) 274cipher_name(int id)
257{ 275{
258 const Cipher *c = cipher_by_number(id); 276 const struct sshcipher *c = cipher_by_number(id);
259 return (c==NULL) ? "<unknown>" : c->name; 277 return (c==NULL) ? "<unknown>" : c->name;
260} 278}
261 279
262void 280const char *
263cipher_init(CipherContext *cc, const Cipher *cipher, 281cipher_warning_message(const struct sshcipher_ctx *cc)
282{
283 if (cc == NULL || cc->cipher == NULL)
284 return NULL;
285 if (cc->cipher->number == SSH_CIPHER_DES)
286 return "use of DES is strongly discouraged due to "
287 "cryptographic weaknesses";
288 return NULL;
289}
290
291int
292cipher_init(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
264 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen, 293 const u_char *key, u_int keylen, const u_char *iv, u_int ivlen,
265 int do_encrypt) 294 int do_encrypt)
266{ 295{
267 static int dowarn = 1; 296#ifdef WITH_OPENSSL
268#ifdef SSH_OLD_EVP 297 int ret = SSH_ERR_INTERNAL_ERROR;
269 EVP_CIPHER *type;
270#else
271 const EVP_CIPHER *type; 298 const EVP_CIPHER *type;
272 int klen; 299 int klen;
273#endif
274 u_char *junk, *discard; 300 u_char *junk, *discard;
275 301
276 if (cipher->number == SSH_CIPHER_DES) { 302 if (cipher->number == SSH_CIPHER_DES) {
277 if (dowarn) {
278 error("Warning: use of DES is strongly discouraged "
279 "due to cryptographic weaknesses");
280 dowarn = 0;
281 }
282 if (keylen > 8) 303 if (keylen > 8)
283 keylen = 8; 304 keylen = 8;
284 } 305 }
306#endif
285 cc->plaintext = (cipher->number == SSH_CIPHER_NONE); 307 cc->plaintext = (cipher->number == SSH_CIPHER_NONE);
286 cc->encrypt = do_encrypt; 308 cc->encrypt = do_encrypt;
287 309
288 if (keylen < cipher->key_len) 310 if (keylen < cipher->key_len ||
289 fatal("cipher_init: key length %d is insufficient for %s.", 311 (iv != NULL && ivlen < cipher_ivlen(cipher)))
290 keylen, cipher->name); 312 return SSH_ERR_INVALID_ARGUMENT;
291 if (iv != NULL && ivlen < cipher_ivlen(cipher))
292 fatal("cipher_init: iv length %d is insufficient for %s.",
293 ivlen, cipher->name);
294 cc->cipher = cipher;
295 313
314 cc->cipher = cipher;
296 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 315 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
297 chachapoly_init(&cc->cp_ctx, key, keylen); 316 return chachapoly_init(&cc->cp_ctx, key, keylen);
298 return;
299 } 317 }
300 type = (*cipher->evptype)(); 318#ifndef WITH_OPENSSL
301 EVP_CIPHER_CTX_init(&cc->evp); 319 if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
302#ifdef SSH_OLD_EVP 320 aesctr_keysetup(&cc->ac_ctx, key, 8 * keylen, 8 * ivlen);
303 if (type->key_len > 0 && type->key_len != keylen) { 321 aesctr_ivsetup(&cc->ac_ctx, iv);
304 debug("cipher_init: set keylen (%d -> %d)", 322 return 0;
305 type->key_len, keylen);
306 type->key_len = keylen;
307 } 323 }
308 EVP_CipherInit(&cc->evp, type, (u_char *)key, (u_char *)iv, 324 if ((cc->cipher->flags & CFLAG_NONE) != 0)
309 (do_encrypt == CIPHER_ENCRYPT)); 325 return 0;
326 return SSH_ERR_INVALID_ARGUMENT;
310#else 327#else
328 type = (*cipher->evptype)();
329 EVP_CIPHER_CTX_init(&cc->evp);
311 if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv, 330 if (EVP_CipherInit(&cc->evp, type, NULL, (u_char *)iv,
312 (do_encrypt == CIPHER_ENCRYPT)) == 0) 331 (do_encrypt == CIPHER_ENCRYPT)) == 0) {
313 fatal("cipher_init: EVP_CipherInit failed for %s", 332 ret = SSH_ERR_LIBCRYPTO_ERROR;
314 cipher->name); 333 goto bad;
334 }
315 if (cipher_authlen(cipher) && 335 if (cipher_authlen(cipher) &&
316 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED, 336 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_IV_FIXED,
317 -1, (u_char *)iv)) 337 -1, (u_char *)iv)) {
318 fatal("cipher_init: EVP_CTRL_GCM_SET_IV_FIXED failed for %s", 338 ret = SSH_ERR_LIBCRYPTO_ERROR;
319 cipher->name); 339 goto bad;
340 }
320 klen = EVP_CIPHER_CTX_key_length(&cc->evp); 341 klen = EVP_CIPHER_CTX_key_length(&cc->evp);
321 if (klen > 0 && keylen != (u_int)klen) { 342 if (klen > 0 && keylen != (u_int)klen) {
322 debug2("cipher_init: set keylen (%d -> %d)", klen, keylen); 343 if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) {
323 if (EVP_CIPHER_CTX_set_key_length(&cc->evp, keylen) == 0) 344 ret = SSH_ERR_LIBCRYPTO_ERROR;
324 fatal("cipher_init: set keylen failed (%d -> %d)", 345 goto bad;
325 klen, keylen); 346 }
347 }
348 if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0) {
349 ret = SSH_ERR_LIBCRYPTO_ERROR;
350 goto bad;
326 } 351 }
327 if (EVP_CipherInit(&cc->evp, NULL, (u_char *)key, NULL, -1) == 0)
328 fatal("cipher_init: EVP_CipherInit: set key failed for %s",
329 cipher->name);
330#endif
331 352
332 if (cipher->discard_len > 0) { 353 if (cipher->discard_len > 0) {
333 junk = xmalloc(cipher->discard_len); 354 if ((junk = malloc(cipher->discard_len)) == NULL ||
334 discard = xmalloc(cipher->discard_len); 355 (discard = malloc(cipher->discard_len)) == NULL) {
335 if (EVP_Cipher(&cc->evp, discard, junk, 356 if (junk != NULL)
336 cipher->discard_len) == 0) 357 free(junk);
337 fatal("evp_crypt: EVP_Cipher failed during discard"); 358 ret = SSH_ERR_ALLOC_FAIL;
359 goto bad;
360 }
361 ret = EVP_Cipher(&cc->evp, discard, junk, cipher->discard_len);
338 explicit_bzero(discard, cipher->discard_len); 362 explicit_bzero(discard, cipher->discard_len);
339 free(junk); 363 free(junk);
340 free(discard); 364 free(discard);
365 if (ret != 1) {
366 ret = SSH_ERR_LIBCRYPTO_ERROR;
367 bad:
368 EVP_CIPHER_CTX_cleanup(&cc->evp);
369 return ret;
370 }
341 } 371 }
372#endif
373 return 0;
342} 374}
343 375
344/* 376/*
@@ -350,204 +382,244 @@ cipher_init(CipherContext *cc, const Cipher *cipher,
350 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag. 382 * Use 'authlen' bytes at offset 'len'+'aadlen' as the authentication tag.
351 * This tag is written on encryption and verified on decryption. 383 * This tag is written on encryption and verified on decryption.
352 * Both 'aadlen' and 'authlen' can be set to 0. 384 * Both 'aadlen' and 'authlen' can be set to 0.
353 * cipher_crypt() returns 0 on success and -1 if the decryption integrity
354 * check fails.
355 */ 385 */
356int 386int
357cipher_crypt(CipherContext *cc, u_int seqnr, u_char *dest, const u_char *src, 387cipher_crypt(struct sshcipher_ctx *cc, u_int seqnr, u_char *dest,
358 u_int len, u_int aadlen, u_int authlen) 388 const u_char *src, u_int len, u_int aadlen, u_int authlen)
359{ 389{
360 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 390 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
361 return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src, len, 391 return chachapoly_crypt(&cc->cp_ctx, seqnr, dest, src,
362 aadlen, authlen, cc->encrypt); 392 len, aadlen, authlen, cc->encrypt);
393 }
394#ifndef WITH_OPENSSL
395 if ((cc->cipher->flags & CFLAG_AESCTR) != 0) {
396 if (aadlen)
397 memcpy(dest, src, aadlen);
398 aesctr_encrypt_bytes(&cc->ac_ctx, src + aadlen,
399 dest + aadlen, len);
400 return 0;
401 }
402 if ((cc->cipher->flags & CFLAG_NONE) != 0) {
403 memcpy(dest, src, aadlen + len);
404 return 0;
405 }
406 return SSH_ERR_INVALID_ARGUMENT;
407#else
363 if (authlen) { 408 if (authlen) {
364 u_char lastiv[1]; 409 u_char lastiv[1];
365 410
366 if (authlen != cipher_authlen(cc->cipher)) 411 if (authlen != cipher_authlen(cc->cipher))
367 fatal("%s: authlen mismatch %d", __func__, authlen); 412 return SSH_ERR_INVALID_ARGUMENT;
368 /* increment IV */ 413 /* increment IV */
369 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN, 414 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
370 1, lastiv)) 415 1, lastiv))
371 fatal("%s: EVP_CTRL_GCM_IV_GEN", __func__); 416 return SSH_ERR_LIBCRYPTO_ERROR;
372 /* set tag on decyption */ 417 /* set tag on decyption */
373 if (!cc->encrypt && 418 if (!cc->encrypt &&
374 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG, 419 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_SET_TAG,
375 authlen, (u_char *)src + aadlen + len)) 420 authlen, (u_char *)src + aadlen + len))
376 fatal("%s: EVP_CTRL_GCM_SET_TAG", __func__); 421 return SSH_ERR_LIBCRYPTO_ERROR;
377 } 422 }
378 if (aadlen) { 423 if (aadlen) {
379 if (authlen && 424 if (authlen &&
380 EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0) 425 EVP_Cipher(&cc->evp, NULL, (u_char *)src, aadlen) < 0)
381 fatal("%s: EVP_Cipher(aad) failed", __func__); 426 return SSH_ERR_LIBCRYPTO_ERROR;
382 memcpy(dest, src, aadlen); 427 memcpy(dest, src, aadlen);
383 } 428 }
384 if (len % cc->cipher->block_size) 429 if (len % cc->cipher->block_size)
385 fatal("%s: bad plaintext length %d", __func__, len); 430 return SSH_ERR_INVALID_ARGUMENT;
386 if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen, 431 if (EVP_Cipher(&cc->evp, dest + aadlen, (u_char *)src + aadlen,
387 len) < 0) 432 len) < 0)
388 fatal("%s: EVP_Cipher failed", __func__); 433 return SSH_ERR_LIBCRYPTO_ERROR;
389 if (authlen) { 434 if (authlen) {
390 /* compute tag (on encrypt) or verify tag (on decrypt) */ 435 /* compute tag (on encrypt) or verify tag (on decrypt) */
391 if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0) { 436 if (EVP_Cipher(&cc->evp, NULL, NULL, 0) < 0)
392 if (cc->encrypt) 437 return cc->encrypt ?
393 fatal("%s: EVP_Cipher(final) failed", __func__); 438 SSH_ERR_LIBCRYPTO_ERROR : SSH_ERR_MAC_INVALID;
394 else
395 return -1;
396 }
397 if (cc->encrypt && 439 if (cc->encrypt &&
398 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG, 440 !EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_GET_TAG,
399 authlen, dest + aadlen + len)) 441 authlen, dest + aadlen + len))
400 fatal("%s: EVP_CTRL_GCM_GET_TAG", __func__); 442 return SSH_ERR_LIBCRYPTO_ERROR;
401 } 443 }
402 return 0; 444 return 0;
445#endif
403} 446}
404 447
405/* Extract the packet length, including any decryption necessary beforehand */ 448/* Extract the packet length, including any decryption necessary beforehand */
406int 449int
407cipher_get_length(CipherContext *cc, u_int *plenp, u_int seqnr, 450cipher_get_length(struct sshcipher_ctx *cc, u_int *plenp, u_int seqnr,
408 const u_char *cp, u_int len) 451 const u_char *cp, u_int len)
409{ 452{
410 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 453 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
411 return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr, 454 return chachapoly_get_length(&cc->cp_ctx, plenp, seqnr,
412 cp, len); 455 cp, len);
413 if (len < 4) 456 if (len < 4)
414 return -1; 457 return SSH_ERR_MESSAGE_INCOMPLETE;
415 *plenp = get_u32(cp); 458 *plenp = get_u32(cp);
416 return 0; 459 return 0;
417} 460}
418 461
419void 462int
420cipher_cleanup(CipherContext *cc) 463cipher_cleanup(struct sshcipher_ctx *cc)
421{ 464{
465 if (cc == NULL || cc->cipher == NULL)
466 return 0;
422 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 467 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
423 explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx)); 468 explicit_bzero(&cc->cp_ctx, sizeof(cc->cp_ctx));
469 else if ((cc->cipher->flags & CFLAG_AESCTR) != 0)
470 explicit_bzero(&cc->ac_ctx, sizeof(cc->ac_ctx));
471#ifdef WITH_OPENSSL
424 else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0) 472 else if (EVP_CIPHER_CTX_cleanup(&cc->evp) == 0)
425 error("cipher_cleanup: EVP_CIPHER_CTX_cleanup failed"); 473 return SSH_ERR_LIBCRYPTO_ERROR;
474#endif
475 return 0;
426} 476}
427 477
428/* 478/*
429 * Selects the cipher, and keys if by computing the MD5 checksum of the 479 * Selects the cipher, and keys if by computing the MD5 checksum of the
430 * passphrase and using the resulting 16 bytes as the key. 480 * passphrase and using the resulting 16 bytes as the key.
431 */ 481 */
432 482int
433void 483cipher_set_key_string(struct sshcipher_ctx *cc, const struct sshcipher *cipher,
434cipher_set_key_string(CipherContext *cc, const Cipher *cipher,
435 const char *passphrase, int do_encrypt) 484 const char *passphrase, int do_encrypt)
436{ 485{
437 u_char digest[16]; 486 u_char digest[16];
487 int r = SSH_ERR_INTERNAL_ERROR;
438 488
439 if (ssh_digest_memory(SSH_DIGEST_MD5, passphrase, strlen(passphrase), 489 if ((r = ssh_digest_memory(SSH_DIGEST_MD5,
440 digest, sizeof(digest)) < 0) 490 passphrase, strlen(passphrase),
441 fatal("%s: md5 failed", __func__); 491 digest, sizeof(digest))) != 0)
442 492 goto out;
443 cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
444 493
494 r = cipher_init(cc, cipher, digest, 16, NULL, 0, do_encrypt);
495 out:
445 explicit_bzero(digest, sizeof(digest)); 496 explicit_bzero(digest, sizeof(digest));
497 return r;
446} 498}
447 499
448/* 500/*
449 * Exports an IV from the CipherContext required to export the key 501 * Exports an IV from the sshcipher_ctx required to export the key
450 * state back from the unprivileged child to the privileged parent 502 * state back from the unprivileged child to the privileged parent
451 * process. 503 * process.
452 */ 504 */
453
454int 505int
455cipher_get_keyiv_len(const CipherContext *cc) 506cipher_get_keyiv_len(const struct sshcipher_ctx *cc)
456{ 507{
457 const Cipher *c = cc->cipher; 508 const struct sshcipher *c = cc->cipher;
458 int ivlen; 509 int ivlen = 0;
459 510
460 if (c->number == SSH_CIPHER_3DES) 511 if (c->number == SSH_CIPHER_3DES)
461 ivlen = 24; 512 ivlen = 24;
462 else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 513 else if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
463 ivlen = 0; 514 ivlen = 0;
515#ifdef WITH_OPENSSL
464 else 516 else
465 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp); 517 ivlen = EVP_CIPHER_CTX_iv_length(&cc->evp);
518#endif /* WITH_OPENSSL */
466 return (ivlen); 519 return (ivlen);
467} 520}
468 521
469void 522int
470cipher_get_keyiv(CipherContext *cc, u_char *iv, u_int len) 523cipher_get_keyiv(struct sshcipher_ctx *cc, u_char *iv, u_int len)
471{ 524{
472 const Cipher *c = cc->cipher; 525 const struct sshcipher *c = cc->cipher;
473 int evplen; 526#ifdef WITH_OPENSSL
527 int evplen;
528#endif
474 529
475 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) { 530 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) {
476 if (len != 0) 531 if (len != 0)
477 fatal("%s: wrong iv length %d != %d", __func__, len, 0); 532 return SSH_ERR_INVALID_ARGUMENT;
478 return; 533 return 0;
479 } 534 }
535 if ((cc->cipher->flags & CFLAG_NONE) != 0)
536 return 0;
480 537
481 switch (c->number) { 538 switch (c->number) {
539#ifdef WITH_OPENSSL
482 case SSH_CIPHER_SSH2: 540 case SSH_CIPHER_SSH2:
483 case SSH_CIPHER_DES: 541 case SSH_CIPHER_DES:
484 case SSH_CIPHER_BLOWFISH: 542 case SSH_CIPHER_BLOWFISH:
485 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); 543 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
486 if (evplen <= 0) 544 if (evplen == 0)
487 return; 545 return 0;
546 else if (evplen < 0)
547 return SSH_ERR_LIBCRYPTO_ERROR;
488 if ((u_int)evplen != len) 548 if ((u_int)evplen != len)
489 fatal("%s: wrong iv length %d != %d", __func__, 549 return SSH_ERR_INVALID_ARGUMENT;
490 evplen, len);
491#ifdef USE_BUILTIN_RIJNDAEL
492 if (c->evptype == evp_rijndael)
493 ssh_rijndael_iv(&cc->evp, 0, iv, len);
494 else
495#endif
496#ifndef OPENSSL_HAVE_EVPCTR 550#ifndef OPENSSL_HAVE_EVPCTR
497 if (c->evptype == evp_aes_128_ctr) 551 if (c->evptype == evp_aes_128_ctr)
498 ssh_aes_ctr_iv(&cc->evp, 0, iv, len); 552 ssh_aes_ctr_iv(&cc->evp, 0, iv, len);
499 else 553 else
500#endif 554#endif
501 memcpy(iv, cc->evp.iv, len); 555 if (cipher_authlen(c)) {
556 if (!EVP_CIPHER_CTX_ctrl(&cc->evp, EVP_CTRL_GCM_IV_GEN,
557 len, iv))
558 return SSH_ERR_LIBCRYPTO_ERROR;
559 } else
560 memcpy(iv, cc->evp.iv, len);
502 break; 561 break;
562#endif
563#ifdef WITH_SSH1
503 case SSH_CIPHER_3DES: 564 case SSH_CIPHER_3DES:
504 ssh1_3des_iv(&cc->evp, 0, iv, 24); 565 return ssh1_3des_iv(&cc->evp, 0, iv, 24);
505 break; 566#endif
506 default: 567 default:
507 fatal("%s: bad cipher %d", __func__, c->number); 568 return SSH_ERR_INVALID_ARGUMENT;
508 } 569 }
570 return 0;
509} 571}
510 572
511void 573int
512cipher_set_keyiv(CipherContext *cc, u_char *iv) 574cipher_set_keyiv(struct sshcipher_ctx *cc, const u_char *iv)
513{ 575{
514 const Cipher *c = cc->cipher; 576 const struct sshcipher *c = cc->cipher;
515 int evplen = 0; 577#ifdef WITH_OPENSSL
578 int evplen = 0;
579#endif
516 580
517 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0) 581 if ((cc->cipher->flags & CFLAG_CHACHAPOLY) != 0)
518 return; 582 return 0;
583 if ((cc->cipher->flags & CFLAG_NONE) != 0)
584 return 0;
519 585
520 switch (c->number) { 586 switch (c->number) {
587#ifdef WITH_OPENSSL
521 case SSH_CIPHER_SSH2: 588 case SSH_CIPHER_SSH2:
522 case SSH_CIPHER_DES: 589 case SSH_CIPHER_DES:
523 case SSH_CIPHER_BLOWFISH: 590 case SSH_CIPHER_BLOWFISH:
524 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp); 591 evplen = EVP_CIPHER_CTX_iv_length(&cc->evp);
525 if (evplen == 0) 592 if (evplen <= 0)
526 return; 593 return SSH_ERR_LIBCRYPTO_ERROR;
527#ifdef USE_BUILTIN_RIJNDAEL 594 if (cipher_authlen(c)) {
528 if (c->evptype == evp_rijndael) 595 /* XXX iv arg is const, but EVP_CIPHER_CTX_ctrl isn't */
529 ssh_rijndael_iv(&cc->evp, 1, iv, evplen); 596 if (!EVP_CIPHER_CTX_ctrl(&cc->evp,
530 else 597 EVP_CTRL_GCM_SET_IV_FIXED, -1, (void *)iv))
531#endif 598 return SSH_ERR_LIBCRYPTO_ERROR;
532#ifndef OPENSSL_HAVE_EVPCTR 599 } else
533 if (c->evptype == evp_aes_128_ctr) 600 memcpy(cc->evp.iv, iv, evplen);
534 ssh_aes_ctr_iv(&cc->evp, 1, iv, evplen);
535 else
536#endif
537 memcpy(cc->evp.iv, iv, evplen);
538 break; 601 break;
602#endif
603#ifdef WITH_SSH1
539 case SSH_CIPHER_3DES: 604 case SSH_CIPHER_3DES:
540 ssh1_3des_iv(&cc->evp, 1, iv, 24); 605 return ssh1_3des_iv(&cc->evp, 1, (u_char *)iv, 24);
541 break; 606#endif
542 default: 607 default:
543 fatal("%s: bad cipher %d", __func__, c->number); 608 return SSH_ERR_INVALID_ARGUMENT;
544 } 609 }
610 return 0;
545} 611}
546 612
613#ifdef WITH_OPENSSL
614#define EVP_X_STATE(evp) (evp).cipher_data
615#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
616#endif
617
547int 618int
548cipher_get_keycontext(const CipherContext *cc, u_char *dat) 619cipher_get_keycontext(const struct sshcipher_ctx *cc, u_char *dat)
549{ 620{
550 const Cipher *c = cc->cipher; 621#ifdef WITH_OPENSSL
622 const struct sshcipher *c = cc->cipher;
551 int plen = 0; 623 int plen = 0;
552 624
553 if (c->evptype == EVP_rc4) { 625 if (c->evptype == EVP_rc4) {
@@ -557,16 +629,21 @@ cipher_get_keycontext(const CipherContext *cc, u_char *dat)
557 memcpy(dat, EVP_X_STATE(cc->evp), plen); 629 memcpy(dat, EVP_X_STATE(cc->evp), plen);
558 } 630 }
559 return (plen); 631 return (plen);
632#else
633 return 0;
634#endif
560} 635}
561 636
562void 637void
563cipher_set_keycontext(CipherContext *cc, u_char *dat) 638cipher_set_keycontext(struct sshcipher_ctx *cc, const u_char *dat)
564{ 639{
565 const Cipher *c = cc->cipher; 640#ifdef WITH_OPENSSL
641 const struct sshcipher *c = cc->cipher;
566 int plen; 642 int plen;
567 643
568 if (c->evptype == EVP_rc4) { 644 if (c->evptype == EVP_rc4) {
569 plen = EVP_X_STATE_LEN(cc->evp); 645 plen = EVP_X_STATE_LEN(cc->evp);
570 memcpy(EVP_X_STATE(cc->evp), dat, plen); 646 memcpy(EVP_X_STATE(cc->evp), dat, plen);
571 } 647 }
648#endif
572} 649}
diff --git a/cipher.h b/cipher.h
index 133d2e73d..de74c1e3b 100644
--- a/cipher.h
+++ b/cipher.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: cipher.h,v 1.44 2014/01/25 10:12:50 dtucker Exp $ */ 1/* $OpenBSD: cipher.h,v 1.46 2014/06/24 01:13:21 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -37,8 +37,10 @@
37#ifndef CIPHER_H 37#ifndef CIPHER_H
38#define CIPHER_H 38#define CIPHER_H
39 39
40#include <sys/types.h>
40#include <openssl/evp.h> 41#include <openssl/evp.h>
41#include "cipher-chachapoly.h" 42#include "cipher-chachapoly.h"
43#include "cipher-aesctr.h"
42 44
43/* 45/*
44 * Cipher types for SSH-1. New types can be added, but old types should not 46 * Cipher types for SSH-1. New types can be added, but old types should not
@@ -60,44 +62,47 @@
60#define CIPHER_ENCRYPT 1 62#define CIPHER_ENCRYPT 1
61#define CIPHER_DECRYPT 0 63#define CIPHER_DECRYPT 0
62 64
63typedef struct Cipher Cipher; 65struct sshcipher;
64typedef struct CipherContext CipherContext; 66struct sshcipher_ctx {
65
66struct Cipher;
67struct CipherContext {
68 int plaintext; 67 int plaintext;
69 int encrypt; 68 int encrypt;
70 EVP_CIPHER_CTX evp; 69 EVP_CIPHER_CTX evp;
71 struct chachapoly_ctx cp_ctx; /* XXX union with evp? */ 70 struct chachapoly_ctx cp_ctx; /* XXX union with evp? */
72 const Cipher *cipher; 71 struct aesctr_ctx ac_ctx; /* XXX union with evp? */
72 const struct sshcipher *cipher;
73}; 73};
74 74
75typedef struct sshcipher Cipher ;
76typedef struct sshcipher_ctx CipherContext ;
77
75u_int cipher_mask_ssh1(int); 78u_int cipher_mask_ssh1(int);
76const Cipher *cipher_by_name(const char *); 79const struct sshcipher *cipher_by_name(const char *);
77const Cipher *cipher_by_number(int); 80const struct sshcipher *cipher_by_number(int);
78int cipher_number(const char *); 81int cipher_number(const char *);
79char *cipher_name(int); 82char *cipher_name(int);
80int ciphers_valid(const char *); 83int ciphers_valid(const char *);
81char *cipher_alg_list(char, int); 84char *cipher_alg_list(char, int);
82void cipher_init(CipherContext *, const Cipher *, const u_char *, u_int, 85int cipher_init(struct sshcipher_ctx *, const struct sshcipher *,
83 const u_char *, u_int, int); 86 const u_char *, u_int, const u_char *, u_int, int);
84int cipher_crypt(CipherContext *, u_int, u_char *, const u_char *, 87const char* cipher_warning_message(const struct sshcipher_ctx *);
88int cipher_crypt(struct sshcipher_ctx *, u_int, u_char *, const u_char *,
85 u_int, u_int, u_int); 89 u_int, u_int, u_int);
86int cipher_get_length(CipherContext *, u_int *, u_int, 90int cipher_get_length(struct sshcipher_ctx *, u_int *, u_int,
87 const u_char *, u_int); 91 const u_char *, u_int);
88void cipher_cleanup(CipherContext *); 92int cipher_cleanup(struct sshcipher_ctx *);
89void cipher_set_key_string(CipherContext *, const Cipher *, const char *, int); 93int cipher_set_key_string(struct sshcipher_ctx *, const struct sshcipher *,
90u_int cipher_blocksize(const Cipher *); 94 const char *, int);
91u_int cipher_keylen(const Cipher *); 95u_int cipher_blocksize(const struct sshcipher *);
92u_int cipher_seclen(const Cipher *); 96u_int cipher_keylen(const struct sshcipher *);
93u_int cipher_authlen(const Cipher *); 97u_int cipher_seclen(const struct sshcipher *);
94u_int cipher_ivlen(const Cipher *); 98u_int cipher_authlen(const struct sshcipher *);
95u_int cipher_is_cbc(const Cipher *); 99u_int cipher_ivlen(const struct sshcipher *);
100u_int cipher_is_cbc(const struct sshcipher *);
96 101
97u_int cipher_get_number(const Cipher *); 102u_int cipher_get_number(const struct sshcipher *);
98void cipher_get_keyiv(CipherContext *, u_char *, u_int); 103int cipher_get_keyiv(struct sshcipher_ctx *, u_char *, u_int);
99void cipher_set_keyiv(CipherContext *, u_char *); 104int cipher_set_keyiv(struct sshcipher_ctx *, const u_char *);
100int cipher_get_keyiv_len(const CipherContext *); 105int cipher_get_keyiv_len(const struct sshcipher_ctx *);
101int cipher_get_keycontext(const CipherContext *, u_char *); 106int cipher_get_keycontext(const struct sshcipher_ctx *, u_char *);
102void cipher_set_keycontext(CipherContext *, u_char *); 107void cipher_set_keycontext(struct sshcipher_ctx *, const u_char *);
103#endif /* CIPHER_H */ 108#endif /* CIPHER_H */
diff --git a/clientloop.c b/clientloop.c
index 4bc5b57d2..0180774bb 100644
--- a/clientloop.c
+++ b/clientloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: clientloop.c,v 1.258 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: clientloop.c,v 1.261 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -100,13 +100,13 @@
100#include "cipher.h" 100#include "cipher.h"
101#include "kex.h" 101#include "kex.h"
102#include "log.h" 102#include "log.h"
103#include "misc.h"
103#include "readconf.h" 104#include "readconf.h"
104#include "clientloop.h" 105#include "clientloop.h"
105#include "sshconnect.h" 106#include "sshconnect.h"
106#include "authfd.h" 107#include "authfd.h"
107#include "atomicio.h" 108#include "atomicio.h"
108#include "sshpty.h" 109#include "sshpty.h"
109#include "misc.h"
110#include "match.h" 110#include "match.h"
111#include "msg.h" 111#include "msg.h"
112#include "roaming.h" 112#include "roaming.h"
@@ -880,13 +880,11 @@ static void
880process_cmdline(void) 880process_cmdline(void)
881{ 881{
882 void (*handler)(int); 882 void (*handler)(int);
883 char *s, *cmd, *cancel_host; 883 char *s, *cmd;
884 int delete = 0, local = 0, remote = 0, dynamic = 0; 884 int ok, delete = 0, local = 0, remote = 0, dynamic = 0;
885 int cancel_port, ok; 885 struct Forward fwd;
886 Forward fwd;
887 886
888 memset(&fwd, 0, sizeof(fwd)); 887 memset(&fwd, 0, sizeof(fwd));
889 fwd.listen_host = fwd.connect_host = NULL;
890 888
891 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 889 leave_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
892 handler = signal(SIGINT, SIG_IGN); 890 handler = signal(SIGINT, SIG_IGN);
@@ -952,29 +950,20 @@ process_cmdline(void)
952 950
953 /* XXX update list of forwards in options */ 951 /* XXX update list of forwards in options */
954 if (delete) { 952 if (delete) {
955 cancel_port = 0; 953 /* We pass 1 for dynamicfwd to restrict to 1 or 2 fields. */
956 cancel_host = hpdelim(&s); /* may be NULL */ 954 if (!parse_forward(&fwd, s, 1, 0)) {
957 if (s != NULL) { 955 logit("Bad forwarding close specification.");
958 cancel_port = a2port(s);
959 cancel_host = cleanhostname(cancel_host);
960 } else {
961 cancel_port = a2port(cancel_host);
962 cancel_host = NULL;
963 }
964 if (cancel_port <= 0) {
965 logit("Bad forwarding close port");
966 goto out; 956 goto out;
967 } 957 }
968 if (remote) 958 if (remote)
969 ok = channel_request_rforward_cancel(cancel_host, 959 ok = channel_request_rforward_cancel(&fwd) == 0;
970 cancel_port) == 0;
971 else if (dynamic) 960 else if (dynamic)
972 ok = channel_cancel_lport_listener(cancel_host, 961 ok = channel_cancel_lport_listener(&fwd,
973 cancel_port, 0, options.gateway_ports) > 0; 962 0, &options.fwd_opts) > 0;
974 else 963 else
975 ok = channel_cancel_lport_listener(cancel_host, 964 ok = channel_cancel_lport_listener(&fwd,
976 cancel_port, CHANNEL_CANCEL_PORT_STATIC, 965 CHANNEL_CANCEL_PORT_STATIC,
977 options.gateway_ports) > 0; 966 &options.fwd_opts) > 0;
978 if (!ok) { 967 if (!ok) {
979 logit("Unkown port forwarding."); 968 logit("Unkown port forwarding.");
980 goto out; 969 goto out;
@@ -986,16 +975,13 @@ process_cmdline(void)
986 goto out; 975 goto out;
987 } 976 }
988 if (local || dynamic) { 977 if (local || dynamic) {
989 if (!channel_setup_local_fwd_listener(fwd.listen_host, 978 if (!channel_setup_local_fwd_listener(&fwd,
990 fwd.listen_port, fwd.connect_host, 979 &options.fwd_opts)) {
991 fwd.connect_port, options.gateway_ports)) {
992 logit("Port forwarding failed."); 980 logit("Port forwarding failed.");
993 goto out; 981 goto out;
994 } 982 }
995 } else { 983 } else {
996 if (channel_request_remote_forwarding(fwd.listen_host, 984 if (channel_request_remote_forwarding(&fwd) < 0) {
997 fwd.listen_port, fwd.connect_host,
998 fwd.connect_port) < 0) {
999 logit("Port forwarding failed."); 985 logit("Port forwarding failed.");
1000 goto out; 986 goto out;
1001 } 987 }
@@ -1008,7 +994,9 @@ out:
1008 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE); 994 enter_raw_mode(options.request_tty == REQUEST_TTY_FORCE);
1009 free(cmd); 995 free(cmd);
1010 free(fwd.listen_host); 996 free(fwd.listen_host);
997 free(fwd.listen_path);
1011 free(fwd.connect_host); 998 free(fwd.connect_host);
999 free(fwd.connect_path);
1012} 1000}
1013 1001
1014/* reasons to suppress output of an escape command in help output */ 1002/* reasons to suppress output of an escape command in help output */
@@ -1865,11 +1853,10 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1865 originator_port = packet_get_int(); 1853 originator_port = packet_get_int();
1866 packet_check_eom(); 1854 packet_check_eom();
1867 1855
1868 debug("client_request_forwarded_tcpip: listen %s port %d, " 1856 debug("%s: listen %s port %d, originator %s port %d", __func__,
1869 "originator %s port %d", listen_address, listen_port, 1857 listen_address, listen_port, originator_address, originator_port);
1870 originator_address, originator_port);
1871 1858
1872 c = channel_connect_by_listen_address(listen_port, 1859 c = channel_connect_by_listen_address(listen_address, listen_port,
1873 "forwarded-tcpip", originator_address); 1860 "forwarded-tcpip", originator_address);
1874 1861
1875 free(originator_address); 1862 free(originator_address);
@@ -1878,6 +1865,27 @@ client_request_forwarded_tcpip(const char *request_type, int rchan)
1878} 1865}
1879 1866
1880static Channel * 1867static Channel *
1868client_request_forwarded_streamlocal(const char *request_type, int rchan)
1869{
1870 Channel *c = NULL;
1871 char *listen_path;
1872
1873 /* Get the remote path. */
1874 listen_path = packet_get_string(NULL);
1875 /* XXX: Skip reserved field for now. */
1876 if (packet_get_string_ptr(NULL) == NULL)
1877 fatal("%s: packet_get_string_ptr failed", __func__);
1878 packet_check_eom();
1879
1880 debug("%s: %s", __func__, listen_path);
1881
1882 c = channel_connect_by_listen_path(listen_path,
1883 "forwarded-streamlocal@openssh.com", "forwarded-streamlocal");
1884 free(listen_path);
1885 return c;
1886}
1887
1888static Channel *
1881client_request_x11(const char *request_type, int rchan) 1889client_request_x11(const char *request_type, int rchan)
1882{ 1890{
1883 Channel *c = NULL; 1891 Channel *c = NULL;
@@ -2004,6 +2012,8 @@ client_input_channel_open(int type, u_int32_t seq, void *ctxt)
2004 2012
2005 if (strcmp(ctype, "forwarded-tcpip") == 0) { 2013 if (strcmp(ctype, "forwarded-tcpip") == 0) {
2006 c = client_request_forwarded_tcpip(ctype, rchan); 2014 c = client_request_forwarded_tcpip(ctype, rchan);
2015 } else if (strcmp(ctype, "forwarded-streamlocal@openssh.com") == 0) {
2016 c = client_request_forwarded_streamlocal(ctype, rchan);
2007 } else if (strcmp(ctype, "x11") == 0) { 2017 } else if (strcmp(ctype, "x11") == 0) {
2008 c = client_request_x11(ctype, rchan); 2018 c = client_request_x11(ctype, rchan);
2009 } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) { 2019 } else if (strcmp(ctype, "auth-agent@openssh.com") == 0) {
@@ -2074,7 +2084,7 @@ client_input_channel_req(int type, u_int32_t seq, void *ctxt)
2074 } 2084 }
2075 packet_check_eom(); 2085 packet_check_eom();
2076 } 2086 }
2077 if (reply && c != NULL) { 2087 if (reply && c != NULL && !(c->flags & CHAN_CLOSE_SENT)) {
2078 packet_start(success ? 2088 packet_start(success ?
2079 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); 2089 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
2080 packet_put_int(c->remote_id); 2090 packet_put_int(c->remote_id);
diff --git a/compat.c b/compat.c
index 2709dc5cf..4d286e8e9 100644
--- a/compat.c
+++ b/compat.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: compat.c,v 1.82 2013/12/30 23:52:27 djm Exp $ */ 1/* $OpenBSD: compat.c,v 1.85 2014/04/20 02:49:32 djm Exp $ */
2/* 2/*
3 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved. 3 * Copyright (c) 1999, 2000, 2001, 2002 Markus Friedl. All rights reserved.
4 * 4 *
diff --git a/compat.h b/compat.h
index a6c3f3d7a..2e25d5ba9 100644
--- a/compat.h
+++ b/compat.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: compat.h,v 1.44 2013/12/30 23:52:27 djm Exp $ */ 1/* $OpenBSD: compat.h,v 1.45 2014/04/18 23:52:25 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 1999, 2000, 2001 Markus Friedl. All rights reserved.
diff --git a/config.h.in b/config.h.in
index 6bc422c3e..a9a8b7ae3 100644
--- a/config.h.in
+++ b/config.h.in
@@ -420,6 +420,9 @@
420/* Define to 1 if you have the `EVP_MD_CTX_init' function. */ 420/* Define to 1 if you have the `EVP_MD_CTX_init' function. */
421#undef HAVE_EVP_MD_CTX_INIT 421#undef HAVE_EVP_MD_CTX_INIT
422 422
423/* Define to 1 if you have the `EVP_ripemd160' function. */
424#undef HAVE_EVP_RIPEMD160
425
423/* Define to 1 if you have the `EVP_sha256' function. */ 426/* Define to 1 if you have the `EVP_sha256' function. */
424#undef HAVE_EVP_SHA256 427#undef HAVE_EVP_SHA256
425 428
@@ -768,6 +771,9 @@
768/* Define to 1 if you have the <memory.h> header file. */ 771/* Define to 1 if you have the <memory.h> header file. */
769#undef HAVE_MEMORY_H 772#undef HAVE_MEMORY_H
770 773
774/* Define to 1 if you have the `memset_s' function. */
775#undef HAVE_MEMSET_S
776
771/* Define to 1 if you have the `mkdtemp' function. */ 777/* Define to 1 if you have the `mkdtemp' function. */
772#undef HAVE_MKDTEMP 778#undef HAVE_MKDTEMP
773 779
@@ -1324,9 +1330,6 @@
1324/* Define if va_copy exists */ 1330/* Define if va_copy exists */
1325#undef HAVE_VA_COPY 1331#undef HAVE_VA_COPY
1326 1332
1327/* Define to 1 if you have the `vhangup' function. */
1328#undef HAVE_VHANGUP
1329
1330/* Define to 1 if you have the <vis.h> header file. */ 1333/* Define to 1 if you have the <vis.h> header file. */
1331#undef HAVE_VIS_H 1334#undef HAVE_VIS_H
1332 1335
@@ -1387,9 +1390,6 @@
1387/* Define if pututxline updates lastlog too */ 1390/* Define if pututxline updates lastlog too */
1388#undef LASTLOG_WRITE_PUTUTXLINE 1391#undef LASTLOG_WRITE_PUTUTXLINE
1389 1392
1390/* Define if you want TCP Wrappers support */
1391#undef LIBWRAP
1392
1393/* Define to whatever link() returns for "not supported" if it doesn't return 1393/* Define to whatever link() returns for "not supported" if it doesn't return
1394 EOPNOTSUPP. */ 1394 EOPNOTSUPP. */
1395#undef LINK_OPNOTSUPP_ERRNO 1395#undef LINK_OPNOTSUPP_ERRNO
@@ -1668,9 +1668,15 @@
1668/* Define if you want IRIX project management */ 1668/* Define if you want IRIX project management */
1669#undef WITH_IRIX_PROJECT 1669#undef WITH_IRIX_PROJECT
1670 1670
1671/* use libcrypto for cryptography */
1672#undef WITH_OPENSSL
1673
1671/* Define if you want SELinux support. */ 1674/* Define if you want SELinux support. */
1672#undef WITH_SELINUX 1675#undef WITH_SELINUX
1673 1676
1677/* include SSH protocol version 1 support */
1678#undef WITH_SSH1
1679
1674/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most 1680/* Define WORDS_BIGENDIAN to 1 if your processor stores words with the most
1675 significant byte first (like Motorola and SPARC, unlike Intel). */ 1681 significant byte first (like Motorola and SPARC, unlike Intel). */
1676#if defined AC_APPLE_UNIVERSAL_BUILD 1682#if defined AC_APPLE_UNIVERSAL_BUILD
diff --git a/configure b/configure
index e2f12cdff..7be478a82 100755
--- a/configure
+++ b/configure
@@ -1,5 +1,5 @@
1#! /bin/sh 1#! /bin/sh
2# From configure.ac Revision: 1.571 . 2# From configure.ac Revision: 1.583 .
3# Guess values for system-dependent variables and create Makefiles. 3# Guess values for system-dependent variables and create Makefiles.
4# Generated by GNU Autoconf 2.68 for OpenSSH Portable. 4# Generated by GNU Autoconf 2.68 for OpenSSH Portable.
5# 5#
@@ -725,7 +725,6 @@ with_osfsia
725with_zlib 725with_zlib
726with_zlib_version_check 726with_zlib_version_check
727with_skey 727with_skey
728with_tcp_wrappers
729with_ldns 728with_ldns
730with_libedit 729with_libedit
731with_audit 730with_audit
@@ -1418,7 +1417,6 @@ Optional Packages:
1418 --with-zlib=PATH Use zlib in PATH 1417 --with-zlib=PATH Use zlib in PATH
1419 --without-zlib-version-check Disable zlib version check 1418 --without-zlib-version-check Disable zlib version check
1420 --with-skey[=PATH] Enable S/Key support (optionally in PATH) 1419 --with-skey[=PATH] Enable S/Key support (optionally in PATH)
1421 --with-tcp-wrappers[=PATH] Enable tcpwrappers support (optionally in PATH)
1422 --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH) 1420 --with-ldns[=PATH] Use ldns for DNSSEC support (optionally in PATH)
1423 --with-libedit[=PATH] Enable libedit support for sftp 1421 --with-libedit[=PATH] Enable libedit support for sftp
1424 --with-audit=module Enable audit support (modules=debug,bsm,linux) 1422 --with-audit=module Enable audit support (modules=debug,bsm,linux)
@@ -9765,84 +9763,6 @@ rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
9765fi 9763fi
9766 9764
9767 9765
9768# Check whether user wants TCP wrappers support
9769TCPW_MSG="no"
9770
9771# Check whether --with-tcp-wrappers was given.
9772if test "${with_tcp_wrappers+set}" = set; then :
9773 withval=$with_tcp_wrappers;
9774 if test "x$withval" != "xno" ; then
9775 saved_LIBS="$LIBS"
9776 saved_LDFLAGS="$LDFLAGS"
9777 saved_CPPFLAGS="$CPPFLAGS"
9778 if test -n "${withval}" && \
9779 test "x${withval}" != "xyes"; then
9780 if test -d "${withval}/lib"; then
9781 if test -n "${need_dash_r}"; then
9782 LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
9783 else
9784 LDFLAGS="-L${withval}/lib ${LDFLAGS}"
9785 fi
9786 else
9787 if test -n "${need_dash_r}"; then
9788 LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
9789 else
9790 LDFLAGS="-L${withval} ${LDFLAGS}"
9791 fi
9792 fi
9793 if test -d "${withval}/include"; then
9794 CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
9795 else
9796 CPPFLAGS="-I${withval} ${CPPFLAGS}"
9797 fi
9798 fi
9799 LIBS="-lwrap $LIBS"
9800 { $as_echo "$as_me:${as_lineno-$LINENO}: checking for libwrap" >&5
9801$as_echo_n "checking for libwrap... " >&6; }
9802 cat confdefs.h - <<_ACEOF >conftest.$ac_ext
9803/* end confdefs.h. */
9804
9805#include <sys/types.h>
9806#include <sys/socket.h>
9807#include <netinet/in.h>
9808#include <tcpd.h>
9809int deny_severity = 0, allow_severity = 0;
9810
9811int
9812main ()
9813{
9814
9815 hosts_access(0);
9816
9817 ;
9818 return 0;
9819}
9820_ACEOF
9821if ac_fn_c_try_link "$LINENO"; then :
9822
9823 { $as_echo "$as_me:${as_lineno-$LINENO}: result: yes" >&5
9824$as_echo "yes" >&6; }
9825
9826$as_echo "#define LIBWRAP 1" >>confdefs.h
9827
9828 SSHDLIBS="$SSHDLIBS -lwrap"
9829 TCPW_MSG="yes"
9830
9831else
9832
9833 as_fn_error $? "*** libwrap missing" "$LINENO" 5
9834
9835
9836fi
9837rm -f core conftest.err conftest.$ac_objext \
9838 conftest$ac_exeext conftest.$ac_ext
9839 LIBS="$saved_LIBS"
9840 fi
9841
9842
9843fi
9844
9845
9846# Check whether user wants to use ldns 9766# Check whether user wants to use ldns
9847LDNS_MSG="no" 9767LDNS_MSG="no"
9848 9768
@@ -10407,10 +10327,6 @@ for ac_func in \
10407 Blowfish_expandstate \ 10327 Blowfish_expandstate \
10408 Blowfish_expand0state \ 10328 Blowfish_expand0state \
10409 Blowfish_stream2word \ 10329 Blowfish_stream2word \
10410 arc4random \
10411 arc4random_buf \
10412 arc4random_stir \
10413 arc4random_uniform \
10414 asprintf \ 10330 asprintf \
10415 b64_ntop \ 10331 b64_ntop \
10416 __b64_ntop \ 10332 __b64_ntop \
@@ -10454,6 +10370,7 @@ for ac_func in \
10454 mblen \ 10370 mblen \
10455 md5_crypt \ 10371 md5_crypt \
10456 memmove \ 10372 memmove \
10373 memset_s \
10457 mkdtemp \ 10374 mkdtemp \
10458 mmap \ 10375 mmap \
10459 ngetaddrinfo \ 10376 ngetaddrinfo \
@@ -10512,7 +10429,6 @@ for ac_func in \
10512 user_from_uid \ 10429 user_from_uid \
10513 usleep \ 10430 usleep \
10514 vasprintf \ 10431 vasprintf \
10515 vhangup \
10516 vsnprintf \ 10432 vsnprintf \
10517 waitpid \ 10433 waitpid \
10518 10434
@@ -11328,11 +11244,9 @@ fi
11328 11244
11329fi 11245fi
11330 11246
11331# If we don't have a working asprintf, then we strongly depend on vsnprintf 11247# We depend on vsnprintf returning the right thing on overflow: the
11332# returning the right thing on overflow: the number of characters it tried to 11248# number of characters it tried to create (as per SUSv3)
11333# create (as per SUSv3) 11249if test "x$ac_cv_func_vsnprintf" = "xyes" ; then
11334if test "x$ac_cv_func_asprintf" != "xyes" && \
11335 test "x$ac_cv_func_vsnprintf" = "xyes" ; then
11336 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5 11250 { $as_echo "$as_me:${as_lineno-$LINENO}: checking whether vsnprintf returns correct values on overflow" >&5
11337$as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; } 11251$as_echo_n "checking whether vsnprintf returns correct values on overflow... " >&6; }
11338 if test "$cross_compiling" = yes; then : 11252 if test "$cross_compiling" = yes; then :
@@ -11347,10 +11261,14 @@ else
11347#include <stdio.h> 11261#include <stdio.h>
11348#include <stdarg.h> 11262#include <stdarg.h>
11349 11263
11350int x_snprintf(char *str,size_t count,const char *fmt,...) 11264int x_snprintf(char *str, size_t count, const char *fmt, ...)
11351{ 11265{
11352 size_t ret; va_list ap; 11266 size_t ret;
11353 va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); 11267 va_list ap;
11268
11269 va_start(ap, fmt);
11270 ret = vsnprintf(str, count, fmt, ap);
11271 va_end(ap);
11354 return ret; 11272 return ret;
11355} 11273}
11356 11274
@@ -11358,8 +11276,12 @@ int
11358main () 11276main ()
11359{ 11277{
11360 11278
11361 char x[1]; 11279char x[1];
11362 exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); 11280if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11)
11281 return 1;
11282if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11)
11283 return 1;
11284return 0;
11363 11285
11364 ; 11286 ;
11365 return 0; 11287 return 0;
@@ -11956,7 +11878,7 @@ main ()
11956 if(fd == NULL) 11878 if(fd == NULL)
11957 exit(1); 11879 exit(1);
11958 11880
11959 if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) 11881 if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0)
11960 exit(1); 11882 exit(1);
11961 11883
11962 exit(0); 11884 exit(0);
@@ -12013,7 +11935,8 @@ main ()
12013 if(fd == NULL) 11935 if(fd == NULL)
12014 exit(1); 11936 exit(1);
12015 11937
12016 if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) 11938 if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(),
11939 SSLeay_version(SSLEAY_VERSION))) <0)
12017 exit(1); 11940 exit(1);
12018 11941
12019 exit(0); 11942 exit(0);
@@ -12025,6 +11948,13 @@ _ACEOF
12025if ac_fn_c_try_run "$LINENO"; then : 11948if ac_fn_c_try_run "$LINENO"; then :
12026 11949
12027 ssl_library_ver=`cat conftest.ssllibver` 11950 ssl_library_ver=`cat conftest.ssllibver`
11951 # Check version is supported.
11952 case "$ssl_library_ver" in
11953 0090[0-7]*|009080[0-5]*)
11954 as_fn_error $? "OpenSSL >= 0.9.8f required" "$LINENO" 5
11955 ;;
11956 *) ;;
11957 esac
12028 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5 11958 { $as_echo "$as_me:${as_lineno-$LINENO}: result: $ssl_library_ver" >&5
12029$as_echo "$ssl_library_ver" >&6; } 11959$as_echo "$ssl_library_ver" >&6; }
12030 11960
@@ -12040,6 +11970,18 @@ rm -f core *.core core.conftest.* gmon.out bb.out conftest$ac_exeext \
12040fi 11970fi
12041 11971
12042 11972
11973# XXX make --without-openssl work
11974
11975cat >>confdefs.h <<_ACEOF
11976#define WITH_OPENSSL 1
11977_ACEOF
11978
11979
11980cat >>confdefs.h <<_ACEOF
11981#define WITH_SSH1 1
11982_ACEOF
11983
11984
12043 11985
12044# Check whether --with-openssl-header-check was given. 11986# Check whether --with-openssl-header-check was given.
12045if test "${with_openssl_header_check+set}" = set; then : 11987if test "${with_openssl_header_check+set}" = set; then :
@@ -12573,6 +12515,25 @@ else
12573fi 12515fi
12574done 12516done
12575 12517
12518# Search for RIPE-MD support in OpenSSL
12519for ac_func in EVP_ripemd160
12520do :
12521 ac_fn_c_check_func "$LINENO" "EVP_ripemd160" "ac_cv_func_EVP_ripemd160"
12522if test "x$ac_cv_func_EVP_ripemd160" = xyes; then :
12523 cat >>confdefs.h <<_ACEOF
12524#define HAVE_EVP_RIPEMD160 1
12525_ACEOF
12526
12527else
12528 unsupported_algorithms="$unsupported_algorithms \
12529 hmac-ripemd160
12530 hmac-ripemd160@openssh.com
12531 hmac-ripemd160-etm@openssh.com"
12532
12533
12534fi
12535done
12536
12576 12537
12577# Check complete ECC support in OpenSSL 12538# Check complete ECC support in OpenSSL
12578{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5 12539{ $as_echo "$as_me:${as_lineno-$LINENO}: checking whether OpenSSL has NID_X9_62_prime256v1" >&5
@@ -12773,6 +12734,24 @@ fi
12773 12734
12774 12735
12775 12736
12737for ac_func in \
12738 arc4random \
12739 arc4random_buf \
12740 arc4random_stir \
12741 arc4random_uniform \
12742
12743do :
12744 as_ac_var=`$as_echo "ac_cv_func_$ac_func" | $as_tr_sh`
12745ac_fn_c_check_func "$LINENO" "$ac_func" "$as_ac_var"
12746if eval test \"x\$"$as_ac_var"\" = x"yes"; then :
12747 cat >>confdefs.h <<_ACEOF
12748#define `$as_echo "HAVE_$ac_func" | $as_tr_cpp` 1
12749_ACEOF
12750
12751fi
12752done
12753
12754
12776saved_LIBS="$LIBS" 12755saved_LIBS="$LIBS"
12777{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5 12756{ $as_echo "$as_me:${as_lineno-$LINENO}: checking for ia_openinfo in -liaf" >&5
12778$as_echo_n "checking for ia_openinfo in -liaf... " >&6; } 12757$as_echo_n "checking for ia_openinfo in -liaf... " >&6; }
@@ -13182,7 +13161,14 @@ fi
13182rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext 13161rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext
13183fi 13162fi
13184 13163
13185SSH_PRIVSEP_USER=sshd 13164case "$host" in
13165*-*-cygwin*)
13166 SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER
13167 ;;
13168*)
13169 SSH_PRIVSEP_USER=sshd
13170 ;;
13171esac
13186 13172
13187# Check whether --with-privsep-user was given. 13173# Check whether --with-privsep-user was given.
13188if test "${with_privsep_user+set}" = set; then : 13174if test "${with_privsep_user+set}" = set; then :
@@ -13195,11 +13181,19 @@ if test "${with_privsep_user+set}" = set; then :
13195 13181
13196fi 13182fi
13197 13183
13184if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then
13185
13186cat >>confdefs.h <<_ACEOF
13187#define SSH_PRIVSEP_USER CYGWIN_SSH_PRIVSEP_USER
13188_ACEOF
13189
13190else
13198 13191
13199cat >>confdefs.h <<_ACEOF 13192cat >>confdefs.h <<_ACEOF
13200#define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER" 13193#define SSH_PRIVSEP_USER "$SSH_PRIVSEP_USER"
13201_ACEOF 13194_ACEOF
13202 13195
13196fi
13203 13197
13204 13198
13205if test "x$have_linux_no_new_privs" = "x1" ; then 13199if test "x$have_linux_no_new_privs" = "x1" ; then
@@ -19872,7 +19866,6 @@ echo " KerberosV support: $KRB5_MSG"
19872echo " SELinux support: $SELINUX_MSG" 19866echo " SELinux support: $SELINUX_MSG"
19873echo " Smartcard support: $SCARD_MSG" 19867echo " Smartcard support: $SCARD_MSG"
19874echo " S/KEY support: $SKEY_MSG" 19868echo " S/KEY support: $SKEY_MSG"
19875echo " TCP Wrappers support: $TCPW_MSG"
19876echo " MD5 password support: $MD5_MSG" 19869echo " MD5 password support: $MD5_MSG"
19877echo " libedit support: $LIBEDIT_MSG" 19870echo " libedit support: $LIBEDIT_MSG"
19878echo " Solaris process contract support: $SPC_MSG" 19871echo " Solaris process contract support: $SPC_MSG"
diff --git a/configure.ac b/configure.ac
index 86692714b..f5c65c5a4 100644
--- a/configure.ac
+++ b/configure.ac
@@ -1,4 +1,4 @@
1# $Id: configure.ac,v 1.571 2014/02/21 17:09:34 tim Exp $ 1# $Id: configure.ac,v 1.583 2014/08/26 20:32:01 djm Exp $
2# 2#
3# Copyright (c) 1999-2004 Damien Miller 3# Copyright (c) 1999-2004 Damien Miller
4# 4#
@@ -15,7 +15,7 @@
15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15# OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 16
17AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org]) 17AC_INIT([OpenSSH], [Portable], [openssh-unix-dev@mindrot.org])
18AC_REVISION($Revision: 1.571 $) 18AC_REVISION($Revision: 1.583 $)
19AC_CONFIG_SRCDIR([ssh.c]) 19AC_CONFIG_SRCDIR([ssh.c])
20AC_LANG([C]) 20AC_LANG([C])
21 21
@@ -1655,10 +1655,6 @@ AC_CHECK_FUNCS([ \
1655 Blowfish_expandstate \ 1655 Blowfish_expandstate \
1656 Blowfish_expand0state \ 1656 Blowfish_expand0state \
1657 Blowfish_stream2word \ 1657 Blowfish_stream2word \
1658 arc4random \
1659 arc4random_buf \
1660 arc4random_stir \
1661 arc4random_uniform \
1662 asprintf \ 1658 asprintf \
1663 b64_ntop \ 1659 b64_ntop \
1664 __b64_ntop \ 1660 __b64_ntop \
@@ -1702,6 +1698,7 @@ AC_CHECK_FUNCS([ \
1702 mblen \ 1698 mblen \
1703 md5_crypt \ 1699 md5_crypt \
1704 memmove \ 1700 memmove \
1701 memset_s \
1705 mkdtemp \ 1702 mkdtemp \
1706 mmap \ 1703 mmap \
1707 ngetaddrinfo \ 1704 ngetaddrinfo \
@@ -1760,7 +1757,6 @@ AC_CHECK_FUNCS([ \
1760 user_from_uid \ 1757 user_from_uid \
1761 usleep \ 1758 usleep \
1762 vasprintf \ 1759 vasprintf \
1763 vhangup \
1764 vsnprintf \ 1760 vsnprintf \
1765 waitpid \ 1761 waitpid \
1766]) 1762])
@@ -1972,11 +1968,9 @@ if test "x$ac_cv_func_snprintf" = "xyes" ; then
1972 ) 1968 )
1973fi 1969fi
1974 1970
1975# If we don't have a working asprintf, then we strongly depend on vsnprintf 1971# We depend on vsnprintf returning the right thing on overflow: the
1976# returning the right thing on overflow: the number of characters it tried to 1972# number of characters it tried to create (as per SUSv3)
1977# create (as per SUSv3) 1973if test "x$ac_cv_func_vsnprintf" = "xyes" ; then
1978if test "x$ac_cv_func_asprintf" != "xyes" && \
1979 test "x$ac_cv_func_vsnprintf" = "xyes" ; then
1980 AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow]) 1974 AC_MSG_CHECKING([whether vsnprintf returns correct values on overflow])
1981 AC_RUN_IFELSE( 1975 AC_RUN_IFELSE(
1982 [AC_LANG_PROGRAM([[ 1976 [AC_LANG_PROGRAM([[
@@ -1984,15 +1978,23 @@ if test "x$ac_cv_func_asprintf" != "xyes" && \
1984#include <stdio.h> 1978#include <stdio.h>
1985#include <stdarg.h> 1979#include <stdarg.h>
1986 1980
1987int x_snprintf(char *str,size_t count,const char *fmt,...) 1981int x_snprintf(char *str, size_t count, const char *fmt, ...)
1988{ 1982{
1989 size_t ret; va_list ap; 1983 size_t ret;
1990 va_start(ap, fmt); ret = vsnprintf(str, count, fmt, ap); va_end(ap); 1984 va_list ap;
1985
1986 va_start(ap, fmt);
1987 ret = vsnprintf(str, count, fmt, ap);
1988 va_end(ap);
1991 return ret; 1989 return ret;
1992} 1990}
1993 ]], [[ 1991 ]], [[
1994 char x[1]; 1992char x[1];
1995 exit(x_snprintf(x, 1, "%s %d", "hello", 12345) == 11 ? 0 : 1); 1993if (x_snprintf(x, 1, "%s %d", "hello", 12345) != 11)
1994 return 1;
1995if (x_snprintf(NULL, 0, "%s %d", "hello", 12345) != 11)
1996 return 1;
1997return 0;
1996 ]])], 1998 ]])],
1997 [AC_MSG_RESULT([yes])], 1999 [AC_MSG_RESULT([yes])],
1998 [ 2000 [
@@ -2328,7 +2330,7 @@ AC_RUN_IFELSE(
2328 if(fd == NULL) 2330 if(fd == NULL)
2329 exit(1); 2331 exit(1);
2330 2332
2331 if ((rc = fprintf(fd ,"%x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0) 2333 if ((rc = fprintf(fd ,"%08x (%s)\n", OPENSSL_VERSION_NUMBER, OPENSSL_VERSION_TEXT)) <0)
2332 exit(1); 2334 exit(1);
2333 2335
2334 exit(0); 2336 exit(0);
@@ -2363,13 +2365,21 @@ AC_RUN_IFELSE(
2363 if(fd == NULL) 2365 if(fd == NULL)
2364 exit(1); 2366 exit(1);
2365 2367
2366 if ((rc = fprintf(fd ,"%x (%s)\n", SSLeay(), SSLeay_version(SSLEAY_VERSION))) <0) 2368 if ((rc = fprintf(fd ,"%08x (%s)\n", SSLeay(),
2369 SSLeay_version(SSLEAY_VERSION))) <0)
2367 exit(1); 2370 exit(1);
2368 2371
2369 exit(0); 2372 exit(0);
2370 ]])], 2373 ]])],
2371 [ 2374 [
2372 ssl_library_ver=`cat conftest.ssllibver` 2375 ssl_library_ver=`cat conftest.ssllibver`
2376 # Check version is supported.
2377 case "$ssl_library_ver" in
2378 0090[[0-7]]*|009080[[0-5]]*)
2379 AC_MSG_ERROR([OpenSSL >= 0.9.8f required])
2380 ;;
2381 *) ;;
2382 esac
2373 AC_MSG_RESULT([$ssl_library_ver]) 2383 AC_MSG_RESULT([$ssl_library_ver])
2374 ], 2384 ],
2375 [ 2385 [
@@ -2381,6 +2391,10 @@ AC_RUN_IFELSE(
2381 ] 2391 ]
2382) 2392)
2383 2393
2394# XXX make --without-openssl work
2395AC_DEFINE_UNQUOTED([WITH_OPENSSL], [1], [use libcrypto for cryptography])
2396AC_DEFINE_UNQUOTED([WITH_SSH1], [1], [include SSH protocol version 1 support])
2397
2384AC_ARG_WITH([openssl-header-check], 2398AC_ARG_WITH([openssl-header-check],
2385 [ --without-openssl-header-check Disable OpenSSL version consistency check], 2399 [ --without-openssl-header-check Disable OpenSSL version consistency check],
2386 [ if test "x$withval" = "xno" ; then 2400 [ if test "x$withval" = "xno" ; then
@@ -2589,6 +2603,14 @@ AC_CHECK_FUNCS([SHA256_Update EVP_sha256], ,
2589 hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com" 2603 hmac-sha2-256-etm@openssh.com hmac-sha2-512-etm@openssh.com"
2590 ] 2604 ]
2591) 2605)
2606# Search for RIPE-MD support in OpenSSL
2607AC_CHECK_FUNCS([EVP_ripemd160], ,
2608 [unsupported_algorithms="$unsupported_algorithms \
2609 hmac-ripemd160
2610 hmac-ripemd160@openssh.com
2611 hmac-ripemd160-etm@openssh.com"
2612 ]
2613)
2592 2614
2593# Check complete ECC support in OpenSSL 2615# Check complete ECC support in OpenSSL
2594AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1]) 2616AC_MSG_CHECKING([whether OpenSSL has NID_X9_62_prime256v1])
@@ -2709,6 +2731,13 @@ fi
2709AC_SUBST([TEST_SSH_ECC]) 2731AC_SUBST([TEST_SSH_ECC])
2710AC_SUBST([COMMENT_OUT_ECC]) 2732AC_SUBST([COMMENT_OUT_ECC])
2711 2733
2734AC_CHECK_FUNCS([ \
2735 arc4random \
2736 arc4random_buf \
2737 arc4random_stir \
2738 arc4random_uniform \
2739])
2740
2712saved_LIBS="$LIBS" 2741saved_LIBS="$LIBS"
2713AC_CHECK_LIB([iaf], [ia_openinfo], [ 2742AC_CHECK_LIB([iaf], [ia_openinfo], [
2714 LIBS="$LIBS -liaf" 2743 LIBS="$LIBS -liaf"
@@ -2892,7 +2921,14 @@ if test "x$PAM_MSG" = "xyes" ; then
2892 ]) 2921 ])
2893fi 2922fi
2894 2923
2895SSH_PRIVSEP_USER=sshd 2924case "$host" in
2925*-*-cygwin*)
2926 SSH_PRIVSEP_USER=CYGWIN_SSH_PRIVSEP_USER
2927 ;;
2928*)
2929 SSH_PRIVSEP_USER=sshd
2930 ;;
2931esac
2896AC_ARG_WITH([privsep-user], 2932AC_ARG_WITH([privsep-user],
2897 [ --with-privsep-user=user Specify non-privileged user for privilege separation], 2933 [ --with-privsep-user=user Specify non-privileged user for privilege separation],
2898 [ 2934 [
@@ -2902,8 +2938,13 @@ AC_ARG_WITH([privsep-user],
2902 fi 2938 fi
2903 ] 2939 ]
2904) 2940)
2905AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"], 2941if test "x$SSH_PRIVSEP_USER" = "xCYGWIN_SSH_PRIVSEP_USER" ; then
2906 [non-privileged user for privilege separation]) 2942 AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], [CYGWIN_SSH_PRIVSEP_USER],
2943 [Cygwin function to fetch non-privileged user for privilege separation])
2944else
2945 AC_DEFINE_UNQUOTED([SSH_PRIVSEP_USER], ["$SSH_PRIVSEP_USER"],
2946 [non-privileged user for privilege separation])
2947fi
2907AC_SUBST([SSH_PRIVSEP_USER]) 2948AC_SUBST([SSH_PRIVSEP_USER])
2908 2949
2909if test "x$have_linux_no_new_privs" = "x1" ; then 2950if test "x$have_linux_no_new_privs" = "x1" ; then
diff --git a/consolekit.c b/consolekit.c
index f1039e652..0266f06a2 100644
--- a/consolekit.c
+++ b/consolekit.c
@@ -53,6 +53,7 @@
53#include "hostfile.h" 53#include "hostfile.h"
54#include "auth.h" 54#include "auth.h"
55#include "log.h" 55#include "log.h"
56#include "misc.h"
56#include "servconf.h" 57#include "servconf.h"
57#include "canohost.h" 58#include "canohost.h"
58#include "session.h" 59#include "session.h"
diff --git a/contrib/caldera/openssh.spec b/contrib/caldera/openssh.spec
index 0061fe933..0011b4dea 100644
--- a/contrib/caldera/openssh.spec
+++ b/contrib/caldera/openssh.spec
@@ -16,7 +16,7 @@
16 16
17#old cvs stuff. please update before use. may be deprecated. 17#old cvs stuff. please update before use. may be deprecated.
18%define use_stable 1 18%define use_stable 1
19%define version 6.6p1 19%define version 6.7p1
20%if %{use_stable} 20%if %{use_stable}
21 %define cvs %{nil} 21 %define cvs %{nil}
22 %define release 1 22 %define release 1
@@ -178,7 +178,6 @@ by Jim Knoble <jmknoble@pobox.com>.
178CFLAGS="$RPM_OPT_FLAGS" \ 178CFLAGS="$RPM_OPT_FLAGS" \
179%configure \ 179%configure \
180 --with-pam \ 180 --with-pam \
181 --with-tcp-wrappers \
182 --with-privsep-path=%{_var}/empty/sshd \ 181 --with-privsep-path=%{_var}/empty/sshd \
183 #leave this line for easy edits. 182 #leave this line for easy edits.
184 183
@@ -363,4 +362,4 @@ fi
363* Mon Jan 01 1998 ... 362* Mon Jan 01 1998 ...
364Template Version: 1.31 363Template Version: 1.31
365 364
366$Id: openssh.spec,v 1.83 2014/02/27 23:03:55 djm Exp $ 365$Id: openssh.spec,v 1.85 2014/08/19 01:36:08 djm Exp $
diff --git a/contrib/cygwin/README b/contrib/cygwin/README
index 2562b6186..1396d99cd 100644
--- a/contrib/cygwin/README
+++ b/contrib/cygwin/README
@@ -69,7 +69,7 @@ Building OpenSSH
69Building from source is easy. Just unpack the source archive, cd to that 69Building from source is easy. Just unpack the source archive, cd to that
70directory, and call cygport: 70directory, and call cygport:
71 71
72 cygport openssh.cygport almostall 72 cygport openssh.cygport all
73 73
74You must have installed the following packages to be able to build OpenSSH 74You must have installed the following packages to be able to build OpenSSH
75with the aforementioned cygport script: 75with the aforementioned cygport script:
@@ -77,7 +77,6 @@ with the aforementioned cygport script:
77 zlib 77 zlib
78 crypt 78 crypt
79 openssl-devel 79 openssl-devel
80 libwrap-devel
81 libedit-devel 80 libedit-devel
82 libkrb5-devel 81 libkrb5-devel
83 82
diff --git a/contrib/cygwin/ssh-host-config b/contrib/cygwin/ssh-host-config
index 05efd3b3b..a7ea3e0d2 100644
--- a/contrib/cygwin/ssh-host-config
+++ b/contrib/cygwin/ssh-host-config
@@ -34,9 +34,9 @@ declare -a csih_required_commands=(
34 /usr/bin/mv coreutils 34 /usr/bin/mv coreutils
35 /usr/bin/rm coreutils 35 /usr/bin/rm coreutils
36 /usr/bin/cygpath cygwin 36 /usr/bin/cygpath cygwin
37 /usr/bin/mkpasswd cygwin
37 /usr/bin/mount cygwin 38 /usr/bin/mount cygwin
38 /usr/bin/ps cygwin 39 /usr/bin/ps cygwin
39 /usr/bin/setfacl cygwin
40 /usr/bin/umount cygwin 40 /usr/bin/umount cygwin
41 /usr/bin/cmp diffutils 41 /usr/bin/cmp diffutils
42 /usr/bin/grep grep 42 /usr/bin/grep grep
@@ -59,8 +59,9 @@ PREFIX=/usr
59SYSCONFDIR=/etc 59SYSCONFDIR=/etc
60LOCALSTATEDIR=/var 60LOCALSTATEDIR=/var
61 61
62sshd_config_configured=no
62port_number=22 63port_number=22
63privsep_configured=no 64strictmodes=yes
64privsep_used=yes 65privsep_used=yes
65cygwin_value="" 66cygwin_value=""
66user_account= 67user_account=
@@ -89,28 +90,8 @@ update_services_file() {
89 # Depends on the above mount 90 # Depends on the above mount
90 _wservices=`cygpath -w "${_services}"` 91 _wservices=`cygpath -w "${_services}"`
91 92
92 # Remove sshd 22/port from services
93 if [ `/usr/bin/grep -q 'sshd[ \t][ \t]*22' "${_services}"; echo $?` -eq 0 ]
94 then
95 /usr/bin/grep -v 'sshd[ \t][ \t]*22' "${_services}" > "${_serv_tmp}"
96 if [ -f "${_serv_tmp}" ]
97 then
98 if /usr/bin/mv "${_serv_tmp}" "${_services}"
99 then
100 csih_inform "Removing sshd from ${_wservices}"
101 else
102 csih_warning "Removing sshd from ${_wservices} failed!"
103 let ++ret
104 fi
105 /usr/bin/rm -f "${_serv_tmp}"
106 else
107 csih_warning "Removing sshd from ${_wservices} failed!"
108 let ++ret
109 fi
110 fi
111
112 # Add ssh 22/tcp and ssh 22/udp to services 93 # Add ssh 22/tcp and ssh 22/udp to services
113 if [ `/usr/bin/grep -q 'ssh[ \t][ \t]*22' "${_services}"; echo $?` -ne 0 ] 94 if [ `/usr/bin/grep -q 'ssh[[:space:]][[:space:]]*22' "${_services}"; echo $?` -ne 0 ]
114 then 95 then
115 if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}" 96 if /usr/bin/awk '{ if ( $2 ~ /^23\/tcp/ ) print "ssh 22/tcp'"${_spaces}"'SSH Remote Login Protocol\nssh 22/udp'"${_spaces}"'SSH Remote Login Protocol"; print $0; }' < "${_services}" > "${_serv_tmp}"
116 then 97 then
@@ -132,17 +113,45 @@ update_services_file() {
132} # --- End of update_services_file --- # 113} # --- End of update_services_file --- #
133 114
134# ====================================================================== 115# ======================================================================
116# Routine: sshd_strictmodes
117# MODIFIES: strictmodes
118# ======================================================================
119sshd_strictmodes() {
120 if [ "${sshd_config_configured}" != "yes" ]
121 then
122 echo
123 csih_inform "StrictModes is set to 'yes' by default."
124 csih_inform "This is the recommended setting, but it requires that the POSIX"
125 csih_inform "permissions of the user's home directory, the user's .ssh"
126 csih_inform "directory, and the user's ssh key files are tight so that"
127 csih_inform "only the user has write permissions."
128 csih_inform "On the other hand, StrictModes don't work well with default"
129 csih_inform "Windows permissions of a home directory mounted with the"
130 csih_inform "'noacl' option, and they don't work at all if the home"
131 csih_inform "directory is on a FAT or FAT32 partition."
132 if ! csih_request "Should StrictModes be used?"
133 then
134 strictmodes=no
135 fi
136 fi
137 return 0
138}
139
140# ======================================================================
135# Routine: sshd_privsep 141# Routine: sshd_privsep
136# MODIFIES: privsep_configured privsep_used 142# MODIFIES: privsep_used
137# ====================================================================== 143# ======================================================================
138sshd_privsep() { 144sshd_privsep() {
139 local sshdconfig_tmp
140 local ret=0 145 local ret=0
141 146
142 if [ "${privsep_configured}" != "yes" ] 147 if [ "${sshd_config_configured}" != "yes" ]
143 then 148 then
144 csih_inform "Privilege separation is set to yes by default since OpenSSH 3.3." 149 echo
145 csih_inform "However, this requires a non-privileged account called 'sshd'." 150 csih_inform "Privilege separation is set to 'sandbox' by default since"
151 csih_inform "OpenSSH 6.1. This is unsupported by Cygwin and has to be set"
152 csih_inform "to 'yes' or 'no'."
153 csih_inform "However, using privilege separation requires a non-privileged account"
154 csih_inform "called 'sshd'."
146 csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep." 155 csih_inform "For more info on privilege separation read /usr/share/doc/openssh/README.privsep."
147 if csih_request "Should privilege separation be used?" 156 if csih_request "Should privilege separation be used?"
148 then 157 then
@@ -159,36 +168,53 @@ sshd_privsep() {
159 privsep_used=no 168 privsep_used=no
160 fi 169 fi
161 fi 170 fi
171 return $ret
172} # --- End of sshd_privsep --- #
162 173
163 # Create default sshd_config from skeleton files in /etc/defaults/etc or 174# ======================================================================
164 # modify to add the missing privsep configuration option 175# Routine: sshd_config_tweak
165 if /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 176# ======================================================================
177sshd_config_tweak() {
178 local ret=0
179
180 # Modify sshd_config
181 csih_inform "Updating ${SYSCONFDIR}/sshd_config file"
182 if [ "${port_number}" -ne 22 ]
166 then 183 then
167 csih_inform "Updating ${SYSCONFDIR}/sshd_config file" 184 /usr/bin/sed -i -e "s/^#\?[[:space:]]*Port[[:space:]].*/Port ${port_number}/" \
168 sshdconfig_tmp=${SYSCONFDIR}/sshd_config.$$ 185 ${SYSCONFDIR}/sshd_config
169 /usr/bin/sed -e "s/^#UsePrivilegeSeparation yes/UsePrivilegeSeparation ${privsep_used}/ 186 if [ $? -ne 0 ]
170 s/^#Port 22/Port ${port_number}/
171 s/^#StrictModes yes/StrictModes no/" \
172 < ${SYSCONFDIR}/sshd_config \
173 > "${sshdconfig_tmp}"
174 if ! /usr/bin/mv "${sshdconfig_tmp}" ${SYSCONFDIR}/sshd_config
175 then 187 then
176 csih_warning "Setting privilege separation to 'yes' failed!" 188 csih_warning "Setting listening port to ${port_number} failed!"
177 csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" 189 csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
178 let ++ret 190 let ++ret
191 fi
192 fi
193 if [ "${strictmodes}" = "no" ]
194 then
195 /usr/bin/sed -i -e "s/^#\?[[:space:]]*StrictModes[[:space:]].*/StrictModes no/" \
196 ${SYSCONFDIR}/sshd_config
197 if [ $? -ne 0 ]
198 then
199 csih_warning "Setting StrictModes to 'no' failed!"
200 csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
201 let ++ret
179 fi 202 fi
180 elif [ "${privsep_configured}" != "yes" ] 203 fi
204 if [ "${sshd_config_configured}" != "yes" ]
181 then 205 then
182 echo >> ${SYSCONFDIR}/sshd_config 206 /usr/bin/sed -i -e "
183 if ! echo "UsePrivilegeSeparation ${privsep_used}" >> ${SYSCONFDIR}/sshd_config 207 s/^#\?UsePrivilegeSeparation .*/UsePrivilegeSeparation ${privsep_used}/" \
208 ${SYSCONFDIR}/sshd_config
209 if [ $? -ne 0 ]
184 then 210 then
185 csih_warning "Setting privilege separation to 'yes' failed!" 211 csih_warning "Setting privilege separation failed!"
186 csih_warning "Check your ${SYSCONFDIR}/sshd_config file!" 212 csih_warning "Check your ${SYSCONFDIR}/sshd_config file!"
187 let ++ret 213 let ++ret
188 fi 214 fi
189 fi 215 fi
190 return $ret 216 return $ret
191} # --- End of sshd_privsep --- # 217} # --- End of sshd_config_tweak --- #
192 218
193# ====================================================================== 219# ======================================================================
194# Routine: update_inetd_conf 220# Routine: update_inetd_conf
@@ -207,11 +233,11 @@ update_inetd_conf() {
207 # we have inetutils-1.5 inetd.d support 233 # we have inetutils-1.5 inetd.d support
208 if [ -f "${_inetcnf}" ] 234 if [ -f "${_inetcnf}" ]
209 then 235 then
210 /usr/bin/grep -q '^[ \t]*ssh' "${_inetcnf}" && _with_comment=0 236 /usr/bin/grep -q '^[[:space:]]*ssh' "${_inetcnf}" && _with_comment=0
211 237
212 # check for sshd OR ssh in top-level inetd.conf file, and remove 238 # check for sshd OR ssh in top-level inetd.conf file, and remove
213 # will be replaced by a file in inetd.d/ 239 # will be replaced by a file in inetd.d/
214 if [ `/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?` -eq 0 ] 240 if [ $(/usr/bin/grep -q '^[# \t]*ssh' "${_inetcnf}"; echo $?) -eq 0 ]
215 then 241 then
216 /usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}" 242 /usr/bin/grep -v '^[# \t]*ssh' "${_inetcnf}" >> "${_inetcnf_tmp}"
217 if [ -f "${_inetcnf_tmp}" ] 243 if [ -f "${_inetcnf_tmp}" ]
@@ -236,9 +262,9 @@ update_inetd_conf() {
236 then 262 then
237 if [ "${_with_comment}" -eq 0 ] 263 if [ "${_with_comment}" -eq 0 ]
238 then 264 then
239 /usr/bin/sed -e 's/@COMMENT@[ \t]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" 265 /usr/bin/sed -e 's/@COMMENT@[[:space:]]*//' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}"
240 else 266 else
241 /usr/bin/sed -e 's/@COMMENT@[ \t]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}" 267 /usr/bin/sed -e 's/@COMMENT@[[:space:]]*/# /' < "${_sshd_inetd_conf}" > "${_sshd_inetd_conf_tmp}"
242 fi 268 fi
243 if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}" 269 if /usr/bin/mv "${_sshd_inetd_conf_tmp}" "${_sshd_inetd_conf}"
244 then 270 then
@@ -251,13 +277,13 @@ update_inetd_conf() {
251 277
252 elif [ -f "${_inetcnf}" ] 278 elif [ -f "${_inetcnf}" ]
253 then 279 then
254 /usr/bin/grep -q '^[ \t]*sshd' "${_inetcnf}" && _with_comment=0 280 /usr/bin/grep -q '^[[:space:]]*sshd' "${_inetcnf}" && _with_comment=0
255 281
256 # check for sshd in top-level inetd.conf file, and remove 282 # check for sshd in top-level inetd.conf file, and remove
257 # will be replaced by a file in inetd.d/ 283 # will be replaced by a file in inetd.d/
258 if [ `/usr/bin/grep -q '^[# \t]*sshd' "${_inetcnf}"; echo $?` -eq 0 ] 284 if [ `/usr/bin/grep -q '^#\?[[:space:]]*sshd' "${_inetcnf}"; echo $?` -eq 0 ]
259 then 285 then
260 /usr/bin/grep -v '^[# \t]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}" 286 /usr/bin/grep -v '^#\?[[:space:]]*sshd' "${_inetcnf}" >> "${_inetcnf_tmp}"
261 if [ -f "${_inetcnf_tmp}" ] 287 if [ -f "${_inetcnf_tmp}" ]
262 then 288 then
263 if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}" 289 if /usr/bin/mv "${_inetcnf_tmp}" "${_inetcnf}"
@@ -305,17 +331,26 @@ check_service_files_ownership() {
305 331
306 if [ -z "${run_service_as}" ] 332 if [ -z "${run_service_as}" ]
307 then 333 then
308 accnt_name=$(/usr/bin/cygrunsrv -VQ sshd | /usr/bin/sed -ne 's/^Account *: *//gp') 334 accnt_name=$(/usr/bin/cygrunsrv -VQ sshd |
335 /usr/bin/sed -ne 's/^Account *: *//gp')
309 if [ "${accnt_name}" = "LocalSystem" ] 336 if [ "${accnt_name}" = "LocalSystem" ]
310 then 337 then
311 # Convert "LocalSystem" to "SYSTEM" as is the correct account name 338 # Convert "LocalSystem" to "SYSTEM" as is the correct account name
312 accnt_name="SYSTEM:" 339 run_service_as="SYSTEM"
313 elif [[ "${accnt_name}" =~ ^\.\\ ]] 340 else
314 then 341 dom="${accnt_name%%\\*}"
315 # Convert "." domain to local machine name 342 accnt_name="${accnt_name#*\\}"
316 accnt_name="U-${COMPUTERNAME}${accnt_name#.}," 343 if [ "${dom}" = '.' ]
344 then
345 # Check local account
346 run_service_as=$(/usr/bin/mkpasswd -l -u "${accnt_name}" |
347 /usr/bin/awk -F: '{print $1;}')
348 else
349 # Check domain
350 run_service_as=$(/usr/bin/mkpasswd -d "${dom}" -u "${accnt_name}" |
351 /usr/bin/awk -F: '{print $1;}')
352 fi
317 fi 353 fi
318 run_service_as=$(/usr/bin/grep -Fi "${accnt_name}" /etc/passwd | /usr/bin/awk -F: '{print $1;}')
319 if [ -z "${run_service_as}" ] 354 if [ -z "${run_service_as}" ]
320 then 355 then
321 csih_warning "Couldn't determine name of user running sshd service from /etc/passwd!" 356 csih_warning "Couldn't determine name of user running sshd service from /etc/passwd!"
@@ -615,32 +650,6 @@ echo
615 650
616warning_cnt=0 651warning_cnt=0
617 652
618# Check for ${SYSCONFDIR} directory
619csih_make_dir "${SYSCONFDIR}" "Cannot create global configuration files."
620if ! /usr/bin/chmod 775 "${SYSCONFDIR}" >/dev/null 2>&1
621then
622 csih_warning "Can't set permissions on ${SYSCONFDIR}!"
623 let ++warning_cnt
624fi
625if ! /usr/bin/setfacl -m u:system:rwx "${SYSCONFDIR}" >/dev/null 2>&1
626then
627 csih_warning "Can't set extended permissions on ${SYSCONFDIR}!"
628 let ++warning_cnt
629fi
630
631# Check for /var/log directory
632csih_make_dir "${LOCALSTATEDIR}/log" "Cannot create log directory."
633if ! /usr/bin/chmod 775 "${LOCALSTATEDIR}/log" >/dev/null 2>&1
634then
635 csih_warning "Can't set permissions on ${LOCALSTATEDIR}/log!"
636 let ++warning_cnt
637fi
638if ! /usr/bin/setfacl -m u:system:rwx "${LOCALSTATEDIR}/log" >/dev/null 2>&1
639then
640 csih_warning "Can't set extended permissions on ${LOCALSTATEDIR}/log!"
641 let ++warning_cnt
642fi
643
644# Create /var/log/lastlog if not already exists 653# Create /var/log/lastlog if not already exists
645if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ] 654if [ -e ${LOCALSTATEDIR}/log/lastlog -a ! -f ${LOCALSTATEDIR}/log/lastlog ]
646then 655then
@@ -665,13 +674,9 @@ then
665 csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!" 674 csih_warning "Can't set permissions on ${LOCALSTATEDIR}/empty!"
666 let ++warning_cnt 675 let ++warning_cnt
667fi 676fi
668if ! /usr/bin/setfacl -m u:system:rwx "${LOCALSTATEDIR}/empty" >/dev/null 2>&1
669then
670 csih_warning "Can't set extended permissions on ${LOCALSTATEDIR}/empty!"
671 let ++warning_cnt
672fi
673 677
674# generate missing host keys 678# generate missing host keys
679csih_inform "Generating missing SSH host keys"
675/usr/bin/ssh-keygen -A || let warning_cnt+=$? 680/usr/bin/ssh-keygen -A || let warning_cnt+=$?
676 681
677# handle ssh_config 682# handle ssh_config
@@ -690,10 +695,11 @@ fi
690csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt 695csih_install_config "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults" || let ++warning_cnt
691if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1 696if ! /usr/bin/cmp "${SYSCONFDIR}/sshd_config" "${SYSCONFDIR}/defaults/${SYSCONFDIR}/sshd_config" >/dev/null 2>&1
692then 697then
693 /usr/bin/grep -q UsePrivilegeSeparation ${SYSCONFDIR}/sshd_config && privsep_configured=yes 698 sshd_config_configured=yes
694fi 699fi
700sshd_strictmodes || let warning_cnt+=$?
695sshd_privsep || let warning_cnt+=$? 701sshd_privsep || let warning_cnt+=$?
696 702sshd_config_tweak || let warning_cnt+=$?
697update_services_file || let warning_cnt+=$? 703update_services_file || let warning_cnt+=$?
698update_inetd_conf || let warning_cnt+=$? 704update_inetd_conf || let warning_cnt+=$?
699install_service || let warning_cnt+=$? 705install_service || let warning_cnt+=$?
diff --git a/contrib/redhat/openssh.spec b/contrib/redhat/openssh.spec
index 96401c6ee..9bdce1e3c 100644
--- a/contrib/redhat/openssh.spec
+++ b/contrib/redhat/openssh.spec
@@ -1,4 +1,4 @@
1%define ver 6.6p1 1%define ver 6.7p1
2%define rel 1 2%define rel 1
3 3
4# OpenSSH privilege separation requires a user & group ID 4# OpenSSH privilege separation requires a user & group ID
@@ -86,7 +86,7 @@ PreReq: initscripts >= 5.00
86%else 86%else
87Requires: initscripts >= 5.20 87Requires: initscripts >= 5.20
88%endif 88%endif
89BuildRequires: perl, openssl-devel, tcp_wrappers 89BuildRequires: perl, openssl-devel
90BuildRequires: /bin/login 90BuildRequires: /bin/login
91%if ! %{build6x} 91%if ! %{build6x}
92BuildPreReq: glibc-devel, pam 92BuildPreReq: glibc-devel, pam
@@ -192,7 +192,6 @@ echo K5DIR=$K5DIR
192 --sysconfdir=%{_sysconfdir}/ssh \ 192 --sysconfdir=%{_sysconfdir}/ssh \
193 --libexecdir=%{_libexecdir}/openssh \ 193 --libexecdir=%{_libexecdir}/openssh \
194 --datadir=%{_datadir}/openssh \ 194 --datadir=%{_datadir}/openssh \
195 --with-tcp-wrappers \
196 --with-rsh=%{_bindir}/rsh \ 195 --with-rsh=%{_bindir}/rsh \
197 --with-default-path=/usr/local/bin:/bin:/usr/bin \ 196 --with-default-path=/usr/local/bin:/bin:/usr/bin \
198 --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \ 197 --with-superuser-path=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin \
diff --git a/contrib/suse/openssh.spec b/contrib/suse/openssh.spec
index 0515d6d7c..f87674317 100644
--- a/contrib/suse/openssh.spec
+++ b/contrib/suse/openssh.spec
@@ -13,7 +13,7 @@
13 13
14Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation 14Summary: OpenSSH, a free Secure Shell (SSH) protocol implementation
15Name: openssh 15Name: openssh
16Version: 6.6p1 16Version: 6.7p1
17URL: http://www.openssh.com/ 17URL: http://www.openssh.com/
18Release: 1 18Release: 1
19Source0: openssh-%{version}.tar.gz 19Source0: openssh-%{version}.tar.gz
@@ -28,11 +28,9 @@ Provides: ssh
28# (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.) 28# (Build[ing] Prereq[uisites] only work for RPM 2.95 and newer.)
29# building prerequisites -- stuff for 29# building prerequisites -- stuff for
30# OpenSSL (openssl-devel), 30# OpenSSL (openssl-devel),
31# TCP Wrappers (tcpd-devel),
32# and Gnome (glibdev, gtkdev, and gnlibsd) 31# and Gnome (glibdev, gtkdev, and gnlibsd)
33# 32#
34BuildPrereq: openssl 33BuildPrereq: openssl
35BuildPrereq: tcpd-devel
36BuildPrereq: zlib-devel 34BuildPrereq: zlib-devel
37#BuildPrereq: glibdev 35#BuildPrereq: glibdev
38#BuildPrereq: gtkdev 36#BuildPrereq: gtkdev
@@ -140,7 +138,6 @@ CFLAGS="$RPM_OPT_FLAGS" \
140 --mandir=%{_mandir} \ 138 --mandir=%{_mandir} \
141 --with-privsep-path=/var/lib/empty \ 139 --with-privsep-path=/var/lib/empty \
142 --with-pam \ 140 --with-pam \
143 --with-tcp-wrappers \
144 --libexecdir=%{_libdir}/ssh 141 --libexecdir=%{_libdir}/ssh
145make 142make
146 143
diff --git a/debian/.git-dpm b/debian/.git-dpm
index e15bf4ebd..c10ac230e 100644
--- a/debian/.git-dpm
+++ b/debian/.git-dpm
@@ -1,7 +1,7 @@
1# see git-dpm(1) from git-dpm package 1# see git-dpm(1) from git-dpm package
202883061577ec43ff8d0e8f0cf486bc5131db507 2762c062828f5a8f6ed189ed6e44ad38fd92f8b36
302883061577ec43ff8d0e8f0cf486bc5131db507 3762c062828f5a8f6ed189ed6e44ad38fd92f8b36
4796ba4fd011b5d0d9d78d592ba2f30fc9d5ed2e7 4487bdb3a5ef6075887b830ccb8a0b14f6da78e93
5487bdb3a5ef6075887b830ccb8a0b14f6da78e93 5487bdb3a5ef6075887b830ccb8a0b14f6da78e93
6openssh_6.7p1.orig.tar.gz 6openssh_6.7p1.orig.tar.gz
714e5fbed710ade334d65925e080d1aaeb9c85bf6 714e5fbed710ade334d65925e080d1aaeb9c85bf6
diff --git a/debian/changelog b/debian/changelog
index 0cf20dc14..e89bee3b7 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,5 +1,46 @@
1openssh (1:6.6p1-9) UNRELEASED; urgency=medium 1openssh (1:6.7p1-1) UNRELEASED; urgency=medium
2 2
3 * New upstream release (http://www.openssh.com/txt/release-6.7):
4 - sshd(8): The default set of ciphers and MACs has been altered to
5 remove unsafe algorithms. In particular, CBC ciphers and arcfour* are
6 disabled by default. The full set of algorithms remains available if
7 configured explicitly via the Ciphers and MACs sshd_config options.
8 - ssh(1), sshd(8): Add support for Unix domain socket forwarding. A
9 remote TCP port may be forwarded to a local Unix domain socket and
10 vice versa or both ends may be a Unix domain socket (closes: #236718).
11 - ssh(1), ssh-keygen(1): Add support for SSHFP DNS records for ED25519
12 key types.
13 - sftp(1): Allow resumption of interrupted uploads.
14 - ssh(1): When rekeying, skip file/DNS lookups of the hostkey if it is
15 the same as the one sent during initial key exchange.
16 - sshd(8): Allow explicit ::1 and 127.0.0.1 forwarding bind addresses
17 when GatewayPorts=no; allows client to choose address family.
18 - sshd(8): Add a sshd_config PermitUserRC option to control whether
19 ~/.ssh/rc is executed, mirroring the no-user-rc authorized_keys
20 option.
21 - ssh(1): Add a %C escape sequence for LocalCommand and ControlPath that
22 expands to a unique identifer based on a hash of the tuple of (local
23 host, remote user, hostname, port). Helps avoid exceeding miserly
24 pathname limits for Unix domain sockets in multiplexing control paths.
25 - sshd(8): Make the "Too many authentication failures" message include
26 the user, source address, port and protocol in a format similar to the
27 authentication success / failure messages.
28 - Use CLOCK_BOOTTIME in preference to CLOCK_MONOTONIC when it is
29 available. It considers time spent suspended, thereby ensuring
30 timeouts (e.g. for expiring agent keys) fire correctly (closes:
31 #734553).
32 - Use prctl() to prevent sftp-server from accessing
33 /proc/self/{mem,maps}.
34 * Restore TCP wrappers support, removed upstream in 6.7. It is true that
35 dropping this reduces preauth attack surface in sshd. On the other
36 hand, this support seems to be quite widely used, and abruptly dropping
37 it (from the perspective of users who don't read openssh-unix-dev) could
38 easily cause more serious problems in practice. It's not entirely clear
39 what the right long-term answer for Debian is, but it at least probably
40 doesn't involve dropping this feature shortly before a freeze.
41 * Replace patch to disable OpenSSL version check with an updated version
42 of Kurt Roeckx's patch from #732940 to just avoid checking the status
43 field.
3 * Build-depend on a new enough dpkg-dev for dpkg-buildflags, rather than 44 * Build-depend on a new enough dpkg-dev for dpkg-buildflags, rather than
4 simply a new enough dpkg. 45 simply a new enough dpkg.
5 * Simplify debian/rules using /usr/share/dpkg/buildflags.mk. 46 * Simplify debian/rules using /usr/share/dpkg/buildflags.mk.
diff --git a/debian/patches/auth-log-verbosity.patch b/debian/patches/auth-log-verbosity.patch
index 8d26d7b6f..84a14cfb8 100644
--- a/debian/patches/auth-log-verbosity.patch
+++ b/debian/patches/auth-log-verbosity.patch
@@ -1,4 +1,4 @@
1From 283322f493ee7dc75511f6cf9e9b88e536de0874 Mon Sep 17 00:00:00 2001 1From 1ecd5db58295874d8b9a7ce98fe1880ab08fbcaf Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:02 +0000 3Date: Sun, 9 Feb 2014 16:10:02 +0000
4Subject: Quieten logs when multiple from= restrictions are used 4Subject: Quieten logs when multiple from= restrictions are used
@@ -16,7 +16,7 @@ Patch-Name: auth-log-verbosity.patch
16 4 files changed, 32 insertions(+), 9 deletions(-) 16 4 files changed, 32 insertions(+), 9 deletions(-)
17 17
18diff --git a/auth-options.c b/auth-options.c 18diff --git a/auth-options.c b/auth-options.c
19index fa209ea..df61330 100644 19index f3d9c9d..d4d22d7 100644
20--- a/auth-options.c 20--- a/auth-options.c
21+++ b/auth-options.c 21+++ b/auth-options.c
22@@ -54,9 +54,20 @@ int forced_tun_device = -1; 22@@ -54,9 +54,20 @@ int forced_tun_device = -1;
@@ -58,7 +58,7 @@ index fa209ea..df61330 100644
58 auth_debug_add("Your host '%.200s' is not " 58 auth_debug_add("Your host '%.200s' is not "
59 "permitted to use this key for login.", 59 "permitted to use this key for login.",
60 remote_host); 60 remote_host);
61@@ -510,11 +524,14 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw, 61@@ -511,11 +525,14 @@ parse_option_list(u_char *optblob, size_t optblob_len, struct passwd *pw,
62 break; 62 break;
63 case 0: 63 case 0:
64 /* no match */ 64 /* no match */
@@ -91,10 +91,10 @@ index 7455c94..a3f0a02 100644
91 void auth_clear_options(void); 91 void auth_clear_options(void);
92 int auth_cert_options(Key *, struct passwd *); 92 int auth_cert_options(Key *, struct passwd *);
93diff --git a/auth-rsa.c b/auth-rsa.c 93diff --git a/auth-rsa.c b/auth-rsa.c
94index 5dad6c3..260ce2f 100644 94index e9f4ede..5d7bdcb 100644
95--- a/auth-rsa.c 95--- a/auth-rsa.c
96+++ b/auth-rsa.c 96+++ b/auth-rsa.c
97@@ -178,6 +178,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file, 97@@ -179,6 +179,8 @@ rsa_key_allowed_in_file(struct passwd *pw, char *file,
98 if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL) 98 if ((f = auth_openkeyfile(file, pw, options.strict_modes)) == NULL)
99 return 0; 99 return 0;
100 100
@@ -104,10 +104,10 @@ index 5dad6c3..260ce2f 100644
104 * Go though the accepted keys, looking for the current key. If 104 * Go though the accepted keys, looking for the current key. If
105 * found, perform a challenge-response dialog to verify that the 105 * found, perform a challenge-response dialog to verify that the
106diff --git a/auth2-pubkey.c b/auth2-pubkey.c 106diff --git a/auth2-pubkey.c b/auth2-pubkey.c
107index 0fd27bb..7c56927 100644 107index f3ca965..f78b046 100644
108--- a/auth2-pubkey.c 108--- a/auth2-pubkey.c
109+++ b/auth2-pubkey.c 109+++ b/auth2-pubkey.c
110@@ -263,6 +263,7 @@ match_principals_file(char *file, struct passwd *pw, struct KeyCert *cert) 110@@ -263,6 +263,7 @@ match_principals_file(char *file, struct passwd *pw, struct sshkey_cert *cert)
111 restore_uid(); 111 restore_uid();
112 return 0; 112 return 0;
113 } 113 }
diff --git a/debian/patches/authorized-keys-man-symlink.patch b/debian/patches/authorized-keys-man-symlink.patch
index 74bfb46e6..6afb0420b 100644
--- a/debian/patches/authorized-keys-man-symlink.patch
+++ b/debian/patches/authorized-keys-man-symlink.patch
@@ -1,4 +1,4 @@
1From 71448da5ce75ba50bcb10dbbd3b8c7633f633e8f Mon Sep 17 00:00:00 2001 1From 19b0441502c07401dd6d418f8f81cc7f1a44ccb1 Mon Sep 17 00:00:00 2001
2From: Tomas Pospisek <tpo_deb@sourcepole.ch> 2From: Tomas Pospisek <tpo_deb@sourcepole.ch>
3Date: Sun, 9 Feb 2014 16:10:07 +0000 3Date: Sun, 9 Feb 2014 16:10:07 +0000
4Subject: Install authorized_keys(5) as a symlink to sshd(8) 4Subject: Install authorized_keys(5) as a symlink to sshd(8)
@@ -13,10 +13,10 @@ Patch-Name: authorized-keys-man-symlink.patch
13 1 file changed, 1 insertion(+) 13 1 file changed, 1 insertion(+)
14 14
15diff --git a/Makefile.in b/Makefile.in 15diff --git a/Makefile.in b/Makefile.in
16index 3d96c05..feee0b2 100644 16index c4cb8ea..a4402e9 100644
17--- a/Makefile.in 17--- a/Makefile.in
18+++ b/Makefile.in 18+++ b/Makefile.in
19@@ -287,6 +287,7 @@ install-files: 19@@ -309,6 +309,7 @@ install-files:
20 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5 20 $(INSTALL) -m 644 sshd_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/sshd_config.5
21 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5 21 $(INSTALL) -m 644 ssh_config.5.out $(DESTDIR)$(mandir)/$(mansubdir)5/ssh_config.5
22 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8 22 $(INSTALL) -m 644 sshd.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/sshd.8
diff --git a/debian/patches/consolekit.patch b/debian/patches/consolekit.patch
index e3ff4d7e4..e50c77f62 100644
--- a/debian/patches/consolekit.patch
+++ b/debian/patches/consolekit.patch
@@ -1,33 +1,33 @@
1From 7a26d16efb4ee303c8d66ee82caf9d0686f4a074 Mon Sep 17 00:00:00 2001 1From f51fe0c55e54c12db952624e980d18f39c41e581 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@ubuntu.com> 2From: Colin Watson <cjwatson@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:09:57 +0000 3Date: Sun, 9 Feb 2014 16:09:57 +0000
4Subject: Add support for registering ConsoleKit sessions on login 4Subject: Add support for registering ConsoleKit sessions on login
5 5
6Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1450 6Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1450
7Last-Updated: 2014-03-20 7Last-Updated: 2014-10-07
8 8
9Patch-Name: consolekit.patch 9Patch-Name: consolekit.patch
10--- 10---
11 Makefile.in | 3 +- 11 Makefile.in | 3 +-
12 configure | 132 +++++++++++++++++++++++++++++++ 12 configure | 132 +++++++++++++++++++++++++++++++
13 configure.ac | 25 ++++++ 13 configure.ac | 25 ++++++
14 consolekit.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 14 consolekit.c | 241 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
15 consolekit.h | 24 ++++++ 15 consolekit.h | 24 ++++++
16 monitor.c | 42 ++++++++++ 16 monitor.c | 42 ++++++++++
17 monitor.h | 2 + 17 monitor.h | 2 +
18 monitor_wrap.c | 30 ++++++++ 18 monitor_wrap.c | 30 +++++++
19 monitor_wrap.h | 4 + 19 monitor_wrap.h | 4 +
20 session.c | 13 ++++ 20 session.c | 13 ++++
21 session.h | 6 ++ 21 session.h | 6 ++
22 11 files changed, 520 insertions(+), 1 deletion(-) 22 11 files changed, 521 insertions(+), 1 deletion(-)
23 create mode 100644 consolekit.c 23 create mode 100644 consolekit.c
24 create mode 100644 consolekit.h 24 create mode 100644 consolekit.h
25 25
26diff --git a/Makefile.in b/Makefile.in 26diff --git a/Makefile.in b/Makefile.in
27index ee1d2c3..3d96c05 100644 27index 086d8dd..c4cb8ea 100644
28--- a/Makefile.in 28--- a/Makefile.in
29+++ b/Makefile.in 29+++ b/Makefile.in
30@@ -97,7 +97,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ 30@@ -107,7 +107,8 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
31 sftp-server.o sftp-common.o \ 31 sftp-server.o sftp-common.o \
32 roaming_common.o roaming_serv.o \ 32 roaming_common.o roaming_serv.o \
33 sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \ 33 sandbox-null.o sandbox-rlimit.o sandbox-systrace.o sandbox-darwin.o \
@@ -38,10 +38,10 @@ index ee1d2c3..3d96c05 100644
38 MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out 38 MANPAGES = moduli.5.out scp.1.out ssh-add.1.out ssh-agent.1.out ssh-keygen.1.out ssh-keyscan.1.out ssh.1.out sshd.8.out sftp-server.8.out sftp.1.out ssh-keysign.8.out ssh-pkcs11-helper.8.out sshd_config.5.out ssh_config.5.out
39 MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5 39 MANPAGES_IN = moduli.5 scp.1 ssh-add.1 ssh-agent.1 ssh-keygen.1 ssh-keyscan.1 ssh.1 sshd.8 sftp-server.8 sftp.1 ssh-keysign.8 ssh-pkcs11-helper.8 sshd_config.5 ssh_config.5
40diff --git a/configure b/configure 40diff --git a/configure b/configure
41index b6b5b6d..e2f12cd 100755 41index ea5f200..7be478a 100755
42--- a/configure 42--- a/configure
43+++ b/configure 43+++ b/configure
44@@ -740,6 +740,7 @@ with_privsep_user 44@@ -739,6 +739,7 @@ with_privsep_user
45 with_sandbox 45 with_sandbox
46 with_selinux 46 with_selinux
47 with_kerberos5 47 with_kerberos5
@@ -49,7 +49,7 @@ index b6b5b6d..e2f12cd 100755
49 with_privsep_path 49 with_privsep_path
50 with_xauth 50 with_xauth
51 enable_strip 51 enable_strip
52@@ -1432,6 +1433,7 @@ Optional Packages: 52@@ -1430,6 +1431,7 @@ Optional Packages:
53 --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum) 53 --with-sandbox=style Specify privilege separation sandbox (no, darwin, rlimit, systrace, seccomp_filter, capsicum)
54 --with-selinux Enable SELinux support 54 --with-selinux Enable SELinux support
55 --with-kerberos5=PATH Enable Kerberos 5 support 55 --with-kerberos5=PATH Enable Kerberos 5 support
@@ -57,7 +57,7 @@ index b6b5b6d..e2f12cd 100755
57 --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty) 57 --with-privsep-path=xxx Path for privilege separation chroot (default=/var/empty)
58 --with-xauth=PATH Specify path to xauth program 58 --with-xauth=PATH Specify path to xauth program
59 --with-maildir=/path/to/mail Specify your system mail directory 59 --with-maildir=/path/to/mail Specify your system mail directory
60@@ -17217,6 +17219,135 @@ fi 60@@ -17211,6 +17213,135 @@ fi
61 61
62 62
63 63
@@ -193,7 +193,7 @@ index b6b5b6d..e2f12cd 100755
193 # Looking for programs, paths and files 193 # Looking for programs, paths and files
194 194
195 PRIVSEP_PATH=/var/empty 195 PRIVSEP_PATH=/var/empty
196@@ -19746,6 +19877,7 @@ echo " MD5 password support: $MD5_MSG" 196@@ -19739,6 +19870,7 @@ echo " MD5 password support: $MD5_MSG"
197 echo " libedit support: $LIBEDIT_MSG" 197 echo " libedit support: $LIBEDIT_MSG"
198 echo " Solaris process contract support: $SPC_MSG" 198 echo " Solaris process contract support: $SPC_MSG"
199 echo " Solaris project support: $SP_MSG" 199 echo " Solaris project support: $SP_MSG"
@@ -202,10 +202,10 @@ index b6b5b6d..e2f12cd 100755
202 echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG" 202 echo " Translate v4 in v6 hack: $IPV4_IN6_HACK_MSG"
203 echo " BSD Auth support: $BSD_AUTH_MSG" 203 echo " BSD Auth support: $BSD_AUTH_MSG"
204diff --git a/configure.ac b/configure.ac 204diff --git a/configure.ac b/configure.ac
205index d235fb0..8669271 100644 205index 7f160f1..f5c65c5 100644
206--- a/configure.ac 206--- a/configure.ac
207+++ b/configure.ac 207+++ b/configure.ac
208@@ -4072,6 +4072,30 @@ AC_ARG_WITH([kerberos5], 208@@ -4113,6 +4113,30 @@ AC_ARG_WITH([kerberos5],
209 AC_SUBST([GSSLIBS]) 209 AC_SUBST([GSSLIBS])
210 AC_SUBST([K5LIBS]) 210 AC_SUBST([K5LIBS])
211 211
@@ -236,7 +236,7 @@ index d235fb0..8669271 100644
236 # Looking for programs, paths and files 236 # Looking for programs, paths and files
237 237
238 PRIVSEP_PATH=/var/empty 238 PRIVSEP_PATH=/var/empty
239@@ -4873,6 +4897,7 @@ echo " MD5 password support: $MD5_MSG" 239@@ -4914,6 +4938,7 @@ echo " MD5 password support: $MD5_MSG"
240 echo " libedit support: $LIBEDIT_MSG" 240 echo " libedit support: $LIBEDIT_MSG"
241 echo " Solaris process contract support: $SPC_MSG" 241 echo " Solaris process contract support: $SPC_MSG"
242 echo " Solaris project support: $SP_MSG" 242 echo " Solaris project support: $SP_MSG"
@@ -246,10 +246,10 @@ index d235fb0..8669271 100644
246 echo " BSD Auth support: $BSD_AUTH_MSG" 246 echo " BSD Auth support: $BSD_AUTH_MSG"
247diff --git a/consolekit.c b/consolekit.c 247diff --git a/consolekit.c b/consolekit.c
248new file mode 100644 248new file mode 100644
249index 0000000..f1039e6 249index 0000000..0266f06
250--- /dev/null 250--- /dev/null
251+++ b/consolekit.c 251+++ b/consolekit.c
252@@ -0,0 +1,240 @@ 252@@ -0,0 +1,241 @@
253+/* 253+/*
254+ * Copyright (c) 2008 Colin Watson. All rights reserved. 254+ * Copyright (c) 2008 Colin Watson. All rights reserved.
255+ * 255+ *
@@ -305,6 +305,7 @@ index 0000000..f1039e6
305+#include "hostfile.h" 305+#include "hostfile.h"
306+#include "auth.h" 306+#include "auth.h"
307+#include "log.h" 307+#include "log.h"
308+#include "misc.h"
308+#include "servconf.h" 309+#include "servconf.h"
309+#include "canohost.h" 310+#include "canohost.h"
310+#include "session.h" 311+#include "session.h"
@@ -521,10 +522,10 @@ index 0000000..8ce3716
521+ 522+
522+#endif /* USE_CONSOLEKIT */ 523+#endif /* USE_CONSOLEKIT */
523diff --git a/monitor.c b/monitor.c 524diff --git a/monitor.c b/monitor.c
524index 11eac63..7c105e6 100644 525index 94b194d..cc15ce4 100644
525--- a/monitor.c 526--- a/monitor.c
526+++ b/monitor.c 527+++ b/monitor.c
527@@ -97,6 +97,9 @@ 528@@ -100,6 +100,9 @@
528 #include "ssh2.h" 529 #include "ssh2.h"
529 #include "roaming.h" 530 #include "roaming.h"
530 #include "authfd.h" 531 #include "authfd.h"
@@ -534,7 +535,7 @@ index 11eac63..7c105e6 100644
534 535
535 #ifdef GSSAPI 536 #ifdef GSSAPI
536 static Gssctxt *gsscontext = NULL; 537 static Gssctxt *gsscontext = NULL;
537@@ -187,6 +190,10 @@ int mm_answer_audit_command(int, Buffer *); 538@@ -190,6 +193,10 @@ int mm_answer_audit_command(int, Buffer *);
538 539
539 static int monitor_read_log(struct monitor *); 540 static int monitor_read_log(struct monitor *);
540 541
@@ -543,9 +544,9 @@ index 11eac63..7c105e6 100644
543+#endif 544+#endif
544+ 545+
545 static Authctxt *authctxt; 546 static Authctxt *authctxt;
546 static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
547 547
548@@ -272,6 +279,9 @@ struct mon_table mon_dispatch_postauth20[] = { 548 #ifdef WITH_SSH1
549@@ -282,6 +289,9 @@ struct mon_table mon_dispatch_postauth20[] = {
549 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 550 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
550 {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command}, 551 {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT, mm_answer_audit_command},
551 #endif 552 #endif
@@ -555,17 +556,17 @@ index 11eac63..7c105e6 100644
555 {0, 0, NULL} 556 {0, 0, NULL}
556 }; 557 };
557 558
558@@ -314,6 +324,9 @@ struct mon_table mon_dispatch_postauth15[] = { 559@@ -327,6 +337,9 @@ struct mon_table mon_dispatch_postauth15[] = {
559 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 560 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
560 {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command}, 561 {MONITOR_REQ_AUDIT_COMMAND, MON_PERMIT|MON_ONCE, mm_answer_audit_command},
561 #endif 562 #endif
562+#ifdef USE_CONSOLEKIT 563+#ifdef USE_CONSOLEKIT
563+ {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register}, 564+ {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register},
564+#endif 565+#endif
566 #endif /* WITH_SSH1 */
565 {0, 0, NULL} 567 {0, 0, NULL}
566 }; 568 };
567 569@@ -509,6 +522,9 @@ monitor_child_postauth(struct monitor *pmonitor)
568@@ -492,6 +505,9 @@ monitor_child_postauth(struct monitor *pmonitor)
569 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1); 570 monitor_permit(mon_dispatch, MONITOR_REQ_PTY, 1);
570 monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1); 571 monitor_permit(mon_dispatch, MONITOR_REQ_PTYCLEANUP, 1);
571 } 572 }
@@ -575,7 +576,7 @@ index 11eac63..7c105e6 100644
575 576
576 for (;;) 577 for (;;)
577 monitor_read(pmonitor, mon_dispatch, NULL); 578 monitor_read(pmonitor, mon_dispatch, NULL);
578@@ -2269,3 +2285,29 @@ mm_answer_gss_updatecreds(int socket, Buffer *m) { 579@@ -2296,3 +2312,29 @@ mm_answer_gss_updatecreds(int socket, Buffer *m) {
579 580
580 #endif /* GSSAPI */ 581 #endif /* GSSAPI */
581 582
@@ -619,10 +620,10 @@ index 4d5e8fa..10ba59e 100644
619 620
620 struct mm_master; 621 struct mm_master;
621diff --git a/monitor_wrap.c b/monitor_wrap.c 622diff --git a/monitor_wrap.c b/monitor_wrap.c
622index f75dc9d..a8fb07b 100644 623index 6dc890a..4c57d4d 100644
623--- a/monitor_wrap.c 624--- a/monitor_wrap.c
624+++ b/monitor_wrap.c 625+++ b/monitor_wrap.c
625@@ -1353,3 +1353,33 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store) 626@@ -1363,3 +1363,33 @@ mm_ssh_gssapi_update_creds(ssh_gssapi_ccache *store)
626 627
627 #endif /* GSSAPI */ 628 #endif /* GSSAPI */
628 629
@@ -670,10 +671,10 @@ index 9c2ee49..00e93fe 100644
670+ 671+
671 #endif /* _MM_WRAP_H_ */ 672 #endif /* _MM_WRAP_H_ */
672diff --git a/session.c b/session.c 673diff --git a/session.c b/session.c
673index 6848df4..9d43fc3 100644 674index 6f389ac..6250c20 100644
674--- a/session.c 675--- a/session.c
675+++ b/session.c 676+++ b/session.c
676@@ -92,6 +92,7 @@ 677@@ -93,6 +93,7 @@
677 #include "kex.h" 678 #include "kex.h"
678 #include "monitor_wrap.h" 679 #include "monitor_wrap.h"
679 #include "sftp.h" 680 #include "sftp.h"
@@ -681,7 +682,7 @@ index 6848df4..9d43fc3 100644
681 682
682 #if defined(KRB5) && defined(USE_AFS) 683 #if defined(KRB5) && defined(USE_AFS)
683 #include <kafs.h> 684 #include <kafs.h>
684@@ -1160,6 +1161,9 @@ do_setup_env(Session *s, const char *shell) 685@@ -1143,6 +1144,9 @@ do_setup_env(Session *s, const char *shell)
685 #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN) 686 #if !defined (HAVE_LOGIN_CAP) && !defined (HAVE_CYGWIN)
686 char *path = NULL; 687 char *path = NULL;
687 #endif 688 #endif
@@ -691,7 +692,7 @@ index 6848df4..9d43fc3 100644
691 692
692 /* Initialize the environment. */ 693 /* Initialize the environment. */
693 envsize = 100; 694 envsize = 100;
694@@ -1304,6 +1308,11 @@ do_setup_env(Session *s, const char *shell) 695@@ -1287,6 +1291,11 @@ do_setup_env(Session *s, const char *shell)
695 child_set_env(&env, &envsize, "KRB5CCNAME", 696 child_set_env(&env, &envsize, "KRB5CCNAME",
696 s->authctxt->krb5_ccname); 697 s->authctxt->krb5_ccname);
697 #endif 698 #endif
@@ -703,7 +704,7 @@ index 6848df4..9d43fc3 100644
703 #ifdef USE_PAM 704 #ifdef USE_PAM
704 /* 705 /*
705 * Pull in any environment variables that may have 706 * Pull in any environment variables that may have
706@@ -2353,6 +2362,10 @@ session_pty_cleanup2(Session *s) 707@@ -2350,6 +2359,10 @@ session_pty_cleanup2(Session *s)
707 708
708 debug("session_pty_cleanup: session %d release %s", s->self, s->tty); 709 debug("session_pty_cleanup: session %d release %s", s->self, s->tty);
709 710
diff --git a/debian/patches/curve25519-sha256-bignum-encoding.patch b/debian/patches/curve25519-sha256-bignum-encoding.patch
deleted file mode 100644
index ccb66048d..000000000
--- a/debian/patches/curve25519-sha256-bignum-encoding.patch
+++ /dev/null
@@ -1,161 +0,0 @@
1From 02883061577ec43ff8d0e8f0cf486bc5131db507 Mon Sep 17 00:00:00 2001
2From: Damien Miller <djm@mindrot.org>
3Date: Sun, 20 Apr 2014 13:47:45 +1000
4Subject: bad bignum encoding for curve25519-sha256@libssh.org
5
6Hi,
7
8So I screwed up when writing the support for the curve25519 KEX method
9that doesn't depend on OpenSSL's BIGNUM type - a bug in my code left
10leading zero bytes where they should have been skipped. The impact of
11this is that OpenSSH 6.5 and 6.6 will fail during key exchange with a
12peer that implements curve25519-sha256@libssh.org properly about 0.2%
13of the time (one in every 512ish connections).
14
15We've fixed this for OpenSSH 6.7 by avoiding the curve25519-sha256
16key exchange for previous versions, but I'd recommend distributors
17of OpenSSH apply this patch so the affected code doesn't become
18too entrenched in LTS releases.
19
20The patch fixes the bug and makes OpenSSH identify itself as 6.6.1 so as
21to distinguish itself from the incorrect versions so the compatibility
22code to disable the affected KEX isn't activated.
23
24I've committed this on the 6.6 branch too.
25
26Apologies for the hassle.
27
28-d
29
30Origin: upstream, https://lists.mindrot.org/pipermail/openssh-unix-dev/2014-April/032494.html
31Forwarded: not-needed
32Last-Update: 2014-04-21
33
34Patch-Name: curve25519-sha256-bignum-encoding.patch
35---
36 bufaux.c | 5 ++++-
37 compat.c | 17 ++++++++++++++++-
38 compat.h | 2 ++
39 sshconnect2.c | 2 ++
40 sshd.c | 3 +++
41 version.h | 2 +-
42 6 files changed, 28 insertions(+), 3 deletions(-)
43
44diff --git a/bufaux.c b/bufaux.c
45index e24b5fc..f6a6f2a 100644
46--- a/bufaux.c
47+++ b/bufaux.c
48@@ -1,4 +1,4 @@
49-/* $OpenBSD: bufaux.c,v 1.56 2014/02/02 03:44:31 djm Exp $ */
50+/* $OpenBSD: bufaux.c,v 1.57 2014/04/16 23:22:45 djm Exp $ */
51 /*
52 * Author: Tatu Ylonen <ylo@cs.hut.fi>
53 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
54@@ -372,6 +372,9 @@ buffer_put_bignum2_from_string(Buffer *buffer, const u_char *s, u_int l)
55
56 if (l > 8 * 1024)
57 fatal("%s: length %u too long", __func__, l);
58+ /* Skip leading zero bytes */
59+ for (; l > 0 && *s == 0; l--, s++)
60+ ;
61 p = buf = xmalloc(l + 1);
62 /*
63 * If most significant bit is set then prepend a zero byte to
64diff --git a/compat.c b/compat.c
65index 9d9fabe..2709dc5 100644
66--- a/compat.c
67+++ b/compat.c
68@@ -95,6 +95,9 @@ compat_datafellows(const char *version)
69 { "Sun_SSH_1.0*", SSH_BUG_NOREKEY|SSH_BUG_EXTEOF},
70 { "OpenSSH_4*", 0 },
71 { "OpenSSH_5*", SSH_NEW_OPENSSH|SSH_BUG_DYNAMIC_RPORT},
72+ { "OpenSSH_6.6.1*", SSH_NEW_OPENSSH},
73+ { "OpenSSH_6.5*,"
74+ "OpenSSH_6.6*", SSH_NEW_OPENSSH|SSH_BUG_CURVE25519PAD},
75 { "OpenSSH*", SSH_NEW_OPENSSH },
76 { "*MindTerm*", 0 },
77 { "2.1.0*", SSH_BUG_SIGBLOB|SSH_BUG_HMAC|
78@@ -251,7 +254,6 @@ compat_cipher_proposal(char *cipher_prop)
79 return cipher_prop;
80 }
81
82-
83 char *
84 compat_pkalg_proposal(char *pkalg_prop)
85 {
86@@ -265,3 +267,16 @@ compat_pkalg_proposal(char *pkalg_prop)
87 return pkalg_prop;
88 }
89
90+char *
91+compat_kex_proposal(char *kex_prop)
92+{
93+ if (!(datafellows & SSH_BUG_CURVE25519PAD))
94+ return kex_prop;
95+ debug2("%s: original KEX proposal: %s", __func__, kex_prop);
96+ kex_prop = filter_proposal(kex_prop, "curve25519-sha256@libssh.org");
97+ debug2("%s: compat KEX proposal: %s", __func__, kex_prop);
98+ if (*kex_prop == '\0')
99+ fatal("No supported key exchange algorithms found");
100+ return kex_prop;
101+}
102+
103diff --git a/compat.h b/compat.h
104index b174fa1..a6c3f3d 100644
105--- a/compat.h
106+++ b/compat.h
107@@ -59,6 +59,7 @@
108 #define SSH_BUG_RFWD_ADDR 0x02000000
109 #define SSH_NEW_OPENSSH 0x04000000
110 #define SSH_BUG_DYNAMIC_RPORT 0x08000000
111+#define SSH_BUG_CURVE25519PAD 0x10000000
112
113 void enable_compat13(void);
114 void enable_compat20(void);
115@@ -66,6 +67,7 @@ void compat_datafellows(const char *);
116 int proto_spec(const char *);
117 char *compat_cipher_proposal(char *);
118 char *compat_pkalg_proposal(char *);
119+char *compat_kex_proposal(char *);
120
121 extern int compat13;
122 extern int compat20;
123diff --git a/sshconnect2.c b/sshconnect2.c
124index 66cb035..1a4e551 100644
125--- a/sshconnect2.c
126+++ b/sshconnect2.c
127@@ -220,6 +220,8 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
128 }
129 if (options.kex_algorithms != NULL)
130 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
131+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
132+ myproposal[PROPOSAL_KEX_ALGS]);
133
134 #ifdef GSSAPI
135 /* If we've got GSSAPI algorithms, then we also support the
136diff --git a/sshd.c b/sshd.c
137index 0964491..fe78d7b 100644
138--- a/sshd.c
139+++ b/sshd.c
140@@ -2534,6 +2534,9 @@ do_ssh2_kex(void)
141 if (options.kex_algorithms != NULL)
142 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms;
143
144+ myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
145+ myproposal[PROPOSAL_KEX_ALGS]);
146+
147 if (options.rekey_limit || options.rekey_interval)
148 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
149 (time_t)options.rekey_interval);
150diff --git a/version.h b/version.h
151index a97c337..0659576 100644
152--- a/version.h
153+++ b/version.h
154@@ -1,6 +1,6 @@
155 /* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */
156
157-#define SSH_VERSION "OpenSSH_6.6"
158+#define SSH_VERSION "OpenSSH_6.6.1"
159
160 #define SSH_PORTABLE "p1"
161 #define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE
diff --git a/debian/patches/debian-banner.patch b/debian/patches/debian-banner.patch
index 49219cf93..ab64cbed5 100644
--- a/debian/patches/debian-banner.patch
+++ b/debian/patches/debian-banner.patch
@@ -1,4 +1,4 @@
1From 9fcad888f4dbf0ecc0c7e87b6ef0f8d88d7ac3ec Mon Sep 17 00:00:00 2001 1From 114c8a8fb488cbe39507edb75c51198a4b9e8b24 Mon Sep 17 00:00:00 2001
2From: Kees Cook <kees@debian.org> 2From: Kees Cook <kees@debian.org>
3Date: Sun, 9 Feb 2014 16:10:06 +0000 3Date: Sun, 9 Feb 2014 16:10:06 +0000
4Subject: Add DebianBanner server configuration option 4Subject: Add DebianBanner server configuration option
@@ -8,7 +8,7 @@ initial protocol handshake, for those scared by package-versioning.patch.
8 8
9Bug-Debian: http://bugs.debian.org/562048 9Bug-Debian: http://bugs.debian.org/562048
10Forwarded: not-needed 10Forwarded: not-needed
11Last-Update: 2013-09-14 11Last-Update: 2014-10-07
12 12
13Patch-Name: debian-banner.patch 13Patch-Name: debian-banner.patch
14--- 14---
@@ -19,10 +19,10 @@ Patch-Name: debian-banner.patch
19 4 files changed, 18 insertions(+), 1 deletion(-) 19 4 files changed, 18 insertions(+), 1 deletion(-)
20 20
21diff --git a/servconf.c b/servconf.c 21diff --git a/servconf.c b/servconf.c
22index 90de888..37fd2de 100644 22index a252487..6c7741a 100644
23--- a/servconf.c 23--- a/servconf.c
24+++ b/servconf.c 24+++ b/servconf.c
25@@ -156,6 +156,7 @@ initialize_server_options(ServerOptions *options) 25@@ -160,6 +160,7 @@ initialize_server_options(ServerOptions *options)
26 options->ip_qos_interactive = -1; 26 options->ip_qos_interactive = -1;
27 options->ip_qos_bulk = -1; 27 options->ip_qos_bulk = -1;
28 options->version_addendum = NULL; 28 options->version_addendum = NULL;
@@ -30,34 +30,34 @@ index 90de888..37fd2de 100644
30 } 30 }
31 31
32 void 32 void
33@@ -309,6 +310,8 @@ fill_default_server_options(ServerOptions *options) 33@@ -321,6 +322,8 @@ fill_default_server_options(ServerOptions *options)
34 options->ip_qos_bulk = IPTOS_THROUGHPUT; 34 options->fwd_opts.streamlocal_bind_mask = 0177;
35 if (options->version_addendum == NULL) 35 if (options->fwd_opts.streamlocal_bind_unlink == -1)
36 options->version_addendum = xstrdup(""); 36 options->fwd_opts.streamlocal_bind_unlink = 0;
37+ if (options->debian_banner == -1) 37+ if (options->debian_banner == -1)
38+ options->debian_banner = 1; 38+ options->debian_banner = 1;
39 /* Turn privilege separation on by default */ 39 /* Turn privilege separation on by default */
40 if (use_privsep == -1) 40 if (use_privsep == -1)
41 use_privsep = PRIVSEP_NOSANDBOX; 41 use_privsep = PRIVSEP_NOSANDBOX;
42@@ -359,6 +362,7 @@ typedef enum { 42@@ -373,6 +376,7 @@ typedef enum {
43 sKexAlgorithms, sIPQoS, sVersionAddendum, 43 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
44 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 44 sStreamLocalBindMask, sStreamLocalBindUnlink,
45 sAuthenticationMethods, sHostKeyAgent, 45 sAllowStreamLocalForwarding,
46+ sDebianBanner, 46+ sDebianBanner,
47 sDeprecated, sUnsupported 47 sDeprecated, sUnsupported
48 } ServerOpCodes; 48 } ServerOpCodes;
49 49
50@@ -496,6 +500,7 @@ static struct { 50@@ -514,6 +518,7 @@ static struct {
51 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 51 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
52 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 52 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
53 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 53 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
54+ { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, 54+ { "debianbanner", sDebianBanner, SSHCFG_GLOBAL },
55 { NULL, sBadOption, 0 } 55 { NULL, sBadOption, 0 }
56 }; 56 };
57 57
58@@ -1654,6 +1659,10 @@ process_server_config_line(ServerOptions *options, char *line, 58@@ -1697,6 +1702,10 @@ process_server_config_line(ServerOptions *options, char *line,
59 } 59 intptr = &options->fwd_opts.streamlocal_bind_unlink;
60 return 0; 60 goto parse_flag;
61 61
62+ case sDebianBanner: 62+ case sDebianBanner:
63+ intptr = &options->debian_banner; 63+ intptr = &options->debian_banner;
@@ -67,10 +67,10 @@ index 90de888..37fd2de 100644
67 logit("%s line %d: Deprecated option %s", 67 logit("%s line %d: Deprecated option %s",
68 filename, linenum, arg); 68 filename, linenum, arg);
69diff --git a/servconf.h b/servconf.h 69diff --git a/servconf.h b/servconf.h
70index c922eb5..dcd1c2a 100644 70index f8265a8..fa48804 100644
71--- a/servconf.h 71--- a/servconf.h
72+++ b/servconf.h 72+++ b/servconf.h
73@@ -186,6 +186,8 @@ typedef struct { 73@@ -188,6 +188,8 @@ typedef struct {
74 74
75 u_int num_auth_methods; 75 u_int num_auth_methods;
76 char *auth_methods[MAX_AUTH_METHODS]; 76 char *auth_methods[MAX_AUTH_METHODS];
@@ -80,10 +80,10 @@ index c922eb5..dcd1c2a 100644
80 80
81 /* Information about the incoming connection as used by Match */ 81 /* Information about the incoming connection as used by Match */
82diff --git a/sshd.c b/sshd.c 82diff --git a/sshd.c b/sshd.c
83index af9b8f1..665c0b9 100644 83index 1710e71..87331c1 100644
84--- a/sshd.c 84--- a/sshd.c
85+++ b/sshd.c 85+++ b/sshd.c
86@@ -440,7 +440,8 @@ sshd_exchange_identification(int sock_in, int sock_out) 86@@ -443,7 +443,8 @@ sshd_exchange_identification(int sock_in, int sock_out)
87 } 87 }
88 88
89 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", 89 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
@@ -94,10 +94,10 @@ index af9b8f1..665c0b9 100644
94 options.version_addendum, newline); 94 options.version_addendum, newline);
95 95
96diff --git a/sshd_config.5 b/sshd_config.5 96diff --git a/sshd_config.5 b/sshd_config.5
97index 2164d58..8f078f6 100644 97index 2843048..58997d3 100644
98--- a/sshd_config.5 98--- a/sshd_config.5
99+++ b/sshd_config.5 99+++ b/sshd_config.5
100@@ -413,6 +413,11 @@ or 100@@ -447,6 +447,11 @@ or
101 .Dq no . 101 .Dq no .
102 The default is 102 The default is
103 .Dq delayed . 103 .Dq delayed .
diff --git a/debian/patches/debian-config.patch b/debian/patches/debian-config.patch
index 9ada04a10..661d30ca8 100644
--- a/debian/patches/debian-config.patch
+++ b/debian/patches/debian-config.patch
@@ -1,4 +1,4 @@
1From df5c8d109fb3d9ec16a487107a44300ed3006849 Mon Sep 17 00:00:00 2001 1From 762c062828f5a8f6ed189ed6e44ad38fd92f8b36 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:18 +0000 3Date: Sun, 9 Feb 2014 16:10:18 +0000
4Subject: Various Debian-specific configuration changes 4Subject: Various Debian-specific configuration changes
@@ -34,10 +34,10 @@ Patch-Name: debian-config.patch
34 5 files changed, 51 insertions(+), 3 deletions(-) 34 5 files changed, 51 insertions(+), 3 deletions(-)
35 35
36diff --git a/readconf.c b/readconf.c 36diff --git a/readconf.c b/readconf.c
37index 32c4b42..5429fc2 100644 37index 0648867..29338b6 100644
38--- a/readconf.c 38--- a/readconf.c
39+++ b/readconf.c 39+++ b/readconf.c
40@@ -1640,7 +1640,7 @@ fill_default_options(Options * options) 40@@ -1681,7 +1681,7 @@ fill_default_options(Options * options)
41 if (options->forward_x11 == -1) 41 if (options->forward_x11 == -1)
42 options->forward_x11 = 0; 42 options->forward_x11 = 0;
43 if (options->forward_x11_trusted == -1) 43 if (options->forward_x11_trusted == -1)
@@ -71,7 +71,7 @@ index 228e5ab..c9386aa 100644
71+ GSSAPIAuthentication yes 71+ GSSAPIAuthentication yes
72+ GSSAPIDelegateCredentials no 72+ GSSAPIDelegateCredentials no
73diff --git a/ssh_config.5 b/ssh_config.5 73diff --git a/ssh_config.5 b/ssh_config.5
74index 1d500e9..22e6372 100644 74index a1005ba..da3c177 100644
75--- a/ssh_config.5 75--- a/ssh_config.5
76+++ b/ssh_config.5 76+++ b/ssh_config.5
77@@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more 77@@ -71,6 +71,22 @@ Since the first obtained value for each parameter is used, more
@@ -97,7 +97,7 @@ index 1d500e9..22e6372 100644
97 The configuration file has the following format: 97 The configuration file has the following format:
98 .Pp 98 .Pp
99 Empty lines and lines starting with 99 Empty lines and lines starting with
100@@ -654,7 +670,8 @@ token used for the session will be set to expire after 20 minutes. 100@@ -673,7 +689,8 @@ token used for the session will be set to expire after 20 minutes.
101 Remote clients will be refused access after this time. 101 Remote clients will be refused access after this time.
102 .Pp 102 .Pp
103 The default is 103 The default is
@@ -120,7 +120,7 @@ index d9b8594..4db32f5 100644
120 #StrictModes yes 120 #StrictModes yes
121 #MaxAuthTries 6 121 #MaxAuthTries 6
122diff --git a/sshd_config.5 b/sshd_config.5 122diff --git a/sshd_config.5 b/sshd_config.5
123index 908e0bb..90fd3f4 100644 123index 7396b23..7aa7b47 100644
124--- a/sshd_config.5 124--- a/sshd_config.5
125+++ b/sshd_config.5 125+++ b/sshd_config.5
126@@ -57,6 +57,31 @@ Arguments may optionally be enclosed in double quotes 126@@ -57,6 +57,31 @@ Arguments may optionally be enclosed in double quotes
diff --git a/debian/patches/dnssec-sshfp.patch b/debian/patches/dnssec-sshfp.patch
index bc89c50fc..0212ea841 100644
--- a/debian/patches/dnssec-sshfp.patch
+++ b/debian/patches/dnssec-sshfp.patch
@@ -1,4 +1,4 @@
1From 912129ba92bea401d8cdeadc7aa7084fbf7625a1 Mon Sep 17 00:00:00 2001 1From 4ac9937c1d9f1901ab0694114d76e59a138aae96 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:01 +0000 3Date: Sun, 9 Feb 2014 16:10:01 +0000
4Subject: Force use of DNSSEC even if "options edns0" isn't in resolv.conf 4Subject: Force use of DNSSEC even if "options edns0" isn't in resolv.conf
@@ -18,10 +18,10 @@ Patch-Name: dnssec-sshfp.patch
18 3 files changed, 21 insertions(+), 6 deletions(-) 18 3 files changed, 21 insertions(+), 6 deletions(-)
19 19
20diff --git a/dns.c b/dns.c 20diff --git a/dns.c b/dns.c
21index 630b97a..478c3d9 100644 21index c4d073c..e5872c1 100644
22--- a/dns.c 22--- a/dns.c
23+++ b/dns.c 23+++ b/dns.c
24@@ -196,6 +196,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, 24@@ -203,6 +203,7 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
25 { 25 {
26 u_int counter; 26 u_int counter;
27 int result; 27 int result;
@@ -29,7 +29,7 @@ index 630b97a..478c3d9 100644
29 struct rrsetinfo *fingerprints = NULL; 29 struct rrsetinfo *fingerprints = NULL;
30 30
31 u_int8_t hostkey_algorithm; 31 u_int8_t hostkey_algorithm;
32@@ -219,8 +220,19 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address, 32@@ -226,8 +227,19 @@ verify_host_key_dns(const char *hostname, struct sockaddr *address,
33 return -1; 33 return -1;
34 } 34 }
35 35
diff --git a/debian/patches/doc-hash-tab-completion.patch b/debian/patches/doc-hash-tab-completion.patch
index 16c40b05f..8e6cfa575 100644
--- a/debian/patches/doc-hash-tab-completion.patch
+++ b/debian/patches/doc-hash-tab-completion.patch
@@ -1,4 +1,4 @@
1From 1d108ef62050b4368e24e1efada16ec88c177fb8 Mon Sep 17 00:00:00 2001 1From 2fd0b3814e27d584efa6df92845a7354e7c2de6c Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:11 +0000 3Date: Sun, 9 Feb 2014 16:10:11 +0000
4Subject: Document that HashKnownHosts may break tab-completion 4Subject: Document that HashKnownHosts may break tab-completion
@@ -13,10 +13,10 @@ Patch-Name: doc-hash-tab-completion.patch
13 1 file changed, 3 insertions(+) 13 1 file changed, 3 insertions(+)
14 14
15diff --git a/ssh_config.5 b/ssh_config.5 15diff --git a/ssh_config.5 b/ssh_config.5
16index 4bf7cbb..1d500e9 100644 16index d68b45a..a1005ba 100644
17--- a/ssh_config.5 17--- a/ssh_config.5
18+++ b/ssh_config.5 18+++ b/ssh_config.5
19@@ -740,6 +740,9 @@ Note that existing names and addresses in known hosts files 19@@ -759,6 +759,9 @@ Note that existing names and addresses in known hosts files
20 will not be converted automatically, 20 will not be converted automatically,
21 but may be manually hashed using 21 but may be manually hashed using
22 .Xr ssh-keygen 1 . 22 .Xr ssh-keygen 1 .
diff --git a/debian/patches/doc-upstart.patch b/debian/patches/doc-upstart.patch
index da8fc7ed4..c1ce1bcae 100644
--- a/debian/patches/doc-upstart.patch
+++ b/debian/patches/doc-upstart.patch
@@ -1,4 +1,4 @@
1From 111de26347496af3f6ed04849fd29bc4bf1c2cea Mon Sep 17 00:00:00 2001 1From 252e76b3ad6e83a798e479a2beba5be7000ff85e Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@ubuntu.com> 2From: Colin Watson <cjwatson@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:10:12 +0000 3Date: Sun, 9 Feb 2014 16:10:12 +0000
4Subject: Refer to ssh's Upstart job as well as its init script 4Subject: Refer to ssh's Upstart job as well as its init script
@@ -12,10 +12,10 @@ Patch-Name: doc-upstart.patch
12 1 file changed, 4 insertions(+), 1 deletion(-) 12 1 file changed, 4 insertions(+), 1 deletion(-)
13 13
14diff --git a/sshd.8 b/sshd.8 14diff --git a/sshd.8 b/sshd.8
15index b016e90..cba168a 100644 15index 3538208..f8f9eac 100644
16--- a/sshd.8 16--- a/sshd.8
17+++ b/sshd.8 17+++ b/sshd.8
18@@ -70,7 +70,10 @@ over an insecure network. 18@@ -67,7 +67,10 @@ over an insecure network.
19 .Nm 19 .Nm
20 listens for connections from clients. 20 listens for connections from clients.
21 It is normally started at boot from 21 It is normally started at boot from
diff --git a/debian/patches/gnome-ssh-askpass2-icon.patch b/debian/patches/gnome-ssh-askpass2-icon.patch
index dab518f65..84fe03acc 100644
--- a/debian/patches/gnome-ssh-askpass2-icon.patch
+++ b/debian/patches/gnome-ssh-askpass2-icon.patch
@@ -1,4 +1,4 @@
1From b7df8fdb32f3d33b70ff8733cb0c39417e367534 Mon Sep 17 00:00:00 2001 1From 1195b028cb9f402633cfdcae6ec34bf63b4ab771 Mon Sep 17 00:00:00 2001
2From: Vincent Untz <vuntz@ubuntu.com> 2From: Vincent Untz <vuntz@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:10:16 +0000 3Date: Sun, 9 Feb 2014 16:10:16 +0000
4Subject: Give the ssh-askpass-gnome window a default icon 4Subject: Give the ssh-askpass-gnome window a default icon
diff --git a/debian/patches/gssapi.patch b/debian/patches/gssapi.patch
index d8439bf03..e8cbc1083 100644
--- a/debian/patches/gssapi.patch
+++ b/debian/patches/gssapi.patch
@@ -1,4 +1,4 @@
1From 9dfcd1a0e691c1cad34b168e27b3ed31ab6986cd Mon Sep 17 00:00:00 2001 1From 1c1b6fa17982eb622e2c4e8f4a279f2113f57413 Mon Sep 17 00:00:00 2001
2From: Simon Wilkinson <simon@sxw.org.uk> 2From: Simon Wilkinson <simon@sxw.org.uk>
3Date: Sun, 9 Feb 2014 16:09:48 +0000 3Date: Sun, 9 Feb 2014 16:09:48 +0000
4Subject: GSSAPI key exchange support 4Subject: GSSAPI key exchange support
@@ -17,7 +17,7 @@ have it merged into the main openssh package rather than having separate
17security history. 17security history.
18 18
19Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242 19Bug: https://bugzilla.mindrot.org/show_bug.cgi?id=1242
20Last-Updated: 2014-03-19 20Last-Updated: 2014-10-07
21 21
22Patch-Name: gssapi.patch 22Patch-Name: gssapi.patch
23--- 23---
@@ -36,9 +36,7 @@ Patch-Name: gssapi.patch
36 kex.c | 16 +++ 36 kex.c | 16 +++
37 kex.h | 14 +++ 37 kex.h | 14 +++
38 kexgssc.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++ 38 kexgssc.c | 332 +++++++++++++++++++++++++++++++++++++++++++++++++++++++
39 kexgsss.c | 289 ++++++++++++++++++++++++++++++++++++++++++++++++ 39 kexgsss.c | 290 ++++++++++++++++++++++++++++++++++++++++++++++++
40 key.c | 3 +-
41 key.h | 1 +
42 monitor.c | 108 +++++++++++++++++- 40 monitor.c | 108 +++++++++++++++++-
43 monitor.h | 3 + 41 monitor.h | 3 +
44 monitor_wrap.c | 47 +++++++- 42 monitor_wrap.c | 47 +++++++-
@@ -54,7 +52,9 @@ Patch-Name: gssapi.patch
54 sshd.c | 110 ++++++++++++++++++ 52 sshd.c | 110 ++++++++++++++++++
55 sshd_config | 2 + 53 sshd_config | 2 +
56 sshd_config.5 | 28 +++++ 54 sshd_config.5 | 28 +++++
57 33 files changed, 2051 insertions(+), 59 deletions(-) 55 sshkey.c | 3 +-
56 sshkey.h | 1 +
57 33 files changed, 2052 insertions(+), 59 deletions(-)
58 create mode 100644 ChangeLog.gssapi 58 create mode 100644 ChangeLog.gssapi
59 create mode 100644 kexgssc.c 59 create mode 100644 kexgssc.c
60 create mode 100644 kexgsss.c 60 create mode 100644 kexgsss.c
@@ -179,10 +179,10 @@ index 0000000..f117a33
179+ (from jbasney AT ncsa.uiuc.edu) 179+ (from jbasney AT ncsa.uiuc.edu)
180+ <gssapi-with-mic support is Bugzilla #1008> 180+ <gssapi-with-mic support is Bugzilla #1008>
181diff --git a/Makefile.in b/Makefile.in 181diff --git a/Makefile.in b/Makefile.in
182index 28a8ec4..ee1d2c3 100644 182index 06be3d5..086d8dd 100644
183--- a/Makefile.in 183--- a/Makefile.in
184+++ b/Makefile.in 184+++ b/Makefile.in
185@@ -72,6 +72,7 @@ LIBSSH_OBJS=authfd.o authfile.o bufaux.o bufbn.o buffer.o \ 185@@ -82,6 +82,7 @@ LIBSSH_OBJS=${LIBOPENSSH_OBJS} \
186 atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \ 186 atomicio.o key.o dispatch.o kex.o mac.o uidswap.o uuencode.o misc.o \
187 monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \ 187 monitor_fdpass.o rijndael.o ssh-dss.o ssh-ecdsa.o ssh-rsa.o dh.o \
188 kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \ 188 kexdh.o kexgex.o kexdhc.o kexgexc.o bufec.o kexecdh.o kexecdhc.o \
@@ -190,7 +190,7 @@ index 28a8ec4..ee1d2c3 100644
190 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \ 190 msg.o progressmeter.o dns.o entropy.o gss-genr.o umac.o umac128.o \
191 ssh-pkcs11.o krl.o smult_curve25519_ref.o \ 191 ssh-pkcs11.o krl.o smult_curve25519_ref.o \
192 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \ 192 kexc25519.o kexc25519c.o poly1305.o chacha.o cipher-chachapoly.o \
193@@ -91,7 +92,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \ 193@@ -101,7 +102,7 @@ SSHDOBJS=sshd.o auth-rhosts.o auth-passwd.o auth-rsa.o auth-rh-rsa.o \
194 auth2-none.o auth2-passwd.o auth2-pubkey.o \ 194 auth2-none.o auth2-passwd.o auth2-pubkey.o \
195 monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \ 195 monitor_mm.o monitor.o monitor_wrap.o kexdhs.o kexgexs.o kexecdhs.o \
196 kexc25519s.o auth-krb5.o \ 196 kexc25519s.o auth-krb5.o \
@@ -200,10 +200,10 @@ index 28a8ec4..ee1d2c3 100644
200 sftp-server.o sftp-common.o \ 200 sftp-server.o sftp-common.o \
201 roaming_common.o roaming_serv.o \ 201 roaming_common.o roaming_serv.o \
202diff --git a/auth-krb5.c b/auth-krb5.c 202diff --git a/auth-krb5.c b/auth-krb5.c
203index 6c62bdf..69a1a53 100644 203index 0089b18..ec47869 100644
204--- a/auth-krb5.c 204--- a/auth-krb5.c
205+++ b/auth-krb5.c 205+++ b/auth-krb5.c
206@@ -182,8 +182,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password) 206@@ -183,8 +183,13 @@ auth_krb5_password(Authctxt *authctxt, const char *password)
207 207
208 len = strlen(authctxt->krb5_ticket_file) + 6; 208 len = strlen(authctxt->krb5_ticket_file) + 6;
209 authctxt->krb5_ccname = xmalloc(len); 209 authctxt->krb5_ccname = xmalloc(len);
@@ -217,7 +217,7 @@ index 6c62bdf..69a1a53 100644
217 217
218 #ifdef USE_PAM 218 #ifdef USE_PAM
219 if (options.use_pam) 219 if (options.use_pam)
220@@ -240,15 +245,22 @@ krb5_cleanup_proc(Authctxt *authctxt) 220@@ -241,15 +246,22 @@ krb5_cleanup_proc(Authctxt *authctxt)
221 #ifndef HEIMDAL 221 #ifndef HEIMDAL
222 krb5_error_code 222 krb5_error_code
223 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { 223 ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
@@ -242,7 +242,7 @@ index 6c62bdf..69a1a53 100644
242 old_umask = umask(0177); 242 old_umask = umask(0177);
243 tmpfd = mkstemp(ccname + strlen("FILE:")); 243 tmpfd = mkstemp(ccname + strlen("FILE:"));
244 oerrno = errno; 244 oerrno = errno;
245@@ -265,6 +277,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) { 245@@ -266,6 +278,7 @@ ssh_krb5_cc_gen(krb5_context ctx, krb5_ccache *ccache) {
246 return oerrno; 246 return oerrno;
247 } 247 }
248 close(tmpfd); 248 close(tmpfd);
@@ -251,7 +251,7 @@ index 6c62bdf..69a1a53 100644
251 return (krb5_cc_resolve(ctx, ccname, ccache)); 251 return (krb5_cc_resolve(ctx, ccname, ccache));
252 } 252 }
253diff --git a/auth2-gss.c b/auth2-gss.c 253diff --git a/auth2-gss.c b/auth2-gss.c
254index c28a705..3ff2d72 100644 254index 447f896..284f364 100644
255--- a/auth2-gss.c 255--- a/auth2-gss.c
256+++ b/auth2-gss.c 256+++ b/auth2-gss.c
257@@ -1,7 +1,7 @@ 257@@ -1,7 +1,7 @@
@@ -263,7 +263,7 @@ index c28a705..3ff2d72 100644
263 * 263 *
264 * Redistribution and use in source and binary forms, with or without 264 * Redistribution and use in source and binary forms, with or without
265 * modification, are permitted provided that the following conditions 265 * modification, are permitted provided that the following conditions
266@@ -52,6 +52,40 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt); 266@@ -53,6 +53,40 @@ static void input_gssapi_mic(int type, u_int32_t plen, void *ctxt);
267 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt); 267 static void input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt);
268 static void input_gssapi_errtok(int, u_int32_t, void *); 268 static void input_gssapi_errtok(int, u_int32_t, void *);
269 269
@@ -304,7 +304,7 @@ index c28a705..3ff2d72 100644
304 /* 304 /*
305 * We only support those mechanisms that we know about (ie ones that we know 305 * We only support those mechanisms that we know about (ie ones that we know
306 * how to check local user kuserok and the like) 306 * how to check local user kuserok and the like)
307@@ -235,7 +269,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt) 307@@ -236,7 +270,8 @@ input_gssapi_exchange_complete(int type, u_int32_t plen, void *ctxt)
308 308
309 packet_check_eom(); 309 packet_check_eom();
310 310
@@ -314,7 +314,7 @@ index c28a705..3ff2d72 100644
314 314
315 authctxt->postponed = 0; 315 authctxt->postponed = 0;
316 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL); 316 dispatch_set(SSH2_MSG_USERAUTH_GSSAPI_TOKEN, NULL);
317@@ -270,7 +305,8 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 317@@ -271,7 +306,8 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
318 gssbuf.length = buffer_len(&b); 318 gssbuf.length = buffer_len(&b);
319 319
320 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic)))) 320 if (!GSS_ERROR(PRIVSEP(ssh_gssapi_checkmic(gssctxt, &gssbuf, &mic))))
@@ -324,7 +324,7 @@ index c28a705..3ff2d72 100644
324 else 324 else
325 logit("GSSAPI MIC check failed"); 325 logit("GSSAPI MIC check failed");
326 326
327@@ -285,6 +321,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt) 327@@ -286,6 +322,12 @@ input_gssapi_mic(int type, u_int32_t plen, void *ctxt)
328 userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL); 328 userauth_finish(authctxt, authenticated, "gssapi-with-mic", NULL);
329 } 329 }
330 330
@@ -338,10 +338,10 @@ index c28a705..3ff2d72 100644
338 "gssapi-with-mic", 338 "gssapi-with-mic",
339 userauth_gssapi, 339 userauth_gssapi,
340diff --git a/auth2.c b/auth2.c 340diff --git a/auth2.c b/auth2.c
341index a5490c0..fbe3e1b 100644 341index d9b440a..2f0d565 100644
342--- a/auth2.c 342--- a/auth2.c
343+++ b/auth2.c 343+++ b/auth2.c
344@@ -69,6 +69,7 @@ extern Authmethod method_passwd; 344@@ -70,6 +70,7 @@ extern Authmethod method_passwd;
345 extern Authmethod method_kbdint; 345 extern Authmethod method_kbdint;
346 extern Authmethod method_hostbased; 346 extern Authmethod method_hostbased;
347 #ifdef GSSAPI 347 #ifdef GSSAPI
@@ -349,7 +349,7 @@ index a5490c0..fbe3e1b 100644
349 extern Authmethod method_gssapi; 349 extern Authmethod method_gssapi;
350 #endif 350 #endif
351 351
352@@ -76,6 +77,7 @@ Authmethod *authmethods[] = { 352@@ -77,6 +78,7 @@ Authmethod *authmethods[] = {
353 &method_none, 353 &method_none,
354 &method_pubkey, 354 &method_pubkey,
355 #ifdef GSSAPI 355 #ifdef GSSAPI
@@ -358,7 +358,7 @@ index a5490c0..fbe3e1b 100644
358 #endif 358 #endif
359 &method_passwd, 359 &method_passwd,
360diff --git a/clientloop.c b/clientloop.c 360diff --git a/clientloop.c b/clientloop.c
361index 59ad3a2..6d8cd7d 100644 361index 397c965..f9175e3 100644
362--- a/clientloop.c 362--- a/clientloop.c
363+++ b/clientloop.c 363+++ b/clientloop.c
364@@ -111,6 +111,10 @@ 364@@ -111,6 +111,10 @@
@@ -372,7 +372,7 @@ index 59ad3a2..6d8cd7d 100644
372 /* import options */ 372 /* import options */
373 extern Options options; 373 extern Options options;
374 374
375@@ -1608,6 +1612,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) 375@@ -1596,6 +1600,15 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
376 /* Do channel operations unless rekeying in progress. */ 376 /* Do channel operations unless rekeying in progress. */
377 if (!rekeying) { 377 if (!rekeying) {
378 channel_after_select(readset, writeset); 378 channel_after_select(readset, writeset);
@@ -389,7 +389,7 @@ index 59ad3a2..6d8cd7d 100644
389 debug("need rekeying"); 389 debug("need rekeying");
390 xxx_kex->done = 0; 390 xxx_kex->done = 0;
391diff --git a/config.h.in b/config.h.in 391diff --git a/config.h.in b/config.h.in
392index 0401ad1..6bc422c 100644 392index 16d6206..a9a8b7a 100644
393--- a/config.h.in 393--- a/config.h.in
394+++ b/config.h.in 394+++ b/config.h.in
395@@ -1622,6 +1622,9 @@ 395@@ -1622,6 +1622,9 @@
@@ -413,10 +413,10 @@ index 0401ad1..6bc422c 100644
413 #undef USE_SOLARIS_PROCESS_CONTRACTS 413 #undef USE_SOLARIS_PROCESS_CONTRACTS
414 414
415diff --git a/configure b/configure 415diff --git a/configure b/configure
416index d690393..b6b5b6d 100755 416index 6815388..ea5f200 100755
417--- a/configure 417--- a/configure
418+++ b/configure 418+++ b/configure
419@@ -7170,6 +7170,63 @@ $as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h 419@@ -7168,6 +7168,63 @@ $as_echo "#define SSH_TUN_COMPAT_AF 1" >>confdefs.h
420 420
421 $as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h 421 $as_echo "#define SSH_TUN_PREPEND_AF 1" >>confdefs.h
422 422
@@ -481,7 +481,7 @@ index d690393..b6b5b6d 100755
481 ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default" 481 ac_fn_c_check_decl "$LINENO" "AU_IPv4" "ac_cv_have_decl_AU_IPv4" "$ac_includes_default"
482 if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then : 482 if test "x$ac_cv_have_decl_AU_IPv4" = xyes; then :
483diff --git a/configure.ac b/configure.ac 483diff --git a/configure.ac b/configure.ac
484index 7c6ce08..d235fb0 100644 484index 67c4486..90e81e1 100644
485--- a/configure.ac 485--- a/configure.ac
486+++ b/configure.ac 486+++ b/configure.ac
487@@ -584,6 +584,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16)) 487@@ -584,6 +584,30 @@ main() { if (NSVersionOfRunTimeLibrary("System") >= (60 << 16))
@@ -866,7 +866,7 @@ index b39281b..1e569ad 100644
866+ 866+
867 #endif /* GSSAPI */ 867 #endif /* GSSAPI */
868diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c 868diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
869index 759fa10..e678a27 100644 869index 795992d..fd8b371 100644
870--- a/gss-serv-krb5.c 870--- a/gss-serv-krb5.c
871+++ b/gss-serv-krb5.c 871+++ b/gss-serv-krb5.c
872@@ -1,7 +1,7 @@ 872@@ -1,7 +1,7 @@
@@ -878,7 +878,7 @@ index 759fa10..e678a27 100644
878 * 878 *
879 * Redistribution and use in source and binary forms, with or without 879 * Redistribution and use in source and binary forms, with or without
880 * modification, are permitted provided that the following conditions 880 * modification, are permitted provided that the following conditions
881@@ -120,8 +120,8 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 881@@ -121,8 +121,8 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
882 krb5_error_code problem; 882 krb5_error_code problem;
883 krb5_principal princ; 883 krb5_principal princ;
884 OM_uint32 maj_status, min_status; 884 OM_uint32 maj_status, min_status;
@@ -888,7 +888,7 @@ index 759fa10..e678a27 100644
888 888
889 if (client->creds == NULL) { 889 if (client->creds == NULL) {
890 debug("No credentials stored"); 890 debug("No credentials stored");
891@@ -180,11 +180,16 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 891@@ -181,11 +181,16 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
892 return; 892 return;
893 } 893 }
894 894
@@ -909,7 +909,7 @@ index 759fa10..e678a27 100644
909 909
910 #ifdef USE_PAM 910 #ifdef USE_PAM
911 if (options.use_pam) 911 if (options.use_pam)
912@@ -196,6 +201,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client) 912@@ -197,6 +202,71 @@ ssh_gssapi_krb5_storecreds(ssh_gssapi_client *client)
913 return; 913 return;
914 } 914 }
915 915
@@ -981,7 +981,7 @@ index 759fa10..e678a27 100644
981 ssh_gssapi_mech gssapi_kerberos_mech = { 981 ssh_gssapi_mech gssapi_kerberos_mech = {
982 "toWM5Slw5Ew8Mqkay+al2g==", 982 "toWM5Slw5Ew8Mqkay+al2g==",
983 "Kerberos", 983 "Kerberos",
984@@ -203,7 +273,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = { 984@@ -204,7 +274,8 @@ ssh_gssapi_mech gssapi_kerberos_mech = {
985 NULL, 985 NULL,
986 &ssh_gssapi_krb5_userok, 986 &ssh_gssapi_krb5_userok,
987 NULL, 987 NULL,
@@ -992,11 +992,11 @@ index 759fa10..e678a27 100644
992 992
993 #endif /* KRB5 */ 993 #endif /* KRB5 */
994diff --git a/gss-serv.c b/gss-serv.c 994diff --git a/gss-serv.c b/gss-serv.c
995index e61b37b..c33463b 100644 995index 5c59924..50fa438 100644
996--- a/gss-serv.c 996--- a/gss-serv.c
997+++ b/gss-serv.c 997+++ b/gss-serv.c
998@@ -1,7 +1,7 @@ 998@@ -1,7 +1,7 @@
999 /* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ 999 /* $OpenBSD: gss-serv.c,v 1.27 2014/07/03 03:34:09 djm Exp $ */
1000 1000
1001 /* 1001 /*
1002- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved. 1002- * Copyright (c) 2001-2003 Simon Wilkinson. All rights reserved.
@@ -1029,7 +1029,7 @@ index e61b37b..c33463b 100644
1029 #ifdef KRB5 1029 #ifdef KRB5
1030 extern ssh_gssapi_mech gssapi_kerberos_mech; 1030 extern ssh_gssapi_mech gssapi_kerberos_mech;
1031@@ -100,25 +106,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx) 1031@@ -100,25 +106,32 @@ ssh_gssapi_acquire_cred(Gssctxt *ctx)
1032 char lname[MAXHOSTNAMELEN]; 1032 char lname[NI_MAXHOST];
1033 gss_OID_set oidset; 1033 gss_OID_set oidset;
1034 1034
1035- gss_create_empty_oid_set(&status, &oidset); 1035- gss_create_empty_oid_set(&status, &oidset);
@@ -1038,11 +1038,11 @@ index e61b37b..c33463b 100644
1038+ gss_create_empty_oid_set(&status, &oidset); 1038+ gss_create_empty_oid_set(&status, &oidset);
1039+ gss_add_oid_set_member(&status, ctx->oid, &oidset); 1039+ gss_add_oid_set_member(&status, ctx->oid, &oidset);
1040 1040
1041- if (gethostname(lname, MAXHOSTNAMELEN)) { 1041- if (gethostname(lname, sizeof(lname))) {
1042- gss_release_oid_set(&status, &oidset); 1042- gss_release_oid_set(&status, &oidset);
1043- return (-1); 1043- return (-1);
1044- } 1044- }
1045+ if (gethostname(lname, MAXHOSTNAMELEN)) { 1045+ if (gethostname(lname, sizeof(lname))) {
1046+ gss_release_oid_set(&status, &oidset); 1046+ gss_release_oid_set(&status, &oidset);
1047+ return (-1); 1047+ return (-1);
1048+ } 1048+ }
@@ -1310,10 +1310,10 @@ index e61b37b..c33463b 100644
1310 1310
1311 #endif 1311 #endif
1312diff --git a/kex.c b/kex.c 1312diff --git a/kex.c b/kex.c
1313index 74e2b86..d114ee3 100644 1313index a173e70..891852b 100644
1314--- a/kex.c 1314--- a/kex.c
1315+++ b/kex.c 1315+++ b/kex.c
1316@@ -51,6 +51,10 @@ 1316@@ -53,6 +53,10 @@
1317 #include "roaming.h" 1317 #include "roaming.h"
1318 #include "digest.h" 1318 #include "digest.h"
1319 1319
@@ -1324,8 +1324,8 @@ index 74e2b86..d114ee3 100644
1324 #if OPENSSL_VERSION_NUMBER >= 0x00907000L 1324 #if OPENSSL_VERSION_NUMBER >= 0x00907000L
1325 # if defined(HAVE_EVP_SHA256) 1325 # if defined(HAVE_EVP_SHA256)
1326 # define evp_ssh_sha256 EVP_sha256 1326 # define evp_ssh_sha256 EVP_sha256
1327@@ -92,6 +96,14 @@ static const struct kexalg kexalgs[] = { 1327@@ -96,6 +100,14 @@ static const struct kexalg kexalgs[] = {
1328 #endif 1328 #endif /* HAVE_EVP_SHA256 */
1329 { NULL, -1, -1, -1}, 1329 { NULL, -1, -1, -1},
1330 }; 1330 };
1331+static const struct kexalg kexalg_prefixes[] = { 1331+static const struct kexalg kexalg_prefixes[] = {
@@ -1339,7 +1339,7 @@ index 74e2b86..d114ee3 100644
1339 1339
1340 char * 1340 char *
1341 kex_alg_list(char sep) 1341 kex_alg_list(char sep)
1342@@ -120,6 +132,10 @@ kex_alg_by_name(const char *name) 1342@@ -124,6 +136,10 @@ kex_alg_by_name(const char *name)
1343 if (strcmp(k->name, name) == 0) 1343 if (strcmp(k->name, name) == 0)
1344 return k; 1344 return k;
1345 } 1345 }
@@ -1351,7 +1351,7 @@ index 74e2b86..d114ee3 100644
1351 } 1351 }
1352 1352
1353diff --git a/kex.h b/kex.h 1353diff --git a/kex.h b/kex.h
1354index c85680e..ea698c4 100644 1354index 4c40ec8..c179a4d 100644
1355--- a/kex.h 1355--- a/kex.h
1356+++ b/kex.h 1356+++ b/kex.h
1357@@ -76,6 +76,9 @@ enum kex_exchange { 1357@@ -76,6 +76,9 @@ enum kex_exchange {
@@ -1729,10 +1729,10 @@ index 0000000..92a31c5
1729+#endif /* GSSAPI */ 1729+#endif /* GSSAPI */
1730diff --git a/kexgsss.c b/kexgsss.c 1730diff --git a/kexgsss.c b/kexgsss.c
1731new file mode 100644 1731new file mode 100644
1732index 0000000..8095259 1732index 0000000..6a0ece8
1733--- /dev/null 1733--- /dev/null
1734+++ b/kexgsss.c 1734+++ b/kexgsss.c
1735@@ -0,0 +1,289 @@ 1735@@ -0,0 +1,290 @@
1736+/* 1736+/*
1737+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 1737+ * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
1738+ * 1738+ *
@@ -1777,6 +1777,7 @@ index 0000000..8095259
1777+#include "dh.h" 1777+#include "dh.h"
1778+#include "ssh-gss.h" 1778+#include "ssh-gss.h"
1779+#include "monitor_wrap.h" 1779+#include "monitor_wrap.h"
1780+#include "misc.h"
1780+#include "servconf.h" 1781+#include "servconf.h"
1781+ 1782+
1782+extern ServerOptions options; 1783+extern ServerOptions options;
@@ -2022,44 +2023,11 @@ index 0000000..8095259
2022+ ssh_gssapi_rekey_creds(); 2023+ ssh_gssapi_rekey_creds();
2023+} 2024+}
2024+#endif /* GSSAPI */ 2025+#endif /* GSSAPI */
2025diff --git a/key.c b/key.c
2026index 168e1b7..3d640e7 100644
2027--- a/key.c
2028+++ b/key.c
2029@@ -985,6 +985,7 @@ static const struct keytype keytypes[] = {
2030 KEY_DSA_CERT_V00, 0, 1 },
2031 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
2032 KEY_ED25519_CERT, 0, 1 },
2033+ { "null", "null", KEY_NULL, 0, 0 },
2034 { NULL, NULL, -1, -1, 0 }
2035 };
2036
2037@@ -1063,7 +1064,7 @@ key_alg_list(int certs_only, int plain_only)
2038 const struct keytype *kt;
2039
2040 for (kt = keytypes; kt->type != -1; kt++) {
2041- if (kt->name == NULL)
2042+ if (kt->name == NULL || kt->type == KEY_NULL)
2043 continue;
2044 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
2045 continue;
2046diff --git a/key.h b/key.h
2047index d8ad13d..c8aeba2 100644
2048--- a/key.h
2049+++ b/key.h
2050@@ -46,6 +46,7 @@ enum types {
2051 KEY_ED25519_CERT,
2052 KEY_RSA_CERT_V00,
2053 KEY_DSA_CERT_V00,
2054+ KEY_NULL,
2055 KEY_UNSPEC
2056 };
2057 enum fp_type {
2058diff --git a/monitor.c b/monitor.c 2026diff --git a/monitor.c b/monitor.c
2059index 531c4f9..2918814 100644 2027index dbe29f1..b0896ef 100644
2060--- a/monitor.c 2028--- a/monitor.c
2061+++ b/monitor.c 2029+++ b/monitor.c
2062@@ -175,6 +175,8 @@ int mm_answer_gss_setup_ctx(int, Buffer *); 2030@@ -178,6 +178,8 @@ int mm_answer_gss_setup_ctx(int, Buffer *);
2063 int mm_answer_gss_accept_ctx(int, Buffer *); 2031 int mm_answer_gss_accept_ctx(int, Buffer *);
2064 int mm_answer_gss_userok(int, Buffer *); 2032 int mm_answer_gss_userok(int, Buffer *);
2065 int mm_answer_gss_checkmic(int, Buffer *); 2033 int mm_answer_gss_checkmic(int, Buffer *);
@@ -2068,7 +2036,7 @@ index 531c4f9..2918814 100644
2068 #endif 2036 #endif
2069 2037
2070 #ifdef SSH_AUDIT_EVENTS 2038 #ifdef SSH_AUDIT_EVENTS
2071@@ -247,11 +249,18 @@ struct mon_table mon_dispatch_proto20[] = { 2039@@ -255,11 +257,18 @@ struct mon_table mon_dispatch_proto20[] = {
2072 {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx}, 2040 {MONITOR_REQ_GSSSTEP, MON_ISAUTH, mm_answer_gss_accept_ctx},
2073 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok}, 2041 {MONITOR_REQ_GSSUSEROK, MON_AUTH, mm_answer_gss_userok},
2074 {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic}, 2042 {MONITOR_REQ_GSSCHECKMIC, MON_ISAUTH, mm_answer_gss_checkmic},
@@ -2084,10 +2052,10 @@ index 531c4f9..2918814 100644
2084+ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, 2052+ {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
2085+ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, 2053+ {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
2086+#endif 2054+#endif
2055 #ifdef WITH_OPENSSL
2087 {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 2056 {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
2088 {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 2057 #endif
2089 {MONITOR_REQ_PTY, 0, mm_answer_pty}, 2058@@ -374,6 +383,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
2090@@ -360,6 +369,10 @@ monitor_child_preauth(Authctxt *_authctxt, struct monitor *pmonitor)
2091 /* Permit requests for moduli and signatures */ 2059 /* Permit requests for moduli and signatures */
2092 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 2060 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
2093 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 2061 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
@@ -2098,7 +2066,7 @@ index 531c4f9..2918814 100644
2098 } else { 2066 } else {
2099 mon_dispatch = mon_dispatch_proto15; 2067 mon_dispatch = mon_dispatch_proto15;
2100 2068
2101@@ -465,6 +478,10 @@ monitor_child_postauth(struct monitor *pmonitor) 2069@@ -482,6 +495,10 @@ monitor_child_postauth(struct monitor *pmonitor)
2102 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1); 2070 monitor_permit(mon_dispatch, MONITOR_REQ_MODULI, 1);
2103 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1); 2071 monitor_permit(mon_dispatch, MONITOR_REQ_SIGN, 1);
2104 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 2072 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
@@ -2109,9 +2077,9 @@ index 531c4f9..2918814 100644
2109 } else { 2077 } else {
2110 mon_dispatch = mon_dispatch_postauth15; 2078 mon_dispatch = mon_dispatch_postauth15;
2111 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1); 2079 monitor_permit(mon_dispatch, MONITOR_REQ_TERM, 1);
2112@@ -1834,6 +1851,13 @@ mm_get_kex(Buffer *m) 2080@@ -1861,6 +1878,13 @@ mm_get_kex(Buffer *m)
2113 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
2114 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 2081 kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
2082 #endif
2115 kex->kex[KEX_C25519_SHA256] = kexc25519_server; 2083 kex->kex[KEX_C25519_SHA256] = kexc25519_server;
2116+#ifdef GSSAPI 2084+#ifdef GSSAPI
2117+ if (options.gss_keyex) { 2085+ if (options.gss_keyex) {
@@ -2123,7 +2091,7 @@ index 531c4f9..2918814 100644
2123 kex->server = 1; 2091 kex->server = 1;
2124 kex->hostkey_type = buffer_get_int(m); 2092 kex->hostkey_type = buffer_get_int(m);
2125 kex->kex_type = buffer_get_int(m); 2093 kex->kex_type = buffer_get_int(m);
2126@@ -2041,6 +2065,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m) 2094@@ -2068,6 +2092,9 @@ mm_answer_gss_setup_ctx(int sock, Buffer *m)
2127 OM_uint32 major; 2095 OM_uint32 major;
2128 u_int len; 2096 u_int len;
2129 2097
@@ -2133,7 +2101,7 @@ index 531c4f9..2918814 100644
2133 goid.elements = buffer_get_string(m, &len); 2101 goid.elements = buffer_get_string(m, &len);
2134 goid.length = len; 2102 goid.length = len;
2135 2103
2136@@ -2068,6 +2095,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) 2104@@ -2095,6 +2122,9 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
2137 OM_uint32 flags = 0; /* GSI needs this */ 2105 OM_uint32 flags = 0; /* GSI needs this */
2138 u_int len; 2106 u_int len;
2139 2107
@@ -2143,7 +2111,7 @@ index 531c4f9..2918814 100644
2143 in.value = buffer_get_string(m, &len); 2111 in.value = buffer_get_string(m, &len);
2144 in.length = len; 2112 in.length = len;
2145 major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags); 2113 major = ssh_gssapi_accept_ctx(gsscontext, &in, &out, &flags);
2146@@ -2085,6 +2115,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m) 2114@@ -2112,6 +2142,7 @@ mm_answer_gss_accept_ctx(int sock, Buffer *m)
2147 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0); 2115 monitor_permit(mon_dispatch, MONITOR_REQ_GSSSTEP, 0);
2148 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1); 2116 monitor_permit(mon_dispatch, MONITOR_REQ_GSSUSEROK, 1);
2149 monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1); 2117 monitor_permit(mon_dispatch, MONITOR_REQ_GSSCHECKMIC, 1);
@@ -2151,7 +2119,7 @@ index 531c4f9..2918814 100644
2151 } 2119 }
2152 return (0); 2120 return (0);
2153 } 2121 }
2154@@ -2096,6 +2127,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m) 2122@@ -2123,6 +2154,9 @@ mm_answer_gss_checkmic(int sock, Buffer *m)
2155 OM_uint32 ret; 2123 OM_uint32 ret;
2156 u_int len; 2124 u_int len;
2157 2125
@@ -2161,7 +2129,7 @@ index 531c4f9..2918814 100644
2161 gssbuf.value = buffer_get_string(m, &len); 2129 gssbuf.value = buffer_get_string(m, &len);
2162 gssbuf.length = len; 2130 gssbuf.length = len;
2163 mic.value = buffer_get_string(m, &len); 2131 mic.value = buffer_get_string(m, &len);
2164@@ -2122,7 +2156,11 @@ mm_answer_gss_userok(int sock, Buffer *m) 2132@@ -2149,7 +2183,11 @@ mm_answer_gss_userok(int sock, Buffer *m)
2165 { 2133 {
2166 int authenticated; 2134 int authenticated;
2167 2135
@@ -2174,7 +2142,7 @@ index 531c4f9..2918814 100644
2174 2142
2175 buffer_clear(m); 2143 buffer_clear(m);
2176 buffer_put_int(m, authenticated); 2144 buffer_put_int(m, authenticated);
2177@@ -2135,5 +2173,73 @@ mm_answer_gss_userok(int sock, Buffer *m) 2145@@ -2162,5 +2200,73 @@ mm_answer_gss_userok(int sock, Buffer *m)
2178 /* Monitor loop will terminate if authenticated */ 2146 /* Monitor loop will terminate if authenticated */
2179 return (authenticated); 2147 return (authenticated);
2180 } 2148 }
@@ -2263,10 +2231,10 @@ index 5bc41b5..7f32b0c 100644
2263 2231
2264 struct mm_master; 2232 struct mm_master;
2265diff --git a/monitor_wrap.c b/monitor_wrap.c 2233diff --git a/monitor_wrap.c b/monitor_wrap.c
2266index 1a47e41..60b987d 100644 2234index 45dc169..e476f0d 100644
2267--- a/monitor_wrap.c 2235--- a/monitor_wrap.c
2268+++ b/monitor_wrap.c 2236+++ b/monitor_wrap.c
2269@@ -1271,7 +1271,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic) 2237@@ -1281,7 +1281,7 @@ mm_ssh_gssapi_checkmic(Gssctxt *ctx, gss_buffer_t gssbuf, gss_buffer_t gssmic)
2270 } 2238 }
2271 2239
2272 int 2240 int
@@ -2275,7 +2243,7 @@ index 1a47e41..60b987d 100644
2275 { 2243 {
2276 Buffer m; 2244 Buffer m;
2277 int authenticated = 0; 2245 int authenticated = 0;
2278@@ -1288,5 +1288,50 @@ mm_ssh_gssapi_userok(char *user) 2246@@ -1298,5 +1298,50 @@ mm_ssh_gssapi_userok(char *user)
2279 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not "); 2247 debug3("%s: user %sauthenticated",__func__, authenticated ? "" : "not ");
2280 return (authenticated); 2248 return (authenticated);
2281 } 2249 }
@@ -2343,10 +2311,10 @@ index 18c2501..a4e9d24 100644
2343 2311
2344 #ifdef USE_PAM 2312 #ifdef USE_PAM
2345diff --git a/readconf.c b/readconf.c 2313diff --git a/readconf.c b/readconf.c
2346index dc884c9..7613ff2 100644 2314index 7948ce1..9127e93 100644
2347--- a/readconf.c 2315--- a/readconf.c
2348+++ b/readconf.c 2316+++ b/readconf.c
2349@@ -141,6 +141,8 @@ typedef enum { 2317@@ -142,6 +142,8 @@ typedef enum {
2350 oClearAllForwardings, oNoHostAuthenticationForLocalhost, 2318 oClearAllForwardings, oNoHostAuthenticationForLocalhost,
2351 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout, 2319 oEnableSSHKeysign, oRekeyLimit, oVerifyHostKeyDNS, oConnectTimeout,
2352 oAddressFamily, oGssAuthentication, oGssDelegateCreds, 2320 oAddressFamily, oGssAuthentication, oGssDelegateCreds,
@@ -2355,7 +2323,7 @@ index dc884c9..7613ff2 100644
2355 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly, 2323 oServerAliveInterval, oServerAliveCountMax, oIdentitiesOnly,
2356 oSendEnv, oControlPath, oControlMaster, oControlPersist, 2324 oSendEnv, oControlPath, oControlMaster, oControlPersist,
2357 oHashKnownHosts, 2325 oHashKnownHosts,
2358@@ -183,10 +185,19 @@ static struct { 2326@@ -185,10 +187,19 @@ static struct {
2359 { "afstokenpassing", oUnsupported }, 2327 { "afstokenpassing", oUnsupported },
2360 #if defined(GSSAPI) 2328 #if defined(GSSAPI)
2361 { "gssapiauthentication", oGssAuthentication }, 2329 { "gssapiauthentication", oGssAuthentication },
@@ -2375,7 +2343,7 @@ index dc884c9..7613ff2 100644
2375 #endif 2343 #endif
2376 { "fallbacktorsh", oDeprecated }, 2344 { "fallbacktorsh", oDeprecated },
2377 { "usersh", oDeprecated }, 2345 { "usersh", oDeprecated },
2378@@ -841,10 +852,30 @@ parse_time: 2346@@ -865,10 +876,30 @@ parse_time:
2379 intptr = &options->gss_authentication; 2347 intptr = &options->gss_authentication;
2380 goto parse_flag; 2348 goto parse_flag;
2381 2349
@@ -2406,7 +2374,7 @@ index dc884c9..7613ff2 100644
2406 case oBatchMode: 2374 case oBatchMode:
2407 intptr = &options->batch_mode; 2375 intptr = &options->batch_mode;
2408 goto parse_flag; 2376 goto parse_flag;
2409@@ -1497,7 +1528,12 @@ initialize_options(Options * options) 2377@@ -1538,7 +1569,12 @@ initialize_options(Options * options)
2410 options->pubkey_authentication = -1; 2378 options->pubkey_authentication = -1;
2411 options->challenge_response_authentication = -1; 2379 options->challenge_response_authentication = -1;
2412 options->gss_authentication = -1; 2380 options->gss_authentication = -1;
@@ -2419,7 +2387,7 @@ index dc884c9..7613ff2 100644
2419 options->password_authentication = -1; 2387 options->password_authentication = -1;
2420 options->kbd_interactive_authentication = -1; 2388 options->kbd_interactive_authentication = -1;
2421 options->kbd_interactive_devices = NULL; 2389 options->kbd_interactive_devices = NULL;
2422@@ -1616,8 +1652,14 @@ fill_default_options(Options * options) 2390@@ -1661,8 +1697,14 @@ fill_default_options(Options * options)
2423 options->challenge_response_authentication = 1; 2391 options->challenge_response_authentication = 1;
2424 if (options->gss_authentication == -1) 2392 if (options->gss_authentication == -1)
2425 options->gss_authentication = 0; 2393 options->gss_authentication = 0;
@@ -2435,10 +2403,10 @@ index dc884c9..7613ff2 100644
2435 options->password_authentication = 1; 2403 options->password_authentication = 1;
2436 if (options->kbd_interactive_authentication == -1) 2404 if (options->kbd_interactive_authentication == -1)
2437diff --git a/readconf.h b/readconf.h 2405diff --git a/readconf.h b/readconf.h
2438index 75e3f8f..5cc97f0 100644 2406index 0b9cb77..0e29889 100644
2439--- a/readconf.h 2407--- a/readconf.h
2440+++ b/readconf.h 2408+++ b/readconf.h
2441@@ -54,7 +54,12 @@ typedef struct { 2409@@ -45,7 +45,12 @@ typedef struct {
2442 int challenge_response_authentication; 2410 int challenge_response_authentication;
2443 /* Try S/Key or TIS, authentication. */ 2411 /* Try S/Key or TIS, authentication. */
2444 int gss_authentication; /* Try GSS authentication */ 2412 int gss_authentication; /* Try GSS authentication */
@@ -2452,10 +2420,10 @@ index 75e3f8f..5cc97f0 100644
2452 * authentication. */ 2420 * authentication. */
2453 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */ 2421 int kbd_interactive_authentication; /* Try keyboard-interactive auth. */
2454diff --git a/servconf.c b/servconf.c 2422diff --git a/servconf.c b/servconf.c
2455index 7ba65d5..0083cf8 100644 2423index b7f3294..cb3c831 100644
2456--- a/servconf.c 2424--- a/servconf.c
2457+++ b/servconf.c 2425+++ b/servconf.c
2458@@ -108,7 +108,10 @@ initialize_server_options(ServerOptions *options) 2426@@ -109,7 +109,10 @@ initialize_server_options(ServerOptions *options)
2459 options->kerberos_ticket_cleanup = -1; 2427 options->kerberos_ticket_cleanup = -1;
2460 options->kerberos_get_afs_token = -1; 2428 options->kerberos_get_afs_token = -1;
2461 options->gss_authentication=-1; 2429 options->gss_authentication=-1;
@@ -2466,7 +2434,7 @@ index 7ba65d5..0083cf8 100644
2466 options->password_authentication = -1; 2434 options->password_authentication = -1;
2467 options->kbd_interactive_authentication = -1; 2435 options->kbd_interactive_authentication = -1;
2468 options->challenge_response_authentication = -1; 2436 options->challenge_response_authentication = -1;
2469@@ -244,8 +247,14 @@ fill_default_server_options(ServerOptions *options) 2437@@ -250,8 +253,14 @@ fill_default_server_options(ServerOptions *options)
2470 options->kerberos_get_afs_token = 0; 2438 options->kerberos_get_afs_token = 0;
2471 if (options->gss_authentication == -1) 2439 if (options->gss_authentication == -1)
2472 options->gss_authentication = 0; 2440 options->gss_authentication = 0;
@@ -2481,7 +2449,7 @@ index 7ba65d5..0083cf8 100644
2481 if (options->password_authentication == -1) 2449 if (options->password_authentication == -1)
2482 options->password_authentication = 1; 2450 options->password_authentication = 1;
2483 if (options->kbd_interactive_authentication == -1) 2451 if (options->kbd_interactive_authentication == -1)
2484@@ -340,7 +349,9 @@ typedef enum { 2452@@ -352,7 +361,9 @@ typedef enum {
2485 sBanner, sUseDNS, sHostbasedAuthentication, 2453 sBanner, sUseDNS, sHostbasedAuthentication,
2486 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval, 2454 sHostbasedUsesNameFromPacketOnly, sClientAliveInterval,
2487 sClientAliveCountMax, sAuthorizedKeysFile, 2455 sClientAliveCountMax, sAuthorizedKeysFile,
@@ -2492,7 +2460,7 @@ index 7ba65d5..0083cf8 100644
2492 sMatch, sPermitOpen, sForceCommand, sChrootDirectory, 2460 sMatch, sPermitOpen, sForceCommand, sChrootDirectory,
2493 sUsePrivilegeSeparation, sAllowAgentForwarding, 2461 sUsePrivilegeSeparation, sAllowAgentForwarding,
2494 sHostCertificate, 2462 sHostCertificate,
2495@@ -407,10 +418,20 @@ static struct { 2463@@ -421,10 +432,20 @@ static struct {
2496 #ifdef GSSAPI 2464 #ifdef GSSAPI
2497 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL }, 2465 { "gssapiauthentication", sGssAuthentication, SSHCFG_ALL },
2498 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL }, 2466 { "gssapicleanupcredentials", sGssCleanupCreds, SSHCFG_GLOBAL },
@@ -2513,7 +2481,7 @@ index 7ba65d5..0083cf8 100644
2513 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL }, 2481 { "passwordauthentication", sPasswordAuthentication, SSHCFG_ALL },
2514 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL }, 2482 { "kbdinteractiveauthentication", sKbdInteractiveAuthentication, SSHCFG_ALL },
2515 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL }, 2483 { "challengeresponseauthentication", sChallengeResponseAuthentication, SSHCFG_GLOBAL },
2516@@ -1086,10 +1107,22 @@ process_server_config_line(ServerOptions *options, char *line, 2484@@ -1104,10 +1125,22 @@ process_server_config_line(ServerOptions *options, char *line,
2517 intptr = &options->gss_authentication; 2485 intptr = &options->gss_authentication;
2518 goto parse_flag; 2486 goto parse_flag;
2519 2487
@@ -2536,7 +2504,7 @@ index 7ba65d5..0083cf8 100644
2536 case sPasswordAuthentication: 2504 case sPasswordAuthentication:
2537 intptr = &options->password_authentication; 2505 intptr = &options->password_authentication;
2538 goto parse_flag; 2506 goto parse_flag;
2539@@ -1995,7 +2028,10 @@ dump_config(ServerOptions *o) 2507@@ -2042,7 +2075,10 @@ dump_config(ServerOptions *o)
2540 #endif 2508 #endif
2541 #ifdef GSSAPI 2509 #ifdef GSSAPI
2542 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication); 2510 dump_cfg_fmtint(sGssAuthentication, o->gss_authentication);
@@ -2548,10 +2516,10 @@ index 7ba65d5..0083cf8 100644
2548 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication); 2516 dump_cfg_fmtint(sPasswordAuthentication, o->password_authentication);
2549 dump_cfg_fmtint(sKbdInteractiveAuthentication, 2517 dump_cfg_fmtint(sKbdInteractiveAuthentication,
2550diff --git a/servconf.h b/servconf.h 2518diff --git a/servconf.h b/servconf.h
2551index 752d1c5..c922eb5 100644 2519index 766db3a..f8265a8 100644
2552--- a/servconf.h 2520--- a/servconf.h
2553+++ b/servconf.h 2521+++ b/servconf.h
2554@@ -112,7 +112,10 @@ typedef struct { 2522@@ -113,7 +113,10 @@ typedef struct {
2555 int kerberos_get_afs_token; /* If true, try to get AFS token if 2523 int kerberos_get_afs_token; /* If true, try to get AFS token if
2556 * authenticated with Kerberos. */ 2524 * authenticated with Kerberos. */
2557 int gss_authentication; /* If true, permit GSSAPI authentication */ 2525 int gss_authentication; /* If true, permit GSSAPI authentication */
@@ -2679,10 +2647,10 @@ index 03a228f..228e5ab 100644
2679 # CheckHostIP yes 2647 # CheckHostIP yes
2680 # AddressFamily any 2648 # AddressFamily any
2681diff --git a/ssh_config.5 b/ssh_config.5 2649diff --git a/ssh_config.5 b/ssh_config.5
2682index b580392..e7accd6 100644 2650index f9ede7a..e6649ac 100644
2683--- a/ssh_config.5 2651--- a/ssh_config.5
2684+++ b/ssh_config.5 2652+++ b/ssh_config.5
2685@@ -682,11 +682,43 @@ Specifies whether user authentication based on GSSAPI is allowed. 2653@@ -701,11 +701,43 @@ Specifies whether user authentication based on GSSAPI is allowed.
2686 The default is 2654 The default is
2687 .Dq no . 2655 .Dq no .
2688 Note that this option applies to protocol version 2 only. 2656 Note that this option applies to protocol version 2 only.
@@ -2728,11 +2696,11 @@ index b580392..e7accd6 100644
2728 Indicates that 2696 Indicates that
2729 .Xr ssh 1 2697 .Xr ssh 1
2730diff --git a/sshconnect2.c b/sshconnect2.c 2698diff --git a/sshconnect2.c b/sshconnect2.c
2731index 7f4ff41..66cb035 100644 2699index 68f7f4f..7b478f1 100644
2732--- a/sshconnect2.c 2700--- a/sshconnect2.c
2733+++ b/sshconnect2.c 2701+++ b/sshconnect2.c
2734@@ -158,9 +158,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 2702@@ -159,9 +159,34 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
2735 { 2703 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
2736 Kex *kex; 2704 Kex *kex;
2737 2705
2738+#ifdef GSSAPI 2706+#ifdef GSSAPI
@@ -2766,9 +2734,9 @@ index 7f4ff41..66cb035 100644
2766 if (options.ciphers == (char *)-1) { 2734 if (options.ciphers == (char *)-1) {
2767 logit("No valid ciphers for protocol version 2 given, using defaults."); 2735 logit("No valid ciphers for protocol version 2 given, using defaults.");
2768 options.ciphers = NULL; 2736 options.ciphers = NULL;
2769@@ -196,6 +221,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 2737@@ -199,6 +224,17 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
2770 if (options.kex_algorithms != NULL) 2738 myproposal[PROPOSAL_KEX_ALGS] = compat_kex_proposal(
2771 myproposal[PROPOSAL_KEX_ALGS] = options.kex_algorithms; 2739 myproposal[PROPOSAL_KEX_ALGS]);
2772 2740
2773+#ifdef GSSAPI 2741+#ifdef GSSAPI
2774+ /* If we've got GSSAPI algorithms, then we also support the 2742+ /* If we've got GSSAPI algorithms, then we also support the
@@ -2784,9 +2752,9 @@ index 7f4ff41..66cb035 100644
2784 if (options.rekey_limit || options.rekey_interval) 2752 if (options.rekey_limit || options.rekey_interval)
2785 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 2753 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
2786 (time_t)options.rekey_interval); 2754 (time_t)options.rekey_interval);
2787@@ -208,10 +244,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 2755@@ -213,10 +249,30 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
2788 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
2789 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 2756 kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
2757 #endif
2790 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 2758 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
2791+#ifdef GSSAPI 2759+#ifdef GSSAPI
2792+ if (options.gss_keyex) { 2760+ if (options.gss_keyex) {
@@ -2815,7 +2783,7 @@ index 7f4ff41..66cb035 100644
2815 xxx_kex = kex; 2783 xxx_kex = kex;
2816 2784
2817 dispatch_run(DISPATCH_BLOCK, &kex->done, kex); 2785 dispatch_run(DISPATCH_BLOCK, &kex->done, kex);
2818@@ -301,6 +357,7 @@ void input_gssapi_token(int type, u_int32_t, void *); 2786@@ -306,6 +362,7 @@ void input_gssapi_token(int type, u_int32_t, void *);
2819 void input_gssapi_hash(int type, u_int32_t, void *); 2787 void input_gssapi_hash(int type, u_int32_t, void *);
2820 void input_gssapi_error(int, u_int32_t, void *); 2788 void input_gssapi_error(int, u_int32_t, void *);
2821 void input_gssapi_errtok(int, u_int32_t, void *); 2789 void input_gssapi_errtok(int, u_int32_t, void *);
@@ -2823,7 +2791,7 @@ index 7f4ff41..66cb035 100644
2823 #endif 2791 #endif
2824 2792
2825 void userauth(Authctxt *, char *); 2793 void userauth(Authctxt *, char *);
2826@@ -316,6 +373,11 @@ static char *authmethods_get(void); 2794@@ -321,6 +378,11 @@ static char *authmethods_get(void);
2827 2795
2828 Authmethod authmethods[] = { 2796 Authmethod authmethods[] = {
2829 #ifdef GSSAPI 2797 #ifdef GSSAPI
@@ -2835,7 +2803,7 @@ index 7f4ff41..66cb035 100644
2835 {"gssapi-with-mic", 2803 {"gssapi-with-mic",
2836 userauth_gssapi, 2804 userauth_gssapi,
2837 NULL, 2805 NULL,
2838@@ -612,19 +674,31 @@ userauth_gssapi(Authctxt *authctxt) 2806@@ -617,19 +679,31 @@ userauth_gssapi(Authctxt *authctxt)
2839 static u_int mech = 0; 2807 static u_int mech = 0;
2840 OM_uint32 min; 2808 OM_uint32 min;
2841 int ok = 0; 2809 int ok = 0;
@@ -2869,7 +2837,7 @@ index 7f4ff41..66cb035 100644
2869 ok = 1; /* Mechanism works */ 2837 ok = 1; /* Mechanism works */
2870 } else { 2838 } else {
2871 mech++; 2839 mech++;
2872@@ -721,8 +795,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt) 2840@@ -726,8 +800,8 @@ input_gssapi_response(int type, u_int32_t plen, void *ctxt)
2873 { 2841 {
2874 Authctxt *authctxt = ctxt; 2842 Authctxt *authctxt = ctxt;
2875 Gssctxt *gssctxt; 2843 Gssctxt *gssctxt;
@@ -2880,7 +2848,7 @@ index 7f4ff41..66cb035 100644
2880 2848
2881 if (authctxt == NULL) 2849 if (authctxt == NULL)
2882 fatal("input_gssapi_response: no authentication context"); 2850 fatal("input_gssapi_response: no authentication context");
2883@@ -831,6 +905,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt) 2851@@ -836,6 +910,48 @@ input_gssapi_error(int type, u_int32_t plen, void *ctxt)
2884 free(msg); 2852 free(msg);
2885 free(lang); 2853 free(lang);
2886 } 2854 }
@@ -2930,10 +2898,10 @@ index 7f4ff41..66cb035 100644
2930 2898
2931 int 2899 int
2932diff --git a/sshd.c b/sshd.c 2900diff --git a/sshd.c b/sshd.c
2933index 7523de9..d787fea 100644 2901index 481d001..e6706a8 100644
2934--- a/sshd.c 2902--- a/sshd.c
2935+++ b/sshd.c 2903+++ b/sshd.c
2936@@ -122,6 +122,10 @@ 2904@@ -123,6 +123,10 @@
2937 #include "ssh-sandbox.h" 2905 #include "ssh-sandbox.h"
2938 #include "version.h" 2906 #include "version.h"
2939 2907
@@ -2941,10 +2909,10 @@ index 7523de9..d787fea 100644
2941+#include <Security/AuthSession.h> 2909+#include <Security/AuthSession.h>
2942+#endif 2910+#endif
2943+ 2911+
2944 #ifdef LIBWRAP 2912 #ifndef O_NOCTTY
2945 #include <tcpd.h> 2913 #define O_NOCTTY 0
2946 #include <syslog.h> 2914 #endif
2947@@ -1728,10 +1732,13 @@ main(int ac, char **av) 2915@@ -1745,10 +1749,13 @@ main(int ac, char **av)
2948 logit("Disabling protocol version 1. Could not load host key"); 2916 logit("Disabling protocol version 1. Could not load host key");
2949 options.protocol &= ~SSH_PROTO_1; 2917 options.protocol &= ~SSH_PROTO_1;
2950 } 2918 }
@@ -2958,7 +2926,7 @@ index 7523de9..d787fea 100644
2958 if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) { 2926 if (!(options.protocol & (SSH_PROTO_1|SSH_PROTO_2))) {
2959 logit("sshd: no hostkeys available -- exiting."); 2927 logit("sshd: no hostkeys available -- exiting.");
2960 exit(1); 2928 exit(1);
2961@@ -2058,6 +2065,60 @@ main(int ac, char **av) 2929@@ -2060,6 +2067,60 @@ main(int ac, char **av)
2962 remote_ip, remote_port, 2930 remote_ip, remote_port,
2963 get_local_ipaddr(sock_in), get_local_port()); 2931 get_local_ipaddr(sock_in), get_local_port());
2964 2932
@@ -3019,7 +2987,7 @@ index 7523de9..d787fea 100644
3019 /* 2987 /*
3020 * We don't want to listen forever unless the other side 2988 * We don't want to listen forever unless the other side
3021 * successfully authenticates itself. So we set up an alarm which is 2989 * successfully authenticates itself. So we set up an alarm which is
3022@@ -2469,6 +2530,48 @@ do_ssh2_kex(void) 2990@@ -2482,6 +2543,48 @@ do_ssh2_kex(void)
3023 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal( 2991 myproposal[PROPOSAL_SERVER_HOST_KEY_ALGS] = compat_pkalg_proposal(
3024 list_hostkey_types()); 2992 list_hostkey_types());
3025 2993
@@ -3067,10 +3035,10 @@ index 7523de9..d787fea 100644
3067+ 3035+
3068 /* start key exchange */ 3036 /* start key exchange */
3069 kex = kex_setup(myproposal); 3037 kex = kex_setup(myproposal);
3070 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 3038 #ifdef WITH_OPENSSL
3071@@ -2477,6 +2580,13 @@ do_ssh2_kex(void) 3039@@ -2492,6 +2595,13 @@ do_ssh2_kex(void)
3072 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
3073 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 3040 kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
3041 #endif
3074 kex->kex[KEX_C25519_SHA256] = kexc25519_server; 3042 kex->kex[KEX_C25519_SHA256] = kexc25519_server;
3075+#ifdef GSSAPI 3043+#ifdef GSSAPI
3076+ if (options.gss_keyex) { 3044+ if (options.gss_keyex) {
@@ -3096,10 +3064,10 @@ index e9045bc..d9b8594 100644
3096 # Set this to 'yes' to enable PAM authentication, account processing, 3064 # Set this to 'yes' to enable PAM authentication, account processing,
3097 # and session processing. If this is enabled, PAM authentication will 3065 # and session processing. If this is enabled, PAM authentication will
3098diff --git a/sshd_config.5 b/sshd_config.5 3066diff --git a/sshd_config.5 b/sshd_config.5
3099index ce71efe..ceed88a 100644 3067index fd44abe..c8b43da 100644
3100--- a/sshd_config.5 3068--- a/sshd_config.5
3101+++ b/sshd_config.5 3069+++ b/sshd_config.5
3102@@ -493,12 +493,40 @@ Specifies whether user authentication based on GSSAPI is allowed. 3070@@ -527,12 +527,40 @@ Specifies whether user authentication based on GSSAPI is allowed.
3103 The default is 3071 The default is
3104 .Dq no . 3072 .Dq no .
3105 Note that this option applies to protocol version 2 only. 3073 Note that this option applies to protocol version 2 only.
@@ -3140,3 +3108,36 @@ index ce71efe..ceed88a 100644
3140 .It Cm HostbasedAuthentication 3108 .It Cm HostbasedAuthentication
3141 Specifies whether rhosts or /etc/hosts.equiv authentication together 3109 Specifies whether rhosts or /etc/hosts.equiv authentication together
3142 with successful public key client host authentication is allowed 3110 with successful public key client host authentication is allowed
3111diff --git a/sshkey.c b/sshkey.c
3112index fdd0c8a..1a96eae 100644
3113--- a/sshkey.c
3114+++ b/sshkey.c
3115@@ -110,6 +110,7 @@ static const struct keytype keytypes[] = {
3116 { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
3117 KEY_DSA_CERT_V00, 0, 1 },
3118 #endif /* WITH_OPENSSL */
3119+ { "null", "null", KEY_NULL, 0, 0 },
3120 { NULL, NULL, -1, -1, 0 }
3121 };
3122
3123@@ -198,7 +199,7 @@ key_alg_list(int certs_only, int plain_only)
3124 const struct keytype *kt;
3125
3126 for (kt = keytypes; kt->type != -1; kt++) {
3127- if (kt->name == NULL)
3128+ if (kt->name == NULL || kt->type == KEY_NULL)
3129 continue;
3130 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
3131 continue;
3132diff --git a/sshkey.h b/sshkey.h
3133index 450b30c..b573e7f 100644
3134--- a/sshkey.h
3135+++ b/sshkey.h
3136@@ -64,6 +64,7 @@ enum sshkey_types {
3137 KEY_ED25519_CERT,
3138 KEY_RSA_CERT_V00,
3139 KEY_DSA_CERT_V00,
3140+ KEY_NULL,
3141 KEY_UNSPEC
3142 };
3143
diff --git a/debian/patches/helpful-wait-terminate.patch b/debian/patches/helpful-wait-terminate.patch
index e79f4990f..de43f2a80 100644
--- a/debian/patches/helpful-wait-terminate.patch
+++ b/debian/patches/helpful-wait-terminate.patch
@@ -1,4 +1,4 @@
1From ef912859a4300360164292abe47b5516c8ee4a13 Mon Sep 17 00:00:00 2001 1From aca34215fc0e85d6b49e04f0a3cd0db79732125e Mon Sep 17 00:00:00 2001
2From: Matthew Vernon <matthew@debian.org> 2From: Matthew Vernon <matthew@debian.org>
3Date: Sun, 9 Feb 2014 16:09:56 +0000 3Date: Sun, 9 Feb 2014 16:09:56 +0000
4Subject: Mention ~& when waiting for forwarded connections to terminate 4Subject: Mention ~& when waiting for forwarded connections to terminate
@@ -12,7 +12,7 @@ Patch-Name: helpful-wait-terminate.patch
12 1 file changed, 1 insertion(+), 1 deletion(-) 12 1 file changed, 1 insertion(+), 1 deletion(-)
13 13
14diff --git a/serverloop.c b/serverloop.c 14diff --git a/serverloop.c b/serverloop.c
15index 2f8e3a0..441d73b 100644 15index e92f9e2..813e5bf 100644
16--- a/serverloop.c 16--- a/serverloop.c
17+++ b/serverloop.c 17+++ b/serverloop.c
18@@ -687,7 +687,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg) 18@@ -687,7 +687,7 @@ server_loop(pid_t pid, int fdin_arg, int fdout_arg, int fderr_arg)
diff --git a/debian/patches/keepalive-extensions.patch b/debian/patches/keepalive-extensions.patch
index 680701f3d..15acabc0e 100644
--- a/debian/patches/keepalive-extensions.patch
+++ b/debian/patches/keepalive-extensions.patch
@@ -1,4 +1,4 @@
1From 81540b7886fdc73c7be304706ea33d6d87b5fc81 Mon Sep 17 00:00:00 2001 1From bd3abc2f732da3a61e4158b915480808957a4357 Mon Sep 17 00:00:00 2001
2From: Richard Kettlewell <rjk@greenend.org.uk> 2From: Richard Kettlewell <rjk@greenend.org.uk>
3Date: Sun, 9 Feb 2014 16:09:52 +0000 3Date: Sun, 9 Feb 2014 16:09:52 +0000
4Subject: Various keepalive extensions 4Subject: Various keepalive extensions
@@ -16,7 +16,7 @@ keepalives.
16Author: Ian Jackson <ian@chiark.greenend.org.uk> 16Author: Ian Jackson <ian@chiark.greenend.org.uk>
17Author: Matthew Vernon <matthew@debian.org> 17Author: Matthew Vernon <matthew@debian.org>
18Author: Colin Watson <cjwatson@debian.org> 18Author: Colin Watson <cjwatson@debian.org>
19Last-Update: 2013-09-14 19Last-Update: 2014-10-07
20 20
21Patch-Name: keepalive-extensions.patch 21Patch-Name: keepalive-extensions.patch
22--- 22---
@@ -26,27 +26,27 @@ Patch-Name: keepalive-extensions.patch
26 3 files changed, 34 insertions(+), 4 deletions(-) 26 3 files changed, 34 insertions(+), 4 deletions(-)
27 27
28diff --git a/readconf.c b/readconf.c 28diff --git a/readconf.c b/readconf.c
29index bcd8cad..6409937 100644 29index bc879eb..337818c 100644
30--- a/readconf.c 30--- a/readconf.c
31+++ b/readconf.c 31+++ b/readconf.c
32@@ -151,6 +151,7 @@ typedef enum { 32@@ -153,6 +153,7 @@ typedef enum {
33 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
34 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 33 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
35 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 34 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
35 oStreamLocalBindMask, oStreamLocalBindUnlink,
36+ oProtocolKeepAlives, oSetupTimeOut, 36+ oProtocolKeepAlives, oSetupTimeOut,
37 oIgnoredUnknownOption, oDeprecated, oUnsupported 37 oIgnoredUnknownOption, oDeprecated, oUnsupported
38 } OpCodes; 38 } OpCodes;
39 39
40@@ -274,6 +275,8 @@ static struct { 40@@ -278,6 +279,8 @@ static struct {
41 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 41 { "streamlocalbindmask", oStreamLocalBindMask },
42 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 42 { "streamlocalbindunlink", oStreamLocalBindUnlink },
43 { "ignoreunknown", oIgnoreUnknown }, 43 { "ignoreunknown", oIgnoreUnknown },
44+ { "protocolkeepalives", oProtocolKeepAlives }, 44+ { "protocolkeepalives", oProtocolKeepAlives },
45+ { "setuptimeout", oSetupTimeOut }, 45+ { "setuptimeout", oSetupTimeOut },
46 46
47 { NULL, oBadOption } 47 { NULL, oBadOption }
48 }; 48 };
49@@ -1247,6 +1250,8 @@ parse_int: 49@@ -1271,6 +1274,8 @@ parse_int:
50 goto parse_flag; 50 goto parse_flag;
51 51
52 case oServerAliveInterval: 52 case oServerAliveInterval:
@@ -55,7 +55,7 @@ index bcd8cad..6409937 100644
55 intptr = &options->server_alive_interval; 55 intptr = &options->server_alive_interval;
56 goto parse_time; 56 goto parse_time;
57 57
58@@ -1746,8 +1751,13 @@ fill_default_options(Options * options) 58@@ -1791,8 +1796,13 @@ fill_default_options(Options * options)
59 options->rekey_interval = 0; 59 options->rekey_interval = 0;
60 if (options->verify_host_key_dns == -1) 60 if (options->verify_host_key_dns == -1)
61 options->verify_host_key_dns = 0; 61 options->verify_host_key_dns = 0;
@@ -72,7 +72,7 @@ index bcd8cad..6409937 100644
72 options->server_alive_count_max = 3; 72 options->server_alive_count_max = 3;
73 if (options->control_master == -1) 73 if (options->control_master == -1)
74diff --git a/ssh_config.5 b/ssh_config.5 74diff --git a/ssh_config.5 b/ssh_config.5
75index 473971e..3172fd4 100644 75index 01f1f7f..ea92ea8 100644
76--- a/ssh_config.5 76--- a/ssh_config.5
77+++ b/ssh_config.5 77+++ b/ssh_config.5
78@@ -205,8 +205,12 @@ Valid arguments are 78@@ -205,8 +205,12 @@ Valid arguments are
@@ -89,7 +89,7 @@ index 473971e..3172fd4 100644
89 The argument must be 89 The argument must be
90 .Dq yes 90 .Dq yes
91 or 91 or
92@@ -1305,8 +1309,15 @@ from the server, 92@@ -1336,8 +1340,15 @@ from the server,
93 will send a message through the encrypted 93 will send a message through the encrypted
94 channel to request a response from the server. 94 channel to request a response from the server.
95 The default 95 The default
@@ -103,10 +103,10 @@ index 473971e..3172fd4 100644
103+and 103+and
104+.Cm SetupTimeOut 104+.Cm SetupTimeOut
105+are Debian-specific compatibility aliases for this option. 105+are Debian-specific compatibility aliases for this option.
106 .It Cm StrictHostKeyChecking 106 .It Cm StreamLocalBindMask
107 If this flag is set to 107 Sets the octal file creation mode mask
108 .Dq yes , 108 .Pq umask
109@@ -1345,6 +1356,12 @@ Specifies whether the system should send TCP keepalive messages to the 109@@ -1403,6 +1414,12 @@ Specifies whether the system should send TCP keepalive messages to the
110 other side. 110 other side.
111 If they are sent, death of the connection or crash of one 111 If they are sent, death of the connection or crash of one
112 of the machines will be properly noticed. 112 of the machines will be properly noticed.
@@ -120,10 +120,10 @@ index 473971e..3172fd4 100644
120 connections will die if the route is down temporarily, and some people 120 connections will die if the route is down temporarily, and some people
121 find it annoying. 121 find it annoying.
122diff --git a/sshd_config.5 b/sshd_config.5 122diff --git a/sshd_config.5 b/sshd_config.5
123index ceed88a..2164d58 100644 123index c8b43da..2843048 100644
124--- a/sshd_config.5 124--- a/sshd_config.5
125+++ b/sshd_config.5 125+++ b/sshd_config.5
126@@ -1183,6 +1183,9 @@ This avoids infinitely hanging sessions. 126@@ -1307,6 +1307,9 @@ This avoids infinitely hanging sessions.
127 .Pp 127 .Pp
128 To disable TCP keepalive messages, the value should be set to 128 To disable TCP keepalive messages, the value should be set to
129 .Dq no . 129 .Dq no .
diff --git a/debian/patches/lintian-symlink-pickiness.patch b/debian/patches/lintian-symlink-pickiness.patch
index 09e09ecf8..81b924e35 100644
--- a/debian/patches/lintian-symlink-pickiness.patch
+++ b/debian/patches/lintian-symlink-pickiness.patch
@@ -1,4 +1,4 @@
1From eb567100ef178f4395c95cc1f37b921e02c3dd5b Mon Sep 17 00:00:00 2001 1From 248d3bb8de371b55aaf3a8f544c15f3a25eb7339 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:08 +0000 3Date: Sun, 9 Feb 2014 16:10:08 +0000
4Subject: Fix picky lintian errors about slogin symlinks 4Subject: Fix picky lintian errors about slogin symlinks
@@ -15,10 +15,10 @@ Patch-Name: lintian-symlink-pickiness.patch
15 1 file changed, 2 insertions(+), 2 deletions(-) 15 1 file changed, 2 insertions(+), 2 deletions(-)
16 16
17diff --git a/Makefile.in b/Makefile.in 17diff --git a/Makefile.in b/Makefile.in
18index feee0b2..7d192bb 100644 18index a4402e9..4eab574 100644
19--- a/Makefile.in 19--- a/Makefile.in
20+++ b/Makefile.in 20+++ b/Makefile.in
21@@ -293,9 +293,9 @@ install-files: 21@@ -315,9 +315,9 @@ install-files:
22 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8 22 $(INSTALL) -m 644 ssh-keysign.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-keysign.8
23 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8 23 $(INSTALL) -m 644 ssh-pkcs11-helper.8.out $(DESTDIR)$(mandir)/$(mansubdir)8/ssh-pkcs11-helper.8
24 -rm -f $(DESTDIR)$(bindir)/slogin 24 -rm -f $(DESTDIR)$(bindir)/slogin
diff --git a/debian/patches/mention-ssh-keygen-on-keychange.patch b/debian/patches/mention-ssh-keygen-on-keychange.patch
index e00b6c345..f90c7e2b1 100644
--- a/debian/patches/mention-ssh-keygen-on-keychange.patch
+++ b/debian/patches/mention-ssh-keygen-on-keychange.patch
@@ -1,4 +1,4 @@
1From 8ab8f1465980856291f215c7b7184a4456398fb4 Mon Sep 17 00:00:00 2001 1From 064453886f4c3d8ac0b0c8d015ad614c8bce3b42 Mon Sep 17 00:00:00 2001
2From: Scott Moser <smoser@ubuntu.com> 2From: Scott Moser <smoser@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:10:03 +0000 3Date: Sun, 9 Feb 2014 16:10:03 +0000
4Subject: Mention ssh-keygen in ssh fingerprint changed warning 4Subject: Mention ssh-keygen in ssh fingerprint changed warning
@@ -13,10 +13,10 @@ Patch-Name: mention-ssh-keygen-on-keychange.patch
13 1 file changed, 6 insertions(+), 1 deletion(-) 13 1 file changed, 6 insertions(+), 1 deletion(-)
14 14
15diff --git a/sshconnect.c b/sshconnect.c 15diff --git a/sshconnect.c b/sshconnect.c
16index 9e02837..e0a5db9 100644 16index 26116d2..ab83d0c 100644
17--- a/sshconnect.c 17--- a/sshconnect.c
18+++ b/sshconnect.c 18+++ b/sshconnect.c
19@@ -1065,9 +1065,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 19@@ -1066,9 +1066,12 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
20 error("%s. This could either mean that", key_msg); 20 error("%s. This could either mean that", key_msg);
21 error("DNS SPOOFING is happening or the IP address for the host"); 21 error("DNS SPOOFING is happening or the IP address for the host");
22 error("and its host key have changed at the same time."); 22 error("and its host key have changed at the same time.");
@@ -30,7 +30,7 @@ index 9e02837..e0a5db9 100644
30 } 30 }
31 /* The host key has changed. */ 31 /* The host key has changed. */
32 warn_changed_key(host_key); 32 warn_changed_key(host_key);
33@@ -1075,6 +1078,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port, 33@@ -1076,6 +1079,8 @@ check_host_key(char *hostname, struct sockaddr *hostaddr, u_short port,
34 user_hostfiles[0]); 34 user_hostfiles[0]);
35 error("Offending %s key in %s:%lu", key_type(host_found->key), 35 error("Offending %s key in %s:%lu", key_type(host_found->key),
36 host_found->file, host_found->line); 36 host_found->file, host_found->line);
diff --git a/debian/patches/no-openssl-version-check.patch b/debian/patches/no-openssl-version-check.patch
deleted file mode 100644
index 56fa46aac..000000000
--- a/debian/patches/no-openssl-version-check.patch
+++ /dev/null
@@ -1,41 +0,0 @@
1From 20690ea4b33e8ff81fea287492270df3a7029777 Mon Sep 17 00:00:00 2001
2From: Philip Hands <phil@hands.com>
3Date: Sun, 9 Feb 2014 16:10:14 +0000
4Subject: Disable OpenSSL version check
5
6OpenSSL's SONAME is sufficient nowadays.
7
8Author: Colin Watson <cjwatson@debian.org>
9Bug-Debian: http://bugs.debian.org/93581
10Bug-Debian: http://bugs.debian.org/664383
11Forwarded: not-needed
12Last-Update: 2013-12-23
13
14Patch-Name: no-openssl-version-check.patch
15---
16 entropy.c | 12 ------------
17 1 file changed, 12 deletions(-)
18
19diff --git a/entropy.c b/entropy.c
20index 2d483b3..2aee2d9 100644
21--- a/entropy.c
22+++ b/entropy.c
23@@ -209,18 +209,6 @@ seed_rng(void)
24 #ifndef OPENSSL_PRNG_ONLY
25 unsigned char buf[RANDOM_SEED_SIZE];
26 #endif
27- /*
28- * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
29- * We match major, minor, fix and status (not patch) for <1.0.0.
30- * After that, we acceptable compatible fix versions (so we
31- * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed
32- * within a patch series.
33- */
34- u_long version_mask = SSLeay() >= 0x1000000f ? ~0xffff0L : ~0xff0L;
35- if (((SSLeay() ^ OPENSSL_VERSION_NUMBER) & version_mask) ||
36- (SSLeay() >> 12) < (OPENSSL_VERSION_NUMBER >> 12))
37- fatal("OpenSSL version mismatch. Built against %lx, you "
38- "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
39
40 #ifndef OPENSSL_PRNG_ONLY
41 if (RAND_status() == 1) {
diff --git a/debian/patches/no-openssl-version-status.patch b/debian/patches/no-openssl-version-status.patch
new file mode 100644
index 000000000..dfcef83b0
--- /dev/null
+++ b/debian/patches/no-openssl-version-status.patch
@@ -0,0 +1,62 @@
1From 37fd625165d0df302e441d9cad9bcc742378eef5 Mon Sep 17 00:00:00 2001
2From: Kurt Roeckx <kurt@roeckx.be>
3Date: Sun, 9 Feb 2014 16:10:14 +0000
4Subject: Don't check the status field of the OpenSSL version
5
6There is no reason to check the version of OpenSSL (in Debian). If it's
7not compatible the soname will change. OpenSSH seems to want to do a
8check for the soname based on the version number, but wants to keep the
9status of the release the same. Remove that check on the status since
10it doesn't tell you anything about how compatible that version is.
11
12Author: Colin Watson <cjwatson@debian.org>
13Bug-Debian: https://bugs.debian.org/93581
14Bug-Debian: https://bugs.debian.org/664383
15Bug-Debian: https://bugs.debian.org/732940
16Forwarded: not-needed
17Last-Update: 2014-10-07
18
19Patch-Name: no-openssl-version-status.patch
20---
21 openbsd-compat/openssl-compat.c | 6 +++---
22 openbsd-compat/regress/opensslvertest.c | 1 +
23 2 files changed, 4 insertions(+), 3 deletions(-)
24
25diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
26index 36570e4..defd5fb 100644
27--- a/openbsd-compat/openssl-compat.c
28+++ b/openbsd-compat/openssl-compat.c
29@@ -34,7 +34,7 @@
30 /*
31 * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
32 * We match major, minor, fix and status (not patch) for <1.0.0.
33- * After that, we acceptable compatible fix versions (so we
34+ * After that, we accept compatible fix and status versions (so we
35 * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed
36 * within a patch series.
37 */
38@@ -55,10 +55,10 @@ ssh_compatible_openssl(long headerver, long libver)
39 }
40
41 /*
42- * For versions >= 1.0.0, major,minor,status must match and library
43+ * For versions >= 1.0.0, major,minor must match and library
44 * fix version must be equal to or newer than the header.
45 */
46- mask = 0xfff0000fL; /* major,minor,status */
47+ mask = 0xfff00000L; /* major,minor */
48 hfix = (headerver & 0x000ff000) >> 12;
49 lfix = (libver & 0x000ff000) >> 12;
50 if ( (headerver & mask) == (libver & mask) && lfix >= hfix)
51diff --git a/openbsd-compat/regress/opensslvertest.c b/openbsd-compat/regress/opensslvertest.c
52index 5d019b5..5847487 100644
53--- a/openbsd-compat/regress/opensslvertest.c
54+++ b/openbsd-compat/regress/opensslvertest.c
55@@ -35,6 +35,7 @@ struct version_test {
56
57 /* built with 1.0.1b release headers */
58 { 0x1000101fL, 0x1000101fL, 1},/* exact match */
59+ { 0x1000101fL, 0x10001010L, 1}, /* different status: ok */
60 { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */
61 { 0x1000101fL, 0x1000100fL, 1}, /* older library patch version: ok */
62 { 0x1000101fL, 0x1000201fL, 1}, /* newer library fix version: ok */
diff --git a/debian/patches/openbsd-docs.patch b/debian/patches/openbsd-docs.patch
index 9a34a4182..37ad675d4 100644
--- a/debian/patches/openbsd-docs.patch
+++ b/debian/patches/openbsd-docs.patch
@@ -1,4 +1,4 @@
1From ec9bfd62211fdf5a3004ef2045c2eb3baccfd375 Mon Sep 17 00:00:00 2001 1From 0b9407d3023938b02bccf7dd1874a871d0cc8eb5 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:09 +0000 3Date: Sun, 9 Feb 2014 16:10:09 +0000
4Subject: Adjust various OpenBSD-specific references in manual pages 4Subject: Adjust various OpenBSD-specific references in manual pages
@@ -10,7 +10,7 @@ No single bug reference for this patch, but history includes:
10 https://bugs.launchpad.net/bugs/456660 (ssl(8)) 10 https://bugs.launchpad.net/bugs/456660 (ssl(8))
11 11
12Forwarded: not-needed 12Forwarded: not-needed
13Last-Update: 2013-09-14 13Last-Update: 2014-10-07
14 14
15Patch-Name: openbsd-docs.patch 15Patch-Name: openbsd-docs.patch
16--- 16---
@@ -44,7 +44,7 @@ index ef0de08..149846c 100644
44 .Sh SEE ALSO 44 .Sh SEE ALSO
45 .Xr ssh-keygen 1 , 45 .Xr ssh-keygen 1 ,
46diff --git a/ssh-keygen.1 b/ssh-keygen.1 46diff --git a/ssh-keygen.1 b/ssh-keygen.1
47index 12e00d4..a71de74 100644 47index 723a016..79b948c 100644
48--- a/ssh-keygen.1 48--- a/ssh-keygen.1
49+++ b/ssh-keygen.1 49+++ b/ssh-keygen.1
50@@ -172,9 +172,7 @@ key in 50@@ -172,9 +172,7 @@ key in
@@ -88,10 +88,10 @@ index 12e00d4..a71de74 100644
88 The file format is described in 88 The file format is described in
89 .Xr moduli 5 . 89 .Xr moduli 5 .
90diff --git a/ssh.1 b/ssh.1 90diff --git a/ssh.1 b/ssh.1
91index ff5e6ac..67b4f44 100644 91index 7f6ab77..de178cd 100644
92--- a/ssh.1 92--- a/ssh.1
93+++ b/ssh.1 93+++ b/ssh.1
94@@ -763,6 +763,10 @@ Protocol 1 is restricted to using only RSA keys, 94@@ -753,6 +753,10 @@ Protocol 1 is restricted to using only RSA keys,
95 but protocol 2 may use any. 95 but protocol 2 may use any.
96 The HISTORY section of 96 The HISTORY section of
97 .Xr ssl 8 97 .Xr ssl 8
@@ -103,10 +103,10 @@ index ff5e6ac..67b4f44 100644
103 .Pp 103 .Pp
104 The file 104 The file
105diff --git a/sshd.8 b/sshd.8 105diff --git a/sshd.8 b/sshd.8
106index e6a900b..b016e90 100644 106index eaeac45..3538208 100644
107--- a/sshd.8 107--- a/sshd.8
108+++ b/sshd.8 108+++ b/sshd.8
109@@ -70,7 +70,7 @@ over an insecure network. 109@@ -67,7 +67,7 @@ over an insecure network.
110 .Nm 110 .Nm
111 listens for connections from clients. 111 listens for connections from clients.
112 It is normally started at boot from 112 It is normally started at boot from
@@ -133,14 +133,14 @@ index e6a900b..b016e90 100644
133 .Xr sshd_config 5 , 133 .Xr sshd_config 5 ,
134 .Xr inetd 8 , 134 .Xr inetd 8 ,
135diff --git a/sshd_config.5 b/sshd_config.5 135diff --git a/sshd_config.5 b/sshd_config.5
136index 8f078f6..908e0bb 100644 136index 58997d3..7396b23 100644
137--- a/sshd_config.5 137--- a/sshd_config.5
138+++ b/sshd_config.5 138+++ b/sshd_config.5
139@@ -283,8 +283,7 @@ This option is only available for protocol version 2. 139@@ -303,8 +303,7 @@ This option is only available for protocol version 2.
140 By default, no banner is displayed. 140 By default, no banner is displayed.
141 .It Cm ChallengeResponseAuthentication 141 .It Cm ChallengeResponseAuthentication
142 Specifies whether challenge-response authentication is allowed (e.g. via 142 Specifies whether challenge-response authentication is allowed (e.g. via
143-PAM or though authentication styles supported in 143-PAM or through authentication styles supported in
144-.Xr login.conf 5 ) 144-.Xr login.conf 5 )
145+PAM). 145+PAM).
146 The default is 146 The default is
diff --git a/debian/patches/package-versioning.patch b/debian/patches/package-versioning.patch
index c9c20d1c0..07a28af9a 100644
--- a/debian/patches/package-versioning.patch
+++ b/debian/patches/package-versioning.patch
@@ -1,4 +1,4 @@
1From 6de70b95f5005447ae23532d4f3ee41a9338479f Mon Sep 17 00:00:00 2001 1From 8679c96f74ee7dbea6c15c764b036fbab7372740 Mon Sep 17 00:00:00 2001
2From: Matthew Vernon <matthew@debian.org> 2From: Matthew Vernon <matthew@debian.org>
3Date: Sun, 9 Feb 2014 16:10:05 +0000 3Date: Sun, 9 Feb 2014 16:10:05 +0000
4Subject: Include the Debian version in our identification 4Subject: Include the Debian version in our identification
@@ -19,10 +19,10 @@ Patch-Name: package-versioning.patch
19 3 files changed, 9 insertions(+), 4 deletions(-) 19 3 files changed, 9 insertions(+), 4 deletions(-)
20 20
21diff --git a/sshconnect.c b/sshconnect.c 21diff --git a/sshconnect.c b/sshconnect.c
22index e0a5db9..87c3770 100644 22index ab83d0c..563405e 100644
23--- a/sshconnect.c 23--- a/sshconnect.c
24+++ b/sshconnect.c 24+++ b/sshconnect.c
25@@ -520,10 +520,10 @@ send_client_banner(int connection_out, int minor1) 25@@ -521,10 +521,10 @@ send_client_banner(int connection_out, int minor1)
26 /* Send our own protocol version identification. */ 26 /* Send our own protocol version identification. */
27 if (compat20) { 27 if (compat20) {
28 xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n", 28 xasprintf(&client_version_string, "SSH-%d.%d-%.100s\r\n",
@@ -36,10 +36,10 @@ index e0a5db9..87c3770 100644
36 if (roaming_atomicio(vwrite, connection_out, client_version_string, 36 if (roaming_atomicio(vwrite, connection_out, client_version_string,
37 strlen(client_version_string)) != strlen(client_version_string)) 37 strlen(client_version_string)) != strlen(client_version_string))
38diff --git a/sshd.c b/sshd.c 38diff --git a/sshd.c b/sshd.c
39index e343d90..af9b8f1 100644 39index 48a14dd..1710e71 100644
40--- a/sshd.c 40--- a/sshd.c
41+++ b/sshd.c 41+++ b/sshd.c
42@@ -440,7 +440,7 @@ sshd_exchange_identification(int sock_in, int sock_out) 42@@ -443,7 +443,7 @@ sshd_exchange_identification(int sock_in, int sock_out)
43 } 43 }
44 44
45 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s", 45 xasprintf(&server_version_string, "SSH-%d.%d-%.100s%s%s%s",
@@ -49,11 +49,11 @@ index e343d90..af9b8f1 100644
49 options.version_addendum, newline); 49 options.version_addendum, newline);
50 50
51diff --git a/version.h b/version.h 51diff --git a/version.h b/version.h
52index a1579ac..a97c337 100644 52index cc8a079..0fee7c3 100644
53--- a/version.h 53--- a/version.h
54+++ b/version.h 54+++ b/version.h
55@@ -3,4 +3,9 @@ 55@@ -3,4 +3,9 @@
56 #define SSH_VERSION "OpenSSH_6.6" 56 #define SSH_VERSION "OpenSSH_6.7"
57 57
58 #define SSH_PORTABLE "p1" 58 #define SSH_PORTABLE "p1"
59-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE 59-#define SSH_RELEASE SSH_VERSION SSH_PORTABLE
diff --git a/debian/patches/quieter-signals.patch b/debian/patches/quieter-signals.patch
index 075b59823..6d9a2f9c0 100644
--- a/debian/patches/quieter-signals.patch
+++ b/debian/patches/quieter-signals.patch
@@ -1,4 +1,4 @@
1From 9875e47079abff55f8d2c1e958e9d50de6eae7ec Mon Sep 17 00:00:00 2001 1From dc028c5992b4b14cca380b6ad2115fcc6907a8b7 Mon Sep 17 00:00:00 2001
2From: Peter Samuelson <peter@p12n.org> 2From: Peter Samuelson <peter@p12n.org>
3Date: Sun, 9 Feb 2014 16:09:55 +0000 3Date: Sun, 9 Feb 2014 16:09:55 +0000
4Subject: Reduce severity of "Killed by signal %d" 4Subject: Reduce severity of "Killed by signal %d"
@@ -22,10 +22,10 @@ Patch-Name: quieter-signals.patch
22 1 file changed, 4 insertions(+), 2 deletions(-) 22 1 file changed, 4 insertions(+), 2 deletions(-)
23 23
24diff --git a/clientloop.c b/clientloop.c 24diff --git a/clientloop.c b/clientloop.c
25index 73a800c..4bc5b57 100644 25index 046ca8b..0180774 100644
26--- a/clientloop.c 26--- a/clientloop.c
27+++ b/clientloop.c 27+++ b/clientloop.c
28@@ -1717,8 +1717,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id) 28@@ -1705,8 +1705,10 @@ client_loop(int have_pty, int escape_char_arg, int ssh2_chan_id)
29 exit_status = 0; 29 exit_status = 0;
30 } 30 }
31 31
diff --git a/debian/patches/restore-tcp-wrappers.patch b/debian/patches/restore-tcp-wrappers.patch
new file mode 100644
index 000000000..c590f52ce
--- /dev/null
+++ b/debian/patches/restore-tcp-wrappers.patch
@@ -0,0 +1,172 @@
1From b25d6dd3b6b5a2cb93723586c56d6fa0277ea56a Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org>
3Date: Tue, 7 Oct 2014 13:22:41 +0100
4Subject: Restore TCP wrappers support
5
6Support for TCP wrappers was dropped in OpenSSH 6.7. See this message
7and thread:
8
9 https://lists.mindrot.org/pipermail/openssh-unix-dev/2014-April/032497.html
10
11It is true that this reduces preauth attack surface in sshd. On the
12other hand, this support seems to be quite widely used, and abruptly
13dropping it (from the perspective of users who don't read
14openssh-unix-dev) could easily cause more serious problems in practice.
15
16It's not entirely clear what the right long-term answer for Debian is,
17but it at least probably doesn't involve dropping this feature shortly
18before a freeze.
19
20Forwarded: not-needed
21Last-Update: 2014-10-07
22
23Patch-Name: restore-tcp-wrappers.patch
24---
25 configure.ac | 57 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++
26 sshd.8 | 7 +++++++
27 sshd.c | 25 +++++++++++++++++++++++++
28 3 files changed, 89 insertions(+)
29
30diff --git a/configure.ac b/configure.ac
31index 90e81e1..7f160f1 100644
32--- a/configure.ac
33+++ b/configure.ac
34@@ -1404,6 +1404,62 @@ AC_ARG_WITH([skey],
35 ]
36 )
37
38+# Check whether user wants TCP wrappers support
39+TCPW_MSG="no"
40+AC_ARG_WITH([tcp-wrappers],
41+ [ --with-tcp-wrappers[[=PATH]] Enable tcpwrappers support (optionally in PATH)],
42+ [
43+ if test "x$withval" != "xno" ; then
44+ saved_LIBS="$LIBS"
45+ saved_LDFLAGS="$LDFLAGS"
46+ saved_CPPFLAGS="$CPPFLAGS"
47+ if test -n "${withval}" && \
48+ test "x${withval}" != "xyes"; then
49+ if test -d "${withval}/lib"; then
50+ if test -n "${need_dash_r}"; then
51+ LDFLAGS="-L${withval}/lib -R${withval}/lib ${LDFLAGS}"
52+ else
53+ LDFLAGS="-L${withval}/lib ${LDFLAGS}"
54+ fi
55+ else
56+ if test -n "${need_dash_r}"; then
57+ LDFLAGS="-L${withval} -R${withval} ${LDFLAGS}"
58+ else
59+ LDFLAGS="-L${withval} ${LDFLAGS}"
60+ fi
61+ fi
62+ if test -d "${withval}/include"; then
63+ CPPFLAGS="-I${withval}/include ${CPPFLAGS}"
64+ else
65+ CPPFLAGS="-I${withval} ${CPPFLAGS}"
66+ fi
67+ fi
68+ LIBS="-lwrap $LIBS"
69+ AC_MSG_CHECKING([for libwrap])
70+ AC_LINK_IFELSE([AC_LANG_PROGRAM([[
71+#include <sys/types.h>
72+#include <sys/socket.h>
73+#include <netinet/in.h>
74+#include <tcpd.h>
75+int deny_severity = 0, allow_severity = 0;
76+ ]], [[
77+ hosts_access(0);
78+ ]])], [
79+ AC_MSG_RESULT([yes])
80+ AC_DEFINE([LIBWRAP], [1],
81+ [Define if you want
82+ TCP Wrappers support])
83+ SSHDLIBS="$SSHDLIBS -lwrap"
84+ TCPW_MSG="yes"
85+ ], [
86+ AC_MSG_ERROR([*** libwrap missing])
87+
88+ ])
89+ LIBS="$saved_LIBS"
90+ fi
91+ ]
92+)
93+
94 # Check whether user wants to use ldns
95 LDNS_MSG="no"
96 AC_ARG_WITH(ldns,
97@@ -4853,6 +4909,7 @@ echo " KerberosV support: $KRB5_MSG"
98 echo " SELinux support: $SELINUX_MSG"
99 echo " Smartcard support: $SCARD_MSG"
100 echo " S/KEY support: $SKEY_MSG"
101+echo " TCP Wrappers support: $TCPW_MSG"
102 echo " MD5 password support: $MD5_MSG"
103 echo " libedit support: $LIBEDIT_MSG"
104 echo " Solaris process contract support: $SPC_MSG"
105diff --git a/sshd.8 b/sshd.8
106index 01459d6..eaeac45 100644
107--- a/sshd.8
108+++ b/sshd.8
109@@ -851,6 +851,12 @@ the user's home directory becomes accessible.
110 This file should be writable only by the user, and need not be
111 readable by anyone else.
112 .Pp
113+.It Pa /etc/hosts.allow
114+.It Pa /etc/hosts.deny
115+Access controls that should be enforced by tcp-wrappers are defined here.
116+Further details are described in
117+.Xr hosts_access 5 .
118+.Pp
119 .It Pa /etc/hosts.equiv
120 This file is for host-based authentication (see
121 .Xr ssh 1 ) .
122@@ -954,6 +960,7 @@ The content of this file is not sensitive; it can be world-readable.
123 .Xr ssh-keygen 1 ,
124 .Xr ssh-keyscan 1 ,
125 .Xr chroot 2 ,
126+.Xr hosts_access 5 ,
127 .Xr login.conf 5 ,
128 .Xr moduli 5 ,
129 .Xr sshd_config 5 ,
130diff --git a/sshd.c b/sshd.c
131index e6706a8..3a6be65 100644
132--- a/sshd.c
133+++ b/sshd.c
134@@ -127,6 +127,13 @@
135 #include <Security/AuthSession.h>
136 #endif
137
138+#ifdef LIBWRAP
139+#include <tcpd.h>
140+#include <syslog.h>
141+int allow_severity;
142+int deny_severity;
143+#endif /* LIBWRAP */
144+
145 #ifndef O_NOCTTY
146 #define O_NOCTTY 0
147 #endif
148@@ -2061,6 +2068,24 @@ main(int ac, char **av)
149 #ifdef SSH_AUDIT_EVENTS
150 audit_connection_from(remote_ip, remote_port);
151 #endif
152+#ifdef LIBWRAP
153+ allow_severity = options.log_facility|LOG_INFO;
154+ deny_severity = options.log_facility|LOG_WARNING;
155+ /* Check whether logins are denied from this host. */
156+ if (packet_connection_is_on_socket()) {
157+ struct request_info req;
158+
159+ request_init(&req, RQ_DAEMON, __progname, RQ_FILE, sock_in, 0);
160+ fromhost(&req);
161+
162+ if (!hosts_access(&req)) {
163+ debug("Connection refused by tcp wrapper");
164+ refuse(&req);
165+ /* NOTREACHED */
166+ fatal("libwrap refuse returns");
167+ }
168+ }
169+#endif /* LIBWRAP */
170
171 /* Log the connection. */
172 verbose("Connection from %s port %d on %s port %d",
diff --git a/debian/patches/scp-quoting.patch b/debian/patches/scp-quoting.patch
index ff037a43a..ee006da93 100644
--- a/debian/patches/scp-quoting.patch
+++ b/debian/patches/scp-quoting.patch
@@ -1,4 +1,4 @@
1From 8ab204ee192e655d5a8f4d599adb3d99eeabedc6 Mon Sep 17 00:00:00 2001 1From fd174c13c46191abdb33c0a45545573a8e06b061 Mon Sep 17 00:00:00 2001
2From: =?UTF-8?q?Nicolas=20Valc=C3=A1rcel?= <nvalcarcel@ubuntu.com> 2From: =?UTF-8?q?Nicolas=20Valc=C3=A1rcel?= <nvalcarcel@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:09:59 +0000 3Date: Sun, 9 Feb 2014 16:09:59 +0000
4Subject: Adjust scp quoting in verbose mode 4Subject: Adjust scp quoting in verbose mode
@@ -17,7 +17,7 @@ Patch-Name: scp-quoting.patch
17 1 file changed, 10 insertions(+), 2 deletions(-) 17 1 file changed, 10 insertions(+), 2 deletions(-)
18 18
19diff --git a/scp.c b/scp.c 19diff --git a/scp.c b/scp.c
20index 18d3b1d..0669d02 100644 20index 1ec3b70..a1b318b 100644
21--- a/scp.c 21--- a/scp.c
22+++ b/scp.c 22+++ b/scp.c
23@@ -189,8 +189,16 @@ do_local_cmd(arglist *a) 23@@ -189,8 +189,16 @@ do_local_cmd(arglist *a)
diff --git a/debian/patches/selinux-role.patch b/debian/patches/selinux-role.patch
index e0ca12fb0..1fa0bf928 100644
--- a/debian/patches/selinux-role.patch
+++ b/debian/patches/selinux-role.patch
@@ -1,4 +1,4 @@
1From ae32d626ed3d15cfd7f432358b63c005961921df Mon Sep 17 00:00:00 2001 1From c9638aa44d787849cea1ae273f0908c6313fd19b Mon Sep 17 00:00:00 2001
2From: Manoj Srivastava <srivasta@debian.org> 2From: Manoj Srivastava <srivasta@debian.org>
3Date: Sun, 9 Feb 2014 16:09:49 +0000 3Date: Sun, 9 Feb 2014 16:09:49 +0000
4Subject: Handle SELinux authorisation roles 4Subject: Handle SELinux authorisation roles
@@ -32,7 +32,7 @@ Patch-Name: selinux-role.patch
32 16 files changed, 104 insertions(+), 31 deletions(-) 32 16 files changed, 104 insertions(+), 31 deletions(-)
33 33
34diff --git a/auth.h b/auth.h 34diff --git a/auth.h b/auth.h
35index 124e597..79e4ea5 100644 35index d081c94..f099e98 100644
36--- a/auth.h 36--- a/auth.h
37+++ b/auth.h 37+++ b/auth.h
38@@ -59,6 +59,7 @@ struct Authctxt { 38@@ -59,6 +59,7 @@ struct Authctxt {
@@ -44,10 +44,10 @@ index 124e597..79e4ea5 100644
44 char *info; /* Extra info for next auth_log */ 44 char *info; /* Extra info for next auth_log */
45 #ifdef BSD_AUTH 45 #ifdef BSD_AUTH
46diff --git a/auth1.c b/auth1.c 46diff --git a/auth1.c b/auth1.c
47index 0f870b3..c707390 100644 47index 5038828..52b17db 100644
48--- a/auth1.c 48--- a/auth1.c
49+++ b/auth1.c 49+++ b/auth1.c
50@@ -380,7 +380,7 @@ void 50@@ -381,7 +381,7 @@ void
51 do_authentication(Authctxt *authctxt) 51 do_authentication(Authctxt *authctxt)
52 { 52 {
53 u_int ulen; 53 u_int ulen;
@@ -56,7 +56,7 @@ index 0f870b3..c707390 100644
56 56
57 /* Get the name of the user that we wish to log in as. */ 57 /* Get the name of the user that we wish to log in as. */
58 packet_read_expect(SSH_CMSG_USER); 58 packet_read_expect(SSH_CMSG_USER);
59@@ -389,11 +389,17 @@ do_authentication(Authctxt *authctxt) 59@@ -390,11 +390,17 @@ do_authentication(Authctxt *authctxt)
60 user = packet_get_cstring(&ulen); 60 user = packet_get_cstring(&ulen);
61 packet_check_eom(); 61 packet_check_eom();
62 62
@@ -75,10 +75,10 @@ index 0f870b3..c707390 100644
75 /* Verify that the user is a valid user. */ 75 /* Verify that the user is a valid user. */
76 if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL) 76 if ((authctxt->pw = PRIVSEP(getpwnamallow(user))) != NULL)
77diff --git a/auth2.c b/auth2.c 77diff --git a/auth2.c b/auth2.c
78index fbe3e1b..70f2925 100644 78index 2f0d565..fa1a588 100644
79--- a/auth2.c 79--- a/auth2.c
80+++ b/auth2.c 80+++ b/auth2.c
81@@ -216,7 +216,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) 81@@ -217,7 +217,7 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
82 { 82 {
83 Authctxt *authctxt = ctxt; 83 Authctxt *authctxt = ctxt;
84 Authmethod *m = NULL; 84 Authmethod *m = NULL;
@@ -87,7 +87,7 @@ index fbe3e1b..70f2925 100644
87 int authenticated = 0; 87 int authenticated = 0;
88 88
89 if (authctxt == NULL) 89 if (authctxt == NULL)
90@@ -228,8 +228,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) 90@@ -229,8 +229,13 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
91 debug("userauth-request for user %s service %s method %s", user, service, method); 91 debug("userauth-request for user %s service %s method %s", user, service, method);
92 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures); 92 debug("attempt %d failures %d", authctxt->attempt, authctxt->failures);
93 93
@@ -101,7 +101,7 @@ index fbe3e1b..70f2925 100644
101 101
102 if (authctxt->attempt++ == 0) { 102 if (authctxt->attempt++ == 0) {
103 /* setup auth context */ 103 /* setup auth context */
104@@ -253,8 +258,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt) 104@@ -254,8 +259,9 @@ input_userauth_request(int type, u_int32_t seq, void *ctxt)
105 use_privsep ? " [net]" : ""); 105 use_privsep ? " [net]" : "");
106 authctxt->service = xstrdup(service); 106 authctxt->service = xstrdup(service);
107 authctxt->style = style ? xstrdup(style) : NULL; 107 authctxt->style = style ? xstrdup(style) : NULL;
@@ -113,10 +113,10 @@ index fbe3e1b..70f2925 100644
113 if (auth2_setup_methods_lists(authctxt) != 0) 113 if (auth2_setup_methods_lists(authctxt) != 0)
114 packet_disconnect("no authentication methods enabled"); 114 packet_disconnect("no authentication methods enabled");
115diff --git a/monitor.c b/monitor.c 115diff --git a/monitor.c b/monitor.c
116index 2918814..11eac63 100644 116index b0896ef..94b194d 100644
117--- a/monitor.c 117--- a/monitor.c
118+++ b/monitor.c 118+++ b/monitor.c
119@@ -145,6 +145,7 @@ int mm_answer_sign(int, Buffer *); 119@@ -148,6 +148,7 @@ int mm_answer_sign(int, Buffer *);
120 int mm_answer_pwnamallow(int, Buffer *); 120 int mm_answer_pwnamallow(int, Buffer *);
121 int mm_answer_auth2_read_banner(int, Buffer *); 121 int mm_answer_auth2_read_banner(int, Buffer *);
122 int mm_answer_authserv(int, Buffer *); 122 int mm_answer_authserv(int, Buffer *);
@@ -124,7 +124,7 @@ index 2918814..11eac63 100644
124 int mm_answer_authpassword(int, Buffer *); 124 int mm_answer_authpassword(int, Buffer *);
125 int mm_answer_bsdauthquery(int, Buffer *); 125 int mm_answer_bsdauthquery(int, Buffer *);
126 int mm_answer_bsdauthrespond(int, Buffer *); 126 int mm_answer_bsdauthrespond(int, Buffer *);
127@@ -221,6 +222,7 @@ struct mon_table mon_dispatch_proto20[] = { 127@@ -229,6 +230,7 @@ struct mon_table mon_dispatch_proto20[] = {
128 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 128 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
129 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 129 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
130 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 130 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
@@ -132,7 +132,7 @@ index 2918814..11eac63 100644
132 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner}, 132 {MONITOR_REQ_AUTH2_READ_BANNER, MON_ONCE, mm_answer_auth2_read_banner},
133 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword}, 133 {MONITOR_REQ_AUTHPASSWORD, MON_AUTH, mm_answer_authpassword},
134 #ifdef USE_PAM 134 #ifdef USE_PAM
135@@ -822,6 +824,7 @@ mm_answer_pwnamallow(int sock, Buffer *m) 135@@ -841,6 +843,7 @@ mm_answer_pwnamallow(int sock, Buffer *m)
136 else { 136 else {
137 /* Allow service/style information on the auth context */ 137 /* Allow service/style information on the auth context */
138 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1); 138 monitor_permit(mon_dispatch, MONITOR_REQ_AUTHSERV, 1);
@@ -140,7 +140,7 @@ index 2918814..11eac63 100644
140 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1); 140 monitor_permit(mon_dispatch, MONITOR_REQ_AUTH2_READ_BANNER, 1);
141 } 141 }
142 #ifdef USE_PAM 142 #ifdef USE_PAM
143@@ -852,14 +855,37 @@ mm_answer_authserv(int sock, Buffer *m) 143@@ -871,14 +874,37 @@ mm_answer_authserv(int sock, Buffer *m)
144 144
145 authctxt->service = buffer_get_string(m, NULL); 145 authctxt->service = buffer_get_string(m, NULL);
146 authctxt->style = buffer_get_string(m, NULL); 146 authctxt->style = buffer_get_string(m, NULL);
@@ -180,7 +180,7 @@ index 2918814..11eac63 100644
180 return (0); 180 return (0);
181 } 181 }
182 182
183@@ -1464,7 +1490,7 @@ mm_answer_pty(int sock, Buffer *m) 183@@ -1485,7 +1511,7 @@ mm_answer_pty(int sock, Buffer *m)
184 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty)); 184 res = pty_allocate(&s->ptyfd, &s->ttyfd, s->tty, sizeof(s->tty));
185 if (res == 0) 185 if (res == 0)
186 goto error; 186 goto error;
@@ -203,10 +203,10 @@ index 7f32b0c..4d5e8fa 100644
203 203
204 struct mm_master; 204 struct mm_master;
205diff --git a/monitor_wrap.c b/monitor_wrap.c 205diff --git a/monitor_wrap.c b/monitor_wrap.c
206index 60b987d..f75dc9d 100644 206index e476f0d..6dc890a 100644
207--- a/monitor_wrap.c 207--- a/monitor_wrap.c
208+++ b/monitor_wrap.c 208+++ b/monitor_wrap.c
209@@ -318,10 +318,10 @@ mm_auth2_read_banner(void) 209@@ -324,10 +324,10 @@ mm_auth2_read_banner(void)
210 return (banner); 210 return (banner);
211 } 211 }
212 212
@@ -219,7 +219,7 @@ index 60b987d..f75dc9d 100644
219 { 219 {
220 Buffer m; 220 Buffer m;
221 221
222@@ -330,12 +330,30 @@ mm_inform_authserv(char *service, char *style) 222@@ -336,12 +336,30 @@ mm_inform_authserv(char *service, char *style)
223 buffer_init(&m); 223 buffer_init(&m);
224 buffer_put_cstring(&m, service); 224 buffer_put_cstring(&m, service);
225 buffer_put_cstring(&m, style ? style : ""); 225 buffer_put_cstring(&m, style ? style : "");
@@ -361,10 +361,10 @@ index e3d1004..80ce13a 100644
361 void ssh_selinux_setfscreatecon(const char *); 361 void ssh_selinux_setfscreatecon(const char *);
362 #endif 362 #endif
363diff --git a/platform.c b/platform.c 363diff --git a/platform.c b/platform.c
364index 30fc609..4aab9a9 100644 364index ee313da..f35ec39 100644
365--- a/platform.c 365--- a/platform.c
366+++ b/platform.c 366+++ b/platform.c
367@@ -142,7 +142,7 @@ platform_setusercontext(struct passwd *pw) 367@@ -143,7 +143,7 @@ platform_setusercontext(struct passwd *pw)
368 * called if sshd is running as root. 368 * called if sshd is running as root.
369 */ 369 */
370 void 370 void
@@ -373,7 +373,7 @@ index 30fc609..4aab9a9 100644
373 { 373 {
374 #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM) 374 #if !defined(HAVE_LOGIN_CAP) && defined(USE_PAM)
375 /* 375 /*
376@@ -183,7 +183,7 @@ platform_setusercontext_post_groups(struct passwd *pw) 376@@ -184,7 +184,7 @@ platform_setusercontext_post_groups(struct passwd *pw)
377 } 377 }
378 #endif /* HAVE_SETPCRED */ 378 #endif /* HAVE_SETPCRED */
379 #ifdef WITH_SELINUX 379 #ifdef WITH_SELINUX
@@ -396,10 +396,10 @@ index 1c7a45d..436ae7c 100644
396 char *platform_krb5_get_principal_name(const char *); 396 char *platform_krb5_get_principal_name(const char *);
397 int platform_sys_dir_uid(uid_t); 397 int platform_sys_dir_uid(uid_t);
398diff --git a/session.c b/session.c 398diff --git a/session.c b/session.c
399index 2bcf818..6848df4 100644 399index 3e96557..6f389ac 100644
400--- a/session.c 400--- a/session.c
401+++ b/session.c 401+++ b/session.c
402@@ -1502,7 +1502,7 @@ safely_chroot(const char *path, uid_t uid) 402@@ -1486,7 +1486,7 @@ safely_chroot(const char *path, uid_t uid)
403 403
404 /* Set login name, uid, gid, and groups. */ 404 /* Set login name, uid, gid, and groups. */
405 void 405 void
@@ -407,8 +407,8 @@ index 2bcf818..6848df4 100644
407+do_setusercontext(struct passwd *pw, const char *role) 407+do_setusercontext(struct passwd *pw, const char *role)
408 { 408 {
409 char *chroot_path, *tmp; 409 char *chroot_path, *tmp;
410 410 #ifdef USE_LIBIAF
411@@ -1530,7 +1530,7 @@ do_setusercontext(struct passwd *pw) 411@@ -1517,7 +1517,7 @@ do_setusercontext(struct passwd *pw)
412 endgrent(); 412 endgrent();
413 #endif 413 #endif
414 414
@@ -417,7 +417,7 @@ index 2bcf818..6848df4 100644
417 417
418 if (options.chroot_directory != NULL && 418 if (options.chroot_directory != NULL &&
419 strcasecmp(options.chroot_directory, "none") != 0) { 419 strcasecmp(options.chroot_directory, "none") != 0) {
420@@ -1679,7 +1679,7 @@ do_child(Session *s, const char *command) 420@@ -1676,7 +1676,7 @@ do_child(Session *s, const char *command)
421 421
422 /* Force a password change */ 422 /* Force a password change */
423 if (s->authctxt->force_pwchange) { 423 if (s->authctxt->force_pwchange) {
@@ -426,7 +426,7 @@ index 2bcf818..6848df4 100644
426 child_close_fds(); 426 child_close_fds();
427 do_pwchange(s); 427 do_pwchange(s);
428 exit(1); 428 exit(1);
429@@ -1706,7 +1706,7 @@ do_child(Session *s, const char *command) 429@@ -1703,7 +1703,7 @@ do_child(Session *s, const char *command)
430 /* When PAM is enabled we rely on it to do the nologin check */ 430 /* When PAM is enabled we rely on it to do the nologin check */
431 if (!options.use_pam) 431 if (!options.use_pam)
432 do_nologin(pw); 432 do_nologin(pw);
@@ -435,7 +435,7 @@ index 2bcf818..6848df4 100644
435 /* 435 /*
436 * PAM session modules in do_setusercontext may have 436 * PAM session modules in do_setusercontext may have
437 * generated messages, so if this in an interactive 437 * generated messages, so if this in an interactive
438@@ -2117,7 +2117,7 @@ session_pty_req(Session *s) 438@@ -2114,7 +2114,7 @@ session_pty_req(Session *s)
439 tty_parse_modes(s->ttyfd, &n_bytes); 439 tty_parse_modes(s->ttyfd, &n_bytes);
440 440
441 if (!use_privsep) 441 if (!use_privsep)
@@ -458,10 +458,10 @@ index 6a2f35e..ef6593c 100644
458 const char *value); 458 const char *value);
459 459
460diff --git a/sshd.c b/sshd.c 460diff --git a/sshd.c b/sshd.c
461index d787fea..e343d90 100644 461index 3a6be65..48a14dd 100644
462--- a/sshd.c 462--- a/sshd.c
463+++ b/sshd.c 463+++ b/sshd.c
464@@ -769,7 +769,7 @@ privsep_postauth(Authctxt *authctxt) 464@@ -772,7 +772,7 @@ privsep_postauth(Authctxt *authctxt)
465 explicit_bzero(rnd, sizeof(rnd)); 465 explicit_bzero(rnd, sizeof(rnd));
466 466
467 /* Drop privileges */ 467 /* Drop privileges */
@@ -471,10 +471,10 @@ index d787fea..e343d90 100644
471 skip: 471 skip:
472 /* It is safe now to apply the key state */ 472 /* It is safe now to apply the key state */
473diff --git a/sshpty.c b/sshpty.c 473diff --git a/sshpty.c b/sshpty.c
474index bbbc0fe..8cc26a2 100644 474index a2059b7..3512ec8 100644
475--- a/sshpty.c 475--- a/sshpty.c
476+++ b/sshpty.c 476+++ b/sshpty.c
477@@ -200,7 +200,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col, 477@@ -187,7 +187,7 @@ pty_change_window_size(int ptyfd, u_int row, u_int col,
478 } 478 }
479 479
480 void 480 void
@@ -483,7 +483,7 @@ index bbbc0fe..8cc26a2 100644
483 { 483 {
484 struct group *grp; 484 struct group *grp;
485 gid_t gid; 485 gid_t gid;
486@@ -227,7 +227,7 @@ pty_setowner(struct passwd *pw, const char *tty) 486@@ -214,7 +214,7 @@ pty_setowner(struct passwd *pw, const char *tty)
487 strerror(errno)); 487 strerror(errno));
488 488
489 #ifdef WITH_SELINUX 489 #ifdef WITH_SELINUX
diff --git a/debian/patches/series b/debian/patches/series
index c554b34ca..bbc7a5fb4 100644
--- a/debian/patches/series
+++ b/debian/patches/series
@@ -1,4 +1,5 @@
1gssapi.patch 1gssapi.patch
2restore-tcp-wrappers.patch
2selinux-role.patch 3selinux-role.patch
3ssh-vulnkey-compat.patch 4ssh-vulnkey-compat.patch
4ssh1-keepalive.patch 5ssh1-keepalive.patch
@@ -22,9 +23,7 @@ ssh-argv0.patch
22doc-hash-tab-completion.patch 23doc-hash-tab-completion.patch
23doc-upstart.patch 24doc-upstart.patch
24ssh-agent-setgid.patch 25ssh-agent-setgid.patch
25no-openssl-version-check.patch 26no-openssl-version-status.patch
26gnome-ssh-askpass2-icon.patch 27gnome-ssh-askpass2-icon.patch
27sigstop.patch 28sigstop.patch
28debian-config.patch 29debian-config.patch
29sshfp_with_server_cert_upstr
30curve25519-sha256-bignum-encoding.patch
diff --git a/debian/patches/shell-path.patch b/debian/patches/shell-path.patch
index 48c16d2a2..07e20f03d 100644
--- a/debian/patches/shell-path.patch
+++ b/debian/patches/shell-path.patch
@@ -1,4 +1,4 @@
1From 6103c29d855e82c098e88ee12f05a6eb41f659ce Mon Sep 17 00:00:00 2001 1From 66377fbb52584b41bd7f6f19116107fbbad41058 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:00 +0000 3Date: Sun, 9 Feb 2014 16:10:00 +0000
4Subject: Look for $SHELL on the path for ProxyCommand/LocalCommand 4Subject: Look for $SHELL on the path for ProxyCommand/LocalCommand
@@ -16,10 +16,10 @@ Patch-Name: shell-path.patch
16 1 file changed, 2 insertions(+), 2 deletions(-) 16 1 file changed, 2 insertions(+), 2 deletions(-)
17 17
18diff --git a/sshconnect.c b/sshconnect.c 18diff --git a/sshconnect.c b/sshconnect.c
19index 573d7a8..9e02837 100644 19index ac09eae..26116d2 100644
20--- a/sshconnect.c 20--- a/sshconnect.c
21+++ b/sshconnect.c 21+++ b/sshconnect.c
22@@ -227,7 +227,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command) 22@@ -228,7 +228,7 @@ ssh_proxy_connect(const char *host, u_short port, const char *proxy_command)
23 /* Execute the proxy command. Note that we gave up any 23 /* Execute the proxy command. Note that we gave up any
24 extra privileges above. */ 24 extra privileges above. */
25 signal(SIGPIPE, SIG_DFL); 25 signal(SIGPIPE, SIG_DFL);
@@ -28,7 +28,7 @@ index 573d7a8..9e02837 100644
28 perror(argv[0]); 28 perror(argv[0]);
29 exit(1); 29 exit(1);
30 } 30 }
31@@ -1387,7 +1387,7 @@ ssh_local_cmd(const char *args) 31@@ -1416,7 +1416,7 @@ ssh_local_cmd(const char *args)
32 if (pid == 0) { 32 if (pid == 0) {
33 signal(SIGPIPE, SIG_DFL); 33 signal(SIGPIPE, SIG_DFL);
34 debug3("Executing %s -c \"%s\"", shell, args); 34 debug3("Executing %s -c \"%s\"", shell, args);
diff --git a/debian/patches/sigstop.patch b/debian/patches/sigstop.patch
index 6a15e0dc5..1eaa7758b 100644
--- a/debian/patches/sigstop.patch
+++ b/debian/patches/sigstop.patch
@@ -1,4 +1,4 @@
1From cfeaa0ba2ce2859573f7e980be09ef05511f56a2 Mon Sep 17 00:00:00 2001 1From 689f465c66059e527974c6d4ea8e95f04d5abab7 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:17 +0000 3Date: Sun, 9 Feb 2014 16:10:17 +0000
4Subject: Support synchronisation with service supervisor using SIGSTOP 4Subject: Support synchronisation with service supervisor using SIGSTOP
@@ -13,10 +13,10 @@ Patch-Name: sigstop.patch
13 1 file changed, 10 insertions(+) 13 1 file changed, 10 insertions(+)
14 14
15diff --git a/sshd.c b/sshd.c 15diff --git a/sshd.c b/sshd.c
16index 665c0b9..0964491 100644 16index 87331c1..23d5a64 100644
17--- a/sshd.c 17--- a/sshd.c
18+++ b/sshd.c 18+++ b/sshd.c
19@@ -1931,6 +1931,16 @@ main(int ac, char **av) 19@@ -1958,6 +1958,16 @@ main(int ac, char **av)
20 } 20 }
21 } 21 }
22 22
diff --git a/debian/patches/ssh-agent-setgid.patch b/debian/patches/ssh-agent-setgid.patch
index af23075b3..9c3ddc86e 100644
--- a/debian/patches/ssh-agent-setgid.patch
+++ b/debian/patches/ssh-agent-setgid.patch
@@ -1,4 +1,4 @@
1From d53483ab71ac2a9195c8f171da5a5dcf54ec16ec Mon Sep 17 00:00:00 2001 1From 78dd041bb6ad29ceb35f05b539b09ccf761eaee2 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:13 +0000 3Date: Sun, 9 Feb 2014 16:10:13 +0000
4Subject: Document consequences of ssh-agent being setgid in ssh-agent(1) 4Subject: Document consequences of ssh-agent being setgid in ssh-agent(1)
@@ -13,10 +13,10 @@ Patch-Name: ssh-agent-setgid.patch
13 1 file changed, 15 insertions(+) 13 1 file changed, 15 insertions(+)
14 14
15diff --git a/ssh-agent.1 b/ssh-agent.1 15diff --git a/ssh-agent.1 b/ssh-agent.1
16index 281ecbd..38fd540 100644 16index a1e634f..f2c4080 100644
17--- a/ssh-agent.1 17--- a/ssh-agent.1
18+++ b/ssh-agent.1 18+++ b/ssh-agent.1
19@@ -183,6 +183,21 @@ environment variable holds the agent's process ID. 19@@ -172,6 +172,21 @@ environment variable holds the agent's process ID.
20 .Pp 20 .Pp
21 The agent exits automatically when the command given on the command 21 The agent exits automatically when the command given on the command
22 line terminates. 22 line terminates.
@@ -37,4 +37,4 @@ index 281ecbd..38fd540 100644
37+so in the program executed by ssh-agent. 37+so in the program executed by ssh-agent.
38 .Sh FILES 38 .Sh FILES
39 .Bl -tag -width Ds 39 .Bl -tag -width Ds
40 .It Pa ~/.ssh/identity 40 .It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
diff --git a/debian/patches/ssh-argv0.patch b/debian/patches/ssh-argv0.patch
index d456facea..0ccf7c42b 100644
--- a/debian/patches/ssh-argv0.patch
+++ b/debian/patches/ssh-argv0.patch
@@ -1,4 +1,4 @@
1From d4ac61d918775f629eff9a389d0f7bb0f8426b48 Mon Sep 17 00:00:00 2001 1From cbd5cb03866f6df50c82d26588b73135d05bf245 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:10:10 +0000 3Date: Sun, 9 Feb 2014 16:10:10 +0000
4Subject: ssh(1): Refer to ssh-argv0(1) 4Subject: ssh(1): Refer to ssh-argv0(1)
@@ -18,10 +18,10 @@ Patch-Name: ssh-argv0.patch
18 1 file changed, 1 insertion(+) 18 1 file changed, 1 insertion(+)
19 19
20diff --git a/ssh.1 b/ssh.1 20diff --git a/ssh.1 b/ssh.1
21index 67b4f44..9868025 100644 21index de178cd..2606b15 100644
22--- a/ssh.1 22--- a/ssh.1
23+++ b/ssh.1 23+++ b/ssh.1
24@@ -1468,6 +1468,7 @@ if an error occurred. 24@@ -1458,6 +1458,7 @@ if an error occurred.
25 .Xr sftp 1 , 25 .Xr sftp 1 ,
26 .Xr ssh-add 1 , 26 .Xr ssh-add 1 ,
27 .Xr ssh-agent 1 , 27 .Xr ssh-agent 1 ,
diff --git a/debian/patches/ssh-vulnkey-compat.patch b/debian/patches/ssh-vulnkey-compat.patch
index fa738b084..427ee6be1 100644
--- a/debian/patches/ssh-vulnkey-compat.patch
+++ b/debian/patches/ssh-vulnkey-compat.patch
@@ -1,4 +1,4 @@
1From d422205e757aaf23e8e0e787f842ef37f6a170a2 Mon Sep 17 00:00:00 2001 1From e6836d7c98c75d3252de56c2f3ea07e12c817e00 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@ubuntu.com> 2From: Colin Watson <cjwatson@ubuntu.com>
3Date: Sun, 9 Feb 2014 16:09:50 +0000 3Date: Sun, 9 Feb 2014 16:09:50 +0000
4Subject: Accept obsolete ssh-vulnkey configuration options 4Subject: Accept obsolete ssh-vulnkey configuration options
@@ -17,10 +17,10 @@ Patch-Name: ssh-vulnkey-compat.patch
17 2 files changed, 2 insertions(+) 17 2 files changed, 2 insertions(+)
18 18
19diff --git a/readconf.c b/readconf.c 19diff --git a/readconf.c b/readconf.c
20index 7613ff2..bcd8cad 100644 20index 9127e93..bc879eb 100644
21--- a/readconf.c 21--- a/readconf.c
22+++ b/readconf.c 22+++ b/readconf.c
23@@ -172,6 +172,7 @@ static struct { 23@@ -174,6 +174,7 @@ static struct {
24 { "passwordauthentication", oPasswordAuthentication }, 24 { "passwordauthentication", oPasswordAuthentication },
25 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication }, 25 { "kbdinteractiveauthentication", oKbdInteractiveAuthentication },
26 { "kbdinteractivedevices", oKbdInteractiveDevices }, 26 { "kbdinteractivedevices", oKbdInteractiveDevices },
@@ -29,10 +29,10 @@ index 7613ff2..bcd8cad 100644
29 { "pubkeyauthentication", oPubkeyAuthentication }, 29 { "pubkeyauthentication", oPubkeyAuthentication },
30 { "dsaauthentication", oPubkeyAuthentication }, /* alias */ 30 { "dsaauthentication", oPubkeyAuthentication }, /* alias */
31diff --git a/servconf.c b/servconf.c 31diff --git a/servconf.c b/servconf.c
32index 0083cf8..90de888 100644 32index cb3c831..a252487 100644
33--- a/servconf.c 33--- a/servconf.c
34+++ b/servconf.c 34+++ b/servconf.c
35@@ -448,6 +448,7 @@ static struct { 35@@ -462,6 +462,7 @@ static struct {
36 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL }, 36 { "x11uselocalhost", sX11UseLocalhost, SSHCFG_ALL },
37 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL }, 37 { "xauthlocation", sXAuthLocation, SSHCFG_GLOBAL },
38 { "strictmodes", sStrictModes, SSHCFG_GLOBAL }, 38 { "strictmodes", sStrictModes, SSHCFG_GLOBAL },
diff --git a/debian/patches/ssh1-keepalive.patch b/debian/patches/ssh1-keepalive.patch
index ded7c122a..2e5fa306d 100644
--- a/debian/patches/ssh1-keepalive.patch
+++ b/debian/patches/ssh1-keepalive.patch
@@ -1,4 +1,4 @@
1From 789d58ed3df120c7b80d07fb2d259c216194a29c Mon Sep 17 00:00:00 2001 1From cbbc8577950b93090171c7394bcdeb68b7c3cd0c Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:09:51 +0000 3Date: Sun, 9 Feb 2014 16:09:51 +0000
4Subject: Partial server keep-alive implementation for SSH1 4Subject: Partial server keep-alive implementation for SSH1
@@ -13,7 +13,7 @@ Patch-Name: ssh1-keepalive.patch
13 2 files changed, 19 insertions(+), 11 deletions(-) 13 2 files changed, 19 insertions(+), 11 deletions(-)
14 14
15diff --git a/clientloop.c b/clientloop.c 15diff --git a/clientloop.c b/clientloop.c
16index 6d8cd7d..73a800c 100644 16index f9175e3..046ca8b 100644
17--- a/clientloop.c 17--- a/clientloop.c
18+++ b/clientloop.c 18+++ b/clientloop.c
19@@ -563,16 +563,21 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt) 19@@ -563,16 +563,21 @@ client_global_request_reply(int type, u_int32_t seq, void *ctxt)
@@ -57,10 +57,10 @@ index 6d8cd7d..73a800c 100644
57 server_alive_time = now + options.server_alive_interval; 57 server_alive_time = now + options.server_alive_interval;
58 } 58 }
59diff --git a/ssh_config.5 b/ssh_config.5 59diff --git a/ssh_config.5 b/ssh_config.5
60index e7accd6..473971e 100644 60index e6649ac..01f1f7f 100644
61--- a/ssh_config.5 61--- a/ssh_config.5
62+++ b/ssh_config.5 62+++ b/ssh_config.5
63@@ -1294,7 +1294,10 @@ If, for example, 63@@ -1325,7 +1325,10 @@ If, for example,
64 .Cm ServerAliveCountMax 64 .Cm ServerAliveCountMax
65 is left at the default, if the server becomes unresponsive, 65 is left at the default, if the server becomes unresponsive,
66 ssh will disconnect after approximately 45 seconds. 66 ssh will disconnect after approximately 45 seconds.
diff --git a/debian/patches/sshfp_with_server_cert_upstr b/debian/patches/sshfp_with_server_cert_upstr
deleted file mode 100644
index b453081c5..000000000
--- a/debian/patches/sshfp_with_server_cert_upstr
+++ /dev/null
@@ -1,83 +0,0 @@
1From 08a63152deb5deda168aaef870bdb9f56425acb3 Mon Sep 17 00:00:00 2001
2From: Matthew Vernon <mcv21@cam.ac.uk>
3Date: Wed, 26 Mar 2014 15:32:23 +0000
4Subject: Attempt SSHFP lookup even if server presents a certificate
5
6If an ssh server presents a certificate to the client, then the client
7does not check the DNS for SSHFP records. This means that a malicious
8server can essentially disable DNS-host-key-checking, which means the
9client will fall back to asking the user (who will just say "yes" to
10the fingerprint, sadly).
11
12This patch is by Damien Miller (of openssh upstream). It's simpler
13than the patch by Mark Wooding which I applied yesterday; a copy is
14taken of the proffered key/cert, the key extracted from the cert (if
15necessary), and then the DNS consulted.
16
17Signed-off-by: Matthew Vernon <matthew@debian.org>
18Bug-Debian: http://bugs.debian.org/742513
19Patch-Name: sshfp_with_server_cert_upstr
20---
21 sshconnect.c | 42 ++++++++++++++++++++++++++----------------
22 1 file changed, 26 insertions(+), 16 deletions(-)
23
24diff --git a/sshconnect.c b/sshconnect.c
25index 87c3770..324f5e0 100644
26--- a/sshconnect.c
27+++ b/sshconnect.c
28@@ -1224,29 +1224,39 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
29 {
30 int flags = 0;
31 char *fp;
32+ Key *plain = NULL;
33
34 fp = key_fingerprint(host_key, SSH_FP_MD5, SSH_FP_HEX);
35 debug("Server host key: %s %s", key_type(host_key), fp);
36 free(fp);
37
38- /* XXX certs are not yet supported for DNS */
39- if (!key_is_cert(host_key) && options.verify_host_key_dns &&
40- verify_host_key_dns(host, hostaddr, host_key, &flags) == 0) {
41- if (flags & DNS_VERIFY_FOUND) {
42-
43- if (options.verify_host_key_dns == 1 &&
44- flags & DNS_VERIFY_MATCH &&
45- flags & DNS_VERIFY_SECURE)
46- return 0;
47-
48- if (flags & DNS_VERIFY_MATCH) {
49- matching_host_key_dns = 1;
50- } else {
51- warn_changed_key(host_key);
52- error("Update the SSHFP RR in DNS with the new "
53- "host key to get rid of this message.");
54+ if (options.verify_host_key_dns) {
55+ /*
56+ * XXX certs are not yet supported for DNS, so downgrade
57+ * them and try the plain key.
58+ */
59+ plain = key_from_private(host_key);
60+ if (key_is_cert(plain))
61+ key_drop_cert(plain);
62+ if (verify_host_key_dns(host, hostaddr, plain, &flags) == 0) {
63+ if (flags & DNS_VERIFY_FOUND) {
64+ if (options.verify_host_key_dns == 1 &&
65+ flags & DNS_VERIFY_MATCH &&
66+ flags & DNS_VERIFY_SECURE) {
67+ key_free(plain);
68+ return 0;
69+ }
70+ if (flags & DNS_VERIFY_MATCH) {
71+ matching_host_key_dns = 1;
72+ } else {
73+ warn_changed_key(plain);
74+ error("Update the SSHFP RR in DNS "
75+ "with the new host key to get rid "
76+ "of this message.");
77+ }
78 }
79 }
80+ key_free(plain);
81 }
82
83 return check_host_key(host, hostaddr, options.port, host_key, RDRW,
diff --git a/debian/patches/syslog-level-silent.patch b/debian/patches/syslog-level-silent.patch
index 7cbd3a7e3..bfc236927 100644
--- a/debian/patches/syslog-level-silent.patch
+++ b/debian/patches/syslog-level-silent.patch
@@ -1,4 +1,4 @@
1From b8ed36cdf2dbebc01e52e83eece4bb1d78607e84 Mon Sep 17 00:00:00 2001 1From 69f7c00e04d1baa01a9038eeb764cfed0830fb19 Mon Sep 17 00:00:00 2001
2From: Jonathan David Amery <jdamery@ysolde.ucam.org> 2From: Jonathan David Amery <jdamery@ysolde.ucam.org>
3Date: Sun, 9 Feb 2014 16:09:54 +0000 3Date: Sun, 9 Feb 2014 16:09:54 +0000
4Subject: "LogLevel SILENT" compatibility 4Subject: "LogLevel SILENT" compatibility
@@ -33,10 +33,10 @@ index 32e1d2e..53e7b65 100644
33 { "FATAL", SYSLOG_LEVEL_FATAL }, 33 { "FATAL", SYSLOG_LEVEL_FATAL },
34 { "ERROR", SYSLOG_LEVEL_ERROR }, 34 { "ERROR", SYSLOG_LEVEL_ERROR },
35diff --git a/ssh.c b/ssh.c 35diff --git a/ssh.c b/ssh.c
36index 1e6cb90..3e63708 100644 36index 26e9681..5bce695 100644
37--- a/ssh.c 37--- a/ssh.c
38+++ b/ssh.c 38+++ b/ssh.c
39@@ -965,7 +965,7 @@ main(int ac, char **av) 39@@ -989,7 +989,7 @@ main(int ac, char **av)
40 /* Do not allocate a tty if stdin is not a tty. */ 40 /* Do not allocate a tty if stdin is not a tty. */
41 if ((!isatty(fileno(stdin)) || stdin_null_flag) && 41 if ((!isatty(fileno(stdin)) || stdin_null_flag) &&
42 options.request_tty != REQUEST_TTY_FORCE) { 42 options.request_tty != REQUEST_TTY_FORCE) {
diff --git a/debian/patches/user-group-modes.patch b/debian/patches/user-group-modes.patch
index 3cdb9d8a1..e4e4657f3 100644
--- a/debian/patches/user-group-modes.patch
+++ b/debian/patches/user-group-modes.patch
@@ -1,4 +1,4 @@
1From 77638f6662ecd8500e1b97e537233b1277ca829f Mon Sep 17 00:00:00 2001 1From 28ea747089f695e58a476a2849133402d4f86b92 Mon Sep 17 00:00:00 2001
2From: Colin Watson <cjwatson@debian.org> 2From: Colin Watson <cjwatson@debian.org>
3Date: Sun, 9 Feb 2014 16:09:58 +0000 3Date: Sun, 9 Feb 2014 16:09:58 +0000
4Subject: Allow harmless group-writability 4Subject: Allow harmless group-writability
@@ -28,7 +28,7 @@ Patch-Name: user-group-modes.patch
28 8 files changed, 82 insertions(+), 29 deletions(-) 28 8 files changed, 82 insertions(+), 29 deletions(-)
29 29
30diff --git a/auth-rhosts.c b/auth-rhosts.c 30diff --git a/auth-rhosts.c b/auth-rhosts.c
31index 06ae7f0..f202787 100644 31index b5bedee..11fcca6 100644
32--- a/auth-rhosts.c 32--- a/auth-rhosts.c
33+++ b/auth-rhosts.c 33+++ b/auth-rhosts.c
34@@ -256,8 +256,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam 34@@ -256,8 +256,7 @@ auth_rhosts2_raw(struct passwd *pw, const char *client_user, const char *hostnam
@@ -52,10 +52,10 @@ index 06ae7f0..f202787 100644
52 pw->pw_name, buf); 52 pw->pw_name, buf);
53 auth_debug_add("Bad file modes for %.200s", buf); 53 auth_debug_add("Bad file modes for %.200s", buf);
54diff --git a/auth.c b/auth.c 54diff --git a/auth.c b/auth.c
55index 9a36f1d..0c45f09 100644 55index 5e60682..18de51a 100644
56--- a/auth.c 56--- a/auth.c
57+++ b/auth.c 57+++ b/auth.c
58@@ -407,8 +407,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host, 58@@ -421,8 +421,7 @@ check_key_in_hostfiles(struct passwd *pw, Key *key, const char *host,
59 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid); 59 user_hostfile = tilde_expand_filename(userfile, pw->pw_uid);
60 if (options.strict_modes && 60 if (options.strict_modes &&
61 (stat(user_hostfile, &st) == 0) && 61 (stat(user_hostfile, &st) == 0) &&
@@ -65,7 +65,7 @@ index 9a36f1d..0c45f09 100644
65 logit("Authentication refused for %.100s: " 65 logit("Authentication refused for %.100s: "
66 "bad owner or modes for %.200s", 66 "bad owner or modes for %.200s",
67 pw->pw_name, user_hostfile); 67 pw->pw_name, user_hostfile);
68@@ -470,8 +469,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, 68@@ -484,8 +483,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
69 snprintf(err, errlen, "%s is not a regular file", buf); 69 snprintf(err, errlen, "%s is not a regular file", buf);
70 return -1; 70 return -1;
71 } 71 }
@@ -75,7 +75,7 @@ index 9a36f1d..0c45f09 100644
75 snprintf(err, errlen, "bad ownership or modes for file %s", 75 snprintf(err, errlen, "bad ownership or modes for file %s",
76 buf); 76 buf);
77 return -1; 77 return -1;
78@@ -486,8 +484,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir, 78@@ -500,8 +498,7 @@ auth_secure_path(const char *name, struct stat *stp, const char *pw_dir,
79 strlcpy(buf, cp, sizeof(buf)); 79 strlcpy(buf, cp, sizeof(buf));
80 80
81 if (stat(buf, &st) < 0 || 81 if (stat(buf, &st) < 0 ||
@@ -86,10 +86,10 @@ index 9a36f1d..0c45f09 100644
86 "bad ownership or modes for directory %s", buf); 86 "bad ownership or modes for directory %s", buf);
87 return -1; 87 return -1;
88diff --git a/misc.c b/misc.c 88diff --git a/misc.c b/misc.c
89index e4c8c32..4e756b0 100644 89index 94b05b0..c25ccd8 100644
90--- a/misc.c 90--- a/misc.c
91+++ b/misc.c 91+++ b/misc.c
92@@ -49,8 +49,9 @@ 92@@ -50,8 +50,9 @@
93 #include <netdb.h> 93 #include <netdb.h>
94 #ifdef HAVE_PATHS_H 94 #ifdef HAVE_PATHS_H
95 # include <paths.h> 95 # include <paths.h>
@@ -100,7 +100,7 @@ index e4c8c32..4e756b0 100644
100 #ifdef SSH_TUN_OPENBSD 100 #ifdef SSH_TUN_OPENBSD
101 #include <net/if.h> 101 #include <net/if.h>
102 #endif 102 #endif
103@@ -59,6 +60,7 @@ 103@@ -60,6 +61,7 @@
104 #include "misc.h" 104 #include "misc.h"
105 #include "log.h" 105 #include "log.h"
106 #include "ssh.h" 106 #include "ssh.h"
@@ -108,7 +108,7 @@ index e4c8c32..4e756b0 100644
108 108
109 /* remove newline at end of string */ 109 /* remove newline at end of string */
110 char * 110 char *
111@@ -643,6 +645,71 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz, 111@@ -644,6 +646,71 @@ read_keyfile_line(FILE *f, const char *filename, char *buf, size_t bufsz,
112 return -1; 112 return -1;
113 } 113 }
114 114
@@ -181,10 +181,10 @@ index e4c8c32..4e756b0 100644
181 tun_open(int tun, int mode) 181 tun_open(int tun, int mode)
182 { 182 {
183diff --git a/misc.h b/misc.h 183diff --git a/misc.h b/misc.h
184index d4df619..ceb173b 100644 184index 374c33c..89e1f75 100644
185--- a/misc.h 185--- a/misc.h
186+++ b/misc.h 186+++ b/misc.h
187@@ -106,4 +106,6 @@ char *read_passphrase(const char *, int); 187@@ -135,4 +135,6 @@ char *read_passphrase(const char *, int);
188 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2))); 188 int ask_permission(const char *, ...) __attribute__((format(printf, 1, 2)));
189 int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *); 189 int read_keyfile_line(FILE *, const char *, char *, size_t, u_long *);
190 190
@@ -192,10 +192,10 @@ index d4df619..ceb173b 100644
192+ 192+
193 #endif /* _MISC_H */ 193 #endif /* _MISC_H */
194diff --git a/platform.c b/platform.c 194diff --git a/platform.c b/platform.c
195index 4aab9a9..f99de7f 100644 195index f35ec39..9a23e6e 100644
196--- a/platform.c 196--- a/platform.c
197+++ b/platform.c 197+++ b/platform.c
198@@ -196,19 +196,3 @@ platform_krb5_get_principal_name(const char *pw_name) 198@@ -197,19 +197,3 @@ platform_krb5_get_principal_name(const char *pw_name)
199 return NULL; 199 return NULL;
200 #endif 200 #endif
201 } 201 }
@@ -216,10 +216,10 @@ index 4aab9a9..f99de7f 100644
216- return 0; 216- return 0;
217-} 217-}
218diff --git a/readconf.c b/readconf.c 218diff --git a/readconf.c b/readconf.c
219index 6409937..32c4b42 100644 219index 337818c..0648867 100644
220--- a/readconf.c 220--- a/readconf.c
221+++ b/readconf.c 221+++ b/readconf.c
222@@ -37,6 +37,8 @@ 222@@ -38,6 +38,8 @@
223 #include <stdio.h> 223 #include <stdio.h>
224 #include <string.h> 224 #include <string.h>
225 #include <unistd.h> 225 #include <unistd.h>
@@ -228,7 +228,7 @@ index 6409937..32c4b42 100644
228 #ifdef HAVE_UTIL_H 228 #ifdef HAVE_UTIL_H
229 #include <util.h> 229 #include <util.h>
230 #endif 230 #endif
231@@ -1477,8 +1479,7 @@ read_config_file(const char *filename, struct passwd *pw, const char *host, 231@@ -1516,8 +1518,7 @@ read_config_file(const char *filename, struct passwd *pw, const char *host,
232 232
233 if (fstat(fileno(f), &sb) == -1) 233 if (fstat(fileno(f), &sb) == -1)
234 fatal("fstat %s: %s", filename, strerror(errno)); 234 fatal("fstat %s: %s", filename, strerror(errno));
@@ -239,10 +239,10 @@ index 6409937..32c4b42 100644
239 } 239 }
240 240
241diff --git a/ssh.1 b/ssh.1 241diff --git a/ssh.1 b/ssh.1
242index 27794e2..ff5e6ac 100644 242index fa5cfb2..7f6ab77 100644
243--- a/ssh.1 243--- a/ssh.1
244+++ b/ssh.1 244+++ b/ssh.1
245@@ -1352,6 +1352,8 @@ The file format and configuration options are described in 245@@ -1342,6 +1342,8 @@ The file format and configuration options are described in
246 .Xr ssh_config 5 . 246 .Xr ssh_config 5 .
247 Because of the potential for abuse, this file must have strict permissions: 247 Because of the potential for abuse, this file must have strict permissions:
248 read/write for the user, and not writable by others. 248 read/write for the user, and not writable by others.
@@ -252,10 +252,10 @@ index 27794e2..ff5e6ac 100644
252 .It Pa ~/.ssh/environment 252 .It Pa ~/.ssh/environment
253 Contains additional definitions for environment variables; see 253 Contains additional definitions for environment variables; see
254diff --git a/ssh_config.5 b/ssh_config.5 254diff --git a/ssh_config.5 b/ssh_config.5
255index 3172fd4..4bf7cbb 100644 255index ea92ea8..d68b45a 100644
256--- a/ssh_config.5 256--- a/ssh_config.5
257+++ b/ssh_config.5 257+++ b/ssh_config.5
258@@ -1529,6 +1529,8 @@ The format of this file is described above. 258@@ -1587,6 +1587,8 @@ The format of this file is described above.
259 This file is used by the SSH client. 259 This file is used by the SSH client.
260 Because of the potential for abuse, this file must have strict permissions: 260 Because of the potential for abuse, this file must have strict permissions:
261 read/write for the user, and not accessible by others. 261 read/write for the user, and not accessible by others.
diff --git a/defines.h b/defines.h
index 354d5b614..3ac8be987 100644
--- a/defines.h
+++ b/defines.h
@@ -25,7 +25,7 @@
25#ifndef _DEFINES_H 25#ifndef _DEFINES_H
26#define _DEFINES_H 26#define _DEFINES_H
27 27
28/* $Id: defines.h,v 1.176 2014/01/17 13:12:38 dtucker Exp $ */ 28/* $Id: defines.h,v 1.183 2014/09/02 19:33:26 djm Exp $ */
29 29
30 30
31/* Constants */ 31/* Constants */
@@ -405,7 +405,7 @@ struct winsize {
405 405
406/* user may have set a different path */ 406/* user may have set a different path */
407#if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) 407#if defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY)
408# undef _PATH_MAILDIR MAILDIR 408# undef _PATH_MAILDIR
409#endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */ 409#endif /* defined(_PATH_MAILDIR) && defined(MAIL_DIRECTORY) */
410 410
411#ifdef MAIL_DIRECTORY 411#ifdef MAIL_DIRECTORY
@@ -603,10 +603,6 @@ struct winsize {
603# define memmove(s1, s2, n) bcopy((s2), (s1), (n)) 603# define memmove(s1, s2, n) bcopy((s2), (s1), (n))
604#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */ 604#endif /* !defined(HAVE_MEMMOVE) && defined(HAVE_BCOPY) */
605 605
606#if defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX)
607# define USE_VHANGUP
608#endif /* defined(HAVE_VHANGUP) && !defined(HAVE_DEV_PTMX) */
609
610#ifndef GETPGRP_VOID 606#ifndef GETPGRP_VOID
611# include <unistd.h> 607# include <unistd.h>
612# define getpgrp() getpgrp(0) 608# define getpgrp() getpgrp(0)
@@ -826,4 +822,23 @@ struct winsize {
826# define arc4random_stir() 822# define arc4random_stir()
827#endif 823#endif
828 824
825#ifndef HAVE_VA_COPY
826# ifdef HAVE___VA_COPY
827# define va_copy(dest, src) __va_copy(dest, src)
828# else
829# define va_copy(dest, src) (dest) = (src)
830# endif
831#endif
832
833#ifndef __predict_true
834# if defined(__GNUC__) && \
835 ((__GNUC__ > (2)) || (__GNUC__ == (2) && __GNUC_MINOR__ >= (96)))
836# define __predict_true(exp) __builtin_expect(((exp) != 0), 1)
837# define __predict_false(exp) __builtin_expect(((exp) != 0), 0)
838# else
839# define __predict_true(exp) ((exp) != 0)
840# define __predict_false(exp) ((exp) != 0)
841# endif /* gcc version */
842#endif /* __predict_true */
843
829#endif /* _DEFINES_H */ 844#endif /* _DEFINES_H */
diff --git a/digest-libc.c b/digest-libc.c
index 1804b0698..1b4423a05 100644
--- a/digest-libc.c
+++ b/digest-libc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: digest-libc.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: digest-libc.c,v 1.3 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * Copyright (c) 2014 Markus Friedl. All rights reserved. 4 * Copyright (c) 2014 Markus Friedl. All rights reserved.
@@ -28,7 +28,8 @@
28#include <sha1.h> 28#include <sha1.h>
29#include <sha2.h> 29#include <sha2.h>
30 30
31#include "buffer.h" 31#include "ssherr.h"
32#include "sshbuf.h"
32#include "digest.h" 33#include "digest.h"
33 34
34typedef void md_init_fn(void *mdctx); 35typedef void md_init_fn(void *mdctx);
@@ -164,7 +165,7 @@ ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
164 const struct ssh_digest *digest = ssh_digest_by_alg(from->alg); 165 const struct ssh_digest *digest = ssh_digest_by_alg(from->alg);
165 166
166 if (digest == NULL || from->alg != to->alg) 167 if (digest == NULL || from->alg != to->alg)
167 return -1; 168 return SSH_ERR_INVALID_ARGUMENT;
168 memcpy(to->mdctx, from->mdctx, digest->ctx_len); 169 memcpy(to->mdctx, from->mdctx, digest->ctx_len);
169 return 0; 170 return 0;
170} 171}
@@ -175,15 +176,15 @@ ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
175 const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); 176 const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
176 177
177 if (digest == NULL) 178 if (digest == NULL)
178 return -1; 179 return SSH_ERR_INVALID_ARGUMENT;
179 digest->md_update(ctx->mdctx, m, mlen); 180 digest->md_update(ctx->mdctx, m, mlen);
180 return 0; 181 return 0;
181} 182}
182 183
183int 184int
184ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) 185ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
185{ 186{
186 return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); 187 return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
187} 188}
188 189
189int 190int
@@ -192,11 +193,11 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
192 const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg); 193 const struct ssh_digest *digest = ssh_digest_by_alg(ctx->alg);
193 194
194 if (digest == NULL) 195 if (digest == NULL)
195 return -1; 196 return SSH_ERR_INVALID_ARGUMENT;
196 if (dlen > UINT_MAX) 197 if (dlen > UINT_MAX)
197 return -1; 198 return SSH_ERR_INVALID_ARGUMENT;
198 if (dlen < digest->digest_len) /* No truncation allowed */ 199 if (dlen < digest->digest_len) /* No truncation allowed */
199 return -1; 200 return SSH_ERR_INVALID_ARGUMENT;
200 digest->md_final(d, ctx->mdctx); 201 digest->md_final(d, ctx->mdctx);
201 return 0; 202 return 0;
202} 203}
@@ -223,16 +224,16 @@ ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
223 struct ssh_digest_ctx *ctx = ssh_digest_start(alg); 224 struct ssh_digest_ctx *ctx = ssh_digest_start(alg);
224 225
225 if (ctx == NULL) 226 if (ctx == NULL)
226 return -1; 227 return SSH_ERR_INVALID_ARGUMENT;
227 if (ssh_digest_update(ctx, m, mlen) != 0 || 228 if (ssh_digest_update(ctx, m, mlen) != 0 ||
228 ssh_digest_final(ctx, d, dlen) != 0) 229 ssh_digest_final(ctx, d, dlen) != 0)
229 return -1; 230 return SSH_ERR_INVALID_ARGUMENT;
230 ssh_digest_free(ctx); 231 ssh_digest_free(ctx);
231 return 0; 232 return 0;
232} 233}
233 234
234int 235int
235ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) 236ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
236{ 237{
237 return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); 238 return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
238} 239}
diff --git a/digest-openssl.c b/digest-openssl.c
index 863d37d03..02b170341 100644
--- a/digest-openssl.c
+++ b/digest-openssl.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: digest-openssl.c,v 1.2 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: digest-openssl.c,v 1.4 2014/07/03 03:26:43 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -26,8 +26,18 @@
26 26
27#include "openbsd-compat/openssl-compat.h" 27#include "openbsd-compat/openssl-compat.h"
28 28
29#include "buffer.h" 29#include "sshbuf.h"
30#include "digest.h" 30#include "digest.h"
31#include "ssherr.h"
32
33#ifndef HAVE_EVP_RIPEMD160
34# define EVP_ripemd160 NULL
35#endif /* HAVE_EVP_RIPEMD160 */
36#ifndef HAVE_EVP_SHA256
37# define EVP_sha256 NULL
38# define EVP_sha384 NULL
39# define EVP_sha512 NULL
40#endif /* HAVE_EVP_SHA256 */
31 41
32struct ssh_digest_ctx { 42struct ssh_digest_ctx {
33 int alg; 43 int alg;
@@ -46,11 +56,9 @@ const struct ssh_digest digests[] = {
46 { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 }, 56 { SSH_DIGEST_MD5, "MD5", 16, EVP_md5 },
47 { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 }, 57 { SSH_DIGEST_RIPEMD160, "RIPEMD160", 20, EVP_ripemd160 },
48 { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 }, 58 { SSH_DIGEST_SHA1, "SHA1", 20, EVP_sha1 },
49#ifdef HAVE_EVP_SHA256 /* XXX replace with local if missing */
50 { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 }, 59 { SSH_DIGEST_SHA256, "SHA256", 32, EVP_sha256 },
51 { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 }, 60 { SSH_DIGEST_SHA384, "SHA384", 48, EVP_sha384 },
52 { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 }, 61 { SSH_DIGEST_SHA512, "SHA512", 64, EVP_sha512 },
53#endif
54 { -1, NULL, 0, NULL }, 62 { -1, NULL, 0, NULL },
55}; 63};
56 64
@@ -61,6 +69,8 @@ ssh_digest_by_alg(int alg)
61 return NULL; 69 return NULL;
62 if (digests[alg].id != alg) /* sanity */ 70 if (digests[alg].id != alg) /* sanity */
63 return NULL; 71 return NULL;
72 if (digests[alg].mdfunc == NULL)
73 return NULL;
64 return &(digests[alg]); 74 return &(digests[alg]);
65} 75}
66 76
@@ -98,9 +108,11 @@ ssh_digest_start(int alg)
98int 108int
99ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to) 109ssh_digest_copy_state(struct ssh_digest_ctx *from, struct ssh_digest_ctx *to)
100{ 110{
111 if (from->alg != to->alg)
112 return SSH_ERR_INVALID_ARGUMENT;
101 /* we have bcopy-style order while openssl has memcpy-style */ 113 /* we have bcopy-style order while openssl has memcpy-style */
102 if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx)) 114 if (!EVP_MD_CTX_copy_ex(&to->mdctx, &from->mdctx))
103 return -1; 115 return SSH_ERR_LIBCRYPTO_ERROR;
104 return 0; 116 return 0;
105} 117}
106 118
@@ -108,14 +120,14 @@ int
108ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) 120ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
109{ 121{
110 if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1) 122 if (EVP_DigestUpdate(&ctx->mdctx, m, mlen) != 1)
111 return -1; 123 return SSH_ERR_LIBCRYPTO_ERROR;
112 return 0; 124 return 0;
113} 125}
114 126
115int 127int
116ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b) 128ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const struct sshbuf *b)
117{ 129{
118 return ssh_digest_update(ctx, buffer_ptr(b), buffer_len(b)); 130 return ssh_digest_update(ctx, sshbuf_ptr(b), sshbuf_len(b));
119} 131}
120 132
121int 133int
@@ -125,13 +137,13 @@ ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
125 u_int l = dlen; 137 u_int l = dlen;
126 138
127 if (dlen > UINT_MAX) 139 if (dlen > UINT_MAX)
128 return -1; 140 return SSH_ERR_INVALID_ARGUMENT;
129 if (dlen < digest->digest_len) /* No truncation allowed */ 141 if (dlen < digest->digest_len) /* No truncation allowed */
130 return -1; 142 return SSH_ERR_INVALID_ARGUMENT;
131 if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1) 143 if (EVP_DigestFinal_ex(&ctx->mdctx, d, &l) != 1)
132 return -1; 144 return SSH_ERR_LIBCRYPTO_ERROR;
133 if (l != digest->digest_len) /* sanity */ 145 if (l != digest->digest_len) /* sanity */
134 return -1; 146 return SSH_ERR_INTERNAL_ERROR;
135 return 0; 147 return 0;
136} 148}
137 149
@@ -148,19 +160,23 @@ ssh_digest_free(struct ssh_digest_ctx *ctx)
148int 160int
149ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen) 161ssh_digest_memory(int alg, const void *m, size_t mlen, u_char *d, size_t dlen)
150{ 162{
151 struct ssh_digest_ctx *ctx = ssh_digest_start(alg); 163 const struct ssh_digest *digest = ssh_digest_by_alg(alg);
152 164 u_int mdlen;
153 if (ctx == NULL) 165
154 return -1; 166 if (digest == NULL)
155 if (ssh_digest_update(ctx, m, mlen) != 0 || 167 return SSH_ERR_INVALID_ARGUMENT;
156 ssh_digest_final(ctx, d, dlen) != 0) 168 if (dlen > UINT_MAX)
157 return -1; 169 return SSH_ERR_INVALID_ARGUMENT;
158 ssh_digest_free(ctx); 170 if (dlen < digest->digest_len)
171 return SSH_ERR_INVALID_ARGUMENT;
172 mdlen = dlen;
173 if (!EVP_Digest(m, mlen, d, &mdlen, digest->mdfunc(), NULL))
174 return SSH_ERR_LIBCRYPTO_ERROR;
159 return 0; 175 return 0;
160} 176}
161 177
162int 178int
163ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) 179ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
164{ 180{
165 return ssh_digest_memory(alg, buffer_ptr(b), buffer_len(b), d, dlen); 181 return ssh_digest_memory(alg, sshbuf_ptr(b), sshbuf_len(b), d, dlen);
166} 182}
diff --git a/digest.h b/digest.h
index 0fb207fca..6afb197f0 100644
--- a/digest.h
+++ b/digest.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: digest.h,v 1.2 2014/01/27 18:58:14 markus Exp $ */ 1/* $OpenBSD: digest.h,v 1.6 2014/07/03 04:36:45 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2013 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -30,6 +30,7 @@
30#define SSH_DIGEST_SHA512 5 30#define SSH_DIGEST_SHA512 5
31#define SSH_DIGEST_MAX 6 31#define SSH_DIGEST_MAX 6
32 32
33struct sshbuf;
33struct ssh_digest_ctx; 34struct ssh_digest_ctx;
34 35
35/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ 36/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
@@ -47,14 +48,15 @@ int ssh_digest_memory(int alg, const void *m, size_t mlen,
47 u_char *d, size_t dlen) 48 u_char *d, size_t dlen)
48 __attribute__((__bounded__(__buffer__, 2, 3))) 49 __attribute__((__bounded__(__buffer__, 2, 3)))
49 __attribute__((__bounded__(__buffer__, 4, 5))); 50 __attribute__((__bounded__(__buffer__, 4, 5)));
50int ssh_digest_buffer(int alg, const Buffer *b, u_char *d, size_t dlen) 51int ssh_digest_buffer(int alg, const struct sshbuf *b, u_char *d, size_t dlen)
51 __attribute__((__bounded__(__buffer__, 3, 4))); 52 __attribute__((__bounded__(__buffer__, 3, 4)));
52 53
53/* Update API */ 54/* Update API */
54struct ssh_digest_ctx *ssh_digest_start(int alg); 55struct ssh_digest_ctx *ssh_digest_start(int alg);
55int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen) 56int ssh_digest_update(struct ssh_digest_ctx *ctx, const void *m, size_t mlen)
56 __attribute__((__bounded__(__buffer__, 2, 3))); 57 __attribute__((__bounded__(__buffer__, 2, 3)));
57int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx, const Buffer *b); 58int ssh_digest_update_buffer(struct ssh_digest_ctx *ctx,
59 const struct sshbuf *b);
58int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen) 60int ssh_digest_final(struct ssh_digest_ctx *ctx, u_char *d, size_t dlen)
59 __attribute__((__bounded__(__buffer__, 2, 3))); 61 __attribute__((__bounded__(__buffer__, 2, 3)));
60void ssh_digest_free(struct ssh_digest_ctx *ctx); 62void ssh_digest_free(struct ssh_digest_ctx *ctx);
diff --git a/dns.c b/dns.c
index 478c3d9c5..e5872c190 100644
--- a/dns.c
+++ b/dns.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: dns.c,v 1.29 2013/05/17 00:13:13 djm Exp $ */ 1/* $OpenBSD: dns.c,v 1.31 2014/06/24 01:13:21 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wesley Griffin. All rights reserved. 4 * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -34,6 +34,8 @@
34#include <stdarg.h> 34#include <stdarg.h>
35#include <stdio.h> 35#include <stdio.h>
36#include <string.h> 36#include <string.h>
37#include <stdarg.h>
38#include <stdlib.h>
37 39
38#include "xmalloc.h" 40#include "xmalloc.h"
39#include "key.h" 41#include "key.h"
@@ -96,6 +98,11 @@ dns_read_key(u_int8_t *algorithm, u_int8_t *digest_type,
96 if (!*digest_type) 98 if (!*digest_type)
97 *digest_type = SSHFP_HASH_SHA256; 99 *digest_type = SSHFP_HASH_SHA256;
98 break; 100 break;
101 case KEY_ED25519:
102 *algorithm = SSHFP_KEY_ED25519;
103 if (!*digest_type)
104 *digest_type = SSHFP_HASH_SHA256;
105 break;
99 default: 106 default:
100 *algorithm = SSHFP_KEY_RESERVED; /* 0 */ 107 *algorithm = SSHFP_KEY_RESERVED; /* 0 */
101 *digest_type = SSHFP_HASH_RESERVED; /* 0 */ 108 *digest_type = SSHFP_HASH_RESERVED; /* 0 */
diff --git a/dns.h b/dns.h
index d5f428177..b9feae6be 100644
--- a/dns.h
+++ b/dns.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: dns.h,v 1.12 2012/05/23 03:28:28 djm Exp $ */ 1/* $OpenBSD: dns.h,v 1.13 2014/04/20 09:24:26 logan Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2003 Wesley Griffin. All rights reserved. 4 * Copyright (c) 2003 Wesley Griffin. All rights reserved.
@@ -32,7 +32,8 @@ enum sshfp_types {
32 SSHFP_KEY_RESERVED = 0, 32 SSHFP_KEY_RESERVED = 0,
33 SSHFP_KEY_RSA = 1, 33 SSHFP_KEY_RSA = 1,
34 SSHFP_KEY_DSA = 2, 34 SSHFP_KEY_DSA = 2,
35 SSHFP_KEY_ECDSA = 3 35 SSHFP_KEY_ECDSA = 3,
36 SSHFP_KEY_ED25519 = 4
36}; 37};
37 38
38enum sshfp_hashes { 39enum sshfp_hashes {
diff --git a/entropy.c b/entropy.c
index 2aee2d917..1e9d52ac4 100644
--- a/entropy.c
+++ b/entropy.c
@@ -43,6 +43,8 @@
43#include <openssl/crypto.h> 43#include <openssl/crypto.h>
44#include <openssl/err.h> 44#include <openssl/err.h>
45 45
46#include "openbsd-compat/openssl-compat.h"
47
46#include "ssh.h" 48#include "ssh.h"
47#include "misc.h" 49#include "misc.h"
48#include "xmalloc.h" 50#include "xmalloc.h"
@@ -209,6 +211,9 @@ seed_rng(void)
209#ifndef OPENSSL_PRNG_ONLY 211#ifndef OPENSSL_PRNG_ONLY
210 unsigned char buf[RANDOM_SEED_SIZE]; 212 unsigned char buf[RANDOM_SEED_SIZE];
211#endif 213#endif
214 if (!ssh_compatible_openssl(OPENSSL_VERSION_NUMBER, SSLeay()))
215 fatal("OpenSSL version mismatch. Built against %lx, you "
216 "have %lx", (u_long)OPENSSL_VERSION_NUMBER, SSLeay());
212 217
213#ifndef OPENSSL_PRNG_ONLY 218#ifndef OPENSSL_PRNG_ONLY
214 if (RAND_status() == 1) { 219 if (RAND_status() == 1) {
diff --git a/gss-serv-krb5.c b/gss-serv-krb5.c
index e678a2757..fd8b37183 100644
--- a/gss-serv-krb5.c
+++ b/gss-serv-krb5.c
@@ -39,6 +39,7 @@
39#include "hostfile.h" 39#include "hostfile.h"
40#include "auth.h" 40#include "auth.h"
41#include "log.h" 41#include "log.h"
42#include "misc.h"
42#include "servconf.h" 43#include "servconf.h"
43 44
44#include "buffer.h" 45#include "buffer.h"
diff --git a/gss-serv.c b/gss-serv.c
index c33463bdf..50fa43834 100644
--- a/gss-serv.c
+++ b/gss-serv.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: gss-serv.c,v 1.26 2014/02/26 20:28:44 djm Exp $ */ 1/* $OpenBSD: gss-serv.c,v 1.27 2014/07/03 03:34:09 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved. 4 * Copyright (c) 2001-2009 Simon Wilkinson. All rights reserved.
@@ -103,14 +103,14 @@ static OM_uint32
103ssh_gssapi_acquire_cred(Gssctxt *ctx) 103ssh_gssapi_acquire_cred(Gssctxt *ctx)
104{ 104{
105 OM_uint32 status; 105 OM_uint32 status;
106 char lname[MAXHOSTNAMELEN]; 106 char lname[NI_MAXHOST];
107 gss_OID_set oidset; 107 gss_OID_set oidset;
108 108
109 if (options.gss_strict_acceptor) { 109 if (options.gss_strict_acceptor) {
110 gss_create_empty_oid_set(&status, &oidset); 110 gss_create_empty_oid_set(&status, &oidset);
111 gss_add_oid_set_member(&status, ctx->oid, &oidset); 111 gss_add_oid_set_member(&status, ctx->oid, &oidset);
112 112
113 if (gethostname(lname, MAXHOSTNAMELEN)) { 113 if (gethostname(lname, sizeof(lname))) {
114 gss_release_oid_set(&status, &oidset); 114 gss_release_oid_set(&status, &oidset);
115 return (-1); 115 return (-1);
116 } 116 }
diff --git a/hmac.h b/hmac.h
index 2374a6955..42b33d002 100644
--- a/hmac.h
+++ b/hmac.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: hmac.h,v 1.6 2014/01/27 18:58:14 markus Exp $ */ 1/* $OpenBSD: hmac.h,v 1.9 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2014 Markus Friedl. All rights reserved. 3 * Copyright (c) 2014 Markus Friedl. All rights reserved.
4 * 4 *
@@ -21,6 +21,7 @@
21/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */ 21/* Returns the algorithm's digest length in bytes or 0 for invalid algorithm */
22size_t ssh_hmac_bytes(int alg); 22size_t ssh_hmac_bytes(int alg);
23 23
24struct sshbuf;
24struct ssh_hmac_ctx; 25struct ssh_hmac_ctx;
25struct ssh_hmac_ctx *ssh_hmac_start(int alg); 26struct ssh_hmac_ctx *ssh_hmac_start(int alg);
26 27
@@ -29,7 +30,7 @@ int ssh_hmac_init(struct ssh_hmac_ctx *ctx, const void *key, size_t klen)
29 __attribute__((__bounded__(__buffer__, 2, 3))); 30 __attribute__((__bounded__(__buffer__, 2, 3)));
30int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen) 31int ssh_hmac_update(struct ssh_hmac_ctx *ctx, const void *m, size_t mlen)
31 __attribute__((__bounded__(__buffer__, 2, 3))); 32 __attribute__((__bounded__(__buffer__, 2, 3)));
32int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const Buffer *b); 33int ssh_hmac_update_buffer(struct ssh_hmac_ctx *ctx, const struct sshbuf *b);
33int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen) 34int ssh_hmac_final(struct ssh_hmac_ctx *ctx, u_char *d, size_t dlen)
34 __attribute__((__bounded__(__buffer__, 2, 3))); 35 __attribute__((__bounded__(__buffer__, 2, 3)));
35void ssh_hmac_free(struct ssh_hmac_ctx *ctx); 36void ssh_hmac_free(struct ssh_hmac_ctx *ctx);
diff --git a/hostfile.c b/hostfile.c
index 8bc9540b7..ee2daf45f 100644
--- a/hostfile.c
+++ b/hostfile.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: hostfile.c,v 1.55 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: hostfile.c,v 1.57 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -47,6 +47,7 @@
47#include <stdio.h> 47#include <stdio.h>
48#include <stdlib.h> 48#include <stdlib.h>
49#include <string.h> 49#include <string.h>
50#include <stdarg.h>
50 51
51#include "xmalloc.h" 52#include "xmalloc.h"
52#include "match.h" 53#include "match.h"
@@ -182,6 +183,7 @@ static int
182hostfile_check_key(int bits, const Key *key, const char *host, 183hostfile_check_key(int bits, const Key *key, const char *host,
183 const char *filename, u_long linenum) 184 const char *filename, u_long linenum)
184{ 185{
186#ifdef WITH_SSH1
185 if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL) 187 if (key == NULL || key->type != KEY_RSA1 || key->rsa == NULL)
186 return 1; 188 return 1;
187 if (bits != BN_num_bits(key->rsa->n)) { 189 if (bits != BN_num_bits(key->rsa->n)) {
@@ -191,6 +193,7 @@ hostfile_check_key(int bits, const Key *key, const char *host,
191 logit("Warning: replace %d with %d in %s, line %lu.", 193 logit("Warning: replace %d with %d in %s, line %lu.",
192 bits, BN_num_bits(key->rsa->n), filename, linenum); 194 bits, BN_num_bits(key->rsa->n), filename, linenum);
193 } 195 }
196#endif
194 return 1; 197 return 1;
195} 198}
196 199
@@ -296,11 +299,15 @@ load_hostkeys(struct hostkeys *hostkeys, const char *host, const char *path)
296 key = key_new(KEY_UNSPEC); 299 key = key_new(KEY_UNSPEC);
297 if (!hostfile_read_key(&cp, &kbits, key)) { 300 if (!hostfile_read_key(&cp, &kbits, key)) {
298 key_free(key); 301 key_free(key);
302#ifdef WITH_SSH1
299 key = key_new(KEY_RSA1); 303 key = key_new(KEY_RSA1);
300 if (!hostfile_read_key(&cp, &kbits, key)) { 304 if (!hostfile_read_key(&cp, &kbits, key)) {
301 key_free(key); 305 key_free(key);
302 continue; 306 continue;
303 } 307 }
308#else
309 continue;
310#endif
304 } 311 }
305 if (!hostfile_check_key(kbits, key, host, path, linenum)) 312 if (!hostfile_check_key(kbits, key, host, path, linenum))
306 continue; 313 continue;
diff --git a/kex.c b/kex.c
index d114ee3e0..891852b54 100644
--- a/kex.c
+++ b/kex.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.c,v 1.98 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: kex.c,v 1.99 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -33,7 +33,9 @@
33#include <stdlib.h> 33#include <stdlib.h>
34#include <string.h> 34#include <string.h>
35 35
36#ifdef WITH_OPENSSL
36#include <openssl/crypto.h> 37#include <openssl/crypto.h>
38#endif
37 39
38#include "xmalloc.h" 40#include "xmalloc.h"
39#include "ssh2.h" 41#include "ssh2.h"
@@ -74,12 +76,13 @@ struct kexalg {
74 int hash_alg; 76 int hash_alg;
75}; 77};
76static const struct kexalg kexalgs[] = { 78static const struct kexalg kexalgs[] = {
79#ifdef WITH_OPENSSL
77 { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 80 { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
78 { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 }, 81 { KEX_DH14, KEX_DH_GRP14_SHA1, 0, SSH_DIGEST_SHA1 },
79 { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 }, 82 { KEX_DHGEX_SHA1, KEX_DH_GEX_SHA1, 0, SSH_DIGEST_SHA1 },
80#ifdef HAVE_EVP_SHA256 83#ifdef HAVE_EVP_SHA256
81 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 }, 84 { KEX_DHGEX_SHA256, KEX_DH_GEX_SHA256, 0, SSH_DIGEST_SHA256 },
82#endif 85#endif /* HAVE_EVP_SHA256 */
83#ifdef OPENSSL_HAS_ECC 86#ifdef OPENSSL_HAS_ECC
84 { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2, 87 { KEX_ECDH_SHA2_NISTP256, KEX_ECDH_SHA2,
85 NID_X9_62_prime256v1, SSH_DIGEST_SHA256 }, 88 NID_X9_62_prime256v1, SSH_DIGEST_SHA256 },
@@ -88,12 +91,13 @@ static const struct kexalg kexalgs[] = {
88# ifdef OPENSSL_HAS_NISTP521 91# ifdef OPENSSL_HAS_NISTP521
89 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1, 92 { KEX_ECDH_SHA2_NISTP521, KEX_ECDH_SHA2, NID_secp521r1,
90 SSH_DIGEST_SHA512 }, 93 SSH_DIGEST_SHA512 },
91# endif 94# endif /* OPENSSL_HAS_NISTP521 */
92#endif 95#endif /* OPENSSL_HAS_ECC */
93 { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 }, 96 { KEX_DH1, KEX_DH_GRP1_SHA1, 0, SSH_DIGEST_SHA1 },
97#endif /* WITH_OPENSSL */
94#ifdef HAVE_EVP_SHA256 98#ifdef HAVE_EVP_SHA256
95 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 }, 99 { KEX_CURVE25519_SHA256, KEX_C25519_SHA256, 0, SSH_DIGEST_SHA256 },
96#endif 100#endif /* HAVE_EVP_SHA256 */
97 { NULL, -1, -1, -1}, 101 { NULL, -1, -1, -1},
98}; 102};
99static const struct kexalg kexalg_prefixes[] = { 103static const struct kexalg kexalg_prefixes[] = {
@@ -631,6 +635,7 @@ kex_derive_keys(Kex *kex, u_char *hash, u_int hashlen,
631 } 635 }
632} 636}
633 637
638#ifdef WITH_OPENSSL
634void 639void
635kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret) 640kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret)
636{ 641{
@@ -642,6 +647,7 @@ kex_derive_keys_bn(Kex *kex, u_char *hash, u_int hashlen, const BIGNUM *secret)
642 buffer_ptr(&shared_secret), buffer_len(&shared_secret)); 647 buffer_ptr(&shared_secret), buffer_len(&shared_secret));
643 buffer_free(&shared_secret); 648 buffer_free(&shared_secret);
644} 649}
650#endif
645 651
646Newkeys * 652Newkeys *
647kex_get_newkeys(int mode) 653kex_get_newkeys(int mode)
@@ -653,6 +659,7 @@ kex_get_newkeys(int mode)
653 return ret; 659 return ret;
654} 660}
655 661
662#ifdef WITH_SSH1
656void 663void
657derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus, 664derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
658 u_int8_t cookie[8], u_int8_t id[16]) 665 u_int8_t cookie[8], u_int8_t id[16])
@@ -685,6 +692,7 @@ derive_ssh1_session_id(BIGNUM *host_modulus, BIGNUM *server_modulus,
685 explicit_bzero(nbuf, sizeof(nbuf)); 692 explicit_bzero(nbuf, sizeof(nbuf));
686 explicit_bzero(obuf, sizeof(obuf)); 693 explicit_bzero(obuf, sizeof(obuf));
687} 694}
695#endif
688 696
689#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH) 697#if defined(DEBUG_KEX) || defined(DEBUG_KEXDH) || defined(DEBUG_KEXECDH)
690void 698void
diff --git a/kex.h b/kex.h
index ea698c467..c179a4d06 100644
--- a/kex.h
+++ b/kex.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: kex.h,v 1.62 2014/01/27 18:58:14 markus Exp $ */ 1/* $OpenBSD: kex.h,v 1.64 2014/05/02 03:27:54 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
diff --git a/kexc25519.c b/kexc25519.c
index ee79b4327..e3afa0055 100644
--- a/kexc25519.c
+++ b/kexc25519.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: kexc25519.c,v 1.5 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: kexc25519.c,v 1.7 2014/05/02 03:27:54 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001, 2013 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
diff --git a/kexgsss.c b/kexgsss.c
index 809525924..6a0ece84b 100644
--- a/kexgsss.c
+++ b/kexgsss.c
@@ -42,6 +42,7 @@
42#include "dh.h" 42#include "dh.h"
43#include "ssh-gss.h" 43#include "ssh-gss.h"
44#include "monitor_wrap.h" 44#include "monitor_wrap.h"
45#include "misc.h"
45#include "servconf.h" 46#include "servconf.h"
46 47
47extern ServerOptions options; 48extern ServerOptions options;
diff --git a/key.c b/key.c
index 3d640e79f..206076159 100644
--- a/key.c
+++ b/key.c
@@ -1,2090 +1,242 @@
1/* $OpenBSD: key.c,v 1.116 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: key.c,v 1.122 2014/07/22 01:18:50 dtucker Exp $ */
2/* 2/*
3 * read_bignum(): 3 * placed in the public domain
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 *
6 * As far as I am concerned, the code I have written for this software
7 * can be used freely for any purpose. Any derived versions of this
8 * software must be clearly marked as such, and if the derived work is
9 * incompatible with the protocol description in the RFC file, it must be
10 * called by a name other than "ssh" or "Secure Shell".
11 *
12 *
13 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
14 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
15 *
16 * Redistribution and use in source and binary forms, with or without
17 * modification, are permitted provided that the following conditions
18 * are met:
19 * 1. Redistributions of source code must retain the above copyright
20 * notice, this list of conditions and the following disclaimer.
21 * 2. Redistributions in binary form must reproduce the above copyright
22 * notice, this list of conditions and the following disclaimer in the
23 * documentation and/or other materials provided with the distribution.
24 *
25 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
26 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
27 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
28 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
29 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
30 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
31 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
32 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
33 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35 */ 4 */
36 5
37#include "includes.h" 6#include "includes.h"
38 7
39#include <sys/param.h> 8#include <sys/param.h>
40#include <sys/types.h> 9#include <sys/types.h>
41 10#include <errno.h>
42#include "crypto_api.h"
43
44#include <openssl/evp.h>
45#include <openbsd-compat/openssl-compat.h>
46
47#include <stdarg.h> 11#include <stdarg.h>
48#include <stdio.h> 12#include <stdio.h>
49#include <string.h>
50 13
51#include "xmalloc.h" 14#define SSH_KEY_NO_DEFINE
52#include "key.h" 15#include "key.h"
53#include "rsa.h"
54#include "uuencode.h"
55#include "buffer.h"
56#include "log.h"
57#include "misc.h"
58#include "ssh2.h"
59#include "digest.h"
60
61static int to_blob(const Key *, u_char **, u_int *, int);
62static Key *key_from_blob2(const u_char *, u_int, int);
63
64static struct KeyCert *
65cert_new(void)
66{
67 struct KeyCert *cert;
68
69 cert = xcalloc(1, sizeof(*cert));
70 buffer_init(&cert->certblob);
71 buffer_init(&cert->critical);
72 buffer_init(&cert->extensions);
73 cert->key_id = NULL;
74 cert->principals = NULL;
75 cert->signature_key = NULL;
76 return cert;
77}
78
79Key *
80key_new(int type)
81{
82 Key *k;
83 RSA *rsa;
84 DSA *dsa;
85 k = xcalloc(1, sizeof(*k));
86 k->type = type;
87 k->ecdsa = NULL;
88 k->ecdsa_nid = -1;
89 k->dsa = NULL;
90 k->rsa = NULL;
91 k->cert = NULL;
92 k->ed25519_sk = NULL;
93 k->ed25519_pk = NULL;
94 switch (k->type) {
95 case KEY_RSA1:
96 case KEY_RSA:
97 case KEY_RSA_CERT_V00:
98 case KEY_RSA_CERT:
99 if ((rsa = RSA_new()) == NULL)
100 fatal("key_new: RSA_new failed");
101 if ((rsa->n = BN_new()) == NULL)
102 fatal("key_new: BN_new failed");
103 if ((rsa->e = BN_new()) == NULL)
104 fatal("key_new: BN_new failed");
105 k->rsa = rsa;
106 break;
107 case KEY_DSA:
108 case KEY_DSA_CERT_V00:
109 case KEY_DSA_CERT:
110 if ((dsa = DSA_new()) == NULL)
111 fatal("key_new: DSA_new failed");
112 if ((dsa->p = BN_new()) == NULL)
113 fatal("key_new: BN_new failed");
114 if ((dsa->q = BN_new()) == NULL)
115 fatal("key_new: BN_new failed");
116 if ((dsa->g = BN_new()) == NULL)
117 fatal("key_new: BN_new failed");
118 if ((dsa->pub_key = BN_new()) == NULL)
119 fatal("key_new: BN_new failed");
120 k->dsa = dsa;
121 break;
122#ifdef OPENSSL_HAS_ECC
123 case KEY_ECDSA:
124 case KEY_ECDSA_CERT:
125 /* Cannot do anything until we know the group */
126 break;
127#endif
128 case KEY_ED25519:
129 case KEY_ED25519_CERT:
130 /* no need to prealloc */
131 break;
132 case KEY_UNSPEC:
133 break;
134 default:
135 fatal("key_new: bad key type %d", k->type);
136 break;
137 }
138 16
139 if (key_is_cert(k)) 17#include "compat.h"
140 k->cert = cert_new(); 18#include "sshkey.h"
141 19#include "ssherr.h"
142 return k; 20#include "log.h"
143} 21#include "authfile.h"
144 22
145void 23void
146key_add_private(Key *k) 24key_add_private(Key *k)
147{ 25{
148 switch (k->type) { 26 int r;
149 case KEY_RSA1: 27
150 case KEY_RSA: 28 if ((r = sshkey_add_private(k)) != 0)
151 case KEY_RSA_CERT_V00: 29 fatal("%s: %s", __func__, ssh_err(r));
152 case KEY_RSA_CERT:
153 if ((k->rsa->d = BN_new()) == NULL)
154 fatal("key_new_private: BN_new failed");
155 if ((k->rsa->iqmp = BN_new()) == NULL)
156 fatal("key_new_private: BN_new failed");
157 if ((k->rsa->q = BN_new()) == NULL)
158 fatal("key_new_private: BN_new failed");
159 if ((k->rsa->p = BN_new()) == NULL)
160 fatal("key_new_private: BN_new failed");
161 if ((k->rsa->dmq1 = BN_new()) == NULL)
162 fatal("key_new_private: BN_new failed");
163 if ((k->rsa->dmp1 = BN_new()) == NULL)
164 fatal("key_new_private: BN_new failed");
165 break;
166 case KEY_DSA:
167 case KEY_DSA_CERT_V00:
168 case KEY_DSA_CERT:
169 if ((k->dsa->priv_key = BN_new()) == NULL)
170 fatal("key_new_private: BN_new failed");
171 break;
172 case KEY_ECDSA:
173 case KEY_ECDSA_CERT:
174 /* Cannot do anything until we know the group */
175 break;
176 case KEY_ED25519:
177 case KEY_ED25519_CERT:
178 /* no need to prealloc */
179 break;
180 case KEY_UNSPEC:
181 break;
182 default:
183 break;
184 }
185} 30}
186 31
187Key * 32Key *
188key_new_private(int type) 33key_new_private(int type)
189{ 34{
190 Key *k = key_new(type); 35 Key *ret = NULL;
191
192 key_add_private(k);
193 return k;
194}
195
196static void
197cert_free(struct KeyCert *cert)
198{
199 u_int i;
200
201 buffer_free(&cert->certblob);
202 buffer_free(&cert->critical);
203 buffer_free(&cert->extensions);
204 free(cert->key_id);
205 for (i = 0; i < cert->nprincipals; i++)
206 free(cert->principals[i]);
207 free(cert->principals);
208 if (cert->signature_key != NULL)
209 key_free(cert->signature_key);
210 free(cert);
211}
212
213void
214key_free(Key *k)
215{
216 if (k == NULL)
217 fatal("key_free: key is NULL");
218 switch (k->type) {
219 case KEY_RSA1:
220 case KEY_RSA:
221 case KEY_RSA_CERT_V00:
222 case KEY_RSA_CERT:
223 if (k->rsa != NULL)
224 RSA_free(k->rsa);
225 k->rsa = NULL;
226 break;
227 case KEY_DSA:
228 case KEY_DSA_CERT_V00:
229 case KEY_DSA_CERT:
230 if (k->dsa != NULL)
231 DSA_free(k->dsa);
232 k->dsa = NULL;
233 break;
234#ifdef OPENSSL_HAS_ECC
235 case KEY_ECDSA:
236 case KEY_ECDSA_CERT:
237 if (k->ecdsa != NULL)
238 EC_KEY_free(k->ecdsa);
239 k->ecdsa = NULL;
240 break;
241#endif
242 case KEY_ED25519:
243 case KEY_ED25519_CERT:
244 if (k->ed25519_pk) {
245 explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
246 free(k->ed25519_pk);
247 k->ed25519_pk = NULL;
248 }
249 if (k->ed25519_sk) {
250 explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
251 free(k->ed25519_sk);
252 k->ed25519_sk = NULL;
253 }
254 break;
255 case KEY_UNSPEC:
256 break;
257 default:
258 fatal("key_free: bad key type %d", k->type);
259 break;
260 }
261 if (key_is_cert(k)) {
262 if (k->cert != NULL)
263 cert_free(k->cert);
264 k->cert = NULL;
265 }
266
267 free(k);
268}
269
270static int
271cert_compare(struct KeyCert *a, struct KeyCert *b)
272{
273 if (a == NULL && b == NULL)
274 return 1;
275 if (a == NULL || b == NULL)
276 return 0;
277 if (buffer_len(&a->certblob) != buffer_len(&b->certblob))
278 return 0;
279 if (timingsafe_bcmp(buffer_ptr(&a->certblob), buffer_ptr(&b->certblob),
280 buffer_len(&a->certblob)) != 0)
281 return 0;
282 return 1;
283}
284
285/*
286 * Compare public portions of key only, allowing comparisons between
287 * certificates and plain keys too.
288 */
289int
290key_equal_public(const Key *a, const Key *b)
291{
292#ifdef OPENSSL_HAS_ECC
293 BN_CTX *bnctx;
294#endif
295 36
296 if (a == NULL || b == NULL || 37 if ((ret = sshkey_new_private(type)) == NULL)
297 key_type_plain(a->type) != key_type_plain(b->type)) 38 fatal("%s: failed", __func__);
298 return 0; 39 return ret;
299
300 switch (a->type) {
301 case KEY_RSA1:
302 case KEY_RSA_CERT_V00:
303 case KEY_RSA_CERT:
304 case KEY_RSA:
305 return a->rsa != NULL && b->rsa != NULL &&
306 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
307 BN_cmp(a->rsa->n, b->rsa->n) == 0;
308 case KEY_DSA_CERT_V00:
309 case KEY_DSA_CERT:
310 case KEY_DSA:
311 return a->dsa != NULL && b->dsa != NULL &&
312 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
313 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
314 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
315 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
316#ifdef OPENSSL_HAS_ECC
317 case KEY_ECDSA_CERT:
318 case KEY_ECDSA:
319 if (a->ecdsa == NULL || b->ecdsa == NULL ||
320 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
321 EC_KEY_get0_public_key(b->ecdsa) == NULL)
322 return 0;
323 if ((bnctx = BN_CTX_new()) == NULL)
324 fatal("%s: BN_CTX_new failed", __func__);
325 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
326 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
327 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
328 EC_KEY_get0_public_key(a->ecdsa),
329 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
330 BN_CTX_free(bnctx);
331 return 0;
332 }
333 BN_CTX_free(bnctx);
334 return 1;
335#endif /* OPENSSL_HAS_ECC */
336 case KEY_ED25519:
337 case KEY_ED25519_CERT:
338 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
339 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
340 default:
341 fatal("key_equal: bad key type %d", a->type);
342 }
343 /* NOTREACHED */
344}
345
346int
347key_equal(const Key *a, const Key *b)
348{
349 if (a == NULL || b == NULL || a->type != b->type)
350 return 0;
351 if (key_is_cert(a)) {
352 if (!cert_compare(a->cert, b->cert))
353 return 0;
354 }
355 return key_equal_public(a, b);
356} 40}
357 41
358u_char* 42u_char*
359key_fingerprint_raw(const Key *k, enum fp_type dgst_type, 43key_fingerprint_raw(const Key *k, enum fp_type dgst_type,
360 u_int *dgst_raw_length) 44 u_int *dgst_raw_length)
361{ 45{
362 u_char *blob = NULL; 46 u_char *ret = NULL;
363 u_char *retval = NULL; 47 size_t dlen;
364 u_int len = 0; 48 int r;
365 int nlen, elen, hash_alg = -1; 49
366 50 if (dgst_raw_length != NULL)
367 *dgst_raw_length = 0; 51 *dgst_raw_length = 0;
368 52 if ((r = sshkey_fingerprint_raw(k, dgst_type, &ret, &dlen)) != 0)
369 /* XXX switch to DIGEST_* directly? */ 53 fatal("%s: %s", __func__, ssh_err(r));
370 switch (dgst_type) { 54 if (dlen > INT_MAX)
371 case SSH_FP_MD5: 55 fatal("%s: giant len %zu", __func__, dlen);
372 hash_alg = SSH_DIGEST_MD5; 56 *dgst_raw_length = dlen;
373 break; 57 return ret;
374 case SSH_FP_SHA1:
375 hash_alg = SSH_DIGEST_SHA1;
376 break;
377 case SSH_FP_SHA256:
378 hash_alg = SSH_DIGEST_SHA256;
379 break;
380 default:
381 fatal("%s: bad digest type %d", __func__, dgst_type);
382 }
383 switch (k->type) {
384 case KEY_RSA1:
385 nlen = BN_num_bytes(k->rsa->n);
386 elen = BN_num_bytes(k->rsa->e);
387 len = nlen + elen;
388 blob = xmalloc(len);
389 BN_bn2bin(k->rsa->n, blob);
390 BN_bn2bin(k->rsa->e, blob + nlen);
391 break;
392 case KEY_DSA:
393 case KEY_ECDSA:
394 case KEY_RSA:
395 case KEY_ED25519:
396 key_to_blob(k, &blob, &len);
397 break;
398 case KEY_DSA_CERT_V00:
399 case KEY_RSA_CERT_V00:
400 case KEY_DSA_CERT:
401 case KEY_ECDSA_CERT:
402 case KEY_RSA_CERT:
403 case KEY_ED25519_CERT:
404 /* We want a fingerprint of the _key_ not of the cert */
405 to_blob(k, &blob, &len, 1);
406 break;
407 case KEY_UNSPEC:
408 return retval;
409 default:
410 fatal("%s: bad key type %d", __func__, k->type);
411 break;
412 }
413 if (blob != NULL) {
414 retval = xmalloc(SSH_DIGEST_MAX_LENGTH);
415 if ((ssh_digest_memory(hash_alg, blob, len,
416 retval, SSH_DIGEST_MAX_LENGTH)) != 0)
417 fatal("%s: digest_memory failed", __func__);
418 explicit_bzero(blob, len);
419 free(blob);
420 *dgst_raw_length = ssh_digest_bytes(hash_alg);
421 } else {
422 fatal("%s: blob is null", __func__);
423 }
424 return retval;
425}
426
427static char *
428key_fingerprint_hex(u_char *dgst_raw, u_int dgst_raw_len)
429{
430 char *retval;
431 u_int i;
432
433 retval = xcalloc(1, dgst_raw_len * 3 + 1);
434 for (i = 0; i < dgst_raw_len; i++) {
435 char hex[4];
436 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
437 strlcat(retval, hex, dgst_raw_len * 3 + 1);
438 }
439
440 /* Remove the trailing ':' character */
441 retval[(dgst_raw_len * 3) - 1] = '\0';
442 return retval;
443}
444
445static char *
446key_fingerprint_bubblebabble(u_char *dgst_raw, u_int dgst_raw_len)
447{
448 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
449 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
450 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
451 u_int i, j = 0, rounds, seed = 1;
452 char *retval;
453
454 rounds = (dgst_raw_len / 2) + 1;
455 retval = xcalloc((rounds * 6), sizeof(char));
456 retval[j++] = 'x';
457 for (i = 0; i < rounds; i++) {
458 u_int idx0, idx1, idx2, idx3, idx4;
459 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
460 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
461 seed) % 6;
462 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
463 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
464 (seed / 6)) % 6;
465 retval[j++] = vowels[idx0];
466 retval[j++] = consonants[idx1];
467 retval[j++] = vowels[idx2];
468 if ((i + 1) < rounds) {
469 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
470 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
471 retval[j++] = consonants[idx3];
472 retval[j++] = '-';
473 retval[j++] = consonants[idx4];
474 seed = ((seed * 5) +
475 ((((u_int)(dgst_raw[2 * i])) * 7) +
476 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
477 }
478 } else {
479 idx0 = seed % 6;
480 idx1 = 16;
481 idx2 = seed / 6;
482 retval[j++] = vowels[idx0];
483 retval[j++] = consonants[idx1];
484 retval[j++] = vowels[idx2];
485 }
486 }
487 retval[j++] = 'x';
488 retval[j++] = '\0';
489 return retval;
490}
491
492/*
493 * Draw an ASCII-Art representing the fingerprint so human brain can
494 * profit from its built-in pattern recognition ability.
495 * This technique is called "random art" and can be found in some
496 * scientific publications like this original paper:
497 *
498 * "Hash Visualization: a New Technique to improve Real-World Security",
499 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
500 * Techniques and E-Commerce (CrypTEC '99)
501 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
502 *
503 * The subject came up in a talk by Dan Kaminsky, too.
504 *
505 * If you see the picture is different, the key is different.
506 * If the picture looks the same, you still know nothing.
507 *
508 * The algorithm used here is a worm crawling over a discrete plane,
509 * leaving a trace (augmenting the field) everywhere it goes.
510 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
511 * makes the respective movement vector be ignored for this turn.
512 * Graphs are not unambiguous, because circles in graphs can be
513 * walked in either direction.
514 */
515
516/*
517 * Field sizes for the random art. Have to be odd, so the starting point
518 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
519 * Else pictures would be too dense, and drawing the frame would
520 * fail, too, because the key type would not fit in anymore.
521 */
522#define FLDBASE 8
523#define FLDSIZE_Y (FLDBASE + 1)
524#define FLDSIZE_X (FLDBASE * 2 + 1)
525static char *
526key_fingerprint_randomart(u_char *dgst_raw, u_int dgst_raw_len, const Key *k)
527{
528 /*
529 * Chars to be used after each other every time the worm
530 * intersects with itself. Matter of taste.
531 */
532 char *augmentation_string = " .o+=*BOX@%&#/^SE";
533 char *retval, *p;
534 u_char field[FLDSIZE_X][FLDSIZE_Y];
535 u_int i, b;
536 int x, y;
537 size_t len = strlen(augmentation_string) - 1;
538
539 retval = xcalloc(1, (FLDSIZE_X + 3) * (FLDSIZE_Y + 2));
540
541 /* initialize field */
542 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
543 x = FLDSIZE_X / 2;
544 y = FLDSIZE_Y / 2;
545
546 /* process raw key */
547 for (i = 0; i < dgst_raw_len; i++) {
548 int input;
549 /* each byte conveys four 2-bit move commands */
550 input = dgst_raw[i];
551 for (b = 0; b < 4; b++) {
552 /* evaluate 2 bit, rest is shifted later */
553 x += (input & 0x1) ? 1 : -1;
554 y += (input & 0x2) ? 1 : -1;
555
556 /* assure we are still in bounds */
557 x = MAX(x, 0);
558 y = MAX(y, 0);
559 x = MIN(x, FLDSIZE_X - 1);
560 y = MIN(y, FLDSIZE_Y - 1);
561
562 /* augment the field */
563 if (field[x][y] < len - 2)
564 field[x][y]++;
565 input = input >> 2;
566 }
567 }
568
569 /* mark starting point and end point*/
570 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
571 field[x][y] = len;
572
573 /* fill in retval */
574 snprintf(retval, FLDSIZE_X, "+--[%4s %4u]", key_type(k), key_size(k));
575 p = strchr(retval, '\0');
576
577 /* output upper border */
578 for (i = p - retval - 1; i < FLDSIZE_X; i++)
579 *p++ = '-';
580 *p++ = '+';
581 *p++ = '\n';
582
583 /* output content */
584 for (y = 0; y < FLDSIZE_Y; y++) {
585 *p++ = '|';
586 for (x = 0; x < FLDSIZE_X; x++)
587 *p++ = augmentation_string[MIN(field[x][y], len)];
588 *p++ = '|';
589 *p++ = '\n';
590 }
591
592 /* output lower border */
593 *p++ = '+';
594 for (i = 0; i < FLDSIZE_X; i++)
595 *p++ = '-';
596 *p++ = '+';
597
598 return retval;
599}
600
601char *
602key_fingerprint(const Key *k, enum fp_type dgst_type, enum fp_rep dgst_rep)
603{
604 char *retval = NULL;
605 u_char *dgst_raw;
606 u_int dgst_raw_len;
607
608 dgst_raw = key_fingerprint_raw(k, dgst_type, &dgst_raw_len);
609 if (!dgst_raw)
610 fatal("key_fingerprint: null from key_fingerprint_raw()");
611 switch (dgst_rep) {
612 case SSH_FP_HEX:
613 retval = key_fingerprint_hex(dgst_raw, dgst_raw_len);
614 break;
615 case SSH_FP_BUBBLEBABBLE:
616 retval = key_fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
617 break;
618 case SSH_FP_RANDOMART:
619 retval = key_fingerprint_randomart(dgst_raw, dgst_raw_len, k);
620 break;
621 default:
622 fatal("key_fingerprint: bad digest representation %d",
623 dgst_rep);
624 break;
625 }
626 explicit_bzero(dgst_raw, dgst_raw_len);
627 free(dgst_raw);
628 return retval;
629}
630
631/*
632 * Reads a multiple-precision integer in decimal from the buffer, and advances
633 * the pointer. The integer must already be initialized. This function is
634 * permitted to modify the buffer. This leaves *cpp to point just beyond the
635 * last processed (and maybe modified) character. Note that this may modify
636 * the buffer containing the number.
637 */
638static int
639read_bignum(char **cpp, BIGNUM * value)
640{
641 char *cp = *cpp;
642 int old;
643
644 /* Skip any leading whitespace. */
645 for (; *cp == ' ' || *cp == '\t'; cp++)
646 ;
647
648 /* Check that it begins with a decimal digit. */
649 if (*cp < '0' || *cp > '9')
650 return 0;
651
652 /* Save starting position. */
653 *cpp = cp;
654
655 /* Move forward until all decimal digits skipped. */
656 for (; *cp >= '0' && *cp <= '9'; cp++)
657 ;
658
659 /* Save the old terminating character, and replace it by \0. */
660 old = *cp;
661 *cp = 0;
662
663 /* Parse the number. */
664 if (BN_dec2bn(&value, *cpp) == 0)
665 return 0;
666
667 /* Restore old terminating character. */
668 *cp = old;
669
670 /* Move beyond the number and return success. */
671 *cpp = cp;
672 return 1;
673}
674
675static int
676write_bignum(FILE *f, BIGNUM *num)
677{
678 char *buf = BN_bn2dec(num);
679 if (buf == NULL) {
680 error("write_bignum: BN_bn2dec() failed");
681 return 0;
682 }
683 fprintf(f, " %s", buf);
684 OPENSSL_free(buf);
685 return 1;
686} 58}
687 59
688/* returns 1 ok, -1 error */
689int 60int
690key_read(Key *ret, char **cpp) 61key_read(Key *ret, char **cpp)
691{ 62{
692 Key *k; 63 return sshkey_read(ret, cpp) == 0 ? 1 : -1;
693 int success = -1;
694 char *cp, *space;
695 int len, n, type;
696 u_int bits;
697 u_char *blob;
698#ifdef OPENSSL_HAS_ECC
699 int curve_nid = -1;
700#endif
701
702 cp = *cpp;
703
704 switch (ret->type) {
705 case KEY_RSA1:
706 /* Get number of bits. */
707 if (*cp < '0' || *cp > '9')
708 return -1; /* Bad bit count... */
709 for (bits = 0; *cp >= '0' && *cp <= '9'; cp++)
710 bits = 10 * bits + *cp - '0';
711 if (bits == 0)
712 return -1;
713 *cpp = cp;
714 /* Get public exponent, public modulus. */
715 if (!read_bignum(cpp, ret->rsa->e))
716 return -1;
717 if (!read_bignum(cpp, ret->rsa->n))
718 return -1;
719 /* validate the claimed number of bits */
720 if ((u_int)BN_num_bits(ret->rsa->n) != bits) {
721 verbose("key_read: claimed key size %d does not match "
722 "actual %d", bits, BN_num_bits(ret->rsa->n));
723 return -1;
724 }
725 success = 1;
726 break;
727 case KEY_UNSPEC:
728 case KEY_RSA:
729 case KEY_DSA:
730 case KEY_ECDSA:
731 case KEY_ED25519:
732 case KEY_DSA_CERT_V00:
733 case KEY_RSA_CERT_V00:
734 case KEY_DSA_CERT:
735 case KEY_ECDSA_CERT:
736 case KEY_RSA_CERT:
737 case KEY_ED25519_CERT:
738 space = strchr(cp, ' ');
739 if (space == NULL) {
740 debug3("key_read: missing whitespace");
741 return -1;
742 }
743 *space = '\0';
744 type = key_type_from_name(cp);
745#ifdef OPENSSL_HAS_ECC
746 if (key_type_plain(type) == KEY_ECDSA &&
747 (curve_nid = key_ecdsa_nid_from_name(cp)) == -1) {
748 debug("key_read: invalid curve");
749 return -1;
750 }
751#endif
752 *space = ' ';
753 if (type == KEY_UNSPEC) {
754 debug3("key_read: missing keytype");
755 return -1;
756 }
757 cp = space+1;
758 if (*cp == '\0') {
759 debug3("key_read: short string");
760 return -1;
761 }
762 if (ret->type == KEY_UNSPEC) {
763 ret->type = type;
764 } else if (ret->type != type) {
765 /* is a key, but different type */
766 debug3("key_read: type mismatch");
767 return -1;
768 }
769 len = 2*strlen(cp);
770 blob = xmalloc(len);
771 n = uudecode(cp, blob, len);
772 if (n < 0) {
773 error("key_read: uudecode %s failed", cp);
774 free(blob);
775 return -1;
776 }
777 k = key_from_blob(blob, (u_int)n);
778 free(blob);
779 if (k == NULL) {
780 error("key_read: key_from_blob %s failed", cp);
781 return -1;
782 }
783 if (k->type != type) {
784 error("key_read: type mismatch: encoding error");
785 key_free(k);
786 return -1;
787 }
788#ifdef OPENSSL_HAS_ECC
789 if (key_type_plain(type) == KEY_ECDSA &&
790 curve_nid != k->ecdsa_nid) {
791 error("key_read: type mismatch: EC curve mismatch");
792 key_free(k);
793 return -1;
794 }
795#endif
796/*XXXX*/
797 if (key_is_cert(ret)) {
798 if (!key_is_cert(k)) {
799 error("key_read: loaded key is not a cert");
800 key_free(k);
801 return -1;
802 }
803 if (ret->cert != NULL)
804 cert_free(ret->cert);
805 ret->cert = k->cert;
806 k->cert = NULL;
807 }
808 if (key_type_plain(ret->type) == KEY_RSA) {
809 if (ret->rsa != NULL)
810 RSA_free(ret->rsa);
811 ret->rsa = k->rsa;
812 k->rsa = NULL;
813#ifdef DEBUG_PK
814 RSA_print_fp(stderr, ret->rsa, 8);
815#endif
816 }
817 if (key_type_plain(ret->type) == KEY_DSA) {
818 if (ret->dsa != NULL)
819 DSA_free(ret->dsa);
820 ret->dsa = k->dsa;
821 k->dsa = NULL;
822#ifdef DEBUG_PK
823 DSA_print_fp(stderr, ret->dsa, 8);
824#endif
825 }
826#ifdef OPENSSL_HAS_ECC
827 if (key_type_plain(ret->type) == KEY_ECDSA) {
828 if (ret->ecdsa != NULL)
829 EC_KEY_free(ret->ecdsa);
830 ret->ecdsa = k->ecdsa;
831 ret->ecdsa_nid = k->ecdsa_nid;
832 k->ecdsa = NULL;
833 k->ecdsa_nid = -1;
834#ifdef DEBUG_PK
835 key_dump_ec_key(ret->ecdsa);
836#endif
837 }
838#endif
839 if (key_type_plain(ret->type) == KEY_ED25519) {
840 free(ret->ed25519_pk);
841 ret->ed25519_pk = k->ed25519_pk;
842 k->ed25519_pk = NULL;
843#ifdef DEBUG_PK
844 /* XXX */
845#endif
846 }
847 success = 1;
848/*XXXX*/
849 key_free(k);
850 if (success != 1)
851 break;
852 /* advance cp: skip whitespace and data */
853 while (*cp == ' ' || *cp == '\t')
854 cp++;
855 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
856 cp++;
857 *cpp = cp;
858 break;
859 default:
860 fatal("key_read: bad key type: %d", ret->type);
861 break;
862 }
863 return success;
864} 64}
865 65
866int 66int
867key_write(const Key *key, FILE *f) 67key_write(const Key *key, FILE *f)
868{ 68{
869 int n, success = 0; 69 return sshkey_write(key, f) == 0 ? 1 : 0;
870 u_int len, bits = 0;
871 u_char *blob;
872 char *uu;
873
874 if (key_is_cert(key)) {
875 if (key->cert == NULL) {
876 error("%s: no cert data", __func__);
877 return 0;
878 }
879 if (buffer_len(&key->cert->certblob) == 0) {
880 error("%s: no signed certificate blob", __func__);
881 return 0;
882 }
883 }
884
885 switch (key->type) {
886 case KEY_RSA1:
887 if (key->rsa == NULL)
888 return 0;
889 /* size of modulus 'n' */
890 bits = BN_num_bits(key->rsa->n);
891 fprintf(f, "%u", bits);
892 if (write_bignum(f, key->rsa->e) &&
893 write_bignum(f, key->rsa->n))
894 return 1;
895 error("key_write: failed for RSA key");
896 return 0;
897 case KEY_DSA:
898 case KEY_DSA_CERT_V00:
899 case KEY_DSA_CERT:
900 if (key->dsa == NULL)
901 return 0;
902 break;
903#ifdef OPENSSL_HAS_ECC
904 case KEY_ECDSA:
905 case KEY_ECDSA_CERT:
906 if (key->ecdsa == NULL)
907 return 0;
908 break;
909#endif
910 case KEY_ED25519:
911 case KEY_ED25519_CERT:
912 if (key->ed25519_pk == NULL)
913 return 0;
914 break;
915 case KEY_RSA:
916 case KEY_RSA_CERT_V00:
917 case KEY_RSA_CERT:
918 if (key->rsa == NULL)
919 return 0;
920 break;
921 default:
922 return 0;
923 }
924
925 key_to_blob(key, &blob, &len);
926 uu = xmalloc(2*len);
927 n = uuencode(blob, len, uu, 2*len);
928 if (n > 0) {
929 fprintf(f, "%s %s", key_ssh_name(key), uu);
930 success = 1;
931 }
932 free(blob);
933 free(uu);
934
935 return success;
936}
937
938const char *
939key_cert_type(const Key *k)
940{
941 switch (k->cert->type) {
942 case SSH2_CERT_TYPE_USER:
943 return "user";
944 case SSH2_CERT_TYPE_HOST:
945 return "host";
946 default:
947 return "unknown";
948 }
949}
950
951struct keytype {
952 char *name;
953 char *shortname;
954 int type;
955 int nid;
956 int cert;
957};
958static const struct keytype keytypes[] = {
959 { NULL, "RSA1", KEY_RSA1, 0, 0 },
960 { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
961 { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
962 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
963#ifdef OPENSSL_HAS_ECC
964 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
965 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
966# ifdef OPENSSL_HAS_NISTP521
967 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
968# endif
969#endif /* OPENSSL_HAS_ECC */
970 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
971 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
972#ifdef OPENSSL_HAS_ECC
973 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
974 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
975 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
976 KEY_ECDSA_CERT, NID_secp384r1, 1 },
977# ifdef OPENSSL_HAS_NISTP521
978 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
979 KEY_ECDSA_CERT, NID_secp521r1, 1 },
980# endif
981#endif /* OPENSSL_HAS_ECC */
982 { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
983 KEY_RSA_CERT_V00, 0, 1 },
984 { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
985 KEY_DSA_CERT_V00, 0, 1 },
986 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
987 KEY_ED25519_CERT, 0, 1 },
988 { "null", "null", KEY_NULL, 0, 0 },
989 { NULL, NULL, -1, -1, 0 }
990};
991
992const char *
993key_type(const Key *k)
994{
995 const struct keytype *kt;
996
997 for (kt = keytypes; kt->type != -1; kt++) {
998 if (kt->type == k->type)
999 return kt->shortname;
1000 }
1001 return "unknown";
1002}
1003
1004static const char *
1005key_ssh_name_from_type_nid(int type, int nid)
1006{
1007 const struct keytype *kt;
1008
1009 for (kt = keytypes; kt->type != -1; kt++) {
1010 if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
1011 return kt->name;
1012 }
1013 return "ssh-unknown";
1014}
1015
1016const char *
1017key_ssh_name(const Key *k)
1018{
1019 return key_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
1020}
1021
1022const char *
1023key_ssh_name_plain(const Key *k)
1024{
1025 return key_ssh_name_from_type_nid(key_type_plain(k->type),
1026 k->ecdsa_nid);
1027}
1028
1029int
1030key_type_from_name(char *name)
1031{
1032 const struct keytype *kt;
1033
1034 for (kt = keytypes; kt->type != -1; kt++) {
1035 /* Only allow shortname matches for plain key types */
1036 if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
1037 (!kt->cert && strcasecmp(kt->shortname, name) == 0))
1038 return kt->type;
1039 }
1040 debug2("key_type_from_name: unknown key type '%s'", name);
1041 return KEY_UNSPEC;
1042}
1043
1044int
1045key_ecdsa_nid_from_name(const char *name)
1046{
1047 const struct keytype *kt;
1048
1049 for (kt = keytypes; kt->type != -1; kt++) {
1050 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
1051 continue;
1052 if (kt->name != NULL && strcmp(name, kt->name) == 0)
1053 return kt->nid;
1054 }
1055 debug2("%s: unknown/non-ECDSA key type '%s'", __func__, name);
1056 return -1;
1057}
1058
1059char *
1060key_alg_list(int certs_only, int plain_only)
1061{
1062 char *ret = NULL;
1063 size_t nlen, rlen = 0;
1064 const struct keytype *kt;
1065
1066 for (kt = keytypes; kt->type != -1; kt++) {
1067 if (kt->name == NULL || kt->type == KEY_NULL)
1068 continue;
1069 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
1070 continue;
1071 if (ret != NULL)
1072 ret[rlen++] = '\n';
1073 nlen = strlen(kt->name);
1074 ret = xrealloc(ret, 1, rlen + nlen + 2);
1075 memcpy(ret + rlen, kt->name, nlen + 1);
1076 rlen += nlen;
1077 }
1078 return ret;
1079}
1080
1081int
1082key_type_is_cert(int type)
1083{
1084 const struct keytype *kt;
1085
1086 for (kt = keytypes; kt->type != -1; kt++) {
1087 if (kt->type == type)
1088 return kt->cert;
1089 }
1090 return 0;
1091}
1092
1093static int
1094key_type_is_valid_ca(int type)
1095{
1096 switch (type) {
1097 case KEY_RSA:
1098 case KEY_DSA:
1099 case KEY_ECDSA:
1100 case KEY_ED25519:
1101 return 1;
1102 default:
1103 return 0;
1104 }
1105}
1106
1107u_int
1108key_size(const Key *k)
1109{
1110 switch (k->type) {
1111 case KEY_RSA1:
1112 case KEY_RSA:
1113 case KEY_RSA_CERT_V00:
1114 case KEY_RSA_CERT:
1115 return BN_num_bits(k->rsa->n);
1116 case KEY_DSA:
1117 case KEY_DSA_CERT_V00:
1118 case KEY_DSA_CERT:
1119 return BN_num_bits(k->dsa->p);
1120 case KEY_ED25519:
1121 return 256; /* XXX */
1122#ifdef OPENSSL_HAS_ECC
1123 case KEY_ECDSA:
1124 case KEY_ECDSA_CERT:
1125 return key_curve_nid_to_bits(k->ecdsa_nid);
1126#endif
1127 }
1128 return 0;
1129}
1130
1131static RSA *
1132rsa_generate_private_key(u_int bits)
1133{
1134 RSA *private = RSA_new();
1135 BIGNUM *f4 = BN_new();
1136
1137 if (private == NULL)
1138 fatal("%s: RSA_new failed", __func__);
1139 if (f4 == NULL)
1140 fatal("%s: BN_new failed", __func__);
1141 if (!BN_set_word(f4, RSA_F4))
1142 fatal("%s: BN_new failed", __func__);
1143 if (!RSA_generate_key_ex(private, bits, f4, NULL))
1144 fatal("%s: key generation failed.", __func__);
1145 BN_free(f4);
1146 return private;
1147}
1148
1149static DSA*
1150dsa_generate_private_key(u_int bits)
1151{
1152 DSA *private = DSA_new();
1153
1154 if (private == NULL)
1155 fatal("%s: DSA_new failed", __func__);
1156 if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1157 NULL, NULL))
1158 fatal("%s: DSA_generate_parameters failed", __func__);
1159 if (!DSA_generate_key(private))
1160 fatal("%s: DSA_generate_key failed.", __func__);
1161 return private;
1162}
1163
1164int
1165key_ecdsa_bits_to_nid(int bits)
1166{
1167 switch (bits) {
1168#ifdef OPENSSL_HAS_ECC
1169 case 256:
1170 return NID_X9_62_prime256v1;
1171 case 384:
1172 return NID_secp384r1;
1173# ifdef OPENSSL_HAS_NISTP521
1174 case 521:
1175 return NID_secp521r1;
1176# endif
1177#endif
1178 default:
1179 return -1;
1180 }
1181}
1182
1183#ifdef OPENSSL_HAS_ECC
1184int
1185key_ecdsa_key_to_nid(EC_KEY *k)
1186{
1187 EC_GROUP *eg;
1188 int nids[] = {
1189 NID_X9_62_prime256v1,
1190 NID_secp384r1,
1191# ifdef OPENSSL_HAS_NISTP521
1192 NID_secp521r1,
1193# endif
1194 -1
1195 };
1196 int nid;
1197 u_int i;
1198 BN_CTX *bnctx;
1199 const EC_GROUP *g = EC_KEY_get0_group(k);
1200
1201 /*
1202 * The group may be stored in a ASN.1 encoded private key in one of two
1203 * ways: as a "named group", which is reconstituted by ASN.1 object ID
1204 * or explicit group parameters encoded into the key blob. Only the
1205 * "named group" case sets the group NID for us, but we can figure
1206 * it out for the other case by comparing against all the groups that
1207 * are supported.
1208 */
1209 if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1210 return nid;
1211 if ((bnctx = BN_CTX_new()) == NULL)
1212 fatal("%s: BN_CTX_new() failed", __func__);
1213 for (i = 0; nids[i] != -1; i++) {
1214 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL)
1215 fatal("%s: EC_GROUP_new_by_curve_name failed",
1216 __func__);
1217 if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1218 break;
1219 EC_GROUP_free(eg);
1220 }
1221 BN_CTX_free(bnctx);
1222 debug3("%s: nid = %d", __func__, nids[i]);
1223 if (nids[i] != -1) {
1224 /* Use the group with the NID attached */
1225 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1226 if (EC_KEY_set_group(k, eg) != 1)
1227 fatal("%s: EC_KEY_set_group", __func__);
1228 }
1229 return nids[i];
1230}
1231
1232static EC_KEY*
1233ecdsa_generate_private_key(u_int bits, int *nid)
1234{
1235 EC_KEY *private;
1236
1237 if ((*nid = key_ecdsa_bits_to_nid(bits)) == -1)
1238 fatal("%s: invalid key length", __func__);
1239 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL)
1240 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1241 if (EC_KEY_generate_key(private) != 1)
1242 fatal("%s: EC_KEY_generate_key failed", __func__);
1243 EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1244 return private;
1245} 70}
1246#endif /* OPENSSL_HAS_ECC */
1247 71
1248Key * 72Key *
1249key_generate(int type, u_int bits) 73key_generate(int type, u_int bits)
1250{ 74{
1251 Key *k = key_new(KEY_UNSPEC); 75 int r;
1252 switch (type) { 76 Key *ret = NULL;
1253 case KEY_DSA: 77
1254 k->dsa = dsa_generate_private_key(bits); 78 if ((r = sshkey_generate(type, bits, &ret)) != 0)
1255 break; 79 fatal("%s: %s", __func__, ssh_err(r));
1256#ifdef OPENSSL_HAS_ECC 80 return ret;
1257 case KEY_ECDSA:
1258 k->ecdsa = ecdsa_generate_private_key(bits, &k->ecdsa_nid);
1259 break;
1260#endif
1261 case KEY_RSA:
1262 case KEY_RSA1:
1263 k->rsa = rsa_generate_private_key(bits);
1264 break;
1265 case KEY_ED25519:
1266 k->ed25519_pk = xmalloc(ED25519_PK_SZ);
1267 k->ed25519_sk = xmalloc(ED25519_SK_SZ);
1268 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1269 break;
1270 case KEY_RSA_CERT_V00:
1271 case KEY_DSA_CERT_V00:
1272 case KEY_RSA_CERT:
1273 case KEY_DSA_CERT:
1274 fatal("key_generate: cert keys cannot be generated directly");
1275 default:
1276 fatal("key_generate: unknown type %d", type);
1277 }
1278 k->type = type;
1279 return k;
1280} 81}
1281 82
1282void 83void
1283key_cert_copy(const Key *from_key, struct Key *to_key) 84key_cert_copy(const Key *from_key, Key *to_key)
1284{ 85{
1285 u_int i; 86 int r;
1286 const struct KeyCert *from;
1287 struct KeyCert *to;
1288
1289 if (to_key->cert != NULL) {
1290 cert_free(to_key->cert);
1291 to_key->cert = NULL;
1292 }
1293 87
1294 if ((from = from_key->cert) == NULL) 88 if ((r = sshkey_cert_copy(from_key, to_key)) != 0)
1295 return; 89 fatal("%s: %s", __func__, ssh_err(r));
1296
1297 to = to_key->cert = cert_new();
1298
1299 buffer_append(&to->certblob, buffer_ptr(&from->certblob),
1300 buffer_len(&from->certblob));
1301
1302 buffer_append(&to->critical,
1303 buffer_ptr(&from->critical), buffer_len(&from->critical));
1304 buffer_append(&to->extensions,
1305 buffer_ptr(&from->extensions), buffer_len(&from->extensions));
1306
1307 to->serial = from->serial;
1308 to->type = from->type;
1309 to->key_id = from->key_id == NULL ? NULL : xstrdup(from->key_id);
1310 to->valid_after = from->valid_after;
1311 to->valid_before = from->valid_before;
1312 to->signature_key = from->signature_key == NULL ?
1313 NULL : key_from_private(from->signature_key);
1314
1315 to->nprincipals = from->nprincipals;
1316 if (to->nprincipals > CERT_MAX_PRINCIPALS)
1317 fatal("%s: nprincipals (%u) > CERT_MAX_PRINCIPALS (%u)",
1318 __func__, to->nprincipals, CERT_MAX_PRINCIPALS);
1319 if (to->nprincipals > 0) {
1320 to->principals = xcalloc(from->nprincipals,
1321 sizeof(*to->principals));
1322 for (i = 0; i < to->nprincipals; i++)
1323 to->principals[i] = xstrdup(from->principals[i]);
1324 }
1325} 90}
1326 91
1327Key * 92Key *
1328key_from_private(const Key *k) 93key_from_private(const Key *k)
1329{ 94{
1330 Key *n = NULL; 95 int r;
1331 switch (k->type) { 96 Key *ret = NULL;
1332 case KEY_DSA:
1333 case KEY_DSA_CERT_V00:
1334 case KEY_DSA_CERT:
1335 n = key_new(k->type);
1336 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1337 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1338 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1339 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL))
1340 fatal("key_from_private: BN_copy failed");
1341 break;
1342#ifdef OPENSSL_HAS_ECC
1343 case KEY_ECDSA:
1344 case KEY_ECDSA_CERT:
1345 n = key_new(k->type);
1346 n->ecdsa_nid = k->ecdsa_nid;
1347 if ((n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid)) == NULL)
1348 fatal("%s: EC_KEY_new_by_curve_name failed", __func__);
1349 if (EC_KEY_set_public_key(n->ecdsa,
1350 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1351 fatal("%s: EC_KEY_set_public_key failed", __func__);
1352 break;
1353#endif
1354 case KEY_RSA:
1355 case KEY_RSA1:
1356 case KEY_RSA_CERT_V00:
1357 case KEY_RSA_CERT:
1358 n = key_new(k->type);
1359 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1360 (BN_copy(n->rsa->e, k->rsa->e) == NULL))
1361 fatal("key_from_private: BN_copy failed");
1362 break;
1363 case KEY_ED25519:
1364 case KEY_ED25519_CERT:
1365 n = key_new(k->type);
1366 if (k->ed25519_pk != NULL) {
1367 n->ed25519_pk = xmalloc(ED25519_PK_SZ);
1368 memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1369 }
1370 break;
1371 default:
1372 fatal("key_from_private: unknown type %d", k->type);
1373 break;
1374 }
1375 if (key_is_cert(k))
1376 key_cert_copy(k, n);
1377 return n;
1378}
1379
1380int
1381key_names_valid2(const char *names)
1382{
1383 char *s, *cp, *p;
1384
1385 if (names == NULL || strcmp(names, "") == 0)
1386 return 0;
1387 s = cp = xstrdup(names);
1388 for ((p = strsep(&cp, ",")); p && *p != '\0';
1389 (p = strsep(&cp, ","))) {
1390 switch (key_type_from_name(p)) {
1391 case KEY_RSA1:
1392 case KEY_UNSPEC:
1393 free(s);
1394 return 0;
1395 }
1396 }
1397 debug3("key names ok: [%s]", names);
1398 free(s);
1399 return 1;
1400}
1401
1402static int
1403cert_parse(Buffer *b, Key *key, const u_char *blob, u_int blen)
1404{
1405 u_char *principals, *critical, *exts, *sig_key, *sig;
1406 u_int signed_len, plen, clen, sklen, slen, kidlen, elen;
1407 Buffer tmp;
1408 char *principal;
1409 int ret = -1;
1410 int v00 = key->type == KEY_DSA_CERT_V00 ||
1411 key->type == KEY_RSA_CERT_V00;
1412
1413 buffer_init(&tmp);
1414
1415 /* Copy the entire key blob for verification and later serialisation */
1416 buffer_append(&key->cert->certblob, blob, blen);
1417
1418 elen = 0; /* Not touched for v00 certs */
1419 principals = exts = critical = sig_key = sig = NULL;
1420 if ((!v00 && buffer_get_int64_ret(&key->cert->serial, b) != 0) ||
1421 buffer_get_int_ret(&key->cert->type, b) != 0 ||
1422 (key->cert->key_id = buffer_get_cstring_ret(b, &kidlen)) == NULL ||
1423 (principals = buffer_get_string_ret(b, &plen)) == NULL ||
1424 buffer_get_int64_ret(&key->cert->valid_after, b) != 0 ||
1425 buffer_get_int64_ret(&key->cert->valid_before, b) != 0 ||
1426 (critical = buffer_get_string_ret(b, &clen)) == NULL ||
1427 (!v00 && (exts = buffer_get_string_ret(b, &elen)) == NULL) ||
1428 (v00 && buffer_get_string_ptr_ret(b, NULL) == NULL) || /* nonce */
1429 buffer_get_string_ptr_ret(b, NULL) == NULL || /* reserved */
1430 (sig_key = buffer_get_string_ret(b, &sklen)) == NULL) {
1431 error("%s: parse error", __func__);
1432 goto out;
1433 }
1434
1435 /* Signature is left in the buffer so we can calculate this length */
1436 signed_len = buffer_len(&key->cert->certblob) - buffer_len(b);
1437
1438 if ((sig = buffer_get_string_ret(b, &slen)) == NULL) {
1439 error("%s: parse error", __func__);
1440 goto out;
1441 }
1442
1443 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1444 key->cert->type != SSH2_CERT_TYPE_HOST) {
1445 error("Unknown certificate type %u", key->cert->type);
1446 goto out;
1447 }
1448 97
1449 buffer_append(&tmp, principals, plen); 98 if ((r = sshkey_from_private(k, &ret)) != 0)
1450 while (buffer_len(&tmp) > 0) { 99 fatal("%s: %s", __func__, ssh_err(r));
1451 if (key->cert->nprincipals >= CERT_MAX_PRINCIPALS) {
1452 error("%s: Too many principals", __func__);
1453 goto out;
1454 }
1455 if ((principal = buffer_get_cstring_ret(&tmp, &plen)) == NULL) {
1456 error("%s: Principals data invalid", __func__);
1457 goto out;
1458 }
1459 key->cert->principals = xrealloc(key->cert->principals,
1460 key->cert->nprincipals + 1, sizeof(*key->cert->principals));
1461 key->cert->principals[key->cert->nprincipals++] = principal;
1462 }
1463
1464 buffer_clear(&tmp);
1465
1466 buffer_append(&key->cert->critical, critical, clen);
1467 buffer_append(&tmp, critical, clen);
1468 /* validate structure */
1469 while (buffer_len(&tmp) != 0) {
1470 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1471 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1472 error("%s: critical option data invalid", __func__);
1473 goto out;
1474 }
1475 }
1476 buffer_clear(&tmp);
1477
1478 buffer_append(&key->cert->extensions, exts, elen);
1479 buffer_append(&tmp, exts, elen);
1480 /* validate structure */
1481 while (buffer_len(&tmp) != 0) {
1482 if (buffer_get_string_ptr_ret(&tmp, NULL) == NULL ||
1483 buffer_get_string_ptr_ret(&tmp, NULL) == NULL) {
1484 error("%s: extension data invalid", __func__);
1485 goto out;
1486 }
1487 }
1488 buffer_clear(&tmp);
1489
1490 if ((key->cert->signature_key = key_from_blob2(sig_key, sklen, 0))
1491 == NULL) {
1492 error("%s: Signature key invalid", __func__);
1493 goto out;
1494 }
1495 if (!key_type_is_valid_ca(key->cert->signature_key->type)) {
1496 error("%s: Invalid signature key type %s (%d)", __func__,
1497 key_type(key->cert->signature_key),
1498 key->cert->signature_key->type);
1499 goto out;
1500 }
1501
1502 switch (key_verify(key->cert->signature_key, sig, slen,
1503 buffer_ptr(&key->cert->certblob), signed_len)) {
1504 case 1:
1505 ret = 0;
1506 break; /* Good signature */
1507 case 0:
1508 error("%s: Invalid signature on certificate", __func__);
1509 goto out;
1510 case -1:
1511 error("%s: Certificate signature verification failed",
1512 __func__);
1513 goto out;
1514 }
1515
1516 out:
1517 buffer_free(&tmp);
1518 free(principals);
1519 free(critical);
1520 free(exts);
1521 free(sig_key);
1522 free(sig);
1523 return ret; 100 return ret;
1524} 101}
1525 102
1526static Key * 103static void
1527key_from_blob2(const u_char *blob, u_int blen, int allow_cert) 104fatal_on_fatal_errors(int r, const char *func, int extra_fatal)
1528{ 105{
1529 Buffer b; 106 if (r == SSH_ERR_INTERNAL_ERROR ||
1530 int rlen, type; 107 r == SSH_ERR_ALLOC_FAIL ||
1531 u_int len; 108 (extra_fatal != 0 && r == extra_fatal))
1532 char *ktype = NULL, *curve = NULL; 109 fatal("%s: %s", func, ssh_err(r));
1533 u_char *pk = NULL;
1534 Key *key = NULL;
1535#ifdef OPENSSL_HAS_ECC
1536 EC_POINT *q = NULL;
1537 int nid = -1;
1538#endif
1539
1540#ifdef DEBUG_PK
1541 dump_base64(stderr, blob, blen);
1542#endif
1543 buffer_init(&b);
1544 buffer_append(&b, blob, blen);
1545 if ((ktype = buffer_get_cstring_ret(&b, NULL)) == NULL) {
1546 error("key_from_blob: can't read key type");
1547 goto out;
1548 }
1549
1550 type = key_type_from_name(ktype);
1551#ifdef OPENSSL_HAS_ECC
1552 if (key_type_plain(type) == KEY_ECDSA)
1553 nid = key_ecdsa_nid_from_name(ktype);
1554#endif
1555 if (!allow_cert && key_type_is_cert(type)) {
1556 error("key_from_blob: certificate not allowed in this context");
1557 goto out;
1558 }
1559 switch (type) {
1560 case KEY_RSA_CERT:
1561 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1562 /* FALLTHROUGH */
1563 case KEY_RSA:
1564 case KEY_RSA_CERT_V00:
1565 key = key_new(type);
1566 if (buffer_get_bignum2_ret(&b, key->rsa->e) == -1 ||
1567 buffer_get_bignum2_ret(&b, key->rsa->n) == -1) {
1568 error("key_from_blob: can't read rsa key");
1569 badkey:
1570 key_free(key);
1571 key = NULL;
1572 goto out;
1573 }
1574#ifdef DEBUG_PK
1575 RSA_print_fp(stderr, key->rsa, 8);
1576#endif
1577 break;
1578 case KEY_DSA_CERT:
1579 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1580 /* FALLTHROUGH */
1581 case KEY_DSA:
1582 case KEY_DSA_CERT_V00:
1583 key = key_new(type);
1584 if (buffer_get_bignum2_ret(&b, key->dsa->p) == -1 ||
1585 buffer_get_bignum2_ret(&b, key->dsa->q) == -1 ||
1586 buffer_get_bignum2_ret(&b, key->dsa->g) == -1 ||
1587 buffer_get_bignum2_ret(&b, key->dsa->pub_key) == -1) {
1588 error("key_from_blob: can't read dsa key");
1589 goto badkey;
1590 }
1591#ifdef DEBUG_PK
1592 DSA_print_fp(stderr, key->dsa, 8);
1593#endif
1594 break;
1595#ifdef OPENSSL_HAS_ECC
1596 case KEY_ECDSA_CERT:
1597 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1598 /* FALLTHROUGH */
1599 case KEY_ECDSA:
1600 key = key_new(type);
1601 key->ecdsa_nid = nid;
1602 if ((curve = buffer_get_string_ret(&b, NULL)) == NULL) {
1603 error("key_from_blob: can't read ecdsa curve");
1604 goto badkey;
1605 }
1606 if (key->ecdsa_nid != key_curve_name_to_nid(curve)) {
1607 error("key_from_blob: ecdsa curve doesn't match type");
1608 goto badkey;
1609 }
1610 if (key->ecdsa != NULL)
1611 EC_KEY_free(key->ecdsa);
1612 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
1613 == NULL)
1614 fatal("key_from_blob: EC_KEY_new_by_curve_name failed");
1615 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL)
1616 fatal("key_from_blob: EC_POINT_new failed");
1617 if (buffer_get_ecpoint_ret(&b, EC_KEY_get0_group(key->ecdsa),
1618 q) == -1) {
1619 error("key_from_blob: can't read ecdsa key point");
1620 goto badkey;
1621 }
1622 if (key_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
1623 q) != 0)
1624 goto badkey;
1625 if (EC_KEY_set_public_key(key->ecdsa, q) != 1)
1626 fatal("key_from_blob: EC_KEY_set_public_key failed");
1627#ifdef DEBUG_PK
1628 key_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
1629#endif
1630 break;
1631#endif /* OPENSSL_HAS_ECC */
1632 case KEY_ED25519_CERT:
1633 (void)buffer_get_string_ptr_ret(&b, NULL); /* Skip nonce */
1634 /* FALLTHROUGH */
1635 case KEY_ED25519:
1636 if ((pk = buffer_get_string_ret(&b, &len)) == NULL) {
1637 error("key_from_blob: can't read ed25519 key");
1638 goto badkey;
1639 }
1640 if (len != ED25519_PK_SZ) {
1641 error("key_from_blob: ed25519 len %d != %d",
1642 len, ED25519_PK_SZ);
1643 goto badkey;
1644 }
1645 key = key_new(type);
1646 key->ed25519_pk = pk;
1647 pk = NULL;
1648 break;
1649 case KEY_UNSPEC:
1650 key = key_new(type);
1651 break;
1652 default:
1653 error("key_from_blob: cannot handle type %s", ktype);
1654 goto out;
1655 }
1656 if (key_is_cert(key) && cert_parse(&b, key, blob, blen) == -1) {
1657 error("key_from_blob: can't parse cert data");
1658 goto badkey;
1659 }
1660 rlen = buffer_len(&b);
1661 if (key != NULL && rlen != 0)
1662 error("key_from_blob: remaining bytes in key blob %d", rlen);
1663 out:
1664 free(ktype);
1665 free(curve);
1666 free(pk);
1667#ifdef OPENSSL_HAS_ECC
1668 if (q != NULL)
1669 EC_POINT_free(q);
1670#endif
1671 buffer_free(&b);
1672 return key;
1673} 110}
1674 111
1675Key * 112Key *
1676key_from_blob(const u_char *blob, u_int blen) 113key_from_blob(const u_char *blob, u_int blen)
1677{ 114{
1678 return key_from_blob2(blob, blen, 1); 115 int r;
116 Key *ret = NULL;
117
118 if ((r = sshkey_from_blob(blob, blen, &ret)) != 0) {
119 fatal_on_fatal_errors(r, __func__, 0);
120 error("%s: %s", __func__, ssh_err(r));
121 return NULL;
122 }
123 return ret;
1679} 124}
1680 125
1681static int 126int
1682to_blob(const Key *key, u_char **blobp, u_int *lenp, int force_plain) 127key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
1683{ 128{
1684 Buffer b; 129 u_char *blob;
1685 int len, type; 130 size_t blen;
131 int r;
1686 132
1687 if (blobp != NULL) 133 if (blobp != NULL)
1688 *blobp = NULL; 134 *blobp = NULL;
1689 if (lenp != NULL) 135 if (lenp != NULL)
1690 *lenp = 0; 136 *lenp = 0;
1691 if (key == NULL) { 137 if ((r = sshkey_to_blob(key, &blob, &blen)) != 0) {
1692 error("key_to_blob: key == NULL"); 138 fatal_on_fatal_errors(r, __func__, 0);
1693 return 0; 139 error("%s: %s", __func__, ssh_err(r));
1694 }
1695 buffer_init(&b);
1696 type = force_plain ? key_type_plain(key->type) : key->type;
1697 switch (type) {
1698 case KEY_DSA_CERT_V00:
1699 case KEY_RSA_CERT_V00:
1700 case KEY_DSA_CERT:
1701 case KEY_ECDSA_CERT:
1702 case KEY_RSA_CERT:
1703 case KEY_ED25519_CERT:
1704 /* Use the existing blob */
1705 buffer_append(&b, buffer_ptr(&key->cert->certblob),
1706 buffer_len(&key->cert->certblob));
1707 break;
1708 case KEY_DSA:
1709 buffer_put_cstring(&b,
1710 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
1711 buffer_put_bignum2(&b, key->dsa->p);
1712 buffer_put_bignum2(&b, key->dsa->q);
1713 buffer_put_bignum2(&b, key->dsa->g);
1714 buffer_put_bignum2(&b, key->dsa->pub_key);
1715 break;
1716#ifdef OPENSSL_HAS_ECC
1717 case KEY_ECDSA:
1718 buffer_put_cstring(&b,
1719 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
1720 buffer_put_cstring(&b, key_curve_nid_to_name(key->ecdsa_nid));
1721 buffer_put_ecpoint(&b, EC_KEY_get0_group(key->ecdsa),
1722 EC_KEY_get0_public_key(key->ecdsa));
1723 break;
1724#endif
1725 case KEY_RSA:
1726 buffer_put_cstring(&b,
1727 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
1728 buffer_put_bignum2(&b, key->rsa->e);
1729 buffer_put_bignum2(&b, key->rsa->n);
1730 break;
1731 case KEY_ED25519:
1732 buffer_put_cstring(&b,
1733 key_ssh_name_from_type_nid(type, key->ecdsa_nid));
1734 buffer_put_string(&b, key->ed25519_pk, ED25519_PK_SZ);
1735 break;
1736 default:
1737 error("key_to_blob: unsupported key type %d", key->type);
1738 buffer_free(&b);
1739 return 0; 140 return 0;
1740 } 141 }
1741 len = buffer_len(&b); 142 if (blen > INT_MAX)
143 fatal("%s: giant len %zu", __func__, blen);
144 if (blobp != NULL)
145 *blobp = blob;
1742 if (lenp != NULL) 146 if (lenp != NULL)
1743 *lenp = len; 147 *lenp = blen;
1744 if (blobp != NULL) { 148 return blen;
1745 *blobp = xmalloc(len);
1746 memcpy(*blobp, buffer_ptr(&b), len);
1747 }
1748 explicit_bzero(buffer_ptr(&b), len);
1749 buffer_free(&b);
1750 return len;
1751}
1752
1753int
1754key_to_blob(const Key *key, u_char **blobp, u_int *lenp)
1755{
1756 return to_blob(key, blobp, lenp, 0);
1757} 149}
1758 150
1759int 151int
1760key_sign( 152key_sign(const Key *key, u_char **sigp, u_int *lenp,
1761 const Key *key,
1762 u_char **sigp, u_int *lenp,
1763 const u_char *data, u_int datalen) 153 const u_char *data, u_int datalen)
1764{ 154{
1765 switch (key->type) { 155 int r;
1766 case KEY_DSA_CERT_V00: 156 u_char *sig;
1767 case KEY_DSA_CERT: 157 size_t siglen;
1768 case KEY_DSA: 158
1769 return ssh_dss_sign(key, sigp, lenp, data, datalen); 159 if (sigp != NULL)
1770#ifdef OPENSSL_HAS_ECC 160 *sigp = NULL;
1771 case KEY_ECDSA_CERT: 161 if (lenp != NULL)
1772 case KEY_ECDSA: 162 *lenp = 0;
1773 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen); 163 if ((r = sshkey_sign(key, &sig, &siglen,
1774#endif 164 data, datalen, datafellows)) != 0) {
1775 case KEY_RSA_CERT_V00: 165 fatal_on_fatal_errors(r, __func__, 0);
1776 case KEY_RSA_CERT: 166 error("%s: %s", __func__, ssh_err(r));
1777 case KEY_RSA:
1778 return ssh_rsa_sign(key, sigp, lenp, data, datalen);
1779 case KEY_ED25519:
1780 case KEY_ED25519_CERT:
1781 return ssh_ed25519_sign(key, sigp, lenp, data, datalen);
1782 default:
1783 error("key_sign: invalid key type %d", key->type);
1784 return -1; 167 return -1;
1785 } 168 }
169 if (siglen > INT_MAX)
170 fatal("%s: giant len %zu", __func__, siglen);
171 if (sigp != NULL)
172 *sigp = sig;
173 if (lenp != NULL)
174 *lenp = siglen;
175 return 0;
1786} 176}
1787 177
1788/*
1789 * key_verify returns 1 for a correct signature, 0 for an incorrect signature
1790 * and -1 on error.
1791 */
1792int 178int
1793key_verify( 179key_verify(const Key *key, const u_char *signature, u_int signaturelen,
1794 const Key *key,
1795 const u_char *signature, u_int signaturelen,
1796 const u_char *data, u_int datalen) 180 const u_char *data, u_int datalen)
1797{ 181{
1798 if (signaturelen == 0) 182 int r;
1799 return -1;
1800 183
1801 switch (key->type) { 184 if ((r = sshkey_verify(key, signature, signaturelen,
1802 case KEY_DSA_CERT_V00: 185 data, datalen, datafellows)) != 0) {
1803 case KEY_DSA_CERT: 186 fatal_on_fatal_errors(r, __func__, 0);
1804 case KEY_DSA: 187 error("%s: %s", __func__, ssh_err(r));
1805 return ssh_dss_verify(key, signature, signaturelen, data, datalen); 188 return r == SSH_ERR_SIGNATURE_INVALID ? 0 : -1;
1806#ifdef OPENSSL_HAS_ECC
1807 case KEY_ECDSA_CERT:
1808 case KEY_ECDSA:
1809 return ssh_ecdsa_verify(key, signature, signaturelen, data, datalen);
1810#endif
1811 case KEY_RSA_CERT_V00:
1812 case KEY_RSA_CERT:
1813 case KEY_RSA:
1814 return ssh_rsa_verify(key, signature, signaturelen, data, datalen);
1815 case KEY_ED25519:
1816 case KEY_ED25519_CERT:
1817 return ssh_ed25519_verify(key, signature, signaturelen, data, datalen);
1818 default:
1819 error("key_verify: invalid key type %d", key->type);
1820 return -1;
1821 } 189 }
190 return 1;
1822} 191}
1823 192
1824/* Converts a private to a public key */
1825Key * 193Key *
1826key_demote(const Key *k) 194key_demote(const Key *k)
1827{ 195{
1828 Key *pk; 196 int r;
1829 197 Key *ret = NULL;
1830 pk = xcalloc(1, sizeof(*pk));
1831 pk->type = k->type;
1832 pk->flags = k->flags;
1833 pk->ecdsa_nid = k->ecdsa_nid;
1834 pk->dsa = NULL;
1835 pk->ecdsa = NULL;
1836 pk->rsa = NULL;
1837 pk->ed25519_pk = NULL;
1838 pk->ed25519_sk = NULL;
1839
1840 switch (k->type) {
1841 case KEY_RSA_CERT_V00:
1842 case KEY_RSA_CERT:
1843 key_cert_copy(k, pk);
1844 /* FALLTHROUGH */
1845 case KEY_RSA1:
1846 case KEY_RSA:
1847 if ((pk->rsa = RSA_new()) == NULL)
1848 fatal("key_demote: RSA_new failed");
1849 if ((pk->rsa->e = BN_dup(k->rsa->e)) == NULL)
1850 fatal("key_demote: BN_dup failed");
1851 if ((pk->rsa->n = BN_dup(k->rsa->n)) == NULL)
1852 fatal("key_demote: BN_dup failed");
1853 break;
1854 case KEY_DSA_CERT_V00:
1855 case KEY_DSA_CERT:
1856 key_cert_copy(k, pk);
1857 /* FALLTHROUGH */
1858 case KEY_DSA:
1859 if ((pk->dsa = DSA_new()) == NULL)
1860 fatal("key_demote: DSA_new failed");
1861 if ((pk->dsa->p = BN_dup(k->dsa->p)) == NULL)
1862 fatal("key_demote: BN_dup failed");
1863 if ((pk->dsa->q = BN_dup(k->dsa->q)) == NULL)
1864 fatal("key_demote: BN_dup failed");
1865 if ((pk->dsa->g = BN_dup(k->dsa->g)) == NULL)
1866 fatal("key_demote: BN_dup failed");
1867 if ((pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL)
1868 fatal("key_demote: BN_dup failed");
1869 break;
1870#ifdef OPENSSL_HAS_ECC
1871 case KEY_ECDSA_CERT:
1872 key_cert_copy(k, pk);
1873 /* FALLTHROUGH */
1874 case KEY_ECDSA:
1875 if ((pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid)) == NULL)
1876 fatal("key_demote: EC_KEY_new_by_curve_name failed");
1877 if (EC_KEY_set_public_key(pk->ecdsa,
1878 EC_KEY_get0_public_key(k->ecdsa)) != 1)
1879 fatal("key_demote: EC_KEY_set_public_key failed");
1880 break;
1881#endif
1882 case KEY_ED25519_CERT:
1883 key_cert_copy(k, pk);
1884 /* FALLTHROUGH */
1885 case KEY_ED25519:
1886 if (k->ed25519_pk != NULL) {
1887 pk->ed25519_pk = xmalloc(ED25519_PK_SZ);
1888 memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1889 }
1890 break;
1891 default:
1892 fatal("key_demote: bad key type %d", k->type);
1893 break;
1894 }
1895
1896 return (pk);
1897}
1898 198
1899int 199 if ((r = sshkey_demote(k, &ret)) != 0)
1900key_is_cert(const Key *k) 200 fatal("%s: %s", __func__, ssh_err(r));
1901{ 201 return ret;
1902 if (k == NULL)
1903 return 0;
1904 return key_type_is_cert(k->type);
1905}
1906
1907/* Return the cert-less equivalent to a certified key type */
1908int
1909key_type_plain(int type)
1910{
1911 switch (type) {
1912 case KEY_RSA_CERT_V00:
1913 case KEY_RSA_CERT:
1914 return KEY_RSA;
1915 case KEY_DSA_CERT_V00:
1916 case KEY_DSA_CERT:
1917 return KEY_DSA;
1918 case KEY_ECDSA_CERT:
1919 return KEY_ECDSA;
1920 case KEY_ED25519_CERT:
1921 return KEY_ED25519;
1922 default:
1923 return type;
1924 }
1925} 202}
1926 203
1927/* Convert a plain key to their _CERT equivalent */
1928int 204int
1929key_to_certified(Key *k, int legacy) 205key_to_certified(Key *k, int legacy)
1930{ 206{
1931 switch (k->type) { 207 int r;
1932 case KEY_RSA: 208
1933 k->cert = cert_new(); 209 if ((r = sshkey_to_certified(k, legacy)) != 0) {
1934 k->type = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT; 210 fatal_on_fatal_errors(r, __func__, 0);
1935 return 0; 211 error("%s: %s", __func__, ssh_err(r));
1936 case KEY_DSA:
1937 k->cert = cert_new();
1938 k->type = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
1939 return 0;
1940 case KEY_ECDSA:
1941 if (legacy)
1942 fatal("%s: legacy ECDSA certificates are not supported",
1943 __func__);
1944 k->cert = cert_new();
1945 k->type = KEY_ECDSA_CERT;
1946 return 0;
1947 case KEY_ED25519:
1948 if (legacy)
1949 fatal("%s: legacy ED25519 certificates are not "
1950 "supported", __func__);
1951 k->cert = cert_new();
1952 k->type = KEY_ED25519_CERT;
1953 return 0;
1954 default:
1955 error("%s: key has incorrect type %s", __func__, key_type(k));
1956 return -1; 212 return -1;
1957 } 213 }
214 return 0;
1958} 215}
1959 216
1960/* Convert a certificate to its raw key equivalent */
1961int 217int
1962key_drop_cert(Key *k) 218key_drop_cert(Key *k)
1963{ 219{
1964 if (!key_type_is_cert(k->type)) { 220 int r;
1965 error("%s: key has incorrect type %s", __func__, key_type(k)); 221
222 if ((r = sshkey_drop_cert(k)) != 0) {
223 fatal_on_fatal_errors(r, __func__, 0);
224 error("%s: %s", __func__, ssh_err(r));
1966 return -1; 225 return -1;
1967 } 226 }
1968 cert_free(k->cert);
1969 k->cert = NULL;
1970 k->type = key_type_plain(k->type);
1971 return 0; 227 return 0;
1972} 228}
1973 229
1974/* Sign a certified key, (re-)generating the signed certblob. */
1975int 230int
1976key_certify(Key *k, Key *ca) 231key_certify(Key *k, Key *ca)
1977{ 232{
1978 Buffer principals; 233 int r;
1979 u_char *ca_blob, *sig_blob, nonce[32];
1980 u_int i, ca_len, sig_len;
1981
1982 if (k->cert == NULL) {
1983 error("%s: key lacks cert info", __func__);
1984 return -1;
1985 }
1986
1987 if (!key_is_cert(k)) {
1988 error("%s: certificate has unknown type %d", __func__,
1989 k->cert->type);
1990 return -1;
1991 }
1992
1993 if (!key_type_is_valid_ca(ca->type)) {
1994 error("%s: CA key has unsupported type %s", __func__,
1995 key_type(ca));
1996 return -1;
1997 }
1998
1999 key_to_blob(ca, &ca_blob, &ca_len);
2000
2001 buffer_clear(&k->cert->certblob);
2002 buffer_put_cstring(&k->cert->certblob, key_ssh_name(k));
2003
2004 /* -v01 certs put nonce first */
2005 arc4random_buf(&nonce, sizeof(nonce));
2006 if (!key_cert_is_legacy(k))
2007 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
2008
2009 /* XXX this substantially duplicates to_blob(); refactor */
2010 switch (k->type) {
2011 case KEY_DSA_CERT_V00:
2012 case KEY_DSA_CERT:
2013 buffer_put_bignum2(&k->cert->certblob, k->dsa->p);
2014 buffer_put_bignum2(&k->cert->certblob, k->dsa->q);
2015 buffer_put_bignum2(&k->cert->certblob, k->dsa->g);
2016 buffer_put_bignum2(&k->cert->certblob, k->dsa->pub_key);
2017 break;
2018#ifdef OPENSSL_HAS_ECC
2019 case KEY_ECDSA_CERT:
2020 buffer_put_cstring(&k->cert->certblob,
2021 key_curve_nid_to_name(k->ecdsa_nid));
2022 buffer_put_ecpoint(&k->cert->certblob,
2023 EC_KEY_get0_group(k->ecdsa),
2024 EC_KEY_get0_public_key(k->ecdsa));
2025 break;
2026#endif
2027 case KEY_RSA_CERT_V00:
2028 case KEY_RSA_CERT:
2029 buffer_put_bignum2(&k->cert->certblob, k->rsa->e);
2030 buffer_put_bignum2(&k->cert->certblob, k->rsa->n);
2031 break;
2032 case KEY_ED25519_CERT:
2033 buffer_put_string(&k->cert->certblob,
2034 k->ed25519_pk, ED25519_PK_SZ);
2035 break;
2036 default:
2037 error("%s: key has incorrect type %s", __func__, key_type(k));
2038 buffer_clear(&k->cert->certblob);
2039 free(ca_blob);
2040 return -1;
2041 }
2042
2043 /* -v01 certs have a serial number next */
2044 if (!key_cert_is_legacy(k))
2045 buffer_put_int64(&k->cert->certblob, k->cert->serial);
2046
2047 buffer_put_int(&k->cert->certblob, k->cert->type);
2048 buffer_put_cstring(&k->cert->certblob, k->cert->key_id);
2049
2050 buffer_init(&principals);
2051 for (i = 0; i < k->cert->nprincipals; i++)
2052 buffer_put_cstring(&principals, k->cert->principals[i]);
2053 buffer_put_string(&k->cert->certblob, buffer_ptr(&principals),
2054 buffer_len(&principals));
2055 buffer_free(&principals);
2056
2057 buffer_put_int64(&k->cert->certblob, k->cert->valid_after);
2058 buffer_put_int64(&k->cert->certblob, k->cert->valid_before);
2059 buffer_put_string(&k->cert->certblob,
2060 buffer_ptr(&k->cert->critical), buffer_len(&k->cert->critical));
2061
2062 /* -v01 certs have non-critical options here */
2063 if (!key_cert_is_legacy(k)) {
2064 buffer_put_string(&k->cert->certblob,
2065 buffer_ptr(&k->cert->extensions),
2066 buffer_len(&k->cert->extensions));
2067 }
2068
2069 /* -v00 certs put the nonce at the end */
2070 if (key_cert_is_legacy(k))
2071 buffer_put_string(&k->cert->certblob, nonce, sizeof(nonce));
2072
2073 buffer_put_string(&k->cert->certblob, NULL, 0); /* reserved */
2074 buffer_put_string(&k->cert->certblob, ca_blob, ca_len);
2075 free(ca_blob);
2076 234
2077 /* Sign the whole mess */ 235 if ((r = sshkey_certify(k, ca)) != 0) {
2078 if (key_sign(ca, &sig_blob, &sig_len, buffer_ptr(&k->cert->certblob), 236 fatal_on_fatal_errors(r, __func__, 0);
2079 buffer_len(&k->cert->certblob)) != 0) { 237 error("%s: %s", __func__, ssh_err(r));
2080 error("%s: signature operation failed", __func__);
2081 buffer_clear(&k->cert->certblob);
2082 return -1; 238 return -1;
2083 } 239 }
2084 /* Append signature and we are done */
2085 buffer_put_string(&k->cert->certblob, sig_blob, sig_len);
2086 free(sig_blob);
2087
2088 return 0; 240 return 0;
2089} 241}
2090 242
@@ -2092,535 +244,236 @@ int
2092key_cert_check_authority(const Key *k, int want_host, int require_principal, 244key_cert_check_authority(const Key *k, int want_host, int require_principal,
2093 const char *name, const char **reason) 245 const char *name, const char **reason)
2094{ 246{
2095 u_int i, principal_matches; 247 int r;
2096 time_t now = time(NULL); 248
2097 249 if ((r = sshkey_cert_check_authority(k, want_host, require_principal,
2098 if (want_host) { 250 name, reason)) != 0) {
2099 if (k->cert->type != SSH2_CERT_TYPE_HOST) { 251 fatal_on_fatal_errors(r, __func__, 0);
2100 *reason = "Certificate invalid: not a host certificate"; 252 error("%s: %s", __func__, ssh_err(r));
2101 return -1;
2102 }
2103 } else {
2104 if (k->cert->type != SSH2_CERT_TYPE_USER) {
2105 *reason = "Certificate invalid: not a user certificate";
2106 return -1;
2107 }
2108 }
2109 if (now < 0) {
2110 error("%s: system clock lies before epoch", __func__);
2111 *reason = "Certificate invalid: not yet valid";
2112 return -1;
2113 }
2114 if ((u_int64_t)now < k->cert->valid_after) {
2115 *reason = "Certificate invalid: not yet valid";
2116 return -1;
2117 }
2118 if ((u_int64_t)now >= k->cert->valid_before) {
2119 *reason = "Certificate invalid: expired";
2120 return -1; 253 return -1;
2121 } 254 }
2122 if (k->cert->nprincipals == 0) {
2123 if (require_principal) {
2124 *reason = "Certificate lacks principal list";
2125 return -1;
2126 }
2127 } else if (name != NULL) {
2128 principal_matches = 0;
2129 for (i = 0; i < k->cert->nprincipals; i++) {
2130 if (strcmp(name, k->cert->principals[i]) == 0) {
2131 principal_matches = 1;
2132 break;
2133 }
2134 }
2135 if (!principal_matches) {
2136 *reason = "Certificate invalid: name is not a listed "
2137 "principal";
2138 return -1;
2139 }
2140 }
2141 return 0; 255 return 0;
2142} 256}
2143 257
258#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2144int 259int
2145key_cert_is_legacy(const Key *k) 260key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2146{ 261{
2147 switch (k->type) { 262 int r;
2148 case KEY_DSA_CERT_V00: 263
2149 case KEY_RSA_CERT_V00: 264 if ((r = sshkey_ec_validate_public(group, public)) != 0) {
2150 return 1; 265 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2151 default: 266 error("%s: %s", __func__, ssh_err(r));
2152 return 0; 267 return -1;
2153 } 268 }
269 return 0;
2154} 270}
2155 271
2156/* XXX: these are really begging for a table-driven approach */
2157int 272int
2158key_curve_name_to_nid(const char *name) 273key_ec_validate_private(const EC_KEY *key)
2159{ 274{
2160#ifdef OPENSSL_HAS_ECC 275 int r;
2161 if (strcmp(name, "nistp256") == 0) 276
2162 return NID_X9_62_prime256v1; 277 if ((r = sshkey_ec_validate_private(key)) != 0) {
2163 else if (strcmp(name, "nistp384") == 0) 278 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2164 return NID_secp384r1; 279 error("%s: %s", __func__, ssh_err(r));
2165# ifdef OPENSSL_HAS_NISTP521 280 return -1;
2166 else if (strcmp(name, "nistp521") == 0) 281 }
2167 return NID_secp521r1; 282 return 0;
2168# endif
2169#endif
2170
2171 debug("%s: unsupported EC curve name \"%.100s\"", __func__, name);
2172 return -1;
2173} 283}
284#endif /* WITH_OPENSSL */
2174 285
2175u_int 286void
2176key_curve_nid_to_bits(int nid) 287key_private_serialize(const Key *key, struct sshbuf *b)
2177{ 288{
2178 switch (nid) { 289 int r;
2179#ifdef OPENSSL_HAS_ECC 290
2180 case NID_X9_62_prime256v1: 291 if ((r = sshkey_private_serialize(key, b)) != 0)
2181 return 256; 292 fatal("%s: %s", __func__, ssh_err(r));
2182 case NID_secp384r1:
2183 return 384;
2184# ifdef OPENSSL_HAS_NISTP521
2185 case NID_secp521r1:
2186 return 521;
2187# endif
2188#endif
2189 default:
2190 error("%s: unsupported EC curve nid %d", __func__, nid);
2191 return 0;
2192 }
2193} 293}
2194 294
2195const char * 295Key *
2196key_curve_nid_to_name(int nid) 296key_private_deserialize(struct sshbuf *blob)
2197{ 297{
2198#ifdef OPENSSL_HAS_ECC 298 int r;
2199 if (nid == NID_X9_62_prime256v1) 299 Key *ret = NULL;
2200 return "nistp256"; 300
2201 else if (nid == NID_secp384r1) 301 if ((r = sshkey_private_deserialize(blob, &ret)) != 0) {
2202 return "nistp384"; 302 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2203# ifdef OPENSSL_HAS_NISTP521 303 error("%s: %s", __func__, ssh_err(r));
2204 else if (nid == NID_secp521r1) 304 return NULL;
2205 return "nistp521"; 305 }
2206# endif 306 return ret;
2207#endif
2208 error("%s: unsupported EC curve nid %d", __func__, nid);
2209 return NULL;
2210} 307}
2211 308
2212#ifdef OPENSSL_HAS_ECC 309/* authfile.c */
310
2213int 311int
2214key_ec_nid_to_hash_alg(int nid) 312key_save_private(Key *key, const char *filename, const char *passphrase,
313 const char *comment, int force_new_format, const char *new_format_cipher,
314 int new_format_rounds)
2215{ 315{
2216 int kbits = key_curve_nid_to_bits(nid); 316 int r;
2217 317
2218 if (kbits == 0) 318 if ((r = sshkey_save_private(key, filename, passphrase, comment,
2219 fatal("%s: invalid nid %d", __func__, nid); 319 force_new_format, new_format_cipher, new_format_rounds)) != 0) {
2220 /* RFC5656 section 6.2.1 */ 320 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2221 if (kbits <= 256) 321 error("%s: %s", __func__, ssh_err(r));
2222 return SSH_DIGEST_SHA256; 322 return 0;
2223 else if (kbits <= 384) 323 }
2224 return SSH_DIGEST_SHA384; 324 return 1;
2225 else
2226 return SSH_DIGEST_SHA512;
2227} 325}
2228 326
2229int 327int
2230key_ec_validate_public(const EC_GROUP *group, const EC_POINT *public) 328key_load_file(int fd, const char *filename, struct sshbuf *blob)
2231{ 329{
2232 BN_CTX *bnctx; 330 int r;
2233 EC_POINT *nq = NULL;
2234 BIGNUM *order, *x, *y, *tmp;
2235 int ret = -1;
2236
2237 if ((bnctx = BN_CTX_new()) == NULL)
2238 fatal("%s: BN_CTX_new failed", __func__);
2239 BN_CTX_start(bnctx);
2240
2241 /*
2242 * We shouldn't ever hit this case because bignum_get_ecpoint()
2243 * refuses to load GF2m points.
2244 */
2245 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2246 NID_X9_62_prime_field) {
2247 error("%s: group is not a prime field", __func__);
2248 goto out;
2249 }
2250 331
2251 /* Q != infinity */ 332 if ((r = sshkey_load_file(fd, filename, blob)) != 0) {
2252 if (EC_POINT_is_at_infinity(group, public)) { 333 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2253 error("%s: received degenerate public key (infinity)", 334 error("%s: %s", __func__, ssh_err(r));
2254 __func__); 335 return 0;
2255 goto out;
2256 } 336 }
337 return 1;
338}
2257 339
2258 if ((x = BN_CTX_get(bnctx)) == NULL || 340Key *
2259 (y = BN_CTX_get(bnctx)) == NULL || 341key_load_cert(const char *filename)
2260 (order = BN_CTX_get(bnctx)) == NULL || 342{
2261 (tmp = BN_CTX_get(bnctx)) == NULL) 343 int r;
2262 fatal("%s: BN_CTX_get failed", __func__); 344 Key *ret = NULL;
2263 345
2264 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */ 346 if ((r = sshkey_load_cert(filename, &ret)) != 0) {
2265 if (EC_GROUP_get_order(group, order, bnctx) != 1) 347 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2266 fatal("%s: EC_GROUP_get_order failed", __func__); 348 /* Old authfile.c ignored all file errors. */
2267 if (EC_POINT_get_affine_coordinates_GFp(group, public, 349 if (r == SSH_ERR_SYSTEM_ERROR)
2268 x, y, bnctx) != 1) 350 debug("%s: %s", __func__, ssh_err(r));
2269 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__); 351 else
2270 if (BN_num_bits(x) <= BN_num_bits(order) / 2) { 352 error("%s: %s", __func__, ssh_err(r));
2271 error("%s: public key x coordinate too small: " 353 return NULL;
2272 "bits(x) = %d, bits(order)/2 = %d", __func__,
2273 BN_num_bits(x), BN_num_bits(order) / 2);
2274 goto out;
2275 }
2276 if (BN_num_bits(y) <= BN_num_bits(order) / 2) {
2277 error("%s: public key y coordinate too small: "
2278 "bits(y) = %d, bits(order)/2 = %d", __func__,
2279 BN_num_bits(x), BN_num_bits(order) / 2);
2280 goto out;
2281 } 354 }
355 return ret;
2282 356
2283 /* nQ == infinity (n == order of subgroup) */ 357}
2284 if ((nq = EC_POINT_new(group)) == NULL)
2285 fatal("%s: BN_CTX_tmp failed", __func__);
2286 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1)
2287 fatal("%s: EC_GROUP_mul failed", __func__);
2288 if (EC_POINT_is_at_infinity(group, nq) != 1) {
2289 error("%s: received degenerate public key (nQ != infinity)",
2290 __func__);
2291 goto out;
2292 }
2293 358
2294 /* x < order - 1, y < order - 1 */ 359Key *
2295 if (!BN_sub(tmp, order, BN_value_one())) 360key_load_public(const char *filename, char **commentp)
2296 fatal("%s: BN_sub failed", __func__); 361{
2297 if (BN_cmp(x, tmp) >= 0) { 362 int r;
2298 error("%s: public key x coordinate >= group order - 1", 363 Key *ret = NULL;
2299 __func__); 364
2300 goto out; 365 if ((r = sshkey_load_public(filename, &ret, commentp)) != 0) {
2301 } 366 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2302 if (BN_cmp(y, tmp) >= 0) { 367 /* Old authfile.c ignored all file errors. */
2303 error("%s: public key y coordinate >= group order - 1", 368 if (r == SSH_ERR_SYSTEM_ERROR)
2304 __func__); 369 debug("%s: %s", __func__, ssh_err(r));
2305 goto out; 370 else
371 error("%s: %s", __func__, ssh_err(r));
372 return NULL;
2306 } 373 }
2307 ret = 0;
2308 out:
2309 BN_CTX_free(bnctx);
2310 EC_POINT_free(nq);
2311 return ret; 374 return ret;
2312} 375}
2313 376
2314int 377Key *
2315key_ec_validate_private(const EC_KEY *key) 378key_load_private(const char *path, const char *passphrase,
2316{ 379 char **commentp)
2317 BN_CTX *bnctx; 380{
2318 BIGNUM *order, *tmp; 381 int r;
2319 int ret = -1; 382 Key *ret = NULL;
2320 383
2321 if ((bnctx = BN_CTX_new()) == NULL) 384 if ((r = sshkey_load_private(path, passphrase, &ret, commentp)) != 0) {
2322 fatal("%s: BN_CTX_new failed", __func__); 385 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2323 BN_CTX_start(bnctx); 386 /* Old authfile.c ignored all file errors. */
2324 387 if (r == SSH_ERR_SYSTEM_ERROR ||
2325 if ((order = BN_CTX_get(bnctx)) == NULL || 388 r == SSH_ERR_KEY_WRONG_PASSPHRASE)
2326 (tmp = BN_CTX_get(bnctx)) == NULL) 389 debug("%s: %s", __func__, ssh_err(r));
2327 fatal("%s: BN_CTX_get failed", __func__); 390 else
2328 391 error("%s: %s", __func__, ssh_err(r));
2329 /* log2(private) > log2(order)/2 */ 392 return NULL;
2330 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1)
2331 fatal("%s: EC_GROUP_get_order failed", __func__);
2332 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2333 BN_num_bits(order) / 2) {
2334 error("%s: private key too small: "
2335 "bits(y) = %d, bits(order)/2 = %d", __func__,
2336 BN_num_bits(EC_KEY_get0_private_key(key)),
2337 BN_num_bits(order) / 2);
2338 goto out;
2339 } 393 }
394 return ret;
395}
2340 396
2341 /* private < order - 1 */ 397Key *
2342 if (!BN_sub(tmp, order, BN_value_one())) 398key_load_private_cert(int type, const char *filename, const char *passphrase,
2343 fatal("%s: BN_sub failed", __func__); 399 int *perm_ok)
2344 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0) { 400{
2345 error("%s: private key >= group order - 1", __func__); 401 int r;
2346 goto out; 402 Key *ret = NULL;
403
404 if ((r = sshkey_load_private_cert(type, filename, passphrase,
405 &ret, perm_ok)) != 0) {
406 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
407 /* Old authfile.c ignored all file errors. */
408 if (r == SSH_ERR_SYSTEM_ERROR ||
409 r == SSH_ERR_KEY_WRONG_PASSPHRASE)
410 debug("%s: %s", __func__, ssh_err(r));
411 else
412 error("%s: %s", __func__, ssh_err(r));
413 return NULL;
2347 } 414 }
2348 ret = 0;
2349 out:
2350 BN_CTX_free(bnctx);
2351 return ret; 415 return ret;
2352} 416}
2353 417
2354#if defined(DEBUG_KEXECDH) || defined(DEBUG_PK) 418Key *
2355void 419key_load_private_type(int type, const char *filename, const char *passphrase,
2356key_dump_ec_point(const EC_GROUP *group, const EC_POINT *point) 420 char **commentp, int *perm_ok)
2357{ 421{
2358 BIGNUM *x, *y; 422 int r;
2359 BN_CTX *bnctx; 423 Key *ret = NULL;
2360 424
2361 if (point == NULL) { 425 if ((r = sshkey_load_private_type(type, filename, passphrase,
2362 fputs("point=(NULL)\n", stderr); 426 &ret, commentp, perm_ok)) != 0) {
2363 return; 427 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
428 /* Old authfile.c ignored all file errors. */
429 if (r == SSH_ERR_SYSTEM_ERROR ||
430 (r == SSH_ERR_KEY_WRONG_PASSPHRASE))
431 debug("%s: %s", __func__, ssh_err(r));
432 else
433 error("%s: %s", __func__, ssh_err(r));
434 return NULL;
2364 } 435 }
2365 if ((bnctx = BN_CTX_new()) == NULL) 436 return ret;
2366 fatal("%s: BN_CTX_new failed", __func__);
2367 BN_CTX_start(bnctx);
2368 if ((x = BN_CTX_get(bnctx)) == NULL || (y = BN_CTX_get(bnctx)) == NULL)
2369 fatal("%s: BN_CTX_get failed", __func__);
2370 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2371 NID_X9_62_prime_field)
2372 fatal("%s: group is not a prime field", __func__);
2373 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y, bnctx) != 1)
2374 fatal("%s: EC_POINT_get_affine_coordinates_GFp", __func__);
2375 fputs("x=", stderr);
2376 BN_print_fp(stderr, x);
2377 fputs("\ny=", stderr);
2378 BN_print_fp(stderr, y);
2379 fputs("\n", stderr);
2380 BN_CTX_free(bnctx);
2381} 437}
2382 438
2383void 439#ifdef WITH_OPENSSL
2384key_dump_ec_key(const EC_KEY *key) 440Key *
2385{ 441key_load_private_pem(int fd, int type, const char *passphrase,
2386 const BIGNUM *exponent; 442 char **commentp)
2387 443{
2388 key_dump_ec_point(EC_KEY_get0_group(key), EC_KEY_get0_public_key(key)); 444 int r;
2389 fputs("exponent=", stderr); 445 Key *ret = NULL;
2390 if ((exponent = EC_KEY_get0_private_key(key)) == NULL) 446
2391 fputs("(NULL)", stderr); 447 if ((r = sshkey_load_private_pem(fd, type, passphrase,
2392 else 448 &ret, commentp)) != 0) {
2393 BN_print_fp(stderr, EC_KEY_get0_private_key(key)); 449 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2394 fputs("\n", stderr); 450 if (r == SSH_ERR_KEY_WRONG_PASSPHRASE)
451 debug("%s: %s", __func__, ssh_err(r));
452 else
453 error("%s: %s", __func__, ssh_err(r));
454 return NULL;
455 }
456 return ret;
2395} 457}
2396#endif /* defined(DEBUG_KEXECDH) || defined(DEBUG_PK) */ 458#endif /* WITH_OPENSSL */
2397#endif /* OPENSSL_HAS_ECC */
2398 459
2399void 460int
2400key_private_serialize(const Key *key, Buffer *b) 461key_perm_ok(int fd, const char *filename)
2401{ 462{
2402 buffer_put_cstring(b, key_ssh_name(key)); 463 return sshkey_perm_ok(fd, filename) == 0 ? 1 : 0;
2403 switch (key->type) {
2404 case KEY_RSA:
2405 buffer_put_bignum2(b, key->rsa->n);
2406 buffer_put_bignum2(b, key->rsa->e);
2407 buffer_put_bignum2(b, key->rsa->d);
2408 buffer_put_bignum2(b, key->rsa->iqmp);
2409 buffer_put_bignum2(b, key->rsa->p);
2410 buffer_put_bignum2(b, key->rsa->q);
2411 break;
2412 case KEY_RSA_CERT_V00:
2413 case KEY_RSA_CERT:
2414 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2415 fatal("%s: no cert/certblob", __func__);
2416 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2417 buffer_len(&key->cert->certblob));
2418 buffer_put_bignum2(b, key->rsa->d);
2419 buffer_put_bignum2(b, key->rsa->iqmp);
2420 buffer_put_bignum2(b, key->rsa->p);
2421 buffer_put_bignum2(b, key->rsa->q);
2422 break;
2423 case KEY_DSA:
2424 buffer_put_bignum2(b, key->dsa->p);
2425 buffer_put_bignum2(b, key->dsa->q);
2426 buffer_put_bignum2(b, key->dsa->g);
2427 buffer_put_bignum2(b, key->dsa->pub_key);
2428 buffer_put_bignum2(b, key->dsa->priv_key);
2429 break;
2430 case KEY_DSA_CERT_V00:
2431 case KEY_DSA_CERT:
2432 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2433 fatal("%s: no cert/certblob", __func__);
2434 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2435 buffer_len(&key->cert->certblob));
2436 buffer_put_bignum2(b, key->dsa->priv_key);
2437 break;
2438#ifdef OPENSSL_HAS_ECC
2439 case KEY_ECDSA:
2440 buffer_put_cstring(b, key_curve_nid_to_name(key->ecdsa_nid));
2441 buffer_put_ecpoint(b, EC_KEY_get0_group(key->ecdsa),
2442 EC_KEY_get0_public_key(key->ecdsa));
2443 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
2444 break;
2445 case KEY_ECDSA_CERT:
2446 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2447 fatal("%s: no cert/certblob", __func__);
2448 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2449 buffer_len(&key->cert->certblob));
2450 buffer_put_bignum2(b, EC_KEY_get0_private_key(key->ecdsa));
2451 break;
2452#endif /* OPENSSL_HAS_ECC */
2453 case KEY_ED25519:
2454 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
2455 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
2456 break;
2457 case KEY_ED25519_CERT:
2458 if (key->cert == NULL || buffer_len(&key->cert->certblob) == 0)
2459 fatal("%s: no cert/certblob", __func__);
2460 buffer_put_string(b, buffer_ptr(&key->cert->certblob),
2461 buffer_len(&key->cert->certblob));
2462 buffer_put_string(b, key->ed25519_pk, ED25519_PK_SZ);
2463 buffer_put_string(b, key->ed25519_sk, ED25519_SK_SZ);
2464 break;
2465 }
2466} 464}
2467 465
2468Key * 466int
2469key_private_deserialize(Buffer *blob) 467key_in_file(Key *key, const char *filename, int strict_type)
2470{ 468{
2471 char *type_name; 469 int r;
2472 Key *k = NULL; 470
2473 u_char *cert; 471 if ((r = sshkey_in_file(key, filename, strict_type)) != 0) {
2474 u_int len, pklen, sklen; 472 fatal_on_fatal_errors(r, __func__, SSH_ERR_LIBCRYPTO_ERROR);
2475 int type; 473 if (r == SSH_ERR_SYSTEM_ERROR && errno == ENOENT)
2476#ifdef OPENSSL_HAS_ECC 474 return 0;
2477 char *curve; 475 error("%s: %s", __func__, ssh_err(r));
2478 BIGNUM *exponent; 476 return r == SSH_ERR_KEY_NOT_FOUND ? 0 : -1;
2479 EC_POINT *q;
2480#endif
2481
2482 type_name = buffer_get_string(blob, NULL);
2483 type = key_type_from_name(type_name);
2484 switch (type) {
2485 case KEY_DSA:
2486 k = key_new_private(type);
2487 buffer_get_bignum2(blob, k->dsa->p);
2488 buffer_get_bignum2(blob, k->dsa->q);
2489 buffer_get_bignum2(blob, k->dsa->g);
2490 buffer_get_bignum2(blob, k->dsa->pub_key);
2491 buffer_get_bignum2(blob, k->dsa->priv_key);
2492 break;
2493 case KEY_DSA_CERT_V00:
2494 case KEY_DSA_CERT:
2495 cert = buffer_get_string(blob, &len);
2496 if ((k = key_from_blob(cert, len)) == NULL)
2497 fatal("Certificate parse failed");
2498 free(cert);
2499 key_add_private(k);
2500 buffer_get_bignum2(blob, k->dsa->priv_key);
2501 break;
2502#ifdef OPENSSL_HAS_ECC
2503 case KEY_ECDSA:
2504 k = key_new_private(type);
2505 k->ecdsa_nid = key_ecdsa_nid_from_name(type_name);
2506 curve = buffer_get_string(blob, NULL);
2507 if (k->ecdsa_nid != key_curve_name_to_nid(curve))
2508 fatal("%s: curve names mismatch", __func__);
2509 free(curve);
2510 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
2511 if (k->ecdsa == NULL)
2512 fatal("%s: EC_KEY_new_by_curve_name failed",
2513 __func__);
2514 q = EC_POINT_new(EC_KEY_get0_group(k->ecdsa));
2515 if (q == NULL)
2516 fatal("%s: BN_new failed", __func__);
2517 if ((exponent = BN_new()) == NULL)
2518 fatal("%s: BN_new failed", __func__);
2519 buffer_get_ecpoint(blob,
2520 EC_KEY_get0_group(k->ecdsa), q);
2521 buffer_get_bignum2(blob, exponent);
2522 if (EC_KEY_set_public_key(k->ecdsa, q) != 1)
2523 fatal("%s: EC_KEY_set_public_key failed",
2524 __func__);
2525 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
2526 fatal("%s: EC_KEY_set_private_key failed",
2527 __func__);
2528 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2529 EC_KEY_get0_public_key(k->ecdsa)) != 0)
2530 fatal("%s: bad ECDSA public key", __func__);
2531 if (key_ec_validate_private(k->ecdsa) != 0)
2532 fatal("%s: bad ECDSA private key", __func__);
2533 BN_clear_free(exponent);
2534 EC_POINT_free(q);
2535 break;
2536 case KEY_ECDSA_CERT:
2537 cert = buffer_get_string(blob, &len);
2538 if ((k = key_from_blob(cert, len)) == NULL)
2539 fatal("Certificate parse failed");
2540 free(cert);
2541 key_add_private(k);
2542 if ((exponent = BN_new()) == NULL)
2543 fatal("%s: BN_new failed", __func__);
2544 buffer_get_bignum2(blob, exponent);
2545 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1)
2546 fatal("%s: EC_KEY_set_private_key failed",
2547 __func__);
2548 if (key_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2549 EC_KEY_get0_public_key(k->ecdsa)) != 0 ||
2550 key_ec_validate_private(k->ecdsa) != 0)
2551 fatal("%s: bad ECDSA key", __func__);
2552 BN_clear_free(exponent);
2553 break;
2554#endif
2555 case KEY_RSA:
2556 k = key_new_private(type);
2557 buffer_get_bignum2(blob, k->rsa->n);
2558 buffer_get_bignum2(blob, k->rsa->e);
2559 buffer_get_bignum2(blob, k->rsa->d);
2560 buffer_get_bignum2(blob, k->rsa->iqmp);
2561 buffer_get_bignum2(blob, k->rsa->p);
2562 buffer_get_bignum2(blob, k->rsa->q);
2563
2564 /* Generate additional parameters */
2565 rsa_generate_additional_parameters(k->rsa);
2566 break;
2567 case KEY_RSA_CERT_V00:
2568 case KEY_RSA_CERT:
2569 cert = buffer_get_string(blob, &len);
2570 if ((k = key_from_blob(cert, len)) == NULL)
2571 fatal("Certificate parse failed");
2572 free(cert);
2573 key_add_private(k);
2574 buffer_get_bignum2(blob, k->rsa->d);
2575 buffer_get_bignum2(blob, k->rsa->iqmp);
2576 buffer_get_bignum2(blob, k->rsa->p);
2577 buffer_get_bignum2(blob, k->rsa->q);
2578 break;
2579 case KEY_ED25519:
2580 k = key_new_private(type);
2581 k->ed25519_pk = buffer_get_string(blob, &pklen);
2582 k->ed25519_sk = buffer_get_string(blob, &sklen);
2583 if (pklen != ED25519_PK_SZ)
2584 fatal("%s: ed25519 pklen %d != %d",
2585 __func__, pklen, ED25519_PK_SZ);
2586 if (sklen != ED25519_SK_SZ)
2587 fatal("%s: ed25519 sklen %d != %d",
2588 __func__, sklen, ED25519_SK_SZ);
2589 break;
2590 case KEY_ED25519_CERT:
2591 cert = buffer_get_string(blob, &len);
2592 if ((k = key_from_blob(cert, len)) == NULL)
2593 fatal("Certificate parse failed");
2594 free(cert);
2595 key_add_private(k);
2596 k->ed25519_pk = buffer_get_string(blob, &pklen);
2597 k->ed25519_sk = buffer_get_string(blob, &sklen);
2598 if (pklen != ED25519_PK_SZ)
2599 fatal("%s: ed25519 pklen %d != %d",
2600 __func__, pklen, ED25519_PK_SZ);
2601 if (sklen != ED25519_SK_SZ)
2602 fatal("%s: ed25519 sklen %d != %d",
2603 __func__, sklen, ED25519_SK_SZ);
2604 break;
2605 default:
2606 free(type_name);
2607 buffer_clear(blob);
2608 return NULL;
2609 }
2610 free(type_name);
2611
2612 /* enable blinding */
2613 switch (k->type) {
2614 case KEY_RSA:
2615 case KEY_RSA_CERT_V00:
2616 case KEY_RSA_CERT:
2617 case KEY_RSA1:
2618 if (RSA_blinding_on(k->rsa, NULL) != 1) {
2619 error("%s: RSA_blinding_on failed", __func__);
2620 key_free(k);
2621 return NULL;
2622 }
2623 break;
2624 } 477 }
2625 return k; 478 return 1;
2626} 479}
diff --git a/key.h b/key.h
index c8aeba29e..c6401a576 100644
--- a/key.h
+++ b/key.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: key.h,v 1.41 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: key.h,v 1.42 2014/06/24 01:13:21 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
@@ -26,142 +26,86 @@
26#ifndef KEY_H 26#ifndef KEY_H
27#define KEY_H 27#define KEY_H
28 28
29#include "buffer.h" 29#include "sshkey.h"
30#include <openssl/rsa.h> 30
31#include <openssl/dsa.h> 31typedef struct sshkey Key;
32#ifdef OPENSSL_HAS_ECC 32
33#include <openssl/ec.h> 33#define types sshkey_types
34#define fp_type sshkey_fp_type
35#define fp_rep sshkey_fp_rep
36
37#ifndef SSH_KEY_NO_DEFINE
38#define key_new sshkey_new
39#define key_free sshkey_free
40#define key_equal_public sshkey_equal_public
41#define key_equal sshkey_equal
42#define key_fingerprint sshkey_fingerprint
43#define key_type sshkey_type
44#define key_cert_type sshkey_cert_type
45#define key_ssh_name sshkey_ssh_name
46#define key_ssh_name_plain sshkey_ssh_name_plain
47#define key_type_from_name sshkey_type_from_name
48#define key_ecdsa_nid_from_name sshkey_ecdsa_nid_from_name
49#define key_type_is_cert sshkey_type_is_cert
50#define key_size sshkey_size
51#define key_ecdsa_bits_to_nid sshkey_ecdsa_bits_to_nid
52#define key_ecdsa_key_to_nid sshkey_ecdsa_key_to_nid
53#define key_names_valid2 sshkey_names_valid2
54#define key_is_cert sshkey_is_cert
55#define key_type_plain sshkey_type_plain
56#define key_cert_is_legacy sshkey_cert_is_legacy
57#define key_curve_name_to_nid sshkey_curve_name_to_nid
58#define key_curve_nid_to_bits sshkey_curve_nid_to_bits
59#define key_curve_nid_to_name sshkey_curve_nid_to_name
60#define key_ec_nid_to_hash_alg sshkey_ec_nid_to_hash_alg
61#define key_dump_ec_point sshkey_dump_ec_point
62#define key_dump_ec_key sshkey_dump_ec_key
63#define key_fingerprint sshkey_fingerprint
34#endif 64#endif
35 65
36typedef struct Key Key; 66void key_add_private(Key *);
37enum types { 67Key *key_new_private(int);
38 KEY_RSA1, 68void key_free(Key *);
39 KEY_RSA, 69Key *key_demote(const Key *);
40 KEY_DSA, 70u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
41 KEY_ECDSA, 71int key_write(const Key *, FILE *);
42 KEY_ED25519, 72int key_read(Key *, char **);
43 KEY_RSA_CERT,
44 KEY_DSA_CERT,
45 KEY_ECDSA_CERT,
46 KEY_ED25519_CERT,
47 KEY_RSA_CERT_V00,
48 KEY_DSA_CERT_V00,
49 KEY_NULL,
50 KEY_UNSPEC
51};
52enum fp_type {
53 SSH_FP_SHA1,
54 SSH_FP_MD5,
55 SSH_FP_SHA256
56};
57enum fp_rep {
58 SSH_FP_HEX,
59 SSH_FP_BUBBLEBABBLE,
60 SSH_FP_RANDOMART
61};
62
63/* key is stored in external hardware */
64#define KEY_FLAG_EXT 0x0001
65
66#define CERT_MAX_PRINCIPALS 256
67struct KeyCert {
68 Buffer certblob; /* Kept around for use on wire */
69 u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
70 u_int64_t serial;
71 char *key_id;
72 u_int nprincipals;
73 char **principals;
74 u_int64_t valid_after, valid_before;
75 Buffer critical;
76 Buffer extensions;
77 Key *signature_key;
78};
79
80struct Key {
81 int type;
82 int flags;
83 RSA *rsa;
84 DSA *dsa;
85 int ecdsa_nid; /* NID of curve */
86#ifdef OPENSSL_HAS_ECC
87 EC_KEY *ecdsa;
88#else
89 void *ecdsa;
90#endif
91 struct KeyCert *cert;
92 u_char *ed25519_sk;
93 u_char *ed25519_pk;
94};
95
96#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
97#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES
98
99Key *key_new(int);
100void key_add_private(Key *);
101Key *key_new_private(int);
102void key_free(Key *);
103Key *key_demote(const Key *);
104int key_equal_public(const Key *, const Key *);
105int key_equal(const Key *, const Key *);
106char *key_fingerprint(const Key *, enum fp_type, enum fp_rep);
107u_char *key_fingerprint_raw(const Key *, enum fp_type, u_int *);
108const char *key_type(const Key *);
109const char *key_cert_type(const Key *);
110int key_write(const Key *, FILE *);
111int key_read(Key *, char **);
112u_int key_size(const Key *);
113 73
114Key *key_generate(int, u_int); 74Key *key_generate(int, u_int);
115Key *key_from_private(const Key *); 75Key *key_from_private(const Key *);
116int key_type_from_name(char *);
117int key_is_cert(const Key *);
118int key_type_is_cert(int);
119int key_type_plain(int);
120int key_to_certified(Key *, int); 76int key_to_certified(Key *, int);
121int key_drop_cert(Key *); 77int key_drop_cert(Key *);
122int key_certify(Key *, Key *); 78int key_certify(Key *, Key *);
123void key_cert_copy(const Key *, struct Key *); 79void key_cert_copy(const Key *, Key *);
124int key_cert_check_authority(const Key *, int, int, const char *, 80int key_cert_check_authority(const Key *, int, int, const char *,
125 const char **); 81 const char **);
126int key_cert_is_legacy(const Key *); 82char *key_alg_list(int, int);
127 83
128int key_ecdsa_nid_from_name(const char *); 84#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
129int key_curve_name_to_nid(const char *); 85int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
130const char *key_curve_nid_to_name(int); 86int key_ec_validate_private(const EC_KEY *);
131u_int key_curve_nid_to_bits(int); 87#endif /* defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC) */
132int key_ecdsa_bits_to_nid(int);
133#ifdef OPENSSL_HAS_ECC
134int key_ecdsa_key_to_nid(EC_KEY *);
135int key_ec_nid_to_hash_alg(int nid);
136int key_ec_validate_public(const EC_GROUP *, const EC_POINT *);
137int key_ec_validate_private(const EC_KEY *);
138#endif
139char *key_alg_list(int, int);
140 88
141Key *key_from_blob(const u_char *, u_int); 89Key *key_from_blob(const u_char *, u_int);
142int key_to_blob(const Key *, u_char **, u_int *); 90int key_to_blob(const Key *, u_char **, u_int *);
143const char *key_ssh_name(const Key *);
144const char *key_ssh_name_plain(const Key *);
145int key_names_valid2(const char *);
146 91
147int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 92int key_sign(const Key *, u_char **, u_int *, const u_char *, u_int);
148int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 93int key_verify(const Key *, const u_char *, u_int, const u_char *, u_int);
149 94
150int ssh_dss_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 95void key_private_serialize(const Key *, struct sshbuf *);
151int ssh_dss_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 96Key *key_private_deserialize(struct sshbuf *);
152int ssh_ecdsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 97
153int ssh_ecdsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 98/* authfile.c */
154int ssh_rsa_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 99int key_save_private(Key *, const char *, const char *, const char *,
155int ssh_rsa_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 100 int, const char *, int);
156int ssh_ed25519_sign(const Key *, u_char **, u_int *, const u_char *, u_int); 101int key_load_file(int, const char *, struct sshbuf *);
157int ssh_ed25519_verify(const Key *, const u_char *, u_int, const u_char *, u_int); 102Key *key_load_cert(const char *);
158 103Key *key_load_public(const char *, char **);
159#if defined(OPENSSL_HAS_ECC) && (defined(DEBUG_KEXECDH) || defined(DEBUG_PK)) 104Key *key_load_private(const char *, const char *, char **);
160void key_dump_ec_point(const EC_GROUP *, const EC_POINT *); 105Key *key_load_private_cert(int, const char *, const char *, int *);
161void key_dump_ec_key(const EC_KEY *); 106Key *key_load_private_type(int, const char *, const char *, char **, int *);
162#endif 107Key *key_load_private_pem(int, int, const char *, char **);
163 108int key_perm_ok(int, const char *);
164void key_private_serialize(const Key *, Buffer *); 109int key_in_file(Key *, const char *, int);
165Key *key_private_deserialize(Buffer *);
166 110
167#endif 111#endif
diff --git a/krl.c b/krl.c
index 3b4cded05..eb31df90f 100644
--- a/krl.c
+++ b/krl.c
@@ -14,7 +14,7 @@
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */ 15 */
16 16
17/* $OpenBSD: krl.c,v 1.14 2014/01/31 16:39:19 tedu Exp $ */ 17/* $OpenBSD: krl.c,v 1.17 2014/06/24 01:13:21 djm Exp $ */
18 18
19#include "includes.h" 19#include "includes.h"
20 20
@@ -366,7 +366,7 @@ plain_key_blob(const Key *key, u_char **blob, u_int *blen)
366 } 366 }
367 r = key_to_blob(kcopy, blob, blen); 367 r = key_to_blob(kcopy, blob, blen);
368 free(kcopy); 368 free(kcopy);
369 return r == 0 ? -1 : 0; 369 return r;
370} 370}
371 371
372/* Revoke a key blob. Ownership of blob is transferred to the tree */ 372/* Revoke a key blob. Ownership of blob is transferred to the tree */
@@ -394,7 +394,7 @@ ssh_krl_revoke_key_explicit(struct ssh_krl *krl, const Key *key)
394 u_int len; 394 u_int len;
395 395
396 debug3("%s: revoke type %s", __func__, key_type(key)); 396 debug3("%s: revoke type %s", __func__, key_type(key));
397 if (plain_key_blob(key, &blob, &len) != 0) 397 if (plain_key_blob(key, &blob, &len) < 0)
398 return -1; 398 return -1;
399 return revoke_blob(&krl->revoked_keys, blob, len); 399 return revoke_blob(&krl->revoked_keys, blob, len);
400} 400}
@@ -575,6 +575,7 @@ revoked_certs_generate(struct revoked_certs *rc, Buffer *buf)
575 buffer_put_char(buf, state); 575 buffer_put_char(buf, state);
576 buffer_put_string(buf, 576 buffer_put_string(buf,
577 buffer_ptr(&sect), buffer_len(&sect)); 577 buffer_ptr(&sect), buffer_len(&sect));
578 buffer_clear(&sect);
578 } 579 }
579 580
580 /* If we are starting a new section then prepare it now */ 581 /* If we are starting a new section then prepare it now */
@@ -753,7 +754,8 @@ static int
753parse_revoked_certs(Buffer *buf, struct ssh_krl *krl) 754parse_revoked_certs(Buffer *buf, struct ssh_krl *krl)
754{ 755{
755 int ret = -1, nbits; 756 int ret = -1, nbits;
756 u_char type, *blob; 757 u_char type;
758 const u_char *blob;
757 u_int blen; 759 u_int blen;
758 Buffer subsect; 760 Buffer subsect;
759 u_int64_t serial, serial_lo, serial_hi; 761 u_int64_t serial, serial_lo, serial_hi;
@@ -887,7 +889,8 @@ ssh_krl_from_blob(Buffer *buf, struct ssh_krl **krlp,
887 char timestamp[64]; 889 char timestamp[64];
888 int ret = -1, r, sig_seen; 890 int ret = -1, r, sig_seen;
889 Key *key = NULL, **ca_used = NULL; 891 Key *key = NULL, **ca_used = NULL;
890 u_char type, *blob, *rdata = NULL; 892 u_char type, *rdata = NULL;
893 const u_char *blob;
891 u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used; 894 u_int i, j, sig_off, sects_off, rlen, blen, format_version, nca_used;
892 895
893 nca_used = 0; 896 nca_used = 0;
@@ -1127,7 +1130,7 @@ is_key_revoked(struct ssh_krl *krl, const Key *key)
1127 1130
1128 /* Next, explicit keys */ 1131 /* Next, explicit keys */
1129 memset(&rb, 0, sizeof(rb)); 1132 memset(&rb, 0, sizeof(rb));
1130 if (plain_key_blob(key, &rb.blob, &rb.len) != 0) 1133 if (plain_key_blob(key, &rb.blob, &rb.len) < 0)
1131 return -1; 1134 return -1;
1132 erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb); 1135 erb = RB_FIND(revoked_blob_tree, &krl->revoked_keys, &rb);
1133 free(rb.blob); 1136 free(rb.blob);
diff --git a/mac.c b/mac.c
index 097757213..402dc984c 100644
--- a/mac.c
+++ b/mac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mac.c,v 1.28 2014/02/07 06:55:54 djm Exp $ */ 1/* $OpenBSD: mac.c,v 1.30 2014/04/30 19:07:48 naddy Exp $ */
2/* 2/*
3 * Copyright (c) 2001 Markus Friedl. All rights reserved. 3 * Copyright (c) 2001 Markus Friedl. All rights reserved.
4 * 4 *
@@ -175,7 +175,8 @@ mac_compute(Mac *mac, u_int32_t seqno, u_char *data, int datalen)
175 u_char m[EVP_MAX_MD_SIZE]; 175 u_char m[EVP_MAX_MD_SIZE];
176 u_int64_t for_align; 176 u_int64_t for_align;
177 } u; 177 } u;
178 u_char b[4], nonce[8]; 178 u_char b[4];
179 u_char nonce[8];
179 180
180 if (mac->mac_len > sizeof(u)) 181 if (mac->mac_len > sizeof(u))
181 fatal("mac_compute: mac too long %u %zu", 182 fatal("mac_compute: mac too long %u %zu",
diff --git a/misc.c b/misc.c
index 4e756b04b..c25ccd80e 100644
--- a/misc.c
+++ b/misc.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.c,v 1.92 2013/10/14 23:28:23 djm Exp $ */ 1/* $OpenBSD: misc.c,v 1.94 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved. 4 * Copyright (c) 2005,2006 Damien Miller. All rights reserved.
@@ -29,6 +29,7 @@
29#include <sys/types.h> 29#include <sys/types.h>
30#include <sys/ioctl.h> 30#include <sys/ioctl.h>
31#include <sys/socket.h> 31#include <sys/socket.h>
32#include <sys/un.h>
32#include <sys/param.h> 33#include <sys/param.h>
33 34
34#include <stdarg.h> 35#include <stdarg.h>
@@ -855,6 +856,20 @@ get_u32(const void *vp)
855 return (v); 856 return (v);
856} 857}
857 858
859u_int32_t
860get_u32_le(const void *vp)
861{
862 const u_char *p = (const u_char *)vp;
863 u_int32_t v;
864
865 v = (u_int32_t)p[0];
866 v |= (u_int32_t)p[1] << 8;
867 v |= (u_int32_t)p[2] << 16;
868 v |= (u_int32_t)p[3] << 24;
869
870 return (v);
871}
872
858u_int16_t 873u_int16_t
859get_u16(const void *vp) 874get_u16(const void *vp)
860{ 875{
@@ -893,6 +908,16 @@ put_u32(void *vp, u_int32_t v)
893 p[3] = (u_char)v & 0xff; 908 p[3] = (u_char)v & 0xff;
894} 909}
895 910
911void
912put_u32_le(void *vp, u_int32_t v)
913{
914 u_char *p = (u_char *)vp;
915
916 p[0] = (u_char)v & 0xff;
917 p[1] = (u_char)(v >> 8) & 0xff;
918 p[2] = (u_char)(v >> 16) & 0xff;
919 p[3] = (u_char)(v >> 24) & 0xff;
920}
896 921
897void 922void
898put_u16(void *vp, u_int16_t v) 923put_u16(void *vp, u_int16_t v)
@@ -925,17 +950,24 @@ ms_to_timeval(struct timeval *tv, int ms)
925time_t 950time_t
926monotime(void) 951monotime(void)
927{ 952{
928#if defined(HAVE_CLOCK_GETTIME) && defined(CLOCK_MONOTONIC) 953#if defined(HAVE_CLOCK_GETTIME) && \
954 (defined(CLOCK_MONOTONIC) || defined(CLOCK_BOOTTIME))
929 struct timespec ts; 955 struct timespec ts;
930 static int gettime_failed = 0; 956 static int gettime_failed = 0;
931 957
932 if (!gettime_failed) { 958 if (!gettime_failed) {
959#if defined(CLOCK_BOOTTIME)
960 if (clock_gettime(CLOCK_BOOTTIME, &ts) == 0)
961 return (ts.tv_sec);
962#endif
963#if defined(CLOCK_MONOTONIC)
933 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0) 964 if (clock_gettime(CLOCK_MONOTONIC, &ts) == 0)
934 return (ts.tv_sec); 965 return (ts.tv_sec);
966#endif
935 debug3("clock_gettime: %s", strerror(errno)); 967 debug3("clock_gettime: %s", strerror(errno));
936 gettime_failed = 1; 968 gettime_failed = 1;
937 } 969 }
938#endif 970#endif /* HAVE_CLOCK_GETTIME && (CLOCK_MONOTONIC || CLOCK_BOOTTIME */
939 971
940 return time(NULL); 972 return time(NULL);
941} 973}
@@ -1092,6 +1124,53 @@ lowercase(char *s)
1092 for (; *s; s++) 1124 for (; *s; s++)
1093 *s = tolower((u_char)*s); 1125 *s = tolower((u_char)*s);
1094} 1126}
1127
1128int
1129unix_listener(const char *path, int backlog, int unlink_first)
1130{
1131 struct sockaddr_un sunaddr;
1132 int saved_errno, sock;
1133
1134 memset(&sunaddr, 0, sizeof(sunaddr));
1135 sunaddr.sun_family = AF_UNIX;
1136 if (strlcpy(sunaddr.sun_path, path, sizeof(sunaddr.sun_path)) >= sizeof(sunaddr.sun_path)) {
1137 error("%s: \"%s\" too long for Unix domain socket", __func__,
1138 path);
1139 errno = ENAMETOOLONG;
1140 return -1;
1141 }
1142
1143 sock = socket(PF_UNIX, SOCK_STREAM, 0);
1144 if (sock < 0) {
1145 saved_errno = errno;
1146 error("socket: %.100s", strerror(errno));
1147 errno = saved_errno;
1148 return -1;
1149 }
1150 if (unlink_first == 1) {
1151 if (unlink(path) != 0 && errno != ENOENT)
1152 error("unlink(%s): %.100s", path, strerror(errno));
1153 }
1154 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
1155 saved_errno = errno;
1156 error("bind: %.100s", strerror(errno));
1157 close(sock);
1158 error("%s: cannot bind to path: %s", __func__, path);
1159 errno = saved_errno;
1160 return -1;
1161 }
1162 if (listen(sock, backlog) < 0) {
1163 saved_errno = errno;
1164 error("listen: %.100s", strerror(errno));
1165 close(sock);
1166 unlink(path);
1167 error("%s: cannot listen on path: %s", __func__, path);
1168 errno = saved_errno;
1169 return -1;
1170 }
1171 return sock;
1172}
1173
1095void 1174void
1096sock_set_v6only(int s) 1175sock_set_v6only(int s)
1097{ 1176{
diff --git a/misc.h b/misc.h
index ceb173bda..89e1f75d3 100644
--- a/misc.h
+++ b/misc.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: misc.h,v 1.50 2013/10/14 23:28:23 djm Exp $ */ 1/* $OpenBSD: misc.h,v 1.54 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -15,6 +15,25 @@
15#ifndef _MISC_H 15#ifndef _MISC_H
16#define _MISC_H 16#define _MISC_H
17 17
18/* Data structure for representing a forwarding request. */
19struct Forward {
20 char *listen_host; /* Host (address) to listen on. */
21 int listen_port; /* Port to forward. */
22 char *listen_path; /* Path to bind domain socket. */
23 char *connect_host; /* Host to connect. */
24 int connect_port; /* Port to connect on connect_host. */
25 char *connect_path; /* Path to connect domain socket. */
26 int allocated_port; /* Dynamically allocated listen port */
27 int handle; /* Handle for dynamic listen ports */
28};
29
30/* Common server and client forwarding options. */
31struct ForwardOptions {
32 int gateway_ports; /* Allow remote connects to forwarded ports. */
33 mode_t streamlocal_bind_mask; /* umask for streamlocal binds */
34 int streamlocal_bind_unlink; /* unlink socket before bind */
35};
36
18/* misc.c */ 37/* misc.c */
19 38
20char *chop(char *); 39char *chop(char *);
@@ -37,6 +56,7 @@ void ms_subtract_diff(struct timeval *, int *);
37void ms_to_timeval(struct timeval *, int); 56void ms_to_timeval(struct timeval *, int);
38time_t monotime(void); 57time_t monotime(void);
39void lowercase(char *s); 58void lowercase(char *s);
59int unix_listener(const char *, int, int);
40 60
41void sock_set_v6only(int); 61void sock_set_v6only(int);
42 62
@@ -68,6 +88,9 @@ int tun_open(int, int);
68#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1) 88#define SSH_TUNID_ERR (SSH_TUNID_ANY - 1)
69#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2) 89#define SSH_TUNID_MAX (SSH_TUNID_ANY - 2)
70 90
91/* Fake port to indicate that host field is really a path. */
92#define PORT_STREAMLOCAL -2
93
71/* Functions to extract or store big-endian words of various sizes */ 94/* Functions to extract or store big-endian words of various sizes */
72u_int64_t get_u64(const void *) 95u_int64_t get_u64(const void *)
73 __attribute__((__bounded__( __minbytes__, 1, 8))); 96 __attribute__((__bounded__( __minbytes__, 1, 8)));
@@ -82,6 +105,12 @@ void put_u32(void *, u_int32_t)
82void put_u16(void *, u_int16_t) 105void put_u16(void *, u_int16_t)
83 __attribute__((__bounded__( __minbytes__, 1, 2))); 106 __attribute__((__bounded__( __minbytes__, 1, 2)));
84 107
108/* Little-endian store/load, used by umac.c */
109u_int32_t get_u32_le(const void *)
110 __attribute__((__bounded__(__minbytes__, 1, 4)));
111void put_u32_le(void *, u_int32_t)
112 __attribute__((__bounded__(__minbytes__, 1, 4)));
113
85struct bwlimit { 114struct bwlimit {
86 size_t buflen; 115 size_t buflen;
87 u_int64_t rate, thresh, lamt; 116 u_int64_t rate, thresh, lamt;
diff --git a/moduli.0 b/moduli.0
index 7d678b459..d9aaadba9 100644
--- a/moduli.0
+++ b/moduli.0
@@ -1,4 +1,4 @@
1MODULI(5) OpenBSD Programmer's Manual MODULI(5) 1MODULI(5) File Formats Manual MODULI(5)
2 2
3NAME 3NAME
4 moduli - Diffie-Hellman moduli 4 moduli - Diffie-Hellman moduli
@@ -71,4 +71,4 @@ STANDARDS
71 the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006, 71 the Secure Shell (SSH) Transport Layer Protocol, RFC 4419, March 2006,
72 2006. 72 2006.
73 73
74OpenBSD 5.5 September 26, 2012 OpenBSD 5.5 74OpenBSD 5.6 September 26, 2012 OpenBSD 5.6
diff --git a/monitor.c b/monitor.c
index 7c105e687..cc15ce486 100644
--- a/monitor.c
+++ b/monitor.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor.c,v 1.131 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: monitor.c,v 1.135 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -40,9 +40,10 @@
40#endif 40#endif
41#include <pwd.h> 41#include <pwd.h>
42#include <signal.h> 42#include <signal.h>
43#include <stdarg.h>
44#include <stdlib.h> 43#include <stdlib.h>
45#include <string.h> 44#include <string.h>
45#include <stdarg.h>
46#include <stdio.h>
46#include <unistd.h> 47#include <unistd.h>
47#ifdef HAVE_POLL_H 48#ifdef HAVE_POLL_H
48#include <poll.h> 49#include <poll.h>
@@ -56,7 +57,9 @@
56#include <skey.h> 57#include <skey.h>
57#endif 58#endif
58 59
60#ifdef WITH_OPENSSL
59#include <openssl/dh.h> 61#include <openssl/dh.h>
62#endif
60 63
61#include "openbsd-compat/sys-queue.h" 64#include "openbsd-compat/sys-queue.h"
62#include "atomicio.h" 65#include "atomicio.h"
@@ -84,6 +87,7 @@
84#include "sshlogin.h" 87#include "sshlogin.h"
85#include "canohost.h" 88#include "canohost.h"
86#include "log.h" 89#include "log.h"
90#include "misc.h"
87#include "servconf.h" 91#include "servconf.h"
88#include "monitor.h" 92#include "monitor.h"
89#include "monitor_mm.h" 93#include "monitor_mm.h"
@@ -92,7 +96,6 @@
92#endif 96#endif
93#include "monitor_wrap.h" 97#include "monitor_wrap.h"
94#include "monitor_fdpass.h" 98#include "monitor_fdpass.h"
95#include "misc.h"
96#include "compat.h" 99#include "compat.h"
97#include "ssh2.h" 100#include "ssh2.h"
98#include "roaming.h" 101#include "roaming.h"
@@ -195,7 +198,10 @@ int mm_answer_consolekit_register(int, Buffer *);
195#endif 198#endif
196 199
197static Authctxt *authctxt; 200static Authctxt *authctxt;
201
202#ifdef WITH_SSH1
198static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */ 203static BIGNUM *ssh1_challenge = NULL; /* used for ssh1 rsa auth */
204#endif
199 205
200/* local state for key verify */ 206/* local state for key verify */
201static u_char *key_blob = NULL; 207static u_char *key_blob = NULL;
@@ -225,7 +231,9 @@ struct mon_table {
225#define MON_PERMIT 0x1000 /* Request is permitted */ 231#define MON_PERMIT 0x1000 /* Request is permitted */
226 232
227struct mon_table mon_dispatch_proto20[] = { 233struct mon_table mon_dispatch_proto20[] = {
234#ifdef WITH_OPENSSL
228 {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli}, 235 {MONITOR_REQ_MODULI, MON_ONCE, mm_answer_moduli},
236#endif
229 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign}, 237 {MONITOR_REQ_SIGN, MON_ONCE, mm_answer_sign},
230 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 238 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
231 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv}, 239 {MONITOR_REQ_AUTHSERV, MON_ONCE, mm_answer_authserv},
@@ -270,7 +278,9 @@ struct mon_table mon_dispatch_postauth20[] = {
270 {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign}, 278 {MONITOR_REQ_GSSSIGN, 0, mm_answer_gss_sign},
271 {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds}, 279 {MONITOR_REQ_GSSUPCREDS, 0, mm_answer_gss_updatecreds},
272#endif 280#endif
281#ifdef WITH_OPENSSL
273 {MONITOR_REQ_MODULI, 0, mm_answer_moduli}, 282 {MONITOR_REQ_MODULI, 0, mm_answer_moduli},
283#endif
274 {MONITOR_REQ_SIGN, 0, mm_answer_sign}, 284 {MONITOR_REQ_SIGN, 0, mm_answer_sign},
275 {MONITOR_REQ_PTY, 0, mm_answer_pty}, 285 {MONITOR_REQ_PTY, 0, mm_answer_pty},
276 {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup}, 286 {MONITOR_REQ_PTYCLEANUP, 0, mm_answer_pty_cleanup},
@@ -286,6 +296,7 @@ struct mon_table mon_dispatch_postauth20[] = {
286}; 296};
287 297
288struct mon_table mon_dispatch_proto15[] = { 298struct mon_table mon_dispatch_proto15[] = {
299#ifdef WITH_SSH1
289 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow}, 300 {MONITOR_REQ_PWNAM, MON_ONCE, mm_answer_pwnamallow},
290 {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey}, 301 {MONITOR_REQ_SESSKEY, MON_ONCE, mm_answer_sesskey},
291 {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid}, 302 {MONITOR_REQ_SESSID, MON_ONCE, mm_answer_sessid},
@@ -313,10 +324,12 @@ struct mon_table mon_dispatch_proto15[] = {
313#ifdef SSH_AUDIT_EVENTS 324#ifdef SSH_AUDIT_EVENTS
314 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event}, 325 {MONITOR_REQ_AUDIT_EVENT, MON_PERMIT, mm_answer_audit_event},
315#endif 326#endif
327#endif /* WITH_SSH1 */
316 {0, 0, NULL} 328 {0, 0, NULL}
317}; 329};
318 330
319struct mon_table mon_dispatch_postauth15[] = { 331struct mon_table mon_dispatch_postauth15[] = {
332#ifdef WITH_SSH1
320 {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty}, 333 {MONITOR_REQ_PTY, MON_ONCE, mm_answer_pty},
321 {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup}, 334 {MONITOR_REQ_PTYCLEANUP, MON_ONCE, mm_answer_pty_cleanup},
322 {MONITOR_REQ_TERM, 0, mm_answer_term}, 335 {MONITOR_REQ_TERM, 0, mm_answer_term},
@@ -327,6 +340,7 @@ struct mon_table mon_dispatch_postauth15[] = {
327#ifdef USE_CONSOLEKIT 340#ifdef USE_CONSOLEKIT
328 {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register}, 341 {MONITOR_REQ_CONSOLEKIT_REGISTER, 0, mm_answer_consolekit_register},
329#endif 342#endif
343#endif /* WITH_SSH1 */
330 {0, 0, NULL} 344 {0, 0, NULL}
331}; 345};
332 346
@@ -485,6 +499,9 @@ monitor_child_postauth(struct monitor *pmonitor)
485 signal(SIGHUP, &monitor_child_handler); 499 signal(SIGHUP, &monitor_child_handler);
486 signal(SIGTERM, &monitor_child_handler); 500 signal(SIGTERM, &monitor_child_handler);
487 signal(SIGINT, &monitor_child_handler); 501 signal(SIGINT, &monitor_child_handler);
502#ifdef SIGXFSZ
503 signal(SIGXFSZ, SIG_IGN);
504#endif
488 505
489 if (compat20) { 506 if (compat20) {
490 mon_dispatch = mon_dispatch_postauth20; 507 mon_dispatch = mon_dispatch_postauth20;
@@ -665,6 +682,7 @@ monitor_reset_key_state(void)
665 hostbased_chost = NULL; 682 hostbased_chost = NULL;
666} 683}
667 684
685#ifdef WITH_OPENSSL
668int 686int
669mm_answer_moduli(int sock, Buffer *m) 687mm_answer_moduli(int sock, Buffer *m)
670{ 688{
@@ -699,6 +717,7 @@ mm_answer_moduli(int sock, Buffer *m)
699 mm_request_send(sock, MONITOR_ANS_MODULI, m); 717 mm_request_send(sock, MONITOR_ANS_MODULI, m);
700 return (0); 718 return (0);
701} 719}
720#endif
702 721
703extern AuthenticationConnection *auth_conn; 722extern AuthenticationConnection *auth_conn;
704 723
@@ -1225,6 +1244,7 @@ mm_answer_keyallowed(int sock, Buffer *m)
1225 cuser, chost); 1244 cuser, chost);
1226 auth_method = "hostbased"; 1245 auth_method = "hostbased";
1227 break; 1246 break;
1247#ifdef WITH_SSH1
1228 case MM_RSAHOSTKEY: 1248 case MM_RSAHOSTKEY:
1229 key->type = KEY_RSA1; /* XXX */ 1249 key->type = KEY_RSA1; /* XXX */
1230 allowed = options.rhosts_rsa_authentication && 1250 allowed = options.rhosts_rsa_authentication &&
@@ -1234,6 +1254,7 @@ mm_answer_keyallowed(int sock, Buffer *m)
1234 auth_clear_options(); 1254 auth_clear_options();
1235 auth_method = "rsa"; 1255 auth_method = "rsa";
1236 break; 1256 break;
1257#endif
1237 default: 1258 default:
1238 fatal("%s: unknown key type %d", __func__, type); 1259 fatal("%s: unknown key type %d", __func__, type);
1239 break; 1260 break;
@@ -1570,6 +1591,7 @@ mm_answer_pty_cleanup(int sock, Buffer *m)
1570 return (0); 1591 return (0);
1571} 1592}
1572 1593
1594#ifdef WITH_SSH1
1573int 1595int
1574mm_answer_sesskey(int sock, Buffer *m) 1596mm_answer_sesskey(int sock, Buffer *m)
1575{ 1597{
@@ -1747,6 +1769,7 @@ mm_answer_rsa_response(int sock, Buffer *m)
1747 1769
1748 return (success); 1770 return (success);
1749} 1771}
1772#endif
1750 1773
1751int 1774int
1752mm_answer_term(int sock, Buffer *req) 1775mm_answer_term(int sock, Buffer *req)
@@ -1851,6 +1874,8 @@ monitor_apply_keystate(struct monitor *pmonitor)
1851 if (options.compression) 1874 if (options.compression)
1852 mm_init_compression(pmonitor->m_zlib); 1875 mm_init_compression(pmonitor->m_zlib);
1853 1876
1877 packet_set_postauth();
1878
1854 if (options.rekey_limit || options.rekey_interval) 1879 if (options.rekey_limit || options.rekey_interval)
1855 packet_set_rekey_limits((u_int32_t)options.rekey_limit, 1880 packet_set_rekey_limits((u_int32_t)options.rekey_limit,
1856 (time_t)options.rekey_interval); 1881 (time_t)options.rekey_interval);
@@ -1887,11 +1912,13 @@ mm_get_kex(Buffer *m)
1887 timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0) 1912 timingsafe_bcmp(kex->session_id, session_id2, session_id2_len) != 0)
1888 fatal("mm_get_get: internal error: bad session id"); 1913 fatal("mm_get_get: internal error: bad session id");
1889 kex->we_need = buffer_get_int(m); 1914 kex->we_need = buffer_get_int(m);
1915#ifdef WITH_OPENSSL
1890 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 1916 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
1891 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 1917 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
1892 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 1918 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
1893 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 1919 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
1894 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 1920 kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
1921#endif
1895 kex->kex[KEX_C25519_SHA256] = kexc25519_server; 1922 kex->kex[KEX_C25519_SHA256] = kexc25519_server;
1896#ifdef GSSAPI 1923#ifdef GSSAPI
1897 if (options.gss_keyex) { 1924 if (options.gss_keyex) {
diff --git a/monitor_fdpass.c b/monitor_fdpass.c
index 7eb6f5c6e..100fa5660 100644
--- a/monitor_fdpass.c
+++ b/monitor_fdpass.c
@@ -34,12 +34,17 @@
34#endif 34#endif
35 35
36#include <errno.h> 36#include <errno.h>
37#ifdef HAVE_POLL_H
38#include <poll.h>
39#endif
40#include <string.h> 37#include <string.h>
41#include <stdarg.h> 38#include <stdarg.h>
42 39
40#ifdef HAVE_POLL_H
41# include <poll.h>
42#else
43# ifdef HAVE_SYS_POLL_H
44# include <sys/poll.h>
45# endif
46#endif
47
43#include "log.h" 48#include "log.h"
44#include "monitor_fdpass.h" 49#include "monitor_fdpass.h"
45 50
diff --git a/monitor_wrap.c b/monitor_wrap.c
index a8fb07b52..4c57d4df3 100644
--- a/monitor_wrap.c
+++ b/monitor_wrap.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: monitor_wrap.c,v 1.79 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: monitor_wrap.c,v 1.80 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Copyright 2002 Niels Provos <provos@citi.umich.edu> 3 * Copyright 2002 Niels Provos <provos@citi.umich.edu>
4 * Copyright 2002 Markus Friedl <markus@openbsd.org> 4 * Copyright 2002 Markus Friedl <markus@openbsd.org>
@@ -38,14 +38,18 @@
38#include <string.h> 38#include <string.h>
39#include <unistd.h> 39#include <unistd.h>
40 40
41#ifdef WITH_OPENSSL
41#include <openssl/bn.h> 42#include <openssl/bn.h>
42#include <openssl/dh.h> 43#include <openssl/dh.h>
43#include <openssl/evp.h> 44#include <openssl/evp.h>
45#endif
44 46
45#include "openbsd-compat/sys-queue.h" 47#include "openbsd-compat/sys-queue.h"
46#include "xmalloc.h" 48#include "xmalloc.h"
47#include "ssh.h" 49#include "ssh.h"
50#ifdef WITH_OPENSSL
48#include "dh.h" 51#include "dh.h"
52#endif
49#include "buffer.h" 53#include "buffer.h"
50#include "key.h" 54#include "key.h"
51#include "cipher.h" 55#include "cipher.h"
@@ -174,6 +178,7 @@ mm_request_receive_expect(int sock, enum monitor_reqtype type, Buffer *m)
174 rtype, type); 178 rtype, type);
175} 179}
176 180
181#ifdef WITH_OPENSSL
177DH * 182DH *
178mm_choose_dh(int min, int nbits, int max) 183mm_choose_dh(int min, int nbits, int max)
179{ 184{
@@ -207,6 +212,7 @@ mm_choose_dh(int min, int nbits, int max)
207 212
208 return (dh_new_group(g, p)); 213 return (dh_new_group(g, p));
209} 214}
215#endif
210 216
211int 217int
212mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen) 218mm_key_sign(Key *key, u_char **sigp, u_int *lenp, u_char *data, u_int datalen)
@@ -930,6 +936,7 @@ mm_terminate(void)
930 buffer_free(&m); 936 buffer_free(&m);
931} 937}
932 938
939#ifdef WITH_SSH1
933int 940int
934mm_ssh1_session_key(BIGNUM *num) 941mm_ssh1_session_key(BIGNUM *num)
935{ 942{
@@ -949,6 +956,7 @@ mm_ssh1_session_key(BIGNUM *num)
949 956
950 return (rsafail); 957 return (rsafail);
951} 958}
959#endif
952 960
953static void 961static void
954mm_chall_setup(char **name, char **infotxt, u_int *numprompts, 962mm_chall_setup(char **name, char **infotxt, u_int *numprompts,
@@ -1096,6 +1104,7 @@ mm_ssh1_session_id(u_char session_id[16])
1096 buffer_free(&m); 1104 buffer_free(&m);
1097} 1105}
1098 1106
1107#ifdef WITH_SSH1
1099int 1108int
1100mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey) 1109mm_auth_rsa_key_allowed(struct passwd *pw, BIGNUM *client_n, Key **rkey)
1101{ 1110{
@@ -1191,6 +1200,7 @@ mm_auth_rsa_verify_response(Key *key, BIGNUM *p, u_char response[16])
1191 1200
1192 return (success); 1201 return (success);
1193} 1202}
1203#endif
1194 1204
1195#ifdef SSH_AUDIT_EVENTS 1205#ifdef SSH_AUDIT_EVENTS
1196void 1206void
diff --git a/mux.c b/mux.c
index 882fa61b5..48f7a050f 100644
--- a/mux.c
+++ b/mux.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: mux.c,v 1.44 2013/07/12 00:19:58 djm Exp $ */ 1/* $OpenBSD: mux.c,v 1.48 2014/07/17 07:22:19 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2002-2008 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -105,6 +105,11 @@ struct mux_session_confirm_ctx {
105 u_int rid; 105 u_int rid;
106}; 106};
107 107
108/* Context for stdio fwd open confirmation callback */
109struct mux_stdio_confirm_ctx {
110 u_int rid;
111};
112
108/* Context for global channel callback */ 113/* Context for global channel callback */
109struct mux_channel_confirm_ctx { 114struct mux_channel_confirm_ctx {
110 u_int cid; /* channel id */ 115 u_int cid; /* channel id */
@@ -157,6 +162,7 @@ struct mux_master_state {
157#define MUX_FWD_DYNAMIC 3 162#define MUX_FWD_DYNAMIC 3
158 163
159static void mux_session_confirm(int, int, void *); 164static void mux_session_confirm(int, int, void *);
165static void mux_stdio_confirm(int, int, void *);
160 166
161static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *); 167static int process_mux_master_hello(u_int, Channel *, Buffer *, Buffer *);
162static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *); 168static int process_mux_new_session(u_int, Channel *, Buffer *, Buffer *);
@@ -509,29 +515,33 @@ process_mux_terminate(u_int rid, Channel *c, Buffer *m, Buffer *r)
509} 515}
510 516
511static char * 517static char *
512format_forward(u_int ftype, Forward *fwd) 518format_forward(u_int ftype, struct Forward *fwd)
513{ 519{
514 char *ret; 520 char *ret;
515 521
516 switch (ftype) { 522 switch (ftype) {
517 case MUX_FWD_LOCAL: 523 case MUX_FWD_LOCAL:
518 xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d", 524 xasprintf(&ret, "local forward %.200s:%d -> %.200s:%d",
525 (fwd->listen_path != NULL) ? fwd->listen_path :
519 (fwd->listen_host == NULL) ? 526 (fwd->listen_host == NULL) ?
520 (options.gateway_ports ? "*" : "LOCALHOST") : 527 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
521 fwd->listen_host, fwd->listen_port, 528 fwd->listen_host, fwd->listen_port,
529 (fwd->connect_path != NULL) ? fwd->connect_path :
522 fwd->connect_host, fwd->connect_port); 530 fwd->connect_host, fwd->connect_port);
523 break; 531 break;
524 case MUX_FWD_DYNAMIC: 532 case MUX_FWD_DYNAMIC:
525 xasprintf(&ret, "dynamic forward %.200s:%d -> *", 533 xasprintf(&ret, "dynamic forward %.200s:%d -> *",
526 (fwd->listen_host == NULL) ? 534 (fwd->listen_host == NULL) ?
527 (options.gateway_ports ? "*" : "LOCALHOST") : 535 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
528 fwd->listen_host, fwd->listen_port); 536 fwd->listen_host, fwd->listen_port);
529 break; 537 break;
530 case MUX_FWD_REMOTE: 538 case MUX_FWD_REMOTE:
531 xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d", 539 xasprintf(&ret, "remote forward %.200s:%d -> %.200s:%d",
540 (fwd->listen_path != NULL) ? fwd->listen_path :
532 (fwd->listen_host == NULL) ? 541 (fwd->listen_host == NULL) ?
533 "LOCALHOST" : fwd->listen_host, 542 "LOCALHOST" : fwd->listen_host,
534 fwd->listen_port, 543 fwd->listen_port,
544 (fwd->connect_path != NULL) ? fwd->connect_path :
535 fwd->connect_host, fwd->connect_port); 545 fwd->connect_host, fwd->connect_port);
536 break; 546 break;
537 default: 547 default:
@@ -551,14 +561,18 @@ compare_host(const char *a, const char *b)
551} 561}
552 562
553static int 563static int
554compare_forward(Forward *a, Forward *b) 564compare_forward(struct Forward *a, struct Forward *b)
555{ 565{
556 if (!compare_host(a->listen_host, b->listen_host)) 566 if (!compare_host(a->listen_host, b->listen_host))
557 return 0; 567 return 0;
568 if (!compare_host(a->listen_path, b->listen_path))
569 return 0;
558 if (a->listen_port != b->listen_port) 570 if (a->listen_port != b->listen_port)
559 return 0; 571 return 0;
560 if (!compare_host(a->connect_host, b->connect_host)) 572 if (!compare_host(a->connect_host, b->connect_host))
561 return 0; 573 return 0;
574 if (!compare_host(a->connect_path, b->connect_path))
575 return 0;
562 if (a->connect_port != b->connect_port) 576 if (a->connect_port != b->connect_port)
563 return 0; 577 return 0;
564 578
@@ -570,7 +584,7 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
570{ 584{
571 struct mux_channel_confirm_ctx *fctx = ctxt; 585 struct mux_channel_confirm_ctx *fctx = ctxt;
572 char *failmsg = NULL; 586 char *failmsg = NULL;
573 Forward *rfwd; 587 struct Forward *rfwd;
574 Channel *c; 588 Channel *c;
575 Buffer out; 589 Buffer out;
576 590
@@ -587,7 +601,8 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
587 rfwd = &options.remote_forwards[fctx->fid]; 601 rfwd = &options.remote_forwards[fctx->fid];
588 debug("%s: %s for: listen %d, connect %s:%d", __func__, 602 debug("%s: %s for: listen %d, connect %s:%d", __func__,
589 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 603 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
590 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); 604 rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
605 rfwd->connect_host, rfwd->connect_port);
591 if (type == SSH2_MSG_REQUEST_SUCCESS) { 606 if (type == SSH2_MSG_REQUEST_SUCCESS) {
592 if (rfwd->listen_port == 0) { 607 if (rfwd->listen_port == 0) {
593 rfwd->allocated_port = packet_get_int(); 608 rfwd->allocated_port = packet_get_int();
@@ -607,8 +622,12 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
607 } else { 622 } else {
608 if (rfwd->listen_port == 0) 623 if (rfwd->listen_port == 0)
609 channel_update_permitted_opens(rfwd->handle, -1); 624 channel_update_permitted_opens(rfwd->handle, -1);
610 xasprintf(&failmsg, "remote port forwarding failed for " 625 if (rfwd->listen_path != NULL)
611 "listen port %d", rfwd->listen_port); 626 xasprintf(&failmsg, "remote port forwarding failed for "
627 "listen path %s", rfwd->listen_path);
628 else
629 xasprintf(&failmsg, "remote port forwarding failed for "
630 "listen port %d", rfwd->listen_port);
612 } 631 }
613 fail: 632 fail:
614 error("%s: %s", __func__, failmsg); 633 error("%s: %s", __func__, failmsg);
@@ -627,34 +646,46 @@ mux_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
627static int 646static int
628process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) 647process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
629{ 648{
630 Forward fwd; 649 struct Forward fwd;
631 char *fwd_desc = NULL; 650 char *fwd_desc = NULL;
651 char *listen_addr, *connect_addr;
632 u_int ftype; 652 u_int ftype;
633 u_int lport, cport; 653 u_int lport, cport;
634 int i, ret = 0, freefwd = 1; 654 int i, ret = 0, freefwd = 1;
635 655
636 fwd.listen_host = fwd.connect_host = NULL; 656 /* XXX - lport/cport check redundant */
637 if (buffer_get_int_ret(&ftype, m) != 0 || 657 if (buffer_get_int_ret(&ftype, m) != 0 ||
638 (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || 658 (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
639 buffer_get_int_ret(&lport, m) != 0 || 659 buffer_get_int_ret(&lport, m) != 0 ||
640 (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || 660 (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
641 buffer_get_int_ret(&cport, m) != 0 || 661 buffer_get_int_ret(&cport, m) != 0 ||
642 lport > 65535 || cport > 65535) { 662 (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
663 (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
643 error("%s: malformed message", __func__); 664 error("%s: malformed message", __func__);
644 ret = -1; 665 ret = -1;
645 goto out; 666 goto out;
646 } 667 }
647 fwd.listen_port = lport; 668 if (*listen_addr == '\0') {
648 fwd.connect_port = cport; 669 free(listen_addr);
649 if (*fwd.listen_host == '\0') { 670 listen_addr = NULL;
650 free(fwd.listen_host);
651 fwd.listen_host = NULL;
652 } 671 }
653 if (*fwd.connect_host == '\0') { 672 if (*connect_addr == '\0') {
654 free(fwd.connect_host); 673 free(connect_addr);
655 fwd.connect_host = NULL; 674 connect_addr = NULL;
656 } 675 }
657 676
677 memset(&fwd, 0, sizeof(fwd));
678 fwd.listen_port = lport;
679 if (fwd.listen_port == PORT_STREAMLOCAL)
680 fwd.listen_path = listen_addr;
681 else
682 fwd.listen_host = listen_addr;
683 fwd.connect_port = cport;
684 if (fwd.connect_port == PORT_STREAMLOCAL)
685 fwd.connect_path = connect_addr;
686 else
687 fwd.connect_host = connect_addr;
688
658 debug2("%s: channel %d: request %s", __func__, c->self, 689 debug2("%s: channel %d: request %s", __func__, c->self,
659 (fwd_desc = format_forward(ftype, &fwd))); 690 (fwd_desc = format_forward(ftype, &fwd)));
660 691
@@ -662,25 +693,30 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
662 ftype != MUX_FWD_DYNAMIC) { 693 ftype != MUX_FWD_DYNAMIC) {
663 logit("%s: invalid forwarding type %u", __func__, ftype); 694 logit("%s: invalid forwarding type %u", __func__, ftype);
664 invalid: 695 invalid:
665 free(fwd.listen_host); 696 free(listen_addr);
666 free(fwd.connect_host); 697 free(connect_addr);
667 buffer_put_int(r, MUX_S_FAILURE); 698 buffer_put_int(r, MUX_S_FAILURE);
668 buffer_put_int(r, rid); 699 buffer_put_int(r, rid);
669 buffer_put_cstring(r, "Invalid forwarding request"); 700 buffer_put_cstring(r, "Invalid forwarding request");
670 return 0; 701 return 0;
671 } 702 }
672 if (fwd.listen_port >= 65536) { 703 if (ftype == MUX_FWD_DYNAMIC && fwd.listen_path) {
704 logit("%s: streamlocal and dynamic forwards "
705 "are mutually exclusive", __func__);
706 goto invalid;
707 }
708 if (fwd.listen_port != PORT_STREAMLOCAL && fwd.listen_port >= 65536) {
673 logit("%s: invalid listen port %u", __func__, 709 logit("%s: invalid listen port %u", __func__,
674 fwd.listen_port); 710 fwd.listen_port);
675 goto invalid; 711 goto invalid;
676 } 712 }
677 if (fwd.connect_port >= 65536 || (ftype != MUX_FWD_DYNAMIC && 713 if ((fwd.connect_port != PORT_STREAMLOCAL && fwd.connect_port >= 65536)
678 ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) { 714 || (ftype != MUX_FWD_DYNAMIC && ftype != MUX_FWD_REMOTE && fwd.connect_port == 0)) {
679 logit("%s: invalid connect port %u", __func__, 715 logit("%s: invalid connect port %u", __func__,
680 fwd.connect_port); 716 fwd.connect_port);
681 goto invalid; 717 goto invalid;
682 } 718 }
683 if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL) { 719 if (ftype != MUX_FWD_DYNAMIC && fwd.connect_host == NULL && fwd.connect_path == NULL) {
684 logit("%s: missing connect host", __func__); 720 logit("%s: missing connect host", __func__);
685 goto invalid; 721 goto invalid;
686 } 722 }
@@ -731,9 +767,8 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
731 } 767 }
732 768
733 if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) { 769 if (ftype == MUX_FWD_LOCAL || ftype == MUX_FWD_DYNAMIC) {
734 if (!channel_setup_local_fwd_listener(fwd.listen_host, 770 if (!channel_setup_local_fwd_listener(&fwd,
735 fwd.listen_port, fwd.connect_host, fwd.connect_port, 771 &options.fwd_opts)) {
736 options.gateway_ports)) {
737 fail: 772 fail:
738 logit("slave-requested %s failed", fwd_desc); 773 logit("slave-requested %s failed", fwd_desc);
739 buffer_put_int(r, MUX_S_FAILURE); 774 buffer_put_int(r, MUX_S_FAILURE);
@@ -746,8 +781,7 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
746 } else { 781 } else {
747 struct mux_channel_confirm_ctx *fctx; 782 struct mux_channel_confirm_ctx *fctx;
748 783
749 fwd.handle = channel_request_remote_forwarding(fwd.listen_host, 784 fwd.handle = channel_request_remote_forwarding(&fwd);
750 fwd.listen_port, fwd.connect_host, fwd.connect_port);
751 if (fwd.handle < 0) 785 if (fwd.handle < 0)
752 goto fail; 786 goto fail;
753 add_remote_forward(&options, &fwd); 787 add_remote_forward(&options, &fwd);
@@ -768,7 +802,9 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
768 free(fwd_desc); 802 free(fwd_desc);
769 if (freefwd) { 803 if (freefwd) {
770 free(fwd.listen_host); 804 free(fwd.listen_host);
805 free(fwd.listen_path);
771 free(fwd.connect_host); 806 free(fwd.connect_host);
807 free(fwd.connect_path);
772 } 808 }
773 return ret; 809 return ret;
774} 810}
@@ -776,36 +812,47 @@ process_mux_open_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
776static int 812static int
777process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r) 813process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
778{ 814{
779 Forward fwd, *found_fwd; 815 struct Forward fwd, *found_fwd;
780 char *fwd_desc = NULL; 816 char *fwd_desc = NULL;
781 const char *error_reason = NULL; 817 const char *error_reason = NULL;
818 char *listen_addr = NULL, *connect_addr = NULL;
782 u_int ftype; 819 u_int ftype;
783 int i, listen_port, ret = 0; 820 int i, ret = 0;
784 u_int lport, cport; 821 u_int lport, cport;
785 822
786 fwd.listen_host = fwd.connect_host = NULL;
787 if (buffer_get_int_ret(&ftype, m) != 0 || 823 if (buffer_get_int_ret(&ftype, m) != 0 ||
788 (fwd.listen_host = buffer_get_string_ret(m, NULL)) == NULL || 824 (listen_addr = buffer_get_string_ret(m, NULL)) == NULL ||
789 buffer_get_int_ret(&lport, m) != 0 || 825 buffer_get_int_ret(&lport, m) != 0 ||
790 (fwd.connect_host = buffer_get_string_ret(m, NULL)) == NULL || 826 (connect_addr = buffer_get_string_ret(m, NULL)) == NULL ||
791 buffer_get_int_ret(&cport, m) != 0 || 827 buffer_get_int_ret(&cport, m) != 0 ||
792 lport > 65535 || cport > 65535) { 828 (lport != (u_int)PORT_STREAMLOCAL && lport > 65535) ||
829 (cport != (u_int)PORT_STREAMLOCAL && cport > 65535)) {
793 error("%s: malformed message", __func__); 830 error("%s: malformed message", __func__);
794 ret = -1; 831 ret = -1;
795 goto out; 832 goto out;
796 } 833 }
797 fwd.listen_port = lport;
798 fwd.connect_port = cport;
799 834
800 if (*fwd.listen_host == '\0') { 835 if (*listen_addr == '\0') {
801 free(fwd.listen_host); 836 free(listen_addr);
802 fwd.listen_host = NULL; 837 listen_addr = NULL;
803 } 838 }
804 if (*fwd.connect_host == '\0') { 839 if (*connect_addr == '\0') {
805 free(fwd.connect_host); 840 free(connect_addr);
806 fwd.connect_host = NULL; 841 connect_addr = NULL;
807 } 842 }
808 843
844 memset(&fwd, 0, sizeof(fwd));
845 fwd.listen_port = lport;
846 if (fwd.listen_port == PORT_STREAMLOCAL)
847 fwd.listen_path = listen_addr;
848 else
849 fwd.listen_host = listen_addr;
850 fwd.connect_port = cport;
851 if (fwd.connect_port == PORT_STREAMLOCAL)
852 fwd.connect_path = connect_addr;
853 else
854 fwd.connect_host = connect_addr;
855
809 debug2("%s: channel %d: request cancel %s", __func__, c->self, 856 debug2("%s: channel %d: request cancel %s", __func__, c->self,
810 (fwd_desc = format_forward(ftype, &fwd))); 857 (fwd_desc = format_forward(ftype, &fwd)));
811 858
@@ -840,18 +887,14 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
840 * This shouldn't fail unless we confused the host/port 887 * This shouldn't fail unless we confused the host/port
841 * between options.remote_forwards and permitted_opens. 888 * between options.remote_forwards and permitted_opens.
842 * However, for dynamic allocated listen ports we need 889 * However, for dynamic allocated listen ports we need
843 * to lookup the actual listen port. 890 * to use the actual listen port.
844 */ 891 */
845 listen_port = (fwd.listen_port == 0) ? 892 if (channel_request_rforward_cancel(found_fwd) == -1)
846 found_fwd->allocated_port : fwd.listen_port;
847 if (channel_request_rforward_cancel(fwd.listen_host,
848 listen_port) == -1)
849 error_reason = "port not in permitted opens"; 893 error_reason = "port not in permitted opens";
850 } else { /* local and dynamic forwards */ 894 } else { /* local and dynamic forwards */
851 /* Ditto */ 895 /* Ditto */
852 if (channel_cancel_lport_listener(fwd.listen_host, 896 if (channel_cancel_lport_listener(&fwd, fwd.connect_port,
853 fwd.listen_port, fwd.connect_port, 897 &options.fwd_opts) == -1)
854 options.gateway_ports) == -1)
855 error_reason = "port not found"; 898 error_reason = "port not found";
856 } 899 }
857 900
@@ -860,8 +903,11 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
860 buffer_put_int(r, rid); 903 buffer_put_int(r, rid);
861 904
862 free(found_fwd->listen_host); 905 free(found_fwd->listen_host);
906 free(found_fwd->listen_path);
863 free(found_fwd->connect_host); 907 free(found_fwd->connect_host);
908 free(found_fwd->connect_path);
864 found_fwd->listen_host = found_fwd->connect_host = NULL; 909 found_fwd->listen_host = found_fwd->connect_host = NULL;
910 found_fwd->listen_path = found_fwd->connect_path = NULL;
865 found_fwd->listen_port = found_fwd->connect_port = 0; 911 found_fwd->listen_port = found_fwd->connect_port = 0;
866 } else { 912 } else {
867 buffer_put_int(r, MUX_S_FAILURE); 913 buffer_put_int(r, MUX_S_FAILURE);
@@ -870,8 +916,8 @@ process_mux_close_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
870 } 916 }
871 out: 917 out:
872 free(fwd_desc); 918 free(fwd_desc);
873 free(fwd.listen_host); 919 free(listen_addr);
874 free(fwd.connect_host); 920 free(connect_addr);
875 921
876 return ret; 922 return ret;
877} 923}
@@ -883,6 +929,7 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
883 char *reserved, *chost; 929 char *reserved, *chost;
884 u_int cport, i, j; 930 u_int cport, i, j;
885 int new_fd[2]; 931 int new_fd[2];
932 struct mux_stdio_confirm_ctx *cctx;
886 933
887 chost = reserved = NULL; 934 chost = reserved = NULL;
888 if ((reserved = buffer_get_string_ret(m, NULL)) == NULL || 935 if ((reserved = buffer_get_string_ret(m, NULL)) == NULL ||
@@ -962,15 +1009,60 @@ process_mux_stdio_fwd(u_int rid, Channel *c, Buffer *m, Buffer *r)
962 1009
963 channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1); 1010 channel_register_cleanup(nc->self, mux_master_session_cleanup_cb, 1);
964 1011
965 /* prepare reply */ 1012 cctx = xcalloc(1, sizeof(*cctx));
966 /* XXX defer until channel confirmed */ 1013 cctx->rid = rid;
967 buffer_put_int(r, MUX_S_SESSION_OPENED); 1014 channel_register_open_confirm(nc->self, mux_stdio_confirm, cctx);
968 buffer_put_int(r, rid); 1015 c->mux_pause = 1; /* stop handling messages until open_confirm done */
969 buffer_put_int(r, nc->self);
970 1016
1017 /* reply is deferred, sent by mux_session_confirm */
971 return 0; 1018 return 0;
972} 1019}
973 1020
1021/* Callback on open confirmation in mux master for a mux stdio fwd session. */
1022static void
1023mux_stdio_confirm(int id, int success, void *arg)
1024{
1025 struct mux_stdio_confirm_ctx *cctx = arg;
1026 Channel *c, *cc;
1027 Buffer reply;
1028
1029 if (cctx == NULL)
1030 fatal("%s: cctx == NULL", __func__);
1031 if ((c = channel_by_id(id)) == NULL)
1032 fatal("%s: no channel for id %d", __func__, id);
1033 if ((cc = channel_by_id(c->ctl_chan)) == NULL)
1034 fatal("%s: channel %d lacks control channel %d", __func__,
1035 id, c->ctl_chan);
1036
1037 if (!success) {
1038 debug3("%s: sending failure reply", __func__);
1039 /* prepare reply */
1040 buffer_init(&reply);
1041 buffer_put_int(&reply, MUX_S_FAILURE);
1042 buffer_put_int(&reply, cctx->rid);
1043 buffer_put_cstring(&reply, "Session open refused by peer");
1044 goto done;
1045 }
1046
1047 debug3("%s: sending success reply", __func__);
1048 /* prepare reply */
1049 buffer_init(&reply);
1050 buffer_put_int(&reply, MUX_S_SESSION_OPENED);
1051 buffer_put_int(&reply, cctx->rid);
1052 buffer_put_int(&reply, c->self);
1053
1054 done:
1055 /* Send reply */
1056 buffer_put_string(&cc->output, buffer_ptr(&reply), buffer_len(&reply));
1057 buffer_free(&reply);
1058
1059 if (cc->mux_pause <= 0)
1060 fatal("%s: mux_pause %d", __func__, cc->mux_pause);
1061 cc->mux_pause = 0; /* start processing messages again */
1062 c->open_confirm_ctx = NULL;
1063 free(cctx);
1064}
1065
974static int 1066static int
975process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r) 1067process_mux_stop_listening(u_int rid, Channel *c, Buffer *m, Buffer *r)
976{ 1068{
@@ -1010,7 +1102,7 @@ mux_master_read_cb(Channel *c)
1010{ 1102{
1011 struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx; 1103 struct mux_master_state *state = (struct mux_master_state *)c->mux_ctx;
1012 Buffer in, out; 1104 Buffer in, out;
1013 void *ptr; 1105 const u_char *ptr;
1014 u_int type, rid, have, i; 1106 u_int type, rid, have, i;
1015 int ret = -1; 1107 int ret = -1;
1016 1108
@@ -1133,12 +1225,11 @@ mux_tty_alloc_failed(Channel *c)
1133void 1225void
1134muxserver_listen(void) 1226muxserver_listen(void)
1135{ 1227{
1136 struct sockaddr_un addr;
1137 socklen_t sun_len;
1138 mode_t old_umask; 1228 mode_t old_umask;
1139 char *orig_control_path = options.control_path; 1229 char *orig_control_path = options.control_path;
1140 char rbuf[16+1]; 1230 char rbuf[16+1];
1141 u_int i, r; 1231 u_int i, r;
1232 int oerrno;
1142 1233
1143 if (options.control_path == NULL || 1234 if (options.control_path == NULL ||
1144 options.control_master == SSHCTL_MASTER_NO) 1235 options.control_master == SSHCTL_MASTER_NO)
@@ -1163,24 +1254,12 @@ muxserver_listen(void)
1163 xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf); 1254 xasprintf(&options.control_path, "%s.%s", orig_control_path, rbuf);
1164 debug3("%s: temporary control path %s", __func__, options.control_path); 1255 debug3("%s: temporary control path %s", __func__, options.control_path);
1165 1256
1166 memset(&addr, '\0', sizeof(addr));
1167 addr.sun_family = AF_UNIX;
1168 sun_len = offsetof(struct sockaddr_un, sun_path) +
1169 strlen(options.control_path) + 1;
1170
1171 if (strlcpy(addr.sun_path, options.control_path,
1172 sizeof(addr.sun_path)) >= sizeof(addr.sun_path)) {
1173 error("ControlPath \"%s\" too long for Unix domain socket",
1174 options.control_path);
1175 goto disable_mux_master;
1176 }
1177
1178 if ((muxserver_sock = socket(PF_UNIX, SOCK_STREAM, 0)) < 0)
1179 fatal("%s socket(): %s", __func__, strerror(errno));
1180
1181 old_umask = umask(0177); 1257 old_umask = umask(0177);
1182 if (bind(muxserver_sock, (struct sockaddr *)&addr, sun_len) == -1) { 1258 muxserver_sock = unix_listener(options.control_path, 64, 0);
1183 if (errno == EINVAL || errno == EADDRINUSE) { 1259 oerrno = errno;
1260 umask(old_umask);
1261 if (muxserver_sock < 0) {
1262 if (oerrno == EINVAL || oerrno == EADDRINUSE) {
1184 error("ControlSocket %s already exists, " 1263 error("ControlSocket %s already exists, "
1185 "disabling multiplexing", options.control_path); 1264 "disabling multiplexing", options.control_path);
1186 disable_mux_master: 1265 disable_mux_master:
@@ -1193,13 +1272,11 @@ muxserver_listen(void)
1193 options.control_path = NULL; 1272 options.control_path = NULL;
1194 options.control_master = SSHCTL_MASTER_NO; 1273 options.control_master = SSHCTL_MASTER_NO;
1195 return; 1274 return;
1196 } else 1275 } else {
1197 fatal("%s bind(): %s", __func__, strerror(errno)); 1276 /* unix_listener() logs the error */
1277 cleanup_exit(255);
1278 }
1198 } 1279 }
1199 umask(old_umask);
1200
1201 if (listen(muxserver_sock, 64) == -1)
1202 fatal("%s listen(): %s", __func__, strerror(errno));
1203 1280
1204 /* Now atomically "move" the mux socket into position */ 1281 /* Now atomically "move" the mux socket into position */
1205 if (link(options.control_path, orig_control_path) != 0) { 1282 if (link(options.control_path, orig_control_path) != 0) {
@@ -1429,7 +1506,7 @@ mux_client_read_packet(int fd, Buffer *m)
1429{ 1506{
1430 Buffer queue; 1507 Buffer queue;
1431 u_int need, have; 1508 u_int need, have;
1432 void *ptr; 1509 const u_char *ptr;
1433 int oerrno; 1510 int oerrno;
1434 1511
1435 buffer_init(&queue); 1512 buffer_init(&queue);
@@ -1593,7 +1670,7 @@ mux_client_request_terminate(int fd)
1593} 1670}
1594 1671
1595static int 1672static int
1596mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd) 1673mux_client_forward(int fd, int cancel_flag, u_int ftype, struct Forward *fwd)
1597{ 1674{
1598 Buffer m; 1675 Buffer m;
1599 char *e, *fwd_desc; 1676 char *e, *fwd_desc;
@@ -1608,11 +1685,19 @@ mux_client_forward(int fd, int cancel_flag, u_int ftype, Forward *fwd)
1608 buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD); 1685 buffer_put_int(&m, cancel_flag ? MUX_C_CLOSE_FWD : MUX_C_OPEN_FWD);
1609 buffer_put_int(&m, muxclient_request_id); 1686 buffer_put_int(&m, muxclient_request_id);
1610 buffer_put_int(&m, ftype); 1687 buffer_put_int(&m, ftype);
1611 buffer_put_cstring(&m, 1688 if (fwd->listen_path != NULL) {
1612 fwd->listen_host == NULL ? "" : fwd->listen_host); 1689 buffer_put_cstring(&m, fwd->listen_path);
1690 } else {
1691 buffer_put_cstring(&m,
1692 fwd->listen_host == NULL ? "" : fwd->listen_host);
1693 }
1613 buffer_put_int(&m, fwd->listen_port); 1694 buffer_put_int(&m, fwd->listen_port);
1614 buffer_put_cstring(&m, 1695 if (fwd->connect_path != NULL) {
1615 fwd->connect_host == NULL ? "" : fwd->connect_host); 1696 buffer_put_cstring(&m, fwd->connect_path);
1697 } else {
1698 buffer_put_cstring(&m,
1699 fwd->connect_host == NULL ? "" : fwd->connect_host);
1700 }
1616 buffer_put_int(&m, fwd->connect_port); 1701 buffer_put_int(&m, fwd->connect_port);
1617 1702
1618 if (mux_client_write_packet(fd, &m) != 0) 1703 if (mux_client_write_packet(fd, &m) != 0)
@@ -1922,7 +2007,7 @@ mux_client_request_stdio_fwd(int fd)
1922 case MUX_S_FAILURE: 2007 case MUX_S_FAILURE:
1923 e = buffer_get_string(&m, NULL); 2008 e = buffer_get_string(&m, NULL);
1924 buffer_free(&m); 2009 buffer_free(&m);
1925 fatal("%s: stdio forwarding request failed: %s", __func__, e); 2010 fatal("Stdio forwarding request failed: %s", e);
1926 default: 2011 default:
1927 buffer_free(&m); 2012 buffer_free(&m);
1928 error("%s: unexpected response from master 0x%08x", 2013 error("%s: unexpected response from master 0x%08x",
diff --git a/myproposal.h b/myproposal.h
index 3a0f5aeab..b35b2b8bd 100644
--- a/myproposal.h
+++ b/myproposal.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: myproposal.h,v 1.35 2013/12/06 13:39:49 markus Exp $ */ 1/* $OpenBSD: myproposal.h,v 1.41 2014/07/11 13:54:34 tedu Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000 Markus Friedl. All rights reserved. 4 * Copyright (c) 2000 Markus Friedl. All rights reserved.
@@ -69,23 +69,28 @@
69#ifdef HAVE_EVP_SHA256 69#ifdef HAVE_EVP_SHA256
70# define KEX_SHA256_METHODS \ 70# define KEX_SHA256_METHODS \
71 "diffie-hellman-group-exchange-sha256," 71 "diffie-hellman-group-exchange-sha256,"
72#define KEX_CURVE25519_METHODS \
73 "curve25519-sha256@libssh.org,"
74#define SHA2_HMAC_MODES \ 72#define SHA2_HMAC_MODES \
75 "hmac-sha2-256," \ 73 "hmac-sha2-256," \
76 "hmac-sha2-512," 74 "hmac-sha2-512,"
77#else 75#else
78# define KEX_SHA256_METHODS 76# define KEX_SHA256_METHODS
79# define KEX_CURVE25519_METHODS
80# define SHA2_HMAC_MODES 77# define SHA2_HMAC_MODES
81#endif 78#endif
82 79
83# define KEX_DEFAULT_KEX \ 80#ifdef WITH_OPENSSL
81# ifdef HAVE_EVP_SHA256
82# define KEX_CURVE25519_METHODS "curve25519-sha256@libssh.org,"
83# else
84# define KEX_CURVE25519_METHODS ""
85# endif
86#define KEX_SERVER_KEX \
84 KEX_CURVE25519_METHODS \ 87 KEX_CURVE25519_METHODS \
85 KEX_ECDH_METHODS \ 88 KEX_ECDH_METHODS \
86 KEX_SHA256_METHODS \ 89 KEX_SHA256_METHODS \
90 "diffie-hellman-group14-sha1"
91
92#define KEX_CLIENT_KEX KEX_SERVER_KEX "," \
87 "diffie-hellman-group-exchange-sha1," \ 93 "diffie-hellman-group-exchange-sha1," \
88 "diffie-hellman-group14-sha1," \
89 "diffie-hellman-group1-sha1" 94 "diffie-hellman-group1-sha1"
90 95
91#define KEX_DEFAULT_PK_ALG \ 96#define KEX_DEFAULT_PK_ALG \
@@ -102,47 +107,91 @@
102 107
103/* the actual algorithms */ 108/* the actual algorithms */
104 109
105#define KEX_DEFAULT_ENCRYPT \ 110#define KEX_SERVER_ENCRYPT \
106 "aes128-ctr,aes192-ctr,aes256-ctr," \ 111 "aes128-ctr,aes192-ctr,aes256-ctr," \
107 "arcfour256,arcfour128," \
108 AESGCM_CIPHER_MODES \ 112 AESGCM_CIPHER_MODES \
109 "chacha20-poly1305@openssh.com," \ 113 "chacha20-poly1305@openssh.com"
114
115#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT "," \
116 "arcfour256,arcfour128," \
110 "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \ 117 "aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc," \
111 "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se" 118 "aes192-cbc,aes256-cbc,arcfour,rijndael-cbc@lysator.liu.se"
112 119
113#define KEX_DEFAULT_MAC \ 120#define KEX_SERVER_MAC \
114 "hmac-md5-etm@openssh.com," \
115 "hmac-sha1-etm@openssh.com," \
116 "umac-64-etm@openssh.com," \ 121 "umac-64-etm@openssh.com," \
117 "umac-128-etm@openssh.com," \ 122 "umac-128-etm@openssh.com," \
118 "hmac-sha2-256-etm@openssh.com," \ 123 "hmac-sha2-256-etm@openssh.com," \
119 "hmac-sha2-512-etm@openssh.com," \ 124 "hmac-sha2-512-etm@openssh.com," \
125 "hmac-sha1-etm@openssh.com," \
126 "umac-64@openssh.com," \
127 "umac-128@openssh.com," \
128 "hmac-sha2-256," \
129 "hmac-sha2-512," \
130 "hmac-sha1"
131
132#define KEX_CLIENT_MAC KEX_SERVER_MAC "," \
133 "hmac-md5-etm@openssh.com," \
120 "hmac-ripemd160-etm@openssh.com," \ 134 "hmac-ripemd160-etm@openssh.com," \
121 "hmac-sha1-96-etm@openssh.com," \ 135 "hmac-sha1-96-etm@openssh.com," \
122 "hmac-md5-96-etm@openssh.com," \ 136 "hmac-md5-96-etm@openssh.com," \
123 "hmac-md5," \ 137 "hmac-md5," \
124 "hmac-sha1," \
125 "umac-64@openssh.com," \
126 "umac-128@openssh.com," \
127 SHA2_HMAC_MODES \
128 "hmac-ripemd160," \ 138 "hmac-ripemd160," \
129 "hmac-ripemd160@openssh.com," \ 139 "hmac-ripemd160@openssh.com," \
130 "hmac-sha1-96," \ 140 "hmac-sha1-96," \
131 "hmac-md5-96" 141 "hmac-md5-96"
132 142
143#else
144
145#define KEX_SERVER_KEX \
146 "curve25519-sha256@libssh.org"
147#define KEX_DEFAULT_PK_ALG \
148 "ssh-ed25519-cert-v01@openssh.com," \
149 "ssh-ed25519"
150#define KEX_SERVER_ENCRYPT \
151 "aes128-ctr,aes192-ctr,aes256-ctr," \
152 "chacha20-poly1305@openssh.com"
153#define KEX_SERVER_MAC \
154 "umac-64-etm@openssh.com," \
155 "umac-128-etm@openssh.com," \
156 "hmac-sha2-256-etm@openssh.com," \
157 "hmac-sha2-512-etm@openssh.com," \
158 "hmac-sha1-etm@openssh.com," \
159 "umac-64@openssh.com," \
160 "umac-128@openssh.com," \
161 "hmac-sha2-256," \
162 "hmac-sha2-512," \
163 "hmac-sha1"
164
165#define KEX_CLIENT_KEX KEX_SERVER_KEX
166#define KEX_CLIENT_ENCRYPT KEX_SERVER_ENCRYPT
167#define KEX_CLIENT_MAC KEX_SERVER_MAC
168
169#endif /* WITH_OPENSSL */
170
133#define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib" 171#define KEX_DEFAULT_COMP "none,zlib@openssh.com,zlib"
134#define KEX_DEFAULT_LANG "" 172#define KEX_DEFAULT_LANG ""
135 173
174#define KEX_CLIENT \
175 KEX_CLIENT_KEX, \
176 KEX_DEFAULT_PK_ALG, \
177 KEX_CLIENT_ENCRYPT, \
178 KEX_CLIENT_ENCRYPT, \
179 KEX_CLIENT_MAC, \
180 KEX_CLIENT_MAC, \
181 KEX_DEFAULT_COMP, \
182 KEX_DEFAULT_COMP, \
183 KEX_DEFAULT_LANG, \
184 KEX_DEFAULT_LANG
136 185
137static char *myproposal[PROPOSAL_MAX] = { 186#define KEX_SERVER \
138 KEX_DEFAULT_KEX, 187 KEX_SERVER_KEX, \
139 KEX_DEFAULT_PK_ALG, 188 KEX_DEFAULT_PK_ALG, \
140 KEX_DEFAULT_ENCRYPT, 189 KEX_SERVER_ENCRYPT, \
141 KEX_DEFAULT_ENCRYPT, 190 KEX_SERVER_ENCRYPT, \
142 KEX_DEFAULT_MAC, 191 KEX_SERVER_MAC, \
143 KEX_DEFAULT_MAC, 192 KEX_SERVER_MAC, \
144 KEX_DEFAULT_COMP, 193 KEX_DEFAULT_COMP, \
145 KEX_DEFAULT_COMP, 194 KEX_DEFAULT_COMP, \
146 KEX_DEFAULT_LANG, 195 KEX_DEFAULT_LANG, \
147 KEX_DEFAULT_LANG 196 KEX_DEFAULT_LANG
148}; 197
diff --git a/openbsd-compat/Makefile.in b/openbsd-compat/Makefile.in
index 6ecfb93d5..ab1a3e315 100644
--- a/openbsd-compat/Makefile.in
+++ b/openbsd-compat/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.55 2014/02/04 00:37:50 djm Exp $ 1# $Id: Makefile.in,v 1.56 2014/09/30 23:43:08 djm Exp $
2 2
3sysconfdir=@sysconfdir@ 3sysconfdir=@sysconfdir@
4piddir=@piddir@ 4piddir=@piddir@
@@ -18,7 +18,7 @@ LDFLAGS=-L. @LDFLAGS@
18 18
19OPENBSD=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 realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.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 19OPENBSD=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 realpath.o rresvport.o setenv.o setproctitle.o sha2.o sigact.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
20 20
21COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.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 xmmap.o xcrypt.o 21COMPAT=arc4random.o bsd-asprintf.o bsd-closefrom.o bsd-cray.o bsd-cygwin_util.o bsd-getpeereid.o getrrsetbyname-ldns.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 xmmap.o xcrypt.o kludge-fd_set.o
22 22
23PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o 23PORTS=port-aix.o port-irix.o port-linux.o port-solaris.o port-tun.o port-uw.o
24 24
diff --git a/openbsd-compat/arc4random.c b/openbsd-compat/arc4random.c
index eac073cc0..09dbfda16 100644
--- a/openbsd-compat/arc4random.c
+++ b/openbsd-compat/arc4random.c
@@ -87,7 +87,7 @@ _rs_stir(void)
87 _rs_init(rnd, sizeof(rnd)); 87 _rs_init(rnd, sizeof(rnd));
88 } else 88 } else
89 _rs_rekey(rnd, sizeof(rnd)); 89 _rs_rekey(rnd, sizeof(rnd));
90 memset(rnd, 0, sizeof(rnd)); 90 explicit_bzero(rnd, sizeof(rnd));
91 91
92 /* invalidate rs_buf */ 92 /* invalidate rs_buf */
93 rs_have = 0; 93 rs_have = 0;
@@ -229,7 +229,7 @@ arc4random_buf(void *_buf, size_t n)
229 buf[i] = r & 0xff; 229 buf[i] = r & 0xff;
230 r >>= 8; 230 r >>= 8;
231 } 231 }
232 i = r = 0; 232 explicit_bzero(&r, sizeof(r));
233} 233}
234#endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */ 234#endif /* !defined(HAVE_ARC4RANDOM_BUF) && defined(HAVE_ARC4RANDOM) */
235 235
diff --git a/openbsd-compat/bsd-cygwin_util.c b/openbsd-compat/bsd-cygwin_util.c
index 267e77a11..a2d82126d 100644
--- a/openbsd-compat/bsd-cygwin_util.c
+++ b/openbsd-compat/bsd-cygwin_util.c
@@ -57,6 +57,22 @@ check_ntsec(const char *filename)
57 return (pathconf(filename, _PC_POSIX_PERMISSIONS)); 57 return (pathconf(filename, _PC_POSIX_PERMISSIONS));
58} 58}
59 59
60const char *
61cygwin_ssh_privsep_user()
62{
63 static char cyg_privsep_user[DNLEN + UNLEN + 2];
64
65 if (!cyg_privsep_user[0])
66 {
67#ifdef CW_CYGNAME_FROM_WINNAME
68 if (cygwin_internal (CW_CYGNAME_FROM_WINNAME, "sshd", cyg_privsep_user,
69 sizeof cyg_privsep_user) != 0)
70#endif
71 strcpy (cyg_privsep_user, "sshd");
72 }
73 return cyg_privsep_user;
74}
75
60#define NL(x) x, (sizeof (x) - 1) 76#define NL(x) x, (sizeof (x) - 1)
61#define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0])) 77#define WENV_SIZ (sizeof (wenv_arr) / sizeof (wenv_arr[0]))
62 78
diff --git a/openbsd-compat/bsd-cygwin_util.h b/openbsd-compat/bsd-cygwin_util.h
index 1177366f1..79cb2a197 100644
--- a/openbsd-compat/bsd-cygwin_util.h
+++ b/openbsd-compat/bsd-cygwin_util.h
@@ -1,4 +1,4 @@
1/* $Id: bsd-cygwin_util.h,v 1.17 2014/01/18 10:04:00 dtucker Exp $ */ 1/* $Id: bsd-cygwin_util.h,v 1.18 2014/05/27 04:34:43 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com> 4 * Copyright (c) 2000, 2001, 2011, 2013 Corinna Vinschen <vinschen@redhat.com>
@@ -39,6 +39,8 @@
39/* Avoid including windows headers. */ 39/* Avoid including windows headers. */
40typedef void *HANDLE; 40typedef void *HANDLE;
41#define INVALID_HANDLE_VALUE ((HANDLE) -1) 41#define INVALID_HANDLE_VALUE ((HANDLE) -1)
42#define DNLEN 16
43#define UNLEN 256
42 44
43/* Cygwin functions for which declarations are only available when including 45/* Cygwin functions for which declarations are only available when including
44 windows headers, so we have to define them here explicitely. */ 46 windows headers, so we have to define them here explicitely. */
@@ -48,6 +50,8 @@ extern void cygwin_set_impersonation_token (const HANDLE);
48#include <sys/cygwin.h> 50#include <sys/cygwin.h>
49#include <io.h> 51#include <io.h>
50 52
53#define CYGWIN_SSH_PRIVSEP_USER (cygwin_ssh_privsep_user())
54const char *cygwin_ssh_privsep_user();
51 55
52int binary_open(const char *, int , ...); 56int binary_open(const char *, int , ...);
53int check_ntsec(const char *); 57int check_ntsec(const char *);
diff --git a/openbsd-compat/bsd-snprintf.c b/openbsd-compat/bsd-snprintf.c
index 975991e7f..23a635989 100644
--- a/openbsd-compat/bsd-snprintf.c
+++ b/openbsd-compat/bsd-snprintf.c
@@ -538,7 +538,7 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen,
538 } 538 }
539 while (*value && (cnt < max)) { 539 while (*value && (cnt < max)) {
540 DOPR_OUTCH(buffer, *currlen, maxlen, *value); 540 DOPR_OUTCH(buffer, *currlen, maxlen, *value);
541 *value++; 541 value++;
542 ++cnt; 542 ++cnt;
543 } 543 }
544 while ((padlen < 0) && (cnt < max)) { 544 while ((padlen < 0) && (cnt < max)) {
@@ -553,7 +553,7 @@ fmtstr(char *buffer, size_t *currlen, size_t maxlen,
553 553
554static int 554static int
555fmtint(char *buffer, size_t *currlen, size_t maxlen, 555fmtint(char *buffer, size_t *currlen, size_t maxlen,
556 LLONG value, int base, int min, int max, int flags) 556 intmax_t value, int base, int min, int max, int flags)
557{ 557{
558 int signvalue = 0; 558 int signvalue = 0;
559 unsigned LLONG uvalue; 559 unsigned LLONG uvalue;
diff --git a/openbsd-compat/explicit_bzero.c b/openbsd-compat/explicit_bzero.c
index b106741e5..3c85a4843 100644
--- a/openbsd-compat/explicit_bzero.c
+++ b/openbsd-compat/explicit_bzero.c
@@ -7,14 +7,34 @@
7 7
8#include "includes.h" 8#include "includes.h"
9 9
10/*
11 * explicit_bzero - don't let the compiler optimize away bzero
12 */
13
10#ifndef HAVE_EXPLICIT_BZERO 14#ifndef HAVE_EXPLICIT_BZERO
11 15
16#ifdef HAVE_MEMSET_S
17
18void
19explicit_bzero(void *p, size_t n)
20{
21 (void)memset_s(p, n, 0, n);
22}
23
24#else /* HAVE_MEMSET_S */
25
12/* 26/*
13 * explicit_bzero - don't let the compiler optimize away bzero 27 * Indirect bzero through a volatile pointer to hopefully avoid
28 * dead-store optimisation eliminating the call.
14 */ 29 */
30static void (* volatile ssh_bzero)(void *, size_t) = bzero;
31
15void 32void
16explicit_bzero(void *p, size_t n) 33explicit_bzero(void *p, size_t n)
17{ 34{
18 bzero(p, n); 35 ssh_bzero(p, n);
19} 36}
20#endif 37
38#endif /* HAVE_MEMSET_S */
39
40#endif /* HAVE_EXPLICIT_BZERO */
diff --git a/openbsd-compat/kludge-fd_set.c b/openbsd-compat/kludge-fd_set.c
new file mode 100644
index 000000000..6c2ffb64b
--- /dev/null
+++ b/openbsd-compat/kludge-fd_set.c
@@ -0,0 +1,28 @@
1/* Placed in the public domain. */
2
3/*
4 * _FORTIFY_SOURCE includes a misguided check for FD_SET(n)/FD_ISSET(b)
5 * where n > FD_SETSIZE. This breaks OpenSSH and other programs that
6 * explicitly allocate fd_sets. To avoid this, we wrap FD_SET in a
7 * function compiled without _FORTIFY_SOURCE.
8 */
9
10#include "config.h"
11
12#if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE)
13# include <features.h>
14# if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ)
15# if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0)
16# undef _FORTIFY_SOURCE
17# undef __USE_FORTIFY_LEVEL
18# include <sys/socket.h>
19void kludge_FD_SET(int n, fd_set *set) {
20 FD_SET(n, set);
21}
22int kludge_FD_ISSET(int n, fd_set *set) {
23 return FD_ISSET(n, set);
24}
25# endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */
26# endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */
27#endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */
28
diff --git a/openbsd-compat/openbsd-compat.h b/openbsd-compat/openbsd-compat.h
index bc9888e31..ce6abae82 100644
--- a/openbsd-compat/openbsd-compat.h
+++ b/openbsd-compat/openbsd-compat.h
@@ -1,4 +1,4 @@
1/* $Id: openbsd-compat.h,v 1.61 2014/02/04 00:18:23 djm Exp $ */ 1/* $Id: openbsd-compat.h,v 1.62 2014/09/30 23:43:08 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 1999-2003 Damien Miller. All rights reserved. 4 * Copyright (c) 1999-2003 Damien Miller. All rights reserved.
@@ -268,4 +268,20 @@ char *shadow_pw(struct passwd *pw);
268#include "port-tun.h" 268#include "port-tun.h"
269#include "port-uw.h" 269#include "port-uw.h"
270 270
271/* _FORTIFY_SOURCE breaks FD_ISSET(n)/FD_SET(n) for n > FD_SETSIZE. Avoid. */
272#if defined(HAVE_FEATURES_H) && defined(_FORTIFY_SOURCE)
273# include <features.h>
274# if defined(__GNU_LIBRARY__) && defined(__GLIBC_PREREQ)
275# if __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0)
276# include <sys/socket.h> /* Ensure include guard is defined */
277# undef FD_SET
278# undef FD_ISSET
279# define FD_SET(n, set) kludge_FD_SET(n, set)
280# define FD_ISSET(n, set) kludge_FD_ISSET(n, set)
281void kludge_FD_SET(int, fd_set *);
282int kludge_FD_ISSET(int, fd_set *);
283# endif /* __GLIBC_PREREQ(2, 15) && (_FORTIFY_SOURCE > 0) */
284# endif /* __GNU_LIBRARY__ && __GLIBC_PREREQ */
285#endif /* HAVE_FEATURES_H && _FORTIFY_SOURCE */
286
271#endif /* _OPENBSD_COMPAT_H */ 287#endif /* _OPENBSD_COMPAT_H */
diff --git a/openbsd-compat/openssl-compat.c b/openbsd-compat/openssl-compat.c
index 885c121f2..defd5fb61 100644
--- a/openbsd-compat/openssl-compat.c
+++ b/openbsd-compat/openssl-compat.c
@@ -1,4 +1,4 @@
1/* $Id: openssl-compat.c,v 1.17 2014/02/13 05:38:33 dtucker Exp $ */ 1/* $Id: openssl-compat.c,v 1.19 2014/07/02 05:28:07 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> 4 * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@@ -16,6 +16,7 @@
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS
19#include "includes.h" 20#include "includes.h"
20 21
21#include <stdarg.h> 22#include <stdarg.h>
@@ -26,147 +27,44 @@
26# include <openssl/conf.h> 27# include <openssl/conf.h>
27#endif 28#endif
28 29
29#ifndef HAVE_RSA_GET_DEFAULT_METHOD
30# include <openssl/rsa.h>
31#endif
32
33#include "log.h" 30#include "log.h"
34 31
35#define SSH_DONT_OVERLOAD_OPENSSL_FUNCS
36#include "openssl-compat.h" 32#include "openssl-compat.h"
37 33
38#ifdef SSH_OLD_EVP 34/*
39int 35 * OpenSSL version numbers: MNNFFPPS: major minor fix patch status
40ssh_EVP_CipherInit(EVP_CIPHER_CTX *evp, const EVP_CIPHER *type, 36 * We match major, minor, fix and status (not patch) for <1.0.0.
41 unsigned char *key, unsigned char *iv, int enc) 37 * After that, we accept compatible fix and status versions (so we
42{ 38 * allow 1.0.1 to work with 1.0.0). Going backwards is only allowed
43 EVP_CipherInit(evp, type, key, iv, enc); 39 * within a patch series.
44 return 1; 40 */
45}
46
47int
48ssh_EVP_Cipher(EVP_CIPHER_CTX *evp, char *dst, char *src, int len)
49{
50 EVP_Cipher(evp, dst, src, len);
51 return 1;
52}
53
54int
55ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *evp)
56{
57 EVP_CIPHER_CTX_cleanup(evp);
58 return 1;
59}
60#endif
61
62#ifndef HAVE_EVP_DIGESTINIT_EX
63int
64EVP_DigestInit_ex(EVP_MD_CTX *ctx, const EVP_MD *md, void *engine)
65{
66 if (engine != NULL)
67 fatal("%s: ENGINE is not supported", __func__);
68# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
69 EVP_DigestInit(ctx, md);
70 return 1;
71# else
72 return EVP_DigestInit(ctx, md);
73# endif
74}
75#endif
76
77#ifndef HAVE_EVP_DIGESTFINAL_EX
78int
79EVP_DigestFinal_ex(EVP_MD_CTX *ctx, unsigned char *md, unsigned int *s)
80{
81# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
82 EVP_DigestFinal(ctx, md, s);
83 return 1;
84# else
85 return EVP_DigestFinal(ctx, md, s);
86# endif
87}
88#endif
89
90#ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
91int
92ssh_EVP_DigestUpdate(EVP_MD_CTX *ctx, const void *d, unsigned int cnt)
93{
94 EVP_DigestUpdate(ctx, d, cnt);
95 return 1;
96}
97#endif
98
99#ifndef HAVE_EVP_MD_CTX_COPY_EX
100int
101EVP_MD_CTX_copy_ex(EVP_MD_CTX *out, const EVP_MD_CTX *in)
102{
103 return EVP_MD_CTX_copy(out, in);
104}
105#endif
106
107#ifndef HAVE_BN_IS_PRIME_EX
108int
109BN_is_prime_ex(const BIGNUM *p, int nchecks, BN_CTX *ctx, void *cb)
110{
111 if (cb != NULL)
112 fatal("%s: callback args not supported", __func__);
113 return BN_is_prime(p, nchecks, NULL, ctx, NULL);
114}
115#endif
116
117#ifndef HAVE_RSA_GENERATE_KEY_EX
118int
119RSA_generate_key_ex(RSA *rsa, int bits, BIGNUM *bn_e, void *cb)
120{
121 RSA *new_rsa, tmp_rsa;
122 unsigned long e;
123
124 if (cb != NULL)
125 fatal("%s: callback args not supported", __func__);
126 e = BN_get_word(bn_e);
127 if (e == 0xffffffffL)
128 fatal("%s: value of e too large", __func__);
129 new_rsa = RSA_generate_key(bits, e, NULL, NULL);
130 if (new_rsa == NULL)
131 return 0;
132 /* swap rsa/new_rsa then free new_rsa */
133 tmp_rsa = *rsa;
134 *rsa = *new_rsa;
135 *new_rsa = tmp_rsa;
136 RSA_free(new_rsa);
137 return 1;
138}
139#endif
140 41
141#ifndef HAVE_DSA_GENERATE_PARAMETERS_EX
142int 42int
143DSA_generate_parameters_ex(DSA *dsa, int bits, const unsigned char *seed, 43ssh_compatible_openssl(long headerver, long libver)
144 int seed_len, int *counter_ret, unsigned long *h_ret, void *cb)
145{ 44{
146 DSA *new_dsa, tmp_dsa; 45 long mask, hfix, lfix;
147 46
148 if (cb != NULL) 47 /* exact match is always OK */
149 fatal("%s: callback args not supported", __func__); 48 if (headerver == libver)
150 new_dsa = DSA_generate_parameters(bits, (unsigned char *)seed, seed_len, 49 return 1;
151 counter_ret, h_ret, NULL, NULL); 50
152 if (new_dsa == NULL) 51 /* for versions < 1.0.0, major,minor,fix,status must match */
153 return 0; 52 if (headerver < 0x1000000f) {
154 /* swap dsa/new_dsa then free new_dsa */ 53 mask = 0xfffff00fL; /* major,minor,fix,status */
155 tmp_dsa = *dsa; 54 return (headerver & mask) == (libver & mask);
156 *dsa = *new_dsa; 55 }
157 *new_dsa = tmp_dsa; 56
158 DSA_free(new_dsa); 57 /*
159 return 1; 58 * For versions >= 1.0.0, major,minor must match and library
160} 59 * fix version must be equal to or newer than the header.
161#endif 60 */
162 61 mask = 0xfff00000L; /* major,minor */
163#ifndef HAVE_RSA_GET_DEFAULT_METHOD 62 hfix = (headerver & 0x000ff000) >> 12;
164RSA_METHOD * 63 lfix = (libver & 0x000ff000) >> 12;
165RSA_get_default_method(void) 64 if ( (headerver & mask) == (libver & mask) && lfix >= hfix)
166{ 65 return 1;
167 return RSA_PKCS1_SSLeay(); 66 return 0;
168} 67}
169#endif
170 68
171#ifdef USE_OPENSSL_ENGINE 69#ifdef USE_OPENSSL_ENGINE
172void 70void
diff --git a/openbsd-compat/openssl-compat.h b/openbsd-compat/openssl-compat.h
index 276b9706d..3695d412b 100644
--- a/openbsd-compat/openssl-compat.h
+++ b/openbsd-compat/openssl-compat.h
@@ -1,4 +1,4 @@
1/* $Id: openssl-compat.h,v 1.26 2014/02/13 05:38:33 dtucker Exp $ */ 1/* $Id: openssl-compat.h,v 1.31 2014/08/29 18:18:29 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au> 4 * Copyright (c) 2005 Darren Tucker <dtucker@zip.com.au>
@@ -16,28 +16,19 @@
16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 16 * OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
17 */ 17 */
18 18
19#ifndef _OPENSSL_COMPAT_H
20#define _OPENSSL_COMPAT_H
21
19#include "includes.h" 22#include "includes.h"
20#include <openssl/opensslv.h> 23#include <openssl/opensslv.h>
21#include <openssl/evp.h> 24#include <openssl/evp.h>
22#include <openssl/rsa.h> 25#include <openssl/rsa.h>
23#include <openssl/dsa.h> 26#include <openssl/dsa.h>
24 27
25/* Only in 0.9.8 */ 28int ssh_compatible_openssl(long, long);
26#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
27# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
28#endif
29#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
30# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
31#endif
32
33/* OPENSSL_free() is Free() in versions before OpenSSL 0.9.6 */
34#if !defined(OPENSSL_VERSION_NUMBER) || (OPENSSL_VERSION_NUMBER < 0x0090600f)
35# define OPENSSL_free(x) Free(x)
36#endif
37 29
38#if OPENSSL_VERSION_NUMBER < 0x00906000L 30#if (OPENSSL_VERSION_NUMBER <= 0x0090805fL)
39# define SSH_OLD_EVP 31# error OpenSSL 0.9.8f or greater is required
40# define EVP_CIPHER_CTX_get_app_data(e) ((e)->app_data)
41#endif 32#endif
42 33
43#if OPENSSL_VERSION_NUMBER < 0x10000001L 34#if OPENSSL_VERSION_NUMBER < 0x10000001L
@@ -46,27 +37,17 @@
46# define LIBCRYPTO_EVP_INL_TYPE size_t 37# define LIBCRYPTO_EVP_INL_TYPE size_t
47#endif 38#endif
48 39
49#if (OPENSSL_VERSION_NUMBER < 0x00907000L) || defined(OPENSSL_LOBOTOMISED_AES) 40#ifndef OPENSSL_RSA_MAX_MODULUS_BITS
50# define USE_BUILTIN_RIJNDAEL 41# define OPENSSL_RSA_MAX_MODULUS_BITS 16384
51#endif 42#endif
52 43#ifndef OPENSSL_DSA_MAX_MODULUS_BITS
53#ifdef USE_BUILTIN_RIJNDAEL 44# define OPENSSL_DSA_MAX_MODULUS_BITS 10000
54# include "rijndael.h"
55# define AES_KEY rijndael_ctx
56# define AES_BLOCK_SIZE 16
57# define AES_encrypt(a, b, c) rijndael_encrypt(c, a, b)
58# define AES_set_encrypt_key(a, b, c) rijndael_set_key(c, (char *)a, b, 1)
59# define EVP_aes_128_cbc evp_rijndael
60# define EVP_aes_192_cbc evp_rijndael
61# define EVP_aes_256_cbc evp_rijndael
62const EVP_CIPHER *evp_rijndael(void);
63void ssh_rijndael_iv(EVP_CIPHER_CTX *, int, u_char *, u_int);
64#endif 45#endif
65 46
66#ifndef OPENSSL_HAVE_EVPCTR 47#ifndef OPENSSL_HAVE_EVPCTR
67#define EVP_aes_128_ctr evp_aes_128_ctr 48# define EVP_aes_128_ctr evp_aes_128_ctr
68#define EVP_aes_192_ctr evp_aes_128_ctr 49# define EVP_aes_192_ctr evp_aes_128_ctr
69#define EVP_aes_256_ctr evp_aes_128_ctr 50# define EVP_aes_256_ctr evp_aes_128_ctr
70const EVP_CIPHER *evp_aes_128_ctr(void); 51const EVP_CIPHER *evp_aes_128_ctr(void);
71void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t); 52void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
72#endif 53#endif
@@ -88,26 +69,9 @@ void ssh_aes_ctr_iv(EVP_CIPHER_CTX *, int, u_char *, size_t);
88# endif 69# endif
89#endif 70#endif
90 71
91#if OPENSSL_VERSION_NUMBER < 0x00907000L
92#define EVP_X_STATE(evp) &(evp).c
93#define EVP_X_STATE_LEN(evp) sizeof((evp).c)
94#else
95#define EVP_X_STATE(evp) (evp).cipher_data
96#define EVP_X_STATE_LEN(evp) (evp).cipher->ctx_size
97#endif
98
99/* OpenSSL 0.9.8e returns cipher key len not context key len */
100#if (OPENSSL_VERSION_NUMBER == 0x0090805fL)
101# define EVP_CIPHER_CTX_key_length(c) ((c)->key_len)
102#endif
103
104#ifndef HAVE_RSA_GET_DEFAULT_METHOD
105RSA_METHOD *RSA_get_default_method(void);
106#endif
107
108/* 72/*
109 * We overload some of the OpenSSL crypto functions with ssh_* equivalents 73 * We overload some of the OpenSSL crypto functions with ssh_* equivalents
110 * which cater for older and/or less featureful OpenSSL version. 74 * to automatically handle OpenSSL engine initialisation.
111 * 75 *
112 * In order for the compat library to call the real functions, it must 76 * In order for the compat library to call the real functions, it must
113 * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and 77 * define SSH_DONT_OVERLOAD_OPENSSL_FUNCS before including this file and
@@ -115,19 +79,6 @@ RSA_METHOD *RSA_get_default_method(void);
115 */ 79 */
116#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS 80#ifndef SSH_DONT_OVERLOAD_OPENSSL_FUNCS
117 81
118# ifdef SSH_OLD_EVP
119# ifdef EVP_Cipher
120# undef EVP_Cipher
121# endif
122# define EVP_CipherInit(a,b,c,d,e) ssh_EVP_CipherInit((a),(b),(c),(d),(e))
123# define EVP_Cipher(a,b,c,d) ssh_EVP_Cipher((a),(b),(c),(d))
124# define EVP_CIPHER_CTX_cleanup(a) ssh_EVP_CIPHER_CTX_cleanup((a))
125# endif /* SSH_OLD_EVP */
126
127# ifdef OPENSSL_EVP_DIGESTUPDATE_VOID
128# define EVP_DigestUpdate(a,b,c) ssh_EVP_DigestUpdate((a),(b),(c))
129# endif
130
131# ifdef USE_OPENSSL_ENGINE 82# ifdef USE_OPENSSL_ENGINE
132# ifdef OpenSSL_add_all_algorithms 83# ifdef OpenSSL_add_all_algorithms
133# undef OpenSSL_add_all_algorithms 84# undef OpenSSL_add_all_algorithms
@@ -135,48 +86,8 @@ RSA_METHOD *RSA_get_default_method(void);
135# define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms() 86# define OpenSSL_add_all_algorithms() ssh_OpenSSL_add_all_algorithms()
136# endif 87# endif
137 88
138# ifndef HAVE_BN_IS_PRIME_EX
139int BN_is_prime_ex(const BIGNUM *, int, BN_CTX *, void *);
140# endif
141
142# ifndef HAVE_DSA_GENERATE_PARAMETERS_EX
143int DSA_generate_parameters_ex(DSA *, int, const unsigned char *, int, int *,
144 unsigned long *, void *);
145# endif
146
147# ifndef HAVE_RSA_GENERATE_KEY_EX
148int RSA_generate_key_ex(RSA *, int, BIGNUM *, void *);
149# endif
150
151# ifndef HAVE_EVP_DIGESTINIT_EX
152int EVP_DigestInit_ex(EVP_MD_CTX *, const EVP_MD *, void *);
153# endif
154
155# ifndef HAVE_EVP_DISESTFINAL_EX
156int EVP_DigestFinal_ex(EVP_MD_CTX *, unsigned char *, unsigned int *);
157# endif
158
159# ifndef EVP_MD_CTX_COPY_EX
160int EVP_MD_CTX_copy_ex(EVP_MD_CTX *, const EVP_MD_CTX *);
161# endif
162
163int ssh_EVP_CipherInit(EVP_CIPHER_CTX *, const EVP_CIPHER *, unsigned char *,
164 unsigned char *, int);
165int ssh_EVP_Cipher(EVP_CIPHER_CTX *, char *, char *, int);
166int ssh_EVP_CIPHER_CTX_cleanup(EVP_CIPHER_CTX *);
167void ssh_OpenSSL_add_all_algorithms(void); 89void ssh_OpenSSL_add_all_algorithms(void);
168 90
169# ifndef HAVE_HMAC_CTX_INIT
170# define HMAC_CTX_init(a)
171# endif
172
173# ifndef HAVE_EVP_MD_CTX_INIT
174# define EVP_MD_CTX_init(a)
175# endif
176
177# ifndef HAVE_EVP_MD_CTX_CLEANUP
178# define EVP_MD_CTX_cleanup(a)
179# endif
180
181#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */ 91#endif /* SSH_DONT_OVERLOAD_OPENSSL_FUNCS */
182 92
93#endif /* _OPENSSL_COMPAT_H */
diff --git a/openbsd-compat/port-uw.c b/openbsd-compat/port-uw.c
index b1fbfa208..db24dbb94 100644
--- a/openbsd-compat/port-uw.c
+++ b/openbsd-compat/port-uw.c
@@ -42,6 +42,7 @@
42#include "key.h" 42#include "key.h"
43#include "auth-options.h" 43#include "auth-options.h"
44#include "log.h" 44#include "log.h"
45#include "misc.h" /* servconf.h needs misc.h for struct ForwardOptions */
45#include "servconf.h" 46#include "servconf.h"
46#include "hostfile.h" 47#include "hostfile.h"
47#include "auth.h" 48#include "auth.h"
diff --git a/openbsd-compat/regress/Makefile.in b/openbsd-compat/regress/Makefile.in
index bcf214bd0..dabdb0912 100644
--- a/openbsd-compat/regress/Makefile.in
+++ b/openbsd-compat/regress/Makefile.in
@@ -1,4 +1,4 @@
1# $Id: Makefile.in,v 1.4 2006/08/19 09:12:14 dtucker Exp $ 1# $Id: Makefile.in,v 1.5 2014/06/17 13:06:08 dtucker Exp $
2 2
3sysconfdir=@sysconfdir@ 3sysconfdir=@sysconfdir@
4piddir=@piddir@ 4piddir=@piddir@
@@ -16,11 +16,11 @@ LIBS=@LIBS@
16LDFLAGS=@LDFLAGS@ $(LIBCOMPAT) 16LDFLAGS=@LDFLAGS@ $(LIBCOMPAT)
17 17
18TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \ 18TESTPROGS=closefromtest$(EXEEXT) snprintftest$(EXEEXT) strduptest$(EXEEXT) \
19 strtonumtest$(EXEEXT) 19 strtonumtest$(EXEEXT) opensslvertest$(EXEEXT)
20 20
21all: t-exec ${OTHERTESTS} 21all: t-exec ${OTHERTESTS}
22 22
23%$(EXEEXT): %.c 23%$(EXEEXT): %.c $(LIBCOMPAT)
24 $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS) 24 $(CC) $(CFLAGS) $(CPPFLAGS) $(LDFLAGS) -o $@ $< $(LIBCOMPAT) $(LIBS)
25 25
26t-exec: $(TESTPROGS) 26t-exec: $(TESTPROGS)
diff --git a/openbsd-compat/regress/opensslvertest.c b/openbsd-compat/regress/opensslvertest.c
new file mode 100644
index 000000000..58474873d
--- /dev/null
+++ b/openbsd-compat/regress/opensslvertest.c
@@ -0,0 +1,70 @@
1/*
2 * Copyright (c) 2014 Darren Tucker
3 *
4 * Permission to use, copy, modify, and distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#include <stdio.h>
18#include <stdlib.h>
19
20int ssh_compatible_openssl(long, long);
21
22struct version_test {
23 long headerver;
24 long libver;
25 int result;
26} version_tests[] = {
27 /* built with 0.9.8b release headers */
28 { 0x0090802fL, 0x0090802fL, 1}, /* exact match */
29 { 0x0090802fL, 0x0090804fL, 1}, /* newer library fix version: ok */
30 { 0x0090802fL, 0x0090801fL, 1}, /* older library fix version: ok */
31 { 0x0090802fL, 0x0090702fL, 0}, /* older library minor version: NO */
32 { 0x0090802fL, 0x0090902fL, 0}, /* newer library minor version: NO */
33 { 0x0090802fL, 0x0080802fL, 0}, /* older library major version: NO */
34 { 0x0090802fL, 0x1000100fL, 0}, /* newer library major version: NO */
35
36 /* built with 1.0.1b release headers */
37 { 0x1000101fL, 0x1000101fL, 1},/* exact match */
38 { 0x1000101fL, 0x10001010L, 1}, /* different status: ok */
39 { 0x1000101fL, 0x1000102fL, 1}, /* newer library patch version: ok */
40 { 0x1000101fL, 0x1000100fL, 1}, /* older library patch version: ok */
41 { 0x1000101fL, 0x1000201fL, 1}, /* newer library fix version: ok */
42 { 0x1000101fL, 0x1000001fL, 0}, /* older library fix version: NO */
43 { 0x1000101fL, 0x1010101fL, 0}, /* newer library minor version: NO */
44 { 0x1000101fL, 0x0000101fL, 0}, /* older library major version: NO */
45 { 0x1000101fL, 0x2000101fL, 0}, /* newer library major version: NO */
46};
47
48void
49fail(long hver, long lver, int result)
50{
51 fprintf(stderr, "opensslver: header %lx library %lx != %d \n", hver, lver, result);
52 exit(1);
53}
54
55int
56main(void)
57{
58 unsigned int i;
59 int res;
60 long hver, lver;
61
62 for (i = 0; i < sizeof(version_tests) / sizeof(version_tests[0]); i++) {
63 hver = version_tests[i].headerver;
64 lver = version_tests[i].libver;
65 res = version_tests[i].result;
66 if (ssh_compatible_openssl(hver, lver) != res)
67 fail(hver, lver, res);
68 }
69 exit(0);
70}
diff --git a/opensshd.init.in b/opensshd.init.in
index 0db60caa7..517345bfb 100755
--- a/opensshd.init.in
+++ b/opensshd.init.in
@@ -21,6 +21,7 @@ HOST_KEY_RSA1=$sysconfdir/ssh_host_key
21HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key 21HOST_KEY_DSA=$sysconfdir/ssh_host_dsa_key
22HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key 22HOST_KEY_RSA=$sysconfdir/ssh_host_rsa_key
23@COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key 23@COMMENT_OUT_ECC@HOST_KEY_ECDSA=$sysconfdir/ssh_host_ecdsa_key
24HOST_KEY_ED25519=$sysconfdir/ssh_host_ed25519_key
24 25
25 26
26checkkeys() { 27checkkeys() {
@@ -36,6 +37,9 @@ checkkeys() {
36@COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then 37@COMMENT_OUT_ECC@ if [ ! -f $HOST_KEY_ECDSA ]; then
37@COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N "" 38@COMMENT_OUT_ECC@ ${SSH_KEYGEN} -t ecdsa -f ${HOST_KEY_ECDSA} -N ""
38@COMMENT_OUT_ECC@ fi 39@COMMENT_OUT_ECC@ fi
40 if [ ! -f $HOST_KEY_ED25519 ]; then
41 ${SSH_KEYGEN} -t ed25519 -f ${HOST_KEY_ED25519} -N ""
42 fi
39} 43}
40 44
41stop_service() { 45stop_service() {
diff --git a/packet.c b/packet.c
index 54c0558f9..6e7b87757 100644
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.c,v 1.192 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: packet.c,v 1.198 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -66,7 +66,6 @@
66#include "crc32.h" 66#include "crc32.h"
67#include "compress.h" 67#include "compress.h"
68#include "deattack.h" 68#include "deattack.h"
69#include "channels.h"
70#include "compat.h" 69#include "compat.h"
71#include "ssh1.h" 70#include "ssh1.h"
72#include "ssh2.h" 71#include "ssh2.h"
@@ -77,7 +76,9 @@
77#include "log.h" 76#include "log.h"
78#include "canohost.h" 77#include "canohost.h"
79#include "misc.h" 78#include "misc.h"
79#include "channels.h"
80#include "ssh.h" 80#include "ssh.h"
81#include "ssherr.h"
81#include "roaming.h" 82#include "roaming.h"
82 83
83#ifdef PACKET_DEBUG 84#ifdef PACKET_DEBUG
@@ -222,6 +223,7 @@ void
222packet_set_connection(int fd_in, int fd_out) 223packet_set_connection(int fd_in, int fd_out)
223{ 224{
224 const Cipher *none = cipher_by_name("none"); 225 const Cipher *none = cipher_by_name("none");
226 int r;
225 227
226 if (none == NULL) 228 if (none == NULL)
227 fatal("packet_set_connection: cannot load cipher 'none'"); 229 fatal("packet_set_connection: cannot load cipher 'none'");
@@ -229,10 +231,11 @@ packet_set_connection(int fd_in, int fd_out)
229 active_state = alloc_session_state(); 231 active_state = alloc_session_state();
230 active_state->connection_in = fd_in; 232 active_state->connection_in = fd_in;
231 active_state->connection_out = fd_out; 233 active_state->connection_out = fd_out;
232 cipher_init(&active_state->send_context, none, (const u_char *)"", 234 if ((r = cipher_init(&active_state->send_context, none,
233 0, NULL, 0, CIPHER_ENCRYPT); 235 (const u_char *)"", 0, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
234 cipher_init(&active_state->receive_context, none, (const u_char *)"", 236 (r = cipher_init(&active_state->receive_context, none,
235 0, NULL, 0, CIPHER_DECRYPT); 237 (const u_char *)"", 0, NULL, 0, CIPHER_DECRYPT)) != 0)
238 fatal("%s: cipher_init: %s", __func__, ssh_err(r));
236 active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL; 239 active_state->newkeys[MODE_IN] = active_state->newkeys[MODE_OUT] = NULL;
237 if (!active_state->initialized) { 240 if (!active_state->initialized) {
238 active_state->initialized = 1; 241 active_state->initialized = 1;
@@ -329,13 +332,15 @@ void
329packet_get_keyiv(int mode, u_char *iv, u_int len) 332packet_get_keyiv(int mode, u_char *iv, u_int len)
330{ 333{
331 CipherContext *cc; 334 CipherContext *cc;
335 int r;
332 336
333 if (mode == MODE_OUT) 337 if (mode == MODE_OUT)
334 cc = &active_state->send_context; 338 cc = &active_state->send_context;
335 else 339 else
336 cc = &active_state->receive_context; 340 cc = &active_state->receive_context;
337 341
338 cipher_get_keyiv(cc, iv, len); 342 if ((r = cipher_get_keyiv(cc, iv, len)) != 0)
343 fatal("%s: cipher_get_keyiv: %s", __func__, ssh_err(r));
339} 344}
340 345
341int 346int
@@ -381,13 +386,15 @@ void
381packet_set_iv(int mode, u_char *dat) 386packet_set_iv(int mode, u_char *dat)
382{ 387{
383 CipherContext *cc; 388 CipherContext *cc;
389 int r;
384 390
385 if (mode == MODE_OUT) 391 if (mode == MODE_OUT)
386 cc = &active_state->send_context; 392 cc = &active_state->send_context;
387 else 393 else
388 cc = &active_state->receive_context; 394 cc = &active_state->receive_context;
389 395
390 cipher_set_keyiv(cc, dat); 396 if ((r = cipher_set_keyiv(cc, dat)) != 0)
397 fatal("%s: cipher_set_keyiv: %s", __func__, ssh_err(r));
391} 398}
392 399
393int 400int
@@ -552,6 +559,7 @@ void
552packet_set_encryption_key(const u_char *key, u_int keylen, int number) 559packet_set_encryption_key(const u_char *key, u_int keylen, int number)
553{ 560{
554 const Cipher *cipher = cipher_by_number(number); 561 const Cipher *cipher = cipher_by_number(number);
562 int r;
555 563
556 if (cipher == NULL) 564 if (cipher == NULL)
557 fatal("packet_set_encryption_key: unknown cipher number %d", number); 565 fatal("packet_set_encryption_key: unknown cipher number %d", number);
@@ -561,10 +569,11 @@ packet_set_encryption_key(const u_char *key, u_int keylen, int number)
561 fatal("packet_set_encryption_key: keylen too big: %d", keylen); 569 fatal("packet_set_encryption_key: keylen too big: %d", keylen);
562 memcpy(active_state->ssh1_key, key, keylen); 570 memcpy(active_state->ssh1_key, key, keylen);
563 active_state->ssh1_keylen = keylen; 571 active_state->ssh1_keylen = keylen;
564 cipher_init(&active_state->send_context, cipher, key, keylen, NULL, 572 if ((r = cipher_init(&active_state->send_context, cipher,
565 0, CIPHER_ENCRYPT); 573 key, keylen, NULL, 0, CIPHER_ENCRYPT)) != 0 ||
566 cipher_init(&active_state->receive_context, cipher, key, keylen, NULL, 574 (r = cipher_init(&active_state->receive_context, cipher,
567 0, CIPHER_DECRYPT); 575 key, keylen, NULL, 0, CIPHER_DECRYPT)) != 0)
576 fatal("%s: cipher_init: %s", __func__, ssh_err(r));
568} 577}
569 578
570u_int 579u_int
@@ -630,6 +639,7 @@ packet_put_raw(const void *buf, u_int len)
630 buffer_append(&active_state->outgoing_packet, buf, len); 639 buffer_append(&active_state->outgoing_packet, buf, len);
631} 640}
632 641
642#ifdef WITH_OPENSSL
633void 643void
634packet_put_bignum(BIGNUM * value) 644packet_put_bignum(BIGNUM * value)
635{ 645{
@@ -641,6 +651,7 @@ packet_put_bignum2(BIGNUM * value)
641{ 651{
642 buffer_put_bignum2(&active_state->outgoing_packet, value); 652 buffer_put_bignum2(&active_state->outgoing_packet, value);
643} 653}
654#endif
644 655
645#ifdef OPENSSL_HAS_ECC 656#ifdef OPENSSL_HAS_ECC
646void 657void
@@ -742,7 +753,7 @@ set_newkeys(int mode)
742 Comp *comp; 753 Comp *comp;
743 CipherContext *cc; 754 CipherContext *cc;
744 u_int64_t *max_blocks; 755 u_int64_t *max_blocks;
745 int crypt_type; 756 int r, crypt_type;
746 757
747 debug2("set_newkeys: mode %d", mode); 758 debug2("set_newkeys: mode %d", mode);
748 759
@@ -784,8 +795,9 @@ set_newkeys(int mode)
784 if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0) 795 if (cipher_authlen(enc->cipher) == 0 && mac_init(mac) == 0)
785 mac->enabled = 1; 796 mac->enabled = 1;
786 DBG(debug("cipher_init_context: %d", mode)); 797 DBG(debug("cipher_init_context: %d", mode));
787 cipher_init(cc, enc->cipher, enc->key, enc->key_len, 798 if ((r = cipher_init(cc, enc->cipher, enc->key, enc->key_len,
788 enc->iv, enc->iv_len, crypt_type); 799 enc->iv, enc->iv_len, crypt_type)) != 0)
800 fatal("%s: cipher_init: %s", __func__, ssh_err(r));
789 /* Deleting the keys does not gain extra security */ 801 /* Deleting the keys does not gain extra security */
790 /* explicit_bzero(enc->iv, enc->block_size); 802 /* explicit_bzero(enc->iv, enc->block_size);
791 explicit_bzero(enc->key, enc->key_len); 803 explicit_bzero(enc->key, enc->key_len);
@@ -912,8 +924,8 @@ packet_send2_wrapped(void)
912 roundup(active_state->extra_pad, block_size); 924 roundup(active_state->extra_pad, block_size);
913 pad = active_state->extra_pad - 925 pad = active_state->extra_pad -
914 ((len + padlen) % active_state->extra_pad); 926 ((len + padlen) % active_state->extra_pad);
915 debug3("packet_send2: adding %d (len %d padlen %d extra_pad %d)", 927 DBG(debug3("%s: adding %d (len %d padlen %d extra_pad %d)",
916 pad, len, padlen, active_state->extra_pad); 928 __func__, pad, len, padlen, active_state->extra_pad));
917 padlen += pad; 929 padlen += pad;
918 active_state->extra_pad = 0; 930 active_state->extra_pad = 0;
919 } 931 }
@@ -1569,6 +1581,7 @@ packet_get_int64(void)
1569 * must have been initialized before this call. 1581 * must have been initialized before this call.
1570 */ 1582 */
1571 1583
1584#ifdef WITH_OPENSSL
1572void 1585void
1573packet_get_bignum(BIGNUM * value) 1586packet_get_bignum(BIGNUM * value)
1574{ 1587{
@@ -1598,6 +1611,7 @@ packet_get_raw(u_int *length_ptr)
1598 *length_ptr = bytes; 1611 *length_ptr = bytes;
1599 return buffer_ptr(&active_state->incoming_packet); 1612 return buffer_ptr(&active_state->incoming_packet);
1600} 1613}
1614#endif
1601 1615
1602int 1616int
1603packet_remaining(void) 1617packet_remaining(void)
@@ -1618,7 +1632,7 @@ packet_get_string(u_int *length_ptr)
1618 return buffer_get_string(&active_state->incoming_packet, length_ptr); 1632 return buffer_get_string(&active_state->incoming_packet, length_ptr);
1619} 1633}
1620 1634
1621void * 1635const void *
1622packet_get_string_ptr(u_int *length_ptr) 1636packet_get_string_ptr(u_int *length_ptr)
1623{ 1637{
1624 return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr); 1638 return buffer_get_string_ptr(&active_state->incoming_packet, length_ptr);
@@ -2055,3 +2069,23 @@ packet_restore_state(void)
2055 add_recv_bytes(len); 2069 add_recv_bytes(len);
2056 } 2070 }
2057} 2071}
2072
2073/* Reset after_authentication and reset compression in post-auth privsep */
2074void
2075packet_set_postauth(void)
2076{
2077 Comp *comp;
2078 int mode;
2079
2080 debug("%s: called", __func__);
2081 /* This was set in net child, but is not visible in user child */
2082 active_state->after_authentication = 1;
2083 active_state->rekeying = 0;
2084 for (mode = 0; mode < MODE_MAX; mode++) {
2085 if (active_state->newkeys[mode] == NULL)
2086 continue;
2087 comp = &active_state->newkeys[mode]->comp;
2088 if (comp && comp->enabled)
2089 packet_init_compression();
2090 }
2091}
diff --git a/packet.h b/packet.h
index f8edf851c..e7b5fcba9 100644
--- a/packet.h
+++ b/packet.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: packet.h,v 1.59 2013/07/12 00:19:59 djm Exp $ */ 1/* $OpenBSD: packet.h,v 1.61 2014/05/03 17:20:34 markus Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -70,7 +70,7 @@ void packet_get_ecpoint(const EC_GROUP *, EC_POINT *);
70void *packet_get_raw(u_int *length_ptr); 70void *packet_get_raw(u_int *length_ptr);
71void *packet_get_string(u_int *length_ptr); 71void *packet_get_string(u_int *length_ptr);
72char *packet_get_cstring(u_int *length_ptr); 72char *packet_get_cstring(u_int *length_ptr);
73void *packet_get_string_ptr(u_int *length_ptr); 73const void *packet_get_string_ptr(u_int *length_ptr);
74void packet_disconnect(const char *fmt,...) __attribute__((noreturn)) __attribute__((format(printf, 1, 2))); 74void packet_disconnect(const char *fmt,...) __attribute__((noreturn)) __attribute__((format(printf, 1, 2)));
75void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2))); 75void packet_send_debug(const char *fmt,...) __attribute__((format(printf, 1, 2)));
76 76
@@ -120,6 +120,7 @@ time_t packet_get_rekey_timeout(void);
120 120
121void packet_backup_state(void); 121void packet_backup_state(void);
122void packet_restore_state(void); 122void packet_restore_state(void);
123void packet_set_postauth(void);
123 124
124void *packet_get_input(void); 125void *packet_get_input(void);
125void *packet_get_output(void); 126void *packet_get_output(void);
diff --git a/platform.c b/platform.c
index f99de7fab..9a23e6e3e 100644
--- a/platform.c
+++ b/platform.c
@@ -1,4 +1,4 @@
1/* $Id: platform.c,v 1.21 2014/01/21 01:59:29 tim Exp $ */ 1/* $Id: platform.c,v 1.22 2014/07/18 04:11:26 djm Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2006 Darren Tucker. All rights reserved. 4 * Copyright (c) 2006 Darren Tucker. All rights reserved.
@@ -25,6 +25,7 @@
25 25
26#include "log.h" 26#include "log.h"
27#include "buffer.h" 27#include "buffer.h"
28#include "misc.h"
28#include "servconf.h" 29#include "servconf.h"
29#include "key.h" 30#include "key.h"
30#include "hostfile.h" 31#include "hostfile.h"
diff --git a/poly1305.h b/poly1305.h
index 221efc462..f7db5f8d7 100644
--- a/poly1305.h
+++ b/poly1305.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: poly1305.h,v 1.2 2013/12/19 22:57:13 djm Exp $ */ 1/* $OpenBSD: poly1305.h,v 1.4 2014/05/02 03:27:54 djm Exp $ */
2 2
3/* 3/*
4 * Public Domain poly1305 from Andrew Moon 4 * Public Domain poly1305 from Andrew Moon
diff --git a/readconf.c b/readconf.c
index 5429fc2ad..29338b619 100644
--- a/readconf.c
+++ b/readconf.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.c,v 1.218 2014/02/23 20:11:36 djm Exp $ */ 1/* $OpenBSD: readconf.c,v 1.220 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -18,6 +18,7 @@
18#include <sys/stat.h> 18#include <sys/stat.h>
19#include <sys/socket.h> 19#include <sys/socket.h>
20#include <sys/wait.h> 20#include <sys/wait.h>
21#include <sys/un.h>
21 22
22#include <netinet/in.h> 23#include <netinet/in.h>
23#include <netinet/in_systm.h> 24#include <netinet/in_systm.h>
@@ -50,9 +51,9 @@
50#include "pathnames.h" 51#include "pathnames.h"
51#include "log.h" 52#include "log.h"
52#include "key.h" 53#include "key.h"
54#include "misc.h"
53#include "readconf.h" 55#include "readconf.h"
54#include "match.h" 56#include "match.h"
55#include "misc.h"
56#include "buffer.h" 57#include "buffer.h"
57#include "kex.h" 58#include "kex.h"
58#include "mac.h" 59#include "mac.h"
@@ -153,6 +154,7 @@ typedef enum {
153 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass, 154 oKexAlgorithms, oIPQoS, oRequestTTY, oIgnoreUnknown, oProxyUseFdpass,
154 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots, 155 oCanonicalDomains, oCanonicalizeHostname, oCanonicalizeMaxDots,
155 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs, 156 oCanonicalizeFallbackLocal, oCanonicalizePermittedCNAMEs,
157 oStreamLocalBindMask, oStreamLocalBindUnlink,
156 oProtocolKeepAlives, oSetupTimeOut, 158 oProtocolKeepAlives, oSetupTimeOut,
157 oIgnoredUnknownOption, oDeprecated, oUnsupported 159 oIgnoredUnknownOption, oDeprecated, oUnsupported
158} OpCodes; 160} OpCodes;
@@ -276,6 +278,8 @@ static struct {
276 { "canonicalizehostname", oCanonicalizeHostname }, 278 { "canonicalizehostname", oCanonicalizeHostname },
277 { "canonicalizemaxdots", oCanonicalizeMaxDots }, 279 { "canonicalizemaxdots", oCanonicalizeMaxDots },
278 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs }, 280 { "canonicalizepermittedcnames", oCanonicalizePermittedCNAMEs },
281 { "streamlocalbindmask", oStreamLocalBindMask },
282 { "streamlocalbindunlink", oStreamLocalBindUnlink },
279 { "ignoreunknown", oIgnoreUnknown }, 283 { "ignoreunknown", oIgnoreUnknown },
280 { "protocolkeepalives", oProtocolKeepAlives }, 284 { "protocolkeepalives", oProtocolKeepAlives },
281 { "setuptimeout", oSetupTimeOut }, 285 { "setuptimeout", oSetupTimeOut },
@@ -289,12 +293,13 @@ static struct {
289 */ 293 */
290 294
291void 295void
292add_local_forward(Options *options, const Forward *newfwd) 296add_local_forward(Options *options, const struct Forward *newfwd)
293{ 297{
294 Forward *fwd; 298 struct Forward *fwd;
295#ifndef NO_IPPORT_RESERVED_CONCEPT 299#ifndef NO_IPPORT_RESERVED_CONCEPT
296 extern uid_t original_real_uid; 300 extern uid_t original_real_uid;
297 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0) 301 if (newfwd->listen_port < IPPORT_RESERVED && original_real_uid != 0 &&
302 newfwd->listen_path == NULL)
298 fatal("Privileged ports can only be forwarded by root."); 303 fatal("Privileged ports can only be forwarded by root.");
299#endif 304#endif
300 options->local_forwards = xrealloc(options->local_forwards, 305 options->local_forwards = xrealloc(options->local_forwards,
@@ -304,8 +309,10 @@ add_local_forward(Options *options, const Forward *newfwd)
304 309
305 fwd->listen_host = newfwd->listen_host; 310 fwd->listen_host = newfwd->listen_host;
306 fwd->listen_port = newfwd->listen_port; 311 fwd->listen_port = newfwd->listen_port;
312 fwd->listen_path = newfwd->listen_path;
307 fwd->connect_host = newfwd->connect_host; 313 fwd->connect_host = newfwd->connect_host;
308 fwd->connect_port = newfwd->connect_port; 314 fwd->connect_port = newfwd->connect_port;
315 fwd->connect_path = newfwd->connect_path;
309} 316}
310 317
311/* 318/*
@@ -314,9 +321,9 @@ add_local_forward(Options *options, const Forward *newfwd)
314 */ 321 */
315 322
316void 323void
317add_remote_forward(Options *options, const Forward *newfwd) 324add_remote_forward(Options *options, const struct Forward *newfwd)
318{ 325{
319 Forward *fwd; 326 struct Forward *fwd;
320 327
321 options->remote_forwards = xrealloc(options->remote_forwards, 328 options->remote_forwards = xrealloc(options->remote_forwards,
322 options->num_remote_forwards + 1, 329 options->num_remote_forwards + 1,
@@ -325,8 +332,10 @@ add_remote_forward(Options *options, const Forward *newfwd)
325 332
326 fwd->listen_host = newfwd->listen_host; 333 fwd->listen_host = newfwd->listen_host;
327 fwd->listen_port = newfwd->listen_port; 334 fwd->listen_port = newfwd->listen_port;
335 fwd->listen_path = newfwd->listen_path;
328 fwd->connect_host = newfwd->connect_host; 336 fwd->connect_host = newfwd->connect_host;
329 fwd->connect_port = newfwd->connect_port; 337 fwd->connect_port = newfwd->connect_port;
338 fwd->connect_path = newfwd->connect_path;
330 fwd->handle = newfwd->handle; 339 fwd->handle = newfwd->handle;
331 fwd->allocated_port = 0; 340 fwd->allocated_port = 0;
332} 341}
@@ -338,7 +347,9 @@ clear_forwardings(Options *options)
338 347
339 for (i = 0; i < options->num_local_forwards; i++) { 348 for (i = 0; i < options->num_local_forwards; i++) {
340 free(options->local_forwards[i].listen_host); 349 free(options->local_forwards[i].listen_host);
350 free(options->local_forwards[i].listen_path);
341 free(options->local_forwards[i].connect_host); 351 free(options->local_forwards[i].connect_host);
352 free(options->local_forwards[i].connect_path);
342 } 353 }
343 if (options->num_local_forwards > 0) { 354 if (options->num_local_forwards > 0) {
344 free(options->local_forwards); 355 free(options->local_forwards);
@@ -347,7 +358,9 @@ clear_forwardings(Options *options)
347 options->num_local_forwards = 0; 358 options->num_local_forwards = 0;
348 for (i = 0; i < options->num_remote_forwards; i++) { 359 for (i = 0; i < options->num_remote_forwards; i++) {
349 free(options->remote_forwards[i].listen_host); 360 free(options->remote_forwards[i].listen_host);
361 free(options->remote_forwards[i].listen_path);
350 free(options->remote_forwards[i].connect_host); 362 free(options->remote_forwards[i].connect_host);
363 free(options->remote_forwards[i].connect_path);
351 } 364 }
352 if (options->num_remote_forwards > 0) { 365 if (options->num_remote_forwards > 0) {
353 free(options->remote_forwards); 366 free(options->remote_forwards);
@@ -362,6 +375,7 @@ add_identity_file(Options *options, const char *dir, const char *filename,
362 int userprovided) 375 int userprovided)
363{ 376{
364 char *path; 377 char *path;
378 int i;
365 379
366 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES) 380 if (options->num_identity_files >= SSH_MAX_IDENTITY_FILES)
367 fatal("Too many identity files specified (max %d)", 381 fatal("Too many identity files specified (max %d)",
@@ -372,6 +386,16 @@ add_identity_file(Options *options, const char *dir, const char *filename,
372 else 386 else
373 (void)xasprintf(&path, "%.100s%.100s", dir, filename); 387 (void)xasprintf(&path, "%.100s%.100s", dir, filename);
374 388
389 /* Avoid registering duplicates */
390 for (i = 0; i < options->num_identity_files; i++) {
391 if (options->identity_file_userprovided[i] == userprovided &&
392 strcmp(options->identity_files[i], path) == 0) {
393 debug2("%s: ignoring duplicate key %s", __func__, path);
394 free(path);
395 return;
396 }
397 }
398
375 options->identity_file_userprovided[options->num_identity_files] = 399 options->identity_file_userprovided[options->num_identity_files] =
376 userprovided; 400 userprovided;
377 options->identity_files[options->num_identity_files++] = path; 401 options->identity_files[options->num_identity_files++] = path;
@@ -721,7 +745,7 @@ process_config_line(Options *options, struct passwd *pw, const char *host,
721 LogLevel *log_level_ptr; 745 LogLevel *log_level_ptr;
722 long long val64; 746 long long val64;
723 size_t len; 747 size_t len;
724 Forward fwd; 748 struct Forward fwd;
725 const struct multistate *multistate_ptr; 749 const struct multistate *multistate_ptr;
726 struct allowed_cname *cname; 750 struct allowed_cname *cname;
727 751
@@ -811,7 +835,7 @@ parse_time:
811 goto parse_time; 835 goto parse_time;
812 836
813 case oGatewayPorts: 837 case oGatewayPorts:
814 intptr = &options->gateway_ports; 838 intptr = &options->fwd_opts.gateway_ports;
815 goto parse_flag; 839 goto parse_flag;
816 840
817 case oExitOnForwardFailure: 841 case oExitOnForwardFailure:
@@ -1433,6 +1457,21 @@ parse_int:
1433 intptr = &options->canonicalize_fallback_local; 1457 intptr = &options->canonicalize_fallback_local;
1434 goto parse_flag; 1458 goto parse_flag;
1435 1459
1460 case oStreamLocalBindMask:
1461 arg = strdelim(&s);
1462 if (!arg || *arg == '\0')
1463 fatal("%.200s line %d: Missing StreamLocalBindMask argument.", filename, linenum);
1464 /* Parse mode in octal format */
1465 value = strtol(arg, &endofnumber, 8);
1466 if (arg == endofnumber || value < 0 || value > 0777)
1467 fatal("%.200s line %d: Bad mask.", filename, linenum);
1468 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1469 break;
1470
1471 case oStreamLocalBindUnlink:
1472 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1473 goto parse_flag;
1474
1436 case oDeprecated: 1475 case oDeprecated:
1437 debug("%s line %d: Deprecated option \"%s\"", 1476 debug("%s line %d: Deprecated option \"%s\"",
1438 filename, linenum, keyword); 1477 filename, linenum, keyword);
@@ -1529,7 +1568,9 @@ initialize_options(Options * options)
1529 options->forward_x11_timeout = -1; 1568 options->forward_x11_timeout = -1;
1530 options->exit_on_forward_failure = -1; 1569 options->exit_on_forward_failure = -1;
1531 options->xauth_location = NULL; 1570 options->xauth_location = NULL;
1532 options->gateway_ports = -1; 1571 options->fwd_opts.gateway_ports = -1;
1572 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
1573 options->fwd_opts.streamlocal_bind_unlink = -1;
1533 options->use_privileged_port = -1; 1574 options->use_privileged_port = -1;
1534 options->rsa_authentication = -1; 1575 options->rsa_authentication = -1;
1535 options->pubkey_authentication = -1; 1576 options->pubkey_authentication = -1;
@@ -1647,8 +1688,12 @@ fill_default_options(Options * options)
1647 options->exit_on_forward_failure = 0; 1688 options->exit_on_forward_failure = 0;
1648 if (options->xauth_location == NULL) 1689 if (options->xauth_location == NULL)
1649 options->xauth_location = _PATH_XAUTH; 1690 options->xauth_location = _PATH_XAUTH;
1650 if (options->gateway_ports == -1) 1691 if (options->fwd_opts.gateway_ports == -1)
1651 options->gateway_ports = 0; 1692 options->fwd_opts.gateway_ports = 0;
1693 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
1694 options->fwd_opts.streamlocal_bind_mask = 0177;
1695 if (options->fwd_opts.streamlocal_bind_unlink == -1)
1696 options->fwd_opts.streamlocal_bind_unlink = 0;
1652 if (options->use_privileged_port == -1) 1697 if (options->use_privileged_port == -1)
1653 options->use_privileged_port = 0; 1698 options->use_privileged_port = 0;
1654 if (options->rsa_authentication == -1) 1699 if (options->rsa_authentication == -1)
@@ -1811,22 +1856,92 @@ fill_default_options(Options * options)
1811 /* options->preferred_authentications will be set in ssh */ 1856 /* options->preferred_authentications will be set in ssh */
1812} 1857}
1813 1858
1859struct fwdarg {
1860 char *arg;
1861 int ispath;
1862};
1863
1864/*
1865 * parse_fwd_field
1866 * parses the next field in a port forwarding specification.
1867 * sets fwd to the parsed field and advances p past the colon
1868 * or sets it to NULL at end of string.
1869 * returns 0 on success, else non-zero.
1870 */
1871static int
1872parse_fwd_field(char **p, struct fwdarg *fwd)
1873{
1874 char *ep, *cp = *p;
1875 int ispath = 0;
1876
1877 if (*cp == '\0') {
1878 *p = NULL;
1879 return -1; /* end of string */
1880 }
1881
1882 /*
1883 * A field escaped with square brackets is used literally.
1884 * XXX - allow ']' to be escaped via backslash?
1885 */
1886 if (*cp == '[') {
1887 /* find matching ']' */
1888 for (ep = cp + 1; *ep != ']' && *ep != '\0'; ep++) {
1889 if (*ep == '/')
1890 ispath = 1;
1891 }
1892 /* no matching ']' or not at end of field. */
1893 if (ep[0] != ']' || (ep[1] != ':' && ep[1] != '\0'))
1894 return -1;
1895 /* NUL terminate the field and advance p past the colon */
1896 *ep++ = '\0';
1897 if (*ep != '\0')
1898 *ep++ = '\0';
1899 fwd->arg = cp + 1;
1900 fwd->ispath = ispath;
1901 *p = ep;
1902 return 0;
1903 }
1904
1905 for (cp = *p; *cp != '\0'; cp++) {
1906 switch (*cp) {
1907 case '\\':
1908 memmove(cp, cp + 1, strlen(cp + 1) + 1);
1909 cp++;
1910 break;
1911 case '/':
1912 ispath = 1;
1913 break;
1914 case ':':
1915 *cp++ = '\0';
1916 goto done;
1917 }
1918 }
1919done:
1920 fwd->arg = *p;
1921 fwd->ispath = ispath;
1922 *p = cp;
1923 return 0;
1924}
1925
1814/* 1926/*
1815 * parse_forward 1927 * parse_forward
1816 * parses a string containing a port forwarding specification of the form: 1928 * parses a string containing a port forwarding specification of the form:
1817 * dynamicfwd == 0 1929 * dynamicfwd == 0
1818 * [listenhost:]listenport:connecthost:connectport 1930 * [listenhost:]listenport|listenpath:connecthost:connectport|connectpath
1931 * listenpath:connectpath
1819 * dynamicfwd == 1 1932 * dynamicfwd == 1
1820 * [listenhost:]listenport 1933 * [listenhost:]listenport
1821 * returns number of arguments parsed or zero on error 1934 * returns number of arguments parsed or zero on error
1822 */ 1935 */
1823int 1936int
1824parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd) 1937parse_forward(struct Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1825{ 1938{
1939 struct fwdarg fwdargs[4];
1940 char *p, *cp;
1826 int i; 1941 int i;
1827 char *p, *cp, *fwdarg[4];
1828 1942
1829 memset(fwd, '\0', sizeof(*fwd)); 1943 memset(fwd, 0, sizeof(*fwd));
1944 memset(fwdargs, 0, sizeof(fwdargs));
1830 1945
1831 cp = p = xstrdup(fwdspec); 1946 cp = p = xstrdup(fwdspec);
1832 1947
@@ -1834,39 +1949,70 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1834 while (isspace((u_char)*cp)) 1949 while (isspace((u_char)*cp))
1835 cp++; 1950 cp++;
1836 1951
1837 for (i = 0; i < 4; ++i) 1952 for (i = 0; i < 4; ++i) {
1838 if ((fwdarg[i] = hpdelim(&cp)) == NULL) 1953 if (parse_fwd_field(&cp, &fwdargs[i]) != 0)
1839 break; 1954 break;
1955 }
1840 1956
1841 /* Check for trailing garbage */ 1957 /* Check for trailing garbage */
1842 if (cp != NULL) 1958 if (cp != NULL && *cp != '\0') {
1843 i = 0; /* failure */ 1959 i = 0; /* failure */
1960 }
1844 1961
1845 switch (i) { 1962 switch (i) {
1846 case 1: 1963 case 1:
1847 fwd->listen_host = NULL; 1964 if (fwdargs[0].ispath) {
1848 fwd->listen_port = a2port(fwdarg[0]); 1965 fwd->listen_path = xstrdup(fwdargs[0].arg);
1966 fwd->listen_port = PORT_STREAMLOCAL;
1967 } else {
1968 fwd->listen_host = NULL;
1969 fwd->listen_port = a2port(fwdargs[0].arg);
1970 }
1849 fwd->connect_host = xstrdup("socks"); 1971 fwd->connect_host = xstrdup("socks");
1850 break; 1972 break;
1851 1973
1852 case 2: 1974 case 2:
1853 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 1975 if (fwdargs[0].ispath && fwdargs[1].ispath) {
1854 fwd->listen_port = a2port(fwdarg[1]); 1976 fwd->listen_path = xstrdup(fwdargs[0].arg);
1855 fwd->connect_host = xstrdup("socks"); 1977 fwd->listen_port = PORT_STREAMLOCAL;
1978 fwd->connect_path = xstrdup(fwdargs[1].arg);
1979 fwd->connect_port = PORT_STREAMLOCAL;
1980 } else if (fwdargs[1].ispath) {
1981 fwd->listen_host = NULL;
1982 fwd->listen_port = a2port(fwdargs[0].arg);
1983 fwd->connect_path = xstrdup(fwdargs[1].arg);
1984 fwd->connect_port = PORT_STREAMLOCAL;
1985 } else {
1986 fwd->listen_host = xstrdup(fwdargs[0].arg);
1987 fwd->listen_port = a2port(fwdargs[1].arg);
1988 fwd->connect_host = xstrdup("socks");
1989 }
1856 break; 1990 break;
1857 1991
1858 case 3: 1992 case 3:
1859 fwd->listen_host = NULL; 1993 if (fwdargs[0].ispath) {
1860 fwd->listen_port = a2port(fwdarg[0]); 1994 fwd->listen_path = xstrdup(fwdargs[0].arg);
1861 fwd->connect_host = xstrdup(cleanhostname(fwdarg[1])); 1995 fwd->listen_port = PORT_STREAMLOCAL;
1862 fwd->connect_port = a2port(fwdarg[2]); 1996 fwd->connect_host = xstrdup(fwdargs[1].arg);
1997 fwd->connect_port = a2port(fwdargs[2].arg);
1998 } else if (fwdargs[2].ispath) {
1999 fwd->listen_host = xstrdup(fwdargs[0].arg);
2000 fwd->listen_port = a2port(fwdargs[1].arg);
2001 fwd->connect_path = xstrdup(fwdargs[2].arg);
2002 fwd->connect_port = PORT_STREAMLOCAL;
2003 } else {
2004 fwd->listen_host = NULL;
2005 fwd->listen_port = a2port(fwdargs[0].arg);
2006 fwd->connect_host = xstrdup(fwdargs[1].arg);
2007 fwd->connect_port = a2port(fwdargs[2].arg);
2008 }
1863 break; 2009 break;
1864 2010
1865 case 4: 2011 case 4:
1866 fwd->listen_host = xstrdup(cleanhostname(fwdarg[0])); 2012 fwd->listen_host = xstrdup(fwdargs[0].arg);
1867 fwd->listen_port = a2port(fwdarg[1]); 2013 fwd->listen_port = a2port(fwdargs[1].arg);
1868 fwd->connect_host = xstrdup(cleanhostname(fwdarg[2])); 2014 fwd->connect_host = xstrdup(fwdargs[2].arg);
1869 fwd->connect_port = a2port(fwdarg[3]); 2015 fwd->connect_port = a2port(fwdargs[3].arg);
1870 break; 2016 break;
1871 default: 2017 default:
1872 i = 0; /* failure */ 2018 i = 0; /* failure */
@@ -1878,29 +2024,42 @@ parse_forward(Forward *fwd, const char *fwdspec, int dynamicfwd, int remotefwd)
1878 if (!(i == 1 || i == 2)) 2024 if (!(i == 1 || i == 2))
1879 goto fail_free; 2025 goto fail_free;
1880 } else { 2026 } else {
1881 if (!(i == 3 || i == 4)) 2027 if (!(i == 3 || i == 4)) {
1882 goto fail_free; 2028 if (fwd->connect_path == NULL &&
1883 if (fwd->connect_port <= 0) 2029 fwd->listen_path == NULL)
2030 goto fail_free;
2031 }
2032 if (fwd->connect_port <= 0 && fwd->connect_path == NULL)
1884 goto fail_free; 2033 goto fail_free;
1885 } 2034 }
1886 2035
1887 if (fwd->listen_port < 0 || (!remotefwd && fwd->listen_port == 0)) 2036 if ((fwd->listen_port < 0 && fwd->listen_path == NULL) ||
2037 (!remotefwd && fwd->listen_port == 0))
1888 goto fail_free; 2038 goto fail_free;
1889
1890 if (fwd->connect_host != NULL && 2039 if (fwd->connect_host != NULL &&
1891 strlen(fwd->connect_host) >= NI_MAXHOST) 2040 strlen(fwd->connect_host) >= NI_MAXHOST)
1892 goto fail_free; 2041 goto fail_free;
2042 /* XXX - if connecting to a remote socket, max sun len may not match this host */
2043 if (fwd->connect_path != NULL &&
2044 strlen(fwd->connect_path) >= PATH_MAX_SUN)
2045 goto fail_free;
1893 if (fwd->listen_host != NULL && 2046 if (fwd->listen_host != NULL &&
1894 strlen(fwd->listen_host) >= NI_MAXHOST) 2047 strlen(fwd->listen_host) >= NI_MAXHOST)
1895 goto fail_free; 2048 goto fail_free;
1896 2049 if (fwd->listen_path != NULL &&
2050 strlen(fwd->listen_path) >= PATH_MAX_SUN)
2051 goto fail_free;
1897 2052
1898 return (i); 2053 return (i);
1899 2054
1900 fail_free: 2055 fail_free:
1901 free(fwd->connect_host); 2056 free(fwd->connect_host);
1902 fwd->connect_host = NULL; 2057 fwd->connect_host = NULL;
2058 free(fwd->connect_path);
2059 fwd->connect_path = NULL;
1903 free(fwd->listen_host); 2060 free(fwd->listen_host);
1904 fwd->listen_host = NULL; 2061 fwd->listen_host = NULL;
2062 free(fwd->listen_path);
2063 fwd->listen_path = NULL;
1905 return (0); 2064 return (0);
1906} 2065}
diff --git a/readconf.h b/readconf.h
index 5cc97f0da..0e298898a 100644
--- a/readconf.h
+++ b/readconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: readconf.h,v 1.101 2014/02/23 20:11:36 djm Exp $ */ 1/* $OpenBSD: readconf.h,v 1.102 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -16,21 +16,12 @@
16#ifndef READCONF_H 16#ifndef READCONF_H
17#define READCONF_H 17#define READCONF_H
18 18
19/* Data structure for representing a forwarding request. */
20
21typedef struct {
22 char *listen_host; /* Host (address) to listen on. */
23 int listen_port; /* Port to forward. */
24 char *connect_host; /* Host to connect. */
25 int connect_port; /* Port to connect on connect_host. */
26 int allocated_port; /* Dynamically allocated listen port */
27 int handle; /* Handle for dynamic listen ports */
28} Forward;
29/* Data structure for representing option data. */ 19/* Data structure for representing option data. */
30 20
31#define MAX_SEND_ENV 256 21#define MAX_SEND_ENV 256
32#define SSH_MAX_HOSTS_FILES 32 22#define SSH_MAX_HOSTS_FILES 32
33#define MAX_CANON_DOMAINS 32 23#define MAX_CANON_DOMAINS 32
24#define PATH_MAX_SUN (sizeof((struct sockaddr_un *)0)->sun_path)
34 25
35struct allowed_cname { 26struct allowed_cname {
36 char *source_list; 27 char *source_list;
@@ -44,7 +35,7 @@ typedef struct {
44 int forward_x11_trusted; /* Trust Forward X11 display. */ 35 int forward_x11_trusted; /* Trust Forward X11 display. */
45 int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */ 36 int exit_on_forward_failure; /* Exit if bind(2) fails for -L/-R */
46 char *xauth_location; /* Location for xauth program */ 37 char *xauth_location; /* Location for xauth program */
47 int gateway_ports; /* Allow remote connects to forwarded ports. */ 38 struct ForwardOptions fwd_opts; /* forwarding options */
48 int use_privileged_port; /* Don't use privileged port if false. */ 39 int use_privileged_port; /* Don't use privileged port if false. */
49 int rhosts_rsa_authentication; /* Try rhosts with RSA 40 int rhosts_rsa_authentication; /* Try rhosts with RSA
50 * authentication. */ 41 * authentication. */
@@ -111,11 +102,11 @@ typedef struct {
111 102
112 /* Local TCP/IP forward requests. */ 103 /* Local TCP/IP forward requests. */
113 int num_local_forwards; 104 int num_local_forwards;
114 Forward *local_forwards; 105 struct Forward *local_forwards;
115 106
116 /* Remote TCP/IP forward requests. */ 107 /* Remote TCP/IP forward requests. */
117 int num_remote_forwards; 108 int num_remote_forwards;
118 Forward *remote_forwards; 109 struct Forward *remote_forwards;
119 int clear_forwardings; 110 int clear_forwardings;
120 111
121 int enable_ssh_keysign; 112 int enable_ssh_keysign;
@@ -186,12 +177,12 @@ int process_config_line(Options *, struct passwd *, const char *, char *,
186 const char *, int, int *, int); 177 const char *, int, int *, int);
187int read_config_file(const char *, struct passwd *, const char *, 178int read_config_file(const char *, struct passwd *, const char *,
188 Options *, int); 179 Options *, int);
189int parse_forward(Forward *, const char *, int, int); 180int parse_forward(struct Forward *, const char *, int, int);
190int default_ssh_port(void); 181int default_ssh_port(void);
191int option_clear_or_none(const char *); 182int option_clear_or_none(const char *);
192 183
193void add_local_forward(Options *, const Forward *); 184void add_local_forward(Options *, const struct Forward *);
194void add_remote_forward(Options *, const Forward *); 185void add_remote_forward(Options *, const struct Forward *);
195void add_identity_file(Options *, const char *, const char *, int); 186void add_identity_file(Options *, const char *, const char *, int);
196 187
197#endif /* READCONF_H */ 188#endif /* READCONF_H */
diff --git a/regress/Makefile b/regress/Makefile
index 6e3b8d634..3feb7a997 100644
--- a/regress/Makefile
+++ b/regress/Makefile
@@ -1,6 +1,6 @@
1# $OpenBSD: Makefile,v 1.68 2014/01/25 04:35:32 dtucker Exp $ 1# $OpenBSD: Makefile,v 1.70 2014/06/24 01:14:17 djm Exp $
2 2
3REGRESS_TARGETS= t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec 3REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec
4tests: $(REGRESS_TARGETS) 4tests: $(REGRESS_TARGETS)
5 5
6# Interop tests are not run by default 6# Interop tests are not run by default
@@ -180,3 +180,11 @@ t-exec-interop: ${INTEROP_TESTS:=.sh}
180 180
181# Not run by default 181# Not run by default
182interop: ${INTEROP_TARGETS} 182interop: ${INTEROP_TARGETS}
183
184# Unit tests, built by top-level Makefile
185unit:
186 set -e ; if test -z "${SKIP_UNIT}" ; then \
187 ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
188 ${.OBJDIR}/unittests/sshkey/test_sshkey \
189 -d ${.CURDIR}//unittests/sshkey/testdata ; \
190 fi
diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh
index 94cc64acf..41cb7af69 100644
--- a/regress/connect-privsep.sh
+++ b/regress/connect-privsep.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: connect-privsep.sh,v 1.4 2012/07/02 14:37:06 dtucker Exp $ 1# $OpenBSD: connect-privsep.sh,v 1.5 2014/05/04 10:40:59 logan Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="proxy connect with privsep" 4tid="proxy connect with privsep"
@@ -26,7 +26,7 @@ done
26 26
27# Because sandbox is sensitive to changes in libc, especially malloc, retest 27# Because sandbox is sensitive to changes in libc, especially malloc, retest
28# with every malloc.conf option (and none). 28# with every malloc.conf option (and none).
29for m in '' A F G H J P R S X Z '<' '>'; do 29for m in '' A F G H J P R S X '<' '>'; do
30 for p in 1 2; do 30 for p in 1 2; do
31 env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true 31 env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
32 if [ $? -ne 0 ]; then 32 if [ $? -ne 0 ]; then
diff --git a/regress/dhgex.sh b/regress/dhgex.sh
index 4c1a3d83c..57fca4a32 100644
--- a/regress/dhgex.sh
+++ b/regress/dhgex.sh
@@ -1,10 +1,11 @@
1# $OpenBSD: dhgex.sh,v 1.1 2014/01/25 04:35:32 dtucker Exp $ 1# $OpenBSD: dhgex.sh,v 1.2 2014/04/21 22:15:37 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="dhgex" 4tid="dhgex"
5 5
6LOG=${TEST_SSH_LOGFILE} 6LOG=${TEST_SSH_LOGFILE}
7rm -f ${LOG} 7rm -f ${LOG}
8cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
8 9
9kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange` 10kexs=`${SSH} -Q kex | grep diffie-hellman-group-exchange`
10 11
@@ -14,6 +15,9 @@ ssh_test_dhgex()
14 cipher="$1"; shift 15 cipher="$1"; shift
15 kex="$1"; shift 16 kex="$1"; shift
16 17
18 cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
19 echo "KexAlgorithms=$kex" >> $OBJ/sshd_proxy
20 echo "Ciphers=$cipher" >> $OBJ/sshd_proxy
17 rm -f ${LOG} 21 rm -f ${LOG}
18 opts="-oKexAlgorithms=$kex -oCiphers=$cipher" 22 opts="-oKexAlgorithms=$kex -oCiphers=$cipher"
19 groupsz="1024<$bits<8192" 23 groupsz="1024<$bits<8192"
diff --git a/regress/forwarding.sh b/regress/forwarding.sh
index 94873f22c..f799d4951 100644
--- a/regress/forwarding.sh
+++ b/regress/forwarding.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: forwarding.sh,v 1.11 2013/06/10 21:56:43 dtucker Exp $ 1# $OpenBSD: forwarding.sh,v 1.12 2014/07/15 15:54:15 millert Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="local and remote forwarding" 4tid="local and remote forwarding"
@@ -28,7 +28,7 @@ for p in 1 2; do
28 trace "transfer over forwarded channels and check result" 28 trace "transfer over forwarded channels and check result"
29 ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \ 29 ${SSH} -$q -F $OBJ/ssh_config -p$last -o 'ConnectionAttempts=4' \
30 somehost cat ${DATA} > ${COPY} 30 somehost cat ${DATA} > ${COPY}
31 test -f ${COPY} || fail "failed copy of ${DATA}" 31 test -s ${COPY} || fail "failed copy of ${DATA}"
32 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" 32 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
33 33
34 sleep 10 34 sleep 10
@@ -114,8 +114,24 @@ for p in 1 2; do
114 trace "config file: transfer over forwarded channels and check result" 114 trace "config file: transfer over forwarded channels and check result"
115 ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ 115 ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \
116 somehost cat ${DATA} > ${COPY} 116 somehost cat ${DATA} > ${COPY}
117 test -f ${COPY} || fail "failed copy of ${DATA}" 117 test -s ${COPY} || fail "failed copy of ${DATA}"
118 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" 118 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
119 119
120 wait 120 wait
121done 121done
122
123for p in 2; do
124 trace "transfer over chained unix domain socket forwards and check result"
125 rm -f $OBJ/unix-[123].fwd
126 ${SSH} -f -F $OBJ/ssh_config -R${base}01:[$OBJ/unix-1.fwd] somehost sleep 10
127 ${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-1.fwd]:[$OBJ/unix-2.fwd] somehost sleep 10
128 ${SSH} -f -F $OBJ/ssh_config -R[$OBJ/unix-2.fwd]:[$OBJ/unix-3.fwd] somehost sleep 10
129 ${SSH} -f -F $OBJ/ssh_config -L[$OBJ/unix-3.fwd]:127.0.0.1:$PORT somehost sleep 10
130 ${SSH} -F $OBJ/ssh_config -p${base}01 -o 'ConnectionAttempts=4' \
131 somehost cat ${DATA} > ${COPY}
132 test -s ${COPY} || fail "failed copy ${DATA}"
133 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
134
135 #wait
136 sleep 10
137done
diff --git a/regress/integrity.sh b/regress/integrity.sh
index 852d82690..d3a489ff7 100644
--- a/regress/integrity.sh
+++ b/regress/integrity.sh
@@ -1,7 +1,8 @@
1# $OpenBSD: integrity.sh,v 1.12 2013/11/21 03:18:51 djm Exp $ 1# $OpenBSD: integrity.sh,v 1.14 2014/05/21 07:04:21 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="integrity" 4tid="integrity"
5cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
5 6
6# start at byte 2900 (i.e. after kex) and corrupt at different offsets 7# start at byte 2900 (i.e. after kex) and corrupt at different offsets
7# XXX the test hangs if we modify the low bytes of the packet length 8# XXX the test hangs if we modify the low bytes of the packet length
@@ -34,11 +35,15 @@ for m in $macs; do
34 # avoid modifying the high bytes of the length 35 # avoid modifying the high bytes of the length
35 continue 36 continue
36 fi 37 fi
38 cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
37 # modify output from sshd at offset $off 39 # modify output from sshd at offset $off
38 pxy="proxycommand=$cmd | $OBJ/modpipe -wm xor:$off:1" 40 pxy="proxycommand=$cmd | $OBJ/modpipe -wm xor:$off:1"
39 if ssh -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then 41 if ssh -Q cipher-auth | grep "^${m}\$" >/dev/null 2>&1 ; then
42 echo "Ciphers=$m" >> $OBJ/sshd_proxy
40 macopt="-c $m" 43 macopt="-c $m"
41 else 44 else
45 echo "Ciphers=aes128-ctr" >> $OBJ/sshd_proxy
46 echo "MACs=$m" >> $OBJ/sshd_proxy
42 macopt="-m $m -c aes128-ctr" 47 macopt="-m $m -c aes128-ctr"
43 fi 48 fi
44 verbose "test $tid: $m @$off" 49 verbose "test $tid: $m @$off"
@@ -49,14 +54,14 @@ for m in $macs; do
49 fail "ssh -m $m succeeds with bit-flip at $off" 54 fail "ssh -m $m succeeds with bit-flip at $off"
50 fi 55 fi
51 ecnt=`expr $ecnt + 1` 56 ecnt=`expr $ecnt + 1`
52 output=$(tail -2 $TEST_SSH_LOGFILE | egrep -v "^debug" | \ 57 out=$(tail -2 $TEST_SSH_LOGFILE | egrep -v "^debug" | \
53 tr -s '\r\n' '.') 58 tr -s '\r\n' '.')
54 case "$output" in 59 case "$out" in
55 Bad?packet*) elen=`expr $elen + 1`; skip=3;; 60 Bad?packet*) elen=`expr $elen + 1`; skip=3;;
56 Corrupted?MAC* | Decryption?integrity?check?failed*) 61 Corrupted?MAC* | Decryption?integrity?check?failed*)
57 emac=`expr $emac + 1`; skip=0;; 62 emac=`expr $emac + 1`; skip=0;;
58 padding*) epad=`expr $epad + 1`; skip=0;; 63 padding*) epad=`expr $epad + 1`; skip=0;;
59 *) fail "unexpected error mac $m at $off";; 64 *) fail "unexpected error mac $m at $off: $out";;
60 esac 65 esac
61 done 66 done
62 verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen" 67 verbose "test $tid: $ecnt errors: mac $emac padding $epad length $elen"
diff --git a/regress/kextype.sh b/regress/kextype.sh
index 8c2ac09d6..6f952f4e4 100644
--- a/regress/kextype.sh
+++ b/regress/kextype.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: kextype.sh,v 1.4 2013/11/07 04:26:56 dtucker Exp $ 1# $OpenBSD: kextype.sh,v 1.5 2014/04/21 22:15:37 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="login with different key exchange algorithms" 4tid="login with different key exchange algorithms"
@@ -7,6 +7,11 @@ TIME=/usr/bin/time
7cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak 7cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
8cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak 8cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
9 9
10# Make server accept all key exchanges.
11ALLKEX=`ssh -Q kex`
12KEXOPT=`echo $ALLKEX | tr ' ' ,`
13echo "KexAlgorithms=$KEXOPT" >> $OBJ/sshd_proxy
14
10tries="1 2 3 4" 15tries="1 2 3 4"
11for k in `${SSH} -Q kex`; do 16for k in `${SSH} -Q kex`; do
12 verbose "kex $k" 17 verbose "kex $k"
diff --git a/regress/krl.sh b/regress/krl.sh
index 09246371c..287384b4a 100644
--- a/regress/krl.sh
+++ b/regress/krl.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: krl.sh,v 1.2 2013/11/21 03:15:46 djm Exp $ 1# $OpenBSD: krl.sh,v 1.3 2014/06/24 01:04:43 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="key revocation lists" 4tid="key revocation lists"
@@ -37,6 +37,9 @@ serial: 700-797
37serial: 798 37serial: 798
38serial: 799 38serial: 799
39serial: 599-701 39serial: 599-701
40# Some multiple consecutive serial number ranges
41serial: 10000-20000
42serial: 30000-40000
40EOF 43EOF
41 44
42# A specification that revokes some certificated by key ID. 45# A specification that revokes some certificated by key ID.
diff --git a/regress/login-timeout.sh b/regress/login-timeout.sh
index d9b48f391..eb76f554b 100644
--- a/regress/login-timeout.sh
+++ b/regress/login-timeout.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: login-timeout.sh,v 1.6 2014/02/27 20:04:16 djm Exp $ 1# $OpenBSD: login-timeout.sh,v 1.7 2014/03/13 20:44:49 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="connect after login grace timeout" 4tid="connect after login grace timeout"
@@ -22,6 +22,7 @@ $SUDO kill `$SUDO cat $PIDFILE`
22trace "test login grace without privsep" 22trace "test login grace without privsep"
23echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config 23echo "UsePrivilegeSeparation no" >> $OBJ/sshd_config
24start_sshd 24start_sshd
25sleep 1
25 26
26(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 & 27(echo SSH-2.0-fake; sleep 60) | telnet 127.0.0.1 ${PORT} >/dev/null 2>&1 &
27sleep 15 28sleep 15
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
index 3e697e691..8ee140be6 100644
--- a/regress/multiplex.sh
+++ b/regress/multiplex.sh
@@ -1,10 +1,26 @@
1# $OpenBSD: multiplex.sh,v 1.21 2013/05/17 04:29:14 dtucker Exp $ 1# $OpenBSD: multiplex.sh,v 1.25 2014/07/22 01:32:12 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4CTL=/tmp/openssh.regress.ctl-sock.$$ 4CTL=/tmp/openssh.regress.ctl-sock.$$
5 5
6tid="connection multiplexing" 6tid="connection multiplexing"
7 7
8if have_prog nc ; then
9 if nc -h 2>&1 | grep -- -N >/dev/null; then
10 NC="nc -N";
11 elif nc -h 2>&1 | grep -- "-U.*Use UNIX" >/dev/null ; then
12 NC="nc"
13 else
14 echo "nc is incompatible"
15 fi
16fi
17
18if test -z "$NC" ; then
19 echo "skipped (no compatible nc found)"
20 exit 0
21fi
22
23trace "will use ProxyCommand $proxycmd"
8if config_defined DISABLE_FD_PASSING ; then 24if config_defined DISABLE_FD_PASSING ; then
9 echo "skipped (not supported on this platform)" 25 echo "skipped (not supported on this platform)"
10 exit 0 26 exit 0
@@ -29,7 +45,8 @@ start_mux_master()
29 trace "start master, fork to background" 45 trace "start master, fork to background"
30 ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \ 46 ${SSH} -Nn2 -MS$CTL -F $OBJ/ssh_config -oSendEnv="_XXX_TEST" somehost \
31 -E $TEST_REGRESS_LOGFILE 2>&1 & 47 -E $TEST_REGRESS_LOGFILE 2>&1 &
32 MASTER_PID=$! 48 # NB. $SSH_PID will be killed by test-exec.sh:cleanup on fatal errors.
49 SSH_PID=$!
33 wait_for_mux_master_ready 50 wait_for_mux_master_ready
34} 51}
35 52
@@ -71,6 +88,25 @@ test -f ${COPY} || fail "scp: failed copy ${DATA}"
71cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}" 88cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
72 89
73rm -f ${COPY} 90rm -f ${COPY}
91verbose "test $tid: forward"
92trace "forward over TCP/IP and check result"
93$NC -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} &
94netcat_pid=$!
95${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1
96$NC -d 127.0.0.1 $((${PORT} + 2)) > ${COPY} < /dev/null
97cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
98kill $netcat_pid 2>/dev/null
99rm -f ${COPY} $OBJ/unix-[123].fwd
100
101trace "forward over UNIX and check result"
102$NC -Ul $OBJ/unix-1.fwd < ${DATA} &
103netcat_pid=$!
104${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
105${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
106$NC -d -U $OBJ/unix-3.fwd > ${COPY} </dev/null
107cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
108kill $netcat_pid 2>/dev/null
109rm -f ${COPY} $OBJ/unix-[123].fwd
74 110
75for s in 0 1 4 5 44; do 111for s in 0 1 4 5 44; do
76 trace "exit status $s over multiplexed connection" 112 trace "exit status $s over multiplexed connection"
@@ -95,7 +131,7 @@ verbose "test $tid: cmd check"
95${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ 131${SSH} -F $OBJ/ssh_config -S $CTL -Ocheck otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
96 || fail "check command failed" 132 || fail "check command failed"
97 133
98verbose "test $tid: cmd forward local" 134verbose "test $tid: cmd forward local (TCP)"
99${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \ 135${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $P:localhost:$PORT otherhost \
100 || fail "request local forward failed" 136 || fail "request local forward failed"
101${SSH} -F $OBJ/ssh_config -p$P otherhost true \ 137${SSH} -F $OBJ/ssh_config -p$P otherhost true \
@@ -105,7 +141,7 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $P:localhost:$PORT otherhost \
105${SSH} -F $OBJ/ssh_config -p$P otherhost true \ 141${SSH} -F $OBJ/ssh_config -p$P otherhost true \
106 && fail "local forward port still listening" 142 && fail "local forward port still listening"
107 143
108verbose "test $tid: cmd forward remote" 144verbose "test $tid: cmd forward remote (TCP)"
109${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \ 145${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $P:localhost:$PORT otherhost \
110 || fail "request remote forward failed" 146 || fail "request remote forward failed"
111${SSH} -F $OBJ/ssh_config -p$P otherhost true \ 147${SSH} -F $OBJ/ssh_config -p$P otherhost true \
@@ -115,13 +151,35 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $P:localhost:$PORT otherhost \
115${SSH} -F $OBJ/ssh_config -p$P otherhost true \ 151${SSH} -F $OBJ/ssh_config -p$P otherhost true \
116 && fail "remote forward port still listening" 152 && fail "remote forward port still listening"
117 153
154verbose "test $tid: cmd forward local (UNIX)"
155${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
156 || fail "request local forward failed"
157echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \
158 || fail "connect to local forward path failed"
159${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -L $OBJ/unix-1.fwd:localhost:$PORT otherhost \
160 || fail "cancel local forward failed"
161N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
162test ${N} -eq 0 || fail "local forward path still listening"
163rm -f $OBJ/unix-1.fwd
164
165verbose "test $tid: cmd forward remote (UNIX)"
166${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
167 || fail "request remote forward failed"
168echo "" | $NC -U $OBJ/unix-1.fwd | grep "Protocol mismatch" >/dev/null 2>&1 \
169 || fail "connect to remote forwarded path failed"
170${SSH} -F $OBJ/ssh_config -S $CTL -Ocancel -R $OBJ/unix-1.fwd:localhost:$PORT otherhost \
171 || fail "cancel remote forward failed"
172N=$(echo "xyzzy" | $NC -U $OBJ/unix-1.fwd 2>&1 | grep "xyzzy" | wc -l)
173test ${N} -eq 0 || fail "remote forward path still listening"
174rm -f $OBJ/unix-1.fwd
175
118verbose "test $tid: cmd exit" 176verbose "test $tid: cmd exit"
119${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \ 177${SSH} -F $OBJ/ssh_config -S $CTL -Oexit otherhost >>$TEST_REGRESS_LOGFILE 2>&1 \
120 || fail "send exit command failed" 178 || fail "send exit command failed"
121 179
122# Wait for master to exit 180# Wait for master to exit
123wait $MASTER_PID 181wait $SSH_PID
124kill -0 $MASTER_PID >/dev/null 2>&1 && fail "exit command failed" 182kill -0 $SSH_PID >/dev/null 2>&1 && fail "exit command failed"
125 183
126# Restart master and test -O stop command with master using -N 184# Restart master and test -O stop command with master using -N
127verbose "test $tid: cmd stop" 185verbose "test $tid: cmd stop"
@@ -138,6 +196,8 @@ ${SSH} -F $OBJ/ssh_config -S $CTL -Ostop otherhost >>$TEST_REGRESS_LOGFILE 2>&1
138# wait until both long-running command and master have exited. 196# wait until both long-running command and master have exited.
139wait $SLEEP_PID 197wait $SLEEP_PID
140[ $! != 0 ] || fail "waiting for concurrent command" 198[ $! != 0 ] || fail "waiting for concurrent command"
141wait $MASTER_PID 199wait $SSH_PID
142[ $! != 0 ] || fail "waiting for master stop" 200[ $! != 0 ] || fail "waiting for master stop"
143kill -0 $MASTER_PID >/dev/null 2>&1 && fail "stop command failed" 201kill -0 $SSH_PID >/dev/null 2>&1 && fatal "stop command failed"
202SSH_PID="" # Already gone, so don't kill in cleanup
203
diff --git a/regress/proxy-connect.sh b/regress/proxy-connect.sh
index 76e602dd6..023ba7367 100644
--- a/regress/proxy-connect.sh
+++ b/regress/proxy-connect.sh
@@ -1,26 +1,31 @@
1# $OpenBSD: proxy-connect.sh,v 1.6 2013/03/07 00:20:34 djm Exp $ 1# $OpenBSD: proxy-connect.sh,v 1.7 2014/05/03 18:46:14 dtucker Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="proxy connect" 4tid="proxy connect"
5 5
6verbose "plain username" 6mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
7for p in 1 2; do 7
8 ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true 8for ps in no yes; do
9 if [ $? -ne 0 ]; then 9 cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
10 fail "ssh proxyconnect protocol $p failed" 10 echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
11 fi 11
12 SSH_CONNECTION=`${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 'echo $SSH_CONNECTION'` 12 for p in 1 2; do
13 for c in no yes; do
14 verbose "plain username protocol $p privsep=$ps comp=$c"
15 opts="-$p -oCompression=$c -F $OBJ/ssh_proxy"
16 SSH_CONNECTION=`${SSH} $opts 999.999.999.999 'echo $SSH_CONNECTION'`
13 if [ $? -ne 0 ]; then 17 if [ $? -ne 0 ]; then
14 fail "ssh proxyconnect protocol $p failed" 18 fail "ssh proxyconnect protocol $p privsep=$ps comp=$c failed"
15 fi 19 fi
16 if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then 20 if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
17 fail "bad SSH_CONNECTION" 21 fail "bad SSH_CONNECTION protocol $p privsep=$ps comp=$c"
18 fi 22 fi
23 done
24 done
19done 25done
20 26
21verbose "username with style"
22for p in 1 2; do 27for p in 1 2; do
28 verbose "username with style protocol $p"
23 ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ 29 ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \
24 fail "ssh proxyconnect protocol $p failed" 30 fail "ssh proxyconnect protocol $p failed"
25done 31done
26
diff --git a/regress/rekey.sh b/regress/rekey.sh
index cf9401ea0..fd452b034 100644
--- a/regress/rekey.sh
+++ b/regress/rekey.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: rekey.sh,v 1.14 2013/11/21 03:18:51 djm Exp $ 1# $OpenBSD: rekey.sh,v 1.15 2014/04/21 22:15:37 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="rekey" 4tid="rekey"
@@ -6,14 +6,22 @@ tid="rekey"
6LOG=${TEST_SSH_LOGFILE} 6LOG=${TEST_SSH_LOGFILE}
7 7
8rm -f ${LOG} 8rm -f ${LOG}
9cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
9 10
10# Test rekeying based on data volume only. 11# Test rekeying based on data volume only.
11# Arguments will be passed to ssh. 12# Arguments will be passed to ssh.
12ssh_data_rekeying() 13ssh_data_rekeying()
13{ 14{
15 _kexopt=$1 ; shift
16 _opts="$@"
17 if ! test -z "$_kexopts" ; then
18 cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
19 echo "$_kexopt" >> $OBJ/sshd_proxy
20 _opts="$_opts -o$_kexopt"
21 fi
14 rm -f ${COPY} ${LOG} 22 rm -f ${COPY} ${LOG}
15 ${SSH} <${DATA} -oCompression=no $@ -v -F $OBJ/ssh_proxy somehost \ 23 _opts="$_opts -oCompression=no"
16 "cat > ${COPY}" 24 ${SSH} <${DATA} $_opts -v -F $OBJ/ssh_proxy somehost "cat > ${COPY}"
17 if [ $? -ne 0 ]; then 25 if [ $? -ne 0 ]; then
18 fail "ssh failed ($@)" 26 fail "ssh failed ($@)"
19 fi 27 fi
@@ -41,7 +49,7 @@ done
41 49
42for opt in $opts; do 50for opt in $opts; do
43 verbose "client rekey $opt" 51 verbose "client rekey $opt"
44 ssh_data_rekeying -oRekeyLimit=256k -o$opt 52 ssh_data_rekeying "$opt" -oRekeyLimit=256k
45done 53done
46 54
47# AEAD ciphers are magical so test with all KexAlgorithms 55# AEAD ciphers are magical so test with all KexAlgorithms
@@ -49,14 +57,14 @@ if ${SSH} -Q cipher-auth | grep '^.*$' >/dev/null 2>&1 ; then
49 for c in `${SSH} -Q cipher-auth`; do 57 for c in `${SSH} -Q cipher-auth`; do
50 for kex in `${SSH} -Q kex`; do 58 for kex in `${SSH} -Q kex`; do
51 verbose "client rekey $c $kex" 59 verbose "client rekey $c $kex"
52 ssh_data_rekeying -oRekeyLimit=256k -oCiphers=$c -oKexAlgorithms=$kex 60 ssh_data_rekeying "KexAlgorithms=$kex" -oRekeyLimit=256k -oCiphers=$c
53 done 61 done
54 done 62 done
55fi 63fi
56 64
57for s in 16 1k 128k 256k; do 65for s in 16 1k 128k 256k; do
58 verbose "client rekeylimit ${s}" 66 verbose "client rekeylimit ${s}"
59 ssh_data_rekeying -oCompression=no -oRekeyLimit=$s 67 ssh_data_rekeying "" -oCompression=no -oRekeyLimit=$s
60done 68done
61 69
62for s in 5 10; do 70for s in 5 10; do
diff --git a/regress/test-exec.sh b/regress/test-exec.sh
index aac8aa5c2..a1bab832f 100644
--- a/regress/test-exec.sh
+++ b/regress/test-exec.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: test-exec.sh,v 1.47 2013/11/09 05:41:34 dtucker Exp $ 1# $OpenBSD: test-exec.sh,v 1.48 2014/07/06 07:42:03 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4#SUDO=sudo 4#SUDO=sudo
@@ -240,13 +240,20 @@ md5 () {
240# helper 240# helper
241cleanup () 241cleanup ()
242{ 242{
243 if [ "x$SSH_PID" != "x" ]; then
244 if [ $SSH_PID -lt 2 ]; then
245 echo bad pid for ssh: $SSH_PID
246 else
247 kill $SSH_PID
248 fi
249 fi
243 if [ -f $PIDFILE ]; then 250 if [ -f $PIDFILE ]; then
244 pid=`$SUDO cat $PIDFILE` 251 pid=`$SUDO cat $PIDFILE`
245 if [ "X$pid" = "X" ]; then 252 if [ "X$pid" = "X" ]; then
246 echo no sshd running 253 echo no sshd running
247 else 254 else
248 if [ $pid -lt 2 ]; then 255 if [ $pid -lt 2 ]; then
249 echo bad pid for ssh: $pid 256 echo bad pid for sshd: $pid
250 else 257 else
251 $SUDO kill $pid 258 $SUDO kill $pid
252 trace "wait for sshd to exit" 259 trace "wait for sshd to exit"
diff --git a/regress/try-ciphers.sh b/regress/try-ciphers.sh
index ac34cedbf..2881ce16c 100644
--- a/regress/try-ciphers.sh
+++ b/regress/try-ciphers.sh
@@ -1,13 +1,18 @@
1# $OpenBSD: try-ciphers.sh,v 1.22 2013/11/21 03:18:51 djm Exp $ 1# $OpenBSD: try-ciphers.sh,v 1.23 2014/04/21 22:15:37 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="try ciphers" 4tid="try ciphers"
5 5
6cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
7
6for c in `${SSH} -Q cipher`; do 8for c in `${SSH} -Q cipher`; do
7 n=0 9 n=0
8 for m in `${SSH} -Q mac`; do 10 for m in `${SSH} -Q mac`; do
9 trace "proto 2 cipher $c mac $m" 11 trace "proto 2 cipher $c mac $m"
10 verbose "test $tid: proto 2 cipher $c mac $m" 12 verbose "test $tid: proto 2 cipher $c mac $m"
13 cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
14 echo "Ciphers=$c" >> $OBJ/sshd_proxy
15 echo "MACs=$m" >> $OBJ/sshd_proxy
11 ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true 16 ${SSH} -F $OBJ/ssh_proxy -2 -m $m -c $c somehost true
12 if [ $? -ne 0 ]; then 17 if [ $? -ne 0 ]; then
13 fail "ssh -2 failed with mac $m cipher $c" 18 fail "ssh -2 failed with mac $m cipher $c"
diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile
new file mode 100644
index 000000000..bdb4574e2
--- /dev/null
+++ b/regress/unittests/Makefile
@@ -0,0 +1,5 @@
1# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $
2
3SUBDIR= test_helper sshbuf sshkey
4
5.include <bsd.subdir.mk>
diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc
new file mode 100644
index 000000000..4c3363749
--- /dev/null
+++ b/regress/unittests/Makefile.inc
@@ -0,0 +1,59 @@
1# $OpenBSD: Makefile.inc,v 1.1 2014/04/30 05:32:00 djm Exp $
2
3.include <bsd.own.mk>
4.include <bsd.obj.mk>
5
6# enable warnings
7WARNINGS=Yes
8
9DEBUG=-g
10CFLAGS+= -fstack-protector-all
11CDIAGFLAGS= -Wall
12CDIAGFLAGS+= -Wextra
13CDIAGFLAGS+= -Werror
14CDIAGFLAGS+= -Wchar-subscripts
15CDIAGFLAGS+= -Wcomment
16CDIAGFLAGS+= -Wformat
17CDIAGFLAGS+= -Wformat-security
18CDIAGFLAGS+= -Wimplicit
19CDIAGFLAGS+= -Winline
20CDIAGFLAGS+= -Wmissing-declarations
21CDIAGFLAGS+= -Wmissing-prototypes
22CDIAGFLAGS+= -Wparentheses
23CDIAGFLAGS+= -Wpointer-arith
24CDIAGFLAGS+= -Wpointer-sign
25CDIAGFLAGS+= -Wreturn-type
26CDIAGFLAGS+= -Wshadow
27CDIAGFLAGS+= -Wsign-compare
28CDIAGFLAGS+= -Wstrict-aliasing
29CDIAGFLAGS+= -Wstrict-prototypes
30CDIAGFLAGS+= -Wswitch
31CDIAGFLAGS+= -Wtrigraphs
32CDIAGFLAGS+= -Wuninitialized
33CDIAGFLAGS+= -Wunused
34.if ${COMPILER_VERSION} == "gcc4"
35CDIAGFLAGS+= -Wold-style-definition
36.endif
37
38SSHREL=../../../../../usr.bin/ssh
39
40CFLAGS+=-I${.CURDIR}/../test_helper -I${.CURDIR}/${SSHREL}
41
42.if exists(${.CURDIR}/../test_helper/${__objdir})
43LDADD+=-L${.CURDIR}/../test_helper/${__objdir} -ltest_helper
44DPADD+=${.CURDIR}/../test_helper/${__objdir}/libtest_helper.a
45.else
46LDADD+=-L${.CURDIR}/../test_helper -ltest_helper
47DPADD+=${.CURDIR}/../test_helper/libtest_helper.a
48.endif
49
50.if exists(${.CURDIR}/${SSHREL}/lib/${__objdir})
51LDADD+=-L${.CURDIR}/${SSHREL}/lib/${__objdir} -lssh
52DPADD+=${.CURDIR}/${SSHREL}/lib/${__objdir}/libssh.a
53.else
54LDADD+=-L${.CURDIR}/${SSHREL}/lib -lssh
55DPADD+=${.CURDIR}/${SSHREL}/lib/libssh.a
56.endif
57
58LDADD+= -lcrypto
59DPADD+= ${LIBCRYPTO}
diff --git a/regress/unittests/sshbuf/Makefile b/regress/unittests/sshbuf/Makefile
new file mode 100644
index 000000000..85f99ac38
--- /dev/null
+++ b/regress/unittests/sshbuf/Makefile
@@ -0,0 +1,14 @@
1# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $
2
3PROG=test_sshbuf
4SRCS=tests.c
5SRCS+=test_sshbuf.c
6SRCS+=test_sshbuf_getput_basic.c
7SRCS+=test_sshbuf_getput_crypto.c
8SRCS+=test_sshbuf_misc.c
9SRCS+=test_sshbuf_fuzz.c
10SRCS+=test_sshbuf_getput_fuzz.c
11SRCS+=test_sshbuf_fixed.c
12
13.include <bsd.regress.mk>
14
diff --git a/regress/unittests/sshbuf/test_sshbuf.c b/regress/unittests/sshbuf/test_sshbuf.c
new file mode 100644
index 000000000..ee77d6934
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf.c
@@ -0,0 +1,240 @@
1/* $OpenBSD: test_sshbuf.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#define SSHBUF_INTERNAL 1 /* access internals for testing */
9#include "includes.h"
10
11#include <sys/types.h>
12#include <sys/param.h>
13#include <stdio.h>
14#ifdef HAVE_STDINT_H
15# include <stdint.h>
16#endif
17#include <stdlib.h>
18#include <string.h>
19
20#include "../test_helper/test_helper.h"
21
22#include "ssherr.h"
23#include "sshbuf.h"
24
25void sshbuf_tests(void);
26
27void
28sshbuf_tests(void)
29{
30 struct sshbuf *p1;
31 const u_char *cdp;
32 u_char *dp;
33 size_t sz;
34 int r;
35
36 TEST_START("allocate sshbuf");
37 p1 = sshbuf_new();
38 ASSERT_PTR_NE(p1, NULL);
39 TEST_DONE();
40
41 TEST_START("max size on fresh buffer");
42 ASSERT_SIZE_T_GT(sshbuf_max_size(p1), 0);
43 TEST_DONE();
44
45 TEST_START("available on fresh buffer");
46 ASSERT_SIZE_T_GT(sshbuf_avail(p1), 0);
47 TEST_DONE();
48
49 TEST_START("len = 0 on empty buffer");
50 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
51 TEST_DONE();
52
53 TEST_START("set valid max size");
54 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 65536), 0);
55 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 65536);
56 TEST_DONE();
57
58 TEST_START("available on limited buffer");
59 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 65536);
60 TEST_DONE();
61
62 TEST_START("free");
63 sshbuf_free(p1);
64 TEST_DONE();
65
66 TEST_START("consume on empty buffer");
67 p1 = sshbuf_new();
68 ASSERT_PTR_NE(p1, NULL);
69 ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0);
70 ASSERT_INT_EQ(sshbuf_consume(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE);
71 sshbuf_free(p1);
72 TEST_DONE();
73
74 TEST_START("consume_end on empty buffer");
75 p1 = sshbuf_new();
76 ASSERT_PTR_NE(p1, NULL);
77 ASSERT_INT_EQ(sshbuf_consume_end(p1, 0), 0);
78 ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), SSH_ERR_MESSAGE_INCOMPLETE);
79 sshbuf_free(p1);
80 TEST_DONE();
81
82 TEST_START("reserve space");
83 p1 = sshbuf_new();
84 ASSERT_PTR_NE(p1, NULL);
85 r = sshbuf_reserve(p1, 1, &dp);
86 ASSERT_INT_EQ(r, 0);
87 ASSERT_PTR_NE(dp, NULL);
88 *dp = 0x11;
89 r = sshbuf_reserve(p1, 3, &dp);
90 ASSERT_INT_EQ(r, 0);
91 ASSERT_PTR_NE(dp, NULL);
92 *dp++ = 0x22;
93 *dp++ = 0x33;
94 *dp++ = 0x44;
95 TEST_DONE();
96
97 TEST_START("sshbuf_len on filled buffer");
98 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
99 TEST_DONE();
100
101 TEST_START("sshbuf_ptr on filled buffer");
102 cdp = sshbuf_ptr(p1);
103 ASSERT_PTR_NE(cdp, NULL);
104 ASSERT_U8_EQ(cdp[0], 0x11);
105 ASSERT_U8_EQ(cdp[1], 0x22);
106 ASSERT_U8_EQ(cdp[2], 0x33);
107 ASSERT_U8_EQ(cdp[3], 0x44);
108 TEST_DONE();
109
110 TEST_START("consume on filled buffer");
111 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
112 ASSERT_INT_EQ(sshbuf_consume(p1, 0), 0);
113 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
114 r = sshbuf_consume(p1, 64);
115 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
116 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
117 ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0);
118 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3);
119 cdp = sshbuf_ptr(p1);
120 ASSERT_PTR_NE(p1, NULL);
121 ASSERT_U8_EQ(cdp[0], 0x22);
122 ASSERT_INT_EQ(sshbuf_consume(p1, 2), 0);
123 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
124 cdp = sshbuf_ptr(p1);
125 ASSERT_PTR_NE(p1, NULL);
126 ASSERT_U8_EQ(cdp[0], 0x44);
127 r = sshbuf_consume(p1, 2);
128 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
129 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
130 ASSERT_INT_EQ(sshbuf_consume(p1, 1), 0);
131 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
132 r = sshbuf_consume(p1, 1);
133 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
134 sshbuf_free(p1);
135 TEST_DONE();
136
137 TEST_START("consume_end on filled buffer");
138 p1 = sshbuf_new();
139 ASSERT_PTR_NE(p1, NULL);
140 r = sshbuf_reserve(p1, 4, &dp);
141 ASSERT_INT_EQ(r, 0);
142 ASSERT_PTR_NE(dp, NULL);
143 *dp++ = 0x11;
144 *dp++ = 0x22;
145 *dp++ = 0x33;
146 *dp++ = 0x44;
147 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
148 r = sshbuf_consume_end(p1, 5);
149 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
150 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
151 ASSERT_INT_EQ(sshbuf_consume_end(p1, 3), 0);
152 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
153 cdp = sshbuf_ptr(p1);
154 ASSERT_PTR_NE(cdp, NULL);
155 ASSERT_U8_EQ(*cdp, 0x11);
156 r = sshbuf_consume_end(p1, 2);
157 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
158 ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0);
159 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
160 sshbuf_free(p1);
161 TEST_DONE();
162
163 TEST_START("fill limited buffer");
164 p1 = sshbuf_new();
165 ASSERT_PTR_NE(p1, NULL);
166 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0);
167 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
168 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223);
169 r = sshbuf_reserve(p1, 1223, &dp);
170 ASSERT_INT_EQ(r, 0);
171 ASSERT_PTR_NE(dp, NULL);
172 memset(dp, 0xd7, 1223);
173 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223);
174 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0);
175 r = sshbuf_reserve(p1, 1, &dp);
176 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
177 ASSERT_PTR_EQ(dp, NULL);
178 TEST_DONE();
179
180 TEST_START("consume and force compaction");
181 ASSERT_INT_EQ(sshbuf_consume(p1, 223), 0);
182 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000);
183 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223);
184 r = sshbuf_reserve(p1, 224, &dp);
185 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
186 ASSERT_PTR_EQ(dp, NULL);
187 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1000);
188 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 223);
189 r = sshbuf_reserve(p1, 223, &dp);
190 ASSERT_INT_EQ(r, 0);
191 ASSERT_PTR_NE(dp, NULL);
192 memset(dp, 0x7d, 223);
193 cdp = sshbuf_ptr(p1);
194 ASSERT_PTR_NE(cdp, NULL);
195 ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
196 ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
197 TEST_DONE();
198
199 TEST_START("resize full buffer");
200 r = sshbuf_set_max_size(p1, 1000);
201 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
202 sz = roundup(1223 + SSHBUF_SIZE_INC * 3, SSHBUF_SIZE_INC);
203 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sz), 0);
204 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
205 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - 1223);
206 ASSERT_INT_EQ(sshbuf_len(p1), 1223);
207 TEST_DONE();
208
209 /* NB. uses sshbuf internals */
210 TEST_START("alloc chunking");
211 r = sshbuf_reserve(p1, 1, &dp);
212 ASSERT_INT_EQ(r, 0);
213 ASSERT_PTR_NE(dp, NULL);
214 *dp = 0xff;
215 cdp = sshbuf_ptr(p1);
216 ASSERT_PTR_NE(cdp, NULL);
217 ASSERT_MEM_FILLED_EQ(cdp, 0xd7, 1000);
218 ASSERT_MEM_FILLED_EQ(cdp + 1000, 0x7d, 223);
219 ASSERT_MEM_FILLED_EQ(cdp + 1223, 0xff, 1);
220 ASSERT_SIZE_T_EQ(sshbuf_alloc(p1) % SSHBUF_SIZE_INC, 0);
221 sshbuf_free(p1);
222 TEST_DONE();
223
224 TEST_START("reset buffer");
225 p1 = sshbuf_new();
226 ASSERT_PTR_NE(p1, NULL);
227 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1223), 0);
228 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
229 r = sshbuf_reserve(p1, 1223, &dp);
230 ASSERT_INT_EQ(r, 0);
231 ASSERT_PTR_NE(dp, NULL);
232 memset(dp, 0xd7, 1223);
233 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1223);
234 sshbuf_reset(p1);
235 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), 1223);
236 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
237 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 1223);
238 sshbuf_free(p1);
239 TEST_DONE();
240}
diff --git a/regress/unittests/sshbuf/test_sshbuf_fixed.c b/regress/unittests/sshbuf/test_sshbuf_fixed.c
new file mode 100644
index 000000000..df4925f7c
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_fixed.c
@@ -0,0 +1,126 @@
1/* $OpenBSD: test_sshbuf_fixed.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#define SSHBUF_INTERNAL 1 /* access internals for testing */
9#include "includes.h"
10
11#include <sys/types.h>
12#include <sys/param.h>
13#include <stdio.h>
14#ifdef HAVE_STDINT_H
15# include <stdint.h>
16#endif
17#include <stdlib.h>
18#include <string.h>
19
20#include "../test_helper/test_helper.h"
21
22#include "sshbuf.h"
23#include "ssherr.h"
24
25void sshbuf_fixed(void);
26
27const u_char test_buf[] = "\x01\x12\x34\x56\x78\x00\x00\x00\x05hello";
28
29void
30sshbuf_fixed(void)
31{
32 struct sshbuf *p1, *p2, *p3;
33 u_char c;
34 char *s;
35 u_int i;
36 size_t l;
37
38 TEST_START("sshbuf_from");
39 p1 = sshbuf_from(test_buf, sizeof(test_buf));
40 ASSERT_PTR_NE(p1, NULL);
41 ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL);
42 ASSERT_INT_EQ(sshbuf_check_reserve(p1, 1), SSH_ERR_BUFFER_READ_ONLY);
43 ASSERT_INT_EQ(sshbuf_reserve(p1, 1, NULL), SSH_ERR_BUFFER_READ_ONLY);
44 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 200), SSH_ERR_BUFFER_READ_ONLY);
45 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), SSH_ERR_BUFFER_READ_ONLY);
46 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), 0);
47 ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf);
48 sshbuf_free(p1);
49 TEST_DONE();
50
51 TEST_START("sshbuf_from data");
52 p1 = sshbuf_from(test_buf, sizeof(test_buf) - 1);
53 ASSERT_PTR_NE(p1, NULL);
54 ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf);
55 ASSERT_INT_EQ(sshbuf_get_u8(p1, &c), 0);
56 ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 1);
57 ASSERT_U8_EQ(c, 1);
58 ASSERT_INT_EQ(sshbuf_get_u32(p1, &i), 0);
59 ASSERT_PTR_EQ(sshbuf_ptr(p1), test_buf + 5);
60 ASSERT_U32_EQ(i, 0x12345678);
61 ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s, &l), 0);
62 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
63 ASSERT_STRING_EQ(s, "hello");
64 ASSERT_SIZE_T_EQ(l, 5);
65 sshbuf_free(p1);
66 free(s);
67 TEST_DONE();
68
69 TEST_START("sshbuf_fromb ");
70 p1 = sshbuf_new();
71 ASSERT_PTR_NE(p1, NULL);
72 ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1);
73 ASSERT_PTR_EQ(sshbuf_parent(p1), NULL);
74 ASSERT_INT_EQ(sshbuf_put(p1, test_buf, sizeof(test_buf) - 1), 0);
75 p2 = sshbuf_fromb(p1);
76 ASSERT_PTR_NE(p2, NULL);
77 ASSERT_U_INT_EQ(sshbuf_refcount(p1), 2);
78 ASSERT_PTR_EQ(sshbuf_parent(p1), NULL);
79 ASSERT_PTR_EQ(sshbuf_parent(p2), p1);
80 ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1));
81 ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
82 ASSERT_PTR_NE(sshbuf_ptr(p2), NULL);
83 ASSERT_PTR_EQ(sshbuf_mutable_ptr(p1), NULL);
84 ASSERT_PTR_EQ(sshbuf_mutable_ptr(p2), NULL);
85 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sshbuf_len(p2));
86 ASSERT_INT_EQ(sshbuf_get_u8(p2, &c), 0);
87 ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 1);
88 ASSERT_U8_EQ(c, 1);
89 ASSERT_INT_EQ(sshbuf_get_u32(p2, &i), 0);
90 ASSERT_PTR_EQ(sshbuf_ptr(p2), sshbuf_ptr(p1) + 5);
91 ASSERT_U32_EQ(i, 0x12345678);
92 ASSERT_INT_EQ(sshbuf_get_cstring(p2, &s, &l), 0);
93 ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0);
94 ASSERT_STRING_EQ(s, "hello");
95 ASSERT_SIZE_T_EQ(l, 5);
96 sshbuf_free(p1);
97 ASSERT_U_INT_EQ(sshbuf_refcount(p1), 1);
98 sshbuf_free(p2);
99 free(s);
100 TEST_DONE();
101
102 TEST_START("sshbuf_froms");
103 p1 = sshbuf_new();
104 ASSERT_PTR_NE(p1, NULL);
105 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x01), 0);
106 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0);
107 ASSERT_INT_EQ(sshbuf_put_cstring(p1, "hello"), 0);
108 p2 = sshbuf_new();
109 ASSERT_PTR_NE(p2, NULL);
110 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(test_buf) - 1);
111 ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0);
112 ASSERT_SIZE_T_EQ(sshbuf_len(p2), sizeof(test_buf) + 4 - 1);
113 ASSERT_INT_EQ(sshbuf_froms(p2, &p3), 0);
114 ASSERT_SIZE_T_EQ(sshbuf_len(p2), 0);
115 ASSERT_PTR_NE(p3, NULL);
116 ASSERT_PTR_NE(sshbuf_ptr(p3), NULL);
117 ASSERT_SIZE_T_EQ(sshbuf_len(p3), sizeof(test_buf) - 1);
118 ASSERT_MEM_EQ(sshbuf_ptr(p3), test_buf, sizeof(test_buf) - 1);
119 sshbuf_free(p3);
120 ASSERT_INT_EQ(sshbuf_put_stringb(p2, p1), 0);
121 ASSERT_INT_EQ(sshbuf_consume_end(p2, 1), 0);
122 ASSERT_INT_EQ(sshbuf_froms(p2, &p3), SSH_ERR_MESSAGE_INCOMPLETE);
123 ASSERT_PTR_EQ(p3, NULL);
124 sshbuf_free(p2);
125 sshbuf_free(p1);
126}
diff --git a/regress/unittests/sshbuf/test_sshbuf_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_fuzz.c
new file mode 100644
index 000000000..c52376b53
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_fuzz.c
@@ -0,0 +1,127 @@
1/* $OpenBSD: test_sshbuf_fuzz.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14# include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include "../test_helper/test_helper.h"
20
21#include "ssherr.h"
22#include "sshbuf.h"
23
24#define NUM_FUZZ_TESTS (1 << 18)
25
26void sshbuf_fuzz_tests(void);
27
28void
29sshbuf_fuzz_tests(void)
30{
31 struct sshbuf *p1;
32 u_char *dp;
33 size_t sz, sz2, i;
34 u_int32_t r;
35 int ret;
36
37 /* NB. uses sshbuf internals */
38 TEST_START("fuzz alloc/dealloc");
39 p1 = sshbuf_new();
40 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 16 * 1024), 0);
41 ASSERT_PTR_NE(p1, NULL);
42 ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
43 ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
44 for (i = 0; i < NUM_FUZZ_TESTS; i++) {
45 r = arc4random_uniform(10);
46 if (r == 0) {
47 /* 10% chance: small reserve */
48 r = arc4random_uniform(10);
49 fuzz_reserve:
50 sz = sshbuf_avail(p1);
51 sz2 = sshbuf_len(p1);
52 ret = sshbuf_reserve(p1, r, &dp);
53 if (ret < 0) {
54 ASSERT_PTR_EQ(dp, NULL);
55 ASSERT_SIZE_T_LT(sz, r);
56 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
57 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
58 } else {
59 ASSERT_PTR_NE(dp, NULL);
60 ASSERT_SIZE_T_GE(sz, r);
61 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz - r);
62 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 + r);
63 memset(dp, arc4random_uniform(255) + 1, r);
64 }
65 } else if (r < 3) {
66 /* 20% chance: big reserve */
67 r = arc4random_uniform(8 * 1024);
68 goto fuzz_reserve;
69 } else if (r == 3) {
70 /* 10% chance: small consume */
71 r = arc4random_uniform(10);
72 fuzz_consume:
73 sz = sshbuf_avail(p1);
74 sz2 = sshbuf_len(p1);
75 /* 50% change consume from end, otherwise start */
76 ret = ((arc4random() & 1) ?
77 sshbuf_consume : sshbuf_consume_end)(p1, r);
78 if (ret < 0) {
79 ASSERT_SIZE_T_LT(sz2, r);
80 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz);
81 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2);
82 } else {
83 ASSERT_SIZE_T_GE(sz2, r);
84 ASSERT_SIZE_T_EQ(sshbuf_avail(p1), sz + r);
85 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sz2 - r);
86 }
87 } else if (r < 8) {
88 /* 40% chance: big consume */
89 r = arc4random_uniform(2 * 1024);
90 goto fuzz_consume;
91 } else if (r == 8) {
92 /* 10% chance: reset max size */
93 r = arc4random_uniform(16 * 1024);
94 sz = sshbuf_max_size(p1);
95 if (sshbuf_set_max_size(p1, r) < 0)
96 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), sz);
97 else
98 ASSERT_SIZE_T_EQ(sshbuf_max_size(p1), r);
99 } else {
100 if (arc4random_uniform(8192) == 0) {
101 /* tiny chance: new buffer */
102 ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
103 ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
104 sshbuf_free(p1);
105 p1 = sshbuf_new();
106 ASSERT_PTR_NE(p1, NULL);
107 ASSERT_INT_EQ(sshbuf_set_max_size(p1,
108 16 * 1024), 0);
109 } else {
110 /* Almost 10%: giant reserve */
111 /* use arc4random_buf for r > 2^32 on 64 bit */
112 arc4random_buf(&r, sizeof(r));
113 while (r < SSHBUF_SIZE_MAX / 2) {
114 r <<= 1;
115 r |= arc4random() & 1;
116 }
117 goto fuzz_reserve;
118 }
119 }
120 ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
121 ASSERT_SIZE_T_LE(sshbuf_max_size(p1), 16 * 1024);
122 }
123 ASSERT_PTR_NE(sshbuf_ptr(p1), NULL);
124 ASSERT_MEM_ZERO_NE(sshbuf_ptr(p1), sshbuf_len(p1));
125 sshbuf_free(p1);
126 TEST_DONE();
127}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_basic.c b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c
new file mode 100644
index 000000000..966e8432b
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_basic.c
@@ -0,0 +1,484 @@
1/* $OpenBSD: test_sshbuf_getput_basic.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14# include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include "../test_helper/test_helper.h"
20#include "ssherr.h"
21#include "sshbuf.h"
22
23void sshbuf_getput_basic_tests(void);
24
25void
26sshbuf_getput_basic_tests(void)
27{
28 struct sshbuf *p1, *p2;
29 const u_char *cd;
30 u_char *d, d2[32], x[] = {
31 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x00, 0x99
32 };
33 u_int64_t v64;
34 u_int32_t v32;
35 u_int16_t v16;
36 u_char v8;
37 size_t s;
38 char *s2;
39 int r;
40 u_char bn1[] = { 0x00, 0x00, 0x00 };
41 u_char bn2[] = { 0x00, 0x00, 0x01, 0x02 };
42 u_char bn3[] = { 0x00, 0x80, 0x09 };
43 u_char bn_exp1[] = { 0x00, 0x00, 0x00, 0x00 };
44 u_char bn_exp2[] = { 0x00, 0x00, 0x00, 0x02, 0x01, 0x02 };
45 u_char bn_exp3[] = { 0x00, 0x00, 0x00, 0x03, 0x00, 0x80, 0x09 };
46
47 TEST_START("PEEK_U64");
48 ASSERT_U64_EQ(PEEK_U64(x), 0x1122334455667788ULL);
49 TEST_DONE();
50
51 TEST_START("PEEK_U32");
52 ASSERT_U32_EQ(PEEK_U32(x), 0x11223344);
53 TEST_DONE();
54
55 TEST_START("PEEK_U16");
56 ASSERT_U16_EQ(PEEK_U16(x), 0x1122);
57 TEST_DONE();
58
59 TEST_START("POKE_U64");
60 bzero(d2, sizeof(d2));
61 POKE_U64(d2, 0x1122334455667788ULL);
62 ASSERT_MEM_EQ(d2, x, 8);
63 TEST_DONE();
64
65 TEST_START("POKE_U32");
66 bzero(d2, sizeof(d2));
67 POKE_U32(d2, 0x11223344);
68 ASSERT_MEM_EQ(d2, x, 4);
69 TEST_DONE();
70
71 TEST_START("POKE_U16");
72 bzero(d2, sizeof(d2));
73 POKE_U16(d2, 0x1122);
74 ASSERT_MEM_EQ(d2, x, 2);
75 TEST_DONE();
76
77 TEST_START("sshbuf_put");
78 p1 = sshbuf_new();
79 ASSERT_PTR_NE(p1, NULL);
80 ASSERT_INT_EQ(sshbuf_put(p1, x, 5), 0);
81 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5);
82 cd = sshbuf_ptr(p1);
83 ASSERT_PTR_NE(cd, NULL);
84 ASSERT_U8_EQ(cd[0], 0x11);
85 ASSERT_U8_EQ(cd[1], 0x22);
86 ASSERT_U8_EQ(cd[2], 0x33);
87 ASSERT_U8_EQ(cd[3], 0x44);
88 ASSERT_U8_EQ(cd[4], 0x55);
89 TEST_DONE();
90
91 TEST_START("sshbuf_get");
92 ASSERT_INT_EQ(sshbuf_get(p1, d2, 4), 0);
93 ASSERT_MEM_EQ(d2, x, 4);
94 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
95 ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55);
96 TEST_DONE();
97
98 TEST_START("sshbuf_get truncated");
99 r = sshbuf_get(p1, d2, 4);
100 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
101 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
102 ASSERT_U8_EQ(*(sshbuf_ptr(p1)), 0x55);
103 TEST_DONE();
104
105 TEST_START("sshbuf_put truncated");
106 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0);
107 r = sshbuf_put(p1, x, 5);
108 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
109 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
110 sshbuf_free(p1);
111 TEST_DONE();
112
113 TEST_START("sshbuf_get_u64");
114 p1 = sshbuf_new();
115 ASSERT_PTR_NE(p1, NULL);
116 ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0);
117 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10);
118 ASSERT_INT_EQ(sshbuf_get_u64(p1, &v64), 0);
119 ASSERT_U64_EQ(v64, 0x1122334455667788ULL);
120 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
121 TEST_DONE();
122
123 TEST_START("sshbuf_get_u64 truncated");
124 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
125 r = sshbuf_get_u64(p1, &v64);
126 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
127 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
128 sshbuf_free(p1);
129 TEST_DONE();
130
131 TEST_START("sshbuf_get_u32");
132 p1 = sshbuf_new();
133 ASSERT_PTR_NE(p1, NULL);
134 ASSERT_INT_EQ(sshbuf_put(p1, x, 10), 0);
135 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 10);
136 ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0);
137 ASSERT_U32_EQ(v32, 0x11223344);
138 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 6);
139 ASSERT_INT_EQ(sshbuf_get_u32(p1, &v32), 0);
140 ASSERT_U32_EQ(v32, 0x55667788);
141 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
142 TEST_DONE();
143
144 TEST_START("sshbuf_get_u32 truncated");
145 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
146 r = sshbuf_get_u32(p1, &v32);
147 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
148 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
149 sshbuf_free(p1);
150 TEST_DONE();
151
152 TEST_START("sshbuf_get_u16");
153 p1 = sshbuf_new();
154 ASSERT_PTR_NE(p1, NULL);
155 ASSERT_INT_EQ(sshbuf_put(p1, x, 9), 0);
156 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 9);
157 ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
158 ASSERT_U16_EQ(v16, 0x1122);
159 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 7);
160 ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
161 ASSERT_U16_EQ(v16, 0x3344);
162 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 5);
163 ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
164 ASSERT_U16_EQ(v16, 0x5566);
165 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 3);
166 ASSERT_INT_EQ(sshbuf_get_u16(p1, &v16), 0);
167 ASSERT_U16_EQ(v16, 0x7788);
168 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
169 TEST_DONE();
170
171 TEST_START("sshbuf_get_u16 truncated");
172 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
173 r = sshbuf_get_u16(p1, &v16);
174 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
175 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
176 sshbuf_free(p1);
177 TEST_DONE();
178
179 TEST_START("sshbuf_get_u8");
180 p1 = sshbuf_new();
181 ASSERT_PTR_NE(p1, NULL);
182 ASSERT_INT_EQ(sshbuf_put(p1, x, 2), 0);
183 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
184 ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0);
185 ASSERT_U8_EQ(v8, 0x11);
186 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
187 ASSERT_INT_EQ(sshbuf_get_u8(p1, &v8), 0);
188 ASSERT_U8_EQ(v8, 0x22);
189 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
190 TEST_DONE();
191
192 TEST_START("sshbuf_get_u8 truncated");
193 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
194 r = sshbuf_get_u8(p1, &v8);
195 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
196 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
197 sshbuf_free(p1);
198 TEST_DONE();
199
200 TEST_START("sshbuf_put_u64");
201 p1 = sshbuf_new();
202 ASSERT_PTR_NE(p1, NULL);
203 ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0);
204 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8);
205 ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8);
206 sshbuf_free(p1);
207 TEST_DONE();
208
209 TEST_START("sshbuf_put_u64 exact");
210 p1 = sshbuf_new();
211 ASSERT_PTR_NE(p1, NULL);
212 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 8), 0);
213 ASSERT_INT_EQ(sshbuf_put_u64(p1, 0x1122334455667788ULL), 0);
214 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 8);
215 ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 8);
216 sshbuf_free(p1);
217 TEST_DONE();
218
219 TEST_START("sshbuf_put_u64 limited");
220 p1 = sshbuf_new();
221 ASSERT_PTR_NE(p1, NULL);
222 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 7), 0);
223 r = sshbuf_put_u64(p1, 0x1122334455667788ULL);
224 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
225 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
226 sshbuf_free(p1);
227 TEST_DONE();
228
229 TEST_START("sshbuf_put_u32");
230 p1 = sshbuf_new();
231 ASSERT_PTR_NE(p1, NULL);
232 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0);
233 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
234 ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4);
235 sshbuf_free(p1);
236 TEST_DONE();
237
238 TEST_START("sshbuf_put_u32 exact");
239 p1 = sshbuf_new();
240 ASSERT_PTR_NE(p1, NULL);
241 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 4), 0);
242 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x11223344), 0);
243 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
244 ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 4);
245 sshbuf_free(p1);
246 TEST_DONE();
247
248 TEST_START("sshbuf_put_u32 limited");
249 p1 = sshbuf_new();
250 ASSERT_PTR_NE(p1, NULL);
251 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 3), 0);
252 r = sshbuf_put_u32(p1, 0x11223344);
253 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
254 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
255 sshbuf_free(p1);
256 TEST_DONE();
257
258 TEST_START("sshbuf_put_u16");
259 p1 = sshbuf_new();
260 ASSERT_PTR_NE(p1, NULL);
261 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0);
262 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
263 ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2);
264 sshbuf_free(p1);
265 TEST_DONE();
266
267 TEST_START("sshbuf_put_u16");
268 p1 = sshbuf_new();
269 ASSERT_PTR_NE(p1, NULL);
270 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 2), 0);
271 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0x1122), 0);
272 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
273 ASSERT_MEM_EQ(sshbuf_ptr(p1), x, 2);
274 sshbuf_free(p1);
275 TEST_DONE();
276
277 TEST_START("sshbuf_put_u16 limited");
278 p1 = sshbuf_new();
279 ASSERT_PTR_NE(p1, NULL);
280 ASSERT_INT_EQ(sshbuf_set_max_size(p1, 1), 0);
281 r = sshbuf_put_u16(p1, 0x1122);
282 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
283 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
284 sshbuf_free(p1);
285 TEST_DONE();
286
287 TEST_START("sshbuf_get_string");
288 p1 = sshbuf_new();
289 ASSERT_PTR_NE(p1, NULL);
290 ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
291 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
292 ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
293 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 + 4);
294 ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0);
295 ASSERT_SIZE_T_EQ(s, sizeof(x));
296 ASSERT_MEM_EQ(d, x, sizeof(x));
297 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
298 free(d);
299 sshbuf_free(p1);
300 TEST_DONE();
301
302 TEST_START("sshbuf_get_string exact");
303 p1 = sshbuf_new();
304 ASSERT_PTR_NE(p1, NULL);
305 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4), 0);
306 ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
307 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
308 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
309 ASSERT_INT_EQ(sshbuf_get_string(p1, &d, &s), 0);
310 ASSERT_SIZE_T_EQ(s, sizeof(x));
311 ASSERT_MEM_EQ(d, x, sizeof(x));
312 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
313 free(d);
314 sshbuf_free(p1);
315 TEST_DONE();
316
317 TEST_START("sshbuf_get_string truncated");
318 p1 = sshbuf_new();
319 ASSERT_PTR_NE(p1, NULL);
320 ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
321 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
322 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
323 ASSERT_INT_EQ(sshbuf_consume_end(p1, 1), 0);
324 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3);
325 r = sshbuf_get_string(p1, &d, &s);
326 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
327 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 3);
328 sshbuf_free(p1);
329 TEST_DONE();
330
331 TEST_START("sshbuf_get_string giant");
332 p1 = sshbuf_new();
333 ASSERT_PTR_NE(p1, NULL);
334 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0);
335 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
336 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
337 r = sshbuf_get_string(p1, &d, &s);
338 ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE);
339 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
340 sshbuf_free(p1);
341 TEST_DONE();
342
343 TEST_START("sshbuf_get_cstring giant");
344 p1 = sshbuf_new();
345 ASSERT_PTR_NE(p1, NULL);
346 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0xffffffff), 0);
347 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
348 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
349 r = sshbuf_get_cstring(p1, &s2, &s);
350 ASSERT_INT_EQ(r, SSH_ERR_STRING_TOO_LARGE);
351 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
352 sshbuf_free(p1);
353 TEST_DONE();
354
355 TEST_START("sshbuf_get_cstring embedded \\0");
356 p1 = sshbuf_new();
357 ASSERT_PTR_NE(p1, NULL);
358 ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x)), 0);
359 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x)), 0);
360 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
361 r = sshbuf_get_cstring(p1, &s2, NULL);
362 ASSERT_INT_EQ(r, SSH_ERR_INVALID_FORMAT);
363 sshbuf_free(p1);
364 TEST_DONE();
365
366 TEST_START("sshbuf_get_cstring trailing \\0");
367 p1 = sshbuf_new();
368 ASSERT_PTR_NE(p1, NULL);
369 ASSERT_INT_EQ(sshbuf_put_u32(p1, sizeof(x) - 1), 0);
370 ASSERT_INT_EQ(sshbuf_put(p1, x, sizeof(x) - 1), 0);
371 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4 - 1);
372 ASSERT_INT_EQ(sshbuf_get_cstring(p1, &s2, &s), 0);
373 ASSERT_SIZE_T_EQ(s, sizeof(x) - 1);
374 ASSERT_MEM_EQ(s2, x, s);
375 free(s2);
376 sshbuf_free(p1);
377 TEST_DONE();
378
379 TEST_START("sshbuf_put_string");
380 p1 = sshbuf_new();
381 ASSERT_PTR_NE(p1, NULL);
382 ASSERT_INT_EQ(sshbuf_put_string(p1, x, sizeof(x)), 0);
383 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(x) + 4);
384 ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), sizeof(x));
385 ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, x, sizeof(x));
386 sshbuf_free(p1);
387 TEST_DONE();
388
389 TEST_START("sshbuf_put_string limited");
390 p1 = sshbuf_new();
391 ASSERT_PTR_NE(p1, NULL);
392 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(x) + 4 - 1), 0);
393 r = sshbuf_put_string(p1, x, sizeof(x));
394 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
395 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
396 sshbuf_free(p1);
397 TEST_DONE();
398
399 TEST_START("sshbuf_put_string giant");
400 p1 = sshbuf_new();
401 ASSERT_PTR_NE(p1, NULL);
402 r = sshbuf_put_string(p1, (void *)0x01, 0xfffffffc);
403 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
404 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
405 sshbuf_free(p1);
406 TEST_DONE();
407
408 TEST_START("sshbuf_putf");
409 p1 = sshbuf_new();
410 ASSERT_PTR_NE(p1, NULL);
411 r = sshbuf_putf(p1, "%s %d %x", "hello", 23, 0x5f);
412 ASSERT_INT_EQ(r, 0);
413 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 11);
414 ASSERT_MEM_EQ(sshbuf_ptr(p1), "hello 23 5f", 11);
415 sshbuf_free(p1);
416 TEST_DONE();
417
418 TEST_START("sshbuf_putb");
419 p1 = sshbuf_new();
420 ASSERT_PTR_NE(p1, NULL);
421 p2 = sshbuf_new();
422 ASSERT_PTR_NE(p2, NULL);
423 ASSERT_INT_EQ(sshbuf_put(p1, "blahblahblah", 12), 0);
424 ASSERT_INT_EQ(sshbuf_putb(p2, p1), 0);
425 sshbuf_free(p1);
426 ASSERT_SIZE_T_EQ(sshbuf_len(p2), 12);
427 ASSERT_MEM_EQ(sshbuf_ptr(p2), "blahblahblah", 12);
428 sshbuf_free(p2);
429 TEST_DONE();
430
431 TEST_START("sshbuf_put_bignum2_bytes empty buf");
432 p1 = sshbuf_new();
433 ASSERT_PTR_NE(p1, NULL);
434 ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, NULL, 0), 0);
435 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1));
436 ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1));
437 sshbuf_free(p1);
438 TEST_DONE();
439
440 TEST_START("sshbuf_put_bignum2_bytes all zeroes");
441 p1 = sshbuf_new();
442 ASSERT_PTR_NE(p1, NULL);
443 ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn1, sizeof(bn1)), 0);
444 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp1));
445 ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp1, sizeof(bn_exp1));
446 sshbuf_free(p1);
447 TEST_DONE();
448
449 TEST_START("sshbuf_put_bignum2_bytes simple");
450 p1 = sshbuf_new();
451 ASSERT_PTR_NE(p1, NULL);
452 ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2+2, sizeof(bn2)-2), 0);
453 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2));
454 ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2));
455 sshbuf_free(p1);
456 TEST_DONE();
457
458 TEST_START("sshbuf_put_bignum2_bytes leading zero");
459 p1 = sshbuf_new();
460 ASSERT_PTR_NE(p1, NULL);
461 ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn2, sizeof(bn2)), 0);
462 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp2));
463 ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp2, sizeof(bn_exp2));
464 sshbuf_free(p1);
465 TEST_DONE();
466
467 TEST_START("sshbuf_put_bignum2_bytes neg");
468 p1 = sshbuf_new();
469 ASSERT_PTR_NE(p1, NULL);
470 ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3+1, sizeof(bn3)-1), 0);
471 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3));
472 ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3));
473 sshbuf_free(p1);
474 TEST_DONE();
475
476 TEST_START("sshbuf_put_bignum2_bytes neg and leading zero");
477 p1 = sshbuf_new();
478 ASSERT_PTR_NE(p1, NULL);
479 ASSERT_INT_EQ(sshbuf_put_bignum2_bytes(p1, bn3, sizeof(bn3)), 0);
480 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(bn_exp3));
481 ASSERT_MEM_EQ(sshbuf_ptr(p1), bn_exp3, sizeof(bn_exp3));
482 sshbuf_free(p1);
483 TEST_DONE();
484}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
new file mode 100644
index 000000000..0c4c71ecd
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
@@ -0,0 +1,409 @@
1/* $OpenBSD: test_sshbuf_getput_crypto.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14# include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include <openssl/bn.h>
20#include <openssl/objects.h>
21#ifdef OPENSSL_HAS_NISTP256
22# include <openssl/ec.h>
23#endif
24
25#include "../test_helper/test_helper.h"
26#include "ssherr.h"
27#include "sshbuf.h"
28
29void sshbuf_getput_crypto_tests(void);
30
31void
32sshbuf_getput_crypto_tests(void)
33{
34 struct sshbuf *p1;
35 const u_char *d;
36 size_t s;
37 BIGNUM *bn, *bn2;
38 /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */
39 const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10";
40 /* This one has MSB set to test bignum2 encoding negative-avoidance */
41 const char *hexbn2 = "f0e0d0c0b0a0908070605040302010007fff11";
42 u_char expbn1[] = {
43 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
44 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
45 };
46 u_char expbn2[] = {
47 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
48 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
49 0x7f, 0xff, 0x11
50 };
51#ifdef OPENSSL_HAS_NISTP256
52 BIGNUM *bn_x, *bn_y;
53 int ec256_nid = NID_X9_62_prime256v1;
54 char *ec256_x = "0C828004839D0106AA59575216191357"
55 "34B451459DADB586677EF9DF55784999";
56 char *ec256_y = "4D196B50F0B4E94B3C73E3A9D4CD9DF2"
57 "C8F9A35E42BDD047550F69D80EC23CD4";
58 u_char expec256[] = {
59 0x04,
60 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06,
61 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57,
62 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86,
63 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99,
64 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b,
65 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2,
66 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47,
67 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4
68 };
69 EC_KEY *eck;
70 EC_POINT *ecp;
71#endif
72 int r;
73
74#define MKBN(b, bnn) \
75 do { \
76 bnn = NULL; \
77 ASSERT_INT_GT(BN_hex2bn(&bnn, b), 0); \
78 } while (0)
79
80 TEST_START("sshbuf_put_bignum1");
81 MKBN(hexbn1, bn);
82 p1 = sshbuf_new();
83 ASSERT_PTR_NE(p1, NULL);
84 ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0);
85 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 2);
86 ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn));
87 ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn1, sizeof(expbn1));
88 BN_free(bn);
89 sshbuf_free(p1);
90 TEST_DONE();
91
92 TEST_START("sshbuf_put_bignum1 limited");
93 MKBN(hexbn1, bn);
94 p1 = sshbuf_new();
95 ASSERT_PTR_NE(p1, NULL);
96 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0);
97 r = sshbuf_put_bignum1(p1, bn);
98 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
99 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
100 BN_free(bn);
101 sshbuf_free(p1);
102 TEST_DONE();
103
104 TEST_START("sshbuf_put_bignum1 bn2");
105 MKBN(hexbn2, bn);
106 p1 = sshbuf_new();
107 ASSERT_PTR_NE(p1, NULL);
108 ASSERT_INT_EQ(sshbuf_put_bignum1(p1, bn), 0);
109 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 2);
110 ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), (u_int16_t)BN_num_bits(bn));
111 ASSERT_MEM_EQ(sshbuf_ptr(p1) + 2, expbn2, sizeof(expbn2));
112 BN_free(bn);
113 sshbuf_free(p1);
114 TEST_DONE();
115
116 TEST_START("sshbuf_put_bignum1 bn2 limited");
117 MKBN(hexbn2, bn);
118 p1 = sshbuf_new();
119 ASSERT_PTR_NE(p1, NULL);
120 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 1), 0);
121 r = sshbuf_put_bignum1(p1, bn);
122 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
123 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
124 BN_free(bn);
125 sshbuf_free(p1);
126 TEST_DONE();
127
128 TEST_START("sshbuf_put_bignum2");
129 MKBN(hexbn1, bn);
130 p1 = sshbuf_new();
131 ASSERT_PTR_NE(p1, NULL);
132 ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0);
133 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 4);
134 ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn));
135 ASSERT_MEM_EQ(sshbuf_ptr(p1) + 4, expbn1, sizeof(expbn1));
136 BN_free(bn);
137 sshbuf_free(p1);
138 TEST_DONE();
139
140 TEST_START("sshbuf_put_bignum2 limited");
141 MKBN(hexbn1, bn);
142 p1 = sshbuf_new();
143 ASSERT_PTR_NE(p1, NULL);
144 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn1) + 3), 0);
145 r = sshbuf_put_bignum2(p1, bn);
146 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
147 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
148 BN_free(bn);
149 sshbuf_free(p1);
150 TEST_DONE();
151
152 TEST_START("sshbuf_put_bignum2 bn2");
153 MKBN(hexbn2, bn);
154 p1 = sshbuf_new();
155 ASSERT_PTR_NE(p1, NULL);
156 ASSERT_INT_EQ(sshbuf_put_bignum2(p1, bn), 0);
157 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4 + 1); /* MSB */
158 ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), (u_int32_t)BN_num_bytes(bn) + 1);
159 ASSERT_U8_EQ(*(sshbuf_ptr(p1) + 4), 0x00);
160 ASSERT_MEM_EQ(sshbuf_ptr(p1) + 5, expbn2, sizeof(expbn2));
161 BN_free(bn);
162 sshbuf_free(p1);
163 TEST_DONE();
164
165 TEST_START("sshbuf_put_bignum2 bn2 limited");
166 MKBN(hexbn2, bn);
167 p1 = sshbuf_new();
168 ASSERT_PTR_NE(p1, NULL);
169 ASSERT_INT_EQ(sshbuf_set_max_size(p1, sizeof(expbn2) + 3), 0);
170 r = sshbuf_put_bignum2(p1, bn);
171 ASSERT_INT_EQ(r, SSH_ERR_NO_BUFFER_SPACE);
172 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 0);
173 BN_free(bn);
174 sshbuf_free(p1);
175 TEST_DONE();
176
177 TEST_START("sshbuf_get_bignum1");
178 MKBN(hexbn1, bn);
179 p1 = sshbuf_new();
180 ASSERT_PTR_NE(p1, NULL);
181 ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
182 ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0);
183 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1));
184 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
185 bn2 = BN_new();
186 ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0);
187 ASSERT_BIGNUM_EQ(bn, bn2);
188 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
189 BN_free(bn);
190 BN_free(bn2);
191 sshbuf_free(p1);
192 TEST_DONE();
193
194 TEST_START("sshbuf_get_bignum1 truncated");
195 MKBN(hexbn1, bn);
196 p1 = sshbuf_new();
197 ASSERT_PTR_NE(p1, NULL);
198 ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
199 ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0);
200 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1);
201 bn2 = BN_new();
202 r = sshbuf_get_bignum1(p1, bn2);
203 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
204 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn1) - 1);
205 BN_free(bn);
206 BN_free(bn2);
207 sshbuf_free(p1);
208 TEST_DONE();
209
210 TEST_START("sshbuf_get_bignum1 giant");
211 MKBN(hexbn1, bn);
212 p1 = sshbuf_new();
213 ASSERT_PTR_NE(p1, NULL);
214 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xffff), 0);
215 ASSERT_INT_EQ(sshbuf_reserve(p1, (0xffff + 7) / 8, NULL), 0);
216 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8));
217 bn2 = BN_new();
218 r = sshbuf_get_bignum1(p1, bn2);
219 ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE);
220 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + ((0xffff + 7) / 8));
221 BN_free(bn);
222 BN_free(bn2);
223 sshbuf_free(p1);
224 TEST_DONE();
225
226 TEST_START("sshbuf_get_bignum1 bn2");
227 MKBN(hexbn2, bn);
228 p1 = sshbuf_new();
229 ASSERT_PTR_NE(p1, NULL);
230 ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
231 ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
232 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2));
233 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
234 bn2 = BN_new();
235 ASSERT_INT_EQ(sshbuf_get_bignum1(p1, bn2), 0);
236 ASSERT_BIGNUM_EQ(bn, bn2);
237 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
238 BN_free(bn);
239 BN_free(bn2);
240 sshbuf_free(p1);
241 TEST_DONE();
242
243 TEST_START("sshbuf_get_bignum1 bn2 truncated");
244 MKBN(hexbn2, bn);
245 p1 = sshbuf_new();
246 ASSERT_PTR_NE(p1, NULL);
247 ASSERT_INT_EQ(sshbuf_put_u16(p1, BN_num_bits(bn)), 0);
248 ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0);
249 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1);
250 bn2 = BN_new();
251 r = sshbuf_get_bignum1(p1, bn2);
252 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
253 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2 + sizeof(expbn2) - 1);
254 BN_free(bn);
255 BN_free(bn2);
256 sshbuf_free(p1);
257 TEST_DONE();
258
259 TEST_START("sshbuf_get_bignum2");
260 MKBN(hexbn1, bn);
261 p1 = sshbuf_new();
262 ASSERT_PTR_NE(p1, NULL);
263 ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
264 ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1)), 0);
265 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + sizeof(expbn1));
266 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
267 bn2 = BN_new();
268 ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0);
269 ASSERT_BIGNUM_EQ(bn, bn2);
270 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
271 BN_free(bn);
272 BN_free(bn2);
273 sshbuf_free(p1);
274 TEST_DONE();
275
276 TEST_START("sshbuf_get_bignum2 truncated");
277 MKBN(hexbn1, bn);
278 p1 = sshbuf_new();
279 ASSERT_PTR_NE(p1, NULL);
280 ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
281 ASSERT_INT_EQ(sshbuf_put(p1, expbn1, sizeof(expbn1) - 1), 0);
282 bn2 = BN_new();
283 r = sshbuf_get_bignum2(p1, bn2);
284 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
285 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn1) + 3);
286 BN_free(bn);
287 BN_free(bn2);
288 sshbuf_free(p1);
289 TEST_DONE();
290
291 TEST_START("sshbuf_get_bignum2 giant");
292 MKBN(hexbn1, bn);
293 p1 = sshbuf_new();
294 ASSERT_PTR_NE(p1, NULL);
295 ASSERT_INT_EQ(sshbuf_put_u32(p1, 65536), 0);
296 ASSERT_INT_EQ(sshbuf_reserve(p1, 65536, NULL), 0);
297 bn2 = BN_new();
298 r = sshbuf_get_bignum2(p1, bn2);
299 ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_TOO_LARGE);
300 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 65536 + 4);
301 BN_free(bn);
302 BN_free(bn2);
303 sshbuf_free(p1);
304 TEST_DONE();
305
306 TEST_START("sshbuf_get_bignum2 bn2");
307 MKBN(hexbn2, bn);
308 p1 = sshbuf_new();
309 ASSERT_PTR_NE(p1, NULL);
310 ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0); /* MSB */
311 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
312 ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
313 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4 + 1 + sizeof(expbn2));
314 ASSERT_INT_EQ(sshbuf_put_u16(p1, 0xd00f), 0);
315 bn2 = BN_new();
316 ASSERT_INT_EQ(sshbuf_get_bignum2(p1, bn2), 0);
317 ASSERT_BIGNUM_EQ(bn, bn2);
318 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
319 BN_free(bn);
320 BN_free(bn2);
321 sshbuf_free(p1);
322 TEST_DONE();
323
324 TEST_START("sshbuf_get_bignum2 bn2 truncated");
325 MKBN(hexbn2, bn);
326 p1 = sshbuf_new();
327 ASSERT_PTR_NE(p1, NULL);
328 ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn) + 1), 0);
329 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
330 ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2) - 1), 0);
331 bn2 = BN_new();
332 r = sshbuf_get_bignum2(p1, bn2);
333 ASSERT_INT_EQ(r, SSH_ERR_MESSAGE_INCOMPLETE);
334 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 1 + 4 - 1);
335 BN_free(bn);
336 BN_free(bn2);
337 sshbuf_free(p1);
338 TEST_DONE();
339
340 TEST_START("sshbuf_get_bignum2 bn2 negative");
341 MKBN(hexbn2, bn);
342 p1 = sshbuf_new();
343 ASSERT_PTR_NE(p1, NULL);
344 ASSERT_INT_EQ(sshbuf_put_u32(p1, BN_num_bytes(bn)), 0);
345 ASSERT_INT_EQ(sshbuf_put(p1, expbn2, sizeof(expbn2)), 0);
346 bn2 = BN_new();
347 r = sshbuf_get_bignum2(p1, bn2);
348 ASSERT_INT_EQ(r, SSH_ERR_BIGNUM_IS_NEGATIVE);
349 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expbn2) + 4);
350 BN_free(bn);
351 BN_free(bn2);
352 sshbuf_free(p1);
353 TEST_DONE();
354
355#ifdef OPENSSL_HAS_NISTP256
356 TEST_START("sshbuf_put_ec");
357 eck = EC_KEY_new_by_curve_name(ec256_nid);
358 ASSERT_PTR_NE(eck, NULL);
359 ecp = EC_POINT_new(EC_KEY_get0_group(eck));
360 ASSERT_PTR_NE(ecp, NULL);
361 MKBN(ec256_x, bn_x);
362 MKBN(ec256_y, bn_y);
363 ASSERT_INT_EQ(EC_POINT_set_affine_coordinates_GFp(
364 EC_KEY_get0_group(eck), ecp, bn_x, bn_y, NULL), 1);
365 ASSERT_INT_EQ(EC_KEY_set_public_key(eck, ecp), 1);
366 BN_free(bn_x);
367 BN_free(bn_y);
368 EC_POINT_free(ecp);
369 p1 = sshbuf_new();
370 ASSERT_PTR_NE(p1, NULL);
371 ASSERT_INT_EQ(sshbuf_put_eckey(p1, eck), 0);
372 ASSERT_INT_EQ(sshbuf_get_string_direct(p1, &d, &s), 0);
373 ASSERT_SIZE_T_EQ(s, sizeof(expec256));
374 ASSERT_MEM_EQ(d, expec256, sizeof(expec256));
375 sshbuf_free(p1);
376 EC_KEY_free(eck);
377 TEST_DONE();
378
379 TEST_START("sshbuf_get_ec");
380 eck = EC_KEY_new_by_curve_name(ec256_nid);
381 ASSERT_PTR_NE(eck, NULL);
382 p1 = sshbuf_new();
383 ASSERT_PTR_NE(p1, NULL);
384 ASSERT_INT_EQ(sshbuf_put_string(p1, expec256, sizeof(expec256)), 0);
385 ASSERT_SIZE_T_EQ(sshbuf_len(p1), sizeof(expec256) + 4);
386 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x00), 0);
387 ASSERT_INT_EQ(sshbuf_get_eckey(p1, eck), 0);
388 bn_x = BN_new();
389 bn_y = BN_new();
390 ASSERT_PTR_NE(bn_x, NULL);
391 ASSERT_PTR_NE(bn_y, NULL);
392 ASSERT_INT_EQ(EC_POINT_get_affine_coordinates_GFp(
393 EC_KEY_get0_group(eck), EC_KEY_get0_public_key(eck),
394 bn_x, bn_y, NULL), 1);
395 MKBN(ec256_x, bn);
396 MKBN(ec256_y, bn2);
397 ASSERT_INT_EQ(BN_cmp(bn_x, bn), 0);
398 ASSERT_INT_EQ(BN_cmp(bn_y, bn2), 0);
399 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
400 sshbuf_free(p1);
401 EC_KEY_free(eck);
402 BN_free(bn_x);
403 BN_free(bn_y);
404 BN_free(bn);
405 BN_free(bn2);
406 TEST_DONE();
407#endif
408}
409
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
new file mode 100644
index 000000000..8c3269b13
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
@@ -0,0 +1,130 @@
1/* $OpenBSD: test_sshbuf_getput_fuzz.c,v 1.2 2014/05/02 02:54:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14# include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include <openssl/bn.h>
20#include <openssl/objects.h>
21#ifdef OPENSSL_HAS_NISTP256
22# include <openssl/ec.h>
23#endif
24
25#include "../test_helper/test_helper.h"
26#include "ssherr.h"
27#include "sshbuf.h"
28
29void sshbuf_getput_fuzz_tests(void);
30
31static void
32attempt_parse_blob(u_char *blob, size_t len)
33{
34 struct sshbuf *p1;
35 BIGNUM *bn;
36#ifdef OPENSSL_HAS_NISTP256
37 EC_KEY *eck;
38#endif
39 u_char *s;
40 size_t l;
41 u_int8_t u8;
42 u_int16_t u16;
43 u_int32_t u32;
44 u_int64_t u64;
45
46 p1 = sshbuf_new();
47 ASSERT_PTR_NE(p1, NULL);
48 ASSERT_INT_EQ(sshbuf_put(p1, blob, len), 0);
49 sshbuf_get_u8(p1, &u8);
50 sshbuf_get_u16(p1, &u16);
51 sshbuf_get_u32(p1, &u32);
52 sshbuf_get_u64(p1, &u64);
53 if (sshbuf_get_string(p1, &s, &l) == 0) {
54 bzero(s, l);
55 free(s);
56 }
57 bn = BN_new();
58 sshbuf_get_bignum1(p1, bn);
59 BN_clear_free(bn);
60 bn = BN_new();
61 sshbuf_get_bignum2(p1, bn);
62 BN_clear_free(bn);
63#ifdef OPENSSL_HAS_NISTP256
64 eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
65 ASSERT_PTR_NE(eck, NULL);
66 sshbuf_get_eckey(p1, eck);
67 EC_KEY_free(eck);
68#endif
69 sshbuf_free(p1);
70}
71
72
73static void
74onerror(void *fuzz)
75{
76 fprintf(stderr, "Failed during fuzz:\n");
77 fuzz_dump((struct fuzz *)fuzz);
78}
79
80void
81sshbuf_getput_fuzz_tests(void)
82{
83 u_char blob[] = {
84 /* u8 */
85 0xd0,
86 /* u16 */
87 0xc0, 0xde,
88 /* u32 */
89 0xfa, 0xce, 0xde, 0xad,
90 /* u64 */
91 0xfe, 0xed, 0xac, 0x1d, 0x1f, 0x1c, 0xbe, 0xef,
92 /* string */
93 0x00, 0x00, 0x00, 0x09,
94 'O', ' ', 'G', 'o', 'r', 'g', 'o', 'n', '!',
95 /* bignum1 */
96 0x79,
97 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
98 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
99 /* bignum2 */
100 0x00, 0x00, 0x00, 0x14,
101 0x00,
102 0xf0, 0xe0, 0xd0, 0xc0, 0xb0, 0xa0, 0x90, 0x80,
103 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
104 0x7f, 0xff, 0x11,
105 /* EC point (NIST-256 curve) */
106 0x00, 0x00, 0x00, 0x41,
107 0x04,
108 0x0c, 0x82, 0x80, 0x04, 0x83, 0x9d, 0x01, 0x06,
109 0xaa, 0x59, 0x57, 0x52, 0x16, 0x19, 0x13, 0x57,
110 0x34, 0xb4, 0x51, 0x45, 0x9d, 0xad, 0xb5, 0x86,
111 0x67, 0x7e, 0xf9, 0xdf, 0x55, 0x78, 0x49, 0x99,
112 0x4d, 0x19, 0x6b, 0x50, 0xf0, 0xb4, 0xe9, 0x4b,
113 0x3c, 0x73, 0xe3, 0xa9, 0xd4, 0xcd, 0x9d, 0xf2,
114 0xc8, 0xf9, 0xa3, 0x5e, 0x42, 0xbd, 0xd0, 0x47,
115 0x55, 0x0f, 0x69, 0xd8, 0x0e, 0xc2, 0x3c, 0xd4,
116 };
117 struct fuzz *fuzz;
118
119 TEST_START("fuzz blob parsing");
120 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_2_BIT_FLIP |
121 FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
122 FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, blob, sizeof(blob));
123 TEST_ONERROR(onerror, fuzz);
124 for(; !fuzz_done(fuzz); fuzz_next(fuzz))
125 attempt_parse_blob(blob, sizeof(blob));
126 fuzz_cleanup(fuzz);
127 TEST_DONE();
128 TEST_ONERROR(NULL, NULL);
129}
130
diff --git a/regress/unittests/sshbuf/test_sshbuf_misc.c b/regress/unittests/sshbuf/test_sshbuf_misc.c
new file mode 100644
index 000000000..f155491a0
--- /dev/null
+++ b/regress/unittests/sshbuf/test_sshbuf_misc.c
@@ -0,0 +1,138 @@
1/* $OpenBSD: test_sshbuf_misc.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14# include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include "../test_helper/test_helper.h"
20
21#include "sshbuf.h"
22
23void sshbuf_misc_tests(void);
24
25void
26sshbuf_misc_tests(void)
27{
28 struct sshbuf *p1;
29 char tmp[512], *p;
30 FILE *out;
31 size_t sz;
32
33 TEST_START("sshbuf_dump");
34 out = tmpfile();
35 ASSERT_PTR_NE(out, NULL);
36 p1 = sshbuf_new();
37 ASSERT_PTR_NE(p1, NULL);
38 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0);
39 sshbuf_dump(p1, out);
40 fflush(out);
41 rewind(out);
42 sz = fread(tmp, 1, sizeof(tmp), out);
43 ASSERT_INT_EQ(ferror(out), 0);
44 ASSERT_INT_NE(feof(out), 0);
45 ASSERT_SIZE_T_GT(sz, 0);
46 tmp[sz] = '\0';
47 ASSERT_PTR_NE(strstr(tmp, "12 34 56 78"), NULL);
48 fclose(out);
49 sshbuf_free(p1);
50 TEST_DONE();
51
52 TEST_START("sshbuf_dtob16");
53 p1 = sshbuf_new();
54 ASSERT_PTR_NE(p1, NULL);
55 ASSERT_INT_EQ(sshbuf_put_u32(p1, 0x12345678), 0);
56 p = sshbuf_dtob16(p1);
57 ASSERT_PTR_NE(p, NULL);
58 ASSERT_STRING_EQ(p, "12345678");
59 free(p);
60 sshbuf_free(p1);
61 TEST_DONE();
62
63 TEST_START("sshbuf_dtob64 len 1");
64 p1 = sshbuf_new();
65 ASSERT_PTR_NE(p1, NULL);
66 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0);
67 p = sshbuf_dtob64(p1);
68 ASSERT_PTR_NE(p, NULL);
69 ASSERT_STRING_EQ(p, "EQ==");
70 free(p);
71 sshbuf_free(p1);
72 TEST_DONE();
73
74 TEST_START("sshbuf_dtob64 len 2");
75 p1 = sshbuf_new();
76 ASSERT_PTR_NE(p1, NULL);
77 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0);
78 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0);
79 p = sshbuf_dtob64(p1);
80 ASSERT_PTR_NE(p, NULL);
81 ASSERT_STRING_EQ(p, "ESI=");
82 free(p);
83 sshbuf_free(p1);
84 TEST_DONE();
85
86 TEST_START("sshbuf_dtob64 len 3");
87 p1 = sshbuf_new();
88 ASSERT_PTR_NE(p1, NULL);
89 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x11), 0);
90 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x22), 0);
91 ASSERT_INT_EQ(sshbuf_put_u8(p1, 0x33), 0);
92 p = sshbuf_dtob64(p1);
93 ASSERT_PTR_NE(p, NULL);
94 ASSERT_STRING_EQ(p, "ESIz");
95 free(p);
96 sshbuf_free(p1);
97 TEST_DONE();
98
99 TEST_START("sshbuf_dtob64 len 8191");
100 p1 = sshbuf_new();
101 ASSERT_PTR_NE(p1, NULL);
102 ASSERT_INT_EQ(sshbuf_reserve(p1, 8192, NULL), 0);
103 bzero(sshbuf_mutable_ptr(p1), 8192);
104 p = sshbuf_dtob64(p1);
105 ASSERT_PTR_NE(p, NULL);
106 ASSERT_SIZE_T_EQ(strlen(p), ((8191 + 2) / 3) * 4);
107 free(p);
108 sshbuf_free(p1);
109 TEST_DONE();
110
111 TEST_START("sshbuf_b64tod len 1");
112 p1 = sshbuf_new();
113 ASSERT_PTR_NE(p1, NULL);
114 ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A=="), 0);
115 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 1);
116 ASSERT_U8_EQ(*sshbuf_ptr(p1), 0xd0);
117 sshbuf_free(p1);
118 TEST_DONE();
119
120 TEST_START("sshbuf_b64tod len 2");
121 p1 = sshbuf_new();
122 ASSERT_PTR_NE(p1, NULL);
123 ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A8="), 0);
124 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 2);
125 ASSERT_U16_EQ(PEEK_U16(sshbuf_ptr(p1)), 0xd00f);
126 sshbuf_free(p1);
127 TEST_DONE();
128
129 TEST_START("sshbuf_b64tod len 4");
130 p1 = sshbuf_new();
131 ASSERT_PTR_NE(p1, NULL);
132 ASSERT_INT_EQ(sshbuf_b64tod(p1, "0A/QDw=="), 0);
133 ASSERT_SIZE_T_EQ(sshbuf_len(p1), 4);
134 ASSERT_U32_EQ(PEEK_U32(sshbuf_ptr(p1)), 0xd00fd00f);
135 sshbuf_free(p1);
136 TEST_DONE();
137}
138
diff --git a/regress/unittests/sshbuf/tests.c b/regress/unittests/sshbuf/tests.c
new file mode 100644
index 000000000..1557e4342
--- /dev/null
+++ b/regress/unittests/sshbuf/tests.c
@@ -0,0 +1,28 @@
1/* $OpenBSD: tests.c,v 1.1 2014/04/30 05:32:00 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "../test_helper/test_helper.h"
9
10void sshbuf_tests(void);
11void sshbuf_getput_basic_tests(void);
12void sshbuf_getput_crypto_tests(void);
13void sshbuf_misc_tests(void);
14void sshbuf_fuzz_tests(void);
15void sshbuf_getput_fuzz_tests(void);
16void sshbuf_fixed(void);
17
18void
19tests(void)
20{
21 sshbuf_tests();
22 sshbuf_getput_basic_tests();
23 sshbuf_getput_crypto_tests();
24 sshbuf_misc_tests();
25 sshbuf_fuzz_tests();
26 sshbuf_getput_fuzz_tests();
27 sshbuf_fixed();
28}
diff --git a/regress/unittests/sshkey/Makefile b/regress/unittests/sshkey/Makefile
new file mode 100644
index 000000000..1bcd26676
--- /dev/null
+++ b/regress/unittests/sshkey/Makefile
@@ -0,0 +1,13 @@
1# $OpenBSD: Makefile,v 1.1 2014/06/24 01:14:18 djm Exp $
2
3TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
4
5PROG=test_sshkey
6SRCS=tests.c test_sshkey.c test_file.c test_fuzz.c common.c
7REGRESS_TARGETS=run-regress-${PROG}
8
9run-regress-${PROG}: ${PROG}
10 env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
11
12.include <bsd.regress.mk>
13
diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c
new file mode 100644
index 000000000..0a4b3a90c
--- /dev/null
+++ b/regress/unittests/sshkey/common.c
@@ -0,0 +1,84 @@
1/* $OpenBSD: common.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
2/*
3 * Helpers for key API tests
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <stdio.h>
15#ifdef HAVE_STDINT_H
16#include <stdint.h>
17#endif
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
22#include <openssl/bn.h>
23#include <openssl/rsa.h>
24#include <openssl/dsa.h>
25#include <openssl/objects.h>
26#ifdef OPENSSL_HAS_NISTP256
27# include <openssl/ec.h>
28#endif
29
30#include "../test_helper/test_helper.h"
31
32#include "ssherr.h"
33#include "authfile.h"
34#include "sshkey.h"
35#include "sshbuf.h"
36
37#include "common.h"
38
39struct sshbuf *
40load_file(const char *name)
41{
42 int fd;
43 struct sshbuf *ret;
44
45 ASSERT_PTR_NE(ret = sshbuf_new(), NULL);
46 ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1);
47 ASSERT_INT_EQ(sshkey_load_file(fd, name, ret), 0);
48 close(fd);
49 return ret;
50}
51
52struct sshbuf *
53load_text_file(const char *name)
54{
55 struct sshbuf *ret = load_file(name);
56 const u_char *p;
57
58 /* Trim whitespace at EOL */
59 for (p = sshbuf_ptr(ret); sshbuf_len(ret) > 0;) {
60 if (p[sshbuf_len(ret) - 1] == '\r' ||
61 p[sshbuf_len(ret) - 1] == '\t' ||
62 p[sshbuf_len(ret) - 1] == ' ' ||
63 p[sshbuf_len(ret) - 1] == '\n')
64 ASSERT_INT_EQ(sshbuf_consume_end(ret, 1), 0);
65 else
66 break;
67 }
68 /* \0 terminate */
69 ASSERT_INT_EQ(sshbuf_put_u8(ret, 0), 0);
70 return ret;
71}
72
73BIGNUM *
74load_bignum(const char *name)
75{
76 BIGNUM *ret = NULL;
77 struct sshbuf *buf;
78
79 buf = load_text_file(name);
80 ASSERT_INT_NE(BN_hex2bn(&ret, (const char *)sshbuf_ptr(buf)), 0);
81 sshbuf_free(buf);
82 return ret;
83}
84
diff --git a/regress/unittests/sshkey/common.h b/regress/unittests/sshkey/common.h
new file mode 100644
index 000000000..bf7d19dce
--- /dev/null
+++ b/regress/unittests/sshkey/common.h
@@ -0,0 +1,16 @@
1/* $OpenBSD: common.h,v 1.1 2014/06/24 01:14:18 djm Exp $ */
2/*
3 * Helpers for key API tests
4 *
5 * Placed in the public domain
6 */
7
8/* Load a binary file into a buffer */
9struct sshbuf *load_file(const char *name);
10
11/* Load a text file into a buffer */
12struct sshbuf *load_text_file(const char *name);
13
14/* Load a bignum from a file */
15BIGNUM *load_bignum(const char *name);
16
diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh
new file mode 100755
index 000000000..ee1fe3962
--- /dev/null
+++ b/regress/unittests/sshkey/mktestdata.sh
@@ -0,0 +1,190 @@
1#!/bin/sh
2# $OpenBSD: mktestdata.sh,v 1.3 2014/07/22 23:57:40 dtucker Exp $
3
4PW=mekmitasdigoat
5
6rsa1_params() {
7 _in="$1"
8 _outbase="$2"
9 set -e
10 ssh-keygen -f $_in -e -m pkcs8 | \
11 openssl rsa -noout -text -pubin | \
12 awk '/^Modulus:$/,/^Exponent:/' | \
13 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n
14 # XXX need conversion support in ssh-keygen for the other params
15 for x in n ; do
16 echo "" >> ${_outbase}.$x
17 echo ============ ${_outbase}.$x
18 cat ${_outbase}.$x
19 echo ============
20 done
21}
22
23rsa_params() {
24 _in="$1"
25 _outbase="$2"
26 set -e
27 openssl rsa -noout -text -in $_in | \
28 awk '/^modulus:$/,/^publicExponent:/' | \
29 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.n
30 openssl rsa -noout -text -in $_in | \
31 awk '/^prime1:$/,/^prime2:/' | \
32 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.p
33 openssl rsa -noout -text -in $_in | \
34 awk '/^prime2:$/,/^exponent1:/' | \
35 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.q
36 for x in n p q ; do
37 echo "" >> ${_outbase}.$x
38 echo ============ ${_outbase}.$x
39 cat ${_outbase}.$x
40 echo ============
41 done
42}
43
44dsa_params() {
45 _in="$1"
46 _outbase="$2"
47 set -e
48 openssl dsa -noout -text -in $_in | \
49 awk '/^priv:$/,/^pub:/' | \
50 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv
51 openssl dsa -noout -text -in $_in | \
52 awk '/^pub:/,/^P:/' | #\
53 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub
54 openssl dsa -noout -text -in $_in | \
55 awk '/^G:/,0' | \
56 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.g
57 for x in priv pub g ; do
58 echo "" >> ${_outbase}.$x
59 echo ============ ${_outbase}.$x
60 cat ${_outbase}.$x
61 echo ============
62 done
63}
64
65ecdsa_params() {
66 _in="$1"
67 _outbase="$2"
68 set -e
69 openssl ec -noout -text -in $_in | \
70 awk '/^priv:$/,/^pub:/' | \
71 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.priv
72 openssl ec -noout -text -in $_in | \
73 awk '/^pub:/,/^ASN1 OID:/' | #\
74 grep -v '^[a-zA-Z]' | tr -d ' \n:' > ${_outbase}.pub
75 openssl ec -noout -text -in $_in | \
76 grep "ASN1 OID:" | tr -d '\n' | \
77 sed 's/.*: //;s/ *$//' > ${_outbase}.curve
78 for x in priv pub curve ; do
79 echo "" >> ${_outbase}.$x
80 echo ============ ${_outbase}.$x
81 cat ${_outbase}.$x
82 echo ============
83 done
84}
85
86set -ex
87
88cd testdata
89
90rm -f rsa1_1 rsa_1 dsa_1 ecdsa_1 ed25519_1
91rm -f rsa1_2 rsa_2 dsa_2 ecdsa_2 ed25519_2
92rm -f rsa_n dsa_n ecdsa_n # new-format keys
93rm -f rsa1_1_pw rsa_1_pw dsa_1_pw ecdsa_1_pw ed25519_1_pw
94rm -f rsa_n_pw dsa_n_pw ecdsa_n_pw
95rm -f pw *.pub *.bn.* *.param.* *.fp *.fp.bb
96
97ssh-keygen -t rsa1 -b 768 -C "RSA1 test key #1" -N "" -f rsa1_1
98ssh-keygen -t rsa -b 768 -C "RSA test key #1" -N "" -f rsa_1
99ssh-keygen -t dsa -b 1024 -C "DSA test key #1" -N "" -f dsa_1
100ssh-keygen -t ecdsa -b 256 -C "ECDSA test key #1" -N "" -f ecdsa_1
101ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_1
102
103ssh-keygen -t rsa1 -b 2048 -C "RSA1 test key #2" -N "" -f rsa1_2
104ssh-keygen -t rsa -b 2048 -C "RSA test key #2" -N "" -f rsa_2
105ssh-keygen -t dsa -b 1024 -C "DSA test key #2" -N "" -f dsa_2
106ssh-keygen -t ecdsa -b 521 -C "ECDSA test key #2" -N "" -f ecdsa_2
107ssh-keygen -t ed25519 -C "ED25519 test key #1" -N "" -f ed25519_2
108
109cp rsa_1 rsa_n
110cp dsa_1 dsa_n
111cp ecdsa_1 ecdsa_n
112
113cp rsa1_1 rsa1_1_pw
114cp rsa_1 rsa_1_pw
115cp dsa_1 dsa_1_pw
116cp ecdsa_1 ecdsa_1_pw
117cp ed25519_1 ed25519_1_pw
118cp rsa_1 rsa_n_pw
119cp dsa_1 dsa_n_pw
120cp ecdsa_1 ecdsa_n_pw
121
122ssh-keygen -pf rsa1_1_pw -N "$PW"
123ssh-keygen -pf rsa_1_pw -N "$PW"
124ssh-keygen -pf dsa_1_pw -N "$PW"
125ssh-keygen -pf ecdsa_1_pw -N "$PW"
126ssh-keygen -pf ed25519_1_pw -N "$PW"
127ssh-keygen -opf rsa_n_pw -N "$PW"
128ssh-keygen -opf dsa_n_pw -N "$PW"
129ssh-keygen -opf ecdsa_n_pw -N "$PW"
130
131rsa1_params rsa1_1 rsa1_1.param
132rsa1_params rsa1_2 rsa1_2.param
133rsa_params rsa_1 rsa_1.param
134rsa_params rsa_2 rsa_2.param
135dsa_params dsa_1 dsa_1.param
136dsa_params dsa_1 dsa_1.param
137ecdsa_params ecdsa_1 ecdsa_1.param
138ecdsa_params ecdsa_2 ecdsa_2.param
139# XXX ed25519 params
140
141ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
142 -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
143 -V 19990101:20110101 -z 1 rsa_1.pub
144ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
145 -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
146 -V 19990101:20110101 -z 2 dsa_1.pub
147ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
148 -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
149 -V 19990101:20110101 -z 3 ecdsa_1.pub
150ssh-keygen -s rsa_2 -I hugo -n user1,user2 \
151 -Oforce-command=/bin/ls -Ono-port-forwarding -Osource-address=10.0.0.0/8 \
152 -V 19990101:20110101 -z 4 ed25519_1.pub
153
154ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
155 -V 19990101:20110101 -z 5 rsa_1.pub
156ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
157 -V 19990101:20110101 -z 6 dsa_1.pub
158ssh-keygen -s ecdsa_1 -I julius -n host1,host2 -h \
159 -V 19990101:20110101 -z 7 ecdsa_1.pub
160ssh-keygen -s ed25519_1 -I julius -n host1,host2 -h \
161 -V 19990101:20110101 -z 8 ed25519_1.pub
162
163ssh-keygen -lf rsa1_1 | awk '{print $2}' > rsa1_1.fp
164ssh-keygen -lf rsa_1 | awk '{print $2}' > rsa_1.fp
165ssh-keygen -lf dsa_1 | awk '{print $2}' > dsa_1.fp
166ssh-keygen -lf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp
167ssh-keygen -lf ed25519_1 | awk '{print $2}' > ed25519_1.fp
168ssh-keygen -lf rsa1_2 | awk '{print $2}' > rsa1_2.fp
169ssh-keygen -lf rsa_2 | awk '{print $2}' > rsa_2.fp
170ssh-keygen -lf dsa_2 | awk '{print $2}' > dsa_2.fp
171ssh-keygen -lf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp
172ssh-keygen -lf ed25519_2 | awk '{print $2}' > ed25519_2.fp
173
174ssh-keygen -lf dsa_1-cert.pub | awk '{print $2}' > dsa_1-cert.fp
175ssh-keygen -lf ecdsa_1-cert.pub | awk '{print $2}' > ecdsa_1-cert.fp
176ssh-keygen -lf ed25519_1-cert.pub | awk '{print $2}' > ed25519_1-cert.fp
177ssh-keygen -lf rsa_1-cert.pub | awk '{print $2}' > rsa_1-cert.fp
178
179ssh-keygen -Bf rsa1_1 | awk '{print $2}' > rsa1_1.fp.bb
180ssh-keygen -Bf rsa_1 | awk '{print $2}' > rsa_1.fp.bb
181ssh-keygen -Bf dsa_1 | awk '{print $2}' > dsa_1.fp.bb
182ssh-keygen -Bf ecdsa_1 | awk '{print $2}' > ecdsa_1.fp.bb
183ssh-keygen -Bf ed25519_1 | awk '{print $2}' > ed25519_1.fp.bb
184ssh-keygen -Bf rsa1_2 | awk '{print $2}' > rsa1_2.fp.bb
185ssh-keygen -Bf rsa_2 | awk '{print $2}' > rsa_2.fp.bb
186ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb
187ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb
188ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb
189
190echo "$PW" > pw
diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c
new file mode 100644
index 000000000..764f7fb76
--- /dev/null
+++ b/regress/unittests/sshkey/test_file.c
@@ -0,0 +1,457 @@
1/* $OpenBSD: test_file.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
2/*
3 * Regress test for sshkey.h key management API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <stdio.h>
15#ifdef HAVE_STDINT_H
16#include <stdint.h>
17#endif
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
22#include <openssl/bn.h>
23#include <openssl/rsa.h>
24#include <openssl/dsa.h>
25#include <openssl/objects.h>
26#ifdef OPENSSL_HAS_NISTP256
27# include <openssl/ec.h>
28#endif
29
30#include "../test_helper/test_helper.h"
31
32#include "ssherr.h"
33#include "authfile.h"
34#include "sshkey.h"
35#include "sshbuf.h"
36
37#include "common.h"
38
39void sshkey_file_tests(void);
40
41void
42sshkey_file_tests(void)
43{
44 struct sshkey *k1, *k2;
45 struct sshbuf *buf, *pw;
46 BIGNUM *a, *b, *c;
47 char *cp;
48
49 TEST_START("load passphrase");
50 pw = load_text_file("pw");
51 TEST_DONE();
52
53 TEST_START("parse RSA1 from private");
54 buf = load_file("rsa1_1");
55 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa1_1",
56 &k1, NULL), 0);
57 sshbuf_free(buf);
58 ASSERT_PTR_NE(k1, NULL);
59 a = load_bignum("rsa1_1.param.n");
60 ASSERT_BIGNUM_EQ(k1->rsa->n, a);
61 BN_free(a);
62 TEST_DONE();
63
64 TEST_START("parse RSA1 from private w/ passphrase");
65 buf = load_file("rsa1_1_pw");
66 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
67 (const char *)sshbuf_ptr(pw), "rsa1_1_pw", &k2, NULL), 0);
68 sshbuf_free(buf);
69 ASSERT_PTR_NE(k2, NULL);
70 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
71 sshkey_free(k2);
72 TEST_DONE();
73
74 TEST_START("load RSA1 from public");
75 ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa1_1.pub"), &k2,
76 NULL), 0);
77 ASSERT_PTR_NE(k2, NULL);
78 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
79 sshkey_free(k2);
80 TEST_DONE();
81
82 TEST_START("RSA1 key hex fingerprint");
83 buf = load_text_file("rsa1_1.fp");
84 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
85 ASSERT_PTR_NE(cp, NULL);
86 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
87 sshbuf_free(buf);
88 free(cp);
89 TEST_DONE();
90
91 TEST_START("RSA1 key bubblebabble fingerprint");
92 buf = load_text_file("rsa1_1.fp.bb");
93 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
94 ASSERT_PTR_NE(cp, NULL);
95 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
96 sshbuf_free(buf);
97 free(cp);
98 TEST_DONE();
99
100 sshkey_free(k1);
101
102 TEST_START("parse RSA from private");
103 buf = load_file("rsa_1");
104 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa_1",
105 &k1, NULL), 0);
106 sshbuf_free(buf);
107 ASSERT_PTR_NE(k1, NULL);
108 a = load_bignum("rsa_1.param.n");
109 b = load_bignum("rsa_1.param.p");
110 c = load_bignum("rsa_1.param.q");
111 ASSERT_BIGNUM_EQ(k1->rsa->n, a);
112 ASSERT_BIGNUM_EQ(k1->rsa->p, b);
113 ASSERT_BIGNUM_EQ(k1->rsa->q, c);
114 BN_free(a);
115 BN_free(b);
116 BN_free(c);
117 TEST_DONE();
118
119 TEST_START("parse RSA from private w/ passphrase");
120 buf = load_file("rsa_1_pw");
121 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
122 (const char *)sshbuf_ptr(pw), "rsa_1_pw", &k2, NULL), 0);
123 sshbuf_free(buf);
124 ASSERT_PTR_NE(k2, NULL);
125 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
126 sshkey_free(k2);
127 TEST_DONE();
128
129 TEST_START("parse RSA from new-format");
130 buf = load_file("rsa_n");
131 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
132 "", "rsa_n", &k2, NULL), 0);
133 sshbuf_free(buf);
134 ASSERT_PTR_NE(k2, NULL);
135 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
136 sshkey_free(k2);
137 TEST_DONE();
138
139 TEST_START("parse RSA from new-format w/ passphrase");
140 buf = load_file("rsa_n_pw");
141 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
142 (const char *)sshbuf_ptr(pw), "rsa_n_pw", &k2, NULL), 0);
143 sshbuf_free(buf);
144 ASSERT_PTR_NE(k2, NULL);
145 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
146 sshkey_free(k2);
147 TEST_DONE();
148
149 TEST_START("load RSA from public");
150 ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
151 NULL), 0);
152 ASSERT_PTR_NE(k2, NULL);
153 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
154 sshkey_free(k2);
155 TEST_DONE();
156
157 TEST_START("load RSA cert");
158 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k2), 0);
159 ASSERT_PTR_NE(k2, NULL);
160 ASSERT_INT_EQ(k2->type, KEY_RSA_CERT);
161 ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
162 ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
163 TEST_DONE();
164
165 TEST_START("RSA key hex fingerprint");
166 buf = load_text_file("rsa_1.fp");
167 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
168 ASSERT_PTR_NE(cp, NULL);
169 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
170 sshbuf_free(buf);
171 free(cp);
172 TEST_DONE();
173
174 TEST_START("RSA cert hex fingerprint");
175 buf = load_text_file("rsa_1-cert.fp");
176 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
177 ASSERT_PTR_NE(cp, NULL);
178 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
179 sshbuf_free(buf);
180 free(cp);
181 sshkey_free(k2);
182 TEST_DONE();
183
184 TEST_START("RSA key bubblebabble fingerprint");
185 buf = load_text_file("rsa_1.fp.bb");
186 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
187 ASSERT_PTR_NE(cp, NULL);
188 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
189 sshbuf_free(buf);
190 free(cp);
191 TEST_DONE();
192
193 sshkey_free(k1);
194
195 TEST_START("parse DSA from private");
196 buf = load_file("dsa_1");
197 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "dsa_1",
198 &k1, NULL), 0);
199 sshbuf_free(buf);
200 ASSERT_PTR_NE(k1, NULL);
201 a = load_bignum("dsa_1.param.g");
202 b = load_bignum("dsa_1.param.priv");
203 c = load_bignum("dsa_1.param.pub");
204 ASSERT_BIGNUM_EQ(k1->dsa->g, a);
205 ASSERT_BIGNUM_EQ(k1->dsa->priv_key, b);
206 ASSERT_BIGNUM_EQ(k1->dsa->pub_key, c);
207 BN_free(a);
208 BN_free(b);
209 BN_free(c);
210 TEST_DONE();
211
212 TEST_START("parse DSA from private w/ passphrase");
213 buf = load_file("dsa_1_pw");
214 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
215 (const char *)sshbuf_ptr(pw), "dsa_1_pw", &k2, NULL), 0);
216 sshbuf_free(buf);
217 ASSERT_PTR_NE(k2, NULL);
218 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
219 sshkey_free(k2);
220 TEST_DONE();
221
222 TEST_START("parse DSA from new-format");
223 buf = load_file("dsa_n");
224 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
225 "", "dsa_n", &k2, NULL), 0);
226 sshbuf_free(buf);
227 ASSERT_PTR_NE(k2, NULL);
228 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
229 sshkey_free(k2);
230 TEST_DONE();
231
232 TEST_START("parse DSA from new-format w/ passphrase");
233 buf = load_file("dsa_n_pw");
234 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
235 (const char *)sshbuf_ptr(pw), "dsa_n_pw", &k2, NULL), 0);
236 sshbuf_free(buf);
237 ASSERT_PTR_NE(k2, NULL);
238 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
239 sshkey_free(k2);
240 TEST_DONE();
241
242 TEST_START("load DSA from public");
243 ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_1.pub"), &k2,
244 NULL), 0);
245 ASSERT_PTR_NE(k2, NULL);
246 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
247 sshkey_free(k2);
248 TEST_DONE();
249
250 TEST_START("load DSA cert");
251 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k2), 0);
252 ASSERT_PTR_NE(k2, NULL);
253 ASSERT_INT_EQ(k2->type, KEY_DSA_CERT);
254 ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
255 ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
256 TEST_DONE();
257
258 TEST_START("DSA key hex fingerprint");
259 buf = load_text_file("dsa_1.fp");
260 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
261 ASSERT_PTR_NE(cp, NULL);
262 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
263 sshbuf_free(buf);
264 free(cp);
265 TEST_DONE();
266
267 TEST_START("DSA cert hex fingerprint");
268 buf = load_text_file("dsa_1-cert.fp");
269 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
270 ASSERT_PTR_NE(cp, NULL);
271 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
272 sshbuf_free(buf);
273 free(cp);
274 sshkey_free(k2);
275 TEST_DONE();
276
277 TEST_START("DSA key bubblebabble fingerprint");
278 buf = load_text_file("dsa_1.fp.bb");
279 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
280 ASSERT_PTR_NE(cp, NULL);
281 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
282 sshbuf_free(buf);
283 free(cp);
284 TEST_DONE();
285
286 sshkey_free(k1);
287
288#ifdef OPENSSL_HAS_ECC
289 TEST_START("parse ECDSA from private");
290 buf = load_file("ecdsa_1");
291 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "ecdsa_1",
292 &k1, NULL), 0);
293 sshbuf_free(buf);
294 ASSERT_PTR_NE(k1, NULL);
295 buf = load_text_file("ecdsa_1.param.curve");
296 ASSERT_STRING_EQ((const char *)sshbuf_ptr(buf),
297 OBJ_nid2sn(k1->ecdsa_nid));
298 sshbuf_free(buf);
299 a = load_bignum("ecdsa_1.param.priv");
300 b = load_bignum("ecdsa_1.param.pub");
301 c = EC_POINT_point2bn(EC_KEY_get0_group(k1->ecdsa),
302 EC_KEY_get0_public_key(k1->ecdsa), POINT_CONVERSION_UNCOMPRESSED,
303 NULL, NULL);
304 ASSERT_PTR_NE(c, NULL);
305 ASSERT_BIGNUM_EQ(EC_KEY_get0_private_key(k1->ecdsa), a);
306 ASSERT_BIGNUM_EQ(b, c);
307 BN_free(a);
308 BN_free(b);
309 BN_free(c);
310 TEST_DONE();
311
312 TEST_START("parse ECDSA from private w/ passphrase");
313 buf = load_file("ecdsa_1_pw");
314 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
315 (const char *)sshbuf_ptr(pw), "ecdsa_1_pw", &k2, NULL), 0);
316 sshbuf_free(buf);
317 ASSERT_PTR_NE(k2, NULL);
318 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
319 sshkey_free(k2);
320 TEST_DONE();
321
322 TEST_START("parse ECDSA from new-format");
323 buf = load_file("ecdsa_n");
324 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
325 "", "ecdsa_n", &k2, NULL), 0);
326 sshbuf_free(buf);
327 ASSERT_PTR_NE(k2, NULL);
328 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
329 sshkey_free(k2);
330 TEST_DONE();
331
332 TEST_START("parse ECDSA from new-format w/ passphrase");
333 buf = load_file("ecdsa_n_pw");
334 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
335 (const char *)sshbuf_ptr(pw), "ecdsa_n_pw", &k2, NULL), 0);
336 sshbuf_free(buf);
337 ASSERT_PTR_NE(k2, NULL);
338 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
339 sshkey_free(k2);
340 TEST_DONE();
341
342 TEST_START("load ECDSA from public");
343 ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_1.pub"), &k2,
344 NULL), 0);
345 ASSERT_PTR_NE(k2, NULL);
346 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
347 sshkey_free(k2);
348 TEST_DONE();
349
350 TEST_START("load ECDSA cert");
351 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k2), 0);
352 ASSERT_PTR_NE(k2, NULL);
353 ASSERT_INT_EQ(k2->type, KEY_ECDSA_CERT);
354 ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
355 ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
356 TEST_DONE();
357
358 TEST_START("ECDSA key hex fingerprint");
359 buf = load_text_file("ecdsa_1.fp");
360 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
361 ASSERT_PTR_NE(cp, NULL);
362 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
363 sshbuf_free(buf);
364 free(cp);
365 TEST_DONE();
366
367 TEST_START("ECDSA cert hex fingerprint");
368 buf = load_text_file("ecdsa_1-cert.fp");
369 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
370 ASSERT_PTR_NE(cp, NULL);
371 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
372 sshbuf_free(buf);
373 free(cp);
374 sshkey_free(k2);
375 TEST_DONE();
376
377 TEST_START("ECDSA key bubblebabble fingerprint");
378 buf = load_text_file("ecdsa_1.fp.bb");
379 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
380 ASSERT_PTR_NE(cp, NULL);
381 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
382 sshbuf_free(buf);
383 free(cp);
384 TEST_DONE();
385
386 sshkey_free(k1);
387#endif /* OPENSSL_HAS_ECC */
388
389 TEST_START("parse Ed25519 from private");
390 buf = load_file("ed25519_1");
391 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "ed25519_1",
392 &k1, NULL), 0);
393 sshbuf_free(buf);
394 ASSERT_PTR_NE(k1, NULL);
395 ASSERT_INT_EQ(k1->type, KEY_ED25519);
396 /* XXX check key contents */
397 TEST_DONE();
398
399 TEST_START("parse Ed25519 from private w/ passphrase");
400 buf = load_file("ed25519_1_pw");
401 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf,
402 (const char *)sshbuf_ptr(pw), "ed25519_1_pw", &k2, NULL), 0);
403 sshbuf_free(buf);
404 ASSERT_PTR_NE(k2, NULL);
405 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
406 sshkey_free(k2);
407 TEST_DONE();
408
409 TEST_START("load Ed25519 from public");
410 ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"), &k2,
411 NULL), 0);
412 ASSERT_PTR_NE(k2, NULL);
413 ASSERT_INT_EQ(sshkey_equal(k1, k2), 1);
414 sshkey_free(k2);
415 TEST_DONE();
416
417 TEST_START("load Ed25519 cert");
418 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k2), 0);
419 ASSERT_PTR_NE(k2, NULL);
420 ASSERT_INT_EQ(k2->type, KEY_ED25519_CERT);
421 ASSERT_INT_EQ(sshkey_equal(k1, k2), 0);
422 ASSERT_INT_EQ(sshkey_equal_public(k1, k2), 1);
423 TEST_DONE();
424
425 TEST_START("Ed25519 key hex fingerprint");
426 buf = load_text_file("ed25519_1.fp");
427 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
428 ASSERT_PTR_NE(cp, NULL);
429 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
430 sshbuf_free(buf);
431 free(cp);
432 TEST_DONE();
433
434 TEST_START("Ed25519 cert hex fingerprint");
435 buf = load_text_file("ed25519_1-cert.fp");
436 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
437 ASSERT_PTR_NE(cp, NULL);
438 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
439 sshbuf_free(buf);
440 free(cp);
441 sshkey_free(k2);
442 TEST_DONE();
443
444 TEST_START("Ed25519 key bubblebabble fingerprint");
445 buf = load_text_file("ed25519_1.fp.bb");
446 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
447 ASSERT_PTR_NE(cp, NULL);
448 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
449 sshbuf_free(buf);
450 free(cp);
451 TEST_DONE();
452
453 sshkey_free(k1);
454
455 sshbuf_free(pw);
456
457}
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c
new file mode 100644
index 000000000..a3f61a6df
--- /dev/null
+++ b/regress/unittests/sshkey/test_fuzz.c
@@ -0,0 +1,406 @@
1/* $OpenBSD: test_fuzz.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
2/*
3 * Fuzz tests for key parsing
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <sys/stat.h>
13#include <fcntl.h>
14#include <stdio.h>
15#ifdef HAVE_STDINT_H
16#include <stdint.h>
17#endif
18#include <stdlib.h>
19#include <string.h>
20#include <unistd.h>
21
22#include <openssl/bn.h>
23#include <openssl/rsa.h>
24#include <openssl/dsa.h>
25#include <openssl/objects.h>
26#ifdef OPENSSL_HAS_NISTP256
27# include <openssl/ec.h>
28#endif
29
30#include "../test_helper/test_helper.h"
31
32#include "ssherr.h"
33#include "authfile.h"
34#include "sshkey.h"
35#include "sshbuf.h"
36
37#include "common.h"
38
39void sshkey_fuzz_tests(void);
40
41static void
42onerror(void *fuzz)
43{
44 fprintf(stderr, "Failed during fuzz:\n");
45 fuzz_dump((struct fuzz *)fuzz);
46}
47
48static void
49public_fuzz(struct sshkey *k)
50{
51 struct sshkey *k1;
52 struct sshbuf *buf;
53 struct fuzz *fuzz;
54
55 ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
56 ASSERT_INT_EQ(sshkey_to_blob_buf(k, buf), 0);
57 /* XXX need a way to run the tests in "slow, but complete" mode */
58 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */
59 FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */
60 FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
61 sshbuf_mutable_ptr(buf), sshbuf_len(buf));
62 ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(buf), sshbuf_len(buf),
63 &k1), 0);
64 sshkey_free(k1);
65 sshbuf_free(buf);
66 TEST_ONERROR(onerror, fuzz);
67 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
68 if (sshkey_from_blob(fuzz_ptr(fuzz), fuzz_len(fuzz), &k1) == 0)
69 sshkey_free(k1);
70 }
71 fuzz_cleanup(fuzz);
72}
73
74static void
75sig_fuzz(struct sshkey *k)
76{
77 struct fuzz *fuzz;
78 u_char *sig, c[] = "some junk to be signed";
79 size_t l;
80
81 ASSERT_INT_EQ(sshkey_sign(k, &sig, &l, c, sizeof(c), 0), 0);
82 ASSERT_SIZE_T_GT(l, 0);
83 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* too slow FUZZ_2_BIT_FLIP | */
84 FUZZ_1_BYTE_FLIP | FUZZ_2_BYTE_FLIP |
85 FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END, sig, l);
86 ASSERT_INT_EQ(sshkey_verify(k, sig, l, c, sizeof(c), 0), 0);
87 free(sig);
88 TEST_ONERROR(onerror, fuzz);
89 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
90 sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
91 c, sizeof(c), 0);
92 }
93 fuzz_cleanup(fuzz);
94}
95
96void
97sshkey_fuzz_tests(void)
98{
99 struct sshkey *k1;
100 struct sshbuf *buf, *fuzzed;
101 struct fuzz *fuzz;
102 int r;
103
104 TEST_START("fuzz RSA1 private");
105 buf = load_file("rsa1_1");
106 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
107 FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
108 sshbuf_mutable_ptr(buf), sshbuf_len(buf));
109 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
110 &k1, NULL), 0);
111 sshkey_free(k1);
112 sshbuf_free(buf);
113 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
114 TEST_ONERROR(onerror, fuzz);
115 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
116 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
117 ASSERT_INT_EQ(r, 0);
118 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
119 &k1, NULL) == 0)
120 sshkey_free(k1);
121 sshbuf_reset(fuzzed);
122 }
123 sshbuf_free(fuzzed);
124 fuzz_cleanup(fuzz);
125 TEST_DONE();
126
127 TEST_START("fuzz RSA1 public");
128 buf = load_file("rsa1_1_pw");
129 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
130 FUZZ_TRUNCATE_START | FUZZ_TRUNCATE_END,
131 sshbuf_mutable_ptr(buf), sshbuf_len(buf));
132 ASSERT_INT_EQ(sshkey_parse_public_rsa1_fileblob(buf, &k1, NULL), 0);
133 sshkey_free(k1);
134 sshbuf_free(buf);
135 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
136 TEST_ONERROR(onerror, fuzz);
137 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
138 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
139 ASSERT_INT_EQ(r, 0);
140 if (sshkey_parse_public_rsa1_fileblob(fuzzed, &k1, NULL) == 0)
141 sshkey_free(k1);
142 sshbuf_reset(fuzzed);
143 }
144 sshbuf_free(fuzzed);
145 fuzz_cleanup(fuzz);
146 TEST_DONE();
147
148 TEST_START("fuzz RSA private");
149 buf = load_file("rsa_1");
150 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
151 sshbuf_len(buf));
152 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
153 &k1, NULL), 0);
154 sshkey_free(k1);
155 sshbuf_free(buf);
156 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
157 TEST_ONERROR(onerror, fuzz);
158 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
159 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
160 ASSERT_INT_EQ(r, 0);
161 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
162 &k1, NULL) == 0)
163 sshkey_free(k1);
164 sshbuf_reset(fuzzed);
165 }
166 sshbuf_free(fuzzed);
167 fuzz_cleanup(fuzz);
168 TEST_DONE();
169
170 TEST_START("fuzz RSA new-format private");
171 buf = load_file("rsa_n");
172 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
173 sshbuf_len(buf));
174 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
175 &k1, NULL), 0);
176 sshkey_free(k1);
177 sshbuf_free(buf);
178 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
179 TEST_ONERROR(onerror, fuzz);
180 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
181 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
182 ASSERT_INT_EQ(r, 0);
183 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
184 &k1, NULL) == 0)
185 sshkey_free(k1);
186 sshbuf_reset(fuzzed);
187 }
188 sshbuf_free(fuzzed);
189 fuzz_cleanup(fuzz);
190 TEST_DONE();
191
192 TEST_START("fuzz DSA private");
193 buf = load_file("dsa_1");
194 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
195 sshbuf_len(buf));
196 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
197 &k1, NULL), 0);
198 sshkey_free(k1);
199 sshbuf_free(buf);
200 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
201 TEST_ONERROR(onerror, fuzz);
202 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
203 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
204 ASSERT_INT_EQ(r, 0);
205 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
206 &k1, NULL) == 0)
207 sshkey_free(k1);
208 sshbuf_reset(fuzzed);
209 }
210 sshbuf_free(fuzzed);
211 fuzz_cleanup(fuzz);
212 TEST_DONE();
213
214 TEST_START("fuzz DSA new-format private");
215 buf = load_file("dsa_n");
216 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
217 sshbuf_len(buf));
218 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
219 &k1, NULL), 0);
220 sshkey_free(k1);
221 sshbuf_free(buf);
222 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
223 TEST_ONERROR(onerror, fuzz);
224 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
225 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
226 ASSERT_INT_EQ(r, 0);
227 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
228 &k1, NULL) == 0)
229 sshkey_free(k1);
230 sshbuf_reset(fuzzed);
231 }
232 sshbuf_free(fuzzed);
233 fuzz_cleanup(fuzz);
234 TEST_DONE();
235
236#ifdef OPENSSL_HAS_ECC
237 TEST_START("fuzz ECDSA private");
238 buf = load_file("ecdsa_1");
239 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
240 sshbuf_len(buf));
241 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
242 &k1, NULL), 0);
243 sshkey_free(k1);
244 sshbuf_free(buf);
245 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
246 TEST_ONERROR(onerror, fuzz);
247 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
248 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
249 ASSERT_INT_EQ(r, 0);
250 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
251 &k1, NULL) == 0)
252 sshkey_free(k1);
253 sshbuf_reset(fuzzed);
254 }
255 sshbuf_free(fuzzed);
256 fuzz_cleanup(fuzz);
257 TEST_DONE();
258
259 TEST_START("fuzz ECDSA new-format private");
260 buf = load_file("ecdsa_n");
261 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
262 sshbuf_len(buf));
263 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
264 &k1, NULL), 0);
265 sshkey_free(k1);
266 sshbuf_free(buf);
267 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
268 TEST_ONERROR(onerror, fuzz);
269 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
270 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
271 ASSERT_INT_EQ(r, 0);
272 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
273 &k1, NULL) == 0)
274 sshkey_free(k1);
275 sshbuf_reset(fuzzed);
276 }
277 sshbuf_free(fuzzed);
278 fuzz_cleanup(fuzz);
279 TEST_DONE();
280#endif
281
282 TEST_START("fuzz Ed25519 private");
283 buf = load_file("ed25519_1");
284 fuzz = fuzz_begin(FUZZ_BASE64, sshbuf_mutable_ptr(buf),
285 sshbuf_len(buf));
286 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
287 &k1, NULL), 0);
288 sshkey_free(k1);
289 sshbuf_free(buf);
290 ASSERT_PTR_NE(fuzzed = sshbuf_new(), NULL);
291 TEST_ONERROR(onerror, fuzz);
292 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
293 r = sshbuf_put(fuzzed, fuzz_ptr(fuzz), fuzz_len(fuzz));
294 ASSERT_INT_EQ(r, 0);
295 if (sshkey_parse_private_fileblob(fuzzed, "", "key",
296 &k1, NULL) == 0)
297 sshkey_free(k1);
298 sshbuf_reset(fuzzed);
299 }
300 sshbuf_free(fuzzed);
301 fuzz_cleanup(fuzz);
302 TEST_DONE();
303
304 TEST_START("fuzz RSA public");
305 buf = load_file("rsa_1");
306 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
307 &k1, NULL), 0);
308 sshbuf_free(buf);
309 public_fuzz(k1);
310 sshkey_free(k1);
311 TEST_DONE();
312
313 TEST_START("fuzz RSA cert");
314 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
315 public_fuzz(k1);
316 sshkey_free(k1);
317 TEST_DONE();
318
319 TEST_START("fuzz DSA public");
320 buf = load_file("dsa_1");
321 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
322 &k1, NULL), 0);
323 sshbuf_free(buf);
324 public_fuzz(k1);
325 sshkey_free(k1);
326 TEST_DONE();
327
328 TEST_START("fuzz DSA cert");
329 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("dsa_1"), &k1), 0);
330 public_fuzz(k1);
331 sshkey_free(k1);
332 TEST_DONE();
333
334#ifdef OPENSSL_HAS_ECC
335 TEST_START("fuzz ECDSA public");
336 buf = load_file("ecdsa_1");
337 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
338 &k1, NULL), 0);
339 sshbuf_free(buf);
340 public_fuzz(k1);
341 sshkey_free(k1);
342 TEST_DONE();
343
344 TEST_START("fuzz ECDSA cert");
345 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ecdsa_1"), &k1), 0);
346 public_fuzz(k1);
347 sshkey_free(k1);
348 TEST_DONE();
349#endif
350
351 TEST_START("fuzz Ed25519 public");
352 buf = load_file("ed25519_1");
353 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
354 &k1, NULL), 0);
355 sshbuf_free(buf);
356 public_fuzz(k1);
357 sshkey_free(k1);
358 TEST_DONE();
359
360 TEST_START("fuzz Ed25519 cert");
361 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("ed25519_1"), &k1), 0);
362 public_fuzz(k1);
363 sshkey_free(k1);
364 TEST_DONE();
365
366 TEST_START("fuzz RSA sig");
367 buf = load_file("rsa_1");
368 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
369 &k1, NULL), 0);
370 sshbuf_free(buf);
371 sig_fuzz(k1);
372 sshkey_free(k1);
373 TEST_DONE();
374
375 TEST_START("fuzz DSA sig");
376 buf = load_file("dsa_1");
377 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
378 &k1, NULL), 0);
379 sshbuf_free(buf);
380 sig_fuzz(k1);
381 sshkey_free(k1);
382 TEST_DONE();
383
384#ifdef OPENSSL_HAS_ECC
385 TEST_START("fuzz ECDSA sig");
386 buf = load_file("ecdsa_1");
387 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
388 &k1, NULL), 0);
389 sshbuf_free(buf);
390 sig_fuzz(k1);
391 sshkey_free(k1);
392 TEST_DONE();
393#endif
394
395 TEST_START("fuzz Ed25519 sig");
396 buf = load_file("ed25519_1");
397 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "key",
398 &k1, NULL), 0);
399 sshbuf_free(buf);
400 sig_fuzz(k1);
401 sshkey_free(k1);
402 TEST_DONE();
403
404/* XXX fuzz decoded new-format blobs too */
405
406}
diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c
new file mode 100644
index 000000000..ef0c67956
--- /dev/null
+++ b/regress/unittests/sshkey/test_sshkey.c
@@ -0,0 +1,357 @@
1/* $OpenBSD: test_sshkey.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
2/*
3 * Regress test for sshkey.h key management API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14#include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include <openssl/bn.h>
20#include <openssl/rsa.h>
21#include <openssl/dsa.h>
22#ifdef OPENSSL_HAS_NISTP256
23# include <openssl/ec.h>
24#endif
25
26#include "../test_helper/test_helper.h"
27
28#include "ssherr.h"
29#include "sshbuf.h"
30#define SSHBUF_INTERNAL 1 /* access internals for testing */
31#include "sshkey.h"
32
33#include "authfile.h"
34#include "common.h"
35#include "ssh2.h"
36
37void sshkey_tests(void);
38
39static void
40build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
41 const struct sshkey *sign_key, const struct sshkey *ca_key)
42{
43 struct sshbuf *ca_buf, *pk, *principals, *critopts, *exts;
44 u_char *sigblob;
45 size_t siglen;
46
47 ca_buf = sshbuf_new();
48 ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0);
49
50 /*
51 * Get the public key serialisation by rendering the key and skipping
52 * the type string. This is a bit of a hack :/
53 */
54 pk = sshbuf_new();
55 ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0);
56 ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);
57
58 principals = sshbuf_new();
59 ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
60 ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);
61
62 critopts = sshbuf_new();
63 /* XXX fill this in */
64
65 exts = sshbuf_new();
66 /* XXX fill this in */
67
68 ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
69 ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */
70 ASSERT_INT_EQ(sshbuf_putb(b, pk), 0); /* public key serialisation */
71 ASSERT_INT_EQ(sshbuf_put_u64(b, 1234), 0); /* serial */
72 ASSERT_INT_EQ(sshbuf_put_u32(b, SSH2_CERT_TYPE_USER), 0); /* type */
73 ASSERT_INT_EQ(sshbuf_put_cstring(b, "gregor"), 0); /* key ID */
74 ASSERT_INT_EQ(sshbuf_put_stringb(b, principals), 0); /* principals */
75 ASSERT_INT_EQ(sshbuf_put_u64(b, 0), 0); /* start */
76 ASSERT_INT_EQ(sshbuf_put_u64(b, 0xffffffffffffffffULL), 0); /* end */
77 ASSERT_INT_EQ(sshbuf_put_stringb(b, critopts), 0); /* options */
78 ASSERT_INT_EQ(sshbuf_put_stringb(b, exts), 0); /* extensions */
79 ASSERT_INT_EQ(sshbuf_put_string(b, NULL, 0), 0); /* reserved */
80 ASSERT_INT_EQ(sshbuf_put_stringb(b, ca_buf), 0); /* signature key */
81 ASSERT_INT_EQ(sshkey_sign(sign_key, &sigblob, &siglen,
82 sshbuf_ptr(b), sshbuf_len(b), 0), 0);
83 ASSERT_INT_EQ(sshbuf_put_string(b, sigblob, siglen), 0); /* signature */
84
85 free(sigblob);
86 sshbuf_free(ca_buf);
87 sshbuf_free(exts);
88 sshbuf_free(critopts);
89 sshbuf_free(principals);
90 sshbuf_free(pk);
91}
92
93void
94sshkey_tests(void)
95{
96 struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *ke, *kf;
97 struct sshbuf *b;
98
99 TEST_START("new invalid");
100 k1 = sshkey_new(-42);
101 ASSERT_PTR_EQ(k1, NULL);
102 TEST_DONE();
103
104 TEST_START("new/free KEY_UNSPEC");
105 k1 = sshkey_new(KEY_UNSPEC);
106 ASSERT_PTR_NE(k1, NULL);
107 sshkey_free(k1);
108 TEST_DONE();
109
110 TEST_START("new/free KEY_RSA1");
111 k1 = sshkey_new(KEY_RSA1);
112 ASSERT_PTR_NE(k1, NULL);
113 ASSERT_PTR_NE(k1->rsa, NULL);
114 ASSERT_PTR_NE(k1->rsa->n, NULL);
115 ASSERT_PTR_NE(k1->rsa->e, NULL);
116 ASSERT_PTR_EQ(k1->rsa->p, NULL);
117 sshkey_free(k1);
118 TEST_DONE();
119
120 TEST_START("new/free KEY_RSA");
121 k1 = sshkey_new(KEY_RSA);
122 ASSERT_PTR_NE(k1, NULL);
123 ASSERT_PTR_NE(k1->rsa, NULL);
124 ASSERT_PTR_NE(k1->rsa->n, NULL);
125 ASSERT_PTR_NE(k1->rsa->e, NULL);
126 ASSERT_PTR_EQ(k1->rsa->p, NULL);
127 sshkey_free(k1);
128 TEST_DONE();
129
130 TEST_START("new/free KEY_DSA");
131 k1 = sshkey_new(KEY_DSA);
132 ASSERT_PTR_NE(k1, NULL);
133 ASSERT_PTR_NE(k1->dsa, NULL);
134 ASSERT_PTR_NE(k1->dsa->g, NULL);
135 ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
136 sshkey_free(k1);
137 TEST_DONE();
138
139 TEST_START("new/free KEY_ECDSA");
140 k1 = sshkey_new(KEY_ECDSA);
141 ASSERT_PTR_NE(k1, NULL);
142 ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */
143 sshkey_free(k1);
144 TEST_DONE();
145
146 TEST_START("new/free KEY_ED25519");
147 k1 = sshkey_new(KEY_ED25519);
148 ASSERT_PTR_NE(k1, NULL);
149 /* These should be blank until key loaded or generated */
150 ASSERT_PTR_EQ(k1->ed25519_sk, NULL);
151 ASSERT_PTR_EQ(k1->ed25519_pk, NULL);
152 sshkey_free(k1);
153 TEST_DONE();
154
155 TEST_START("new_private KEY_RSA");
156 k1 = sshkey_new_private(KEY_RSA);
157 ASSERT_PTR_NE(k1, NULL);
158 ASSERT_PTR_NE(k1->rsa, NULL);
159 ASSERT_PTR_NE(k1->rsa->n, NULL);
160 ASSERT_PTR_NE(k1->rsa->e, NULL);
161 ASSERT_PTR_NE(k1->rsa->p, NULL);
162 ASSERT_INT_EQ(sshkey_add_private(k1), 0);
163 sshkey_free(k1);
164 TEST_DONE();
165
166 TEST_START("new_private KEY_DSA");
167 k1 = sshkey_new_private(KEY_DSA);
168 ASSERT_PTR_NE(k1, NULL);
169 ASSERT_PTR_NE(k1->dsa, NULL);
170 ASSERT_PTR_NE(k1->dsa->g, NULL);
171 ASSERT_PTR_NE(k1->dsa->priv_key, NULL);
172 ASSERT_INT_EQ(sshkey_add_private(k1), 0);
173 sshkey_free(k1);
174 TEST_DONE();
175
176 TEST_START("generate KEY_RSA too small modulus");
177 ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 128, &k1),
178 SSH_ERR_INVALID_ARGUMENT);
179 ASSERT_PTR_EQ(k1, NULL);
180 TEST_DONE();
181
182 TEST_START("generate KEY_RSA too large modulus");
183 ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 1 << 20, &k1),
184 SSH_ERR_INVALID_ARGUMENT);
185 ASSERT_PTR_EQ(k1, NULL);
186 TEST_DONE();
187
188 TEST_START("generate KEY_DSA wrong bits");
189 ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 2048, &k1),
190 SSH_ERR_INVALID_ARGUMENT);
191 ASSERT_PTR_EQ(k1, NULL);
192 sshkey_free(k1);
193 TEST_DONE();
194
195 TEST_START("generate KEY_ECDSA wrong bits");
196 ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1),
197 SSH_ERR_INVALID_ARGUMENT);
198 ASSERT_PTR_EQ(k1, NULL);
199 sshkey_free(k1);
200 TEST_DONE();
201
202 TEST_START("generate KEY_RSA");
203 ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &kr), 0);
204 ASSERT_PTR_NE(kr, NULL);
205 ASSERT_PTR_NE(kr->rsa, NULL);
206 ASSERT_PTR_NE(kr->rsa->n, NULL);
207 ASSERT_PTR_NE(kr->rsa->e, NULL);
208 ASSERT_PTR_NE(kr->rsa->p, NULL);
209 ASSERT_INT_EQ(BN_num_bits(kr->rsa->n), 768);
210 TEST_DONE();
211
212 TEST_START("generate KEY_DSA");
213 ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &kd), 0);
214 ASSERT_PTR_NE(kd, NULL);
215 ASSERT_PTR_NE(kd->dsa, NULL);
216 ASSERT_PTR_NE(kd->dsa->g, NULL);
217 ASSERT_PTR_NE(kd->dsa->priv_key, NULL);
218 TEST_DONE();
219
220#ifdef OPENSSL_HAS_ECC
221 TEST_START("generate KEY_ECDSA");
222 ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &ke), 0);
223 ASSERT_PTR_NE(ke, NULL);
224 ASSERT_PTR_NE(ke->ecdsa, NULL);
225 ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL);
226 ASSERT_PTR_NE(EC_KEY_get0_private_key(ke->ecdsa), NULL);
227 TEST_DONE();
228#endif
229
230 TEST_START("generate KEY_ED25519");
231 ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &kf), 0);
232 ASSERT_PTR_NE(kf, NULL);
233 ASSERT_INT_EQ(kf->type, KEY_ED25519);
234 ASSERT_PTR_NE(kf->ed25519_pk, NULL);
235 ASSERT_PTR_NE(kf->ed25519_sk, NULL);
236 TEST_DONE();
237
238 TEST_START("demote KEY_RSA");
239 ASSERT_INT_EQ(sshkey_demote(kr, &k1), 0);
240 ASSERT_PTR_NE(k1, NULL);
241 ASSERT_PTR_NE(kr, k1);
242 ASSERT_INT_EQ(k1->type, KEY_RSA);
243 ASSERT_PTR_NE(k1->rsa, NULL);
244 ASSERT_PTR_NE(k1->rsa->n, NULL);
245 ASSERT_PTR_NE(k1->rsa->e, NULL);
246 ASSERT_PTR_EQ(k1->rsa->p, NULL);
247 TEST_DONE();
248
249 TEST_START("equal KEY_RSA/demoted KEY_RSA");
250 ASSERT_INT_EQ(sshkey_equal(kr, k1), 1);
251 sshkey_free(k1);
252 TEST_DONE();
253
254 TEST_START("demote KEY_DSA");
255 ASSERT_INT_EQ(sshkey_demote(kd, &k1), 0);
256 ASSERT_PTR_NE(k1, NULL);
257 ASSERT_PTR_NE(kd, k1);
258 ASSERT_INT_EQ(k1->type, KEY_DSA);
259 ASSERT_PTR_NE(k1->dsa, NULL);
260 ASSERT_PTR_NE(k1->dsa->g, NULL);
261 ASSERT_PTR_EQ(k1->dsa->priv_key, NULL);
262 TEST_DONE();
263
264 TEST_START("equal KEY_DSA/demoted KEY_DSA");
265 ASSERT_INT_EQ(sshkey_equal(kd, k1), 1);
266 sshkey_free(k1);
267 TEST_DONE();
268
269#ifdef OPENSSL_HAS_ECC
270 TEST_START("demote KEY_ECDSA");
271 ASSERT_INT_EQ(sshkey_demote(ke, &k1), 0);
272 ASSERT_PTR_NE(k1, NULL);
273 ASSERT_PTR_NE(ke, k1);
274 ASSERT_INT_EQ(k1->type, KEY_ECDSA);
275 ASSERT_PTR_NE(k1->ecdsa, NULL);
276 ASSERT_INT_EQ(k1->ecdsa_nid, ke->ecdsa_nid);
277 ASSERT_PTR_NE(EC_KEY_get0_public_key(ke->ecdsa), NULL);
278 ASSERT_PTR_EQ(EC_KEY_get0_private_key(k1->ecdsa), NULL);
279 TEST_DONE();
280
281 TEST_START("equal KEY_ECDSA/demoted KEY_ECDSA");
282 ASSERT_INT_EQ(sshkey_equal(ke, k1), 1);
283 sshkey_free(k1);
284 TEST_DONE();
285#endif
286
287 TEST_START("demote KEY_ED25519");
288 ASSERT_INT_EQ(sshkey_demote(kf, &k1), 0);
289 ASSERT_PTR_NE(k1, NULL);
290 ASSERT_PTR_NE(kf, k1);
291 ASSERT_INT_EQ(k1->type, KEY_ED25519);
292 ASSERT_PTR_NE(k1->ed25519_pk, NULL);
293 ASSERT_PTR_EQ(k1->ed25519_sk, NULL);
294 TEST_DONE();
295
296 TEST_START("equal KEY_ED25519/demoted KEY_ED25519");
297 ASSERT_INT_EQ(sshkey_equal(kf, k1), 1);
298 sshkey_free(k1);
299 TEST_DONE();
300
301 TEST_START("equal mismatched key types");
302 ASSERT_INT_EQ(sshkey_equal(kd, kr), 0);
303#ifdef OPENSSL_HAS_ECC
304 ASSERT_INT_EQ(sshkey_equal(kd, ke), 0);
305 ASSERT_INT_EQ(sshkey_equal(kr, ke), 0);
306 ASSERT_INT_EQ(sshkey_equal(ke, kf), 0);
307#endif
308 ASSERT_INT_EQ(sshkey_equal(kd, kf), 0);
309 TEST_DONE();
310
311 TEST_START("equal different keys");
312 ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &k1), 0);
313 ASSERT_INT_EQ(sshkey_equal(kr, k1), 0);
314 sshkey_free(k1);
315 ASSERT_INT_EQ(sshkey_generate(KEY_DSA, 1024, &k1), 0);
316 ASSERT_INT_EQ(sshkey_equal(kd, k1), 0);
317 sshkey_free(k1);
318#ifdef OPENSSL_HAS_ECC
319 ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 256, &k1), 0);
320 ASSERT_INT_EQ(sshkey_equal(ke, k1), 0);
321 sshkey_free(k1);
322#endif
323 ASSERT_INT_EQ(sshkey_generate(KEY_ED25519, 256, &k1), 0);
324 ASSERT_INT_EQ(sshkey_equal(kf, k1), 0);
325 sshkey_free(k1);
326 TEST_DONE();
327
328 sshkey_free(kr);
329 sshkey_free(kd);
330#ifdef OPENSSL_HAS_ECC
331 sshkey_free(ke);
332#endif
333 sshkey_free(kf);
334
335/* XXX certify test */
336/* XXX sign test */
337/* XXX verify test */
338
339 TEST_START("nested certificate");
340 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
341 ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
342 NULL), 0);
343 b = load_file("rsa_2");
344 ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", "rsa_1",
345 &k3, NULL), 0);
346 sshbuf_reset(b);
347 build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1);
348 ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
349 SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
350 ASSERT_PTR_EQ(k4, NULL);
351 sshbuf_free(b);
352 sshkey_free(k1);
353 sshkey_free(k2);
354 sshkey_free(k3);
355 TEST_DONE();
356
357}
diff --git a/regress/unittests/sshkey/testdata/dsa_1 b/regress/unittests/sshkey/testdata/dsa_1
new file mode 100644
index 000000000..34346869f
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1
@@ -0,0 +1,12 @@
1-----BEGIN DSA PRIVATE KEY-----
2MIIBuwIBAAKBgQCxBNwH8TmLXqiZa0b9pxC6W+zS4Voqp8S+QwecYpNPTmhjaUYI
3E/aJWAzFVtdbysLM89ukvw/z8qBkbMSefdypKmjUtgv51ZD4nfV4Wxb+G+1QExHr
4M+kowOOL3XbcsdbPLUt8vxDJbBlQRch4zyai7CWjQR3JFXpR8sevUFJxSQIVAIdE
5oncp2DEY2U/ZZnIyGCwApCzfAoGARW+eewZTv1Eosxv3ANKx372pf5+fQKwnWizI
6j5z/GY3w3xobRCP9FiL4K3Nip2FvHLTGpRrlfm19RWYAg77VsNgztC4V9C8QrKWc
7WJdkUkoQpZ3VoO25rO13hmIelkal3omKCF4ZE/edeF3d2B8DlzYs0aBcjTCMDrub
8/CJILcYCgYEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j
94hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1
10/EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gCFBl7Lc6V
11hmTiTuhLXjoRdCZS/p/m
12-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/regress/unittests/sshkey/testdata/dsa_1-cert.fp
new file mode 100644
index 000000000..56ee1f89b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1-cert.fp
@@ -0,0 +1 @@
5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.pub b/regress/unittests/sshkey/testdata/dsa_1-cert.pub
new file mode 100644
index 000000000..023edf136
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1-cert.pub
@@ -0,0 +1 @@
ssh-dss-cert-v01@openssh.com AAAAHHNzaC1kc3MtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgj8zueN51MSQ7jW3fFwqyJWA3DycAAavQ8WgMHqcUG7YAAACBALEE3AfxOYteqJlrRv2nELpb7NLhWiqnxL5DB5xik09OaGNpRggT9olYDMVW11vKwszz26S/D/PyoGRsxJ593KkqaNS2C/nVkPid9XhbFv4b7VATEesz6SjA44vddtyx1s8tS3y/EMlsGVBFyHjPJqLsJaNBHckVelHyx69QUnFJAAAAFQCHRKJ3KdgxGNlP2WZyMhgsAKQs3wAAAIBFb557BlO/USizG/cA0rHfval/n59ArCdaLMiPnP8ZjfDfGhtEI/0WIvgrc2KnYW8ctMalGuV+bX1FZgCDvtWw2DO0LhX0LxCspZxYl2RSShClndWg7bms7XeGYh6WRqXeiYoIXhkT9514Xd3YHwOXNizRoFyNMIwOu5v8IkgtxgAAAIEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1/EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gAAAAAAAAABgAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAEA6qftqozw0ah9PG9obAg8iOPwQv6AsT9t/1G69eArSd9Am85OKIhAvYguI1Xtr9rw78X/Xk+6HtyAOF3QemaQD dsa_1.pub
diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp b/regress/unittests/sshkey/testdata/dsa_1.fp
new file mode 100644
index 000000000..56ee1f89b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.fp
@@ -0,0 +1 @@
5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74
diff --git a/regress/unittests/sshkey/testdata/dsa_1.fp.bb b/regress/unittests/sshkey/testdata/dsa_1.fp.bb
new file mode 100644
index 000000000..07dd9b418
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.fp.bb
@@ -0,0 +1 @@
xosat-baneh-gocad-relek-kepur-mibip-motog-bykyb-hisug-mysus-tuxix
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.g b/regress/unittests/sshkey/testdata/dsa_1.param.g
new file mode 100644
index 000000000..4b09f6d18
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.param.g
@@ -0,0 +1 @@
456f9e7b0653bf5128b31bf700d2b1dfbda97f9f9f40ac275a2cc88f9cff198df0df1a1b4423fd1622f82b7362a7616f1cb4c6a51ae57e6d7d45660083bed5b0d833b42e15f42f10aca59c589764524a10a59dd5a0edb9aced7786621e9646a5de898a085e1913f79d785dddd81f0397362cd1a05c8d308c0ebb9bfc22482dc6
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.priv b/regress/unittests/sshkey/testdata/dsa_1.param.priv
new file mode 100644
index 000000000..2dd737cbe
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.param.priv
@@ -0,0 +1 @@
197b2dce958664e24ee84b5e3a11742652fe9fe6
diff --git a/regress/unittests/sshkey/testdata/dsa_1.param.pub b/regress/unittests/sshkey/testdata/dsa_1.param.pub
new file mode 100644
index 000000000..b23d7207f
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.param.pub
@@ -0,0 +1 @@
00809b7d8de7c6422e1297917c8778d8a39d8bca013cb0d632bab12530a566ca1152289d487e2f63e21369da3673bbb8e96568589dd5283da1ba81b441edf2f7a79927951a373f60f39ddeaee8d01d86b003596f895fd9f5fc430a52fd21f2b44523fddbf516351d55730501fb577b0d27a89e907f09a8ecb596208c68cca5c388
diff --git a/regress/unittests/sshkey/testdata/dsa_1.pub b/regress/unittests/sshkey/testdata/dsa_1.pub
new file mode 100644
index 000000000..89681970c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1.pub
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBALEE3AfxOYteqJlrRv2nELpb7NLhWiqnxL5DB5xik09OaGNpRggT9olYDMVW11vKwszz26S/D/PyoGRsxJ593KkqaNS2C/nVkPid9XhbFv4b7VATEesz6SjA44vddtyx1s8tS3y/EMlsGVBFyHjPJqLsJaNBHckVelHyx69QUnFJAAAAFQCHRKJ3KdgxGNlP2WZyMhgsAKQs3wAAAIBFb557BlO/USizG/cA0rHfval/n59ArCdaLMiPnP8ZjfDfGhtEI/0WIvgrc2KnYW8ctMalGuV+bX1FZgCDvtWw2DO0LhX0LxCspZxYl2RSShClndWg7bms7XeGYh6WRqXeiYoIXhkT9514Xd3YHwOXNizRoFyNMIwOu5v8IkgtxgAAAIEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j4hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1/EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4g= DSA test key #1
diff --git a/regress/unittests/sshkey/testdata/dsa_1_pw b/regress/unittests/sshkey/testdata/dsa_1_pw
new file mode 100644
index 000000000..1402153a0
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_1_pw
@@ -0,0 +1,15 @@
1-----BEGIN DSA PRIVATE KEY-----
2Proc-Type: 4,ENCRYPTED
3DEK-Info: AES-128-CBC,9E668E24E7B9D658E3E7D0446B32B376
4
5hDjDLbfCAQutblxLuyNzSLxISSgXTgyzq8St9GE0lUtEc7i0xGNWwoWpFSbtD9y1
6yTG5UkhATQt56SY1ABfXZ21wieYuEEQeSJi0gwUQNNt2SwwITx4EdzDedWiHjikt
7jbzH3v33agp/odw2X9wY6zu75y9CeW9o7SszRl286DliWIHJmhMlbb8r7jRqu62H
8s5YYxD0xS1ipWauxklmIXMWNZHcARo8ZiJOuNdLshrSrl8DUW9P6F89FvxclQzKr
944u3OBm7KbgPvPURDFLgNP6uCGBjzHvhHTpzVBxmQzCl3aGgsTKXiwJ1eupNjntB
10ji0EnbznvoxR6qhXxw/WQ+MnWlWqTXka/2qaB6m3oJv+Zn7cPCJ5kvHnhr2JmNMl
11igTh4Ov4LZLyNgO0Lbec4KyxW9QInRV5CY4Pu5lhqHteiPmOIGMWFtuh8Bb8Kg2q
12VvXnPo5I3FjqV7UhDduO1Wn558sBZWQPqRbHVPN6wXJuM3HGkBl+aNjn0qddv9tr
13VFJd/xdly2Ne81g3CB8jysE+3WEOrV9kdybocp/EhSOzP4i6pjWlyWdR5+CgbvRm
14TUIeIaQbmPIB5251o5YK+Q==
15-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_2 b/regress/unittests/sshkey/testdata/dsa_2
new file mode 100644
index 000000000..b189dc821
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2
@@ -0,0 +1,12 @@
1-----BEGIN DSA PRIVATE KEY-----
2MIIBuwIBAAKBgQDoMxCTyBnLPSO7CRU3RyfJLANLKBZ3/LdcsyNaARctaRA5gzRb
3XdTFFU+rWKfxv+otm0KyCOepLtWy8tjKRYb7Ni46USlGwtM0Adx/3vR4iWNfipDP
4K2V4O97JyMe3wsbF7siC01U4b8Ki+J44iFG9nuRnOTHqUWI615mraQRwlQIVAMsX
5nsPGH8QrU11F1ScAIfZC165dAoGACCXyOHFkxABpJDtJs6AE7Hl3XjI4dnlim/XH
6Y60W6gcO7gHSE2r2ljCubJqoUXmxd5mLKgnu91jIG/4URwDM4V7pb2k99sXpAi8I
7L52eQl88C0bRD9+lEJfR4PMT39EccDRPB4+E055RoYQZ/McIyad8sF3Qwt084Eq+
8IkUt2coCgYEAxZRpCY82sM9Mu4B0EcH6O8seRqIRScmelljhUtKxuvf2PChwIWkR
9HK9lORHBE3iKyurC5Muf3abuHKwMFjrOjHKOTqXBRrDZ7RgLQA0aUAQD3lWc9OTP
10NShjphpq5xr0HZB31eJg3/Mo6KxYlRpzMXbTyenZP0XLICSSAywvTDoCFG5whl2k
11Y2FLGfi9V6ylUVH6jKgE
12-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp b/regress/unittests/sshkey/testdata/dsa_2.fp
new file mode 100644
index 000000000..ba9de82a8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2.fp
@@ -0,0 +1 @@
72:5f:50:6b:e5:64:c5:62:21:92:3f:8b:10:9b:9f:1a
diff --git a/regress/unittests/sshkey/testdata/dsa_2.fp.bb b/regress/unittests/sshkey/testdata/dsa_2.fp.bb
new file mode 100644
index 000000000..37a5221a7
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2.fp.bb
@@ -0,0 +1 @@
xesoh-mebaf-feced-lenuz-sicam-pevok-bosak-nogaz-ligen-fekef-fixex
diff --git a/regress/unittests/sshkey/testdata/dsa_2.pub b/regress/unittests/sshkey/testdata/dsa_2.pub
new file mode 100644
index 000000000..6ed2736b1
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_2.pub
@@ -0,0 +1 @@
ssh-dss AAAAB3NzaC1kc3MAAACBAOgzEJPIGcs9I7sJFTdHJ8ksA0soFnf8t1yzI1oBFy1pEDmDNFtd1MUVT6tYp/G/6i2bQrII56ku1bLy2MpFhvs2LjpRKUbC0zQB3H/e9HiJY1+KkM8rZXg73snIx7fCxsXuyILTVThvwqL4njiIUb2e5Gc5MepRYjrXmatpBHCVAAAAFQDLF57Dxh/EK1NdRdUnACH2QteuXQAAAIAIJfI4cWTEAGkkO0mzoATseXdeMjh2eWKb9cdjrRbqBw7uAdITavaWMK5smqhRebF3mYsqCe73WMgb/hRHAMzhXulvaT32xekCLwgvnZ5CXzwLRtEP36UQl9Hg8xPf0RxwNE8Hj4TTnlGhhBn8xwjJp3ywXdDC3TzgSr4iRS3ZygAAAIEAxZRpCY82sM9Mu4B0EcH6O8seRqIRScmelljhUtKxuvf2PChwIWkRHK9lORHBE3iKyurC5Muf3abuHKwMFjrOjHKOTqXBRrDZ7RgLQA0aUAQD3lWc9OTPNShjphpq5xr0HZB31eJg3/Mo6KxYlRpzMXbTyenZP0XLICSSAywvTDo= DSA test key #2
diff --git a/regress/unittests/sshkey/testdata/dsa_n b/regress/unittests/sshkey/testdata/dsa_n
new file mode 100644
index 000000000..34346869f
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_n
@@ -0,0 +1,12 @@
1-----BEGIN DSA PRIVATE KEY-----
2MIIBuwIBAAKBgQCxBNwH8TmLXqiZa0b9pxC6W+zS4Voqp8S+QwecYpNPTmhjaUYI
3E/aJWAzFVtdbysLM89ukvw/z8qBkbMSefdypKmjUtgv51ZD4nfV4Wxb+G+1QExHr
4M+kowOOL3XbcsdbPLUt8vxDJbBlQRch4zyai7CWjQR3JFXpR8sevUFJxSQIVAIdE
5oncp2DEY2U/ZZnIyGCwApCzfAoGARW+eewZTv1Eosxv3ANKx372pf5+fQKwnWizI
6j5z/GY3w3xobRCP9FiL4K3Nip2FvHLTGpRrlfm19RWYAg77VsNgztC4V9C8QrKWc
7WJdkUkoQpZ3VoO25rO13hmIelkal3omKCF4ZE/edeF3d2B8DlzYs0aBcjTCMDrub
8/CJILcYCgYEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j
94hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1
10/EMKUv0h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gCFBl7Lc6V
11hmTiTuhLXjoRdCZS/p/m
12-----END DSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/dsa_n_pw b/regress/unittests/sshkey/testdata/dsa_n_pw
new file mode 100644
index 000000000..42f70dd23
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/dsa_n_pw
@@ -0,0 +1,22 @@
1-----BEGIN OPENSSH PRIVATE KEY-----
2b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABD5nB+Nkw
3LNoPtAG7C3IdXmAAAAEAAAAAEAAAGyAAAAB3NzaC1kc3MAAACBALEE3AfxOYteqJlrRv2n
4ELpb7NLhWiqnxL5DB5xik09OaGNpRggT9olYDMVW11vKwszz26S/D/PyoGRsxJ593KkqaN
5S2C/nVkPid9XhbFv4b7VATEesz6SjA44vddtyx1s8tS3y/EMlsGVBFyHjPJqLsJaNBHckV
6elHyx69QUnFJAAAAFQCHRKJ3KdgxGNlP2WZyMhgsAKQs3wAAAIBFb557BlO/USizG/cA0r
7Hfval/n59ArCdaLMiPnP8ZjfDfGhtEI/0WIvgrc2KnYW8ctMalGuV+bX1FZgCDvtWw2DO0
8LhX0LxCspZxYl2RSShClndWg7bms7XeGYh6WRqXeiYoIXhkT9514Xd3YHwOXNizRoFyNMI
9wOu5v8IkgtxgAAAIEAgJt9jefGQi4Sl5F8h3jYo52LygE8sNYyurElMKVmyhFSKJ1Ifi9j
104hNp2jZzu7jpZWhYndUoPaG6gbRB7fL3p5knlRo3P2Dznd6u6NAdhrADWW+JX9n1/EMKUv
110h8rRFI/3b9RY1HVVzBQH7V3sNJ6iekH8JqOy1liCMaMylw4gAAAHw8P1DtkBulOGv85qf
12P+md2+LL+NKufVzHl9k2UKQFjeqY6uqs4HSDqvhXe7oiXd5mz6I7orxjtKU9hGjNF4ABUD
13OawVGe/GCRUQ4WgpAgDnqQLeFcdIwtMSIrRZU6xjs314EI7TM7IIiG26JEuXDfZI1e7C3y
14Cc38ZsP3zmg/UjgcCQar5c4n++vhOmeO36+fcUyZ1QlR05SaEtFYJA+otP3RmKTiDwob8Q
15zRMr8Y57i2NTTtFjkmnnnQCibP62yz7N22Dve7RTOH8jiaW7p02Vn/6WmCarevN1rxtLLR
16lkuWtPoKY8z/Ktcev8YE9f2+9H2TfXDRKYqIEfxgZLCJ4yP2gxDe6zurabS0hAO1CP+ej5
17htdJM3/rTqHAIevXX5uhIDmMvRHnLGldaIX1xux8TIJvSfMkYNIwscIP4kx7BGMk04vXtW
185DLm6IZhzw9T3hjr8R0kBugmT6/h9vD5iN1D+wiHIhHYzQKMU9nOeFNsMBFWgJjU0l8VlF
19gEjEMgAEfwynnmIoKB1iA/0em1tdU3naS59DBK+buE0trxUpTAAB5z8yPhAm6DdqrPE8cA
20N3HlMoWrbCuak2A0uyOlEJjPg4UJUnv12ve2c9pAMsAu/4CAszCEM0prR+qd/RA4nn4M5u
21Xrny2wNtt/DybCkA==
22-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1 b/regress/unittests/sshkey/testdata/ecdsa_1
new file mode 100644
index 000000000..aec73dd61
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1
@@ -0,0 +1,5 @@
1-----BEGIN EC PRIVATE KEY-----
2MHcCAQEEIFghsFR1K95tz8qOl3+tX6fv8a/O6AfNbxOSFZX3ihxooAoGCCqGSM49
3AwEHoUQDQgAEalpgP0BOePHtTw0Pus4tdhTb8P9yWUZluvLf1D8vrHImT+G4vr/W
4xo5iXGKQVEifuUVyLkAW2kDrq8J/szeRiQ==
5-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
new file mode 100644
index 000000000..a56dbc8d0
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
@@ -0,0 +1 @@
f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub
new file mode 100644
index 000000000..29b06a4dd
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1-cert.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp256-cert-v01@openssh.com AAAAKGVjZHNhLXNoYTItbmlzdHAyNTYtY2VydC12MDFAb3BlbnNzaC5jb20AAAAgjpoHehzmM54xz776HOiTOLPhkOwSWyXOMYeqDhDEcLgAAAAIbmlzdHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYlxikFRIn7lFci5AFtpA66vCf7M3kYkAAAAAAAAABwAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYlxikFRIn7lFci5AFtpA66vCf7M3kYkAAABjAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAABIAAAAIFZM1PXlXf0a3VuGs7MVdWSealDXprT1nN5hQTg+m+EYAAAAIGN1yNXWEY5V315NhOD3mBuh/xCpfDn5rZjF4YntA7du ecdsa_1.pub
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp b/regress/unittests/sshkey/testdata/ecdsa_1.fp
new file mode 100644
index 000000000..a56dbc8d0
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp
@@ -0,0 +1 @@
f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb
new file mode 100644
index 000000000..f01a5dd44
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.fp.bb
@@ -0,0 +1 @@
xotah-hecal-zibyb-nadug-romuc-hator-venum-hobip-ruluh-ripus-naxix
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.curve b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve
new file mode 100644
index 000000000..fa0400467
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.curve
@@ -0,0 +1 @@
prime256v1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.priv b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv
new file mode 100644
index 000000000..3475f1fe9
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.priv
@@ -0,0 +1 @@
5821b054752bde6dcfca8e977fad5fa7eff1afcee807cd6f13921595f78a1c68
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.param.pub b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub
new file mode 100644
index 000000000..11847a394
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.param.pub
@@ -0,0 +1 @@
046a5a603f404e78f1ed4f0d0fbace2d7614dbf0ff72594665baf2dfd43f2fac72264fe1b8bebfd6c68e625c629054489fb945722e4016da40ebabc27fb3379189
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1.pub b/regress/unittests/sshkey/testdata/ecdsa_1.pub
new file mode 100644
index 000000000..eca1620bc
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYlxikFRIn7lFci5AFtpA66vCf7M3kYk= ECDSA test key #1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_1_pw b/regress/unittests/sshkey/testdata/ecdsa_1_pw
new file mode 100644
index 000000000..071154ab2
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_1_pw
@@ -0,0 +1,8 @@
1-----BEGIN EC PRIVATE KEY-----
2Proc-Type: 4,ENCRYPTED
3DEK-Info: AES-128-CBC,74C8AEA5BFAFCC2B1C8B13DE671F5610
4
5vUsgOvCqezxPmcZcFqrSy9Y1MMlVguY0h9cfSPFC7gUrRr+45uCOYX5bOwEXecKn
6/9uCXZtlBwwqDS9iK5IPoUrjEHvzI5rVbHWUxDrEOVbsfiDuCxrQM19It6QIqC1v
7OSQEdXuBWR5WmhKNc3dqLbWsU8u2s60YwKQmZrj9nM4=
8-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2 b/regress/unittests/sshkey/testdata/ecdsa_2
new file mode 100644
index 000000000..76ae07ad4
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2
@@ -0,0 +1,7 @@
1-----BEGIN EC PRIVATE KEY-----
2MIHcAgEBBEIBg4kVxUfoo/RE/78/QBRqG6PZuHZ82eLnhmZVzBa7XREUiYI/Jw7r
3Qwp4FTBVfXL76Pt5AyBMf+52aVeOUlLRERSgBwYFK4EEACOhgYkDgYYABACNTJ5O
4uNo5dNgIQRLHzKU91m7immKFiutJ6BlDbkRkKr+Envj13J6HOgYvOTm0n7SPlKHS
5STZ4/T36d/rzQOAbIwEnbbwD9HMj6IzE4WH9lJzH7Zy7Tcyu6dOM8L7nOxCp3DUk
6F3aAnPSFJhD7NN0jBWOFsD6uy1OmaTklPfRAnCt1MQ==
7-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp b/regress/unittests/sshkey/testdata/ecdsa_2.fp
new file mode 100644
index 000000000..eb4bbdf03
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp
@@ -0,0 +1 @@
51:bd:ff:2b:6d:26:9b:90:f9:e1:4a:ca:a0:29:8e:70
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb
new file mode 100644
index 000000000..267bc63fd
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.fp.bb
@@ -0,0 +1 @@
xuzaz-zuzuk-virop-vypah-zumel-gylak-selih-fevad-varag-zynif-haxox
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.curve b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve
new file mode 100644
index 000000000..617ea2fb8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.curve
@@ -0,0 +1 @@
secp521r1
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.priv b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv
new file mode 100644
index 000000000..537cdaac3
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.priv
@@ -0,0 +1 @@
01838915c547e8a3f444ffbf3f40146a1ba3d9b8767cd9e2e7866655cc16bb5d111489823f270eeb430a781530557d72fbe8fb7903204c7fee7669578e5252d11114
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.param.pub b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub
new file mode 100644
index 000000000..3352ac769
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.param.pub
@@ -0,0 +1 @@
04008d4c9e4eb8da3974d8084112c7cca53dd66ee29a62858aeb49e819436e44642abf849ef8f5dc9e873a062f3939b49fb48f94a1d2493678fd3dfa77faf340e01b2301276dbc03f47323e88cc4e161fd949cc7ed9cbb4dccaee9d38cf0bee73b10a9dc35241776809cf4852610fb34dd23056385b03eaecb53a66939253df4409c2b7531
diff --git a/regress/unittests/sshkey/testdata/ecdsa_2.pub b/regress/unittests/sshkey/testdata/ecdsa_2.pub
new file mode 100644
index 000000000..34e1881dd
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_2.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBACNTJ5OuNo5dNgIQRLHzKU91m7immKFiutJ6BlDbkRkKr+Envj13J6HOgYvOTm0n7SPlKHSSTZ4/T36d/rzQOAbIwEnbbwD9HMj6IzE4WH9lJzH7Zy7Tcyu6dOM8L7nOxCp3DUkF3aAnPSFJhD7NN0jBWOFsD6uy1OmaTklPfRAnCt1MQ== ECDSA test key #2
diff --git a/regress/unittests/sshkey/testdata/ecdsa_n b/regress/unittests/sshkey/testdata/ecdsa_n
new file mode 100644
index 000000000..aec73dd61
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_n
@@ -0,0 +1,5 @@
1-----BEGIN EC PRIVATE KEY-----
2MHcCAQEEIFghsFR1K95tz8qOl3+tX6fv8a/O6AfNbxOSFZX3ihxooAoGCCqGSM49
3AwEHoUQDQgAEalpgP0BOePHtTw0Pus4tdhTb8P9yWUZluvLf1D8vrHImT+G4vr/W
4xo5iXGKQVEifuUVyLkAW2kDrq8J/szeRiQ==
5-----END EC PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ecdsa_n_pw b/regress/unittests/sshkey/testdata/ecdsa_n_pw
new file mode 100644
index 000000000..75d585908
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ecdsa_n_pw
@@ -0,0 +1,9 @@
1-----BEGIN OPENSSH PRIVATE KEY-----
2b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABBXqI6Z6o
3uRM+jAwdhnDoIMAAAAEAAAAAEAAABoAAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlz
4dHAyNTYAAABBBGpaYD9ATnjx7U8ND7rOLXYU2/D/cllGZbry39Q/L6xyJk/huL6/1saOYl
5xikFRIn7lFci5AFtpA66vCf7M3kYkAAACwYMnoCTqvUTG0ktSSMNsOZLCdal5J4avEpM1L
6sV9SL/RVcwo3ChprhwsnQsaAtMiJCRcHerKgD9qy1MNNaE5VNfVJ0Ih/7ut04cbFKed8p6
70V+w8WP7WvFffBPoHn+GGbQd1FDGzHhXUB61pH8Qzd1bI/sld/XEtMk7iYjNGQe9Rt0RaK
8Wi8trwaA0Fb2w/EFnrdsFFxrIhQEqYBdEQJo782IqAsMG9OwUaM0vy+8bcI=
9-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_1 b/regress/unittests/sshkey/testdata/ed25519_1
new file mode 100644
index 000000000..a537ae13d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1
@@ -0,0 +1,7 @@
1-----BEGIN OPENSSH PRIVATE KEY-----
2b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
3QyNTUxOQAAACC5PeVeSdyylcfG3C0geNO90e3dGgL0fICaz751dA9zEAAAAJglsAcYJbAH
4GAAAAAtzc2gtZWQyNTUxOQAAACC5PeVeSdyylcfG3C0geNO90e3dGgL0fICaz751dA9zEA
5AAAED6HJ8Bh8tdQvhMd5o8IxtIwBv8/FV48FpBFWAbYdsIsLk95V5J3LKVx8bcLSB4073R
67d0aAvR8gJrPvnV0D3MQAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg==
7-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
new file mode 100644
index 000000000..e6d23d0b8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
@@ -0,0 +1 @@
19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f
diff --git a/regress/unittests/sshkey/testdata/ed25519_1-cert.pub b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub
new file mode 100644
index 000000000..ad0b9a888
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1-cert.pub
@@ -0,0 +1 @@
ssh-ed25519-cert-v01@openssh.com AAAAIHNzaC1lZDI1NTE5LWNlcnQtdjAxQG9wZW5zc2guY29tAAAAIHmdL66MkkOvncpc0W4MdvlJZMfQthHiOUv+XKm7gvzOAAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQAAAAAAAAAAgAAAACAAAABmp1bGl1cwAAABIAAAAFaG9zdDEAAAAFaG9zdDIAAAAANouDYAAAAABNHeHgAAAAAAAAAAAAAAAAAAAAMwAAAAtzc2gtZWQyNTUxOQAAACC5PeVeSdyylcfG3C0geNO90e3dGgL0fICaz751dA9zEAAAAFMAAAALc3NoLWVkMjU1MTkAAABAsUStKm1z3Rtvwy3eXE1DrgVp6kix2iEQXfB66IHX2UpAj5yl0eQGXWTSEDIxHDIb0SJvUH43OWX0PrEeAs0mAA== ed25519_1.pub
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp b/regress/unittests/sshkey/testdata/ed25519_1.fp
new file mode 100644
index 000000000..e6d23d0b8
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1.fp
@@ -0,0 +1 @@
19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.fp.bb b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb
new file mode 100644
index 000000000..591a711b4
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1.fp.bb
@@ -0,0 +1 @@
xofip-nuhoh-botam-cypeg-panig-tunef-bimav-numeb-nikic-gocyf-paxax
diff --git a/regress/unittests/sshkey/testdata/ed25519_1.pub b/regress/unittests/sshkey/testdata/ed25519_1.pub
new file mode 100644
index 000000000..633e05077
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQ ED25519 test key #1
diff --git a/regress/unittests/sshkey/testdata/ed25519_1_pw b/regress/unittests/sshkey/testdata/ed25519_1_pw
new file mode 100644
index 000000000..9fc635208
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_1_pw
@@ -0,0 +1,8 @@
1-----BEGIN OPENSSH PRIVATE KEY-----
2b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABAlT1eewp
39gl0gue+sSrBWKAAAAEAAAAAEAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bc
4LSB4073R7d0aAvR8gJrPvnV0D3MQAAAAoMrL9ixIQHoJ86DcKMGt26+bCeaoyGjW5hha2Y
5IxAZ+rRvNjUuv3MGvbUxtUpPZkTP/vk2fVSCuCD9St5Lbt/LKdIk2MfWIFbjZ6iEfdzxz0
6DHmsSDMps8dbePqqIPULR8av447jEzQEkUc8GSR6WqFSJOjJ8OvrJat1KcEK7V2tjZnLS1
7GoLMqVAtCVhuXwUkeJiRQE/JRl172hxB+LAVw=
8-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_2 b/regress/unittests/sshkey/testdata/ed25519_2
new file mode 100644
index 000000000..a6e5f0040
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2
@@ -0,0 +1,7 @@
1-----BEGIN OPENSSH PRIVATE KEY-----
2b3BlbnNzaC1rZXktdjEAAAAABG5vbmUAAAAEbm9uZQAAAAAAAAABAAAAMwAAAAtzc2gtZW
3QyNTUxOQAAACBXUfO5Kid+jhRnyVt+1r9wj2FN/mZ6RfgGdySeYoq4WAAAAJjGeKsZxnir
4GQAAAAtzc2gtZWQyNTUxOQAAACBXUfO5Kid+jhRnyVt+1r9wj2FN/mZ6RfgGdySeYoq4WA
5AAAEB+gn4gGClQl2WMeOkikY+w0A0kSw1KH4Oyami7hlypsFdR87kqJ36OFGfJW37Wv3CP
6YU3+ZnpF+AZ3JJ5iirhYAAAAE0VEMjU1MTkgdGVzdCBrZXkgIzEBAg==
7-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp b/regress/unittests/sshkey/testdata/ed25519_2.fp
new file mode 100644
index 000000000..02c684f36
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2.fp
@@ -0,0 +1 @@
5c:c9:ae:a3:0c:aa:28:29:b8:fc:7c:64:ba:6e:e9:c9
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.fp.bb b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb
new file mode 100644
index 000000000..ebe782e2c
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2.fp.bb
@@ -0,0 +1 @@
xenoz-tovup-zecyt-hohar-motam-sugid-fecyz-tutyk-gosom-ginar-kixux
diff --git a/regress/unittests/sshkey/testdata/ed25519_2.pub b/regress/unittests/sshkey/testdata/ed25519_2.pub
new file mode 100644
index 000000000..37b93352a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/ed25519_2.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIFdR87kqJ36OFGfJW37Wv3CPYU3+ZnpF+AZ3JJ5iirhY ED25519 test key #1
diff --git a/regress/unittests/sshkey/testdata/pw b/regress/unittests/sshkey/testdata/pw
new file mode 100644
index 000000000..8a1dff98a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/pw
@@ -0,0 +1 @@
mekmitasdigoat
diff --git a/regress/unittests/sshkey/testdata/rsa1_1 b/regress/unittests/sshkey/testdata/rsa1_1
new file mode 100644
index 000000000..d22014e88
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_1
Binary files differ
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.fp b/regress/unittests/sshkey/testdata/rsa1_1.fp
new file mode 100644
index 000000000..782ece0db
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_1.fp
@@ -0,0 +1 @@
a8:82:9b:98:c5:e6:19:d6:83:39:9f:4d:3a:8f:7c:80
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.fp.bb b/regress/unittests/sshkey/testdata/rsa1_1.fp.bb
new file mode 100644
index 000000000..caaf9511a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_1.fp.bb
@@ -0,0 +1 @@
xukib-cymuf-mylib-kecih-rogyb-sorid-belys-kytem-dinin-cicil-kyxex
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.param.n b/regress/unittests/sshkey/testdata/rsa1_1.param.n
new file mode 100644
index 000000000..4ceb37362
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_1.param.n
@@ -0,0 +1 @@
00cf68059e5c7743318d740d3ebb55eb577891c9c3098817703f4c3157285055c2daa50102509ebdcade324e541c965e2931fd3459052fe65d013722da805d7ec8ef5b97cc006789d0566c5578b23e7aaa5be2b055d85798030cdead2eb2cc4eb3
diff --git a/regress/unittests/sshkey/testdata/rsa1_1.pub b/regress/unittests/sshkey/testdata/rsa1_1.pub
new file mode 100644
index 000000000..56cf30d30
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_1.pub
@@ -0,0 +1 @@
768 65537 1257820658919101781627826212425999371251377782154008557690434337796299274692579921603319269571889066123773172648045269780061837011867522525764583065919572648969392756890567918758763032103894830246827894023662422727333291801518558899 RSA1 test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa1_1_pw b/regress/unittests/sshkey/testdata/rsa1_1_pw
new file mode 100644
index 000000000..3113dbc0f
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_1_pw
Binary files differ
diff --git a/regress/unittests/sshkey/testdata/rsa1_2 b/regress/unittests/sshkey/testdata/rsa1_2
new file mode 100644
index 000000000..e75e665ff
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_2
Binary files differ
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.fp b/regress/unittests/sshkey/testdata/rsa1_2.fp
new file mode 100644
index 000000000..c3325371d
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_2.fp
@@ -0,0 +1 @@
c0:83:1c:97:5f:32:77:7e:e4:e3:e9:29:b9:eb:76:9c
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.fp.bb b/regress/unittests/sshkey/testdata/rsa1_2.fp.bb
new file mode 100644
index 000000000..cd8037140
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_2.fp.bb
@@ -0,0 +1 @@
xifad-vevot-sozyl-fapeb-meryf-kylut-cydiv-firik-gavyb-lanad-kaxox
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.param.n b/regress/unittests/sshkey/testdata/rsa1_2.param.n
new file mode 100644
index 000000000..f8143a4b9
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_2.param.n
@@ -0,0 +1 @@
00b08a9fa386aceaab2ec3e9cdc7e6cb4eac9e98620279eed6762e1f513739a417ac8a86231fad3b8727a9de994973a7aae674a132547341984ade91aa1c22f01d2f0204ea7fa121969c367a5d04bda384066cf94e0b56d1efc47f50ca28e90603547df41c0676550d82d369f699b457d4f0f077999d9e76ab679fbf4206d418dbabed1823f14e4ddf3aac987686e6b006f8a23ea6af13b4c0e5b1fb5b1eb4db2f47b229422c450574cae9c64db5dcfce050836b6bdfa8fb541b4d426444a5ea20ad51a25d3048414ced2e199da2997968273e8beb10f3a351e98a57b00dadfa8f00a39bb55be94dae898fda6021d728f32b2ec93edd16e51073be3ac7511e5085
diff --git a/regress/unittests/sshkey/testdata/rsa1_2.pub b/regress/unittests/sshkey/testdata/rsa1_2.pub
new file mode 100644
index 000000000..de1afbb8b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa1_2.pub
@@ -0,0 +1 @@
2048 65537 22286299513474010485021611215236051675183880694440075228245854420062562171290421803318459093678819161498086077099067169041536315773126601869537036602014639497662916952995546870691495931205282427606841521014293638607226118353743812583642616889028731910222603216563207637006843580936568089467160095319593442255227365472917576488012409542775346105980501967996562422764758836868135158147777193940857952623773420292946843206784104932927528915610322518810753953608862466374219925252817405397507396462117715293725218947744085154122395590957537510003558169729949140038634486299736757269280065662263306737701939154762092925061 RSA1 test key #2
diff --git a/regress/unittests/sshkey/testdata/rsa_1 b/regress/unittests/sshkey/testdata/rsa_1
new file mode 100644
index 000000000..09e79a72e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1
@@ -0,0 +1,12 @@
1-----BEGIN RSA PRIVATE KEY-----
2MIIBywIBAAJhAM/6MDmVVm/uNQmZpOcthoAAgMDUg7G4H6ZLLyPEhboKaBBHvIdw
3ZdDmB+0LDf3D1aWXyUd2/pCkCysiBzqd/523zAzjY7HayqL6A940AxKBBbWLn+X6
4i2yJR7dTOYkk6QIDAQABAmAgKanBjfWzE5yCIo+c7K5rJyjCKVtAZaAHYIMmveKM
5VcWoFt/x9hDY0GoTX21HfDxLX8oDxnsmhsOrnvSmgUChFwkm45eSETqeVDWwIVFA
6FGL1s38xQsciWZWBFNppAIECMQD7nslReAxwz/Ad++ACXswfJg1l2wUQ1gJA3zh3
7jln6a4s3aV1zxbKlIn8iqBv0BZkCMQDTmO4WqyNnin73XCZs0DWu7GsfcuaH8QnD
8wqPjJgrclTZXedxHkeqO2oyZW4mLC9ECMBb/blsZ49kzyDiVWuYcj/+Q1MyodhAR
932bagCi9RBAVYEYSRU5dlXRucLxULSnikQIxAJ5teY5Vcru6kZfJUifUuO0QrKAu
10WnbcPVBqMmUHfchsm/RhFFIt6W4uKmlEhTYrkQIxAMAStb7QCU3yU6ZkN7uL22Zs
11498i4jY6y+VEXv+L9O09VdlEnXhbUisOhy1bhyS3yg==
12-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/regress/unittests/sshkey/testdata/rsa_1-cert.fp
new file mode 100644
index 000000000..bf9c2e362
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1-cert.fp
@@ -0,0 +1 @@
be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b
diff --git a/regress/unittests/sshkey/testdata/rsa_1-cert.pub b/regress/unittests/sshkey/testdata/rsa_1-cert.pub
new file mode 100644
index 000000000..51b1ce0dd
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1-cert.pub
@@ -0,0 +1 @@
ssh-rsa-cert-v01@openssh.com AAAAHHNzaC1yc2EtY2VydC12MDFAb3BlbnNzaC5jb20AAAAg1i9Ueveqg9sFSGsEYmsQqlI+dpC3nqhucPfwBVo3DtcAAAADAQABAAAAYQDP+jA5lVZv7jUJmaTnLYaAAIDA1IOxuB+mSy8jxIW6CmgQR7yHcGXQ5gftCw39w9Wll8lHdv6QpAsrIgc6nf+dt8wM42Ox2sqi+gPeNAMSgQW1i5/l+otsiUe3UzmJJOkAAAAAAAAABQAAAAIAAAAGanVsaXVzAAAAEgAAAAVob3N0MQAAAAVob3N0MgAAAAA2i4NgAAAAAE0d4eAAAAAAAAAAAAAAAAAAAAAzAAAAC3NzaC1lZDI1NTE5AAAAILk95V5J3LKVx8bcLSB4073R7d0aAvR8gJrPvnV0D3MQAAAAUwAAAAtzc2gtZWQyNTUxOQAAAED0TLf2Mv2F9TBt1Skf/1vviUgt7bt9xvL5HqugnVDfKaEg+RNKgfa5Rtpteb39EODkH8v4FJPWlmNG0F9w0cYF rsa_1.pub
diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp b/regress/unittests/sshkey/testdata/rsa_1.fp
new file mode 100644
index 000000000..bf9c2e362
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.fp
@@ -0,0 +1 @@
be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b
diff --git a/regress/unittests/sshkey/testdata/rsa_1.fp.bb b/regress/unittests/sshkey/testdata/rsa_1.fp.bb
new file mode 100644
index 000000000..448133bad
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.fp.bb
@@ -0,0 +1 @@
xetif-zuvul-nylyc-vykor-lumac-gyhyv-bacih-cimyk-sycen-gikym-pixax
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.n b/regress/unittests/sshkey/testdata/rsa_1.param.n
new file mode 100644
index 000000000..2ffc2ba7e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.param.n
@@ -0,0 +1 @@
00cffa303995566fee350999a4e72d86800080c0d483b1b81fa64b2f23c485ba0a681047bc877065d0e607ed0b0dfdc3d5a597c94776fe90a40b2b22073a9dff9db7cc0ce363b1dacaa2fa03de3403128105b58b9fe5fa8b6c8947b753398924e9
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.p b/regress/unittests/sshkey/testdata/rsa_1.param.p
new file mode 100644
index 000000000..4fcf148c3
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.param.p
@@ -0,0 +1 @@
00fb9ec951780c70cff01dfbe0025ecc1f260d65db0510d60240df38778e59fa6b8b37695d73c5b2a5227f22a81bf40599
diff --git a/regress/unittests/sshkey/testdata/rsa_1.param.q b/regress/unittests/sshkey/testdata/rsa_1.param.q
new file mode 100644
index 000000000..3473f5144
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.param.q
@@ -0,0 +1 @@
00d398ee16ab23678a7ef75c266cd035aeec6b1f72e687f109c3c2a3e3260adc95365779dc4791ea8eda8c995b898b0bd1
diff --git a/regress/unittests/sshkey/testdata/rsa_1.pub b/regress/unittests/sshkey/testdata/rsa_1.pub
new file mode 100644
index 000000000..889fdae86
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1.pub
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAYQDP+jA5lVZv7jUJmaTnLYaAAIDA1IOxuB+mSy8jxIW6CmgQR7yHcGXQ5gftCw39w9Wll8lHdv6QpAsrIgc6nf+dt8wM42Ox2sqi+gPeNAMSgQW1i5/l+otsiUe3UzmJJOk= RSA test key #1
diff --git a/regress/unittests/sshkey/testdata/rsa_1_pw b/regress/unittests/sshkey/testdata/rsa_1_pw
new file mode 100644
index 000000000..71637a59b
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_1_pw
@@ -0,0 +1,15 @@
1-----BEGIN RSA PRIVATE KEY-----
2Proc-Type: 4,ENCRYPTED
3DEK-Info: AES-128-CBC,1E851A01F12A49FDC256E7A665C61D4B
4
5+sfWU7kg3idmHL6vShby5LXnfF4bZDPhJjv89uldae7qPEgEW8qS8o0Ssokxf7Au
6/vTQnbSB+gy/qZaUOykOzqiV1YL7UfkbOkM2QYnzzrVeGzI5RZ0G9iH8HBn2owQ+
7Ejf1UKDUVZEea5X0IwQRfE0zaZqFS4tyEex0iKz8dI4FvyabKLZsCs1DBGO7A3ml
8LgP947mh10yKWTP2fbq8LOhDUEWCXrh2NzuH6Rl5nNyC4MNQEkLzK1wL7J/WCNaL
9sciYmuqEQRDikDDQQFZw2wjBD638fhK+IhuN3VGegiXFnu5C+p9kzUvqVk4X9g2r
10BMmlP0pceFv/fEwtNNaeI2Tt7mIsWsZTmCqdzOUAYqGIiNjzykWw64nMO3TpVpbA
11i4854RhblbeiyjENbMVPU6BAk4fx7OJvDElLxwN43CS3U0MldbI7A4uG3B3RTSCj
121rGxRNAHWC3q3zzrn6gLwrUVje4iTedaKItLIHQeo1A091Tr8AqQdZi/Ck2Ju0Hl
134Qdwzjw1Y5n1Akm+EWh31ydxtUQ0YBOz/W6DKwTNA1D8oH9bZBG4f0pnvVhtttAO
14WKj+DUqMa+f3OOmQ9UXlitk2pEgjeMngTgfQnhZiCts=
15-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_2 b/regress/unittests/sshkey/testdata/rsa_2
new file mode 100644
index 000000000..058cf777a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2
@@ -0,0 +1,27 @@
1-----BEGIN RSA PRIVATE KEY-----
2MIIEowIBAAKCAQEAlDS/ygeFfsR/mhZK/XMHU/gzRogPuMQIYUd17WDjMprA6dQb
3ckTDrNm/mrf09I6YAhjgooEL16oWM1z6cesDE0KwaJsy6uTmXFMLO+Ha4mtFHhmu
4tiyJcQ9MKKr0vC64384WQZygZk0OlVz7x9WSPiGXzal5MzsX4TYq5B05o2Cb+epA
5FxK0c8cdYZD0Sy57gWRpRA3yJq4zh/hks98jzn0XA3HAJA39MKhUG5tf5e6z5BeP
6Yi5FvdnDQ9WcasRiEvkmHbg59pbgg/Lbsl6OgZQruS8hKiJ3YBARt2euCCeg7qAF
7KbXRR9TMwfphH3Ai4Oi/w6HPRAhdrwooA/gKkQIDAQABAoIBAH22OLB/rMaYmrvz
8COzvM1oQgD3lj6Bj98+8M9WEh3MXPWeaGSXWGjx1/0aXn1oJ0fqFa5Wr7IWkqmwr
9A+y5McSWntg8PPZt7tCFSFQlAetonhooIsA4CuUx2qHsUOeGoh6EyvAgkRX1atdb
10Jd6d1AyLph43EK1aBKltrvgLqiZfs7mcuwyvKtN9ktdKY2FDhn6DHpm9pE9MEHJV
11Xv1isNc6a0qNoRlKqxrSZHNEN4fbjLw31wBySzmmnIog5wVEwaHeASwLJT6TmuIZ
12eZxnd7/jMwRZWH8ZIGKvkTMp4fYzK9QkehO7A2HFD3FPDBVrkSJjqRdkujF8vu1C
130RwrD1kCgYEAxFXUoE1ero6vp9akvR/mw94kYjXE/YOz1yi0KTkZUs6gURc8Kzsm
14MzlEZ31rnngE4jQHYAvuPEfiqcnUgylW3QuevMgo2hCLYO7aG5C0fk8TeOiuvnrF
15YPO8rSJWk/BgdrPtzu45P7jmWsjkHn+y+t8cKvq1sZY40sn2YgIhYK8CgYEAwT6j
165tReI6sxpHltPUbvOdpD04eL6ggBAKwzb5aBoa/Dj+sU1zg5uyY8diggQEEznlBW
17iWTQmmmfy1ef9i6YAwNuZveKOrVwNMcdubQJ2X26XoFrmA59PjsbLtr1bdUb02gz
186P5x6pcw5qzEq0mddgvHiU3RhL24xdc1LW8nmL8CgYEAmgaT1macPuklmNBlURGz
194jll5b41GoW2EreWDzkCStpbHwLRa0DuCQWGSoI0aY/SlPsoRgtWDOiAQ59ZHsTR
20pnw1PfjxQ5HzJkp7xWBSmTzEE/jHDhwWuKa+gD0OGuVbaARkLhDpzLnrzZEIlXyt
21Fu7tlDI3VGh7j7Jtnhn5wXUCgYBKmPbGfcaVeFmih2lfFUn2CEbUmmetgUd5zf/R
22HMWP9/zDStlxt3e5winm5tiEVWcqvxKY2T0Zzppr8biDXTs7NpDg2MAYp7/X7+GO
23tWxz8/AE2WsCeN1qL4Dv1oCV1IV4V6pqUAcDqzeqZJlLEhDh5+wwGcU+u8pfPRN/
24JYCgmwKBgDa+kXPqzcc6vzD9cwEEk4ftn9/Vk2yBx0XOu8RdEkRhXj1QXGJckCqh
25FkXzVbuurFhsBt+H0B4arw+51T9fVCZqfcaU34u+Qa/FQvTod4OJUSRxYUaDqygs
26VTyuP+zGZlIw7JWktxjVazENsM/ef5wBH0Nf839OZbPVDLfn7K0j
27-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp b/regress/unittests/sshkey/testdata/rsa_2.fp
new file mode 100644
index 000000000..53939f413
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.fp
@@ -0,0 +1 @@
fb:8f:7b:26:3d:42:40:ef:ed:f1:ed:ee:66:9e:ba:b0
diff --git a/regress/unittests/sshkey/testdata/rsa_2.fp.bb b/regress/unittests/sshkey/testdata/rsa_2.fp.bb
new file mode 100644
index 000000000..e90a3571a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.fp.bb
@@ -0,0 +1 @@
xepev-gupub-vuvyg-femiv-gonat-defiv-hirak-betub-pahut-veryd-hexix
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.n b/regress/unittests/sshkey/testdata/rsa_2.param.n
new file mode 100644
index 000000000..389de4226
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.param.n
@@ -0,0 +1 @@
009434bfca07857ec47f9a164afd730753f83346880fb8c408614775ed60e3329ac0e9d41b7244c3acd9bf9ab7f4f48e980218e0a2810bd7aa16335cfa71eb031342b0689b32eae4e65c530b3be1dae26b451e19aeb62c89710f4c28aaf4bc2eb8dfce16419ca0664d0e955cfbc7d5923e2197cda979333b17e1362ae41d39a3609bf9ea401712b473c71d6190f44b2e7b816469440df226ae3387f864b3df23ce7d170371c0240dfd30a8541b9b5fe5eeb3e4178f622e45bdd9c343d59c6ac46212f9261db839f696e083f2dbb25e8e81942bb92f212a2277601011b767ae0827a0eea00529b5d147d4ccc1fa611f7022e0e8bfc3a1cf44085daf0a2803f80a91
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.p b/regress/unittests/sshkey/testdata/rsa_2.param.p
new file mode 100644
index 000000000..c3c9a130a
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.param.p
@@ -0,0 +1 @@
00c455d4a04d5eae8eafa7d6a4bd1fe6c3de246235c4fd83b3d728b429391952cea051173c2b3b26333944677d6b9e7804e23407600bee3c47e2a9c9d4832956dd0b9ebcc828da108b60eeda1b90b47e4f1378e8aebe7ac560f3bcad225693f06076b3edceee393fb8e65ac8e41e7fb2fadf1c2afab5b19638d2c9f662022160af
diff --git a/regress/unittests/sshkey/testdata/rsa_2.param.q b/regress/unittests/sshkey/testdata/rsa_2.param.q
new file mode 100644
index 000000000..728c474b0
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.param.q
@@ -0,0 +1 @@
00c13ea3e6d45e23ab31a4796d3d46ef39da43d3878bea080100ac336f9681a1afc38feb14d73839bb263c7628204041339e50568964d09a699fcb579ff62e9803036e66f78a3ab57034c71db9b409d97dba5e816b980e7d3e3b1b2edaf56dd51bd36833e8fe71ea9730e6acc4ab499d760bc7894dd184bdb8c5d7352d6f2798bf
diff --git a/regress/unittests/sshkey/testdata/rsa_2.pub b/regress/unittests/sshkey/testdata/rsa_2.pub
new file mode 100644
index 000000000..ed9f78cad
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_2.pub
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCUNL/KB4V+xH+aFkr9cwdT+DNGiA+4xAhhR3XtYOMymsDp1BtyRMOs2b+at/T0jpgCGOCigQvXqhYzXPpx6wMTQrBomzLq5OZcUws74dria0UeGa62LIlxD0woqvS8LrjfzhZBnKBmTQ6VXPvH1ZI+IZfNqXkzOxfhNirkHTmjYJv56kAXErRzxx1hkPRLLnuBZGlEDfImrjOH+GSz3yPOfRcDccAkDf0wqFQbm1/l7rPkF49iLkW92cND1ZxqxGIS+SYduDn2luCD8tuyXo6BlCu5LyEqIndgEBG3Z64IJ6DuoAUptdFH1MzB+mEfcCLg6L/Doc9ECF2vCigD+AqR RSA test key #2
diff --git a/regress/unittests/sshkey/testdata/rsa_n b/regress/unittests/sshkey/testdata/rsa_n
new file mode 100644
index 000000000..09e79a72e
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_n
@@ -0,0 +1,12 @@
1-----BEGIN RSA PRIVATE KEY-----
2MIIBywIBAAJhAM/6MDmVVm/uNQmZpOcthoAAgMDUg7G4H6ZLLyPEhboKaBBHvIdw
3ZdDmB+0LDf3D1aWXyUd2/pCkCysiBzqd/523zAzjY7HayqL6A940AxKBBbWLn+X6
4i2yJR7dTOYkk6QIDAQABAmAgKanBjfWzE5yCIo+c7K5rJyjCKVtAZaAHYIMmveKM
5VcWoFt/x9hDY0GoTX21HfDxLX8oDxnsmhsOrnvSmgUChFwkm45eSETqeVDWwIVFA
6FGL1s38xQsciWZWBFNppAIECMQD7nslReAxwz/Ad++ACXswfJg1l2wUQ1gJA3zh3
7jln6a4s3aV1zxbKlIn8iqBv0BZkCMQDTmO4WqyNnin73XCZs0DWu7GsfcuaH8QnD
8wqPjJgrclTZXedxHkeqO2oyZW4mLC9ECMBb/blsZ49kzyDiVWuYcj/+Q1MyodhAR
932bagCi9RBAVYEYSRU5dlXRucLxULSnikQIxAJ5teY5Vcru6kZfJUifUuO0QrKAu
10WnbcPVBqMmUHfchsm/RhFFIt6W4uKmlEhTYrkQIxAMAStb7QCU3yU6ZkN7uL22Zs
11498i4jY6y+VEXv+L9O09VdlEnXhbUisOhy1bhyS3yg==
12-----END RSA PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/testdata/rsa_n_pw b/regress/unittests/sshkey/testdata/rsa_n_pw
new file mode 100644
index 000000000..0166fd5f1
--- /dev/null
+++ b/regress/unittests/sshkey/testdata/rsa_n_pw
@@ -0,0 +1,14 @@
1-----BEGIN OPENSSH PRIVATE KEY-----
2b3BlbnNzaC1rZXktdjEAAAAACmFlczI1Ni1jYmMAAAAGYmNyeXB0AAAAGAAAABClELgtaZ
3qAmMwESpqXDN0uAAAAEAAAAAEAAAB3AAAAB3NzaC1yc2EAAAADAQABAAAAYQDP+jA5lVZv
47jUJmaTnLYaAAIDA1IOxuB+mSy8jxIW6CmgQR7yHcGXQ5gftCw39w9Wll8lHdv6QpAsrIg
5c6nf+dt8wM42Ox2sqi+gPeNAMSgQW1i5/l+otsiUe3UzmJJOkAAAGgwJpHy/nshQa9+Jbw
6yomvgNMYvuuoD7Ll7iCY/RFFGXivTkki27C9q0qx3afauSLQQWFanGhjeJn7JPy98lMcVl
7qnn5XOE5+xxZqA8ONOBD8eH0KBcTH17DH1A1z94p5zZ1VJKIWsBZ0krxgHIXcdv9ucAckj
8N0vAEBm+0wsfy2TTOtuqXvcj65wFwknpyy/SSvU0QTr99FiYe9PIhIslBHO6wlqxfKj+Tm
9E/nCb75dAVu6gTtS2P0pdOqV/V7VHX5C0z3BROqpKDJJcVeoc7vRkEl+MWfvvQrG66IPEW
10luohFXPDPDrxu1zDduyRsmNwpBHChi2rFhxtsjxNK0svMwESeCCKAWmPxnzLJfvMbTCv00
11SpaCr7WhtzsGt73axqSkeOdynp5NNrN7MEdwruMZFirF4BcI2z2H9ugpS+qbLPuE2H5vln
12h7NSwBUNwmZ+4TC8MXFH9KIpRg8dNhf66OU610LYiN4+ZfOYCmfQfgQuBGhMTYFMY6O4SB
13NCdIavvWY6rDSBq7QC1f4rHpwiXxpkiE43Rd8fM32TaPlBPtA=
14-----END OPENSSH PRIVATE KEY-----
diff --git a/regress/unittests/sshkey/tests.c b/regress/unittests/sshkey/tests.c
new file mode 100644
index 000000000..13f265cdb
--- /dev/null
+++ b/regress/unittests/sshkey/tests.c
@@ -0,0 +1,27 @@
1/* $OpenBSD: tests.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
2/*
3 * Regress test for sshbuf.h buffer API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <openssl/evp.h>
11
12#include "../test_helper/test_helper.h"
13
14void sshkey_tests(void);
15void sshkey_file_tests(void);
16void sshkey_fuzz_tests(void);
17
18void
19tests(void)
20{
21 OpenSSL_add_all_algorithms();
22 ERR_load_CRYPTO_strings();
23
24 sshkey_tests();
25 sshkey_file_tests();
26 sshkey_fuzz_tests();
27}
diff --git a/regress/unittests/test_helper/Makefile b/regress/unittests/test_helper/Makefile
new file mode 100644
index 000000000..3e90903ef
--- /dev/null
+++ b/regress/unittests/test_helper/Makefile
@@ -0,0 +1,13 @@
1# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $
2
3LIB= test_helper
4SRCS= test_helper.c fuzz.c
5
6DEBUGLIBS= no
7NOPROFILE= yes
8NOPIC= yes
9
10install:
11 @echo -n
12
13.include <bsd.lib.mk>
diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c
new file mode 100644
index 000000000..77c6e7cad
--- /dev/null
+++ b/regress/unittests/test_helper/fuzz.c
@@ -0,0 +1,378 @@
1/* $OpenBSD: fuzz.c,v 1.3 2014/05/02 09:41:32 andre Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* Utility functions/framework for fuzz tests */
19
20#include "includes.h"
21
22#include <sys/types.h>
23
24#include <assert.h>
25#include <ctype.h>
26#include <stdio.h>
27#ifdef HAVE_STDINT_H
28# include <stdint.h>
29#endif
30#include <stdlib.h>
31#include <string.h>
32#include <assert.h>
33
34#include "test_helper.h"
35
36/* #define FUZZ_DEBUG */
37
38#ifdef FUZZ_DEBUG
39# define FUZZ_DBG(x) do { \
40 printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
41 printf x; \
42 printf("\n"); \
43 fflush(stdout); \
44 } while (0)
45#else
46# define FUZZ_DBG(x)
47#endif
48
49/* For brevity later */
50typedef unsigned long long fuzz_ullong;
51
52/* For base-64 fuzzing */
53static const char fuzz_b64chars[] =
54 "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
55
56struct fuzz {
57 /* Fuzz method currently in use */
58 int strategy;
59
60 /* Fuzz methods remaining */
61 int strategies;
62
63 /* Original seed data blob */
64 void *seed;
65 size_t slen;
66
67 /* Current working copy of seed with fuzz mutations applied */
68 u_char *fuzzed;
69
70 /* Used by fuzz methods */
71 size_t o1, o2;
72};
73
74static const char *
75fuzz_ntop(u_int n)
76{
77 switch (n) {
78 case 0:
79 return "NONE";
80 case FUZZ_1_BIT_FLIP:
81 return "FUZZ_1_BIT_FLIP";
82 case FUZZ_2_BIT_FLIP:
83 return "FUZZ_2_BIT_FLIP";
84 case FUZZ_1_BYTE_FLIP:
85 return "FUZZ_1_BYTE_FLIP";
86 case FUZZ_2_BYTE_FLIP:
87 return "FUZZ_2_BYTE_FLIP";
88 case FUZZ_TRUNCATE_START:
89 return "FUZZ_TRUNCATE_START";
90 case FUZZ_TRUNCATE_END:
91 return "FUZZ_TRUNCATE_END";
92 case FUZZ_BASE64:
93 return "FUZZ_BASE64";
94 default:
95 abort();
96 }
97}
98
99void
100fuzz_dump(struct fuzz *fuzz)
101{
102 u_char *p = fuzz_ptr(fuzz);
103 size_t i, j, len = fuzz_len(fuzz);
104
105 switch (fuzz->strategy) {
106 case FUZZ_1_BIT_FLIP:
107 fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n",
108 fuzz_ntop(fuzz->strategy),
109 fuzz->o1, fuzz->slen * 8, fuzz->o1);
110 break;
111 case FUZZ_2_BIT_FLIP:
112 fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n",
113 fuzz_ntop(fuzz->strategy),
114 (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
115 ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
116 fuzz->o1, fuzz->o2);
117 break;
118 case FUZZ_1_BYTE_FLIP:
119 fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n",
120 fuzz_ntop(fuzz->strategy),
121 fuzz->o1, fuzz->slen, fuzz->o1);
122 break;
123 case FUZZ_2_BYTE_FLIP:
124 fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n",
125 fuzz_ntop(fuzz->strategy),
126 (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
127 ((fuzz_ullong)fuzz->slen) * fuzz->slen,
128 fuzz->o1, fuzz->o2);
129 break;
130 case FUZZ_TRUNCATE_START:
131 fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
132 fuzz_ntop(fuzz->strategy),
133 fuzz->o1, fuzz->slen, fuzz->o1);
134 break;
135 case FUZZ_TRUNCATE_END:
136 fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
137 fuzz_ntop(fuzz->strategy),
138 fuzz->o1, fuzz->slen, fuzz->o1);
139 break;
140 case FUZZ_BASE64:
141 assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
142 fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n",
143 fuzz_ntop(fuzz->strategy),
144 (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
145 fuzz->slen * (fuzz_ullong)64, fuzz->o1,
146 fuzz_b64chars[fuzz->o2]);
147 break;
148 default:
149 abort();
150 }
151
152 fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len);
153 for (i = 0; i < len; i += 16) {
154 fprintf(stderr, "%.4zd: ", i);
155 for (j = i; j < i + 16; j++) {
156 if (j < len)
157 fprintf(stderr, "%02x ", p[j]);
158 else
159 fprintf(stderr, " ");
160 }
161 fprintf(stderr, " ");
162 for (j = i; j < i + 16; j++) {
163 if (j < len) {
164 if (isascii(p[j]) && isprint(p[j]))
165 fprintf(stderr, "%c", p[j]);
166 else
167 fprintf(stderr, ".");
168 }
169 }
170 fprintf(stderr, "\n");
171 }
172}
173
174struct fuzz *
175fuzz_begin(u_int strategies, const void *p, size_t l)
176{
177 struct fuzz *ret = calloc(sizeof(*ret), 1);
178
179 assert(p != NULL);
180 assert(ret != NULL);
181 ret->seed = malloc(l);
182 assert(ret->seed != NULL);
183 memcpy(ret->seed, p, l);
184 ret->slen = l;
185 ret->strategies = strategies;
186
187 assert(ret->slen < SIZE_MAX / 8);
188 assert(ret->strategies <= (FUZZ_MAX|(FUZZ_MAX-1)));
189
190 FUZZ_DBG(("begin, ret = %p", ret));
191
192 fuzz_next(ret);
193 return ret;
194}
195
196void
197fuzz_cleanup(struct fuzz *fuzz)
198{
199 FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
200 assert(fuzz != NULL);
201 assert(fuzz->seed != NULL);
202 assert(fuzz->fuzzed != NULL);
203 free(fuzz->seed);
204 free(fuzz->fuzzed);
205 free(fuzz);
206}
207
208static int
209fuzz_strategy_done(struct fuzz *fuzz)
210{
211 FUZZ_DBG(("fuzz = %p, strategy = %s, o1 = %zu, o2 = %zu, slen = %zu",
212 fuzz, fuzz_ntop(fuzz->strategy), fuzz->o1, fuzz->o2, fuzz->slen));
213
214 switch (fuzz->strategy) {
215 case FUZZ_1_BIT_FLIP:
216 return fuzz->o1 >= fuzz->slen * 8;
217 case FUZZ_2_BIT_FLIP:
218 return fuzz->o2 >= fuzz->slen * 8;
219 case FUZZ_2_BYTE_FLIP:
220 return fuzz->o2 >= fuzz->slen;
221 case FUZZ_1_BYTE_FLIP:
222 case FUZZ_TRUNCATE_START:
223 case FUZZ_TRUNCATE_END:
224 case FUZZ_BASE64:
225 return fuzz->o1 >= fuzz->slen;
226 default:
227 abort();
228 }
229}
230
231void
232fuzz_next(struct fuzz *fuzz)
233{
234 u_int i;
235
236 FUZZ_DBG(("start, fuzz = %p, strategy = %s, strategies = 0x%lx, "
237 "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
238 (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
239
240 if (fuzz->strategy == 0 || fuzz_strategy_done(fuzz)) {
241 /* If we are just starting out, we need to allocate too */
242 if (fuzz->fuzzed == NULL) {
243 FUZZ_DBG(("alloc"));
244 fuzz->fuzzed = calloc(fuzz->slen, 1);
245 }
246 /* Pick next strategy */
247 FUZZ_DBG(("advance"));
248 for (i = 1; i <= FUZZ_MAX; i <<= 1) {
249 if ((fuzz->strategies & i) != 0) {
250 fuzz->strategy = i;
251 break;
252 }
253 }
254 FUZZ_DBG(("selected = %u", fuzz->strategy));
255 if (fuzz->strategy == 0) {
256 FUZZ_DBG(("done, no more strategies"));
257 return;
258 }
259 fuzz->strategies &= ~(fuzz->strategy);
260 fuzz->o1 = fuzz->o2 = 0;
261 }
262
263 assert(fuzz->fuzzed != NULL);
264
265 switch (fuzz->strategy) {
266 case FUZZ_1_BIT_FLIP:
267 assert(fuzz->o1 / 8 < fuzz->slen);
268 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
269 fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
270 fuzz->o1++;
271 break;
272 case FUZZ_2_BIT_FLIP:
273 assert(fuzz->o1 / 8 < fuzz->slen);
274 assert(fuzz->o2 / 8 < fuzz->slen);
275 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
276 fuzz->fuzzed[fuzz->o1 / 8] ^= 1 << (fuzz->o1 % 8);
277 fuzz->fuzzed[fuzz->o2 / 8] ^= 1 << (fuzz->o2 % 8);
278 fuzz->o1++;
279 if (fuzz->o1 >= fuzz->slen * 8) {
280 fuzz->o1 = 0;
281 fuzz->o2++;
282 }
283 break;
284 case FUZZ_1_BYTE_FLIP:
285 assert(fuzz->o1 < fuzz->slen);
286 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
287 fuzz->fuzzed[fuzz->o1] ^= 0xff;
288 fuzz->o1++;
289 break;
290 case FUZZ_2_BYTE_FLIP:
291 assert(fuzz->o1 < fuzz->slen);
292 assert(fuzz->o2 < fuzz->slen);
293 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
294 fuzz->fuzzed[fuzz->o1] ^= 0xff;
295 fuzz->fuzzed[fuzz->o2] ^= 0xff;
296 fuzz->o1++;
297 if (fuzz->o1 >= fuzz->slen) {
298 fuzz->o1 = 0;
299 fuzz->o2++;
300 }
301 break;
302 case FUZZ_TRUNCATE_START:
303 case FUZZ_TRUNCATE_END:
304 assert(fuzz->o1 < fuzz->slen);
305 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
306 fuzz->o1++;
307 break;
308 case FUZZ_BASE64:
309 assert(fuzz->o1 < fuzz->slen);
310 assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
311 memcpy(fuzz->fuzzed, fuzz->seed, fuzz->slen);
312 fuzz->fuzzed[fuzz->o1] = fuzz_b64chars[fuzz->o2];
313 fuzz->o2++;
314 if (fuzz->o2 >= sizeof(fuzz_b64chars) - 1) {
315 fuzz->o2 = 0;
316 fuzz->o1++;
317 }
318 break;
319 default:
320 abort();
321 }
322
323 FUZZ_DBG(("done, fuzz = %p, strategy = %s, strategies = 0x%lx, "
324 "o1 = %zu, o2 = %zu, slen = %zu", fuzz, fuzz_ntop(fuzz->strategy),
325 (u_long)fuzz->strategies, fuzz->o1, fuzz->o2, fuzz->slen));
326}
327
328int
329fuzz_done(struct fuzz *fuzz)
330{
331 FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
332 (u_long)fuzz->strategies));
333
334 return fuzz_strategy_done(fuzz) && fuzz->strategies == 0;
335}
336
337size_t
338fuzz_len(struct fuzz *fuzz)
339{
340 assert(fuzz->fuzzed != NULL);
341 switch (fuzz->strategy) {
342 case FUZZ_1_BIT_FLIP:
343 case FUZZ_2_BIT_FLIP:
344 case FUZZ_1_BYTE_FLIP:
345 case FUZZ_2_BYTE_FLIP:
346 case FUZZ_BASE64:
347 return fuzz->slen;
348 case FUZZ_TRUNCATE_START:
349 case FUZZ_TRUNCATE_END:
350 assert(fuzz->o1 <= fuzz->slen);
351 return fuzz->slen - fuzz->o1;
352 default:
353 abort();
354 }
355}
356
357u_char *
358fuzz_ptr(struct fuzz *fuzz)
359{
360 assert(fuzz->fuzzed != NULL);
361 switch (fuzz->strategy) {
362 case FUZZ_1_BIT_FLIP:
363 case FUZZ_2_BIT_FLIP:
364 case FUZZ_1_BYTE_FLIP:
365 case FUZZ_2_BYTE_FLIP:
366 case FUZZ_BASE64:
367 return fuzz->fuzzed;
368 case FUZZ_TRUNCATE_START:
369 assert(fuzz->o1 <= fuzz->slen);
370 return fuzz->fuzzed + fuzz->o1;
371 case FUZZ_TRUNCATE_END:
372 assert(fuzz->o1 <= fuzz->slen);
373 return fuzz->fuzzed;
374 default:
375 abort();
376 }
377}
378
diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c
new file mode 100644
index 000000000..d0bc67833
--- /dev/null
+++ b/regress/unittests/test_helper/test_helper.c
@@ -0,0 +1,471 @@
1/* $OpenBSD: test_helper.c,v 1.2 2014/05/02 09:41:32 andre Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* Utility functions/framework for regress tests */
19
20#include "includes.h"
21
22#include <sys/types.h>
23#include <sys/param.h>
24
25#include <fcntl.h>
26#include <stdio.h>
27#ifdef HAVE_STDINT_H
28# include <stdint.h>
29#endif
30#include <stdlib.h>
31#include <string.h>
32#include <assert.h>
33#include <unistd.h>
34
35#include <openssl/bn.h>
36
37#if defined(HAVE_STRNVIS) && defined(HAVE_VIS_H) && !defined(BROKEN_STRNVIS)
38# include <vis.h>
39#endif
40
41#include "test_helper.h"
42
43#define TEST_CHECK_INT(r, pred) do { \
44 switch (pred) { \
45 case TEST_EQ: \
46 if (r == 0) \
47 return; \
48 break; \
49 case TEST_NE: \
50 if (r != 0) \
51 return; \
52 break; \
53 case TEST_LT: \
54 if (r < 0) \
55 return; \
56 break; \
57 case TEST_LE: \
58 if (r <= 0) \
59 return; \
60 break; \
61 case TEST_GT: \
62 if (r > 0) \
63 return; \
64 break; \
65 case TEST_GE: \
66 if (r >= 0) \
67 return; \
68 break; \
69 default: \
70 abort(); \
71 } \
72 } while (0)
73
74#define TEST_CHECK(x1, x2, pred) do { \
75 switch (pred) { \
76 case TEST_EQ: \
77 if (x1 == x2) \
78 return; \
79 break; \
80 case TEST_NE: \
81 if (x1 != x2) \
82 return; \
83 break; \
84 case TEST_LT: \
85 if (x1 < x2) \
86 return; \
87 break; \
88 case TEST_LE: \
89 if (x1 <= x2) \
90 return; \
91 break; \
92 case TEST_GT: \
93 if (x1 > x2) \
94 return; \
95 break; \
96 case TEST_GE: \
97 if (x1 >= x2) \
98 return; \
99 break; \
100 default: \
101 abort(); \
102 } \
103 } while (0)
104
105extern char *__progname;
106
107static int verbose_mode = 0;
108static int quiet_mode = 0;
109static char *active_test_name = NULL;
110static u_int test_number = 0;
111static test_onerror_func_t *test_onerror = NULL;
112static void *onerror_ctx = NULL;
113static const char *data_dir = NULL;
114
115int
116main(int argc, char **argv)
117{
118 int ch;
119
120 /* Handle systems without __progname */
121 if (__progname == NULL) {
122 __progname = strrchr(argv[0], '/');
123 if (__progname == NULL || __progname[1] == '\0')
124 __progname = argv[0];
125 else
126 __progname++;
127 if ((__progname = strdup(__progname)) == NULL) {
128 fprintf(stderr, "strdup failed\n");
129 exit(1);
130 }
131 }
132
133 while ((ch = getopt(argc, argv, "vqd:")) != -1) {
134 switch (ch) {
135 case 'd':
136 data_dir = optarg;
137 break;
138 case 'q':
139 verbose_mode = 0;
140 quiet_mode = 1;
141 break;
142 case 'v':
143 verbose_mode = 1;
144 quiet_mode = 0;
145 break;
146 default:
147 fprintf(stderr, "Unrecognised command line option\n");
148 fprintf(stderr, "Usage: %s [-v]\n", __progname);
149 exit(1);
150 }
151 }
152 setvbuf(stdout, NULL, _IONBF, 0);
153 if (!quiet_mode)
154 printf("%s: ", __progname);
155 if (verbose_mode)
156 printf("\n");
157
158 tests();
159
160 if (!quiet_mode)
161 printf(" %u tests ok\n", test_number);
162 return 0;
163}
164
165const char *
166test_data_file(const char *name)
167{
168 static char ret[PATH_MAX];
169
170 if (data_dir != NULL)
171 snprintf(ret, sizeof(ret), "%s/%s", data_dir, name);
172 else
173 strlcpy(ret, name, sizeof(ret));
174 if (access(ret, F_OK) != 0) {
175 fprintf(stderr, "Cannot access data file %s: %s\n",
176 ret, strerror(errno));
177 exit(1);
178 }
179 return ret;
180}
181
182void
183test_start(const char *n)
184{
185 assert(active_test_name == NULL);
186 assert((active_test_name = strdup(n)) != NULL);
187 if (verbose_mode)
188 printf("test %u - \"%s\": ", test_number, active_test_name);
189 test_number++;
190}
191
192void
193set_onerror_func(test_onerror_func_t *f, void *ctx)
194{
195 test_onerror = f;
196 onerror_ctx = ctx;
197}
198
199void
200test_done(void)
201{
202 assert(active_test_name != NULL);
203 free(active_test_name);
204 active_test_name = NULL;
205 if (verbose_mode)
206 printf("OK\n");
207 else if (!quiet_mode) {
208 printf(".");
209 fflush(stdout);
210 }
211}
212
213void
214ssl_err_check(const char *file, int line)
215{
216 long openssl_error = ERR_get_error();
217
218 if (openssl_error == 0)
219 return;
220
221 fprintf(stderr, "\n%s:%d: uncaught OpenSSL error: %s",
222 file, line, ERR_error_string(openssl_error, NULL));
223 abort();
224}
225
226static const char *
227pred_name(enum test_predicate p)
228{
229 switch (p) {
230 case TEST_EQ:
231 return "EQ";
232 case TEST_NE:
233 return "NE";
234 case TEST_LT:
235 return "LT";
236 case TEST_LE:
237 return "LE";
238 case TEST_GT:
239 return "GT";
240 case TEST_GE:
241 return "GE";
242 default:
243 return "UNKNOWN";
244 }
245}
246
247static void
248test_die(void)
249{
250 if (test_onerror != NULL)
251 test_onerror(onerror_ctx);
252 abort();
253}
254
255static void
256test_header(const char *file, int line, const char *a1, const char *a2,
257 const char *name, enum test_predicate pred)
258{
259 fprintf(stderr, "\n%s:%d test #%u \"%s\"\n",
260 file, line, test_number, active_test_name);
261 fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
262 name, pred_name(pred), a1,
263 a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
264}
265
266void
267assert_bignum(const char *file, int line, const char *a1, const char *a2,
268 const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred)
269{
270 int r = BN_cmp(aa1, aa2);
271
272 TEST_CHECK_INT(r, pred);
273 test_header(file, line, a1, a2, "BIGNUM", pred);
274 fprintf(stderr, "%12s = 0x%s\n", a1, BN_bn2hex(aa1));
275 fprintf(stderr, "%12s = 0x%s\n", a2, BN_bn2hex(aa2));
276 test_die();
277}
278
279void
280assert_string(const char *file, int line, const char *a1, const char *a2,
281 const char *aa1, const char *aa2, enum test_predicate pred)
282{
283 int r = strcmp(aa1, aa2);
284
285 TEST_CHECK_INT(r, pred);
286 test_header(file, line, a1, a2, "STRING", pred);
287 fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
288 fprintf(stderr, "%12s = %s (len %zu)\n", a2, aa2, strlen(aa2));
289 test_die();
290}
291
292static char *
293tohex(const void *_s, size_t l)
294{
295 u_int8_t *s = (u_int8_t *)_s;
296 size_t i, j;
297 const char *hex = "0123456789abcdef";
298 char *r = malloc((l * 2) + 1);
299
300 assert(r != NULL);
301 for (i = j = 0; i < l; i++) {
302 r[j++] = hex[(s[i] >> 4) & 0xf];
303 r[j++] = hex[s[i] & 0xf];
304 }
305 r[j] = '\0';
306 return r;
307}
308
309void
310assert_mem(const char *file, int line, const char *a1, const char *a2,
311 const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
312{
313 int r = memcmp(aa1, aa2, l);
314
315 TEST_CHECK_INT(r, pred);
316 test_header(file, line, a1, a2, "STRING", pred);
317 fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l);
318 fprintf(stderr, "%12s = %s (len %zu)\n", a2, tohex(aa2, MIN(l, 256)), l);
319 test_die();
320}
321
322static int
323memvalcmp(const u_int8_t *s, u_char v, size_t l, size_t *where)
324{
325 size_t i;
326
327 for (i = 0; i < l; i++) {
328 if (s[i] != v) {
329 *where = i;
330 return 1;
331 }
332 }
333 return 0;
334}
335
336void
337assert_mem_filled(const char *file, int line, const char *a1,
338 const void *aa1, u_char v, size_t l, enum test_predicate pred)
339{
340 size_t where = -1;
341 int r = memvalcmp(aa1, v, l, &where);
342 char tmp[64];
343
344 if (l == 0)
345 return;
346 TEST_CHECK_INT(r, pred);
347 test_header(file, line, a1, NULL, "MEM_ZERO", pred);
348 fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
349 tohex(aa1, MIN(l, 20)), l > 20 ? "..." : "", l);
350 snprintf(tmp, sizeof(tmp), "(%s)[%zu]", a1, where);
351 fprintf(stderr, "%20s = 0x%02x (expected 0x%02x)\n", tmp,
352 ((u_char *)aa1)[where], v);
353 test_die();
354}
355
356void
357assert_int(const char *file, int line, const char *a1, const char *a2,
358 int aa1, int aa2, enum test_predicate pred)
359{
360 TEST_CHECK(aa1, aa2, pred);
361 test_header(file, line, a1, a2, "INT", pred);
362 fprintf(stderr, "%12s = %d\n", a1, aa1);
363 fprintf(stderr, "%12s = %d\n", a2, aa2);
364 test_die();
365}
366
367void
368assert_size_t(const char *file, int line, const char *a1, const char *a2,
369 size_t aa1, size_t aa2, enum test_predicate pred)
370{
371 TEST_CHECK(aa1, aa2, pred);
372 test_header(file, line, a1, a2, "SIZE_T", pred);
373 fprintf(stderr, "%12s = %zu\n", a1, aa1);
374 fprintf(stderr, "%12s = %zu\n", a2, aa2);
375 test_die();
376}
377
378void
379assert_u_int(const char *file, int line, const char *a1, const char *a2,
380 u_int aa1, u_int aa2, enum test_predicate pred)
381{
382 TEST_CHECK(aa1, aa2, pred);
383 test_header(file, line, a1, a2, "U_INT", pred);
384 fprintf(stderr, "%12s = %u / 0x%x\n", a1, aa1, aa1);
385 fprintf(stderr, "%12s = %u / 0x%x\n", a2, aa2, aa2);
386 test_die();
387}
388
389void
390assert_long_long(const char *file, int line, const char *a1, const char *a2,
391 long long aa1, long long aa2, enum test_predicate pred)
392{
393 TEST_CHECK(aa1, aa2, pred);
394 test_header(file, line, a1, a2, "LONG LONG", pred);
395 fprintf(stderr, "%12s = %lld / 0x%llx\n", a1, aa1, aa1);
396 fprintf(stderr, "%12s = %lld / 0x%llx\n", a2, aa2, aa2);
397 test_die();
398}
399
400void
401assert_char(const char *file, int line, const char *a1, const char *a2,
402 char aa1, char aa2, enum test_predicate pred)
403{
404 char buf[8];
405
406 TEST_CHECK(aa1, aa2, pred);
407 test_header(file, line, a1, a2, "CHAR", pred);
408 fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
409 vis(buf, aa1, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa1);
410 fprintf(stderr, "%12s = '%s' / 0x02%x\n", a1,
411 vis(buf, aa2, VIS_SAFE|VIS_NL|VIS_TAB|VIS_OCTAL, 0), aa2);
412 test_die();
413}
414
415void
416assert_u8(const char *file, int line, const char *a1, const char *a2,
417 u_int8_t aa1, u_int8_t aa2, enum test_predicate pred)
418{
419 TEST_CHECK(aa1, aa2, pred);
420 test_header(file, line, a1, a2, "U8", pred);
421 fprintf(stderr, "%12s = 0x%02x %u\n", a1, aa1, aa1);
422 fprintf(stderr, "%12s = 0x%02x %u\n", a2, aa2, aa2);
423 test_die();
424}
425
426void
427assert_u16(const char *file, int line, const char *a1, const char *a2,
428 u_int16_t aa1, u_int16_t aa2, enum test_predicate pred)
429{
430 TEST_CHECK(aa1, aa2, pred);
431 test_header(file, line, a1, a2, "U16", pred);
432 fprintf(stderr, "%12s = 0x%04x %u\n", a1, aa1, aa1);
433 fprintf(stderr, "%12s = 0x%04x %u\n", a2, aa2, aa2);
434 test_die();
435}
436
437void
438assert_u32(const char *file, int line, const char *a1, const char *a2,
439 u_int32_t aa1, u_int32_t aa2, enum test_predicate pred)
440{
441 TEST_CHECK(aa1, aa2, pred);
442 test_header(file, line, a1, a2, "U32", pred);
443 fprintf(stderr, "%12s = 0x%08x %u\n", a1, aa1, aa1);
444 fprintf(stderr, "%12s = 0x%08x %u\n", a2, aa2, aa2);
445 test_die();
446}
447
448void
449assert_u64(const char *file, int line, const char *a1, const char *a2,
450 u_int64_t aa1, u_int64_t aa2, enum test_predicate pred)
451{
452 TEST_CHECK(aa1, aa2, pred);
453 test_header(file, line, a1, a2, "U64", pred);
454 fprintf(stderr, "%12s = 0x%016llx %llu\n", a1,
455 (unsigned long long)aa1, (unsigned long long)aa1);
456 fprintf(stderr, "%12s = 0x%016llx %llu\n", a2,
457 (unsigned long long)aa2, (unsigned long long)aa2);
458 test_die();
459}
460
461void
462assert_ptr(const char *file, int line, const char *a1, const char *a2,
463 const void *aa1, const void *aa2, enum test_predicate pred)
464{
465 TEST_CHECK(aa1, aa2, pred);
466 test_header(file, line, a1, a2, "PTR", pred);
467 fprintf(stderr, "%12s = %p\n", a1, aa1);
468 fprintf(stderr, "%12s = %p\n", a2, aa2);
469 test_die();
470}
471
diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h
new file mode 100644
index 000000000..a398c615f
--- /dev/null
+++ b/regress/unittests/test_helper/test_helper.h
@@ -0,0 +1,292 @@
1/* $OpenBSD: test_helper.h,v 1.3 2014/05/02 09:41:32 andre Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18/* Utility functions/framework for regress tests */
19
20#ifndef _TEST_HELPER_H
21#define _TEST_HELPER_H
22
23#include "includes.h"
24
25#include <sys/types.h>
26#ifdef HAVE_STDINT_H
27# include <stdint.h>
28#endif
29
30#include <openssl/bn.h>
31#include <openssl/err.h>
32
33enum test_predicate {
34 TEST_EQ, TEST_NE, TEST_LT, TEST_LE, TEST_GT, TEST_GE
35};
36typedef void (test_onerror_func_t)(void *);
37
38/* Supplied by test suite */
39void tests(void);
40
41const char *test_data_file(const char *name);
42void test_start(const char *n);
43void set_onerror_func(test_onerror_func_t *f, void *ctx);
44void test_done(void);
45void ssl_err_check(const char *file, int line);
46void assert_bignum(const char *file, int line,
47 const char *a1, const char *a2,
48 const BIGNUM *aa1, const BIGNUM *aa2, enum test_predicate pred);
49void assert_string(const char *file, int line,
50 const char *a1, const char *a2,
51 const char *aa1, const char *aa2, enum test_predicate pred);
52void assert_mem(const char *file, int line,
53 const char *a1, const char *a2,
54 const void *aa1, const void *aa2, size_t l, enum test_predicate pred);
55void assert_mem_filled(const char *file, int line,
56 const char *a1,
57 const void *aa1, u_char v, size_t l, enum test_predicate pred);
58void assert_int(const char *file, int line,
59 const char *a1, const char *a2,
60 int aa1, int aa2, enum test_predicate pred);
61void assert_size_t(const char *file, int line,
62 const char *a1, const char *a2,
63 size_t aa1, size_t aa2, enum test_predicate pred);
64void assert_u_int(const char *file, int line,
65 const char *a1, const char *a2,
66 u_int aa1, u_int aa2, enum test_predicate pred);
67void assert_long_long(const char *file, int line,
68 const char *a1, const char *a2,
69 long long aa1, long long aa2, enum test_predicate pred);
70void assert_char(const char *file, int line,
71 const char *a1, const char *a2,
72 char aa1, char aa2, enum test_predicate pred);
73void assert_ptr(const char *file, int line,
74 const char *a1, const char *a2,
75 const void *aa1, const void *aa2, enum test_predicate pred);
76void assert_u8(const char *file, int line,
77 const char *a1, const char *a2,
78 u_int8_t aa1, u_int8_t aa2, enum test_predicate pred);
79void assert_u16(const char *file, int line,
80 const char *a1, const char *a2,
81 u_int16_t aa1, u_int16_t aa2, enum test_predicate pred);
82void assert_u32(const char *file, int line,
83 const char *a1, const char *a2,
84 u_int32_t aa1, u_int32_t aa2, enum test_predicate pred);
85void assert_u64(const char *file, int line,
86 const char *a1, const char *a2,
87 u_int64_t aa1, u_int64_t aa2, enum test_predicate pred);
88
89#define TEST_START(n) test_start(n)
90#define TEST_DONE() test_done()
91#define TEST_ONERROR(f, c) set_onerror_func(f, c)
92#define SSL_ERR_CHECK() ssl_err_check(__FILE__, __LINE__)
93
94#define ASSERT_BIGNUM_EQ(a1, a2) \
95 assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
96#define ASSERT_STRING_EQ(a1, a2) \
97 assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
98#define ASSERT_MEM_EQ(a1, a2, l) \
99 assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_EQ)
100#define ASSERT_MEM_FILLED_EQ(a1, c, l) \
101 assert_mem_filled(__FILE__, __LINE__, #a1, a1, c, l, TEST_EQ)
102#define ASSERT_MEM_ZERO_EQ(a1, l) \
103 assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_EQ)
104#define ASSERT_INT_EQ(a1, a2) \
105 assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
106#define ASSERT_SIZE_T_EQ(a1, a2) \
107 assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
108#define ASSERT_U_INT_EQ(a1, a2) \
109 assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
110#define ASSERT_LONG_LONG_EQ(a1, a2) \
111 assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
112#define ASSERT_CHAR_EQ(a1, a2) \
113 assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
114#define ASSERT_PTR_EQ(a1, a2) \
115 assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
116#define ASSERT_U8_EQ(a1, a2) \
117 assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
118#define ASSERT_U16_EQ(a1, a2) \
119 assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
120#define ASSERT_U32_EQ(a1, a2) \
121 assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
122#define ASSERT_U64_EQ(a1, a2) \
123 assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_EQ)
124
125#define ASSERT_BIGNUM_NE(a1, a2) \
126 assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
127#define ASSERT_STRING_NE(a1, a2) \
128 assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
129#define ASSERT_MEM_NE(a1, a2, l) \
130 assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_NE)
131#define ASSERT_MEM_ZERO_NE(a1, l) \
132 assert_mem_filled(__FILE__, __LINE__, #a1, a1, '\0', l, TEST_NE)
133#define ASSERT_INT_NE(a1, a2) \
134 assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
135#define ASSERT_SIZE_T_NE(a1, a2) \
136 assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
137#define ASSERT_U_INT_NE(a1, a2) \
138 assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
139#define ASSERT_LONG_LONG_NE(a1, a2) \
140 assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
141#define ASSERT_CHAR_NE(a1, a2) \
142 assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
143#define ASSERT_PTR_NE(a1, a2) \
144 assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
145#define ASSERT_U8_NE(a1, a2) \
146 assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
147#define ASSERT_U16_NE(a1, a2) \
148 assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
149#define ASSERT_U32_NE(a1, a2) \
150 assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
151#define ASSERT_U64_NE(a1, a2) \
152 assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_NE)
153
154#define ASSERT_BIGNUM_LT(a1, a2) \
155 assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
156#define ASSERT_STRING_LT(a1, a2) \
157 assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
158#define ASSERT_MEM_LT(a1, a2, l) \
159 assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LT)
160#define ASSERT_INT_LT(a1, a2) \
161 assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
162#define ASSERT_SIZE_T_LT(a1, a2) \
163 assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
164#define ASSERT_U_INT_LT(a1, a2) \
165 assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
166#define ASSERT_LONG_LONG_LT(a1, a2) \
167 assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
168#define ASSERT_CHAR_LT(a1, a2) \
169 assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
170#define ASSERT_PTR_LT(a1, a2) \
171 assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
172#define ASSERT_U8_LT(a1, a2) \
173 assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
174#define ASSERT_U16_LT(a1, a2) \
175 assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
176#define ASSERT_U32_LT(a1, a2) \
177 assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
178#define ASSERT_U64_LT(a1, a2) \
179 assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LT)
180
181#define ASSERT_BIGNUM_LE(a1, a2) \
182 assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
183#define ASSERT_STRING_LE(a1, a2) \
184 assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
185#define ASSERT_MEM_LE(a1, a2, l) \
186 assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_LE)
187#define ASSERT_INT_LE(a1, a2) \
188 assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
189#define ASSERT_SIZE_T_LE(a1, a2) \
190 assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
191#define ASSERT_U_INT_LE(a1, a2) \
192 assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
193#define ASSERT_LONG_LONG_LE(a1, a2) \
194 assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
195#define ASSERT_CHAR_LE(a1, a2) \
196 assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
197#define ASSERT_PTR_LE(a1, a2) \
198 assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
199#define ASSERT_U8_LE(a1, a2) \
200 assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
201#define ASSERT_U16_LE(a1, a2) \
202 assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
203#define ASSERT_U32_LE(a1, a2) \
204 assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
205#define ASSERT_U64_LE(a1, a2) \
206 assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_LE)
207
208#define ASSERT_BIGNUM_GT(a1, a2) \
209 assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
210#define ASSERT_STRING_GT(a1, a2) \
211 assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
212#define ASSERT_MEM_GT(a1, a2, l) \
213 assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GT)
214#define ASSERT_INT_GT(a1, a2) \
215 assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
216#define ASSERT_SIZE_T_GT(a1, a2) \
217 assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
218#define ASSERT_U_INT_GT(a1, a2) \
219 assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
220#define ASSERT_LONG_LONG_GT(a1, a2) \
221 assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
222#define ASSERT_CHAR_GT(a1, a2) \
223 assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
224#define ASSERT_PTR_GT(a1, a2) \
225 assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
226#define ASSERT_U8_GT(a1, a2) \
227 assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
228#define ASSERT_U16_GT(a1, a2) \
229 assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
230#define ASSERT_U32_GT(a1, a2) \
231 assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
232#define ASSERT_U64_GT(a1, a2) \
233 assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GT)
234
235#define ASSERT_BIGNUM_GE(a1, a2) \
236 assert_bignum(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
237#define ASSERT_STRING_GE(a1, a2) \
238 assert_string(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
239#define ASSERT_MEM_GE(a1, a2, l) \
240 assert_mem(__FILE__, __LINE__, #a1, #a2, a1, a2, l, TEST_GE)
241#define ASSERT_INT_GE(a1, a2) \
242 assert_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
243#define ASSERT_SIZE_T_GE(a1, a2) \
244 assert_size_t(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
245#define ASSERT_U_INT_GE(a1, a2) \
246 assert_u_int(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
247#define ASSERT_LONG_LONG_GE(a1, a2) \
248 assert_long_long(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
249#define ASSERT_CHAR_GE(a1, a2) \
250 assert_char(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
251#define ASSERT_PTR_GE(a1, a2) \
252 assert_ptr(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
253#define ASSERT_U8_GE(a1, a2) \
254 assert_u8(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
255#define ASSERT_U16_GE(a1, a2) \
256 assert_u16(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
257#define ASSERT_U32_GE(a1, a2) \
258 assert_u32(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
259#define ASSERT_U64_GE(a1, a2) \
260 assert_u64(__FILE__, __LINE__, #a1, #a2, a1, a2, TEST_GE)
261
262/* Fuzzing support */
263
264struct fuzz;
265#define FUZZ_1_BIT_FLIP 0x00000001 /* Flip one bit at a time */
266#define FUZZ_2_BIT_FLIP 0x00000002 /* Flip two bits at a time */
267#define FUZZ_1_BYTE_FLIP 0x00000004 /* Flip one byte at a time */
268#define FUZZ_2_BYTE_FLIP 0x00000008 /* Flip two bytes at a time */
269#define FUZZ_TRUNCATE_START 0x00000010 /* Truncate from beginning */
270#define FUZZ_TRUNCATE_END 0x00000020 /* Truncate from end */
271#define FUZZ_BASE64 0x00000040 /* Try all base64 chars */
272#define FUZZ_MAX FUZZ_BASE64
273
274/* Start fuzzing a blob of data with selected strategies (bitmask) */
275struct fuzz *fuzz_begin(u_int strategies, const void *p, size_t l);
276
277/* Free a fuzz context */
278void fuzz_cleanup(struct fuzz *fuzz);
279
280/* Prepare the next fuzz case in the series */
281void fuzz_next(struct fuzz *fuzz);
282
283/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */
284int fuzz_done(struct fuzz *fuzz);
285
286/* Return the length and a pointer to the current fuzzed case */
287size_t fuzz_len(struct fuzz *fuzz);
288u_char *fuzz_ptr(struct fuzz *fuzz);
289
290/* Dump the current fuzz case to stderr */
291void fuzz_dump(struct fuzz *fuzz);
292#endif /* _TEST_HELPER_H */
diff --git a/rijndael.c b/rijndael.c
index 7432ea2e4..cde90789e 100644
--- a/rijndael.c
+++ b/rijndael.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: rijndael.c,v 1.16 2004/06/23 00:39:38 mouring Exp $ */ 1/* $OpenBSD: rijndael.c,v 1.18 2014/04/29 15:42:07 markus Exp $ */
2 2
3/** 3/**
4 * rijndael-alg-fst.c 4 * rijndael-alg-fst.c
@@ -25,6 +25,7 @@
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28
28#include "includes.h" 29#include "includes.h"
29 30
30#include <stdlib.h> 31#include <stdlib.h>
@@ -32,7 +33,7 @@
32 33
33#include "rijndael.h" 34#include "rijndael.h"
34 35
35#define FULL_UNROLL 36#undef FULL_UNROLL
36 37
37/* 38/*
38Te0[x] = S [x].[02, 01, 01, 03]; 39Te0[x] = S [x].[02, 01, 01, 03];
@@ -247,7 +248,6 @@ static const u32 Te2[256] = {
247 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U, 248 0xb0cb7bb0U, 0x54fca854U, 0xbbd66dbbU, 0x163a2c16U,
248}; 249};
249static const u32 Te3[256] = { 250static const u32 Te3[256] = {
250
251 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U, 251 0x6363a5c6U, 0x7c7c84f8U, 0x777799eeU, 0x7b7b8df6U,
252 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U, 252 0xf2f20dffU, 0x6b6bbdd6U, 0x6f6fb1deU, 0xc5c55491U,
253 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U, 253 0x30305060U, 0x01010302U, 0x6767a9ceU, 0x2b2b7d56U,
@@ -532,7 +532,6 @@ static const u32 Td2[256] = {
532 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U, 532 0xf4cd65daU, 0xbed50605U, 0x621fd134U, 0xfe8ac4a6U,
533 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U, 533 0x539d342eU, 0x55a0a2f3U, 0xe132058aU, 0xeb75a4f6U,
534 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU, 534 0xec390b83U, 0xefaa4060U, 0x9f065e71U, 0x1051bd6eU,
535
536 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U, 535 0x8af93e21U, 0x063d96ddU, 0x05aedd3eU, 0xbd464de6U,
537 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U, 536 0x8db59154U, 0x5d0571c4U, 0xd46f0406U, 0x15ff6050U,
538 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U, 537 0xfb241998U, 0xe997d6bdU, 0x43cc8940U, 0x9e7767d9U,
@@ -724,8 +723,10 @@ static const u32 rcon[] = {
724 * 723 *
725 * @return the number of rounds for the given cipher key size. 724 * @return the number of rounds for the given cipher key size.
726 */ 725 */
727static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits) { 726int
728 int i = 0; 727rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits)
728{
729 int i = 0;
729 u32 temp; 730 u32 temp;
730 731
731 rk[0] = GETU32(cipherKey ); 732 rk[0] = GETU32(cipherKey );
@@ -786,9 +787,9 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int
786 rk[ 9] = rk[ 1] ^ rk[ 8]; 787 rk[ 9] = rk[ 1] ^ rk[ 8];
787 rk[10] = rk[ 2] ^ rk[ 9]; 788 rk[10] = rk[ 2] ^ rk[ 9];
788 rk[11] = rk[ 3] ^ rk[10]; 789 rk[11] = rk[ 3] ^ rk[10];
789 if (++i == 7) { 790 if (++i == 7) {
790 return 14; 791 return 14;
791 } 792 }
792 temp = rk[11]; 793 temp = rk[11];
793 rk[12] = rk[ 4] ^ 794 rk[12] = rk[ 4] ^
794 (Te4[(temp >> 24) ] & 0xff000000) ^ 795 (Te4[(temp >> 24) ] & 0xff000000) ^
@@ -797,7 +798,7 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int
797 (Te4[(temp ) & 0xff] & 0x000000ff); 798 (Te4[(temp ) & 0xff] & 0x000000ff);
798 rk[13] = rk[ 5] ^ rk[12]; 799 rk[13] = rk[ 5] ^ rk[12];
799 rk[14] = rk[ 6] ^ rk[13]; 800 rk[14] = rk[ 6] ^ rk[13];
800 rk[15] = rk[ 7] ^ rk[14]; 801 rk[15] = rk[ 7] ^ rk[14];
801 rk += 8; 802 rk += 8;
802 } 803 }
803 } 804 }
@@ -809,18 +810,21 @@ static int rijndaelKeySetupEnc(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int
809 * 810 *
810 * @return the number of rounds for the given cipher key size. 811 * @return the number of rounds for the given cipher key size.
811 */ 812 */
812static int 813int
813rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits, 814rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits,
814 int have_encrypt) { 815 int have_encrypt)
816{
815 int Nr, i, j; 817 int Nr, i, j;
816 u32 temp; 818 u32 temp;
817 819
818 if (have_encrypt) { 820 /* expand the cipher key: */
821 if (have_encrypt > 0) {
822 /* Already done */
819 Nr = have_encrypt; 823 Nr = have_encrypt;
820 } else { 824 } else {
821 /* expand the cipher key: */
822 Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits); 825 Nr = rijndaelKeySetupEnc(rk, cipherKey, keyBits);
823 } 826 }
827
824 /* invert the order of the round keys: */ 828 /* invert the order of the round keys: */
825 for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) { 829 for (i = 0, j = 4*Nr; i < j; i += 4, j -= 4) {
826 temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp; 830 temp = rk[i ]; rk[i ] = rk[j ]; rk[j ] = temp;
@@ -855,7 +859,10 @@ rijndaelKeySetupDec(u32 rk[/*4*(Nr + 1)*/], const u8 cipherKey[], int keyBits,
855 return Nr; 859 return Nr;
856} 860}
857 861
858static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16], u8 ct[16]) { 862void
863rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16],
864 u8 ct[16])
865{
859 u32 s0, s1, s2, s3, t0, t1, t2, t3; 866 u32 s0, s1, s2, s3, t0, t1, t2, t3;
860#ifndef FULL_UNROLL 867#ifndef FULL_UNROLL
861 int r; 868 int r;
@@ -871,50 +878,50 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
871 s3 = GETU32(pt + 12) ^ rk[3]; 878 s3 = GETU32(pt + 12) ^ rk[3];
872#ifdef FULL_UNROLL 879#ifdef FULL_UNROLL
873 /* round 1: */ 880 /* round 1: */
874 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4]; 881 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[ 4];
875 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5]; 882 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[ 5];
876 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6]; 883 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[ 6];
877 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7]; 884 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[ 7];
878 /* round 2: */ 885 /* round 2: */
879 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8]; 886 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[ 8];
880 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9]; 887 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[ 9];
881 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10]; 888 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[10];
882 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11]; 889 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[11];
883 /* round 3: */ 890 /* round 3: */
884 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12]; 891 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[12];
885 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13]; 892 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[13];
886 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14]; 893 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[14];
887 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15]; 894 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[15];
888 /* round 4: */ 895 /* round 4: */
889 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16]; 896 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[16];
890 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17]; 897 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[17];
891 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18]; 898 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[18];
892 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19]; 899 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[19];
893 /* round 5: */ 900 /* round 5: */
894 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20]; 901 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[20];
895 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21]; 902 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[21];
896 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22]; 903 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[22];
897 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23]; 904 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[23];
898 /* round 6: */ 905 /* round 6: */
899 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24]; 906 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[24];
900 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25]; 907 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[25];
901 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26]; 908 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[26];
902 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27]; 909 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[27];
903 /* round 7: */ 910 /* round 7: */
904 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28]; 911 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[28];
905 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29]; 912 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[29];
906 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30]; 913 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[30];
907 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31]; 914 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[31];
908 /* round 8: */ 915 /* round 8: */
909 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32]; 916 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[32];
910 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33]; 917 s1 = Te0[t1 >> 24] ^ Te1[(t2 >> 16) & 0xff] ^ Te2[(t3 >> 8) & 0xff] ^ Te3[t0 & 0xff] ^ rk[33];
911 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34]; 918 s2 = Te0[t2 >> 24] ^ Te1[(t3 >> 16) & 0xff] ^ Te2[(t0 >> 8) & 0xff] ^ Te3[t1 & 0xff] ^ rk[34];
912 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35]; 919 s3 = Te0[t3 >> 24] ^ Te1[(t0 >> 16) & 0xff] ^ Te2[(t1 >> 8) & 0xff] ^ Te3[t2 & 0xff] ^ rk[35];
913 /* round 9: */ 920 /* round 9: */
914 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36]; 921 t0 = Te0[s0 >> 24] ^ Te1[(s1 >> 16) & 0xff] ^ Te2[(s2 >> 8) & 0xff] ^ Te3[s3 & 0xff] ^ rk[36];
915 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37]; 922 t1 = Te0[s1 >> 24] ^ Te1[(s2 >> 16) & 0xff] ^ Te2[(s3 >> 8) & 0xff] ^ Te3[s0 & 0xff] ^ rk[37];
916 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38]; 923 t2 = Te0[s2 >> 24] ^ Te1[(s3 >> 16) & 0xff] ^ Te2[(s0 >> 8) & 0xff] ^ Te3[s1 & 0xff] ^ rk[38];
917 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39]; 924 t3 = Te0[s3 >> 24] ^ Te1[(s0 >> 16) & 0xff] ^ Te2[(s1 >> 8) & 0xff] ^ Te3[s2 & 0xff] ^ rk[39];
918 if (Nr > 10) { 925 if (Nr > 10) {
919 /* round 10: */ 926 /* round 10: */
920 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40]; 927 s0 = Te0[t0 >> 24] ^ Te1[(t1 >> 16) & 0xff] ^ Te2[(t2 >> 8) & 0xff] ^ Te3[t3 & 0xff] ^ rk[40];
@@ -1036,7 +1043,10 @@ static void rijndaelEncrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 pt[16
1036 PUTU32(ct + 12, s3); 1043 PUTU32(ct + 12, s3);
1037} 1044}
1038 1045
1039static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16], u8 pt[16]) { 1046static void
1047rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16],
1048 u8 pt[16])
1049{
1040 u32 s0, s1, s2, s3, t0, t1, t2, t3; 1050 u32 s0, s1, s2, s3, t0, t1, t2, t3;
1041#ifndef FULL_UNROLL 1051#ifndef FULL_UNROLL
1042 int r; 1052 int r;
@@ -1187,33 +1197,33 @@ static void rijndaelDecrypt(const u32 rk[/*4*(Nr + 1)*/], int Nr, const u8 ct[16
1187 * apply last round and 1197 * apply last round and
1188 * map cipher state to byte array block: 1198 * map cipher state to byte array block:
1189 */ 1199 */
1190 s0 = 1200 s0 =
1191 (Td4[(t0 >> 24) ] & 0xff000000) ^ 1201 (Td4[(t0 >> 24) ] & 0xff000000) ^
1192 (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^ 1202 (Td4[(t3 >> 16) & 0xff] & 0x00ff0000) ^
1193 (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^ 1203 (Td4[(t2 >> 8) & 0xff] & 0x0000ff00) ^
1194 (Td4[(t1 ) & 0xff] & 0x000000ff) ^ 1204 (Td4[(t1 ) & 0xff] & 0x000000ff) ^
1195 rk[0]; 1205 rk[0];
1196 PUTU32(pt , s0); 1206 PUTU32(pt , s0);
1197 s1 = 1207 s1 =
1198 (Td4[(t1 >> 24) ] & 0xff000000) ^ 1208 (Td4[(t1 >> 24) ] & 0xff000000) ^
1199 (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^ 1209 (Td4[(t0 >> 16) & 0xff] & 0x00ff0000) ^
1200 (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^ 1210 (Td4[(t3 >> 8) & 0xff] & 0x0000ff00) ^
1201 (Td4[(t2 ) & 0xff] & 0x000000ff) ^ 1211 (Td4[(t2 ) & 0xff] & 0x000000ff) ^
1202 rk[1]; 1212 rk[1];
1203 PUTU32(pt + 4, s1); 1213 PUTU32(pt + 4, s1);
1204 s2 = 1214 s2 =
1205 (Td4[(t2 >> 24) ] & 0xff000000) ^ 1215 (Td4[(t2 >> 24) ] & 0xff000000) ^
1206 (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^ 1216 (Td4[(t1 >> 16) & 0xff] & 0x00ff0000) ^
1207 (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^ 1217 (Td4[(t0 >> 8) & 0xff] & 0x0000ff00) ^
1208 (Td4[(t3 ) & 0xff] & 0x000000ff) ^ 1218 (Td4[(t3 ) & 0xff] & 0x000000ff) ^
1209 rk[2]; 1219 rk[2];
1210 PUTU32(pt + 8, s2); 1220 PUTU32(pt + 8, s2);
1211 s3 = 1221 s3 =
1212 (Td4[(t3 >> 24) ] & 0xff000000) ^ 1222 (Td4[(t3 >> 24) ] & 0xff000000) ^
1213 (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^ 1223 (Td4[(t2 >> 16) & 0xff] & 0x00ff0000) ^
1214 (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^ 1224 (Td4[(t1 >> 8) & 0xff] & 0x0000ff00) ^
1215 (Td4[(t0 ) & 0xff] & 0x000000ff) ^ 1225 (Td4[(t0 ) & 0xff] & 0x000000ff) ^
1216 rk[3]; 1226 rk[3];
1217 PUTU32(pt + 12, s3); 1227 PUTU32(pt + 12, s3);
1218} 1228}
1219 1229
diff --git a/rijndael.h b/rijndael.h
index c614bb188..53e74e0a8 100644
--- a/rijndael.h
+++ b/rijndael.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: rijndael.h,v 1.12 2001/12/19 07:18:56 deraadt Exp $ */ 1/* $OpenBSD: rijndael.h,v 1.14 2014/04/29 15:42:07 markus Exp $ */
2 2
3/** 3/**
4 * rijndael-alg-fst.h 4 * rijndael-alg-fst.h
@@ -25,27 +25,32 @@
25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, 25 * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 * EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */ 27 */
28#ifndef __RIJNDAEL_H 28#ifndef _PRIVATE_RIJNDAEL_H
29#define __RIJNDAEL_H 29#define _PRIVATE_RIJNDAEL_H
30 30
31#define MAXKC (256/32) 31#define AES_MAXKEYBITS (256)
32#define MAXKB (256/8) 32#define AES_MAXKEYBYTES (AES_MAXKEYBITS/8)
33#define MAXNR 14 33/* for 256-bit keys, fewer for less */
34#define AES_MAXROUNDS 14
34 35
35typedef unsigned char u8; 36typedef unsigned char u8;
36typedef unsigned short u16; 37typedef unsigned short u16;
37typedef unsigned int u32; 38typedef unsigned int u32;
38 39
40int rijndaelKeySetupEnc(unsigned int [], const unsigned char [], int);
41void rijndaelEncrypt(const unsigned int [], int, const unsigned char [],
42 unsigned char []);
43
39/* The structure for key information */ 44/* The structure for key information */
40typedef struct { 45typedef struct {
41 int decrypt; 46 int decrypt;
42 int Nr; /* key-length-dependent number of rounds */ 47 int Nr; /* key-length-dependent number of rounds */
43 u32 ek[4*(MAXNR + 1)]; /* encrypt key schedule */ 48 u32 ek[4*(AES_MAXROUNDS + 1)]; /* encrypt key schedule */
44 u32 dk[4*(MAXNR + 1)]; /* decrypt key schedule */ 49 u32 dk[4*(AES_MAXROUNDS + 1)]; /* decrypt key schedule */
45} rijndael_ctx; 50} rijndael_ctx;
46 51
47void rijndael_set_key(rijndael_ctx *, u_char *, int, int); 52void rijndael_set_key(rijndael_ctx *, u_char *, int, int);
48void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *); 53void rijndael_decrypt(rijndael_ctx *, u_char *, u_char *);
49void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *); 54void rijndael_encrypt(rijndael_ctx *, u_char *, u_char *);
50 55
51#endif /* __RIJNDAEL_H */ 56#endif /* _PRIVATE_RIJNDAEL_H */
diff --git a/roaming_client.c b/roaming_client.c
index de049cdc1..5e5c28b2b 100644
--- a/roaming_client.c
+++ b/roaming_client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: roaming_client.c,v 1.7 2014/01/09 23:20:00 djm Exp $ */ 1/* $OpenBSD: roaming_client.c,v 1.8 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2004-2009 AppGate Network Security AB 3 * Copyright (c) 2004-2009 AppGate Network Security AB
4 * 4 *
@@ -28,9 +28,6 @@
28#include <string.h> 28#include <string.h>
29#include <unistd.h> 29#include <unistd.h>
30 30
31#include <openssl/crypto.h>
32#include <openssl/sha.h>
33
34#include "xmalloc.h" 31#include "xmalloc.h"
35#include "buffer.h" 32#include "buffer.h"
36#include "channels.h" 33#include "channels.h"
diff --git a/rsa.c b/rsa.c
index d0b5bbf5e..5ecacef90 100644
--- a/rsa.c
+++ b/rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: rsa.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: rsa.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -67,85 +67,122 @@
67#include <stdarg.h> 67#include <stdarg.h>
68#include <string.h> 68#include <string.h>
69 69
70#include "xmalloc.h"
71#include "rsa.h" 70#include "rsa.h"
72#include "log.h" 71#include "log.h"
72#include "ssherr.h"
73 73
74void 74int
75rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key) 75rsa_public_encrypt(BIGNUM *out, BIGNUM *in, RSA *key)
76{ 76{
77 u_char *inbuf, *outbuf; 77 u_char *inbuf = NULL, *outbuf = NULL;
78 int len, ilen, olen; 78 int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
79 79
80 if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e)) 80 if (BN_num_bits(key->e) < 2 || !BN_is_odd(key->e))
81 fatal("rsa_public_encrypt() exponent too small or not odd"); 81 return SSH_ERR_INVALID_ARGUMENT;
82 82
83 olen = BN_num_bytes(key->n); 83 olen = BN_num_bytes(key->n);
84 outbuf = xmalloc(olen); 84 if ((outbuf = malloc(olen)) == NULL) {
85 r = SSH_ERR_ALLOC_FAIL;
86 goto out;
87 }
85 88
86 ilen = BN_num_bytes(in); 89 ilen = BN_num_bytes(in);
87 inbuf = xmalloc(ilen); 90 if ((inbuf = malloc(ilen)) == NULL) {
91 r = SSH_ERR_ALLOC_FAIL;
92 goto out;
93 }
88 BN_bn2bin(in, inbuf); 94 BN_bn2bin(in, inbuf);
89 95
90 if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key, 96 if ((len = RSA_public_encrypt(ilen, inbuf, outbuf, key,
91 RSA_PKCS1_PADDING)) <= 0) 97 RSA_PKCS1_PADDING)) <= 0) {
92 fatal("rsa_public_encrypt() failed"); 98 r = SSH_ERR_LIBCRYPTO_ERROR;
99 goto out;
100 }
93 101
94 if (BN_bin2bn(outbuf, len, out) == NULL) 102 if (BN_bin2bn(outbuf, len, out) == NULL) {
95 fatal("rsa_public_encrypt: BN_bin2bn failed"); 103 r = SSH_ERR_LIBCRYPTO_ERROR;
104 goto out;
105 }
106 r = 0;
96 107
97 explicit_bzero(outbuf, olen); 108 out:
98 explicit_bzero(inbuf, ilen); 109 if (outbuf != NULL) {
99 free(outbuf); 110 explicit_bzero(outbuf, olen);
100 free(inbuf); 111 free(outbuf);
112 }
113 if (inbuf != NULL) {
114 explicit_bzero(inbuf, ilen);
115 free(inbuf);
116 }
117 return r;
101} 118}
102 119
103int 120int
104rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key) 121rsa_private_decrypt(BIGNUM *out, BIGNUM *in, RSA *key)
105{ 122{
106 u_char *inbuf, *outbuf; 123 u_char *inbuf = NULL, *outbuf = NULL;
107 int len, ilen, olen; 124 int len, ilen, olen, r = SSH_ERR_INTERNAL_ERROR;
108 125
109 olen = BN_num_bytes(key->n); 126 olen = BN_num_bytes(key->n);
110 outbuf = xmalloc(olen); 127 if ((outbuf = malloc(olen)) == NULL) {
128 r = SSH_ERR_ALLOC_FAIL;
129 goto out;
130 }
111 131
112 ilen = BN_num_bytes(in); 132 ilen = BN_num_bytes(in);
113 inbuf = xmalloc(ilen); 133 if ((inbuf = malloc(ilen)) == NULL) {
134 r = SSH_ERR_ALLOC_FAIL;
135 goto out;
136 }
114 BN_bn2bin(in, inbuf); 137 BN_bn2bin(in, inbuf);
115 138
116 if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key, 139 if ((len = RSA_private_decrypt(ilen, inbuf, outbuf, key,
117 RSA_PKCS1_PADDING)) <= 0) { 140 RSA_PKCS1_PADDING)) <= 0) {
118 error("rsa_private_decrypt() failed"); 141 r = SSH_ERR_LIBCRYPTO_ERROR;
119 } else { 142 goto out;
120 if (BN_bin2bn(outbuf, len, out) == NULL) 143 } else if (BN_bin2bn(outbuf, len, out) == NULL) {
121 fatal("rsa_private_decrypt: BN_bin2bn failed"); 144 r = SSH_ERR_LIBCRYPTO_ERROR;
145 goto out;
146 }
147 r = 0;
148 out:
149 if (outbuf != NULL) {
150 explicit_bzero(outbuf, olen);
151 free(outbuf);
152 }
153 if (inbuf != NULL) {
154 explicit_bzero(inbuf, ilen);
155 free(inbuf);
122 } 156 }
123 explicit_bzero(outbuf, olen); 157 return r;
124 explicit_bzero(inbuf, ilen);
125 free(outbuf);
126 free(inbuf);
127 return len;
128} 158}
129 159
130/* calculate p-1 and q-1 */ 160/* calculate p-1 and q-1 */
131void 161int
132rsa_generate_additional_parameters(RSA *rsa) 162rsa_generate_additional_parameters(RSA *rsa)
133{ 163{
134 BIGNUM *aux; 164 BIGNUM *aux = NULL;
135 BN_CTX *ctx; 165 BN_CTX *ctx = NULL;
166 int r;
136 167
137 if ((aux = BN_new()) == NULL)
138 fatal("rsa_generate_additional_parameters: BN_new failed");
139 if ((ctx = BN_CTX_new()) == NULL) 168 if ((ctx = BN_CTX_new()) == NULL)
140 fatal("rsa_generate_additional_parameters: BN_CTX_new failed"); 169 return SSH_ERR_ALLOC_FAIL;
170 if ((aux = BN_new()) == NULL) {
171 r = SSH_ERR_ALLOC_FAIL;
172 goto out;
173 }
141 174
142 if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) || 175 if ((BN_sub(aux, rsa->q, BN_value_one()) == 0) ||
143 (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) || 176 (BN_mod(rsa->dmq1, rsa->d, aux, ctx) == 0) ||
144 (BN_sub(aux, rsa->p, BN_value_one()) == 0) || 177 (BN_sub(aux, rsa->p, BN_value_one()) == 0) ||
145 (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) 178 (BN_mod(rsa->dmp1, rsa->d, aux, ctx) == 0)) {
146 fatal("rsa_generate_additional_parameters: BN_sub/mod failed"); 179 r = SSH_ERR_LIBCRYPTO_ERROR;
147 180 goto out;
181 }
182 r = 0;
183 out:
148 BN_clear_free(aux); 184 BN_clear_free(aux);
149 BN_CTX_free(ctx); 185 BN_CTX_free(ctx);
186 return r;
150} 187}
151 188
diff --git a/rsa.h b/rsa.h
index b841ea4e1..c476707d5 100644
--- a/rsa.h
+++ b/rsa.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: rsa.h,v 1.16 2006/03/25 22:22:43 djm Exp $ */ 1/* $OpenBSD: rsa.h,v 1.17 2014/06/24 01:13:21 djm Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -19,8 +19,8 @@
19#include <openssl/bn.h> 19#include <openssl/bn.h>
20#include <openssl/rsa.h> 20#include <openssl/rsa.h>
21 21
22void rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *); 22int rsa_public_encrypt(BIGNUM *, BIGNUM *, RSA *);
23int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *); 23int rsa_private_decrypt(BIGNUM *, BIGNUM *, RSA *);
24void rsa_generate_additional_parameters(RSA *); 24int rsa_generate_additional_parameters(RSA *);
25 25
26#endif /* RSA_H */ 26#endif /* RSA_H */
diff --git a/sandbox-seccomp-filter.c b/sandbox-seccomp-filter.c
index c0c17c2fc..b6f6258f2 100644
--- a/sandbox-seccomp-filter.c
+++ b/sandbox-seccomp-filter.c
@@ -25,6 +25,8 @@
25 */ 25 */
26/* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */ 26/* #define SANDBOX_SECCOMP_FILTER_DEBUG 1 */
27 27
28/* XXX it should be possible to do logging via the log socket safely */
29
28#ifdef SANDBOX_SECCOMP_FILTER_DEBUG 30#ifdef SANDBOX_SECCOMP_FILTER_DEBUG
29/* Use the kernel headers in case of an older toolchain. */ 31/* Use the kernel headers in case of an older toolchain. */
30# include <asm/siginfo.h> 32# include <asm/siginfo.h>
@@ -89,6 +91,7 @@ static const struct sock_filter preauth_insns[] = {
89 BPF_STMT(BPF_LD+BPF_W+BPF_ABS, 91 BPF_STMT(BPF_LD+BPF_W+BPF_ABS,
90 offsetof(struct seccomp_data, nr)), 92 offsetof(struct seccomp_data, nr)),
91 SC_DENY(open, EACCES), 93 SC_DENY(open, EACCES),
94 SC_DENY(stat, EACCES),
92 SC_ALLOW(getpid), 95 SC_ALLOW(getpid),
93 SC_ALLOW(gettimeofday), 96 SC_ALLOW(gettimeofday),
94 SC_ALLOW(clock_gettime), 97 SC_ALLOW(clock_gettime),
@@ -115,6 +118,10 @@ static const struct sock_filter preauth_insns[] = {
115#ifdef __NR_mmap 118#ifdef __NR_mmap
116 SC_ALLOW(mmap), 119 SC_ALLOW(mmap),
117#endif 120#endif
121#ifdef __dietlibc__
122 SC_ALLOW(mremap),
123 SC_ALLOW(exit),
124#endif
118 SC_ALLOW(munmap), 125 SC_ALLOW(munmap),
119 SC_ALLOW(exit_group), 126 SC_ALLOW(exit_group),
120#ifdef __NR_rt_sigprocmask 127#ifdef __NR_rt_sigprocmask
diff --git a/sandbox-systrace.c b/sandbox-systrace.c
index 6706c9a80..aaa3d8f0a 100644
--- a/sandbox-systrace.c
+++ b/sandbox-systrace.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sandbox-systrace.c,v 1.9 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: sandbox-systrace.c,v 1.13 2014/07/17 00:10:56 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -52,7 +52,17 @@ struct sandbox_policy {
52static const struct sandbox_policy preauth_policy[] = { 52static const struct sandbox_policy preauth_policy[] = {
53 { SYS_open, SYSTR_POLICY_NEVER }, 53 { SYS_open, SYSTR_POLICY_NEVER },
54 54
55#ifdef SYS_getentropy
56 /* OpenBSD 5.6 and newer use getentropy(2) to seed arc4random(3). */
57 { SYS_getentropy, SYSTR_POLICY_PERMIT },
58#else
59 /* Previous releases used sysctl(3)'s kern.arnd variable. */
55 { SYS___sysctl, SYSTR_POLICY_PERMIT }, 60 { SYS___sysctl, SYSTR_POLICY_PERMIT },
61#endif
62
63#ifdef SYS_sendsyslog
64 { SYS_sendsyslog, SYSTR_POLICY_PERMIT },
65#endif
56 { SYS_close, SYSTR_POLICY_PERMIT }, 66 { SYS_close, SYSTR_POLICY_PERMIT },
57 { SYS_exit, SYSTR_POLICY_PERMIT }, 67 { SYS_exit, SYSTR_POLICY_PERMIT },
58 { SYS_getpid, SYSTR_POLICY_PERMIT }, 68 { SYS_getpid, SYSTR_POLICY_PERMIT },
diff --git a/scp.0 b/scp.0
index b9eeffc4e..0495f2555 100644
--- a/scp.0
+++ b/scp.0
@@ -1,4 +1,4 @@
1SCP(1) OpenBSD Reference Manual SCP(1) 1SCP(1) General Commands Manual SCP(1)
2 2
3NAME 3NAME
4 scp - secure copy (remote file copy program) 4 scp - secure copy (remote file copy program)
@@ -11,8 +11,8 @@ SYNOPSIS
11DESCRIPTION 11DESCRIPTION
12 scp copies files between hosts on a network. It uses ssh(1) for data 12 scp copies files between hosts on a network. It uses ssh(1) for data
13 transfer, and uses the same authentication and provides the same security 13 transfer, and uses the same authentication and provides the same security
14 as ssh(1). Unlike rcp(1), scp will ask for passwords or passphrases if 14 as ssh(1). scp will ask for passwords or passphrases if they are needed
15 they are needed for authentication. 15 for authentication.
16 16
17 File names may contain a user and host specification to indicate that the 17 File names may contain a user and host specification to indicate that the
18 file is to be copied to/from that host. Local file names can be made 18 file is to be copied to/from that host. Local file names can be made
@@ -125,8 +125,7 @@ DESCRIPTION
125 -P port 125 -P port
126 Specifies the port to connect to on the remote host. Note that 126 Specifies the port to connect to on the remote host. Note that
127 this option is written with a capital `P', because -p is already 127 this option is written with a capital `P', because -p is already
128 reserved for preserving the times and modes of the file in 128 reserved for preserving the times and modes of the file.
129 rcp(1).
130 129
131 -p Preserves modification times, access times, and modes from the 130 -p Preserves modification times, access times, and modes from the
132 original file. 131 original file.
@@ -149,15 +148,15 @@ EXIT STATUS
149 The scp utility exits 0 on success, and >0 if an error occurs. 148 The scp utility exits 0 on success, and >0 if an error occurs.
150 149
151SEE ALSO 150SEE ALSO
152 rcp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), 151 sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh_config(5),
153 ssh_config(5), sshd(8) 152 sshd(8)
154 153
155HISTORY 154HISTORY
156 scp is based on the rcp(1) program in BSD source code from the Regents of 155 scp is based on the rcp program in BSD source code from the Regents of
157 the University of California. 156 the University of California.
158 157
159AUTHORS 158AUTHORS
160 Timo Rinne <tri@iki.fi> 159 Timo Rinne <tri@iki.fi>
161 Tatu Ylonen <ylo@cs.hut.fi> 160 Tatu Ylonen <ylo@cs.hut.fi>
162 161
163OpenBSD 5.5 October 20, 2013 OpenBSD 5.5 162OpenBSD 5.6 March 19, 2014 OpenBSD 5.6
diff --git a/scp.1 b/scp.1
index 3b67cff0e..1791b6189 100644
--- a/scp.1
+++ b/scp.1
@@ -8,9 +8,9 @@
8.\" 8.\"
9.\" Created: Sun May 7 00:14:37 1995 ylo 9.\" Created: Sun May 7 00:14:37 1995 ylo
10.\" 10.\"
11.\" $OpenBSD: scp.1,v 1.61 2013/10/20 09:51:26 djm Exp $ 11.\" $OpenBSD: scp.1,v 1.62 2014/03/19 14:42:44 tedu Exp $
12.\" 12.\"
13.Dd $Mdocdate: October 20 2013 $ 13.Dd $Mdocdate: March 19 2014 $
14.Dt SCP 1 14.Dt SCP 1
15.Os 15.Os
16.Sh NAME 16.Sh NAME
@@ -49,8 +49,6 @@ It uses
49for data transfer, and uses the same authentication and provides the 49for data transfer, and uses the same authentication and provides the
50same security as 50same security as
51.Xr ssh 1 . 51.Xr ssh 1 .
52Unlike
53.Xr rcp 1 ,
54.Nm 52.Nm
55will ask for passwords or passphrases if they are needed for 53will ask for passwords or passphrases if they are needed for
56authentication. 54authentication.
@@ -191,8 +189,7 @@ Note that this option is written with a capital
191.Sq P , 189.Sq P ,
192because 190because
193.Fl p 191.Fl p
194is already reserved for preserving the times and modes of the file in 192is already reserved for preserving the times and modes of the file.
195.Xr rcp 1 .
196.It Fl p 193.It Fl p
197Preserves modification times, access times, and modes from the 194Preserves modification times, access times, and modes from the
198original file. 195original file.
@@ -225,7 +222,6 @@ debugging connection, authentication, and configuration problems.
225.Sh EXIT STATUS 222.Sh EXIT STATUS
226.Ex -std scp 223.Ex -std scp
227.Sh SEE ALSO 224.Sh SEE ALSO
228.Xr rcp 1 ,
229.Xr sftp 1 , 225.Xr sftp 1 ,
230.Xr ssh 1 , 226.Xr ssh 1 ,
231.Xr ssh-add 1 , 227.Xr ssh-add 1 ,
@@ -235,9 +231,7 @@ debugging connection, authentication, and configuration problems.
235.Xr sshd 8 231.Xr sshd 8
236.Sh HISTORY 232.Sh HISTORY
237.Nm 233.Nm
238is based on the 234is based on the rcp program in
239.Xr rcp 1
240program in
241.Bx 235.Bx
242source code from the Regents of the University of California. 236source code from the Regents of the University of California.
243.Sh AUTHORS 237.Sh AUTHORS
diff --git a/scp.c b/scp.c
index 0669d0215..a1b318b9f 100644
--- a/scp.c
+++ b/scp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: scp.c,v 1.179 2013/11/20 20:53:10 deraadt Exp $ */ 1/* $OpenBSD: scp.c,v 1.180 2014/06/24 02:21:01 djm Exp $ */
2/* 2/*
3 * scp - secure remote copy. This is basically patched BSD rcp which 3 * scp - secure remote copy. This is basically patched BSD rcp which
4 * uses ssh to do the data transfer (instead of using rcmd). 4 * uses ssh to do the data transfer (instead of using rcmd).
@@ -755,7 +755,7 @@ source(int argc, char **argv)
755 static BUF buffer; 755 static BUF buffer;
756 BUF *bp; 756 BUF *bp;
757 off_t i, statbytes; 757 off_t i, statbytes;
758 size_t amt; 758 size_t amt, nr;
759 int fd = -1, haderr, indx; 759 int fd = -1, haderr, indx;
760 char *last, *name, buf[2048], encname[MAXPATHLEN]; 760 char *last, *name, buf[2048], encname[MAXPATHLEN];
761 int len; 761 int len;
@@ -828,12 +828,16 @@ next: if (fd != -1) {
828 if (i + (off_t)amt > stb.st_size) 828 if (i + (off_t)amt > stb.st_size)
829 amt = stb.st_size - i; 829 amt = stb.st_size - i;
830 if (!haderr) { 830 if (!haderr) {
831 if (atomicio(read, fd, bp->buf, amt) != amt) 831 if ((nr = atomicio(read, fd,
832 bp->buf, amt)) != amt) {
832 haderr = errno; 833 haderr = errno;
834 memset(bp->buf + nr, 0, amt - nr);
835 }
833 } 836 }
834 /* Keep writing after error to retain sync */ 837 /* Keep writing after error to retain sync */
835 if (haderr) { 838 if (haderr) {
836 (void)atomicio(vwrite, remout, bp->buf, amt); 839 (void)atomicio(vwrite, remout, bp->buf, amt);
840 memset(bp->buf, 0, amt);
837 continue; 841 continue;
838 } 842 }
839 if (atomicio6(vwrite, remout, bp->buf, amt, scpio, 843 if (atomicio6(vwrite, remout, bp->buf, amt, scpio,
diff --git a/servconf.c b/servconf.c
index 37fd2de6d..6c7741ab2 100644
--- a/servconf.c
+++ b/servconf.c
@@ -1,5 +1,5 @@
1 1
2/* $OpenBSD: servconf.c,v 1.249 2014/01/29 06:18:35 djm Exp $ */ 2/* $OpenBSD: servconf.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
3/* 3/*
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
5 * All rights reserved 5 * All rights reserved
@@ -39,10 +39,10 @@
39#include "ssh.h" 39#include "ssh.h"
40#include "log.h" 40#include "log.h"
41#include "buffer.h" 41#include "buffer.h"
42#include "misc.h"
42#include "servconf.h" 43#include "servconf.h"
43#include "compat.h" 44#include "compat.h"
44#include "pathnames.h" 45#include "pathnames.h"
45#include "misc.h"
46#include "cipher.h" 46#include "cipher.h"
47#include "key.h" 47#include "key.h"
48#include "kex.h" 48#include "kex.h"
@@ -93,6 +93,7 @@ initialize_server_options(ServerOptions *options)
93 options->x11_display_offset = -1; 93 options->x11_display_offset = -1;
94 options->x11_use_localhost = -1; 94 options->x11_use_localhost = -1;
95 options->permit_tty = -1; 95 options->permit_tty = -1;
96 options->permit_user_rc = -1;
96 options->xauth_location = NULL; 97 options->xauth_location = NULL;
97 options->strict_modes = -1; 98 options->strict_modes = -1;
98 options->tcp_keep_alive = -1; 99 options->tcp_keep_alive = -1;
@@ -122,6 +123,7 @@ initialize_server_options(ServerOptions *options)
122 options->rekey_limit = -1; 123 options->rekey_limit = -1;
123 options->rekey_interval = -1; 124 options->rekey_interval = -1;
124 options->allow_tcp_forwarding = -1; 125 options->allow_tcp_forwarding = -1;
126 options->allow_streamlocal_forwarding = -1;
125 options->allow_agent_forwarding = -1; 127 options->allow_agent_forwarding = -1;
126 options->num_allow_users = 0; 128 options->num_allow_users = 0;
127 options->num_deny_users = 0; 129 options->num_deny_users = 0;
@@ -131,7 +133,9 @@ initialize_server_options(ServerOptions *options)
131 options->macs = NULL; 133 options->macs = NULL;
132 options->kex_algorithms = NULL; 134 options->kex_algorithms = NULL;
133 options->protocol = SSH_PROTO_UNKNOWN; 135 options->protocol = SSH_PROTO_UNKNOWN;
134 options->gateway_ports = -1; 136 options->fwd_opts.gateway_ports = -1;
137 options->fwd_opts.streamlocal_bind_mask = (mode_t)-1;
138 options->fwd_opts.streamlocal_bind_unlink = -1;
135 options->num_subsystems = 0; 139 options->num_subsystems = 0;
136 options->max_startups_begin = -1; 140 options->max_startups_begin = -1;
137 options->max_startups_rate = -1; 141 options->max_startups_rate = -1;
@@ -220,6 +224,8 @@ fill_default_server_options(ServerOptions *options)
220 options->xauth_location = _PATH_XAUTH; 224 options->xauth_location = _PATH_XAUTH;
221 if (options->permit_tty == -1) 225 if (options->permit_tty == -1)
222 options->permit_tty = 1; 226 options->permit_tty = 1;
227 if (options->permit_user_rc == -1)
228 options->permit_user_rc = 1;
223 if (options->strict_modes == -1) 229 if (options->strict_modes == -1)
224 options->strict_modes = 1; 230 options->strict_modes = 1;
225 if (options->tcp_keep_alive == -1) 231 if (options->tcp_keep_alive == -1)
@@ -276,10 +282,12 @@ fill_default_server_options(ServerOptions *options)
276 options->rekey_interval = 0; 282 options->rekey_interval = 0;
277 if (options->allow_tcp_forwarding == -1) 283 if (options->allow_tcp_forwarding == -1)
278 options->allow_tcp_forwarding = FORWARD_ALLOW; 284 options->allow_tcp_forwarding = FORWARD_ALLOW;
285 if (options->allow_streamlocal_forwarding == -1)
286 options->allow_streamlocal_forwarding = FORWARD_ALLOW;
279 if (options->allow_agent_forwarding == -1) 287 if (options->allow_agent_forwarding == -1)
280 options->allow_agent_forwarding = 1; 288 options->allow_agent_forwarding = 1;
281 if (options->gateway_ports == -1) 289 if (options->fwd_opts.gateway_ports == -1)
282 options->gateway_ports = 0; 290 options->fwd_opts.gateway_ports = 0;
283 if (options->max_startups == -1) 291 if (options->max_startups == -1)
284 options->max_startups = 100; 292 options->max_startups = 100;
285 if (options->max_startups_rate == -1) 293 if (options->max_startups_rate == -1)
@@ -310,6 +318,10 @@ fill_default_server_options(ServerOptions *options)
310 options->ip_qos_bulk = IPTOS_THROUGHPUT; 318 options->ip_qos_bulk = IPTOS_THROUGHPUT;
311 if (options->version_addendum == NULL) 319 if (options->version_addendum == NULL)
312 options->version_addendum = xstrdup(""); 320 options->version_addendum = xstrdup("");
321 if (options->fwd_opts.streamlocal_bind_mask == (mode_t)-1)
322 options->fwd_opts.streamlocal_bind_mask = 0177;
323 if (options->fwd_opts.streamlocal_bind_unlink == -1)
324 options->fwd_opts.streamlocal_bind_unlink = 0;
313 if (options->debian_banner == -1) 325 if (options->debian_banner == -1)
314 options->debian_banner = 1; 326 options->debian_banner = 1;
315 /* Turn privilege separation on by default */ 327 /* Turn privilege separation on by default */
@@ -361,7 +373,9 @@ typedef enum {
361 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile, 373 sRevokedKeys, sTrustedUserCAKeys, sAuthorizedPrincipalsFile,
362 sKexAlgorithms, sIPQoS, sVersionAddendum, 374 sKexAlgorithms, sIPQoS, sVersionAddendum,
363 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser, 375 sAuthorizedKeysCommand, sAuthorizedKeysCommandUser,
364 sAuthenticationMethods, sHostKeyAgent, 376 sAuthenticationMethods, sHostKeyAgent, sPermitUserRC,
377 sStreamLocalBindMask, sStreamLocalBindUnlink,
378 sAllowStreamLocalForwarding,
365 sDebianBanner, 379 sDebianBanner,
366 sDeprecated, sUnsupported 380 sDeprecated, sUnsupported
367} ServerOpCodes; 381} ServerOpCodes;
@@ -486,6 +500,7 @@ static struct {
486 { "acceptenv", sAcceptEnv, SSHCFG_ALL }, 500 { "acceptenv", sAcceptEnv, SSHCFG_ALL },
487 { "permittunnel", sPermitTunnel, SSHCFG_ALL }, 501 { "permittunnel", sPermitTunnel, SSHCFG_ALL },
488 { "permittty", sPermitTTY, SSHCFG_ALL }, 502 { "permittty", sPermitTTY, SSHCFG_ALL },
503 { "permituserrc", sPermitUserRC, SSHCFG_ALL },
489 { "match", sMatch, SSHCFG_ALL }, 504 { "match", sMatch, SSHCFG_ALL },
490 { "permitopen", sPermitOpen, SSHCFG_ALL }, 505 { "permitopen", sPermitOpen, SSHCFG_ALL },
491 { "forcecommand", sForceCommand, SSHCFG_ALL }, 506 { "forcecommand", sForceCommand, SSHCFG_ALL },
@@ -500,6 +515,9 @@ static struct {
500 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL }, 515 { "authorizedkeyscommanduser", sAuthorizedKeysCommandUser, SSHCFG_ALL },
501 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL }, 516 { "versionaddendum", sVersionAddendum, SSHCFG_GLOBAL },
502 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL }, 517 { "authenticationmethods", sAuthenticationMethods, SSHCFG_ALL },
518 { "streamlocalbindmask", sStreamLocalBindMask, SSHCFG_ALL },
519 { "streamlocalbindunlink", sStreamLocalBindUnlink, SSHCFG_ALL },
520 { "allowstreamlocalforwarding", sAllowStreamLocalForwarding, SSHCFG_ALL },
503 { "debianbanner", sDebianBanner, SSHCFG_GLOBAL }, 521 { "debianbanner", sDebianBanner, SSHCFG_GLOBAL },
504 { NULL, sBadOption, 0 } 522 { NULL, sBadOption, 0 }
505}; 523};
@@ -1169,6 +1187,10 @@ process_server_config_line(ServerOptions *options, char *line,
1169 intptr = &options->permit_tty; 1187 intptr = &options->permit_tty;
1170 goto parse_flag; 1188 goto parse_flag;
1171 1189
1190 case sPermitUserRC:
1191 intptr = &options->permit_user_rc;
1192 goto parse_flag;
1193
1172 case sStrictModes: 1194 case sStrictModes:
1173 intptr = &options->strict_modes; 1195 intptr = &options->strict_modes;
1174 goto parse_flag; 1196 goto parse_flag;
@@ -1226,7 +1248,7 @@ process_server_config_line(ServerOptions *options, char *line,
1226 break; 1248 break;
1227 1249
1228 case sGatewayPorts: 1250 case sGatewayPorts:
1229 intptr = &options->gateway_ports; 1251 intptr = &options->fwd_opts.gateway_ports;
1230 multistate_ptr = multistate_gatewayports; 1252 multistate_ptr = multistate_gatewayports;
1231 goto parse_multistate; 1253 goto parse_multistate;
1232 1254
@@ -1261,6 +1283,11 @@ process_server_config_line(ServerOptions *options, char *line,
1261 multistate_ptr = multistate_tcpfwd; 1283 multistate_ptr = multistate_tcpfwd;
1262 goto parse_multistate; 1284 goto parse_multistate;
1263 1285
1286 case sAllowStreamLocalForwarding:
1287 intptr = &options->allow_streamlocal_forwarding;
1288 multistate_ptr = multistate_tcpfwd;
1289 goto parse_multistate;
1290
1264 case sAllowAgentForwarding: 1291 case sAllowAgentForwarding:
1265 intptr = &options->allow_agent_forwarding; 1292 intptr = &options->allow_agent_forwarding;
1266 goto parse_flag; 1293 goto parse_flag;
@@ -1659,6 +1686,22 @@ process_server_config_line(ServerOptions *options, char *line,
1659 } 1686 }
1660 return 0; 1687 return 0;
1661 1688
1689 case sStreamLocalBindMask:
1690 arg = strdelim(&cp);
1691 if (!arg || *arg == '\0')
1692 fatal("%s line %d: missing StreamLocalBindMask argument.",
1693 filename, linenum);
1694 /* Parse mode in octal format */
1695 value = strtol(arg, &p, 8);
1696 if (arg == p || value < 0 || value > 0777)
1697 fatal("%s line %d: Bad mask.", filename, linenum);
1698 options->fwd_opts.streamlocal_bind_mask = (mode_t)value;
1699 break;
1700
1701 case sStreamLocalBindUnlink:
1702 intptr = &options->fwd_opts.streamlocal_bind_unlink;
1703 goto parse_flag;
1704
1662 case sDebianBanner: 1705 case sDebianBanner:
1663 intptr = &options->debian_banner; 1706 intptr = &options->debian_banner;
1664 goto parse_int; 1707 goto parse_int;
@@ -1802,13 +1845,15 @@ copy_set_server_options(ServerOptions *dst, ServerOptions *src, int preauth)
1802 M_CP_INTOPT(permit_empty_passwd); 1845 M_CP_INTOPT(permit_empty_passwd);
1803 1846
1804 M_CP_INTOPT(allow_tcp_forwarding); 1847 M_CP_INTOPT(allow_tcp_forwarding);
1848 M_CP_INTOPT(allow_streamlocal_forwarding);
1805 M_CP_INTOPT(allow_agent_forwarding); 1849 M_CP_INTOPT(allow_agent_forwarding);
1806 M_CP_INTOPT(permit_tun); 1850 M_CP_INTOPT(permit_tun);
1807 M_CP_INTOPT(gateway_ports); 1851 M_CP_INTOPT(fwd_opts.gateway_ports);
1808 M_CP_INTOPT(x11_display_offset); 1852 M_CP_INTOPT(x11_display_offset);
1809 M_CP_INTOPT(x11_forwarding); 1853 M_CP_INTOPT(x11_forwarding);
1810 M_CP_INTOPT(x11_use_localhost); 1854 M_CP_INTOPT(x11_use_localhost);
1811 M_CP_INTOPT(permit_tty); 1855 M_CP_INTOPT(permit_tty);
1856 M_CP_INTOPT(permit_user_rc);
1812 M_CP_INTOPT(max_sessions); 1857 M_CP_INTOPT(max_sessions);
1813 M_CP_INTOPT(max_authtries); 1858 M_CP_INTOPT(max_authtries);
1814 M_CP_INTOPT(ip_qos_interactive); 1859 M_CP_INTOPT(ip_qos_interactive);
@@ -1901,6 +1946,8 @@ fmt_intarg(ServerOpCodes code, int val)
1901 return fmt_multistate_int(val, multistate_privsep); 1946 return fmt_multistate_int(val, multistate_privsep);
1902 case sAllowTcpForwarding: 1947 case sAllowTcpForwarding:
1903 return fmt_multistate_int(val, multistate_tcpfwd); 1948 return fmt_multistate_int(val, multistate_tcpfwd);
1949 case sAllowStreamLocalForwarding:
1950 return fmt_multistate_int(val, multistate_tcpfwd);
1904 case sProtocol: 1951 case sProtocol:
1905 switch (val) { 1952 switch (val) {
1906 case SSH_PROTO_1: 1953 case SSH_PROTO_1:
@@ -2053,15 +2100,17 @@ dump_config(ServerOptions *o)
2053 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding); 2100 dump_cfg_fmtint(sX11Forwarding, o->x11_forwarding);
2054 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost); 2101 dump_cfg_fmtint(sX11UseLocalhost, o->x11_use_localhost);
2055 dump_cfg_fmtint(sPermitTTY, o->permit_tty); 2102 dump_cfg_fmtint(sPermitTTY, o->permit_tty);
2103 dump_cfg_fmtint(sPermitUserRC, o->permit_user_rc);
2056 dump_cfg_fmtint(sStrictModes, o->strict_modes); 2104 dump_cfg_fmtint(sStrictModes, o->strict_modes);
2057 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive); 2105 dump_cfg_fmtint(sTCPKeepAlive, o->tcp_keep_alive);
2058 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd); 2106 dump_cfg_fmtint(sEmptyPasswd, o->permit_empty_passwd);
2059 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env); 2107 dump_cfg_fmtint(sPermitUserEnvironment, o->permit_user_env);
2060 dump_cfg_fmtint(sUseLogin, o->use_login); 2108 dump_cfg_fmtint(sUseLogin, o->use_login);
2061 dump_cfg_fmtint(sCompression, o->compression); 2109 dump_cfg_fmtint(sCompression, o->compression);
2062 dump_cfg_fmtint(sGatewayPorts, o->gateway_ports); 2110 dump_cfg_fmtint(sGatewayPorts, o->fwd_opts.gateway_ports);
2063 dump_cfg_fmtint(sUseDNS, o->use_dns); 2111 dump_cfg_fmtint(sUseDNS, o->use_dns);
2064 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding); 2112 dump_cfg_fmtint(sAllowTcpForwarding, o->allow_tcp_forwarding);
2113 dump_cfg_fmtint(sAllowStreamLocalForwarding, o->allow_streamlocal_forwarding);
2065 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep); 2114 dump_cfg_fmtint(sUsePrivilegeSeparation, use_privsep);
2066 2115
2067 /* string arguments */ 2116 /* string arguments */
diff --git a/servconf.h b/servconf.h
index dcd1c2ab8..fa48804ec 100644
--- a/servconf.h
+++ b/servconf.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: servconf.h,v 1.112 2014/01/29 06:18:35 djm Exp $ */ 1/* $OpenBSD: servconf.h,v 1.114 2014/07/15 15:54:14 millert Exp $ */
2 2
3/* 3/*
4 * Author: Tatu Ylonen <ylo@cs.hut.fi> 4 * Author: Tatu Ylonen <ylo@cs.hut.fi>
@@ -83,6 +83,7 @@ typedef struct {
83 int x11_use_localhost; /* If true, use localhost for fake X11 server. */ 83 int x11_use_localhost; /* If true, use localhost for fake X11 server. */
84 char *xauth_location; /* Location of xauth program */ 84 char *xauth_location; /* Location of xauth program */
85 int permit_tty; /* If false, deny pty allocation */ 85 int permit_tty; /* If false, deny pty allocation */
86 int permit_user_rc; /* If false, deny ~/.ssh/rc execution */
86 int strict_modes; /* If true, require string home dir modes. */ 87 int strict_modes; /* If true, require string home dir modes. */
87 int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */ 88 int tcp_keep_alive; /* If true, set SO_KEEPALIVE. */
88 int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */ 89 int ip_qos_interactive; /* IP ToS/DSCP/class for interactive */
@@ -91,7 +92,7 @@ typedef struct {
91 char *macs; /* Supported SSH2 macs. */ 92 char *macs; /* Supported SSH2 macs. */
92 char *kex_algorithms; /* SSH2 kex methods in order of preference. */ 93 char *kex_algorithms; /* SSH2 kex methods in order of preference. */
93 int protocol; /* Supported protocol versions. */ 94 int protocol; /* Supported protocol versions. */
94 int gateway_ports; /* If true, allow remote connects to forwarded ports. */ 95 struct ForwardOptions fwd_opts; /* forwarding options */
95 SyslogFacility log_facility; /* Facility for system logging. */ 96 SyslogFacility log_facility; /* Facility for system logging. */
96 LogLevel log_level; /* Level for system logging. */ 97 LogLevel log_level; /* Level for system logging. */
97 int rhosts_rsa_authentication; /* If true, permit rhosts RSA 98 int rhosts_rsa_authentication; /* If true, permit rhosts RSA
@@ -126,6 +127,7 @@ typedef struct {
126 int use_login; /* If true, login(1) is used */ 127 int use_login; /* If true, login(1) is used */
127 int compression; /* If true, compression is allowed */ 128 int compression; /* If true, compression is allowed */
128 int allow_tcp_forwarding; /* One of FORWARD_* */ 129 int allow_tcp_forwarding; /* One of FORWARD_* */
130 int allow_streamlocal_forwarding; /* One of FORWARD_* */
129 int allow_agent_forwarding; 131 int allow_agent_forwarding;
130 u_int num_allow_users; 132 u_int num_allow_users;
131 char *allow_users[MAX_ALLOW_USERS]; 133 char *allow_users[MAX_ALLOW_USERS];
diff --git a/serverloop.c b/serverloop.c
index 441d73b4d..813e5bf38 100644
--- a/serverloop.c
+++ b/serverloop.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: serverloop.c,v 1.170 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: serverloop.c,v 1.172 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -61,6 +61,7 @@
61#include "packet.h" 61#include "packet.h"
62#include "buffer.h" 62#include "buffer.h"
63#include "log.h" 63#include "log.h"
64#include "misc.h"
64#include "servconf.h" 65#include "servconf.h"
65#include "canohost.h" 66#include "canohost.h"
66#include "sshpty.h" 67#include "sshpty.h"
@@ -77,7 +78,6 @@
77#include "dispatch.h" 78#include "dispatch.h"
78#include "auth-options.h" 79#include "auth-options.h"
79#include "serverloop.h" 80#include "serverloop.h"
80#include "misc.h"
81#include "roaming.h" 81#include "roaming.h"
82 82
83extern ServerOptions options; 83extern ServerOptions options;
@@ -970,7 +970,7 @@ server_request_direct_tcpip(void)
970 /* XXX fine grained permissions */ 970 /* XXX fine grained permissions */
971 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 && 971 if ((options.allow_tcp_forwarding & FORWARD_LOCAL) != 0 &&
972 !no_port_forwarding_flag) { 972 !no_port_forwarding_flag) {
973 c = channel_connect_to(target, target_port, 973 c = channel_connect_to_port(target, target_port,
974 "direct-tcpip", "direct-tcpip"); 974 "direct-tcpip", "direct-tcpip");
975 } else { 975 } else {
976 logit("refused local port forward: " 976 logit("refused local port forward: "
@@ -985,6 +985,38 @@ server_request_direct_tcpip(void)
985} 985}
986 986
987static Channel * 987static Channel *
988server_request_direct_streamlocal(void)
989{
990 Channel *c = NULL;
991 char *target, *originator;
992 u_short originator_port;
993
994 target = packet_get_string(NULL);
995 originator = packet_get_string(NULL);
996 originator_port = packet_get_int();
997 packet_check_eom();
998
999 debug("server_request_direct_streamlocal: originator %s port %d, target %s",
1000 originator, originator_port, target);
1001
1002 /* XXX fine grained permissions */
1003 if ((options.allow_streamlocal_forwarding & FORWARD_LOCAL) != 0 &&
1004 !no_port_forwarding_flag) {
1005 c = channel_connect_to_path(target,
1006 "direct-streamlocal@openssh.com", "direct-streamlocal");
1007 } else {
1008 logit("refused streamlocal port forward: "
1009 "originator %s port %d, target %s",
1010 originator, originator_port, target);
1011 }
1012
1013 free(originator);
1014 free(target);
1015
1016 return c;
1017}
1018
1019static Channel *
988server_request_tun(void) 1020server_request_tun(void)
989{ 1021{
990 Channel *c = NULL; 1022 Channel *c = NULL;
@@ -1081,6 +1113,8 @@ server_input_channel_open(int type, u_int32_t seq, void *ctxt)
1081 c = server_request_session(); 1113 c = server_request_session();
1082 } else if (strcmp(ctype, "direct-tcpip") == 0) { 1114 } else if (strcmp(ctype, "direct-tcpip") == 0) {
1083 c = server_request_direct_tcpip(); 1115 c = server_request_direct_tcpip();
1116 } else if (strcmp(ctype, "direct-streamlocal@openssh.com") == 0) {
1117 c = server_request_direct_streamlocal();
1084 } else if (strcmp(ctype, "tun@openssh.com") == 0) { 1118 } else if (strcmp(ctype, "tun@openssh.com") == 0) {
1085 c = server_request_tun(); 1119 c = server_request_tun();
1086 } 1120 }
@@ -1125,47 +1159,74 @@ server_input_global_request(int type, u_int32_t seq, void *ctxt)
1125 /* -R style forwarding */ 1159 /* -R style forwarding */
1126 if (strcmp(rtype, "tcpip-forward") == 0) { 1160 if (strcmp(rtype, "tcpip-forward") == 0) {
1127 struct passwd *pw; 1161 struct passwd *pw;
1128 char *listen_address; 1162 struct Forward fwd;
1129 u_short listen_port;
1130 1163
1131 pw = the_authctxt->pw; 1164 pw = the_authctxt->pw;
1132 if (pw == NULL || !the_authctxt->valid) 1165 if (pw == NULL || !the_authctxt->valid)
1133 fatal("server_input_global_request: no/invalid user"); 1166 fatal("server_input_global_request: no/invalid user");
1134 listen_address = packet_get_string(NULL); 1167 memset(&fwd, 0, sizeof(fwd));
1135 listen_port = (u_short)packet_get_int(); 1168 fwd.listen_host = packet_get_string(NULL);
1169 fwd.listen_port = (u_short)packet_get_int();
1136 debug("server_input_global_request: tcpip-forward listen %s port %d", 1170 debug("server_input_global_request: tcpip-forward listen %s port %d",
1137 listen_address, listen_port); 1171 fwd.listen_host, fwd.listen_port);
1138 1172
1139 /* check permissions */ 1173 /* check permissions */
1140 if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 || 1174 if ((options.allow_tcp_forwarding & FORWARD_REMOTE) == 0 ||
1141 no_port_forwarding_flag || 1175 no_port_forwarding_flag ||
1142 (!want_reply && listen_port == 0) 1176 (!want_reply && fwd.listen_port == 0)
1143#ifndef NO_IPPORT_RESERVED_CONCEPT 1177#ifndef NO_IPPORT_RESERVED_CONCEPT
1144 || (listen_port != 0 && listen_port < IPPORT_RESERVED && 1178 || (fwd.listen_port != 0 && fwd.listen_port < IPPORT_RESERVED &&
1145 pw->pw_uid != 0) 1179 pw->pw_uid != 0)
1146#endif 1180#endif
1147 ) { 1181 ) {
1148 success = 0; 1182 success = 0;
1149 packet_send_debug("Server has disabled port forwarding."); 1183 packet_send_debug("Server has disabled port forwarding.");
1150 } else { 1184 } else {
1151 /* Start listening on the port */ 1185 /* Start listening on the port */
1152 success = channel_setup_remote_fwd_listener( 1186 success = channel_setup_remote_fwd_listener(&fwd,
1153 listen_address, listen_port, 1187 &allocated_listen_port, &options.fwd_opts);
1154 &allocated_listen_port, options.gateway_ports);
1155 } 1188 }
1156 free(listen_address); 1189 free(fwd.listen_host);
1157 } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) { 1190 } else if (strcmp(rtype, "cancel-tcpip-forward") == 0) {
1158 char *cancel_address; 1191 struct Forward fwd;
1159 u_short cancel_port;
1160 1192
1161 cancel_address = packet_get_string(NULL); 1193 memset(&fwd, 0, sizeof(fwd));
1162 cancel_port = (u_short)packet_get_int(); 1194 fwd.listen_host = packet_get_string(NULL);
1195 fwd.listen_port = (u_short)packet_get_int();
1163 debug("%s: cancel-tcpip-forward addr %s port %d", __func__, 1196 debug("%s: cancel-tcpip-forward addr %s port %d", __func__,
1164 cancel_address, cancel_port); 1197 fwd.listen_host, fwd.listen_port);
1198
1199 success = channel_cancel_rport_listener(&fwd);
1200 free(fwd.listen_host);
1201 } else if (strcmp(rtype, "streamlocal-forward@openssh.com") == 0) {
1202 struct Forward fwd;
1203
1204 memset(&fwd, 0, sizeof(fwd));
1205 fwd.listen_path = packet_get_string(NULL);
1206 debug("server_input_global_request: streamlocal-forward listen path %s",
1207 fwd.listen_path);
1208
1209 /* check permissions */
1210 if ((options.allow_streamlocal_forwarding & FORWARD_REMOTE) == 0
1211 || no_port_forwarding_flag) {
1212 success = 0;
1213 packet_send_debug("Server has disabled port forwarding.");
1214 } else {
1215 /* Start listening on the socket */
1216 success = channel_setup_remote_fwd_listener(
1217 &fwd, NULL, &options.fwd_opts);
1218 }
1219 free(fwd.listen_path);
1220 } else if (strcmp(rtype, "cancel-streamlocal-forward@openssh.com") == 0) {
1221 struct Forward fwd;
1222
1223 memset(&fwd, 0, sizeof(fwd));
1224 fwd.listen_path = packet_get_string(NULL);
1225 debug("%s: cancel-streamlocal-forward path %s", __func__,
1226 fwd.listen_path);
1165 1227
1166 success = channel_cancel_rport_listener(cancel_address, 1228 success = channel_cancel_rport_listener(&fwd);
1167 cancel_port); 1229 free(fwd.listen_path);
1168 free(cancel_address);
1169 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) { 1230 } else if (strcmp(rtype, "no-more-sessions@openssh.com") == 0) {
1170 no_more_sessions = 1; 1231 no_more_sessions = 1;
1171 success = 1; 1232 success = 1;
@@ -1204,7 +1265,7 @@ server_input_channel_req(int type, u_int32_t seq, void *ctxt)
1204 } else if ((c->type == SSH_CHANNEL_LARVAL || 1265 } else if ((c->type == SSH_CHANNEL_LARVAL ||
1205 c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0) 1266 c->type == SSH_CHANNEL_OPEN) && strcmp(c->ctype, "session") == 0)
1206 success = session_input_channel_req(c, rtype); 1267 success = session_input_channel_req(c, rtype);
1207 if (reply) { 1268 if (reply && !(c->flags & CHAN_CLOSE_SENT)) {
1208 packet_start(success ? 1269 packet_start(success ?
1209 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE); 1270 SSH2_MSG_CHANNEL_SUCCESS : SSH2_MSG_CHANNEL_FAILURE);
1210 packet_put_int(c->remote_id); 1271 packet_put_int(c->remote_id);
diff --git a/session.c b/session.c
index 9d43fc3c7..6250c2031 100644
--- a/session.c
+++ b/session.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: session.c,v 1.270 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: session.c,v 1.274 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 3 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
4 * All rights reserved 4 * All rights reserved
@@ -49,6 +49,7 @@
49#include <errno.h> 49#include <errno.h>
50#include <fcntl.h> 50#include <fcntl.h>
51#include <grp.h> 51#include <grp.h>
52#include <netdb.h>
52#ifdef HAVE_PATHS_H 53#ifdef HAVE_PATHS_H
53#include <paths.h> 54#include <paths.h>
54#endif 55#endif
@@ -83,11 +84,11 @@
83#include "authfd.h" 84#include "authfd.h"
84#include "pathnames.h" 85#include "pathnames.h"
85#include "log.h" 86#include "log.h"
87#include "misc.h"
86#include "servconf.h" 88#include "servconf.h"
87#include "sshlogin.h" 89#include "sshlogin.h"
88#include "serverloop.h" 90#include "serverloop.h"
89#include "canohost.h" 91#include "canohost.h"
90#include "misc.h"
91#include "session.h" 92#include "session.h"
92#include "kex.h" 93#include "kex.h"
93#include "monitor_wrap.h" 94#include "monitor_wrap.h"
@@ -183,7 +184,6 @@ auth_input_request_forwarding(struct passwd * pw)
183{ 184{
184 Channel *nc; 185 Channel *nc;
185 int sock = -1; 186 int sock = -1;
186 struct sockaddr_un sunaddr;
187 187
188 if (auth_sock_name != NULL) { 188 if (auth_sock_name != NULL) {
189 error("authentication forwarding requested twice."); 189 error("authentication forwarding requested twice.");
@@ -209,33 +209,15 @@ auth_input_request_forwarding(struct passwd * pw)
209 xasprintf(&auth_sock_name, "%s/agent.%ld", 209 xasprintf(&auth_sock_name, "%s/agent.%ld",
210 auth_sock_dir, (long) getpid()); 210 auth_sock_dir, (long) getpid());
211 211
212 /* Create the socket. */ 212 /* Start a Unix listener on auth_sock_name. */
213 sock = socket(AF_UNIX, SOCK_STREAM, 0); 213 sock = unix_listener(auth_sock_name, SSH_LISTEN_BACKLOG, 0);
214 if (sock < 0) {
215 error("socket: %.100s", strerror(errno));
216 restore_uid();
217 goto authsock_err;
218 }
219
220 /* Bind it to the name. */
221 memset(&sunaddr, 0, sizeof(sunaddr));
222 sunaddr.sun_family = AF_UNIX;
223 strlcpy(sunaddr.sun_path, auth_sock_name, sizeof(sunaddr.sun_path));
224
225 if (bind(sock, (struct sockaddr *)&sunaddr, sizeof(sunaddr)) < 0) {
226 error("bind: %.100s", strerror(errno));
227 restore_uid();
228 goto authsock_err;
229 }
230 214
231 /* Restore the privileged uid. */ 215 /* Restore the privileged uid. */
232 restore_uid(); 216 restore_uid();
233 217
234 /* Start listening on the socket. */ 218 /* Check for socket/bind/listen failure. */
235 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) { 219 if (sock < 0)
236 error("listen: %.100s", strerror(errno));
237 goto authsock_err; 220 goto authsock_err;
238 }
239 221
240 /* Allocate a channel for the authentication agent socket. */ 222 /* Allocate a channel for the authentication agent socket. */
241 nc = channel_new("auth socket", 223 nc = channel_new("auth socket",
@@ -274,6 +256,7 @@ do_authenticated(Authctxt *authctxt)
274 setproctitle("%s", authctxt->pw->pw_name); 256 setproctitle("%s", authctxt->pw->pw_name);
275 257
276 /* setup the channel layer */ 258 /* setup the channel layer */
259 /* XXX - streamlocal? */
277 if (no_port_forwarding_flag || 260 if (no_port_forwarding_flag ||
278 (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0) 261 (options.allow_tcp_forwarding & FORWARD_LOCAL) == 0)
279 channel_disable_adm_local_opens(); 262 channel_disable_adm_local_opens();
@@ -393,7 +376,7 @@ do_authenticated1(Authctxt *authctxt)
393 } 376 }
394 debug("Received TCP/IP port forwarding request."); 377 debug("Received TCP/IP port forwarding request.");
395 if (channel_input_port_forward_request(s->pw->pw_uid == 0, 378 if (channel_input_port_forward_request(s->pw->pw_uid == 0,
396 options.gateway_ports) < 0) { 379 &options.fwd_opts) < 0) {
397 debug("Port forwarding failed."); 380 debug("Port forwarding failed.");
398 break; 381 break;
399 } 382 }
@@ -1367,7 +1350,8 @@ do_rc_files(Session *s, const char *shell)
1367 1350
1368 /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */ 1351 /* ignore _PATH_SSH_USER_RC for subsystems and admin forced commands */
1369 if (!s->is_subsystem && options.adm_forced_command == NULL && 1352 if (!s->is_subsystem && options.adm_forced_command == NULL &&
1370 !no_user_rc && stat(_PATH_SSH_USER_RC, &st) >= 0) { 1353 !no_user_rc && options.permit_user_rc &&
1354 stat(_PATH_SSH_USER_RC, &st) >= 0) {
1371 snprintf(cmd, sizeof cmd, "%s -c '%s %s'", 1355 snprintf(cmd, sizeof cmd, "%s -c '%s %s'",
1372 shell, _PATH_BSHELL, _PATH_SSH_USER_RC); 1356 shell, _PATH_BSHELL, _PATH_SSH_USER_RC);
1373 if (debug_flag) 1357 if (debug_flag)
@@ -1514,6 +1498,9 @@ void
1514do_setusercontext(struct passwd *pw, const char *role) 1498do_setusercontext(struct passwd *pw, const char *role)
1515{ 1499{
1516 char *chroot_path, *tmp; 1500 char *chroot_path, *tmp;
1501#ifdef USE_LIBIAF
1502 int doing_chroot = 0;
1503#endif
1517 1504
1518 platform_setusercontext(pw); 1505 platform_setusercontext(pw);
1519 1506
@@ -1553,6 +1540,9 @@ do_setusercontext(struct passwd *pw, const char *role)
1553 /* Make sure we don't attempt to chroot again */ 1540 /* Make sure we don't attempt to chroot again */
1554 free(options.chroot_directory); 1541 free(options.chroot_directory);
1555 options.chroot_directory = NULL; 1542 options.chroot_directory = NULL;
1543#ifdef USE_LIBIAF
1544 doing_chroot = 1;
1545#endif
1556 } 1546 }
1557 1547
1558#ifdef HAVE_LOGIN_CAP 1548#ifdef HAVE_LOGIN_CAP
@@ -1567,7 +1557,14 @@ do_setusercontext(struct passwd *pw, const char *role)
1567 (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK); 1557 (void) setusercontext(lc, pw, pw->pw_uid, LOGIN_SETUMASK);
1568#else 1558#else
1569# ifdef USE_LIBIAF 1559# ifdef USE_LIBIAF
1570 if (set_id(pw->pw_name) != 0) { 1560/* In a chroot environment, the set_id() will always fail; typically
1561 * because of the lack of necessary authentication services and runtime
1562 * such as ./usr/lib/libiaf.so, ./usr/lib/libpam.so.1, and ./etc/passwd
1563 * We skip it in the internal sftp chroot case.
1564 * We'll lose auditing and ACLs but permanently_set_uid will
1565 * take care of the rest.
1566 */
1567 if ((doing_chroot == 0) && set_id(pw->pw_name) != 0) {
1571 fatal("set_id(%s) Failed", pw->pw_name); 1568 fatal("set_id(%s) Failed", pw->pw_name);
1572 } 1569 }
1573# endif /* USE_LIBIAF */ 1570# endif /* USE_LIBIAF */
@@ -2653,7 +2650,7 @@ session_setup_x11fwd(Session *s)
2653{ 2650{
2654 struct stat st; 2651 struct stat st;
2655 char display[512], auth_display[512]; 2652 char display[512], auth_display[512];
2656 char hostname[MAXHOSTNAMELEN]; 2653 char hostname[NI_MAXHOST];
2657 u_int i; 2654 u_int i;
2658 2655
2659 if (no_x11_forwarding_flag) { 2656 if (no_x11_forwarding_flag) {
diff --git a/sftp-client.c b/sftp-client.c
index 2f5907c85..990b58d14 100644
--- a/sftp-client.c
+++ b/sftp-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.c,v 1.114 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: sftp-client.c,v 1.115 2014/04/21 14:36:16 logan Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -1420,7 +1420,7 @@ download_dir(struct sftp_conn *conn, char *src, char *dst,
1420 1420
1421int 1421int
1422do_upload(struct sftp_conn *conn, char *local_path, char *remote_path, 1422do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1423 int preserve_flag, int fsync_flag) 1423 int preserve_flag, int resume, int fsync_flag)
1424{ 1424{
1425 int local_fd; 1425 int local_fd;
1426 int status = SSH2_FX_OK; 1426 int status = SSH2_FX_OK;
@@ -1429,7 +1429,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1429 char *handle, *data; 1429 char *handle, *data;
1430 Buffer msg; 1430 Buffer msg;
1431 struct stat sb; 1431 struct stat sb;
1432 Attrib a; 1432 Attrib a, *c = NULL;
1433 u_int32_t startid; 1433 u_int32_t startid;
1434 u_int32_t ackid; 1434 u_int32_t ackid;
1435 struct outstanding_ack { 1435 struct outstanding_ack {
@@ -1467,6 +1467,26 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1467 if (!preserve_flag) 1467 if (!preserve_flag)
1468 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME; 1468 a.flags &= ~SSH2_FILEXFER_ATTR_ACMODTIME;
1469 1469
1470 if (resume) {
1471 /* Get remote file size if it exists */
1472 if ((c = do_stat(conn, remote_path, 0)) == NULL) {
1473 close(local_fd);
1474 return -1;
1475 }
1476
1477 if ((off_t)c->size >= sb.st_size) {
1478 error("destination file bigger or same size as "
1479 "source file");
1480 close(local_fd);
1481 return -1;
1482 }
1483
1484 if (lseek(local_fd, (off_t)c->size, SEEK_SET) == -1) {
1485 close(local_fd);
1486 return -1;
1487 }
1488 }
1489
1470 buffer_init(&msg); 1490 buffer_init(&msg);
1471 1491
1472 /* Send open request */ 1492 /* Send open request */
@@ -1474,7 +1494,8 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1474 buffer_put_char(&msg, SSH2_FXP_OPEN); 1494 buffer_put_char(&msg, SSH2_FXP_OPEN);
1475 buffer_put_int(&msg, id); 1495 buffer_put_int(&msg, id);
1476 buffer_put_cstring(&msg, remote_path); 1496 buffer_put_cstring(&msg, remote_path);
1477 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|SSH2_FXF_TRUNC); 1497 buffer_put_int(&msg, SSH2_FXF_WRITE|SSH2_FXF_CREAT|
1498 (resume ? SSH2_FXF_APPEND : SSH2_FXF_TRUNC));
1478 encode_attrib(&msg, &a); 1499 encode_attrib(&msg, &a);
1479 send_msg(conn, &msg); 1500 send_msg(conn, &msg);
1480 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path); 1501 debug3("Sent message SSH2_FXP_OPEN I:%u P:%s", id, remote_path);
@@ -1493,7 +1514,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1493 data = xmalloc(conn->transfer_buflen); 1514 data = xmalloc(conn->transfer_buflen);
1494 1515
1495 /* Read from local and write to remote */ 1516 /* Read from local and write to remote */
1496 offset = progress_counter = 0; 1517 offset = progress_counter = (resume ? c->size : 0);
1497 if (showprogress) 1518 if (showprogress)
1498 start_progress_meter(local_path, sb.st_size, 1519 start_progress_meter(local_path, sb.st_size,
1499 &progress_counter); 1520 &progress_counter);
@@ -1608,7 +1629,7 @@ do_upload(struct sftp_conn *conn, char *local_path, char *remote_path,
1608 1629
1609static int 1630static int
1610upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth, 1631upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
1611 int preserve_flag, int print_flag, int fsync_flag) 1632 int preserve_flag, int print_flag, int resume, int fsync_flag)
1612{ 1633{
1613 int ret = 0, status; 1634 int ret = 0, status;
1614 DIR *dirp; 1635 DIR *dirp;
@@ -1677,12 +1698,12 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
1677 continue; 1698 continue;
1678 1699
1679 if (upload_dir_internal(conn, new_src, new_dst, 1700 if (upload_dir_internal(conn, new_src, new_dst,
1680 depth + 1, preserve_flag, print_flag, 1701 depth + 1, preserve_flag, print_flag, resume,
1681 fsync_flag) == -1) 1702 fsync_flag) == -1)
1682 ret = -1; 1703 ret = -1;
1683 } else if (S_ISREG(sb.st_mode)) { 1704 } else if (S_ISREG(sb.st_mode)) {
1684 if (do_upload(conn, new_src, new_dst, 1705 if (do_upload(conn, new_src, new_dst,
1685 preserve_flag, fsync_flag) == -1) { 1706 preserve_flag, resume, fsync_flag) == -1) {
1686 error("Uploading of file %s to %s failed!", 1707 error("Uploading of file %s to %s failed!",
1687 new_src, new_dst); 1708 new_src, new_dst);
1688 ret = -1; 1709 ret = -1;
@@ -1701,7 +1722,7 @@ upload_dir_internal(struct sftp_conn *conn, char *src, char *dst, int depth,
1701 1722
1702int 1723int
1703upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag, 1724upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag,
1704 int print_flag, int fsync_flag) 1725 int print_flag, int resume, int fsync_flag)
1705{ 1726{
1706 char *dst_canon; 1727 char *dst_canon;
1707 int ret; 1728 int ret;
@@ -1712,7 +1733,7 @@ upload_dir(struct sftp_conn *conn, char *src, char *dst, int preserve_flag,
1712 } 1733 }
1713 1734
1714 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag, 1735 ret = upload_dir_internal(conn, src, dst_canon, 0, preserve_flag,
1715 print_flag, fsync_flag); 1736 print_flag, resume, fsync_flag);
1716 1737
1717 free(dst_canon); 1738 free(dst_canon);
1718 return ret; 1739 return ret;
diff --git a/sftp-client.h b/sftp-client.h
index ba92ad01a..967840b9c 100644
--- a/sftp-client.h
+++ b/sftp-client.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp-client.h,v 1.24 2013/10/17 00:30:13 djm Exp $ */ 1/* $OpenBSD: sftp-client.h,v 1.25 2014/04/21 14:36:16 logan Exp $ */
2 2
3/* 3/*
4 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 4 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
@@ -120,13 +120,13 @@ int download_dir(struct sftp_conn *, char *, char *, Attrib *, int,
120 * Upload 'local_path' to 'remote_path'. Preserve permissions and times 120 * Upload 'local_path' to 'remote_path'. Preserve permissions and times
121 * if 'pflag' is set 121 * if 'pflag' is set
122 */ 122 */
123int do_upload(struct sftp_conn *, char *, char *, int, int); 123int do_upload(struct sftp_conn *, char *, char *, int, int, int);
124 124
125/* 125/*
126 * Recursively upload 'local_directory' to 'remote_directory'. Preserve 126 * Recursively upload 'local_directory' to 'remote_directory'. Preserve
127 * times if 'pflag' is set 127 * times if 'pflag' is set
128 */ 128 */
129int upload_dir(struct sftp_conn *, char *, char *, int, int, int); 129int upload_dir(struct sftp_conn *, char *, char *, int, int, int, int);
130 130
131/* Concatenate paths, taking care of slashes. Caller must free result. */ 131/* Concatenate paths, taking care of slashes. Caller must free result. */
132char *path_append(char *, char *); 132char *path_append(char *, char *);
diff --git a/sftp-server.0 b/sftp-server.0
index ce7ddc07f..d811e252d 100644
--- a/sftp-server.0
+++ b/sftp-server.0
@@ -1,4 +1,4 @@
1SFTP-SERVER(8) OpenBSD System Manager's Manual SFTP-SERVER(8) 1SFTP-SERVER(8) System Manager's Manual SFTP-SERVER(8)
2 2
3NAME 3NAME
4 sftp-server - SFTP server subsystem 4 sftp-server - SFTP server subsystem
@@ -76,9 +76,10 @@ DESCRIPTION
76 Sets an explicit umask(2) to be applied to newly-created files 76 Sets an explicit umask(2) to be applied to newly-created files
77 and directories, instead of the user's default mask. 77 and directories, instead of the user's default mask.
78 78
79 For logging to work, sftp-server must be able to access /dev/log. Use of 79 On some systems, sftp-server must be able to access /dev/log for logging
80 sftp-server in a chroot configuration therefore requires that syslogd(8) 80 to work, and use of sftp-server in a chroot configuration therefore
81 establish a logging socket inside the chroot directory. 81 requires that syslogd(8) establish a logging socket inside the chroot
82 directory.
82 83
83SEE ALSO 84SEE ALSO
84 sftp(1), ssh(1), sshd_config(5), sshd(8) 85 sftp(1), ssh(1), sshd_config(5), sshd(8)
@@ -92,4 +93,4 @@ HISTORY
92AUTHORS 93AUTHORS
93 Markus Friedl <markus@openbsd.org> 94 Markus Friedl <markus@openbsd.org>
94 95
95OpenBSD 5.5 October 14, 2013 OpenBSD 5.5 96OpenBSD 5.6 July 28, 2014 OpenBSD 5.6
diff --git a/sftp-server.8 b/sftp-server.8
index 1e0b277b4..75d8d8d53 100644
--- a/sftp-server.8
+++ b/sftp-server.8
@@ -1,4 +1,4 @@
1.\" $OpenBSD: sftp-server.8,v 1.25 2013/10/14 14:18:56 jmc Exp $ 1.\" $OpenBSD: sftp-server.8,v 1.26 2014/07/28 15:40:08 schwarze Exp $
2.\" 2.\"
3.\" Copyright (c) 2000 Markus Friedl. All rights reserved. 3.\" Copyright (c) 2000 Markus Friedl. All rights reserved.
4.\" 4.\"
@@ -22,7 +22,7 @@
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\" 24.\"
25.Dd $Mdocdate: October 14 2013 $ 25.Dd $Mdocdate: July 28 2014 $
26.Dt SFTP-SERVER 8 26.Dt SFTP-SERVER 8
27.Os 27.Os
28.Sh NAME 28.Sh NAME
@@ -140,11 +140,11 @@ to be applied to newly-created files and directories, instead of the
140user's default mask. 140user's default mask.
141.El 141.El
142.Pp 142.Pp
143For logging to work, 143On some systems,
144.Nm 144.Nm
145must be able to access 145must be able to access
146.Pa /dev/log . 146.Pa /dev/log
147Use of 147for logging to work, and use of
148.Nm 148.Nm
149in a chroot configuration therefore requires that 149in a chroot configuration therefore requires that
150.Xr syslogd 8 150.Xr syslogd 8
diff --git a/sftp-server.c b/sftp-server.c
index b8eb59c36..0177130cf 100644
--- a/sftp-server.c
+++ b/sftp-server.c
@@ -29,6 +29,9 @@
29#ifdef HAVE_SYS_STATVFS_H 29#ifdef HAVE_SYS_STATVFS_H
30#include <sys/statvfs.h> 30#include <sys/statvfs.h>
31#endif 31#endif
32#ifdef HAVE_SYS_PRCTL_H
33#include <sys/prctl.h>
34#endif
32 35
33#include <dirent.h> 36#include <dirent.h>
34#include <errno.h> 37#include <errno.h>
@@ -1523,6 +1526,17 @@ sftp_server_main(int argc, char **argv, struct passwd *user_pw)
1523 1526
1524 log_init(__progname, log_level, log_facility, log_stderr); 1527 log_init(__progname, log_level, log_facility, log_stderr);
1525 1528
1529#if defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE)
1530 /*
1531 * On Linux, we should try to avoid making /proc/self/{mem,maps}
1532 * available to the user so that sftp access doesn't automatically
1533 * imply arbitrary code execution access that will break
1534 * restricted configurations.
1535 */
1536 if (prctl(PR_SET_DUMPABLE, 0) != 0)
1537 fatal("unable to make the process undumpable");
1538#endif /* defined(HAVE_PRCTL) && defined(PR_SET_DUMPABLE) */
1539
1526 if ((cp = getenv("SSH_CONNECTION")) != NULL) { 1540 if ((cp = getenv("SSH_CONNECTION")) != NULL) {
1527 client_addr = xstrdup(cp); 1541 client_addr = xstrdup(cp);
1528 if ((cp = strchr(client_addr, ' ')) == NULL) { 1542 if ((cp = strchr(client_addr, ' ')) == NULL) {
diff --git a/sftp.0 b/sftp.0
index 7139aac43..e37043455 100644
--- a/sftp.0
+++ b/sftp.0
@@ -1,4 +1,4 @@
1SFTP(1) OpenBSD Reference Manual SFTP(1) 1SFTP(1) General Commands Manual SFTP(1)
2 2
3NAME 3NAME
4 sftp - secure file transfer program 4 sftp - secure file transfer program
@@ -44,9 +44,9 @@ DESCRIPTION
44 44
45 -6 Forces sftp to use IPv6 addresses only. 45 -6 Forces sftp to use IPv6 addresses only.
46 46
47 -a Attempt to continue interrupted downloads rather than overwriting 47 -a Attempt to continue interrupted transfers rather than overwriting
48 existing partial or complete copies of files. If the remote file 48 existing partial or complete copies of files. If the partial
49 contents differ from the partial local copy then the resultant 49 contents differ from those being transferred, then the resultant
50 file is likely to be corrupt. 50 file is likely to be corrupt.
51 51
52 -B buffer_size 52 -B buffer_size
@@ -60,10 +60,11 @@ DESCRIPTION
60 used in conjunction with non-interactive authentication. A 60 used in conjunction with non-interactive authentication. A
61 batchfile of `-' may be used to indicate standard input. sftp 61 batchfile of `-' may be used to indicate standard input. sftp
62 will abort if any of the following commands fail: get, put, 62 will abort if any of the following commands fail: get, put,
63 reget, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod, chown, 63 reget, reput, rename, ln, rm, mkdir, chdir, ls, lchdir, chmod,
64 chgrp, lpwd, df, symlink, and lmkdir. Termination on error can 64 chown, chgrp, lpwd, df, symlink, and lmkdir. Termination on
65 be suppressed on a command by command basis by prefixing the 65 error can be suppressed on a command by command basis by
66 command with a `-' character (for example, -rm /tmp/blah*). 66 prefixing the command with a `-' character (for example, -rm
67 /tmp/blah*).
67 68
68 -C Enables compression (via ssh's -C flag). 69 -C Enables compression (via ssh's -C flag).
69 70
@@ -310,7 +311,7 @@ INTERACTIVE COMMANDS
310 progress 311 progress
311 Toggle display of progress meter. 312 Toggle display of progress meter.
312 313
313 put [-fPpr] local-path [remote-path] 314 put [-afPpr] local-path [remote-path]
314 Upload local-path and store it on the remote machine. If the 315 Upload local-path and store it on the remote machine. If the
315 remote path name is not specified, it is given the same name it 316 remote path name is not specified, it is given the same name it
316 has on the local machine. local-path may contain glob(3) 317 has on the local machine. local-path may contain glob(3)
@@ -318,6 +319,12 @@ INTERACTIVE COMMANDS
318 remote-path is specified, then remote-path must specify a 319 remote-path is specified, then remote-path must specify a
319 directory. 320 directory.
320 321
322 If the -a flag is specified, then attempt to resume partial
323 transfers of existing files. Note that resumption assumes that
324 any partial copy of the remote file matches the local copy. If
325 the local file contents differ from the remote local copy then
326 the resultant file is likely to be corrupt.
327
321 If the -f flag is specified, then a request will be sent to the 328 If the -f flag is specified, then a request will be sent to the
322 server to call fsync(2) after the file has been transferred. 329 server to call fsync(2) after the file has been transferred.
323 Note that this is only supported by servers that implement the 330 Note that this is only supported by servers that implement the
@@ -338,6 +345,10 @@ INTERACTIVE COMMANDS
338 Resume download of remote-path. Equivalent to get with the -a 345 Resume download of remote-path. Equivalent to get with the -a
339 flag set. 346 flag set.
340 347
348 reput [-Ppr] [local-path] remote-path
349 Resume upload of [local-path]. Equivalent to put with the -a
350 flag set.
351
341 rename oldpath newpath 352 rename oldpath newpath
342 Rename remote file from oldpath to newpath. 353 Rename remote file from oldpath to newpath.
343 354
@@ -367,4 +378,4 @@ SEE ALSO
367 T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh- 378 T. Ylonen and S. Lehtinen, SSH File Transfer Protocol, draft-ietf-secsh-
368 filexfer-00.txt, January 2001, work in progress material. 379 filexfer-00.txt, January 2001, work in progress material.
369 380
370OpenBSD 5.5 October 20, 2013 OpenBSD 5.5 381OpenBSD 5.6 April 22, 2014 OpenBSD 5.6
diff --git a/sftp.1 b/sftp.1
index a700c2adb..7eb9970ab 100644
--- a/sftp.1
+++ b/sftp.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: sftp.1,v 1.97 2013/10/20 09:51:26 djm Exp $ 1.\" $OpenBSD: sftp.1,v 1.99 2014/04/22 14:16:30 jmc Exp $
2.\" 2.\"
3.\" Copyright (c) 2001 Damien Miller. All rights reserved. 3.\" Copyright (c) 2001 Damien Miller. All rights reserved.
4.\" 4.\"
@@ -22,7 +22,7 @@
22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 22.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 23.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
24.\" 24.\"
25.Dd $Mdocdate: October 20 2013 $ 25.Dd $Mdocdate: April 22 2014 $
26.Dt SFTP 1 26.Dt SFTP 1
27.Os 27.Os
28.Sh NAME 28.Sh NAME
@@ -108,10 +108,10 @@ Forces
108.Nm 108.Nm
109to use IPv6 addresses only. 109to use IPv6 addresses only.
110.It Fl a 110.It Fl a
111Attempt to continue interrupted downloads rather than overwriting existing 111Attempt to continue interrupted transfers rather than overwriting
112partial or complete copies of files. 112existing partial or complete copies of files.
113If the remote file contents differ from the partial local copy then the 113If the partial contents differ from those being transferred,
114resultant file is likely to be corrupt. 114then the resultant file is likely to be corrupt.
115.It Fl B Ar buffer_size 115.It Fl B Ar buffer_size
116Specify the size of the buffer that 116Specify the size of the buffer that
117.Nm 117.Nm
@@ -134,7 +134,7 @@ may be used to indicate standard input.
134.Nm 134.Nm
135will abort if any of the following 135will abort if any of the following
136commands fail: 136commands fail:
137.Ic get , put , reget , rename , ln , 137.Ic get , put , reget , reput, rename , ln ,
138.Ic rm , mkdir , chdir , ls , 138.Ic rm , mkdir , chdir , ls ,
139.Ic lchdir , chmod , chown , 139.Ic lchdir , chmod , chown ,
140.Ic chgrp , lpwd , df , symlink , 140.Ic chgrp , lpwd , df , symlink ,
@@ -495,7 +495,7 @@ Create remote directory specified by
495.It Ic progress 495.It Ic progress
496Toggle display of progress meter. 496Toggle display of progress meter.
497.It Xo Ic put 497.It Xo Ic put
498.Op Fl fPpr 498.Op Fl afPpr
499.Ar local-path 499.Ar local-path
500.Op Ar remote-path 500.Op Ar remote-path
501.Xc 501.Xc
@@ -515,6 +515,15 @@ is specified, then
515must specify a directory. 515must specify a directory.
516.Pp 516.Pp
517If the 517If the
518.Fl a
519flag is specified, then attempt to resume partial
520transfers of existing files.
521Note that resumption assumes that any partial copy of the remote file
522matches the local copy.
523If the local file contents differ from the remote local copy then
524the resultant file is likely to be corrupt.
525.Pp
526If the
518.Fl f 527.Fl f
519flag is specified, then a request will be sent to the server to call 528flag is specified, then a request will be sent to the server to call
520.Xr fsync 2 529.Xr fsync 2
@@ -552,6 +561,18 @@ Equivalent to
552with the 561with the
553.Fl a 562.Fl a
554flag set. 563flag set.
564.It Xo Ic reput
565.Op Fl Ppr
566.Op Ar local-path
567.Ar remote-path
568.Xc
569Resume upload of
570.Op Ar local-path .
571Equivalent to
572.Ic put
573with the
574.Fl a
575flag set.
555.It Ic rename Ar oldpath Ar newpath 576.It Ic rename Ar oldpath Ar newpath
556Rename remote file from 577Rename remote file from
557.Ar oldpath 578.Ar oldpath
diff --git a/sftp.c b/sftp.c
index ad1f8c84d..ff4d63d5c 100644
--- a/sftp.c
+++ b/sftp.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sftp.c,v 1.158 2013/11/20 20:54:10 deraadt Exp $ */ 1/* $OpenBSD: sftp.c,v 1.164 2014/07/09 01:45:10 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org> 3 * Copyright (c) 2001-2004 Damien Miller <djm@openbsd.org>
4 * 4 *
@@ -88,7 +88,7 @@ int showprogress = 1;
88/* When this option is set, we always recursively download/upload directories */ 88/* When this option is set, we always recursively download/upload directories */
89int global_rflag = 0; 89int global_rflag = 0;
90 90
91/* When this option is set, we resume download if possible */ 91/* When this option is set, we resume download or upload if possible */
92int global_aflag = 0; 92int global_aflag = 0;
93 93
94/* When this option is set, the file transfers will always preserve times */ 94/* When this option is set, the file transfers will always preserve times */
@@ -151,14 +151,15 @@ enum sftp_command {
151 I_PUT, 151 I_PUT,
152 I_PWD, 152 I_PWD,
153 I_QUIT, 153 I_QUIT,
154 I_REGET,
154 I_RENAME, 155 I_RENAME,
156 I_REPUT,
155 I_RM, 157 I_RM,
156 I_RMDIR, 158 I_RMDIR,
157 I_SHELL, 159 I_SHELL,
158 I_SYMLINK, 160 I_SYMLINK,
159 I_VERSION, 161 I_VERSION,
160 I_PROGRESS, 162 I_PROGRESS,
161 I_REGET,
162}; 163};
163 164
164struct CMD { 165struct CMD {
@@ -201,6 +202,7 @@ static const struct CMD cmds[] = {
201 { "quit", I_QUIT, NOARGS }, 202 { "quit", I_QUIT, NOARGS },
202 { "reget", I_REGET, REMOTE }, 203 { "reget", I_REGET, REMOTE },
203 { "rename", I_RENAME, REMOTE }, 204 { "rename", I_RENAME, REMOTE },
205 { "reput", I_REPUT, LOCAL },
204 { "rm", I_RM, REMOTE }, 206 { "rm", I_RM, REMOTE },
205 { "rmdir", I_RMDIR, REMOTE }, 207 { "rmdir", I_RMDIR, REMOTE },
206 { "symlink", I_SYMLINK, REMOTE }, 208 { "symlink", I_SYMLINK, REMOTE },
@@ -250,6 +252,7 @@ help(void)
250 "exit Quit sftp\n" 252 "exit Quit sftp\n"
251 "get [-Ppr] remote [local] Download file\n" 253 "get [-Ppr] remote [local] Download file\n"
252 "reget remote [local] Resume download file\n" 254 "reget remote [local] Resume download file\n"
255 "reput [local] remote Resume upload file\n"
253 "help Display this help text\n" 256 "help Display this help text\n"
254 "lcd path Change local directory to 'path'\n" 257 "lcd path Change local directory to 'path'\n"
255 "lls [ls-options [path]] Display local directory listing\n" 258 "lls [ls-options [path]] Display local directory listing\n"
@@ -586,15 +589,19 @@ process_get(struct sftp_conn *conn, char *src, char *dst, char *pwd,
586 char *abs_dst = NULL; 589 char *abs_dst = NULL;
587 glob_t g; 590 glob_t g;
588 char *filename, *tmp=NULL; 591 char *filename, *tmp=NULL;
589 int i, err = 0; 592 int i, r, err = 0;
590 593
591 abs_src = xstrdup(src); 594 abs_src = xstrdup(src);
592 abs_src = make_absolute(abs_src, pwd); 595 abs_src = make_absolute(abs_src, pwd);
593 memset(&g, 0, sizeof(g)); 596 memset(&g, 0, sizeof(g));
594 597
595 debug3("Looking up %s", abs_src); 598 debug3("Looking up %s", abs_src);
596 if (remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) { 599 if ((r = remote_glob(conn, abs_src, GLOB_MARK, NULL, &g)) != 0) {
597 error("File \"%s\" not found.", abs_src); 600 if (r == GLOB_NOSPACE) {
601 error("Too many matches for \"%s\".", abs_src);
602 } else {
603 error("File \"%s\" not found.", abs_src);
604 }
598 err = -1; 605 err = -1;
599 goto out; 606 goto out;
600 } 607 }
@@ -660,7 +667,7 @@ out:
660 667
661static int 668static int
662process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd, 669process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
663 int pflag, int rflag, int fflag) 670 int pflag, int rflag, int resume, int fflag)
664{ 671{
665 char *tmp_dst = NULL; 672 char *tmp_dst = NULL;
666 char *abs_dst = NULL; 673 char *abs_dst = NULL;
@@ -723,16 +730,20 @@ process_put(struct sftp_conn *conn, char *src, char *dst, char *pwd,
723 } 730 }
724 free(tmp); 731 free(tmp);
725 732
726 if (!quiet) 733 resume |= global_aflag;
734 if (!quiet && resume)
735 printf("Resuming upload of %s to %s\n", g.gl_pathv[i],
736 abs_dst);
737 else if (!quiet && !resume)
727 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst); 738 printf("Uploading %s to %s\n", g.gl_pathv[i], abs_dst);
728 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) { 739 if (pathname_is_dir(g.gl_pathv[i]) && (rflag || global_rflag)) {
729 if (upload_dir(conn, g.gl_pathv[i], abs_dst, 740 if (upload_dir(conn, g.gl_pathv[i], abs_dst,
730 pflag || global_pflag, 1, 741 pflag || global_pflag, 1, resume,
731 fflag || global_fflag) == -1) 742 fflag || global_fflag) == -1)
732 err = -1; 743 err = -1;
733 } else { 744 } else {
734 if (do_upload(conn, g.gl_pathv[i], abs_dst, 745 if (do_upload(conn, g.gl_pathv[i], abs_dst,
735 pflag || global_pflag, 746 pflag || global_pflag, resume,
736 fflag || global_fflag) == -1) 747 fflag || global_fflag) == -1)
737 err = -1; 748 err = -1;
738 } 749 }
@@ -855,19 +866,23 @@ do_globbed_ls(struct sftp_conn *conn, char *path, char *strip_path,
855{ 866{
856 char *fname, *lname; 867 char *fname, *lname;
857 glob_t g; 868 glob_t g;
858 int err; 869 int err, r;
859 struct winsize ws; 870 struct winsize ws;
860 u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80; 871 u_int i, c = 1, colspace = 0, columns = 1, m = 0, width = 80;
861 872
862 memset(&g, 0, sizeof(g)); 873 memset(&g, 0, sizeof(g));
863 874
864 if (remote_glob(conn, path, 875 if ((r = remote_glob(conn, path,
865 GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT, 876 GLOB_MARK|GLOB_NOCHECK|GLOB_BRACE|GLOB_KEEPSTAT|GLOB_NOSORT,
866 NULL, &g) || 877 NULL, &g)) != 0 ||
867 (g.gl_pathc && !g.gl_matchc)) { 878 (g.gl_pathc && !g.gl_matchc)) {
868 if (g.gl_pathc) 879 if (g.gl_pathc)
869 globfree(&g); 880 globfree(&g);
870 error("Can't ls: \"%s\" not found", path); 881 if (r == GLOB_NOSPACE) {
882 error("Can't ls: Too many matches for \"%s\"", path);
883 } else {
884 error("Can't ls: \"%s\" not found", path);
885 }
871 return -1; 886 return -1;
872 } 887 }
873 888
@@ -1186,8 +1201,9 @@ makeargv(const char *arg, int *argcp, int sloppy, char *lastquote,
1186} 1201}
1187 1202
1188static int 1203static int
1189parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag, 1204parse_args(const char **cpp, int *ignore_errors, int *aflag,
1190 int *hflag, int *iflag, int *lflag, int *pflag, int *rflag, int *sflag, 1205 int *fflag, int *hflag, int *iflag, int *lflag, int *pflag,
1206 int *rflag, int *sflag,
1191 unsigned long *n_arg, char **path1, char **path2) 1207 unsigned long *n_arg, char **path1, char **path2)
1192{ 1208{
1193 const char *cmd, *cp = *cpp; 1209 const char *cmd, *cp = *cpp;
@@ -1239,6 +1255,7 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
1239 switch (cmdnum) { 1255 switch (cmdnum) {
1240 case I_GET: 1256 case I_GET:
1241 case I_REGET: 1257 case I_REGET:
1258 case I_REPUT:
1242 case I_PUT: 1259 case I_PUT:
1243 if ((optidx = parse_getput_flags(cmd, argv, argc, 1260 if ((optidx = parse_getput_flags(cmd, argv, argc,
1244 aflag, fflag, pflag, rflag)) == -1) 1261 aflag, fflag, pflag, rflag)) == -1)
@@ -1256,11 +1273,6 @@ parse_args(const char **cpp, int *ignore_errors, int *aflag, int *fflag,
1256 /* Destination is not globbed */ 1273 /* Destination is not globbed */
1257 undo_glob_escape(*path2); 1274 undo_glob_escape(*path2);
1258 } 1275 }
1259 if (*aflag && cmdnum == I_PUT) {
1260 /* XXX implement resume for uploads */
1261 error("Resume is not supported for uploads");
1262 return -1;
1263 }
1264 break; 1276 break;
1265 case I_LINK: 1277 case I_LINK:
1266 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1) 1278 if ((optidx = parse_link_flags(cmd, argv, argc, sflag)) == -1)
@@ -1382,7 +1394,8 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1382 int err_abort) 1394 int err_abort)
1383{ 1395{
1384 char *path1, *path2, *tmp; 1396 char *path1, *path2, *tmp;
1385 int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0, iflag = 0; 1397 int ignore_errors = 0, aflag = 0, fflag = 0, hflag = 0,
1398 iflag = 0;
1386 int lflag = 0, pflag = 0, rflag = 0, sflag = 0; 1399 int lflag = 0, pflag = 0, rflag = 0, sflag = 0;
1387 int cmdnum, i; 1400 int cmdnum, i;
1388 unsigned long n_arg = 0; 1401 unsigned long n_arg = 0;
@@ -1415,9 +1428,12 @@ parse_dispatch_command(struct sftp_conn *conn, const char *cmd, char **pwd,
1415 err = process_get(conn, path1, path2, *pwd, pflag, 1428 err = process_get(conn, path1, path2, *pwd, pflag,
1416 rflag, aflag, fflag); 1429 rflag, aflag, fflag);
1417 break; 1430 break;
1431 case I_REPUT:
1432 aflag = 1;
1433 /* FALLTHROUGH */
1418 case I_PUT: 1434 case I_PUT:
1419 err = process_put(conn, path1, path2, *pwd, pflag, 1435 err = process_put(conn, path1, path2, *pwd, pflag,
1420 rflag, fflag); 1436 rflag, aflag, fflag);
1421 break; 1437 break;
1422 case I_RENAME: 1438 case I_RENAME:
1423 path1 = make_absolute(path1, *pwd); 1439 path1 = make_absolute(path1, *pwd);
@@ -1834,6 +1850,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1834 pwdlen = tmplen + 1; /* track last seen '/' */ 1850 pwdlen = tmplen + 1; /* track last seen '/' */
1835 } 1851 }
1836 free(tmp); 1852 free(tmp);
1853 tmp = NULL;
1837 1854
1838 if (g.gl_matchc == 0) 1855 if (g.gl_matchc == 0)
1839 goto out; 1856 goto out;
@@ -1841,7 +1858,6 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1841 if (g.gl_matchc > 1) 1858 if (g.gl_matchc > 1)
1842 complete_display(g.gl_pathv, pwdlen); 1859 complete_display(g.gl_pathv, pwdlen);
1843 1860
1844 tmp = NULL;
1845 /* Don't try to extend globs */ 1861 /* Don't try to extend globs */
1846 if (file == NULL || hadglob) 1862 if (file == NULL || hadglob)
1847 goto out; 1863 goto out;
@@ -1904,7 +1920,7 @@ complete_match(EditLine *el, struct sftp_conn *conn, char *remote_path,
1904 lf = el_line(el); 1920 lf = el_line(el);
1905 if (g.gl_matchc == 1) { 1921 if (g.gl_matchc == 1) {
1906 i = 0; 1922 i = 0;
1907 if (!terminated) 1923 if (!terminated && quote != '\0')
1908 ins[i++] = quote; 1924 ins[i++] = quote;
1909 if (*(lf->cursor - 1) != '/' && 1925 if (*(lf->cursor - 1) != '/' &&
1910 (lastarg || *(lf->cursor) != ' ')) 1926 (lastarg || *(lf->cursor) != ' '))
diff --git a/ssh-add.0 b/ssh-add.0
index ba43fee69..f16165ae5 100644
--- a/ssh-add.0
+++ b/ssh-add.0
@@ -1,4 +1,4 @@
1SSH-ADD(1) OpenBSD Reference Manual SSH-ADD(1) 1SSH-ADD(1) General Commands Manual SSH-ADD(1)
2 2
3NAME 3NAME
4 ssh-add - adds private key identities to the authentication agent 4 ssh-add - adds private key identities to the authentication agent
@@ -120,4 +120,4 @@ AUTHORS
120 created OpenSSH. Markus Friedl contributed the support for SSH protocol 120 created OpenSSH. Markus Friedl contributed the support for SSH protocol
121 versions 1.5 and 2.0. 121 versions 1.5 and 2.0.
122 122
123OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 123OpenBSD 5.6 December 7, 2013 OpenBSD 5.6
diff --git a/ssh-add.c b/ssh-add.c
index 3421452af..78a3359ad 100644
--- a/ssh-add.c
+++ b/ssh-add.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-add.c,v 1.109 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: ssh-add.c,v 1.113 2014/07/09 14:15:56 benno Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -62,6 +62,7 @@
62#include "authfile.h" 62#include "authfile.h"
63#include "pathnames.h" 63#include "pathnames.h"
64#include "misc.h" 64#include "misc.h"
65#include "ssherr.h"
65 66
66/* argv0 */ 67/* argv0 */
67extern char *__progname; 68extern char *__progname;
@@ -170,7 +171,7 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
170 Key *private, *cert; 171 Key *private, *cert;
171 char *comment = NULL; 172 char *comment = NULL;
172 char msg[1024], *certpath = NULL; 173 char msg[1024], *certpath = NULL;
173 int fd, perms_ok, ret = -1; 174 int r, fd, perms_ok, ret = -1;
174 Buffer keyblob; 175 Buffer keyblob;
175 176
176 if (strcmp(filename, "-") == 0) { 177 if (strcmp(filename, "-") == 0) {
@@ -201,12 +202,18 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
201 close(fd); 202 close(fd);
202 203
203 /* At first, try empty passphrase */ 204 /* At first, try empty passphrase */
204 private = key_parse_private(&keyblob, filename, "", &comment); 205 if ((r = sshkey_parse_private_fileblob(&keyblob, "", filename,
206 &private, &comment)) != 0 && r != SSH_ERR_KEY_WRONG_PASSPHRASE)
207 fatal("Cannot parse %s: %s", filename, ssh_err(r));
208 /* try last */
209 if (private == NULL && pass != NULL) {
210 if ((r = sshkey_parse_private_fileblob(&keyblob, pass, filename,
211 &private, &comment)) != 0 &&
212 r != SSH_ERR_KEY_WRONG_PASSPHRASE)
213 fatal("Cannot parse %s: %s", filename, ssh_err(r));
214 }
205 if (comment == NULL) 215 if (comment == NULL)
206 comment = xstrdup(filename); 216 comment = xstrdup(filename);
207 /* try last */
208 if (private == NULL && pass != NULL)
209 private = key_parse_private(&keyblob, filename, pass, NULL);
210 if (private == NULL) { 217 if (private == NULL) {
211 /* clear passphrase since it did not work */ 218 /* clear passphrase since it did not work */
212 clear_pass(); 219 clear_pass();
@@ -220,8 +227,11 @@ add_file(AuthenticationConnection *ac, const char *filename, int key_only)
220 buffer_free(&keyblob); 227 buffer_free(&keyblob);
221 return -1; 228 return -1;
222 } 229 }
223 private = key_parse_private(&keyblob, filename, pass, 230 if ((r = sshkey_parse_private_fileblob(&keyblob,
224 &comment); 231 pass, filename, &private, NULL)) != 0 &&
232 r != SSH_ERR_KEY_WRONG_PASSPHRASE)
233 fatal("Cannot parse %s: %s",
234 filename, ssh_err(r));
225 if (private != NULL) 235 if (private != NULL)
226 break; 236 break;
227 clear_pass(); 237 clear_pass();
@@ -427,6 +437,8 @@ main(int argc, char **argv)
427 437
428 OpenSSL_add_all_algorithms(); 438 OpenSSL_add_all_algorithms();
429 439
440 setlinebuf(stdout);
441
430 /* At first, get a connection to the authentication agent. */ 442 /* At first, get a connection to the authentication agent. */
431 ac = ssh_get_authentication_connection(); 443 ac = ssh_get_authentication_connection();
432 if (ac == NULL) { 444 if (ac == NULL) {
diff --git a/ssh-agent.0 b/ssh-agent.0
index c11523db3..cac40e048 100644
--- a/ssh-agent.0
+++ b/ssh-agent.0
@@ -1,4 +1,4 @@
1SSH-AGENT(1) OpenBSD Reference Manual SSH-AGENT(1) 1SSH-AGENT(1) General Commands Manual SSH-AGENT(1)
2 2
3NAME 3NAME
4 ssh-agent - authentication agent 4 ssh-agent - authentication agent
@@ -9,12 +9,18 @@ SYNOPSIS
9 9
10DESCRIPTION 10DESCRIPTION
11 ssh-agent is a program to hold private keys used for public key 11 ssh-agent is a program to hold private keys used for public key
12 authentication (RSA, DSA, ECDSA, ED25519). The idea is that ssh-agent is 12 authentication (RSA, DSA, ECDSA, ED25519). ssh-agent is usually started
13 started in the beginning of an X-session or a login session, and all 13 in the beginning of an X-session or a login session, and all other
14 other windows or programs are started as clients to the ssh-agent 14 windows or programs are started as clients to the ssh-agent program.
15 program. Through use of environment variables the agent can be located 15 Through use of environment variables the agent can be located and
16 and automatically used for authentication when logging in to other 16 automatically used for authentication when logging in to other machines
17 machines using ssh(1). 17 using ssh(1).
18
19 The agent initially does not have any private keys. Keys are added using
20 ssh-add(1). Multiple identities may be stored in ssh-agent concurrently
21 and ssh(1) will automatically use them if present. ssh-add(1) is also
22 used to remove keys from ssh-agent and to query the keys that are held in
23 one.
18 24
19 The options are as follows: 25 The options are as follows:
20 26
@@ -44,17 +50,6 @@ DESCRIPTION
44 If a commandline is given, this is executed as a subprocess of the agent. 50 If a commandline is given, this is executed as a subprocess of the agent.
45 When the command dies, so does the agent. 51 When the command dies, so does the agent.
46 52
47 The agent initially does not have any private keys. Keys are added using
48 ssh-add(1). When executed without arguments, ssh-add(1) adds the files
49 ~/.ssh/id_rsa, ~/.ssh/id_dsa, ~/.ssh/id_ecdsa, ~/.ssh/id_ed25519 and
50 ~/.ssh/identity. If the identity has a passphrase, ssh-add(1) asks for
51 the passphrase on the terminal if it has one or from a small X11 program
52 if running under X11. If neither of these is the case then the
53 authentication will fail. It then sends the identity to the agent.
54 Several identities can be stored in the agent; the agent can
55 automatically use any of these identities. ssh-add -l displays the
56 identities currently held by the agent.
57
58 The idea is that the agent is run in the user's local PC, laptop, or 53 The idea is that the agent is run in the user's local PC, laptop, or
59 terminal. Authentication data need not be stored on any other machine, 54 terminal. Authentication data need not be stored on any other machine,
60 and authentication passphrases never go over the network. However, the 55 and authentication passphrases never go over the network. However, the
@@ -89,26 +84,6 @@ DESCRIPTION
89 terminates. 84 terminates.
90 85
91FILES 86FILES
92 ~/.ssh/identity
93 Contains the protocol version 1 RSA authentication identity of
94 the user.
95
96 ~/.ssh/id_dsa
97 Contains the protocol version 2 DSA authentication identity of
98 the user.
99
100 ~/.ssh/id_ecdsa
101 Contains the protocol version 2 ECDSA authentication identity of
102 the user.
103
104 ~/.ssh/id_ed25519
105 Contains the protocol version 2 ED25519 authentication identity
106 of the user.
107
108 ~/.ssh/id_rsa
109 Contains the protocol version 2 RSA authentication identity of
110 the user.
111
112 $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid> 87 $TMPDIR/ssh-XXXXXXXXXX/agent.<ppid>
113 UNIX-domain sockets used to contain the connection to the 88 UNIX-domain sockets used to contain the connection to the
114 authentication agent. These sockets should only be readable by 89 authentication agent. These sockets should only be readable by
@@ -125,4 +100,4 @@ AUTHORS
125 created OpenSSH. Markus Friedl contributed the support for SSH protocol 100 created OpenSSH. Markus Friedl contributed the support for SSH protocol
126 versions 1.5 and 2.0. 101 versions 1.5 and 2.0.
127 102
128OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 103OpenBSD 5.6 April 16, 2014 OpenBSD 5.6
diff --git a/ssh-agent.1 b/ssh-agent.1
index 38fd540bd..f2c408070 100644
--- a/ssh-agent.1
+++ b/ssh-agent.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-agent.1,v 1.54 2013/12/07 11:58:46 naddy Exp $ 1.\" $OpenBSD: ssh-agent.1,v 1.55 2014/04/16 23:28:12 djm Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -34,7 +34,7 @@
34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 34.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 35.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
36.\" 36.\"
37.Dd $Mdocdate: December 7 2013 $ 37.Dd $Mdocdate: April 16 2014 $
38.Dt SSH-AGENT 1 38.Dt SSH-AGENT 1
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -54,9 +54,8 @@
54.Nm 54.Nm
55is a program to hold private keys used for public key authentication 55is a program to hold private keys used for public key authentication
56(RSA, DSA, ECDSA, ED25519). 56(RSA, DSA, ECDSA, ED25519).
57The idea is that
58.Nm 57.Nm
59is started in the beginning of an X-session or a login session, and 58is usually started in the beginning of an X-session or a login session, and
60all other windows or programs are started as clients to the ssh-agent 59all other windows or programs are started as clients to the ssh-agent
61program. 60program.
62Through use of environment variables the agent can be located 61Through use of environment variables the agent can be located
@@ -64,6 +63,19 @@ and automatically used for authentication when logging in to other
64machines using 63machines using
65.Xr ssh 1 . 64.Xr ssh 1 .
66.Pp 65.Pp
66The agent initially does not have any private keys.
67Keys are added using
68.Xr ssh-add 1 .
69Multiple identities may be stored in
70.Nm
71concurrently and
72.Xr ssh 1
73will automatically use them if present.
74.Xr ssh-add 1
75is also used to remove keys from
76.Nm
77and to query the keys that are held in one.
78.Pp
67The options are as follows: 79The options are as follows:
68.Bl -tag -width Ds 80.Bl -tag -width Ds
69.It Fl a Ar bind_address 81.It Fl a Ar bind_address
@@ -107,29 +119,6 @@ Without this option the default maximum lifetime is forever.
107If a commandline is given, this is executed as a subprocess of the agent. 119If a commandline is given, this is executed as a subprocess of the agent.
108When the command dies, so does the agent. 120When the command dies, so does the agent.
109.Pp 121.Pp
110The agent initially does not have any private keys.
111Keys are added using
112.Xr ssh-add 1 .
113When executed without arguments,
114.Xr ssh-add 1
115adds the files
116.Pa ~/.ssh/id_rsa ,
117.Pa ~/.ssh/id_dsa ,
118.Pa ~/.ssh/id_ecdsa ,
119.Pa ~/.ssh/id_ed25519
120and
121.Pa ~/.ssh/identity .
122If the identity has a passphrase,
123.Xr ssh-add 1
124asks for the passphrase on the terminal if it has one or from a small X11
125program if running under X11.
126If neither of these is the case then the authentication will fail.
127It then sends the identity to the agent.
128Several identities can be stored in the
129agent; the agent can automatically use any of these identities.
130.Ic ssh-add -l
131displays the identities currently held by the agent.
132.Pp
133The idea is that the agent is run in the user's local PC, laptop, or 122The idea is that the agent is run in the user's local PC, laptop, or
134terminal. 123terminal.
135Authentication data need not be stored on any other 124Authentication data need not be stored on any other
@@ -200,16 +189,6 @@ If you need to set any of these environment variables, you will need to do
200so in the program executed by ssh-agent. 189so in the program executed by ssh-agent.
201.Sh FILES 190.Sh FILES
202.Bl -tag -width Ds 191.Bl -tag -width Ds
203.It Pa ~/.ssh/identity
204Contains the protocol version 1 RSA authentication identity of the user.
205.It Pa ~/.ssh/id_dsa
206Contains the protocol version 2 DSA authentication identity of the user.
207.It Pa ~/.ssh/id_ecdsa
208Contains the protocol version 2 ECDSA authentication identity of the user.
209.It Pa ~/.ssh/id_ed25519
210Contains the protocol version 2 ED25519 authentication identity of the user.
211.It Pa ~/.ssh/id_rsa
212Contains the protocol version 2 RSA authentication identity of the user.
213.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt 192.It Pa $TMPDIR/ssh-XXXXXXXXXX/agent.\*(Ltppid\*(Gt
214.Ux Ns -domain 193.Ux Ns -domain
215sockets used to contain the connection to the authentication agent. 194sockets used to contain the connection to the authentication agent.
diff --git a/ssh-agent.c b/ssh-agent.c
index ba2461211..25f10c549 100644
--- a/ssh-agent.c
+++ b/ssh-agent.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-agent.c,v 1.183 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: ssh-agent.c,v 1.190 2014/07/25 21:22:03 dtucker Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -49,8 +49,10 @@
49#endif 49#endif
50#include "openbsd-compat/sys-queue.h" 50#include "openbsd-compat/sys-queue.h"
51 51
52#ifdef WITH_OPENSSL
52#include <openssl/evp.h> 53#include <openssl/evp.h>
53#include "openbsd-compat/openssl-compat.h" 54#include "openbsd-compat/openssl-compat.h"
55#endif
54 56
55#include <errno.h> 57#include <errno.h>
56#include <fcntl.h> 58#include <fcntl.h>
@@ -124,6 +126,9 @@ int max_fd = 0;
124pid_t parent_pid = -1; 126pid_t parent_pid = -1;
125time_t parent_alive_interval = 0; 127time_t parent_alive_interval = 0;
126 128
129/* pid of process for which cleanup_socket is applicable */
130pid_t cleanup_pid = 0;
131
127/* pathname and directory for AUTH_SOCKET */ 132/* pathname and directory for AUTH_SOCKET */
128char socket_name[MAXPATHLEN]; 133char socket_name[MAXPATHLEN];
129char socket_dir[MAXPATHLEN]; 134char socket_dir[MAXPATHLEN];
@@ -221,9 +226,11 @@ process_request_identities(SocketEntry *e, int version)
221 buffer_put_int(&msg, tab->nentries); 226 buffer_put_int(&msg, tab->nentries);
222 TAILQ_FOREACH(id, &tab->idlist, next) { 227 TAILQ_FOREACH(id, &tab->idlist, next) {
223 if (id->key->type == KEY_RSA1) { 228 if (id->key->type == KEY_RSA1) {
229#ifdef WITH_SSH1
224 buffer_put_int(&msg, BN_num_bits(id->key->rsa->n)); 230 buffer_put_int(&msg, BN_num_bits(id->key->rsa->n));
225 buffer_put_bignum(&msg, id->key->rsa->e); 231 buffer_put_bignum(&msg, id->key->rsa->e);
226 buffer_put_bignum(&msg, id->key->rsa->n); 232 buffer_put_bignum(&msg, id->key->rsa->n);
233#endif
227 } else { 234 } else {
228 u_char *blob; 235 u_char *blob;
229 u_int blen; 236 u_int blen;
@@ -238,6 +245,7 @@ process_request_identities(SocketEntry *e, int version)
238 buffer_free(&msg); 245 buffer_free(&msg);
239} 246}
240 247
248#ifdef WITH_SSH1
241/* ssh1 only */ 249/* ssh1 only */
242static void 250static void
243process_authentication_challenge1(SocketEntry *e) 251process_authentication_challenge1(SocketEntry *e)
@@ -273,7 +281,7 @@ process_authentication_challenge1(SocketEntry *e)
273 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) { 281 if (id != NULL && (!id->confirm || confirm_key(id) == 0)) {
274 Key *private = id->key; 282 Key *private = id->key;
275 /* Decrypt the challenge using the private key. */ 283 /* Decrypt the challenge using the private key. */
276 if (rsa_private_decrypt(challenge, challenge, private->rsa) <= 0) 284 if (rsa_private_decrypt(challenge, challenge, private->rsa) != 0)
277 goto failure; 285 goto failure;
278 286
279 /* The response is MD5 of decrypted challenge plus session id. */ 287 /* The response is MD5 of decrypted challenge plus session id. */
@@ -308,6 +316,7 @@ send:
308 BN_clear_free(challenge); 316 BN_clear_free(challenge);
309 buffer_free(&msg); 317 buffer_free(&msg);
310} 318}
319#endif
311 320
312/* ssh2 only */ 321/* ssh2 only */
313static void 322static void
@@ -359,12 +368,16 @@ process_sign_request2(SocketEntry *e)
359static void 368static void
360process_remove_identity(SocketEntry *e, int version) 369process_remove_identity(SocketEntry *e, int version)
361{ 370{
362 u_int blen, bits; 371 u_int blen;
363 int success = 0; 372 int success = 0;
364 Key *key = NULL; 373 Key *key = NULL;
365 u_char *blob; 374 u_char *blob;
375#ifdef WITH_SSH1
376 u_int bits;
377#endif /* WITH_SSH1 */
366 378
367 switch (version) { 379 switch (version) {
380#ifdef WITH_SSH1
368 case 1: 381 case 1:
369 key = key_new(KEY_RSA1); 382 key = key_new(KEY_RSA1);
370 bits = buffer_get_int(&e->request); 383 bits = buffer_get_int(&e->request);
@@ -375,6 +388,7 @@ process_remove_identity(SocketEntry *e, int version)
375 logit("Warning: identity keysize mismatch: actual %u, announced %u", 388 logit("Warning: identity keysize mismatch: actual %u, announced %u",
376 key_size(key), bits); 389 key_size(key), bits);
377 break; 390 break;
391#endif /* WITH_SSH1 */
378 case 2: 392 case 2:
379 blob = buffer_get_string(&e->request, &blen); 393 blob = buffer_get_string(&e->request, &blen);
380 key = key_from_blob(blob, blen); 394 key = key_from_blob(blob, blen);
@@ -471,6 +485,7 @@ process_add_identity(SocketEntry *e, int version)
471 Key *k = NULL; 485 Key *k = NULL;
472 486
473 switch (version) { 487 switch (version) {
488#ifdef WITH_SSH1
474 case 1: 489 case 1:
475 k = key_new_private(KEY_RSA1); 490 k = key_new_private(KEY_RSA1);
476 (void) buffer_get_int(&e->request); /* ignored */ 491 (void) buffer_get_int(&e->request); /* ignored */
@@ -484,7 +499,9 @@ process_add_identity(SocketEntry *e, int version)
484 buffer_get_bignum(&e->request, k->rsa->p); /* q */ 499 buffer_get_bignum(&e->request, k->rsa->p); /* q */
485 500
486 /* Generate additional parameters */ 501 /* Generate additional parameters */
487 rsa_generate_additional_parameters(k->rsa); 502 if (rsa_generate_additional_parameters(k->rsa) != 0)
503 fatal("%s: rsa_generate_additional_parameters "
504 "error", __func__);
488 505
489 /* enable blinding */ 506 /* enable blinding */
490 if (RSA_blinding_on(k->rsa, NULL) != 1) { 507 if (RSA_blinding_on(k->rsa, NULL) != 1) {
@@ -493,6 +510,7 @@ process_add_identity(SocketEntry *e, int version)
493 goto send; 510 goto send;
494 } 511 }
495 break; 512 break;
513#endif /* WITH_SSH1 */
496 case 2: 514 case 2:
497 k = key_private_deserialize(&e->request); 515 k = key_private_deserialize(&e->request);
498 if (k == NULL) { 516 if (k == NULL) {
@@ -501,11 +519,10 @@ process_add_identity(SocketEntry *e, int version)
501 } 519 }
502 break; 520 break;
503 } 521 }
504 comment = buffer_get_string(&e->request, NULL); 522 if (k == NULL)
505 if (k == NULL) {
506 free(comment);
507 goto send; 523 goto send;
508 } 524 comment = buffer_get_string(&e->request, NULL);
525
509 while (buffer_len(&e->request)) { 526 while (buffer_len(&e->request)) {
510 switch ((type = buffer_get_char(&e->request))) { 527 switch ((type = buffer_get_char(&e->request))) {
511 case SSH_AGENT_CONSTRAIN_LIFETIME: 528 case SSH_AGENT_CONSTRAIN_LIFETIME:
@@ -733,6 +750,7 @@ process_message(SocketEntry *e)
733 case SSH_AGENTC_UNLOCK: 750 case SSH_AGENTC_UNLOCK:
734 process_lock_agent(e, type == SSH_AGENTC_LOCK); 751 process_lock_agent(e, type == SSH_AGENTC_LOCK);
735 break; 752 break;
753#ifdef WITH_SSH1
736 /* ssh1 */ 754 /* ssh1 */
737 case SSH_AGENTC_RSA_CHALLENGE: 755 case SSH_AGENTC_RSA_CHALLENGE:
738 process_authentication_challenge1(e); 756 process_authentication_challenge1(e);
@@ -750,6 +768,7 @@ process_message(SocketEntry *e)
750 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES: 768 case SSH_AGENTC_REMOVE_ALL_RSA_IDENTITIES:
751 process_remove_all_identities(e, 1); 769 process_remove_all_identities(e, 1);
752 break; 770 break;
771#endif
753 /* ssh2 */ 772 /* ssh2 */
754 case SSH2_AGENTC_SIGN_REQUEST: 773 case SSH2_AGENTC_SIGN_REQUEST:
755 process_sign_request2(e); 774 process_sign_request2(e);
@@ -949,6 +968,7 @@ after_select(fd_set *readset, fd_set *writeset)
949 break; 968 break;
950 } 969 }
951 buffer_append(&sockets[i].input, buf, len); 970 buffer_append(&sockets[i].input, buf, len);
971 explicit_bzero(buf, sizeof(buf));
952 process_message(&sockets[i]); 972 process_message(&sockets[i]);
953 } 973 }
954 break; 974 break;
@@ -960,6 +980,9 @@ after_select(fd_set *readset, fd_set *writeset)
960static void 980static void
961cleanup_socket(void) 981cleanup_socket(void)
962{ 982{
983 if (cleanup_pid != 0 && getpid() != cleanup_pid)
984 return;
985 debug("%s: cleanup", __func__);
963 if (socket_name[0]) 986 if (socket_name[0])
964 unlink(socket_name); 987 unlink(socket_name);
965 if (socket_dir[0]) 988 if (socket_dir[0])
@@ -1001,15 +1024,10 @@ check_parent_exists(void)
1001static void 1024static void
1002usage(void) 1025usage(void)
1003{ 1026{
1004 fprintf(stderr, "usage: %s [options] [command [arg ...]]\n", 1027 fprintf(stderr,
1005 __progname); 1028 "usage: ssh-agent [-c | -s] [-d] [-a bind_address] [-t life]\n"
1006 fprintf(stderr, "Options:\n"); 1029 " [command [arg ...]]\n"
1007 fprintf(stderr, " -c Generate C-shell commands on stdout.\n"); 1030 " ssh-agent [-c | -s] -k\n");
1008 fprintf(stderr, " -s Generate Bourne shell commands on stdout.\n");
1009 fprintf(stderr, " -k Kill the current agent.\n");
1010 fprintf(stderr, " -d Debug mode.\n");
1011 fprintf(stderr, " -a socket Bind agent socket to given name.\n");
1012 fprintf(stderr, " -t life Default identity lifetime (seconds).\n");
1013 exit(1); 1031 exit(1);
1014} 1032}
1015 1033
@@ -1021,17 +1039,16 @@ main(int ac, char **av)
1021 u_int nalloc; 1039 u_int nalloc;
1022 char *shell, *format, *pidstr, *agentsocket = NULL; 1040 char *shell, *format, *pidstr, *agentsocket = NULL;
1023 fd_set *readsetp = NULL, *writesetp = NULL; 1041 fd_set *readsetp = NULL, *writesetp = NULL;
1024 struct sockaddr_un sunaddr;
1025#ifdef HAVE_SETRLIMIT 1042#ifdef HAVE_SETRLIMIT
1026 struct rlimit rlim; 1043 struct rlimit rlim;
1027#endif 1044#endif
1028 int prev_mask;
1029 extern int optind; 1045 extern int optind;
1030 extern char *optarg; 1046 extern char *optarg;
1031 pid_t pid; 1047 pid_t pid;
1032 char pidstrbuf[1 + 3 * sizeof pid]; 1048 char pidstrbuf[1 + 3 * sizeof pid];
1033 struct timeval *tvp = NULL; 1049 struct timeval *tvp = NULL;
1034 size_t len; 1050 size_t len;
1051 mode_t prev_mask;
1035 1052
1036 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 1053 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
1037 sanitise_stdfd(); 1054 sanitise_stdfd();
@@ -1045,7 +1062,9 @@ main(int ac, char **av)
1045 prctl(PR_SET_DUMPABLE, 0); 1062 prctl(PR_SET_DUMPABLE, 0);
1046#endif 1063#endif
1047 1064
1065#ifdef WITH_OPENSSL
1048 OpenSSL_add_all_algorithms(); 1066 OpenSSL_add_all_algorithms();
1067#endif
1049 1068
1050 __progname = ssh_get_progname(av[0]); 1069 __progname = ssh_get_progname(av[0]);
1051 seed_rng(); 1070 seed_rng();
@@ -1142,27 +1161,14 @@ main(int ac, char **av)
1142 * Create socket early so it will exist before command gets run from 1161 * Create socket early so it will exist before command gets run from
1143 * the parent. 1162 * the parent.
1144 */ 1163 */
1145 sock = socket(AF_UNIX, SOCK_STREAM, 0);
1146 if (sock < 0) {
1147 perror("socket");
1148 *socket_name = '\0'; /* Don't unlink any existing file */
1149 cleanup_exit(1);
1150 }
1151 memset(&sunaddr, 0, sizeof(sunaddr));
1152 sunaddr.sun_family = AF_UNIX;
1153 strlcpy(sunaddr.sun_path, socket_name, sizeof(sunaddr.sun_path));
1154 prev_mask = umask(0177); 1164 prev_mask = umask(0177);
1155 if (bind(sock, (struct sockaddr *) &sunaddr, sizeof(sunaddr)) < 0) { 1165 sock = unix_listener(socket_name, SSH_LISTEN_BACKLOG, 0);
1156 perror("bind"); 1166 if (sock < 0) {
1167 /* XXX - unix_listener() calls error() not perror() */
1157 *socket_name = '\0'; /* Don't unlink any existing file */ 1168 *socket_name = '\0'; /* Don't unlink any existing file */
1158 umask(prev_mask);
1159 cleanup_exit(1); 1169 cleanup_exit(1);
1160 } 1170 }
1161 umask(prev_mask); 1171 umask(prev_mask);
1162 if (listen(sock, SSH_LISTEN_BACKLOG) < 0) {
1163 perror("listen");
1164 cleanup_exit(1);
1165 }
1166 1172
1167 /* 1173 /*
1168 * Fork, and have the parent execute the command, if any, or present 1174 * Fork, and have the parent execute the command, if any, or present
@@ -1231,6 +1237,8 @@ main(int ac, char **av)
1231 1237
1232skip: 1238skip:
1233 1239
1240 cleanup_pid = getpid();
1241
1234#ifdef ENABLE_PKCS11 1242#ifdef ENABLE_PKCS11
1235 pkcs11_init(0); 1243 pkcs11_init(0);
1236#endif 1244#endif
diff --git a/ssh-dss.c b/ssh-dss.c
index 6b4abcb7d..9643d90d8 100644
--- a/ssh-dss.c
+++ b/ssh-dss.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-dss.c,v 1.31 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: ssh-dss.c,v 1.32 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * 4 *
@@ -28,162 +28,192 @@
28#include <sys/types.h> 28#include <sys/types.h>
29 29
30#include <openssl/bn.h> 30#include <openssl/bn.h>
31#include <openssl/dsa.h>
31#include <openssl/evp.h> 32#include <openssl/evp.h>
32 33
33#include <stdarg.h> 34#include <stdarg.h>
34#include <string.h> 35#include <string.h>
35 36
36#include "xmalloc.h" 37#include "sshbuf.h"
37#include "buffer.h"
38#include "compat.h" 38#include "compat.h"
39#include "log.h" 39#include "ssherr.h"
40#include "key.h"
41#include "digest.h" 40#include "digest.h"
41#define SSHKEY_INTERNAL
42#include "sshkey.h"
42 43
43#define INTBLOB_LEN 20 44#define INTBLOB_LEN 20
44#define SIGBLOB_LEN (2*INTBLOB_LEN) 45#define SIGBLOB_LEN (2*INTBLOB_LEN)
45 46
46int 47int
47ssh_dss_sign(const Key *key, u_char **sigp, u_int *lenp, 48ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
48 const u_char *data, u_int datalen) 49 const u_char *data, size_t datalen, u_int compat)
49{ 50{
50 DSA_SIG *sig; 51 DSA_SIG *sig = NULL;
51 u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN]; 52 u_char digest[SSH_DIGEST_MAX_LENGTH], sigblob[SIGBLOB_LEN];
52 u_int rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); 53 size_t rlen, slen, len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
53 Buffer b; 54 struct sshbuf *b = NULL;
54 55 int ret = SSH_ERR_INVALID_ARGUMENT;
55 if (key == NULL || key_type_plain(key->type) != KEY_DSA || 56
56 key->dsa == NULL) { 57 if (lenp != NULL)
57 error("%s: no DSA key", __func__); 58 *lenp = 0;
58 return -1; 59 if (sigp != NULL)
59 } 60 *sigp = NULL;
60 61
61 if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, 62 if (key == NULL || key->dsa == NULL ||
62 digest, sizeof(digest)) != 0) { 63 sshkey_type_plain(key->type) != KEY_DSA)
63 error("%s: ssh_digest_memory failed", __func__); 64 return SSH_ERR_INVALID_ARGUMENT;
64 return -1; 65 if (dlen == 0)
65 } 66 return SSH_ERR_INTERNAL_ERROR;
66 67
67 sig = DSA_do_sign(digest, dlen, key->dsa); 68 if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
68 explicit_bzero(digest, sizeof(digest)); 69 digest, sizeof(digest))) != 0)
69 70 goto out;
70 if (sig == NULL) { 71
71 error("ssh_dss_sign: sign failed"); 72 if ((sig = DSA_do_sign(digest, dlen, key->dsa)) == NULL) {
72 return -1; 73 ret = SSH_ERR_LIBCRYPTO_ERROR;
74 goto out;
73 } 75 }
74 76
75 rlen = BN_num_bytes(sig->r); 77 rlen = BN_num_bytes(sig->r);
76 slen = BN_num_bytes(sig->s); 78 slen = BN_num_bytes(sig->s);
77 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) { 79 if (rlen > INTBLOB_LEN || slen > INTBLOB_LEN) {
78 error("bad sig size %u %u", rlen, slen); 80 ret = SSH_ERR_INTERNAL_ERROR;
79 DSA_SIG_free(sig); 81 goto out;
80 return -1;
81 } 82 }
82 explicit_bzero(sigblob, SIGBLOB_LEN); 83 explicit_bzero(sigblob, SIGBLOB_LEN);
83 BN_bn2bin(sig->r, sigblob+ SIGBLOB_LEN - INTBLOB_LEN - rlen); 84 BN_bn2bin(sig->r, sigblob + SIGBLOB_LEN - INTBLOB_LEN - rlen);
84 BN_bn2bin(sig->s, sigblob+ SIGBLOB_LEN - slen); 85 BN_bn2bin(sig->s, sigblob + SIGBLOB_LEN - slen);
85 DSA_SIG_free(sig);
86 86
87 if (datafellows & SSH_BUG_SIGBLOB) { 87 if (compat & SSH_BUG_SIGBLOB) {
88 if (lenp != NULL)
89 *lenp = SIGBLOB_LEN;
90 if (sigp != NULL) { 88 if (sigp != NULL) {
91 *sigp = xmalloc(SIGBLOB_LEN); 89 if ((*sigp = malloc(SIGBLOB_LEN)) == NULL) {
90 ret = SSH_ERR_ALLOC_FAIL;
91 goto out;
92 }
92 memcpy(*sigp, sigblob, SIGBLOB_LEN); 93 memcpy(*sigp, sigblob, SIGBLOB_LEN);
93 } 94 }
95 if (lenp != NULL)
96 *lenp = SIGBLOB_LEN;
97 ret = 0;
94 } else { 98 } else {
95 /* ietf-drafts */ 99 /* ietf-drafts */
96 buffer_init(&b); 100 if ((b = sshbuf_new()) == NULL) {
97 buffer_put_cstring(&b, "ssh-dss"); 101 ret = SSH_ERR_ALLOC_FAIL;
98 buffer_put_string(&b, sigblob, SIGBLOB_LEN); 102 goto out;
99 len = buffer_len(&b); 103 }
100 if (lenp != NULL) 104 if ((ret = sshbuf_put_cstring(b, "ssh-dss")) != 0 ||
101 *lenp = len; 105 (ret = sshbuf_put_string(b, sigblob, SIGBLOB_LEN)) != 0)
106 goto out;
107 len = sshbuf_len(b);
102 if (sigp != NULL) { 108 if (sigp != NULL) {
103 *sigp = xmalloc(len); 109 if ((*sigp = malloc(len)) == NULL) {
104 memcpy(*sigp, buffer_ptr(&b), len); 110 ret = SSH_ERR_ALLOC_FAIL;
111 goto out;
112 }
113 memcpy(*sigp, sshbuf_ptr(b), len);
105 } 114 }
106 buffer_free(&b); 115 if (lenp != NULL)
116 *lenp = len;
117 ret = 0;
107 } 118 }
108 return 0; 119 out:
120 explicit_bzero(digest, sizeof(digest));
121 if (sig != NULL)
122 DSA_SIG_free(sig);
123 if (b != NULL)
124 sshbuf_free(b);
125 return ret;
109} 126}
127
110int 128int
111ssh_dss_verify(const Key *key, const u_char *signature, u_int signaturelen, 129ssh_dss_verify(const struct sshkey *key,
112 const u_char *data, u_int datalen) 130 const u_char *signature, size_t signaturelen,
131 const u_char *data, size_t datalen, u_int compat)
113{ 132{
114 DSA_SIG *sig; 133 DSA_SIG *sig = NULL;
115 u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; 134 u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob = NULL;
116 u_int len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1); 135 size_t len, dlen = ssh_digest_bytes(SSH_DIGEST_SHA1);
117 int rlen, ret; 136 int ret = SSH_ERR_INTERNAL_ERROR;
118 Buffer b; 137 struct sshbuf *b = NULL;
119 138 char *ktype = NULL;
120 if (key == NULL || key_type_plain(key->type) != KEY_DSA || 139
121 key->dsa == NULL) { 140 if (key == NULL || key->dsa == NULL ||
122 error("%s: no DSA key", __func__); 141 sshkey_type_plain(key->type) != KEY_DSA)
123 return -1; 142 return SSH_ERR_INVALID_ARGUMENT;
124 } 143 if (dlen == 0)
144 return SSH_ERR_INTERNAL_ERROR;
125 145
126 /* fetch signature */ 146 /* fetch signature */
127 if (datafellows & SSH_BUG_SIGBLOB) { 147 if (compat & SSH_BUG_SIGBLOB) {
128 sigblob = xmalloc(signaturelen); 148 if ((sigblob = malloc(signaturelen)) == NULL)
149 return SSH_ERR_ALLOC_FAIL;
129 memcpy(sigblob, signature, signaturelen); 150 memcpy(sigblob, signature, signaturelen);
130 len = signaturelen; 151 len = signaturelen;
131 } else { 152 } else {
132 /* ietf-drafts */ 153 /* ietf-drafts */
133 char *ktype; 154 if ((b = sshbuf_from(signature, signaturelen)) == NULL)
134 buffer_init(&b); 155 return SSH_ERR_ALLOC_FAIL;
135 buffer_append(&b, signature, signaturelen); 156 if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
136 ktype = buffer_get_cstring(&b, NULL); 157 sshbuf_get_string(b, &sigblob, &len) != 0) {
158 ret = SSH_ERR_INVALID_FORMAT;
159 goto out;
160 }
137 if (strcmp("ssh-dss", ktype) != 0) { 161 if (strcmp("ssh-dss", ktype) != 0) {
138 error("%s: cannot handle type %s", __func__, ktype); 162 ret = SSH_ERR_KEY_TYPE_MISMATCH;
139 buffer_free(&b); 163 goto out;
140 free(ktype);
141 return -1;
142 } 164 }
143 free(ktype); 165 if (sshbuf_len(b) != 0) {
144 sigblob = buffer_get_string(&b, &len); 166 ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
145 rlen = buffer_len(&b); 167 goto out;
146 buffer_free(&b);
147 if (rlen != 0) {
148 error("%s: remaining bytes in signature %d",
149 __func__, rlen);
150 free(sigblob);
151 return -1;
152 } 168 }
153 } 169 }
154 170
155 if (len != SIGBLOB_LEN) { 171 if (len != SIGBLOB_LEN) {
156 fatal("bad sigbloblen %u != SIGBLOB_LEN", len); 172 ret = SSH_ERR_INVALID_FORMAT;
173 goto out;
157 } 174 }
158 175
159 /* parse signature */ 176 /* parse signature */
160 if ((sig = DSA_SIG_new()) == NULL) 177 if ((sig = DSA_SIG_new()) == NULL ||
161 fatal("%s: DSA_SIG_new failed", __func__); 178 (sig->r = BN_new()) == NULL ||
162 if ((sig->r = BN_new()) == NULL) 179 (sig->s = BN_new()) == NULL) {
163 fatal("%s: BN_new failed", __func__); 180 ret = SSH_ERR_ALLOC_FAIL;
164 if ((sig->s = BN_new()) == NULL) 181 goto out;
165 fatal("ssh_dss_verify: BN_new failed"); 182 }
166 if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) || 183 if ((BN_bin2bn(sigblob, INTBLOB_LEN, sig->r) == NULL) ||
167 (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) 184 (BN_bin2bn(sigblob+ INTBLOB_LEN, INTBLOB_LEN, sig->s) == NULL)) {
168 fatal("%s: BN_bin2bn failed", __func__); 185 ret = SSH_ERR_LIBCRYPTO_ERROR;
169 186 goto out;
170 /* clean up */ 187 }
171 explicit_bzero(sigblob, len);
172 free(sigblob);
173 188
174 /* sha1 the data */ 189 /* sha1 the data */
175 if (ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen, 190 if ((ret = ssh_digest_memory(SSH_DIGEST_SHA1, data, datalen,
176 digest, sizeof(digest)) != 0) { 191 digest, sizeof(digest))) != 0)
177 error("%s: digest_memory failed", __func__); 192 goto out;
178 return -1; 193
194 switch (DSA_do_verify(digest, dlen, sig, key->dsa)) {
195 case 1:
196 ret = 0;
197 break;
198 case 0:
199 ret = SSH_ERR_SIGNATURE_INVALID;
200 goto out;
201 default:
202 ret = SSH_ERR_LIBCRYPTO_ERROR;
203 goto out;
179 } 204 }
180 205
181 ret = DSA_do_verify(digest, dlen, sig, key->dsa); 206 out:
182 explicit_bzero(digest, sizeof(digest)); 207 explicit_bzero(digest, sizeof(digest));
183 208 if (sig != NULL)
184 DSA_SIG_free(sig); 209 DSA_SIG_free(sig);
185 210 if (b != NULL)
186 debug("%s: signature %s", __func__, 211 sshbuf_free(b);
187 ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); 212 if (ktype != NULL)
213 free(ktype);
214 if (sigblob != NULL) {
215 explicit_bzero(sigblob, len);
216 free(sigblob);
217 }
188 return ret; 218 return ret;
189} 219}
diff --git a/ssh-ecdsa.c b/ssh-ecdsa.c
index 551c9c460..1119db045 100644
--- a/ssh-ecdsa.c
+++ b/ssh-ecdsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-ecdsa.c,v 1.10 2014/02/03 23:28:00 djm Exp $ */ 1/* $OpenBSD: ssh-ecdsa.c,v 1.11 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2010 Damien Miller. All rights reserved. 4 * Copyright (c) 2010 Damien Miller. All rights reserved.
@@ -37,141 +37,155 @@
37 37
38#include <string.h> 38#include <string.h>
39 39
40#include "xmalloc.h" 40#include "sshbuf.h"
41#include "buffer.h" 41#include "ssherr.h"
42#include "compat.h"
43#include "log.h"
44#include "key.h"
45#include "digest.h" 42#include "digest.h"
43#define SSHKEY_INTERNAL
44#include "sshkey.h"
46 45
46/* ARGSUSED */
47int 47int
48ssh_ecdsa_sign(const Key *key, u_char **sigp, u_int *lenp, 48ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
49 const u_char *data, u_int datalen) 49 const u_char *data, size_t datalen, u_int compat)
50{ 50{
51 ECDSA_SIG *sig; 51 ECDSA_SIG *sig = NULL;
52 int hash_alg; 52 int hash_alg;
53 u_char digest[SSH_DIGEST_MAX_LENGTH]; 53 u_char digest[SSH_DIGEST_MAX_LENGTH];
54 u_int len, dlen; 54 size_t len, dlen;
55 Buffer b, bb; 55 struct sshbuf *b = NULL, *bb = NULL;
56 int ret = SSH_ERR_INTERNAL_ERROR;
56 57
57 if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || 58 if (lenp != NULL)
58 key->ecdsa == NULL) { 59 *lenp = 0;
59 error("%s: no ECDSA key", __func__); 60 if (sigp != NULL)
60 return -1; 61 *sigp = NULL;
62
63 if (key == NULL || key->ecdsa == NULL ||
64 sshkey_type_plain(key->type) != KEY_ECDSA)
65 return SSH_ERR_INVALID_ARGUMENT;
66
67 if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
68 (dlen = ssh_digest_bytes(hash_alg)) == 0)
69 return SSH_ERR_INTERNAL_ERROR;
70 if ((ret = ssh_digest_memory(hash_alg, data, datalen,
71 digest, sizeof(digest))) != 0)
72 goto out;
73
74 if ((sig = ECDSA_do_sign(digest, dlen, key->ecdsa)) == NULL) {
75 ret = SSH_ERR_LIBCRYPTO_ERROR;
76 goto out;
61 } 77 }
62 78
63 hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid); 79 if ((bb = sshbuf_new()) == NULL || (b = sshbuf_new()) == NULL) {
64 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 80 ret = SSH_ERR_ALLOC_FAIL;
65 error("%s: bad hash algorithm %d", __func__, hash_alg); 81 goto out;
66 return -1;
67 }
68 if (ssh_digest_memory(hash_alg, data, datalen,
69 digest, sizeof(digest)) != 0) {
70 error("%s: digest_memory failed", __func__);
71 return -1;
72 } 82 }
73 83 if ((ret = sshbuf_put_bignum2(bb, sig->r)) != 0 ||
74 sig = ECDSA_do_sign(digest, dlen, key->ecdsa); 84 (ret = sshbuf_put_bignum2(bb, sig->s)) != 0)
75 explicit_bzero(digest, sizeof(digest)); 85 goto out;
76 86 if ((ret = sshbuf_put_cstring(b, sshkey_ssh_name_plain(key))) != 0 ||
77 if (sig == NULL) { 87 (ret = sshbuf_put_stringb(b, bb)) != 0)
78 error("%s: sign failed", __func__); 88 goto out;
79 return -1; 89 len = sshbuf_len(b);
90 if (sigp != NULL) {
91 if ((*sigp = malloc(len)) == NULL) {
92 ret = SSH_ERR_ALLOC_FAIL;
93 goto out;
94 }
95 memcpy(*sigp, sshbuf_ptr(b), len);
80 } 96 }
81
82 buffer_init(&bb);
83 buffer_put_bignum2(&bb, sig->r);
84 buffer_put_bignum2(&bb, sig->s);
85 ECDSA_SIG_free(sig);
86
87 buffer_init(&b);
88 buffer_put_cstring(&b, key_ssh_name_plain(key));
89 buffer_put_string(&b, buffer_ptr(&bb), buffer_len(&bb));
90 buffer_free(&bb);
91 len = buffer_len(&b);
92 if (lenp != NULL) 97 if (lenp != NULL)
93 *lenp = len; 98 *lenp = len;
94 if (sigp != NULL) { 99 ret = 0;
95 *sigp = xmalloc(len); 100 out:
96 memcpy(*sigp, buffer_ptr(&b), len); 101 explicit_bzero(digest, sizeof(digest));
97 } 102 if (b != NULL)
98 buffer_free(&b); 103 sshbuf_free(b);
99 104 if (bb != NULL)
100 return 0; 105 sshbuf_free(bb);
106 if (sig != NULL)
107 ECDSA_SIG_free(sig);
108 return ret;
101} 109}
110
111/* ARGSUSED */
102int 112int
103ssh_ecdsa_verify(const Key *key, const u_char *signature, u_int signaturelen, 113ssh_ecdsa_verify(const struct sshkey *key,
104 const u_char *data, u_int datalen) 114 const u_char *signature, size_t signaturelen,
115 const u_char *data, size_t datalen, u_int compat)
105{ 116{
106 ECDSA_SIG *sig; 117 ECDSA_SIG *sig = NULL;
107 int hash_alg; 118 int hash_alg;
108 u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; 119 u_char digest[SSH_DIGEST_MAX_LENGTH];
109 u_int len, dlen; 120 size_t dlen;
110 int rlen, ret; 121 int ret = SSH_ERR_INTERNAL_ERROR;
111 Buffer b, bb; 122 struct sshbuf *b = NULL, *sigbuf = NULL;
112 char *ktype; 123 char *ktype = NULL;
113 124
114 if (key == NULL || key_type_plain(key->type) != KEY_ECDSA || 125 if (key == NULL || key->ecdsa == NULL ||
115 key->ecdsa == NULL) { 126 sshkey_type_plain(key->type) != KEY_ECDSA)
116 error("%s: no ECDSA key", __func__); 127 return SSH_ERR_INVALID_ARGUMENT;
117 return -1; 128
118 } 129 if ((hash_alg = sshkey_ec_nid_to_hash_alg(key->ecdsa_nid)) == -1 ||
130 (dlen = ssh_digest_bytes(hash_alg)) == 0)
131 return SSH_ERR_INTERNAL_ERROR;
119 132
120 /* fetch signature */ 133 /* fetch signature */
121 buffer_init(&b); 134 if ((b = sshbuf_from(signature, signaturelen)) == NULL)
122 buffer_append(&b, signature, signaturelen); 135 return SSH_ERR_ALLOC_FAIL;
123 ktype = buffer_get_string(&b, NULL); 136 if (sshbuf_get_cstring(b, &ktype, NULL) != 0 ||
124 if (strcmp(key_ssh_name_plain(key), ktype) != 0) { 137 sshbuf_froms(b, &sigbuf) != 0) {
125 error("%s: cannot handle type %s", __func__, ktype); 138 ret = SSH_ERR_INVALID_FORMAT;
126 buffer_free(&b); 139 goto out;
127 free(ktype);
128 return -1;
129 } 140 }
130 free(ktype); 141 if (strcmp(sshkey_ssh_name_plain(key), ktype) != 0) {
131 sigblob = buffer_get_string(&b, &len); 142 ret = SSH_ERR_KEY_TYPE_MISMATCH;
132 rlen = buffer_len(&b); 143 goto out;
133 buffer_free(&b); 144 }
134 if (rlen != 0) { 145 if (sshbuf_len(b) != 0) {
135 error("%s: remaining bytes in signature %d", __func__, rlen); 146 ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
136 free(sigblob); 147 goto out;
137 return -1;
138 } 148 }
139 149
140 /* parse signature */ 150 /* parse signature */
141 if ((sig = ECDSA_SIG_new()) == NULL) 151 if ((sig = ECDSA_SIG_new()) == NULL) {
142 fatal("%s: ECDSA_SIG_new failed", __func__); 152 ret = SSH_ERR_ALLOC_FAIL;
143 153 goto out;
144 buffer_init(&bb); 154 }
145 buffer_append(&bb, sigblob, len); 155 if (sshbuf_get_bignum2(sigbuf, sig->r) != 0 ||
146 buffer_get_bignum2(&bb, sig->r); 156 sshbuf_get_bignum2(sigbuf, sig->s) != 0) {
147 buffer_get_bignum2(&bb, sig->s); 157 ret = SSH_ERR_INVALID_FORMAT;
148 if (buffer_len(&bb) != 0) 158 goto out;
149 fatal("%s: remaining bytes in inner sigblob", __func__); 159 }
150 buffer_free(&bb); 160 if (sshbuf_len(sigbuf) != 0) {
151 161 ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
152 /* clean up */ 162 goto out;
153 explicit_bzero(sigblob, len);
154 free(sigblob);
155
156 /* hash the data */
157 hash_alg = key_ec_nid_to_hash_alg(key->ecdsa_nid);
158 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
159 error("%s: bad hash algorithm %d", __func__, hash_alg);
160 return -1;
161 } 163 }
162 if (ssh_digest_memory(hash_alg, data, datalen, 164 if ((ret = ssh_digest_memory(hash_alg, data, datalen,
163 digest, sizeof(digest)) != 0) { 165 digest, sizeof(digest))) != 0)
164 error("%s: digest_memory failed", __func__); 166 goto out;
165 return -1; 167
168 switch (ECDSA_do_verify(digest, dlen, sig, key->ecdsa)) {
169 case 1:
170 ret = 0;
171 break;
172 case 0:
173 ret = SSH_ERR_SIGNATURE_INVALID;
174 goto out;
175 default:
176 ret = SSH_ERR_LIBCRYPTO_ERROR;
177 goto out;
166 } 178 }
167 179
168 ret = ECDSA_do_verify(digest, dlen, sig, key->ecdsa); 180 out:
169 explicit_bzero(digest, sizeof(digest)); 181 explicit_bzero(digest, sizeof(digest));
170 182 if (sigbuf != NULL)
171 ECDSA_SIG_free(sig); 183 sshbuf_free(sigbuf);
172 184 if (b != NULL)
173 debug("%s: signature %s", __func__, 185 sshbuf_free(b);
174 ret == 1 ? "correct" : ret == 0 ? "incorrect" : "error"); 186 if (sig != NULL)
187 ECDSA_SIG_free(sig);
188 free(ktype);
175 return ret; 189 return ret;
176} 190}
177 191
diff --git a/ssh-ed25519.c b/ssh-ed25519.c
index 160d1f23b..cb87d4790 100644
--- a/ssh-ed25519.c
+++ b/ssh-ed25519.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-ed25519.c,v 1.3 2014/02/23 20:03:42 djm Exp $ */ 1/* $OpenBSD: ssh-ed25519.c,v 1.4 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2013 Markus Friedl <markus@openbsd.org> 3 * Copyright (c) 2013 Markus Friedl <markus@openbsd.org>
4 * 4 *
@@ -18,132 +18,149 @@
18#include "includes.h" 18#include "includes.h"
19 19
20#include <sys/types.h> 20#include <sys/types.h>
21#include <limits.h>
21 22
22#include "crypto_api.h" 23#include "crypto_api.h"
23 24
24#include <limits.h>
25#include <string.h> 25#include <string.h>
26#include <stdarg.h> 26#include <stdarg.h>
27 27
28#include "xmalloc.h" 28#include "xmalloc.h"
29#include "log.h" 29#include "log.h"
30#include "buffer.h" 30#include "buffer.h"
31#include "key.h" 31#define SSHKEY_INTERNAL
32#include "sshkey.h"
33#include "ssherr.h"
32#include "ssh.h" 34#include "ssh.h"
33 35
34int 36int
35ssh_ed25519_sign(const Key *key, u_char **sigp, u_int *lenp, 37ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
36 const u_char *data, u_int datalen) 38 const u_char *data, size_t datalen, u_int compat)
37{ 39{
38 u_char *sig; 40 u_char *sig = NULL;
39 u_int slen, len; 41 size_t slen = 0, len;
40 unsigned long long smlen; 42 unsigned long long smlen;
41 int ret; 43 int r, ret;
42 Buffer b; 44 struct sshbuf *b = NULL;
43 45
44 if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || 46 if (lenp != NULL)
45 key->ed25519_sk == NULL) { 47 *lenp = 0;
46 error("%s: no ED25519 key", __func__); 48 if (sigp != NULL)
47 return -1; 49 *sigp = NULL;
48 }
49 50
50 if (datalen >= UINT_MAX - crypto_sign_ed25519_BYTES) { 51 if (key == NULL ||
51 error("%s: datalen %u too long", __func__, datalen); 52 sshkey_type_plain(key->type) != KEY_ED25519 ||
52 return -1; 53 key->ed25519_sk == NULL ||
53 } 54 datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
55 return SSH_ERR_INVALID_ARGUMENT;
54 smlen = slen = datalen + crypto_sign_ed25519_BYTES; 56 smlen = slen = datalen + crypto_sign_ed25519_BYTES;
55 sig = xmalloc(slen); 57 if ((sig = malloc(slen)) == NULL)
58 return SSH_ERR_ALLOC_FAIL;
56 59
57 if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen, 60 if ((ret = crypto_sign_ed25519(sig, &smlen, data, datalen,
58 key->ed25519_sk)) != 0 || smlen <= datalen) { 61 key->ed25519_sk)) != 0 || smlen <= datalen) {
59 error("%s: crypto_sign_ed25519 failed: %d", __func__, ret); 62 r = SSH_ERR_INVALID_ARGUMENT; /* XXX better error? */
60 free(sig); 63 goto out;
61 return -1;
62 } 64 }
63 /* encode signature */ 65 /* encode signature */
64 buffer_init(&b); 66 if ((b = sshbuf_new()) == NULL) {
65 buffer_put_cstring(&b, "ssh-ed25519"); 67 r = SSH_ERR_ALLOC_FAIL;
66 buffer_put_string(&b, sig, smlen - datalen); 68 goto out;
67 len = buffer_len(&b); 69 }
70 if ((r = sshbuf_put_cstring(b, "ssh-ed25519")) != 0 ||
71 (r = sshbuf_put_string(b, sig, smlen - datalen)) != 0)
72 goto out;
73 len = sshbuf_len(b);
74 if (sigp != NULL) {
75 if ((*sigp = malloc(len)) == NULL) {
76 r = SSH_ERR_ALLOC_FAIL;
77 goto out;
78 }
79 memcpy(*sigp, sshbuf_ptr(b), len);
80 }
68 if (lenp != NULL) 81 if (lenp != NULL)
69 *lenp = len; 82 *lenp = len;
70 if (sigp != NULL) { 83 /* success */
71 *sigp = xmalloc(len); 84 r = 0;
72 memcpy(*sigp, buffer_ptr(&b), len); 85 out:
86 sshbuf_free(b);
87 if (sig != NULL) {
88 explicit_bzero(sig, slen);
89 free(sig);
73 } 90 }
74 buffer_free(&b);
75 explicit_bzero(sig, slen);
76 free(sig);
77 91
78 return 0; 92 return r;
79} 93}
80 94
81int 95int
82ssh_ed25519_verify(const Key *key, const u_char *signature, u_int signaturelen, 96ssh_ed25519_verify(const struct sshkey *key,
83 const u_char *data, u_int datalen) 97 const u_char *signature, size_t signaturelen,
98 const u_char *data, size_t datalen, u_int compat)
84{ 99{
85 Buffer b; 100 struct sshbuf *b = NULL;
86 char *ktype; 101 char *ktype = NULL;
87 u_char *sigblob, *sm, *m; 102 const u_char *sigblob;
88 u_int len; 103 u_char *sm = NULL, *m = NULL;
89 unsigned long long smlen, mlen; 104 size_t len;
90 int rlen, ret; 105 unsigned long long smlen = 0, mlen = 0;
106 int r, ret;
91 107
92 if (key == NULL || key_type_plain(key->type) != KEY_ED25519 || 108 if (key == NULL ||
93 key->ed25519_pk == NULL) { 109 sshkey_type_plain(key->type) != KEY_ED25519 ||
94 error("%s: no ED25519 key", __func__); 110 key->ed25519_pk == NULL ||
95 return -1; 111 datalen >= INT_MAX - crypto_sign_ed25519_BYTES)
96 } 112 return SSH_ERR_INVALID_ARGUMENT;
97 buffer_init(&b); 113
98 buffer_append(&b, signature, signaturelen); 114 if ((b = sshbuf_from(signature, signaturelen)) == NULL)
99 ktype = buffer_get_cstring(&b, NULL); 115 return SSH_ERR_ALLOC_FAIL;
116 if ((r = sshbuf_get_cstring(b, &ktype, NULL)) != 0 ||
117 (r = sshbuf_get_string_direct(b, &sigblob, &len)) != 0)
118 goto out;
100 if (strcmp("ssh-ed25519", ktype) != 0) { 119 if (strcmp("ssh-ed25519", ktype) != 0) {
101 error("%s: cannot handle type %s", __func__, ktype); 120 r = SSH_ERR_KEY_TYPE_MISMATCH;
102 buffer_free(&b); 121 goto out;
103 free(ktype);
104 return -1;
105 } 122 }
106 free(ktype); 123 if (sshbuf_len(b) != 0) {
107 sigblob = buffer_get_string(&b, &len); 124 r = SSH_ERR_UNEXPECTED_TRAILING_DATA;
108 rlen = buffer_len(&b); 125 goto out;
109 buffer_free(&b);
110 if (rlen != 0) {
111 error("%s: remaining bytes in signature %d", __func__, rlen);
112 free(sigblob);
113 return -1;
114 } 126 }
115 if (len > crypto_sign_ed25519_BYTES) { 127 if (len > crypto_sign_ed25519_BYTES) {
116 error("%s: len %u > crypto_sign_ed25519_BYTES %u", __func__, 128 r = SSH_ERR_INVALID_FORMAT;
117 len, crypto_sign_ed25519_BYTES); 129 goto out;
118 free(sigblob);
119 return -1;
120 } 130 }
131 if (datalen >= SIZE_MAX - len)
132 return SSH_ERR_INVALID_ARGUMENT;
121 smlen = len + datalen; 133 smlen = len + datalen;
122 sm = xmalloc(smlen); 134 mlen = smlen;
135 if ((sm = malloc(smlen)) == NULL || (m = xmalloc(mlen)) == NULL) {
136 r = SSH_ERR_ALLOC_FAIL;
137 goto out;
138 }
123 memcpy(sm, sigblob, len); 139 memcpy(sm, sigblob, len);
124 memcpy(sm+len, data, datalen); 140 memcpy(sm+len, data, datalen);
125 mlen = smlen;
126 m = xmalloc(mlen);
127 if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen, 141 if ((ret = crypto_sign_ed25519_open(m, &mlen, sm, smlen,
128 key->ed25519_pk)) != 0) { 142 key->ed25519_pk)) != 0) {
129 debug2("%s: crypto_sign_ed25519_open failed: %d", 143 debug2("%s: crypto_sign_ed25519_open failed: %d",
130 __func__, ret); 144 __func__, ret);
131 } 145 }
132 if (ret == 0 && mlen != datalen) { 146 if (ret != 0 || mlen != datalen) {
133 debug2("%s: crypto_sign_ed25519_open " 147 r = SSH_ERR_SIGNATURE_INVALID;
134 "mlen != datalen (%llu != %u)", __func__, mlen, datalen); 148 goto out;
135 ret = -1;
136 } 149 }
137 /* XXX compare 'm' and 'data' ? */ 150 /* XXX compare 'm' and 'data' ? */
138 151 /* success */
139 explicit_bzero(sigblob, len); 152 r = 0;
140 explicit_bzero(sm, smlen); 153 out:
141 explicit_bzero(m, smlen); /* NB. mlen may be invalid if ret != 0 */ 154 if (sm != NULL) {
142 free(sigblob); 155 explicit_bzero(sm, smlen);
143 free(sm); 156 free(sm);
144 free(m); 157 }
145 debug("%s: signature %scorrect", __func__, (ret != 0) ? "in" : ""); 158 if (m != NULL) {
146 159 explicit_bzero(m, smlen); /* NB mlen may be invalid if r != 0 */
147 /* translate return code carefully */ 160 free(m);
148 return (ret == 0) ? 1 : -1; 161 }
162 sshbuf_free(b);
163 free(ktype);
164 return r;
149} 165}
166
diff --git a/ssh-keygen.0 b/ssh-keygen.0
index c43678ff0..648f3017f 100644
--- a/ssh-keygen.0
+++ b/ssh-keygen.0
@@ -1,11 +1,11 @@
1SSH-KEYGEN(1) OpenBSD Reference Manual SSH-KEYGEN(1) 1SSH-KEYGEN(1) General Commands Manual SSH-KEYGEN(1)
2 2
3NAME 3NAME
4 ssh-keygen - authentication key generation, management and conversion 4 ssh-keygen - authentication key generation, management and conversion
5 5
6SYNOPSIS 6SYNOPSIS
7 ssh-keygen [-q] [-b bits] [-t type] [-N new_passphrase] [-C comment] 7 ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]
8 [-f output_keyfile] 8 [-N new_passphrase] [-C comment] [-f output_keyfile]
9 ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile] 9 ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]
10 ssh-keygen -i [-m key_format] [-f input_keyfile] 10 ssh-keygen -i [-m key_format] [-f input_keyfile]
11 ssh-keygen -e [-m key_format] [-f input_keyfile] 11 ssh-keygen -e [-m key_format] [-f input_keyfile]
@@ -164,7 +164,9 @@ DESCRIPTION
164 164
165 -i This option will read an unencrypted private (or public) key file 165 -i This option will read an unencrypted private (or public) key file
166 in the format specified by the -m option and print an OpenSSH 166 in the format specified by the -m option and print an OpenSSH
167 compatible private (or public) key to stdout. 167 compatible private (or public) key to stdout. This option allows
168 importing keys from other software, including several commercial
169 SSH implementations. The default import format is ``RFC4716''.
168 170
169 -J num_lines 171 -J num_lines
170 Exit after screening the specified number of lines while 172 Exit after screening the specified number of lines while
@@ -178,9 +180,7 @@ DESCRIPTION
178 Write the last line processed to the file checkpt while 180 Write the last line processed to the file checkpt while
179 performing DH candidate screening using the -T option. This will 181 performing DH candidate screening using the -T option. This will
180 be used to skip lines in the input file that have already been 182 be used to skip lines in the input file that have already been
181 processed if the job is restarted. This option allows importing 183 processed if the job is restarted.
182 keys from other software, including several commercial SSH
183 implementations. The default import format is ``RFC4716''.
184 184
185 -k Generate a KRL file. In this mode, ssh-keygen will generate a 185 -k Generate a KRL file. In this mode, ssh-keygen will generate a
186 KRL file at the location specified via the -f flag that revokes 186 KRL file at the location specified via the -f flag that revokes
@@ -313,7 +313,7 @@ DESCRIPTION
313 Test DH group exchange candidate primes (generated using the -G 313 Test DH group exchange candidate primes (generated using the -G
314 option) for safety. 314 option) for safety.
315 315
316 -t type 316 -t dsa | ecdsa | ed25519 | rsa | rsa1
317 Specifies the type of key to create. The possible values are 317 Specifies the type of key to create. The possible values are
318 ``rsa1'' for protocol version 1 and ``dsa'', ``ecdsa'', 318 ``rsa1'' for protocol version 1 and ``dsa'', ``ecdsa'',
319 ``ed25519'', or ``rsa'' for protocol version 2. 319 ``ed25519'', or ``rsa'' for protocol version 2.
@@ -559,4 +559,4 @@ AUTHORS
559 created OpenSSH. Markus Friedl contributed the support for SSH protocol 559 created OpenSSH. Markus Friedl contributed the support for SSH protocol
560 versions 1.5 and 2.0. 560 versions 1.5 and 2.0.
561 561
562OpenBSD 5.5 February 5, 2014 OpenBSD 5.5 562OpenBSD 5.6 March 31, 2014 OpenBSD 5.6
diff --git a/ssh-keygen.1 b/ssh-keygen.1
index a71de7481..79b948c8b 100644
--- a/ssh-keygen.1
+++ b/ssh-keygen.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-keygen.1,v 1.120 2014/02/05 20:13:25 naddy Exp $ 1.\" $OpenBSD: ssh-keygen.1,v 1.122 2014/03/31 13:39:34 jmc Exp $
2.\" 2.\"
3.\" Author: Tatu Ylonen <ylo@cs.hut.fi> 3.\" Author: Tatu Ylonen <ylo@cs.hut.fi>
4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4.\" Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -35,7 +35,7 @@
35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 35.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 36.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
37.\" 37.\"
38.Dd $Mdocdate: February 5 2014 $ 38.Dd $Mdocdate: March 31 2014 $
39.Dt SSH-KEYGEN 1 39.Dt SSH-KEYGEN 1
40.Os 40.Os
41.Sh NAME 41.Sh NAME
@@ -46,7 +46,7 @@
46.Nm ssh-keygen 46.Nm ssh-keygen
47.Op Fl q 47.Op Fl q
48.Op Fl b Ar bits 48.Op Fl b Ar bits
49.Op Fl t Ar type 49.Op Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1
50.Op Fl N Ar new_passphrase 50.Op Fl N Ar new_passphrase
51.Op Fl C Ar comment 51.Op Fl C Ar comment
52.Op Fl f Ar output_keyfile 52.Op Fl f Ar output_keyfile
@@ -328,6 +328,10 @@ in the format specified by the
328.Fl m 328.Fl m
329option and print an OpenSSH compatible private 329option and print an OpenSSH compatible private
330(or public) key to stdout. 330(or public) key to stdout.
331This option allows importing keys from other software, including several
332commercial SSH implementations.
333The default import format is
334.Dq RFC4716 .
331.It Fl J Ar num_lines 335.It Fl J Ar num_lines
332Exit after screening the specified number of lines 336Exit after screening the specified number of lines
333while performing DH candidate screening using the 337while performing DH candidate screening using the
@@ -346,10 +350,6 @@ while performing DH candidate screening using the
346option. 350option.
347This will be used to skip lines in the input file that have already been 351This will be used to skip lines in the input file that have already been
348processed if the job is restarted. 352processed if the job is restarted.
349This option allows importing keys from other software, including several
350commercial SSH implementations.
351The default import format is
352.Dq RFC4716 .
353.It Fl k 353.It Fl k
354Generate a KRL file. 354Generate a KRL file.
355In this mode, 355In this mode,
@@ -510,7 +510,7 @@ section for details.
510Test DH group exchange candidate primes (generated using the 510Test DH group exchange candidate primes (generated using the
511.Fl G 511.Fl G
512option) for safety. 512option) for safety.
513.It Fl t Ar type 513.It Fl t Cm dsa | ecdsa | ed25519 | rsa | rsa1
514Specifies the type of key to create. 514Specifies the type of key to create.
515The possible values are 515The possible values are
516.Dq rsa1 516.Dq rsa1
diff --git a/ssh-keygen.c b/ssh-keygen.c
index 2a316bcea..23058ee99 100644
--- a/ssh-keygen.c
+++ b/ssh-keygen.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keygen.c,v 1.241 2014/02/05 20:13:25 naddy Exp $ */ 1/* $OpenBSD: ssh-keygen.c,v 1.249 2014/07/03 03:47:27 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1994 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -165,7 +165,7 @@ int rounds = 0;
165/* argv0 */ 165/* argv0 */
166extern char *__progname; 166extern char *__progname;
167 167
168char hostname[MAXHOSTNAMELEN]; 168char hostname[NI_MAXHOST];
169 169
170/* moduli.c */ 170/* moduli.c */
171int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *); 171int gen_candidates(FILE *, u_int32_t, u_int32_t, BIGNUM *);
@@ -195,6 +195,7 @@ type_bits_valid(int type, u_int32_t *bitsp)
195 fprintf(stderr, "key bits exceeds maximum %d\n", maxbits); 195 fprintf(stderr, "key bits exceeds maximum %d\n", maxbits);
196 exit(1); 196 exit(1);
197 } 197 }
198#ifdef WITH_OPENSSL
198 if (type == KEY_DSA && *bitsp != 1024) 199 if (type == KEY_DSA && *bitsp != 1024)
199 fatal("DSA keys must be 1024 bits"); 200 fatal("DSA keys must be 1024 bits");
200 else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768) 201 else if (type != KEY_ECDSA && type != KEY_ED25519 && *bitsp < 768)
@@ -202,6 +203,7 @@ type_bits_valid(int type, u_int32_t *bitsp)
202 else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1) 203 else if (type == KEY_ECDSA && key_ecdsa_bits_to_nid(*bitsp) == -1)
203 fatal("Invalid ECDSA key length - valid lengths are " 204 fatal("Invalid ECDSA key length - valid lengths are "
204 "256, 384 or 521 bits"); 205 "256, 384 or 521 bits");
206#endif
205} 207}
206 208
207static void 209static void
@@ -278,6 +280,7 @@ load_identity(char *filename)
278#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----" 280#define SSH_COM_PRIVATE_BEGIN "---- BEGIN SSH2 ENCRYPTED PRIVATE KEY ----"
279#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb 281#define SSH_COM_PRIVATE_KEY_MAGIC 0x3f6ff9eb
280 282
283#ifdef WITH_OPENSSL
281static void 284static void
282do_convert_to_ssh2(struct passwd *pw, Key *k) 285do_convert_to_ssh2(struct passwd *pw, Key *k)
283{ 286{
@@ -408,7 +411,7 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
408 Buffer b; 411 Buffer b;
409 Key *key = NULL; 412 Key *key = NULL;
410 char *type, *cipher; 413 char *type, *cipher;
411 u_char *sig, data[] = "abcde12345"; 414 u_char *sig = NULL, data[] = "abcde12345";
412 int magic, rlen, ktype, i1, i2, i3, i4; 415 int magic, rlen, ktype, i1, i2, i3, i4;
413 u_int slen; 416 u_int slen;
414 u_long e; 417 u_long e;
@@ -479,7 +482,9 @@ do_convert_private_ssh2_from_blob(u_char *blob, u_int blen)
479 buffer_get_bignum_bits(&b, key->rsa->iqmp); 482 buffer_get_bignum_bits(&b, key->rsa->iqmp);
480 buffer_get_bignum_bits(&b, key->rsa->q); 483 buffer_get_bignum_bits(&b, key->rsa->q);
481 buffer_get_bignum_bits(&b, key->rsa->p); 484 buffer_get_bignum_bits(&b, key->rsa->p);
482 rsa_generate_additional_parameters(key->rsa); 485 if (rsa_generate_additional_parameters(key->rsa) != 0)
486 fatal("%s: rsa_generate_additional_parameters "
487 "error", __func__);
483 break; 488 break;
484 } 489 }
485 rlen = buffer_len(&b); 490 rlen = buffer_len(&b);
@@ -711,6 +716,7 @@ do_convert_from(struct passwd *pw)
711 key_free(k); 716 key_free(k);
712 exit(0); 717 exit(0);
713} 718}
719#endif
714 720
715static void 721static void
716do_print_public(struct passwd *pw) 722do_print_public(struct passwd *pw)
@@ -981,7 +987,7 @@ do_gen_all_hostkeys(struct passwd *pw)
981} 987}
982 988
983static void 989static void
984printhost(FILE *f, const char *name, Key *public, int ca, int hash) 990printhost(FILE *f, const char *name, Key *public, int ca, int revoked, int hash)
985{ 991{
986 if (print_fingerprint) { 992 if (print_fingerprint) {
987 enum fp_rep rep; 993 enum fp_rep rep;
@@ -1001,7 +1007,8 @@ printhost(FILE *f, const char *name, Key *public, int ca, int hash)
1001 } else { 1007 } else {
1002 if (hash && (name = host_hash(name, NULL, 0)) == NULL) 1008 if (hash && (name = host_hash(name, NULL, 0)) == NULL)
1003 fatal("hash_host failed"); 1009 fatal("hash_host failed");
1004 fprintf(f, "%s%s%s ", ca ? CA_MARKER : "", ca ? " " : "", name); 1010 fprintf(f, "%s%s%s ", ca ? CA_MARKER " " : "",
1011 revoked ? REVOKE_MARKER " " : "" , name);
1005 if (!key_write(public, f)) 1012 if (!key_write(public, f))
1006 fatal("key_write failed"); 1013 fatal("key_write failed");
1007 fprintf(f, "\n"); 1014 fprintf(f, "\n");
@@ -1016,7 +1023,7 @@ do_known_hosts(struct passwd *pw, const char *name)
1016 char *cp, *cp2, *kp, *kp2; 1023 char *cp, *cp2, *kp, *kp2;
1017 char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN]; 1024 char line[16*1024], tmp[MAXPATHLEN], old[MAXPATHLEN];
1018 int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0; 1025 int c, skip = 0, inplace = 0, num = 0, invalid = 0, has_unhashed = 0;
1019 int ca; 1026 int ca, revoked;
1020 int found_key = 0; 1027 int found_key = 0;
1021 1028
1022 if (!have_identity) { 1029 if (!have_identity) {
@@ -1030,6 +1037,7 @@ do_known_hosts(struct passwd *pw, const char *name)
1030 if ((in = fopen(identity_file, "r")) == NULL) 1037 if ((in = fopen(identity_file, "r")) == NULL)
1031 fatal("%s: %s: %s", __progname, identity_file, strerror(errno)); 1038 fatal("%s: %s: %s", __progname, identity_file, strerror(errno));
1032 1039
1040 /* XXX this code is a mess; refactor -djm */
1033 /* 1041 /*
1034 * Find hosts goes to stdout, hash and deletions happen in-place 1042 * Find hosts goes to stdout, hash and deletions happen in-place
1035 * A corner case is ssh-keygen -HF foo, which should go to stdout 1043 * A corner case is ssh-keygen -HF foo, which should go to stdout
@@ -1073,7 +1081,7 @@ do_known_hosts(struct passwd *pw, const char *name)
1073 fprintf(out, "%s\n", cp); 1081 fprintf(out, "%s\n", cp);
1074 continue; 1082 continue;
1075 } 1083 }
1076 /* Check whether this is a CA key */ 1084 /* Check whether this is a CA key or revocation marker */
1077 if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 && 1085 if (strncasecmp(cp, CA_MARKER, sizeof(CA_MARKER) - 1) == 0 &&
1078 (cp[sizeof(CA_MARKER) - 1] == ' ' || 1086 (cp[sizeof(CA_MARKER) - 1] == ' ' ||
1079 cp[sizeof(CA_MARKER) - 1] == '\t')) { 1087 cp[sizeof(CA_MARKER) - 1] == '\t')) {
@@ -1081,6 +1089,14 @@ do_known_hosts(struct passwd *pw, const char *name)
1081 cp += sizeof(CA_MARKER); 1089 cp += sizeof(CA_MARKER);
1082 } else 1090 } else
1083 ca = 0; 1091 ca = 0;
1092 if (strncasecmp(cp, REVOKE_MARKER,
1093 sizeof(REVOKE_MARKER) - 1) == 0 &&
1094 (cp[sizeof(REVOKE_MARKER) - 1] == ' ' ||
1095 cp[sizeof(REVOKE_MARKER) - 1] == '\t')) {
1096 revoked = 1;
1097 cp += sizeof(REVOKE_MARKER);
1098 } else
1099 revoked = 0;
1084 1100
1085 /* Find the end of the host name portion. */ 1101 /* Find the end of the host name portion. */
1086 for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++) 1102 for (kp = cp; *kp && *kp != ' ' && *kp != '\t'; kp++)
@@ -1124,20 +1140,23 @@ do_known_hosts(struct passwd *pw, const char *name)
1124 printf("# Host %s found: " 1140 printf("# Host %s found: "
1125 "line %d type %s%s\n", name, 1141 "line %d type %s%s\n", name,
1126 num, key_type(pub), 1142 num, key_type(pub),
1127 ca ? " (CA key)" : ""); 1143 ca ? " (CA key)" :
1128 printhost(out, cp, pub, ca, 0); 1144 revoked? " (revoked)" : "");
1145 printhost(out, cp, pub, ca, revoked, 0);
1129 found_key = 1; 1146 found_key = 1;
1130 } 1147 }
1131 if (delete_host) { 1148 if (delete_host) {
1132 if (!c && !ca) 1149 if (!c || ca || revoked) {
1133 printhost(out, cp, pub, ca, 0); 1150 printhost(out, cp, pub,
1134 else 1151 ca, revoked, 0);
1152 } else {
1135 printf("# Host %s found: " 1153 printf("# Host %s found: "
1136 "line %d type %s\n", name, 1154 "line %d type %s\n", name,
1137 num, key_type(pub)); 1155 num, key_type(pub));
1156 }
1138 } 1157 }
1139 } else if (hash_hosts) 1158 } else if (hash_hosts)
1140 printhost(out, cp, pub, ca, 0); 1159 printhost(out, cp, pub, ca, revoked, 0);
1141 } else { 1160 } else {
1142 if (find_host || delete_host) { 1161 if (find_host || delete_host) {
1143 c = (match_hostname(name, cp, 1162 c = (match_hostname(name, cp,
@@ -1148,38 +1167,43 @@ do_known_hosts(struct passwd *pw, const char *name)
1148 "line %d type %s%s\n", name, 1167 "line %d type %s%s\n", name,
1149 num, key_type(pub), 1168 num, key_type(pub),
1150 ca ? " (CA key)" : ""); 1169 ca ? " (CA key)" : "");
1151 printhost(out, name, pub, 1170 printhost(out, name, pub, ca, revoked,
1152 ca, hash_hosts && !ca); 1171 hash_hosts && !(ca || revoked));
1153 found_key = 1; 1172 found_key = 1;
1154 } 1173 }
1155 if (delete_host) { 1174 if (delete_host) {
1156 if (!c && !ca) 1175 if (!c || ca || revoked) {
1157 printhost(out, cp, pub, ca, 0); 1176 printhost(out, cp, pub,
1158 else 1177 ca, revoked, 0);
1178 } else {
1159 printf("# Host %s found: " 1179 printf("# Host %s found: "
1160 "line %d type %s\n", name, 1180 "line %d type %s\n", name,
1161 num, key_type(pub)); 1181 num, key_type(pub));
1182 }
1162 } 1183 }
1184 } else if (hash_hosts && (ca || revoked)) {
1185 /* Don't hash CA and revoked keys' hostnames */
1186 printhost(out, cp, pub, ca, revoked, 0);
1187 has_unhashed = 1;
1163 } else if (hash_hosts) { 1188 } else if (hash_hosts) {
1189 /* Hash each hostname separately */
1164 for (cp2 = strsep(&cp, ","); 1190 for (cp2 = strsep(&cp, ",");
1165 cp2 != NULL && *cp2 != '\0'; 1191 cp2 != NULL && *cp2 != '\0';
1166 cp2 = strsep(&cp, ",")) { 1192 cp2 = strsep(&cp, ",")) {
1167 if (ca) { 1193 if (strcspn(cp2, "*?!") !=
1168 fprintf(stderr, "Warning: "
1169 "ignoring CA key for host: "
1170 "%.64s\n", cp2);
1171 printhost(out, cp2, pub, ca, 0);
1172 } else if (strcspn(cp2, "*?!") !=
1173 strlen(cp2)) { 1194 strlen(cp2)) {
1174 fprintf(stderr, "Warning: " 1195 fprintf(stderr, "Warning: "
1175 "ignoring host name with " 1196 "ignoring host name with "
1176 "metacharacters: %.64s\n", 1197 "metacharacters: %.64s\n",
1177 cp2); 1198 cp2);
1178 printhost(out, cp2, pub, ca, 0); 1199 printhost(out, cp2, pub, ca,
1179 } else 1200 revoked, 0);
1180 printhost(out, cp2, pub, ca, 1); 1201 has_unhashed = 1;
1202 } else {
1203 printhost(out, cp2, pub, ca,
1204 revoked, 1);
1205 }
1181 } 1206 }
1182 has_unhashed = 1;
1183 } 1207 }
1184 } 1208 }
1185 key_free(pub); 1209 key_free(pub);
@@ -1589,7 +1613,9 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1589 } 1613 }
1590 } 1614 }
1591 1615
1616#ifdef ENABLE_PKCS11
1592 pkcs11_init(1); 1617 pkcs11_init(1);
1618#endif
1593 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid); 1619 tmp = tilde_expand_filename(ca_key_path, pw->pw_uid);
1594 if (pkcs11provider != NULL) { 1620 if (pkcs11provider != NULL) {
1595 if ((ca = load_pkcs11_key(tmp)) == NULL) 1621 if ((ca = load_pkcs11_key(tmp)) == NULL)
@@ -1631,12 +1657,12 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1631 public->cert->valid_after = cert_valid_from; 1657 public->cert->valid_after = cert_valid_from;
1632 public->cert->valid_before = cert_valid_to; 1658 public->cert->valid_before = cert_valid_to;
1633 if (v00) { 1659 if (v00) {
1634 prepare_options_buf(&public->cert->critical, 1660 prepare_options_buf(public->cert->critical,
1635 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS); 1661 OPTIONS_CRITICAL|OPTIONS_EXTENSIONS);
1636 } else { 1662 } else {
1637 prepare_options_buf(&public->cert->critical, 1663 prepare_options_buf(public->cert->critical,
1638 OPTIONS_CRITICAL); 1664 OPTIONS_CRITICAL);
1639 prepare_options_buf(&public->cert->extensions, 1665 prepare_options_buf(public->cert->extensions,
1640 OPTIONS_EXTENSIONS); 1666 OPTIONS_EXTENSIONS);
1641 } 1667 }
1642 public->cert->signature_key = key_from_private(ca); 1668 public->cert->signature_key = key_from_private(ca);
@@ -1672,7 +1698,9 @@ do_ca_sign(struct passwd *pw, int argc, char **argv)
1672 key_free(public); 1698 key_free(public);
1673 free(out); 1699 free(out);
1674 } 1700 }
1701#ifdef ENABLE_PKCS11
1675 pkcs11_terminate(); 1702 pkcs11_terminate();
1703#endif
1676 exit(0); 1704 exit(0);
1677} 1705}
1678 1706
@@ -1820,8 +1848,8 @@ add_cert_option(char *opt)
1820static void 1848static void
1821show_options(const Buffer *optbuf, int v00, int in_critical) 1849show_options(const Buffer *optbuf, int v00, int in_critical)
1822{ 1850{
1823 char *name; 1851 char *name, *arg;
1824 u_char *data; 1852 const u_char *data;
1825 u_int dlen; 1853 u_int dlen;
1826 Buffer options, option; 1854 Buffer options, option;
1827 1855
@@ -1844,9 +1872,9 @@ show_options(const Buffer *optbuf, int v00, int in_critical)
1844 else if ((v00 || in_critical) && 1872 else if ((v00 || in_critical) &&
1845 (strcmp(name, "force-command") == 0 || 1873 (strcmp(name, "force-command") == 0 ||
1846 strcmp(name, "source-address") == 0)) { 1874 strcmp(name, "source-address") == 0)) {
1847 data = buffer_get_string(&option, NULL); 1875 arg = buffer_get_cstring(&option, NULL);
1848 printf(" %s\n", data); 1876 printf(" %s\n", arg);
1849 free(data); 1877 free(arg);
1850 } else { 1878 } else {
1851 printf(" UNKNOWN OPTION (len %u)\n", 1879 printf(" UNKNOWN OPTION (len %u)\n",
1852 buffer_len(&option)); 1880 buffer_len(&option));
@@ -1905,24 +1933,25 @@ do_show_cert(struct passwd *pw)
1905 printf("\n"); 1933 printf("\n");
1906 } 1934 }
1907 printf(" Critical Options: "); 1935 printf(" Critical Options: ");
1908 if (buffer_len(&key->cert->critical) == 0) 1936 if (buffer_len(key->cert->critical) == 0)
1909 printf("(none)\n"); 1937 printf("(none)\n");
1910 else { 1938 else {
1911 printf("\n"); 1939 printf("\n");
1912 show_options(&key->cert->critical, v00, 1); 1940 show_options(key->cert->critical, v00, 1);
1913 } 1941 }
1914 if (!v00) { 1942 if (!v00) {
1915 printf(" Extensions: "); 1943 printf(" Extensions: ");
1916 if (buffer_len(&key->cert->extensions) == 0) 1944 if (buffer_len(key->cert->extensions) == 0)
1917 printf("(none)\n"); 1945 printf("(none)\n");
1918 else { 1946 else {
1919 printf("\n"); 1947 printf("\n");
1920 show_options(&key->cert->extensions, v00, 0); 1948 show_options(key->cert->extensions, v00, 0);
1921 } 1949 }
1922 } 1950 }
1923 exit(0); 1951 exit(0);
1924} 1952}
1925 1953
1954#ifdef WITH_OPENSSL
1926static void 1955static void
1927load_krl(const char *path, struct ssh_krl **krlp) 1956load_krl(const char *path, struct ssh_krl **krlp)
1928{ 1957{
@@ -2145,60 +2174,40 @@ do_check_krl(struct passwd *pw, int argc, char **argv)
2145 ssh_krl_free(krl); 2174 ssh_krl_free(krl);
2146 exit(ret); 2175 exit(ret);
2147} 2176}
2177#endif
2148 2178
2149static void 2179static void
2150usage(void) 2180usage(void)
2151{ 2181{
2152 fprintf(stderr, "usage: %s [options]\n", __progname); 2182 fprintf(stderr,
2153 fprintf(stderr, "Options:\n"); 2183 "usage: ssh-keygen [-q] [-b bits] [-t dsa | ecdsa | ed25519 | rsa | rsa1]\n"
2154 fprintf(stderr, " -A Generate non-existent host keys for all key types.\n"); 2184 " [-N new_passphrase] [-C comment] [-f output_keyfile]\n"
2155 fprintf(stderr, " -a number Number of KDF rounds for new key format or moduli primality tests.\n"); 2185 " ssh-keygen -p [-P old_passphrase] [-N new_passphrase] [-f keyfile]\n"
2156 fprintf(stderr, " -B Show bubblebabble digest of key file.\n"); 2186 " ssh-keygen -i [-m key_format] [-f input_keyfile]\n"
2157 fprintf(stderr, " -b bits Number of bits in the key to create.\n"); 2187 " ssh-keygen -e [-m key_format] [-f input_keyfile]\n"
2158 fprintf(stderr, " -C comment Provide new comment.\n"); 2188 " ssh-keygen -y [-f input_keyfile]\n"
2159 fprintf(stderr, " -c Change comment in private and public key files.\n"); 2189 " ssh-keygen -c [-P passphrase] [-C comment] [-f keyfile]\n"
2190 " ssh-keygen -l [-f input_keyfile]\n"
2191 " ssh-keygen -B [-f input_keyfile]\n");
2160#ifdef ENABLE_PKCS11 2192#ifdef ENABLE_PKCS11
2161 fprintf(stderr, " -D pkcs11 Download public key from pkcs11 token.\n"); 2193 fprintf(stderr,
2194 " ssh-keygen -D pkcs11\n");
2162#endif 2195#endif
2163 fprintf(stderr, " -e Export OpenSSH to foreign format key file.\n"); 2196 fprintf(stderr,
2164 fprintf(stderr, " -F hostname Find hostname in known hosts file.\n"); 2197 " ssh-keygen -F hostname [-f known_hosts_file] [-l]\n"
2165 fprintf(stderr, " -f filename Filename of the key file.\n"); 2198 " ssh-keygen -H [-f known_hosts_file]\n"
2166 fprintf(stderr, " -G file Generate candidates for DH-GEX moduli.\n"); 2199 " ssh-keygen -R hostname [-f known_hosts_file]\n"
2167 fprintf(stderr, " -g Use generic DNS resource record format.\n"); 2200 " ssh-keygen -r hostname [-f input_keyfile] [-g]\n"
2168 fprintf(stderr, " -H Hash names in known_hosts file.\n"); 2201 " ssh-keygen -G output_file [-v] [-b bits] [-M memory] [-S start_point]\n"
2169 fprintf(stderr, " -h Generate host certificate instead of a user certificate.\n"); 2202 " ssh-keygen -T output_file -f input_file [-v] [-a rounds] [-J num_lines]\n"
2170 fprintf(stderr, " -I key_id Key identifier to include in certificate.\n"); 2203 " [-j start_line] [-K checkpt] [-W generator]\n"
2171 fprintf(stderr, " -i Import foreign format to OpenSSH key file.\n"); 2204 " ssh-keygen -s ca_key -I certificate_identity [-h] [-n principals]\n"
2172 fprintf(stderr, " -J number Screen this number of moduli lines.\n"); 2205 " [-O option] [-V validity_interval] [-z serial_number] file ...\n"
2173 fprintf(stderr, " -j number Start screening moduli at specified line.\n"); 2206 " ssh-keygen -L [-f input_keyfile]\n"
2174 fprintf(stderr, " -K checkpt Write checkpoints to this file.\n"); 2207 " ssh-keygen -A\n"
2175 fprintf(stderr, " -k Generate a KRL file.\n"); 2208 " ssh-keygen -k -f krl_file [-u] [-s ca_public] [-z version_number]\n"
2176 fprintf(stderr, " -L Print the contents of a certificate.\n"); 2209 " file ...\n"
2177 fprintf(stderr, " -l Show fingerprint of key file.\n"); 2210 " ssh-keygen -Q -f krl_file file ...\n");
2178 fprintf(stderr, " -M memory Amount of memory (MB) to use for generating DH-GEX moduli.\n");
2179 fprintf(stderr, " -m key_fmt Conversion format for -e/-i (PEM|PKCS8|RFC4716).\n");
2180 fprintf(stderr, " -N phrase Provide new passphrase.\n");
2181 fprintf(stderr, " -n name,... User/host principal names to include in certificate\n");
2182 fprintf(stderr, " -O option Specify a certificate option.\n");
2183 fprintf(stderr, " -o Enforce new private key format.\n");
2184 fprintf(stderr, " -P phrase Provide old passphrase.\n");
2185 fprintf(stderr, " -p Change passphrase of private key file.\n");
2186 fprintf(stderr, " -Q Test whether key(s) are revoked in KRL.\n");
2187 fprintf(stderr, " -q Quiet.\n");
2188 fprintf(stderr, " -R hostname Remove host from known_hosts file.\n");
2189 fprintf(stderr, " -r hostname Print DNS resource record.\n");
2190 fprintf(stderr, " -S start Start point (hex) for generating DH-GEX moduli.\n");
2191 fprintf(stderr, " -s ca_key Certify keys with CA key.\n");
2192 fprintf(stderr, " -T file Screen candidates for DH-GEX moduli.\n");
2193 fprintf(stderr, " -t type Specify type of key to create.\n");
2194 fprintf(stderr, " -u Update KRL rather than creating a new one.\n");
2195 fprintf(stderr, " -V from:to Specify certificate validity interval.\n");
2196 fprintf(stderr, " -v Verbose.\n");
2197 fprintf(stderr, " -W gen Generator to use for generating DH-GEX moduli.\n");
2198 fprintf(stderr, " -y Read private key file and print public key.\n");
2199 fprintf(stderr, " -Z cipher Specify a cipher for new private key format.\n");
2200 fprintf(stderr, " -z serial Specify a serial number.\n");
2201
2202 exit(1); 2211 exit(1);
2203} 2212}
2204 2213
@@ -2469,6 +2478,7 @@ main(int argc, char **argv)
2469 printf("Cannot use -l with -H or -R.\n"); 2478 printf("Cannot use -l with -H or -R.\n");
2470 usage(); 2479 usage();
2471 } 2480 }
2481#ifdef WITH_OPENSSL
2472 if (gen_krl) { 2482 if (gen_krl) {
2473 do_gen_krl(pw, update_krl, argc, argv); 2483 do_gen_krl(pw, update_krl, argc, argv);
2474 return (0); 2484 return (0);
@@ -2477,6 +2487,7 @@ main(int argc, char **argv)
2477 do_check_krl(pw, argc, argv); 2487 do_check_krl(pw, argc, argv);
2478 return (0); 2488 return (0);
2479 } 2489 }
2490#endif
2480 if (ca_key_path != NULL) { 2491 if (ca_key_path != NULL) {
2481 if (cert_key_id == NULL) 2492 if (cert_key_id == NULL)
2482 fatal("Must specify key id (-I) when certifying"); 2493 fatal("Must specify key id (-I) when certifying");
@@ -2494,10 +2505,12 @@ main(int argc, char **argv)
2494 do_change_passphrase(pw); 2505 do_change_passphrase(pw);
2495 if (change_comment) 2506 if (change_comment)
2496 do_change_comment(pw); 2507 do_change_comment(pw);
2508#ifdef WITH_OPENSSL
2497 if (convert_to) 2509 if (convert_to)
2498 do_convert_to(pw); 2510 do_convert_to(pw);
2499 if (convert_from) 2511 if (convert_from)
2500 do_convert_from(pw); 2512 do_convert_from(pw);
2513#endif
2501 if (print_public) 2514 if (print_public)
2502 do_print_public(pw); 2515 do_print_public(pw);
2503 if (rr_hostname != NULL) { 2516 if (rr_hostname != NULL) {
@@ -2519,7 +2532,8 @@ main(int argc, char **argv)
2519 _PATH_HOST_DSA_KEY_FILE, rr_hostname); 2532 _PATH_HOST_DSA_KEY_FILE, rr_hostname);
2520 n += do_print_resource_record(pw, 2533 n += do_print_resource_record(pw,
2521 _PATH_HOST_ECDSA_KEY_FILE, rr_hostname); 2534 _PATH_HOST_ECDSA_KEY_FILE, rr_hostname);
2522 2535 n += do_print_resource_record(pw,
2536 _PATH_HOST_ED25519_KEY_FILE, rr_hostname);
2523 if (n == 0) 2537 if (n == 0)
2524 fatal("no keys found."); 2538 fatal("no keys found.");
2525 exit(0); 2539 exit(0);
diff --git a/ssh-keyscan.0 b/ssh-keyscan.0
index 638c19b48..853bd5152 100644
--- a/ssh-keyscan.0
+++ b/ssh-keyscan.0
@@ -1,4 +1,4 @@
1SSH-KEYSCAN(1) OpenBSD Reference Manual SSH-KEYSCAN(1) 1SSH-KEYSCAN(1) General Commands Manual SSH-KEYSCAN(1)
2 2
3NAME 3NAME
4 ssh-keyscan - gather ssh public keys 4 ssh-keyscan - gather ssh public keys
@@ -51,7 +51,8 @@ DESCRIPTION
51 The possible values are ``rsa1'' for protocol version 1 and 51 The possible values are ``rsa1'' for protocol version 1 and
52 ``dsa'', ``ecdsa'', ``ed25519'', or ``rsa'' for protocol version 52 ``dsa'', ``ecdsa'', ``ed25519'', or ``rsa'' for protocol version
53 2. Multiple values may be specified by separating them with 53 2. Multiple values may be specified by separating them with
54 commas. The default is to fetch ``rsa'' and ``ecdsa'' keys. 54 commas. The default is to fetch ``rsa'', ``ecdsa'', and
55 ``ed25519'' keys.
55 56
56 -v Verbose mode. Causes ssh-keyscan to print debugging messages 57 -v Verbose mode. Causes ssh-keyscan to print debugging messages
57 about its progress. 58 about its progress.
@@ -69,11 +70,11 @@ FILES
69 70
70 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 71 1.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
71 72
72 Output format for rsa1 keys: 73 Output format for RSA1 keys:
73 74
74 host-or-namelist bits exponent modulus 75 host-or-namelist bits exponent modulus
75 76
76 Output format for rsa, dsa and ecdsa keys: 77 Output format for RSA, DSA, ECDSA, and ED25519 keys:
77 78
78 host-or-namelist keytype base64-encoded-key 79 host-or-namelist keytype base64-encoded-key
79 80
@@ -90,7 +91,7 @@ EXAMPLES
90 Find all hosts from the file ssh_hosts which have new or different keys 91 Find all hosts from the file ssh_hosts which have new or different keys
91 from those in the sorted file ssh_known_hosts: 92 from those in the sorted file ssh_known_hosts:
92 93
93 $ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \ 94 $ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \
94 sort -u - ssh_known_hosts | diff ssh_known_hosts - 95 sort -u - ssh_known_hosts | diff ssh_known_hosts -
95 96
96SEE ALSO 97SEE ALSO
@@ -107,4 +108,4 @@ BUGS
107 This is because it opens a connection to the ssh port, reads the public 108 This is because it opens a connection to the ssh port, reads the public
108 key, and drops the connection as soon as it gets the key. 109 key, and drops the connection as soon as it gets the key.
109 110
110OpenBSD 5.5 January 28, 2014 OpenBSD 5.5 111OpenBSD 5.6 March 12, 2014 OpenBSD 5.6
diff --git a/ssh-keyscan.1 b/ssh-keyscan.1
index dae4fd9fb..5c32ea9c7 100644
--- a/ssh-keyscan.1
+++ b/ssh-keyscan.1
@@ -1,4 +1,4 @@
1.\" $OpenBSD: ssh-keyscan.1,v 1.34 2014/01/28 14:13:39 jmc Exp $ 1.\" $OpenBSD: ssh-keyscan.1,v 1.35 2014/03/12 13:06:59 naddy Exp $
2.\" 2.\"
3.\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. 3.\" Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
4.\" 4.\"
@@ -6,7 +6,7 @@
6.\" permitted provided that due credit is given to the author and the 6.\" permitted provided that due credit is given to the author and the
7.\" OpenBSD project by leaving this copyright notice intact. 7.\" OpenBSD project by leaving this copyright notice intact.
8.\" 8.\"
9.Dd $Mdocdate: January 28 2014 $ 9.Dd $Mdocdate: March 12 2014 $
10.Dt SSH-KEYSCAN 1 10.Dt SSH-KEYSCAN 1
11.Os 11.Os
12.Sh NAME 12.Sh NAME
@@ -98,9 +98,10 @@ or
98for protocol version 2. 98for protocol version 2.
99Multiple values may be specified by separating them with commas. 99Multiple values may be specified by separating them with commas.
100The default is to fetch 100The default is to fetch
101.Dq rsa 101.Dq rsa ,
102.Dq ecdsa ,
102and 103and
103.Dq ecdsa 104.Dq ed25519
104keys. 105keys.
105.It Fl v 106.It Fl v
106Verbose mode. 107Verbose mode.
@@ -124,12 +125,12 @@ Input format:
1241.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4 1251.2.3.4,1.2.4.4 name.my.domain,name,n.my.domain,n,1.2.3.4,1.2.4.4
125.Ed 126.Ed
126.Pp 127.Pp
127Output format for rsa1 keys: 128Output format for RSA1 keys:
128.Bd -literal 129.Bd -literal
129host-or-namelist bits exponent modulus 130host-or-namelist bits exponent modulus
130.Ed 131.Ed
131.Pp 132.Pp
132Output format for rsa, dsa and ecdsa keys: 133Output format for RSA, DSA, ECDSA, and ED25519 keys:
133.Bd -literal 134.Bd -literal
134host-or-namelist keytype base64-encoded-key 135host-or-namelist keytype base64-encoded-key
135.Ed 136.Ed
@@ -158,7 +159,7 @@ Find all hosts from the file
158which have new or different keys from those in the sorted file 159which have new or different keys from those in the sorted file
159.Pa ssh_known_hosts : 160.Pa ssh_known_hosts :
160.Bd -literal 161.Bd -literal
161$ ssh-keyscan -t rsa,dsa,ecdsa -f ssh_hosts | \e 162$ ssh-keyscan -t rsa,dsa,ecdsa,ed25519 -f ssh_hosts | \e
162 sort -u - ssh_known_hosts | diff ssh_known_hosts - 163 sort -u - ssh_known_hosts | diff ssh_known_hosts -
163.Ed 164.Ed
164.Sh SEE ALSO 165.Sh SEE ALSO
diff --git a/ssh-keyscan.c b/ssh-keyscan.c
index 8d0a6b8d8..3fabfba14 100644
--- a/ssh-keyscan.c
+++ b/ssh-keyscan.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keyscan.c,v 1.89 2013/12/06 13:39:49 markus Exp $ */ 1/* $OpenBSD: ssh-keyscan.c,v 1.92 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>. 3 * Copyright 1995, 1996 by David Mazieres <dm@lcs.mit.edu>.
4 * 4 *
@@ -58,7 +58,7 @@ int ssh_port = SSH_DEFAULT_PORT;
58#define KT_ECDSA 8 58#define KT_ECDSA 8
59#define KT_ED25519 16 59#define KT_ED25519 16
60 60
61int get_keytypes = KT_RSA|KT_ECDSA;/* Get RSA and ECDSA keys by default */ 61int get_keytypes = KT_RSA|KT_ECDSA|KT_ED25519;
62 62
63int hash_hosts = 0; /* Hash hostname on output */ 63int hash_hosts = 0; /* Hash hostname on output */
64 64
@@ -182,6 +182,7 @@ strnnsep(char **stringp, char *delim)
182 return (tok); 182 return (tok);
183} 183}
184 184
185#ifdef WITH_SSH1
185static Key * 186static Key *
186keygrab_ssh1(con *c) 187keygrab_ssh1(con *c)
187{ 188{
@@ -215,6 +216,7 @@ keygrab_ssh1(con *c)
215 216
216 return (rsa); 217 return (rsa);
217} 218}
219#endif
218 220
219static int 221static int
220hostjump(Key *hostkey) 222hostjump(Key *hostkey)
@@ -242,6 +244,7 @@ ssh2_capable(int remote_major, int remote_minor)
242static Key * 244static Key *
243keygrab_ssh2(con *c) 245keygrab_ssh2(con *c)
244{ 246{
247 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
245 int j; 248 int j;
246 249
247 packet_set_connection(c->c_fd, c->c_fd); 250 packet_set_connection(c->c_fd, c->c_fd);
@@ -252,11 +255,13 @@ keygrab_ssh2(con *c)
252 (c->c_keytype == KT_ED25519 ? "ssh-ed25519" : 255 (c->c_keytype == KT_ED25519 ? "ssh-ed25519" :
253 "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521")); 256 "ecdsa-sha2-nistp256,ecdsa-sha2-nistp384,ecdsa-sha2-nistp521"));
254 c->c_kex = kex_setup(myproposal); 257 c->c_kex = kex_setup(myproposal);
258#ifdef WITH_OPENSSL
255 c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 259 c->c_kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
256 c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 260 c->c_kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
257 c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 261 c->c_kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
258 c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 262 c->c_kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
259 c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 263 c->c_kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
264#endif
260 c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client; 265 c->c_kex->kex[KEX_C25519_SHA256] = kexc25519_client;
261 c->c_kex->verify_host_key = hostjump; 266 c->c_kex->verify_host_key = hostjump;
262 267
@@ -506,10 +511,12 @@ conread(int s)
506 c->c_data = xmalloc(c->c_len); 511 c->c_data = xmalloc(c->c_len);
507 c->c_status = CS_KEYS; 512 c->c_status = CS_KEYS;
508 break; 513 break;
514#ifdef WITH_SSH1
509 case CS_KEYS: 515 case CS_KEYS:
510 keyprint(c, keygrab_ssh1(c)); 516 keyprint(c, keygrab_ssh1(c));
511 confree(s); 517 confree(s);
512 return; 518 return;
519#endif
513 default: 520 default:
514 fatal("conread: invalid status %d", c->c_status); 521 fatal("conread: invalid status %d", c->c_status);
515 break; 522 break;
diff --git a/ssh-keysign.0 b/ssh-keysign.0
index 5f18b54e3..c34125b72 100644
--- a/ssh-keysign.0
+++ b/ssh-keysign.0
@@ -1,4 +1,4 @@
1SSH-KEYSIGN(8) OpenBSD System Manager's Manual SSH-KEYSIGN(8) 1SSH-KEYSIGN(8) System Manager's Manual SSH-KEYSIGN(8)
2 2
3NAME 3NAME
4 ssh-keysign - ssh helper program for host-based authentication 4 ssh-keysign - ssh helper program for host-based authentication
@@ -50,4 +50,4 @@ HISTORY
50AUTHORS 50AUTHORS
51 Markus Friedl <markus@openbsd.org> 51 Markus Friedl <markus@openbsd.org>
52 52
53OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 53OpenBSD 5.6 December 7, 2013 OpenBSD 5.6
diff --git a/ssh-keysign.c b/ssh-keysign.c
index 6bde8ad17..d95bb7d9d 100644
--- a/ssh-keysign.c
+++ b/ssh-keysign.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-keysign.c,v 1.39 2013/12/06 13:39:49 markus Exp $ */ 1/* $OpenBSD: ssh-keysign.c,v 1.42 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2002 Markus Friedl. All rights reserved. 3 * Copyright (c) 2002 Markus Friedl. All rights reserved.
4 * 4 *
@@ -155,7 +155,7 @@ main(int argc, char **argv)
155 struct passwd *pw; 155 struct passwd *pw;
156 int key_fd[NUM_KEYTYPES], i, found, version = 2, fd; 156 int key_fd[NUM_KEYTYPES], i, found, version = 2, fd;
157 u_char *signature, *data; 157 u_char *signature, *data;
158 char *host; 158 char *host, *fp;
159 u_int slen, dlen; 159 u_int slen, dlen;
160 u_int32_t rnd[256]; 160 u_int32_t rnd[256];
161 161
@@ -201,8 +201,7 @@ main(int argc, char **argv)
201 fatal("could not open any host key"); 201 fatal("could not open any host key");
202 202
203 OpenSSL_add_all_algorithms(); 203 OpenSSL_add_all_algorithms();
204 for (i = 0; i < 256; i++) 204 arc4random_buf(rnd, sizeof(rnd));
205 rnd[i] = arc4random();
206 RAND_seed(rnd, sizeof(rnd)); 205 RAND_seed(rnd, sizeof(rnd));
207 206
208 found = 0; 207 found = 0;
@@ -210,8 +209,11 @@ main(int argc, char **argv)
210 keys[i] = NULL; 209 keys[i] = NULL;
211 if (key_fd[i] == -1) 210 if (key_fd[i] == -1)
212 continue; 211 continue;
212#ifdef WITH_OPENSSL
213/* XXX wrong api */
213 keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC, 214 keys[i] = key_load_private_pem(key_fd[i], KEY_UNSPEC,
214 NULL, NULL); 215 NULL, NULL);
216#endif
215 close(key_fd[i]); 217 close(key_fd[i]);
216 if (keys[i] != NULL) 218 if (keys[i] != NULL)
217 found = 1; 219 found = 1;
@@ -243,8 +245,11 @@ main(int argc, char **argv)
243 break; 245 break;
244 } 246 }
245 } 247 }
246 if (!found) 248 if (!found) {
247 fatal("no matching hostkey found"); 249 fp = key_fingerprint(key, SSH_FP_MD5, SSH_FP_HEX);
250 fatal("no matching hostkey found for key %s %s",
251 key_type(key), fp);
252 }
248 253
249 if (key_sign(keys[i], &signature, &slen, data, dlen) != 0) 254 if (key_sign(keys[i], &signature, &slen, data, dlen) != 0)
250 fatal("key_sign failed"); 255 fatal("key_sign failed");
diff --git a/ssh-pkcs11-client.c b/ssh-pkcs11-client.c
index 6c9f9d2c1..8c74864aa 100644
--- a/ssh-pkcs11-client.c
+++ b/ssh-pkcs11-client.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11-client.c,v 1.4 2013/05/17 00:13:14 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11-client.c,v 1.5 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -30,6 +30,8 @@
30#include <unistd.h> 30#include <unistd.h>
31#include <errno.h> 31#include <errno.h>
32 32
33#include <openssl/rsa.h>
34
33#include "pathnames.h" 35#include "pathnames.h"
34#include "xmalloc.h" 36#include "xmalloc.h"
35#include "buffer.h" 37#include "buffer.h"
diff --git a/ssh-pkcs11-helper.0 b/ssh-pkcs11-helper.0
index 20d62f7a9..279ec5486 100644
--- a/ssh-pkcs11-helper.0
+++ b/ssh-pkcs11-helper.0
@@ -1,4 +1,4 @@
1SSH-PKCS11-HELPER(8) OpenBSD System Manager's Manual SSH-PKCS11-HELPER(8) 1SSH-PKCS11-HELPER(8) System Manager's Manual SSH-PKCS11-HELPER(8)
2 2
3NAME 3NAME
4 ssh-pkcs11-helper - ssh-agent helper program for PKCS#11 support 4 ssh-pkcs11-helper - ssh-agent helper program for PKCS#11 support
@@ -22,4 +22,4 @@ HISTORY
22AUTHORS 22AUTHORS
23 Markus Friedl <markus@openbsd.org> 23 Markus Friedl <markus@openbsd.org>
24 24
25OpenBSD 5.5 July 16, 2013 OpenBSD 5.5 25OpenBSD 5.6 July 16, 2013 OpenBSD 5.6
diff --git a/ssh-pkcs11-helper.c b/ssh-pkcs11-helper.c
index b7c52beb8..0b1d8e4cc 100644
--- a/ssh-pkcs11-helper.c
+++ b/ssh-pkcs11-helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.7 2013/12/02 02:56:17 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11-helper.c,v 1.8 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -169,7 +169,7 @@ process_sign(void)
169{ 169{
170 u_char *blob, *data, *signature = NULL; 170 u_char *blob, *data, *signature = NULL;
171 u_int blen, dlen, slen = 0; 171 u_int blen, dlen, slen = 0;
172 int ok = -1, ret; 172 int ok = -1;
173 Key *key, *found; 173 Key *key, *found;
174 Buffer msg; 174 Buffer msg;
175 175
@@ -179,6 +179,9 @@ process_sign(void)
179 179
180 if ((key = key_from_blob(blob, blen)) != NULL) { 180 if ((key = key_from_blob(blob, blen)) != NULL) {
181 if ((found = lookup_key(key)) != NULL) { 181 if ((found = lookup_key(key)) != NULL) {
182#ifdef WITH_OPENSSL
183 int ret;
184
182 slen = RSA_size(key->rsa); 185 slen = RSA_size(key->rsa);
183 signature = xmalloc(slen); 186 signature = xmalloc(slen);
184 if ((ret = RSA_private_encrypt(dlen, data, signature, 187 if ((ret = RSA_private_encrypt(dlen, data, signature,
@@ -186,6 +189,7 @@ process_sign(void)
186 slen = ret; 189 slen = ret;
187 ok = 0; 190 ok = 0;
188 } 191 }
192#endif /* WITH_OPENSSL */
189 } 193 }
190 key_free(key); 194 key_free(key);
191 } 195 }
diff --git a/ssh-pkcs11.c b/ssh-pkcs11.c
index c49cbf42b..c96be3bd2 100644
--- a/ssh-pkcs11.c
+++ b/ssh-pkcs11.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.c,v 1.11 2013/11/13 13:48:20 markus Exp $ */ 1/* $OpenBSD: ssh-pkcs11.c,v 1.14 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -520,7 +520,7 @@ pkcs11_fetch_keys_filter(struct pkcs11_provider *p, CK_ULONG slotidx,
520 key = key_new(KEY_UNSPEC); 520 key = key_new(KEY_UNSPEC);
521 key->rsa = rsa; 521 key->rsa = rsa;
522 key->type = KEY_RSA; 522 key->type = KEY_RSA;
523 key->flags |= KEY_FLAG_EXT; 523 key->flags |= SSHKEY_FLAG_EXT;
524 if (pkcs11_key_included(keysp, nkeys, key)) { 524 if (pkcs11_key_included(keysp, nkeys, key)) {
525 key_free(key); 525 key_free(key);
526 } else { 526 } else {
diff --git a/ssh-pkcs11.h b/ssh-pkcs11.h
index 59f456adf..4d2efda13 100644
--- a/ssh-pkcs11.h
+++ b/ssh-pkcs11.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-pkcs11.h,v 1.2 2010/02/24 06:12:53 djm Exp $ */ 1/* $OpenBSD: ssh-pkcs11.h,v 1.3 2014/04/29 18:01:49 markus Exp $ */
2/* 2/*
3 * Copyright (c) 2010 Markus Friedl. All rights reserved. 3 * Copyright (c) 2010 Markus Friedl. All rights reserved.
4 * 4 *
@@ -18,3 +18,7 @@ int pkcs11_init(int);
18void pkcs11_terminate(void); 18void pkcs11_terminate(void);
19int pkcs11_add_provider(char *, char *, Key ***); 19int pkcs11_add_provider(char *, char *, Key ***);
20int pkcs11_del_provider(char *); 20int pkcs11_del_provider(char *);
21
22#if !defined(WITH_OPENSSL) && defined(ENABLE_PKCS11)
23#undef ENABLE_PKCS11
24#endif
diff --git a/ssh-rsa.c b/ssh-rsa.c
index c6f25b3ee..fec1953b4 100644
--- a/ssh-rsa.c
+++ b/ssh-rsa.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh-rsa.c,v 1.51 2014/02/02 03:44:31 djm Exp $ */ 1/* $OpenBSD: ssh-rsa.c,v 1.52 2014/06/24 01:13:21 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org> 3 * Copyright (c) 2000, 2003 Markus Friedl <markus@openbsd.org>
4 * 4 *
@@ -25,163 +25,167 @@
25#include <stdarg.h> 25#include <stdarg.h>
26#include <string.h> 26#include <string.h>
27 27
28#include "xmalloc.h" 28#include "sshbuf.h"
29#include "log.h"
30#include "buffer.h"
31#include "key.h"
32#include "compat.h" 29#include "compat.h"
33#include "misc.h" 30#include "ssherr.h"
34#include "ssh.h" 31#define SSHKEY_INTERNAL
32#include "sshkey.h"
35#include "digest.h" 33#include "digest.h"
36 34
37static int openssh_RSA_verify(int, u_char *, u_int, u_char *, u_int, RSA *); 35static int openssh_RSA_verify(int, u_char *, size_t, u_char *, size_t, RSA *);
38 36
39/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */ 37/* RSASSA-PKCS1-v1_5 (PKCS #1 v2.0 signature) with SHA1 */
40int 38int
41ssh_rsa_sign(const Key *key, u_char **sigp, u_int *lenp, 39ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
42 const u_char *data, u_int datalen) 40 const u_char *data, size_t datalen, u_int compat)
43{ 41{
44 int hash_alg; 42 int hash_alg;
45 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig; 43 u_char digest[SSH_DIGEST_MAX_LENGTH], *sig = NULL;
46 u_int slen, dlen, len; 44 size_t slen;
47 int ok, nid; 45 u_int dlen, len;
48 Buffer b; 46 int nid, ret = SSH_ERR_INTERNAL_ERROR;
47 struct sshbuf *b = NULL;
49 48
50 if (key == NULL || key_type_plain(key->type) != KEY_RSA || 49 if (lenp != NULL)
51 key->rsa == NULL) { 50 *lenp = 0;
52 error("%s: no RSA key", __func__); 51 if (sigp != NULL)
53 return -1; 52 *sigp = NULL;
54 } 53
54 if (key == NULL || key->rsa == NULL ||
55 sshkey_type_plain(key->type) != KEY_RSA)
56 return SSH_ERR_INVALID_ARGUMENT;
57 slen = RSA_size(key->rsa);
58 if (slen <= 0 || slen > SSHBUF_MAX_BIGNUM)
59 return SSH_ERR_INVALID_ARGUMENT;
55 60
56 /* hash the data */ 61 /* hash the data */
57 hash_alg = SSH_DIGEST_SHA1; 62 hash_alg = SSH_DIGEST_SHA1;
58 nid = NID_sha1; 63 nid = NID_sha1;
59 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 64 if ((dlen = ssh_digest_bytes(hash_alg)) == 0)
60 error("%s: bad hash algorithm %d", __func__, hash_alg); 65 return SSH_ERR_INTERNAL_ERROR;
61 return -1; 66 if ((ret = ssh_digest_memory(hash_alg, data, datalen,
62 } 67 digest, sizeof(digest))) != 0)
63 if (ssh_digest_memory(hash_alg, data, datalen, 68 goto out;
64 digest, sizeof(digest)) != 0) {
65 error("%s: ssh_digest_memory failed", __func__);
66 return -1;
67 }
68
69 slen = RSA_size(key->rsa);
70 sig = xmalloc(slen);
71
72 ok = RSA_sign(nid, digest, dlen, sig, &len, key->rsa);
73 explicit_bzero(digest, sizeof(digest));
74 69
75 if (ok != 1) { 70 if ((sig = malloc(slen)) == NULL) {
76 int ecode = ERR_get_error(); 71 ret = SSH_ERR_ALLOC_FAIL;
72 goto out;
73 }
77 74
78 error("%s: RSA_sign failed: %s", __func__, 75 if (RSA_sign(nid, digest, dlen, sig, &len, key->rsa) != 1) {
79 ERR_error_string(ecode, NULL)); 76 ret = SSH_ERR_LIBCRYPTO_ERROR;
80 free(sig); 77 goto out;
81 return -1;
82 } 78 }
83 if (len < slen) { 79 if (len < slen) {
84 u_int diff = slen - len; 80 size_t diff = slen - len;
85 debug("slen %u > len %u", slen, len);
86 memmove(sig + diff, sig, len); 81 memmove(sig + diff, sig, len);
87 explicit_bzero(sig, diff); 82 explicit_bzero(sig, diff);
88 } else if (len > slen) { 83 } else if (len > slen) {
89 error("%s: slen %u slen2 %u", __func__, slen, len); 84 ret = SSH_ERR_INTERNAL_ERROR;
90 free(sig); 85 goto out;
91 return -1;
92 } 86 }
93 /* encode signature */ 87 /* encode signature */
94 buffer_init(&b); 88 if ((b = sshbuf_new()) == NULL) {
95 buffer_put_cstring(&b, "ssh-rsa"); 89 ret = SSH_ERR_ALLOC_FAIL;
96 buffer_put_string(&b, sig, slen); 90 goto out;
97 len = buffer_len(&b); 91 }
92 if ((ret = sshbuf_put_cstring(b, "ssh-rsa")) != 0 ||
93 (ret = sshbuf_put_string(b, sig, slen)) != 0)
94 goto out;
95 len = sshbuf_len(b);
96 if (sigp != NULL) {
97 if ((*sigp = malloc(len)) == NULL) {
98 ret = SSH_ERR_ALLOC_FAIL;
99 goto out;
100 }
101 memcpy(*sigp, sshbuf_ptr(b), len);
102 }
98 if (lenp != NULL) 103 if (lenp != NULL)
99 *lenp = len; 104 *lenp = len;
100 if (sigp != NULL) { 105 ret = 0;
101 *sigp = xmalloc(len); 106 out:
102 memcpy(*sigp, buffer_ptr(&b), len); 107 explicit_bzero(digest, sizeof(digest));
108 if (sig != NULL) {
109 explicit_bzero(sig, slen);
110 free(sig);
103 } 111 }
104 buffer_free(&b); 112 if (b != NULL)
105 explicit_bzero(sig, slen); 113 sshbuf_free(b);
106 free(sig);
107
108 return 0; 114 return 0;
109} 115}
110 116
111int 117int
112ssh_rsa_verify(const Key *key, const u_char *signature, u_int signaturelen, 118ssh_rsa_verify(const struct sshkey *key,
113 const u_char *data, u_int datalen) 119 const u_char *signature, size_t signaturelen,
120 const u_char *data, size_t datalen, u_int compat)
114{ 121{
115 Buffer b; 122 char *ktype = NULL;
116 int hash_alg; 123 int hash_alg, ret = SSH_ERR_INTERNAL_ERROR;
117 char *ktype; 124 size_t len, diff, modlen, dlen;
118 u_char digest[SSH_DIGEST_MAX_LENGTH], *sigblob; 125 struct sshbuf *b = NULL;
119 u_int len, dlen, modlen; 126 u_char digest[SSH_DIGEST_MAX_LENGTH], *osigblob, *sigblob = NULL;
120 int rlen, ret;
121 127
122 if (key == NULL || key_type_plain(key->type) != KEY_RSA || 128 if (key == NULL || key->rsa == NULL ||
123 key->rsa == NULL) { 129 sshkey_type_plain(key->type) != KEY_RSA ||
124 error("%s: no RSA key", __func__); 130 BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE)
125 return -1; 131 return SSH_ERR_INVALID_ARGUMENT;
126 }
127 132
128 if (BN_num_bits(key->rsa->n) < SSH_RSA_MINIMUM_MODULUS_SIZE) { 133 if ((b = sshbuf_from(signature, signaturelen)) == NULL)
129 error("%s: RSA modulus too small: %d < minimum %d bits", 134 return SSH_ERR_ALLOC_FAIL;
130 __func__, BN_num_bits(key->rsa->n), 135 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
131 SSH_RSA_MINIMUM_MODULUS_SIZE); 136 ret = SSH_ERR_INVALID_FORMAT;
132 return -1; 137 goto out;
133 } 138 }
134 buffer_init(&b);
135 buffer_append(&b, signature, signaturelen);
136 ktype = buffer_get_cstring(&b, NULL);
137 if (strcmp("ssh-rsa", ktype) != 0) { 139 if (strcmp("ssh-rsa", ktype) != 0) {
138 error("%s: cannot handle type %s", __func__, ktype); 140 ret = SSH_ERR_KEY_TYPE_MISMATCH;
139 buffer_free(&b); 141 goto out;
140 free(ktype);
141 return -1;
142 } 142 }
143 free(ktype); 143 if (sshbuf_get_string(b, &sigblob, &len) != 0) {
144 sigblob = buffer_get_string(&b, &len); 144 ret = SSH_ERR_INVALID_FORMAT;
145 rlen = buffer_len(&b); 145 goto out;
146 buffer_free(&b); 146 }
147 if (rlen != 0) { 147 if (sshbuf_len(b) != 0) {
148 error("%s: remaining bytes in signature %d", __func__, rlen); 148 ret = SSH_ERR_UNEXPECTED_TRAILING_DATA;
149 free(sigblob); 149 goto out;
150 return -1;
151 } 150 }
152 /* RSA_verify expects a signature of RSA_size */ 151 /* RSA_verify expects a signature of RSA_size */
153 modlen = RSA_size(key->rsa); 152 modlen = RSA_size(key->rsa);
154 if (len > modlen) { 153 if (len > modlen) {
155 error("%s: len %u > modlen %u", __func__, len, modlen); 154 ret = SSH_ERR_KEY_BITS_MISMATCH;
156 free(sigblob); 155 goto out;
157 return -1;
158 } else if (len < modlen) { 156 } else if (len < modlen) {
159 u_int diff = modlen - len; 157 diff = modlen - len;
160 debug("%s: add padding: modlen %u > len %u", __func__, 158 osigblob = sigblob;
161 modlen, len); 159 if ((sigblob = realloc(sigblob, modlen)) == NULL) {
162 sigblob = xrealloc(sigblob, 1, modlen); 160 sigblob = osigblob; /* put it back for clear/free */
161 ret = SSH_ERR_ALLOC_FAIL;
162 goto out;
163 }
163 memmove(sigblob + diff, sigblob, len); 164 memmove(sigblob + diff, sigblob, len);
164 explicit_bzero(sigblob, diff); 165 explicit_bzero(sigblob, diff);
165 len = modlen; 166 len = modlen;
166 } 167 }
167 /* hash the data */
168 hash_alg = SSH_DIGEST_SHA1; 168 hash_alg = SSH_DIGEST_SHA1;
169 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) { 169 if ((dlen = ssh_digest_bytes(hash_alg)) == 0) {
170 error("%s: bad hash algorithm %d", __func__, hash_alg); 170 ret = SSH_ERR_INTERNAL_ERROR;
171 return -1; 171 goto out;
172 }
173 if (ssh_digest_memory(hash_alg, data, datalen,
174 digest, sizeof(digest)) != 0) {
175 error("%s: ssh_digest_memory failed", __func__);
176 return -1;
177 } 172 }
173 if ((ret = ssh_digest_memory(hash_alg, data, datalen,
174 digest, sizeof(digest))) != 0)
175 goto out;
178 176
179 ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len, 177 ret = openssh_RSA_verify(hash_alg, digest, dlen, sigblob, len,
180 key->rsa); 178 key->rsa);
179 out:
180 if (sigblob != NULL) {
181 explicit_bzero(sigblob, len);
182 free(sigblob);
183 }
184 if (ktype != NULL)
185 free(ktype);
186 if (b != NULL)
187 sshbuf_free(b);
181 explicit_bzero(digest, sizeof(digest)); 188 explicit_bzero(digest, sizeof(digest));
182 explicit_bzero(sigblob, len);
183 free(sigblob);
184 debug("%s: signature %scorrect", __func__, (ret == 0) ? "in" : "");
185 return ret; 189 return ret;
186} 190}
187 191
@@ -204,15 +208,15 @@ static const u_char id_sha1[] = {
204}; 208};
205 209
206static int 210static int
207openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen, 211openssh_RSA_verify(int hash_alg, u_char *hash, size_t hashlen,
208 u_char *sigbuf, u_int siglen, RSA *rsa) 212 u_char *sigbuf, size_t siglen, RSA *rsa)
209{ 213{
210 u_int ret, rsasize, oidlen = 0, hlen = 0; 214 size_t ret, rsasize = 0, oidlen = 0, hlen = 0;
211 int len, oidmatch, hashmatch; 215 int len, oidmatch, hashmatch;
212 const u_char *oid = NULL; 216 const u_char *oid = NULL;
213 u_char *decrypted = NULL; 217 u_char *decrypted = NULL;
214 218
215 ret = 0; 219 ret = SSH_ERR_INTERNAL_ERROR;
216 switch (hash_alg) { 220 switch (hash_alg) {
217 case SSH_DIGEST_SHA1: 221 case SSH_DIGEST_SHA1:
218 oid = id_sha1; 222 oid = id_sha1;
@@ -223,37 +227,39 @@ openssh_RSA_verify(int hash_alg, u_char *hash, u_int hashlen,
223 goto done; 227 goto done;
224 } 228 }
225 if (hashlen != hlen) { 229 if (hashlen != hlen) {
226 error("bad hashlen"); 230 ret = SSH_ERR_INVALID_ARGUMENT;
227 goto done; 231 goto done;
228 } 232 }
229 rsasize = RSA_size(rsa); 233 rsasize = RSA_size(rsa);
230 if (siglen == 0 || siglen > rsasize) { 234 if (rsasize <= 0 || rsasize > SSHBUF_MAX_BIGNUM ||
231 error("bad siglen"); 235 siglen == 0 || siglen > rsasize) {
236 ret = SSH_ERR_INVALID_ARGUMENT;
237 goto done;
238 }
239 if ((decrypted = malloc(rsasize)) == NULL) {
240 ret = SSH_ERR_ALLOC_FAIL;
232 goto done; 241 goto done;
233 } 242 }
234 decrypted = xmalloc(rsasize);
235 if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa, 243 if ((len = RSA_public_decrypt(siglen, sigbuf, decrypted, rsa,
236 RSA_PKCS1_PADDING)) < 0) { 244 RSA_PKCS1_PADDING)) < 0) {
237 error("RSA_public_decrypt failed: %s", 245 ret = SSH_ERR_LIBCRYPTO_ERROR;
238 ERR_error_string(ERR_get_error(), NULL));
239 goto done; 246 goto done;
240 } 247 }
241 if (len < 0 || (u_int)len != hlen + oidlen) { 248 if (len < 0 || (size_t)len != hlen + oidlen) {
242 error("bad decrypted len: %d != %d + %d", len, hlen, oidlen); 249 ret = SSH_ERR_INVALID_FORMAT;
243 goto done; 250 goto done;
244 } 251 }
245 oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0; 252 oidmatch = timingsafe_bcmp(decrypted, oid, oidlen) == 0;
246 hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0; 253 hashmatch = timingsafe_bcmp(decrypted + oidlen, hash, hlen) == 0;
247 if (!oidmatch) { 254 if (!oidmatch || !hashmatch) {
248 error("oid mismatch"); 255 ret = SSH_ERR_SIGNATURE_INVALID;
249 goto done;
250 }
251 if (!hashmatch) {
252 error("hash mismatch");
253 goto done; 256 goto done;
254 } 257 }
255 ret = 1; 258 ret = 0;
256done: 259done:
257 free(decrypted); 260 if (decrypted) {
261 explicit_bzero(decrypted, rsasize);
262 free(decrypted);
263 }
258 return ret; 264 return ret;
259} 265}
diff --git a/ssh.0 b/ssh.0
index 16868cfca..70ea37733 100644
--- a/ssh.0
+++ b/ssh.0
@@ -1,4 +1,4 @@
1SSH(1) OpenBSD Reference Manual SSH(1) 1SSH(1) General Commands Manual SSH(1)
2 2
3NAME 3NAME
4 ssh - OpenSSH SSH client (remote login program) 4 ssh - OpenSSH SSH client (remote login program)
@@ -17,8 +17,9 @@ DESCRIPTION
17 ssh (SSH client) is a program for logging into a remote machine and for 17 ssh (SSH client) is a program for logging into a remote machine and for
18 executing commands on a remote machine. It is intended to replace rlogin 18 executing commands on a remote machine. It is intended to replace rlogin
19 and rsh, and provide secure encrypted communications between two 19 and rsh, and provide secure encrypted communications between two
20 untrusted hosts over an insecure network. X11 connections and arbitrary 20 untrusted hosts over an insecure network. X11 connections, arbitrary TCP
21 TCP ports can also be forwarded over the secure channel. 21 ports and UNIX-domain sockets can also be forwarded over the secure
22 channel.
22 23
23 ssh connects and logs into the specified hostname (with optional user 24 ssh connects and logs into the specified hostname (with optional user
24 name). The user must prove his/her identity to the remote machine using 25 name). The user must prove his/her identity to the remote machine using
@@ -58,28 +59,21 @@ DESCRIPTION
58 address. 59 address.
59 60
60 -C Requests compression of all data (including stdin, stdout, 61 -C Requests compression of all data (including stdin, stdout,
61 stderr, and data for forwarded X11 and TCP connections). The 62 stderr, and data for forwarded X11, TCP and UNIX-domain
62 compression algorithm is the same used by gzip(1), and the 63 connections). The compression algorithm is the same used by
63 ``level'' can be controlled by the CompressionLevel option for 64 gzip(1), and the ``level'' can be controlled by the
64 protocol version 1. Compression is desirable on modem lines and 65 CompressionLevel option for protocol version 1. Compression is
65 other slow connections, but will only slow down things on fast 66 desirable on modem lines and other slow connections, but will
66 networks. The default value can be set on a host-by-host basis 67 only slow down things on fast networks. The default value can be
67 in the configuration files; see the Compression option. 68 set on a host-by-host basis in the configuration files; see the
69 Compression option.
68 70
69 -c cipher_spec 71 -c cipher_spec
70 Selects the cipher specification for encrypting the session. 72 Selects the cipher specification for encrypting the session.
71 73
72 Protocol version 1 allows specification of a single cipher. The 74 Protocol version 1 allows specification of a single cipher. The
73 supported values are ``3des'', ``blowfish'', and ``des''. 3des 75 supported values are ``3des'', ``blowfish'', and ``des''. For
74 (triple-des) is an encrypt-decrypt-encrypt triple with three 76 protocol version 2, cipher_spec is a comma-separated list of
75 different keys. It is believed to be secure. blowfish is a fast
76 block cipher; it appears very secure and is much faster than
77 3des. des is only supported in the ssh client for
78 interoperability with legacy protocol 1 implementations that do
79 not support the 3des cipher. Its use is strongly discouraged due
80 to cryptographic weaknesses. The default is ``3des''.
81
82 For protocol version 2, cipher_spec is a comma-separated list of
83 ciphers listed in order of preference. See the Ciphers keyword 77 ciphers listed in order of preference. See the Ciphers keyword
84 in ssh_config(5) for more information. 78 in ssh_config(5) for more information.
85 79
@@ -133,7 +127,9 @@ DESCRIPTION
133 port forwards to be successfully established before placing 127 port forwards to be successfully established before placing
134 itself in the background. 128 itself in the background.
135 129
136 -g Allows remote hosts to connect to local forwarded ports. 130 -g Allows remote hosts to connect to local forwarded ports. If used
131 on a multiplexed connection, then this option must be specified
132 on the master process.
137 133
138 -I pkcs11 134 -I pkcs11
139 Specify the PKCS#11 shared library ssh should use to communicate 135 Specify the PKCS#11 shared library ssh should use to communicate
@@ -286,6 +282,8 @@ DESCRIPTION
286 SendEnv 282 SendEnv
287 ServerAliveInterval 283 ServerAliveInterval
288 ServerAliveCountMax 284 ServerAliveCountMax
285 StreamLocalBindMask
286 StreamLocalBindUnlink
289 StrictHostKeyChecking 287 StrictHostKeyChecking
290 TCPKeepAlive 288 TCPKeepAlive
291 Tunnel 289 Tunnel
@@ -890,7 +888,7 @@ EXIT STATUS
890 888
891SEE ALSO 889SEE ALSO
892 scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1), 890 scp(1), sftp(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), ssh-keyscan(1),
893 tun(4), hosts.equiv(5), ssh_config(5), ssh-keysign(8), sshd(8) 891 tun(4), ssh_config(5), ssh-keysign(8), sshd(8)
894 892
895STANDARDS 893STANDARDS
896 S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned 894 S. Lehtinen and C. Lonvick, The Secure Shell (SSH) Protocol Assigned
@@ -943,4 +941,4 @@ AUTHORS
943 created OpenSSH. Markus Friedl contributed the support for SSH protocol 941 created OpenSSH. Markus Friedl contributed the support for SSH protocol
944 versions 1.5 and 2.0. 942 versions 1.5 and 2.0.
945 943
946OpenBSD 5.5 December 7, 2013 OpenBSD 5.5 944OpenBSD 5.6 July 24, 2014 OpenBSD 5.6
diff --git a/ssh.1 b/ssh.1
index 986802598..2606b15b1 100644
--- a/ssh.1
+++ b/ssh.1
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh.1,v 1.343 2013/12/07 11:58:46 naddy Exp $ 36.\" $OpenBSD: ssh.1,v 1.348 2014/07/24 22:57:10 millert Exp $
37.Dd $Mdocdate: December 7 2013 $ 37.Dd $Mdocdate: July 24 2014 $
38.Dt SSH 1 38.Dt SSH 1
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -73,8 +73,9 @@ executing commands on a remote machine.
73It is intended to replace rlogin and rsh, 73It is intended to replace rlogin and rsh,
74and provide secure encrypted communications between 74and provide secure encrypted communications between
75two untrusted hosts over an insecure network. 75two untrusted hosts over an insecure network.
76X11 connections and arbitrary TCP ports 76X11 connections, arbitrary TCP ports and
77can also be forwarded over the secure channel. 77.Ux Ns -domain
78sockets can also be forwarded over the secure channel.
78.Pp 79.Pp
79.Nm 80.Nm
80connects and logs into the specified 81connects and logs into the specified
@@ -131,7 +132,9 @@ of the connection.
131Only useful on systems with more than one address. 132Only useful on systems with more than one address.
132.It Fl C 133.It Fl C
133Requests compression of all data (including stdin, stdout, stderr, and 134Requests compression of all data (including stdin, stdout, stderr, and
134data for forwarded X11 and TCP connections). 135data for forwarded X11, TCP and
136.Ux Ns -domain
137connections).
135The compression algorithm is the same used by 138The compression algorithm is the same used by
136.Xr gzip 1 , 139.Xr gzip 1 ,
137and the 140and the
@@ -154,23 +157,6 @@ The supported values are
154.Dq blowfish , 157.Dq blowfish ,
155and 158and
156.Dq des . 159.Dq des .
157.Ar 3des
158(triple-des) is an encrypt-decrypt-encrypt triple with three different keys.
159It is believed to be secure.
160.Ar blowfish
161is a fast block cipher; it appears very secure and is much faster than
162.Ar 3des .
163.Ar des
164is only supported in the
165.Nm
166client for interoperability with legacy protocol 1 implementations
167that do not support the
168.Ar 3des
169cipher.
170Its use is strongly discouraged due to cryptographic weaknesses.
171The default is
172.Dq 3des .
173.Pp
174For protocol version 2, 160For protocol version 2,
175.Ar cipher_spec 161.Ar cipher_spec
176is a comma-separated list of ciphers 162is a comma-separated list of ciphers
@@ -267,6 +253,8 @@ will wait for all remote port forwards to be successfully established
267before placing itself in the background. 253before placing itself in the background.
268.It Fl g 254.It Fl g
269Allows remote hosts to connect to local forwarded ports. 255Allows remote hosts to connect to local forwarded ports.
256If used on a multiplexed connection, then this option must be specified
257on the master process.
270.It Fl I Ar pkcs11 258.It Fl I Ar pkcs11
271Specify the PKCS#11 shared library 259Specify the PKCS#11 shared library
272.Nm 260.Nm
@@ -481,6 +469,8 @@ For full details of the options listed below, and their possible values, see
481.It SendEnv 469.It SendEnv
482.It ServerAliveInterval 470.It ServerAliveInterval
483.It ServerAliveCountMax 471.It ServerAliveCountMax
472.It StreamLocalBindMask
473.It StreamLocalBindUnlink
484.It StrictHostKeyChecking 474.It StrictHostKeyChecking
485.It TCPKeepAlive 475.It TCPKeepAlive
486.It Tunnel 476.It Tunnel
@@ -1472,7 +1462,6 @@ if an error occurred.
1472.Xr ssh-keygen 1 , 1462.Xr ssh-keygen 1 ,
1473.Xr ssh-keyscan 1 , 1463.Xr ssh-keyscan 1 ,
1474.Xr tun 4 , 1464.Xr tun 4 ,
1475.Xr hosts.equiv 5 ,
1476.Xr ssh_config 5 , 1465.Xr ssh_config 5 ,
1477.Xr ssh-keysign 8 , 1466.Xr ssh-keysign 8 ,
1478.Xr sshd 8 1467.Xr sshd 8
diff --git a/ssh.c b/ssh.c
index 3e63708da..5bce695d9 100644
--- a/ssh.c
+++ b/ssh.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: ssh.c,v 1.401 2014/02/26 20:18:37 djm Exp $ */ 1/* $OpenBSD: ssh.c,v 1.407 2014/07/17 07:22:19 djm Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -71,8 +71,10 @@
71#include <netinet/in.h> 71#include <netinet/in.h>
72#include <arpa/inet.h> 72#include <arpa/inet.h>
73 73
74#ifdef WITH_OPENSSL
74#include <openssl/evp.h> 75#include <openssl/evp.h>
75#include <openssl/err.h> 76#include <openssl/err.h>
77#endif
76#include "openbsd-compat/openssl-compat.h" 78#include "openbsd-compat/openssl-compat.h"
77#include "openbsd-compat/sys-queue.h" 79#include "openbsd-compat/sys-queue.h"
78 80
@@ -83,6 +85,7 @@
83#include "canohost.h" 85#include "canohost.h"
84#include "compat.h" 86#include "compat.h"
85#include "cipher.h" 87#include "cipher.h"
88#include "digest.h"
86#include "packet.h" 89#include "packet.h"
87#include "buffer.h" 90#include "buffer.h"
88#include "channels.h" 91#include "channels.h"
@@ -93,9 +96,9 @@
93#include "dispatch.h" 96#include "dispatch.h"
94#include "clientloop.h" 97#include "clientloop.h"
95#include "log.h" 98#include "log.h"
99#include "misc.h"
96#include "readconf.h" 100#include "readconf.h"
97#include "sshconnect.h" 101#include "sshconnect.h"
98#include "misc.h"
99#include "kex.h" 102#include "kex.h"
100#include "mac.h" 103#include "mac.h"
101#include "sshpty.h" 104#include "sshpty.h"
@@ -420,8 +423,11 @@ main(int ac, char **av)
420 int timeout_ms; 423 int timeout_ms;
421 extern int optind, optreset; 424 extern int optind, optreset;
422 extern char *optarg; 425 extern char *optarg;
423 Forward fwd; 426 struct Forward fwd;
424 struct addrinfo *addrs = NULL; 427 struct addrinfo *addrs = NULL;
428 struct ssh_digest_ctx *md;
429 u_char conn_hash[SSH_DIGEST_MAX_LENGTH];
430 char *conn_hash_hex;
425 431
426 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */ 432 /* Ensure that fds 0, 1 and 2 are open or directed to /dev/null */
427 sanitise_stdfd(); 433 sanitise_stdfd();
@@ -539,7 +545,7 @@ main(int ac, char **av)
539 options.forward_x11_trusted = 1; 545 options.forward_x11_trusted = 1;
540 break; 546 break;
541 case 'g': 547 case 'g':
542 options.gateway_ports = 1; 548 options.fwd_opts.gateway_ports = 1;
543 break; 549 break;
544 case 'O': 550 case 'O':
545 if (stdio_forward_host != NULL) 551 if (stdio_forward_host != NULL)
@@ -631,7 +637,13 @@ main(int ac, char **av)
631 break; 637 break;
632 case 'V': 638 case 'V':
633 fprintf(stderr, "%s, %s\n", 639 fprintf(stderr, "%s, %s\n",
634 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); 640 SSH_RELEASE,
641#ifdef WITH_OPENSSL
642 SSLeay_version(SSLEAY_VERSION)
643#else
644 "without OpenSSL"
645#endif
646 );
635 if (opt == 'V') 647 if (opt == 'V')
636 exit(0); 648 exit(0);
637 break; 649 break;
@@ -828,8 +840,10 @@ main(int ac, char **av)
828 840
829 host_arg = xstrdup(host); 841 host_arg = xstrdup(host);
830 842
843#ifdef WITH_OPENSSL
831 OpenSSL_add_all_algorithms(); 844 OpenSSL_add_all_algorithms();
832 ERR_load_crypto_strings(); 845 ERR_load_crypto_strings();
846#endif
833 847
834 /* Initialize the command to execute on remote host. */ 848 /* Initialize the command to execute on remote host. */
835 buffer_init(&command); 849 buffer_init(&command);
@@ -876,7 +890,13 @@ main(int ac, char **av)
876 SYSLOG_FACILITY_USER, !use_syslog); 890 SYSLOG_FACILITY_USER, !use_syslog);
877 891
878 if (debug_flag) 892 if (debug_flag)
879 logit("%s, %s", SSH_VERSION, SSLeay_version(SSLEAY_VERSION)); 893 logit("%s, %s", SSH_RELEASE,
894#ifdef WITH_OPENSSL
895 SSLeay_version(SSLEAY_VERSION)
896#else
897 "without OpenSSL"
898#endif
899 );
880 900
881 /* Parse the configuration files */ 901 /* Parse the configuration files */
882 process_config_files(pw); 902 process_config_files(pw);
@@ -914,10 +934,14 @@ main(int ac, char **av)
914 if (addrs == NULL && options.num_permitted_cnames != 0 && 934 if (addrs == NULL && options.num_permitted_cnames != 0 &&
915 (option_clear_or_none(options.proxy_command) || 935 (option_clear_or_none(options.proxy_command) ||
916 options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) { 936 options.canonicalize_hostname == SSH_CANONICALISE_ALWAYS)) {
917 if ((addrs = resolve_host(host, options.port, 1, 937 if ((addrs = resolve_host(host, options.port,
918 cname, sizeof(cname))) == NULL) 938 option_clear_or_none(options.proxy_command),
919 cleanup_exit(255); /* resolve_host logs the error */ 939 cname, sizeof(cname))) == NULL) {
920 check_follow_cname(&host, cname); 940 /* Don't fatal proxied host names not in the DNS */
941 if (option_clear_or_none(options.proxy_command))
942 cleanup_exit(255); /* logged in resolve_host */
943 } else
944 check_follow_cname(&host, cname);
921 } 945 }
922 946
923 /* 947 /*
@@ -982,12 +1006,29 @@ main(int ac, char **av)
982 shorthost[strcspn(thishost, ".")] = '\0'; 1006 shorthost[strcspn(thishost, ".")] = '\0';
983 snprintf(portstr, sizeof(portstr), "%d", options.port); 1007 snprintf(portstr, sizeof(portstr), "%d", options.port);
984 1008
1009 if ((md = ssh_digest_start(SSH_DIGEST_SHA1)) == NULL ||
1010 ssh_digest_update(md, thishost, strlen(thishost)) < 0 ||
1011 ssh_digest_update(md, host, strlen(host)) < 0 ||
1012 ssh_digest_update(md, portstr, strlen(portstr)) < 0 ||
1013 ssh_digest_update(md, options.user, strlen(options.user)) < 0 ||
1014 ssh_digest_final(md, conn_hash, sizeof(conn_hash)) < 0)
1015 fatal("%s: mux digest failed", __func__);
1016 ssh_digest_free(md);
1017 conn_hash_hex = tohex(conn_hash, ssh_digest_bytes(SSH_DIGEST_SHA1));
1018
985 if (options.local_command != NULL) { 1019 if (options.local_command != NULL) {
986 debug3("expanding LocalCommand: %s", options.local_command); 1020 debug3("expanding LocalCommand: %s", options.local_command);
987 cp = options.local_command; 1021 cp = options.local_command;
988 options.local_command = percent_expand(cp, "d", pw->pw_dir, 1022 options.local_command = percent_expand(cp,
989 "h", host, "l", thishost, "n", host_arg, "r", options.user, 1023 "C", conn_hash_hex,
990 "p", portstr, "u", pw->pw_name, "L", shorthost, 1024 "L", shorthost,
1025 "d", pw->pw_dir,
1026 "h", host,
1027 "l", thishost,
1028 "n", host_arg,
1029 "p", portstr,
1030 "r", options.user,
1031 "u", pw->pw_name,
991 (char *)NULL); 1032 (char *)NULL);
992 debug3("expanded LocalCommand: %s", options.local_command); 1033 debug3("expanded LocalCommand: %s", options.local_command);
993 free(cp); 1034 free(cp);
@@ -997,12 +1038,20 @@ main(int ac, char **av)
997 cp = tilde_expand_filename(options.control_path, 1038 cp = tilde_expand_filename(options.control_path,
998 original_real_uid); 1039 original_real_uid);
999 free(options.control_path); 1040 free(options.control_path);
1000 options.control_path = percent_expand(cp, "h", host, 1041 options.control_path = percent_expand(cp,
1001 "l", thishost, "n", host_arg, "r", options.user, 1042 "C", conn_hash_hex,
1002 "p", portstr, "u", pw->pw_name, "L", shorthost, 1043 "L", shorthost,
1044 "h", host,
1045 "l", thishost,
1046 "n", host_arg,
1047 "p", portstr,
1048 "r", options.user,
1049 "u", pw->pw_name,
1003 (char *)NULL); 1050 (char *)NULL);
1004 free(cp); 1051 free(cp);
1005 } 1052 }
1053 free(conn_hash_hex);
1054
1006 if (muxclient_command != 0 && options.control_path == NULL) 1055 if (muxclient_command != 0 && options.control_path == NULL)
1007 fatal("No ControlPath specified for \"-O\" command"); 1056 fatal("No ControlPath specified for \"-O\" command");
1008 if (options.control_path != NULL) 1057 if (options.control_path != NULL)
@@ -1256,13 +1305,17 @@ fork_postauth(void)
1256static void 1305static void
1257ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt) 1306ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
1258{ 1307{
1259 Forward *rfwd = (Forward *)ctxt; 1308 struct Forward *rfwd = (struct Forward *)ctxt;
1260 1309
1261 /* XXX verbose() on failure? */ 1310 /* XXX verbose() on failure? */
1262 debug("remote forward %s for: listen %d, connect %s:%d", 1311 debug("remote forward %s for: listen %s%s%d, connect %s:%d",
1263 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure", 1312 type == SSH2_MSG_REQUEST_SUCCESS ? "success" : "failure",
1264 rfwd->listen_port, rfwd->connect_host, rfwd->connect_port); 1313 rfwd->listen_path ? rfwd->listen_path :
1265 if (rfwd->listen_port == 0) { 1314 rfwd->listen_host ? rfwd->listen_host : "",
1315 (rfwd->listen_path || rfwd->listen_host) ? ":" : "",
1316 rfwd->listen_port, rfwd->connect_path ? rfwd->connect_path :
1317 rfwd->connect_host, rfwd->connect_port);
1318 if (rfwd->listen_path == NULL && rfwd->listen_port == 0) {
1266 if (type == SSH2_MSG_REQUEST_SUCCESS) { 1319 if (type == SSH2_MSG_REQUEST_SUCCESS) {
1267 rfwd->allocated_port = packet_get_int(); 1320 rfwd->allocated_port = packet_get_int();
1268 logit("Allocated port %u for remote forward to %s:%d", 1321 logit("Allocated port %u for remote forward to %s:%d",
@@ -1276,12 +1329,21 @@ ssh_confirm_remote_forward(int type, u_int32_t seq, void *ctxt)
1276 } 1329 }
1277 1330
1278 if (type == SSH2_MSG_REQUEST_FAILURE) { 1331 if (type == SSH2_MSG_REQUEST_FAILURE) {
1279 if (options.exit_on_forward_failure) 1332 if (options.exit_on_forward_failure) {
1280 fatal("Error: remote port forwarding failed for " 1333 if (rfwd->listen_path != NULL)
1281 "listen port %d", rfwd->listen_port); 1334 fatal("Error: remote port forwarding failed "
1282 else 1335 "for listen path %s", rfwd->listen_path);
1283 logit("Warning: remote port forwarding failed for " 1336 else
1284 "listen port %d", rfwd->listen_port); 1337 fatal("Error: remote port forwarding failed "
1338 "for listen port %d", rfwd->listen_port);
1339 } else {
1340 if (rfwd->listen_path != NULL)
1341 logit("Warning: remote port forwarding failed "
1342 "for listen path %s", rfwd->listen_path);
1343 else
1344 logit("Warning: remote port forwarding failed "
1345 "for listen port %d", rfwd->listen_port);
1346 }
1285 } 1347 }
1286 if (++remote_forward_confirms_received == options.num_remote_forwards) { 1348 if (++remote_forward_confirms_received == options.num_remote_forwards) {
1287 debug("All remote forwarding requests processed"); 1349 debug("All remote forwarding requests processed");
@@ -1298,6 +1360,13 @@ client_cleanup_stdio_fwd(int id, void *arg)
1298} 1360}
1299 1361
1300static void 1362static void
1363ssh_stdio_confirm(int id, int success, void *arg)
1364{
1365 if (!success)
1366 fatal("stdio forwarding failed");
1367}
1368
1369static void
1301ssh_init_stdio_forwarding(void) 1370ssh_init_stdio_forwarding(void)
1302{ 1371{
1303 Channel *c; 1372 Channel *c;
@@ -1317,6 +1386,7 @@ ssh_init_stdio_forwarding(void)
1317 stdio_forward_port, in, out)) == NULL) 1386 stdio_forward_port, in, out)) == NULL)
1318 fatal("%s: channel_connect_stdio_fwd failed", __func__); 1387 fatal("%s: channel_connect_stdio_fwd failed", __func__);
1319 channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0); 1388 channel_register_cleanup(c->self, client_cleanup_stdio_fwd, 0);
1389 channel_register_open_confirm(c->self, ssh_stdio_confirm, NULL);
1320} 1390}
1321 1391
1322static void 1392static void
@@ -1329,18 +1399,18 @@ ssh_init_forwarding(void)
1329 for (i = 0; i < options.num_local_forwards; i++) { 1399 for (i = 0; i < options.num_local_forwards; i++) {
1330 debug("Local connections to %.200s:%d forwarded to remote " 1400 debug("Local connections to %.200s:%d forwarded to remote "
1331 "address %.200s:%d", 1401 "address %.200s:%d",
1402 (options.local_forwards[i].listen_path != NULL) ?
1403 options.local_forwards[i].listen_path :
1332 (options.local_forwards[i].listen_host == NULL) ? 1404 (options.local_forwards[i].listen_host == NULL) ?
1333 (options.gateway_ports ? "*" : "LOCALHOST") : 1405 (options.fwd_opts.gateway_ports ? "*" : "LOCALHOST") :
1334 options.local_forwards[i].listen_host, 1406 options.local_forwards[i].listen_host,
1335 options.local_forwards[i].listen_port, 1407 options.local_forwards[i].listen_port,
1408 (options.local_forwards[i].connect_path != NULL) ?
1409 options.local_forwards[i].connect_path :
1336 options.local_forwards[i].connect_host, 1410 options.local_forwards[i].connect_host,
1337 options.local_forwards[i].connect_port); 1411 options.local_forwards[i].connect_port);
1338 success += channel_setup_local_fwd_listener( 1412 success += channel_setup_local_fwd_listener(
1339 options.local_forwards[i].listen_host, 1413 &options.local_forwards[i], &options.fwd_opts);
1340 options.local_forwards[i].listen_port,
1341 options.local_forwards[i].connect_host,
1342 options.local_forwards[i].connect_port,
1343 options.gateway_ports);
1344 } 1414 }
1345 if (i > 0 && success != i && options.exit_on_forward_failure) 1415 if (i > 0 && success != i && options.exit_on_forward_failure)
1346 fatal("Could not request local forwarding."); 1416 fatal("Could not request local forwarding.");
@@ -1351,17 +1421,18 @@ ssh_init_forwarding(void)
1351 for (i = 0; i < options.num_remote_forwards; i++) { 1421 for (i = 0; i < options.num_remote_forwards; i++) {
1352 debug("Remote connections from %.200s:%d forwarded to " 1422 debug("Remote connections from %.200s:%d forwarded to "
1353 "local address %.200s:%d", 1423 "local address %.200s:%d",
1424 (options.remote_forwards[i].listen_path != NULL) ?
1425 options.remote_forwards[i].listen_path :
1354 (options.remote_forwards[i].listen_host == NULL) ? 1426 (options.remote_forwards[i].listen_host == NULL) ?
1355 "LOCALHOST" : options.remote_forwards[i].listen_host, 1427 "LOCALHOST" : options.remote_forwards[i].listen_host,
1356 options.remote_forwards[i].listen_port, 1428 options.remote_forwards[i].listen_port,
1429 (options.remote_forwards[i].connect_path != NULL) ?
1430 options.remote_forwards[i].connect_path :
1357 options.remote_forwards[i].connect_host, 1431 options.remote_forwards[i].connect_host,
1358 options.remote_forwards[i].connect_port); 1432 options.remote_forwards[i].connect_port);
1359 options.remote_forwards[i].handle = 1433 options.remote_forwards[i].handle =
1360 channel_request_remote_forwarding( 1434 channel_request_remote_forwarding(
1361 options.remote_forwards[i].listen_host, 1435 &options.remote_forwards[i]);
1362 options.remote_forwards[i].listen_port,
1363 options.remote_forwards[i].connect_host,
1364 options.remote_forwards[i].connect_port);
1365 if (options.remote_forwards[i].handle < 0) { 1436 if (options.remote_forwards[i].handle < 0) {
1366 if (options.exit_on_forward_failure) 1437 if (options.exit_on_forward_failure)
1367 fatal("Could not request remote forwarding."); 1438 fatal("Could not request remote forwarding.");
diff --git a/ssh_config.0 b/ssh_config.0
index 6fbd10d61..c40ce5f08 100644
--- a/ssh_config.0
+++ b/ssh_config.0
@@ -1,4 +1,4 @@
1SSH_CONFIG(5) OpenBSD Programmer's Manual SSH_CONFIG(5) 1SSH_CONFIG(5) File Formats Manual SSH_CONFIG(5)
2 2
3NAME 3NAME
4 ssh_config - OpenSSH SSH client configuration files 4 ssh_config - OpenSSH SSH client configuration files
@@ -176,19 +176,30 @@ DESCRIPTION
176 preference. Multiple ciphers must be comma-separated. The 176 preference. Multiple ciphers must be comma-separated. The
177 supported ciphers are: 177 supported ciphers are:
178 178
179 ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'', 179 3des-cbc
180 ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', 180 aes128-cbc
181 ``aes128-gcm@openssh.com'', ``aes256-gcm@openssh.com'', 181 aes192-cbc
182 ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', 182 aes256-cbc
183 ``cast128-cbc'', and ``chacha20-poly1305@openssh.com''. 183 aes128-ctr
184 aes192-ctr
185 aes256-ctr
186 aes128-gcm@openssh.com
187 aes256-gcm@openssh.com
188 arcfour
189 arcfour128
190 arcfour256
191 blowfish-cbc
192 cast128-cbc
193 chacha20-poly1305@openssh.com
184 194
185 The default is: 195 The default is:
186 196
187 aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, 197 aes128-ctr,aes192-ctr,aes256-ctr,
188 aes128-gcm@openssh.com,aes256-gcm@openssh.com, 198 aes128-gcm@openssh.com,aes256-gcm@openssh.com,
189 chacha20-poly1305@openssh.com, 199 chacha20-poly1305@openssh.com,
190 aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, 200 arcfour256,arcfour128,
191 aes256-cbc,arcfour 201 aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,
202 aes192-cbc,aes256-cbc,arcfour
192 203
193 The list of available ciphers may also be obtained using the -Q 204 The list of available ciphers may also be obtained using the -Q
194 option of ssh(1). 205 option of ssh(1).
@@ -261,10 +272,12 @@ DESCRIPTION
261 any domain name), `%h' will be substituted by the target host 272 any domain name), `%h' will be substituted by the target host
262 name, `%n' will be substituted by the original target host name 273 name, `%n' will be substituted by the original target host name
263 specified on the command line, `%p' the destination port, `%r' by 274 specified on the command line, `%p' the destination port, `%r' by
264 the remote login username, and `%u' by the username of the user 275 the remote login username, `%u' by the username of the user
265 running ssh(1). It is recommended that any ControlPath used for 276 running ssh(1), and `%C' by a hash of the concatenation:
266 opportunistic connection sharing include at least %h, %p, and %r. 277 %l%h%p%r. It is recommended that any ControlPath used for
267 This ensures that shared connections are uniquely identified. 278 opportunistic connection sharing include at least %h, %p, and %r
279 (or alternatively %C). This ensures that shared connections are
280 uniquely identified.
268 281
269 ControlPersist 282 ControlPersist
270 When used in conjunction with ControlMaster, specifies that the 283 When used in conjunction with ControlMaster, specifies that the
@@ -437,10 +450,13 @@ DESCRIPTION
437 specify nicknames or abbreviations for hosts. If the hostname 450 specify nicknames or abbreviations for hosts. If the hostname
438 contains the character sequence `%h', then this will be replaced 451 contains the character sequence `%h', then this will be replaced
439 with the host name specified on the command line (this is useful 452 with the host name specified on the command line (this is useful
440 for manipulating unqualified names). The default is the name 453 for manipulating unqualified names). The character sequence `%%'
441 given on the command line. Numeric IP addresses are also 454 will be replaced by a single `%' character, which may be used
442 permitted (both on the command line and in HostName 455 when specifying IPv6 link-local addresses.
443 specifications). 456
457 The default is the name given on the command line. Numeric IP
458 addresses are also permitted (both on the command line and in
459 HostName specifications).
444 460
445 IdentitiesOnly 461 IdentitiesOnly
446 Specifies that ssh(1) should only use the authentication identity 462 Specifies that ssh(1) should only use the authentication identity
@@ -517,8 +533,8 @@ DESCRIPTION
517 curve25519-sha256@libssh.org, 533 curve25519-sha256@libssh.org,
518 ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, 534 ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
519 diffie-hellman-group-exchange-sha256, 535 diffie-hellman-group-exchange-sha256,
520 diffie-hellman-group-exchange-sha1,
521 diffie-hellman-group14-sha1, 536 diffie-hellman-group14-sha1,
537 diffie-hellman-group-exchange-sha1,
522 diffie-hellman-group1-sha1 538 diffie-hellman-group1-sha1
523 539
524 LocalCommand 540 LocalCommand
@@ -529,7 +545,8 @@ DESCRIPTION
529 performed: `%d' (local user's home directory), `%h' (remote host 545 performed: `%d' (local user's home directory), `%h' (remote host
530 name), `%l' (local host name), `%n' (host name as provided on the 546 name), `%l' (local host name), `%n' (host name as provided on the
531 command line), `%p' (remote port), `%r' (remote user name) or 547 command line), `%p' (remote port), `%r' (remote user name) or
532 `%u' (local user name). 548 `%u' (local user name) or `%C' by a hash of the concatenation:
549 %l%h%p%r.
533 550
534 The command is run synchronously and does not have access to the 551 The command is run synchronously and does not have access to the
535 session of the ssh(1) that spawned it. It should not be used for 552 session of the ssh(1) that spawned it. It should not be used for
@@ -568,13 +585,14 @@ DESCRIPTION
568 calculate the MAC after encryption (encrypt-then-mac). These are 585 calculate the MAC after encryption (encrypt-then-mac). These are
569 considered safer and their use recommended. The default is: 586 considered safer and their use recommended. The default is:
570 587
571 hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
572 umac-64-etm@openssh.com,umac-128-etm@openssh.com, 588 umac-64-etm@openssh.com,umac-128-etm@openssh.com,
573 hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, 589 hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
574 hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, 590 umac-64@openssh.com,umac-128@openssh.com,
575 hmac-md5-96-etm@openssh.com, 591 hmac-sha2-256,hmac-sha2-512,
576 hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, 592 hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
577 hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, 593 hmac-ripemd160-etm@openssh.com,
594 hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,
595 hmac-md5,hmac-sha1,hmac-ripemd160,
578 hmac-sha1-96,hmac-md5-96 596 hmac-sha1-96,hmac-md5-96
579 597
580 NoHostAuthenticationForLocalhost 598 NoHostAuthenticationForLocalhost
@@ -628,17 +646,19 @@ DESCRIPTION
628 ProxyCommand 646 ProxyCommand
629 Specifies the command to use to connect to the server. The 647 Specifies the command to use to connect to the server. The
630 command string extends to the end of the line, and is executed 648 command string extends to the end of the line, and is executed
631 with the user's shell. In the command string, any occurrence of 649 using the user's shell `exec' directive to avoid a lingering
632 `%h' will be substituted by the host name to connect, `%p' by the 650 shell process.
633 port, and `%r' by the remote user name. The command can be 651
634 basically anything, and should read from its standard input and 652 In the command string, any occurrence of `%h' will be substituted
635 write to its standard output. It should eventually connect an 653 by the host name to connect, `%p' by the port, and `%r' by the
636 sshd(8) server running on some machine, or execute sshd -i 654 remote user name. The command can be basically anything, and
637 somewhere. Host key management will be done using the HostName 655 should read from its standard input and write to its standard
638 of the host being connected (defaulting to the name typed by the 656 output. It should eventually connect an sshd(8) server running
639 user). Setting the command to ``none'' disables this option 657 on some machine, or execute sshd -i somewhere. Host key
640 entirely. Note that CheckHostIP is not available for connects 658 management will be done using the HostName of the host being
641 with a proxy command. 659 connected (defaulting to the name typed by the user). Setting
660 the command to ``none'' disables this option entirely. Note that
661 CheckHostIP is not available for connects with a proxy command.
642 662
643 This directive is useful in conjunction with nc(1) and its proxy 663 This directive is useful in conjunction with nc(1) and its proxy
644 support. For example, the following directive would connect via 664 support. For example, the following directive would connect via
@@ -751,6 +771,27 @@ DESCRIPTION
751 default is 0, indicating that these messages will not be sent to 771 default is 0, indicating that these messages will not be sent to
752 the server. This option applies to protocol version 2 only. 772 the server. This option applies to protocol version 2 only.
753 773
774 StreamLocalBindMask
775 Sets the octal file creation mode mask (umask) used when creating
776 a Unix-domain socket file for local or remote port forwarding.
777 This option is only used for port forwarding to a Unix-domain
778 socket file.
779
780 The default value is 0177, which creates a Unix-domain socket
781 file that is readable and writable only by the owner. Note that
782 not all operating systems honor the file mode on Unix-domain
783 socket files.
784
785 StreamLocalBindUnlink
786 Specifies whether to remove an existing Unix-domain socket file
787 for local or remote port forwarding before creating a new one.
788 If the socket file already exists and StreamLocalBindUnlink is
789 not enabled, ssh will be unable to forward the port to the Unix-
790 domain socket file. This option is only used for port forwarding
791 to a Unix-domain socket file.
792
793 The argument must be ``yes'' or ``no''. The default is ``no''.
794
754 StrictHostKeyChecking 795 StrictHostKeyChecking
755 If this flag is set to ``yes'', ssh(1) will never automatically 796 If this flag is set to ``yes'', ssh(1) will never automatically
756 add host keys to the ~/.ssh/known_hosts file, and refuses to 797 add host keys to the ~/.ssh/known_hosts file, and refuses to
@@ -886,4 +927,4 @@ AUTHORS
886 created OpenSSH. Markus Friedl contributed the support for SSH protocol 927 created OpenSSH. Markus Friedl contributed the support for SSH protocol
887 versions 1.5 and 2.0. 928 versions 1.5 and 2.0.
888 929
889OpenBSD 5.5 February 23, 2014 OpenBSD 5.5 930OpenBSD 5.6 July 15, 2014 OpenBSD 5.6
diff --git a/ssh_config.5 b/ssh_config.5
index 22e637265..da3c1771a 100644
--- a/ssh_config.5
+++ b/ssh_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: ssh_config.5,v 1.185 2014/02/23 20:11:36 djm Exp $ 36.\" $OpenBSD: ssh_config.5,v 1.191 2014/07/15 15:54:14 millert Exp $
37.Dd $Mdocdate: February 23 2014 $ 37.Dd $Mdocdate: July 15 2014 $
38.Dt SSH_CONFIG 5 38.Dt SSH_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -362,30 +362,47 @@ in order of preference.
362Multiple ciphers must be comma-separated. 362Multiple ciphers must be comma-separated.
363The supported ciphers are: 363The supported ciphers are:
364.Pp 364.Pp
365.Dq 3des-cbc , 365.Bl -item -compact -offset indent
366.Dq aes128-cbc , 366.It
367.Dq aes192-cbc , 3673des-cbc
368.Dq aes256-cbc , 368.It
369.Dq aes128-ctr , 369aes128-cbc
370.Dq aes192-ctr , 370.It
371.Dq aes256-ctr , 371aes192-cbc
372.Dq aes128-gcm@openssh.com , 372.It
373.Dq aes256-gcm@openssh.com , 373aes256-cbc
374.Dq arcfour128 , 374.It
375.Dq arcfour256 , 375aes128-ctr
376.Dq arcfour , 376.It
377.Dq blowfish-cbc , 377aes192-ctr
378.Dq cast128-cbc , 378.It
379and 379aes256-ctr
380.Dq chacha20-poly1305@openssh.com . 380.It
381aes128-gcm@openssh.com
382.It
383aes256-gcm@openssh.com
384.It
385arcfour
386.It
387arcfour128
388.It
389arcfour256
390.It
391blowfish-cbc
392.It
393cast128-cbc
394.It
395chacha20-poly1305@openssh.com
396.El
381.Pp 397.Pp
382The default is: 398The default is:
383.Bd -literal -offset 3n 399.Bd -literal -offset indent
384aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, 400aes128-ctr,aes192-ctr,aes256-ctr,
385aes128-gcm@openssh.com,aes256-gcm@openssh.com, 401aes128-gcm@openssh.com,aes256-gcm@openssh.com,
386chacha20-poly1305@openssh.com, 402chacha20-poly1305@openssh.com,
387aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc, 403arcfour256,arcfour128,
388aes256-cbc,arcfour 404aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,
405aes192-cbc,aes256-cbc,arcfour
389.Ed 406.Ed
390.Pp 407.Pp
391The list of available ciphers may also be obtained using the 408The list of available ciphers may also be obtained using the
@@ -502,14 +519,16 @@ specified on the command line,
502.Ql %p 519.Ql %p
503the destination port, 520the destination port,
504.Ql %r 521.Ql %r
505by the remote login username, and 522by the remote login username,
506.Ql %u 523.Ql %u
507by the username of the user running 524by the username of the user running
508.Xr ssh 1 . 525.Xr ssh 1 , and
526.Ql \&%C
527by a hash of the concatenation: %l%h%p%r.
509It is recommended that any 528It is recommended that any
510.Cm ControlPath 529.Cm ControlPath
511used for opportunistic connection sharing include 530used for opportunistic connection sharing include
512at least %h, %p, and %r. 531at least %h, %p, and %r (or alternatively %C).
513This ensures that shared connections are uniquely identified. 532This ensures that shared connections are uniquely identified.
514.It Cm ControlPersist 533.It Cm ControlPersist
515When used in conjunction with 534When used in conjunction with
@@ -802,6 +821,12 @@ If the hostname contains the character sequence
802.Ql %h , 821.Ql %h ,
803then this will be replaced with the host name specified on the command line 822then this will be replaced with the host name specified on the command line
804(this is useful for manipulating unqualified names). 823(this is useful for manipulating unqualified names).
824The character sequence
825.Ql %%
826will be replaced by a single
827.Ql %
828character, which may be used when specifying IPv6 link-local addresses.
829.Pp
805The default is the name given on the command line. 830The default is the name given on the command line.
806Numeric IP addresses are also permitted (both on the command line and in 831Numeric IP addresses are also permitted (both on the command line and in
807.Cm HostName 832.Cm HostName
@@ -949,8 +974,8 @@ The default is:
949curve25519-sha256@libssh.org, 974curve25519-sha256@libssh.org,
950ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, 975ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
951diffie-hellman-group-exchange-sha256, 976diffie-hellman-group-exchange-sha256,
952diffie-hellman-group-exchange-sha1,
953diffie-hellman-group14-sha1, 977diffie-hellman-group14-sha1,
978diffie-hellman-group-exchange-sha1,
954diffie-hellman-group1-sha1 979diffie-hellman-group1-sha1
955.Ed 980.Ed
956.It Cm LocalCommand 981.It Cm LocalCommand
@@ -972,7 +997,9 @@ The following escape character substitutions will be performed:
972.Ql %r 997.Ql %r
973(remote user name) or 998(remote user name) or
974.Ql %u 999.Ql %u
975(local user name). 1000(local user name) or
1001.Ql \&%C
1002by a hash of the concatenation: %l%h%p%r.
976.Pp 1003.Pp
977The command is run synchronously and does not have access to the 1004The command is run synchronously and does not have access to the
978session of the 1005session of the
@@ -1030,13 +1057,14 @@ calculate the MAC after encryption (encrypt-then-mac).
1030These are considered safer and their use recommended. 1057These are considered safer and their use recommended.
1031The default is: 1058The default is:
1032.Bd -literal -offset indent 1059.Bd -literal -offset indent
1033hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
1034umac-64-etm@openssh.com,umac-128-etm@openssh.com, 1060umac-64-etm@openssh.com,umac-128-etm@openssh.com,
1035hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, 1061hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
1036hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, 1062umac-64@openssh.com,umac-128@openssh.com,
1037hmac-md5-96-etm@openssh.com, 1063hmac-sha2-256,hmac-sha2-512,
1038hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com, 1064hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
1039hmac-sha2-256,hmac-sha2-512,hmac-ripemd160, 1065hmac-ripemd160-etm@openssh.com,
1066hmac-sha1-96-etm@openssh.com,hmac-md5-96-etm@openssh.com,
1067hmac-md5,hmac-sha1,hmac-ripemd160,
1040hmac-sha1-96,hmac-md5-96 1068hmac-sha1-96,hmac-md5-96
1041.Ed 1069.Ed
1042.It Cm NoHostAuthenticationForLocalhost 1070.It Cm NoHostAuthenticationForLocalhost
@@ -1114,8 +1142,11 @@ The default is
1114.It Cm ProxyCommand 1142.It Cm ProxyCommand
1115Specifies the command to use to connect to the server. 1143Specifies the command to use to connect to the server.
1116The command 1144The command
1117string extends to the end of the line, and is executed with 1145string extends to the end of the line, and is executed
1118the user's shell. 1146using the user's shell
1147.Ql exec
1148directive to avoid a lingering shell process.
1149.Pp
1119In the command string, any occurrence of 1150In the command string, any occurrence of
1120.Ql %h 1151.Ql %h
1121will be substituted by the host name to 1152will be substituted by the host name to
@@ -1338,6 +1369,33 @@ This option applies to protocol version 2 only.
1338and 1369and
1339.Cm SetupTimeOut 1370.Cm SetupTimeOut
1340are Debian-specific compatibility aliases for this option. 1371are Debian-specific compatibility aliases for this option.
1372.It Cm StreamLocalBindMask
1373Sets the octal file creation mode mask
1374.Pq umask
1375used when creating a Unix-domain socket file for local or remote
1376port forwarding.
1377This option is only used for port forwarding to a Unix-domain socket file.
1378.Pp
1379The default value is 0177, which creates a Unix-domain socket file that is
1380readable and writable only by the owner.
1381Note that not all operating systems honor the file mode on Unix-domain
1382socket files.
1383.It Cm StreamLocalBindUnlink
1384Specifies whether to remove an existing Unix-domain socket file for local
1385or remote port forwarding before creating a new one.
1386If the socket file already exists and
1387.Cm StreamLocalBindUnlink
1388is not enabled,
1389.Nm ssh
1390will be unable to forward the port to the Unix-domain socket file.
1391This option is only used for port forwarding to a Unix-domain socket file.
1392.Pp
1393The argument must be
1394.Dq yes
1395or
1396.Dq no .
1397The default is
1398.Dq no .
1341.It Cm StrictHostKeyChecking 1399.It Cm StrictHostKeyChecking
1342If this flag is set to 1400If this flag is set to
1343.Dq yes , 1401.Dq yes ,
diff --git a/sshbuf-getput-basic.c b/sshbuf-getput-basic.c
new file mode 100644
index 000000000..b7d0758c2
--- /dev/null
+++ b/sshbuf-getput-basic.c
@@ -0,0 +1,421 @@
1/* $OpenBSD: sshbuf-getput-basic.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#define SSHBUF_INTERNAL
19#include "includes.h"
20
21#include <sys/types.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25
26#include "ssherr.h"
27#include "sshbuf.h"
28
29int
30sshbuf_get(struct sshbuf *buf, void *v, size_t len)
31{
32 const u_char *p = sshbuf_ptr(buf);
33 int r;
34
35 if ((r = sshbuf_consume(buf, len)) < 0)
36 return r;
37 if (v != NULL)
38 memcpy(v, p, len);
39 return 0;
40}
41
42int
43sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp)
44{
45 const u_char *p = sshbuf_ptr(buf);
46 int r;
47
48 if ((r = sshbuf_consume(buf, 8)) < 0)
49 return r;
50 if (valp != NULL)
51 *valp = PEEK_U64(p);
52 return 0;
53}
54
55int
56sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp)
57{
58 const u_char *p = sshbuf_ptr(buf);
59 int r;
60
61 if ((r = sshbuf_consume(buf, 4)) < 0)
62 return r;
63 if (valp != NULL)
64 *valp = PEEK_U32(p);
65 return 0;
66}
67
68int
69sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp)
70{
71 const u_char *p = sshbuf_ptr(buf);
72 int r;
73
74 if ((r = sshbuf_consume(buf, 2)) < 0)
75 return r;
76 if (valp != NULL)
77 *valp = PEEK_U16(p);
78 return 0;
79}
80
81int
82sshbuf_get_u8(struct sshbuf *buf, u_char *valp)
83{
84 const u_char *p = sshbuf_ptr(buf);
85 int r;
86
87 if ((r = sshbuf_consume(buf, 1)) < 0)
88 return r;
89 if (valp != NULL)
90 *valp = (u_int8_t)*p;
91 return 0;
92}
93
94int
95sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp)
96{
97 const u_char *val;
98 size_t len;
99 int r;
100
101 if (valp != NULL)
102 *valp = NULL;
103 if (lenp != NULL)
104 *lenp = 0;
105 if ((r = sshbuf_get_string_direct(buf, &val, &len)) < 0)
106 return r;
107 if (valp != NULL) {
108 if ((*valp = malloc(len + 1)) == NULL) {
109 SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
110 return SSH_ERR_ALLOC_FAIL;
111 }
112 memcpy(*valp, val, len);
113 (*valp)[len] = '\0';
114 }
115 if (lenp != NULL)
116 *lenp = len;
117 return 0;
118}
119
120int
121sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp, size_t *lenp)
122{
123 size_t len;
124 const u_char *p;
125 int r;
126
127 if (valp != NULL)
128 *valp = NULL;
129 if (lenp != NULL)
130 *lenp = 0;
131 if ((r = sshbuf_peek_string_direct(buf, &p, &len)) < 0)
132 return r;
133 if (valp != 0)
134 *valp = p;
135 if (lenp != NULL)
136 *lenp = len;
137 if (sshbuf_consume(buf, len + 4) != 0) {
138 /* Shouldn't happen */
139 SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
140 SSHBUF_ABORT();
141 return SSH_ERR_INTERNAL_ERROR;
142 }
143 return 0;
144}
145
146int
147sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
148 size_t *lenp)
149{
150 u_int32_t len;
151 const u_char *p = sshbuf_ptr(buf);
152
153 if (valp != NULL)
154 *valp = NULL;
155 if (lenp != NULL)
156 *lenp = 0;
157 if (sshbuf_len(buf) < 4) {
158 SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
159 return SSH_ERR_MESSAGE_INCOMPLETE;
160 }
161 len = PEEK_U32(p);
162 if (len > SSHBUF_SIZE_MAX - 4) {
163 SSHBUF_DBG(("SSH_ERR_STRING_TOO_LARGE"));
164 return SSH_ERR_STRING_TOO_LARGE;
165 }
166 if (sshbuf_len(buf) - 4 < len) {
167 SSHBUF_DBG(("SSH_ERR_MESSAGE_INCOMPLETE"));
168 return SSH_ERR_MESSAGE_INCOMPLETE;
169 }
170 if (valp != 0)
171 *valp = p + 4;
172 if (lenp != NULL)
173 *lenp = len;
174 return 0;
175}
176
177int
178sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp)
179{
180 size_t len;
181 const u_char *p, *z;
182 int r;
183
184 if (valp != NULL)
185 *valp = NULL;
186 if (lenp != NULL)
187 *lenp = 0;
188 if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0)
189 return r;
190 /* Allow a \0 only at the end of the string */
191 if (len > 0 &&
192 (z = memchr(p , '\0', len)) != NULL && z < p + len - 1) {
193 SSHBUF_DBG(("SSH_ERR_INVALID_FORMAT"));
194 return SSH_ERR_INVALID_FORMAT;
195 }
196 if ((r = sshbuf_skip_string(buf)) != 0)
197 return -1;
198 if (valp != NULL) {
199 if ((*valp = malloc(len + 1)) == NULL) {
200 SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
201 return SSH_ERR_ALLOC_FAIL;
202 }
203 memcpy(*valp, p, len);
204 (*valp)[len] = '\0';
205 }
206 if (lenp != NULL)
207 *lenp = (size_t)len;
208 return 0;
209}
210
211int
212sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v)
213{
214 u_int32_t len;
215 u_char *p;
216 int r;
217
218 /*
219 * Use sshbuf_peek_string_direct() to figure out if there is
220 * a complete string in 'buf' and copy the string directly
221 * into 'v'.
222 */
223 if ((r = sshbuf_peek_string_direct(buf, NULL, NULL)) != 0 ||
224 (r = sshbuf_get_u32(buf, &len)) != 0 ||
225 (r = sshbuf_reserve(v, len, &p)) != 0 ||
226 (r = sshbuf_get(buf, p, len)) != 0)
227 return r;
228 return 0;
229}
230
231int
232sshbuf_put(struct sshbuf *buf, const void *v, size_t len)
233{
234 u_char *p;
235 int r;
236
237 if ((r = sshbuf_reserve(buf, len, &p)) < 0)
238 return r;
239 memcpy(p, v, len);
240 return 0;
241}
242
243int
244sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v)
245{
246 return sshbuf_put(buf, sshbuf_ptr(v), sshbuf_len(v));
247}
248
249int
250sshbuf_putf(struct sshbuf *buf, const char *fmt, ...)
251{
252 va_list ap;
253 int r;
254
255 va_start(ap, fmt);
256 r = sshbuf_putfv(buf, fmt, ap);
257 va_end(ap);
258 return r;
259}
260
261int
262sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap)
263{
264 va_list ap2;
265 int r, len;
266 u_char *p;
267
268 va_copy(ap2, ap);
269 if ((len = vsnprintf(NULL, 0, fmt, ap2)) < 0) {
270 r = SSH_ERR_INVALID_ARGUMENT;
271 goto out;
272 }
273 if (len == 0) {
274 r = 0;
275 goto out; /* Nothing to do */
276 }
277 va_end(ap2);
278 va_copy(ap2, ap);
279 if ((r = sshbuf_reserve(buf, (size_t)len + 1, &p)) < 0)
280 goto out;
281 if ((r = vsnprintf((char *)p, len + 1, fmt, ap2)) != len) {
282 r = SSH_ERR_INTERNAL_ERROR;
283 goto out; /* Shouldn't happen */
284 }
285 /* Consume terminating \0 */
286 if ((r = sshbuf_consume_end(buf, 1)) != 0)
287 goto out;
288 r = 0;
289 out:
290 va_end(ap2);
291 return r;
292}
293
294int
295sshbuf_put_u64(struct sshbuf *buf, u_int64_t val)
296{
297 u_char *p;
298 int r;
299
300 if ((r = sshbuf_reserve(buf, 8, &p)) < 0)
301 return r;
302 POKE_U64(p, val);
303 return 0;
304}
305
306int
307sshbuf_put_u32(struct sshbuf *buf, u_int32_t val)
308{
309 u_char *p;
310 int r;
311
312 if ((r = sshbuf_reserve(buf, 4, &p)) < 0)
313 return r;
314 POKE_U32(p, val);
315 return 0;
316}
317
318int
319sshbuf_put_u16(struct sshbuf *buf, u_int16_t val)
320{
321 u_char *p;
322 int r;
323
324 if ((r = sshbuf_reserve(buf, 2, &p)) < 0)
325 return r;
326 POKE_U16(p, val);
327 return 0;
328}
329
330int
331sshbuf_put_u8(struct sshbuf *buf, u_char val)
332{
333 u_char *p;
334 int r;
335
336 if ((r = sshbuf_reserve(buf, 1, &p)) < 0)
337 return r;
338 p[0] = val;
339 return 0;
340}
341
342int
343sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len)
344{
345 u_char *d;
346 int r;
347
348 if (len > SSHBUF_SIZE_MAX - 4) {
349 SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE"));
350 return SSH_ERR_NO_BUFFER_SPACE;
351 }
352 if ((r = sshbuf_reserve(buf, len + 4, &d)) < 0)
353 return r;
354 POKE_U32(d, len);
355 memcpy(d + 4, v, len);
356 return 0;
357}
358
359int
360sshbuf_put_cstring(struct sshbuf *buf, const char *v)
361{
362 return sshbuf_put_string(buf, (u_char *)v, strlen(v));
363}
364
365int
366sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v)
367{
368 return sshbuf_put_string(buf, sshbuf_ptr(v), sshbuf_len(v));
369}
370
371int
372sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp)
373{
374 const u_char *p;
375 size_t len;
376 struct sshbuf *ret;
377 int r;
378
379 if (buf == NULL || bufp == NULL)
380 return SSH_ERR_INVALID_ARGUMENT;
381 *bufp = NULL;
382 if ((r = sshbuf_peek_string_direct(buf, &p, &len)) != 0)
383 return r;
384 if ((ret = sshbuf_from(p, len)) == NULL)
385 return SSH_ERR_ALLOC_FAIL;
386 if ((r = sshbuf_consume(buf, len + 4)) != 0 || /* Shouldn't happen */
387 (r = sshbuf_set_parent(ret, buf)) != 0) {
388 sshbuf_free(ret);
389 return r;
390 }
391 *bufp = ret;
392 return 0;
393}
394
395int
396sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len)
397{
398 u_char *d;
399 const u_char *s = (const u_char *)v;
400 int r, prepend;
401
402 if (len > SSHBUF_SIZE_MAX - 5) {
403 SSHBUF_DBG(("SSH_ERR_NO_BUFFER_SPACE"));
404 return SSH_ERR_NO_BUFFER_SPACE;
405 }
406 /* Skip leading zero bytes */
407 for (; len > 0 && *s == 0; len--, s++)
408 ;
409 /*
410 * If most significant bit is set then prepend a zero byte to
411 * avoid interpretation as a negative number.
412 */
413 prepend = len > 0 && (s[0] & 0x80) != 0;
414 if ((r = sshbuf_reserve(buf, len + 4 + prepend, &d)) < 0)
415 return r;
416 POKE_U32(d, len + prepend);
417 if (prepend)
418 d[4] = 0;
419 memcpy(d + 4 + prepend, s, len);
420 return 0;
421}
diff --git a/sshbuf-getput-crypto.c b/sshbuf-getput-crypto.c
new file mode 100644
index 000000000..74351d3e5
--- /dev/null
+++ b/sshbuf-getput-crypto.c
@@ -0,0 +1,237 @@
1/* $OpenBSD: sshbuf-getput-crypto.c,v 1.2 2014/06/18 15:42:09 naddy Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#define SSHBUF_INTERNAL
19#include "includes.h"
20
21#include <sys/types.h>
22#include <stdlib.h>
23#include <stdio.h>
24#include <string.h>
25
26#include <openssl/bn.h>
27#ifdef OPENSSL_HAS_ECC
28# include <openssl/ec.h>
29#endif /* OPENSSL_HAS_ECC */
30
31#include "ssherr.h"
32#include "sshbuf.h"
33
34int
35sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v)
36{
37 const u_char *d;
38 size_t len;
39 int r;
40
41 if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
42 return r;
43 /* Refuse negative (MSB set) bignums */
44 if ((len != 0 && (*d & 0x80) != 0))
45 return SSH_ERR_BIGNUM_IS_NEGATIVE;
46 /* Refuse overlong bignums, allow prepended \0 to avoid MSB set */
47 if (len > SSHBUF_MAX_BIGNUM + 1 ||
48 (len == SSHBUF_MAX_BIGNUM + 1 && *d != 0))
49 return SSH_ERR_BIGNUM_TOO_LARGE;
50 if (v != NULL && BN_bin2bn(d, len, v) == NULL)
51 return SSH_ERR_ALLOC_FAIL;
52 /* Consume the string */
53 if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
54 /* Shouldn't happen */
55 SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
56 SSHBUF_ABORT();
57 return SSH_ERR_INTERNAL_ERROR;
58 }
59 return 0;
60}
61
62int
63sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v)
64{
65 const u_char *d = sshbuf_ptr(buf);
66 u_int16_t len_bits;
67 size_t len_bytes;
68
69 /* Length in bits */
70 if (sshbuf_len(buf) < 2)
71 return SSH_ERR_MESSAGE_INCOMPLETE;
72 len_bits = PEEK_U16(d);
73 len_bytes = (len_bits + 7) >> 3;
74 if (len_bytes > SSHBUF_MAX_BIGNUM)
75 return SSH_ERR_BIGNUM_TOO_LARGE;
76 if (sshbuf_len(buf) < 2 + len_bytes)
77 return SSH_ERR_MESSAGE_INCOMPLETE;
78 if (v != NULL && BN_bin2bn(d + 2, len_bytes, v) == NULL)
79 return SSH_ERR_ALLOC_FAIL;
80 if (sshbuf_consume(buf, 2 + len_bytes) != 0) {
81 SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
82 SSHBUF_ABORT();
83 return SSH_ERR_INTERNAL_ERROR;
84 }
85 return 0;
86}
87
88#ifdef OPENSSL_HAS_ECC
89static int
90get_ec(const u_char *d, size_t len, EC_POINT *v, const EC_GROUP *g)
91{
92 /* Refuse overlong bignums */
93 if (len == 0 || len > SSHBUF_MAX_ECPOINT)
94 return SSH_ERR_ECPOINT_TOO_LARGE;
95 /* Only handle uncompressed points */
96 if (*d != POINT_CONVERSION_UNCOMPRESSED)
97 return SSH_ERR_INVALID_FORMAT;
98 if (v != NULL && EC_POINT_oct2point(g, v, d, len, NULL) != 1)
99 return SSH_ERR_INVALID_FORMAT; /* XXX assumption */
100 return 0;
101}
102
103int
104sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g)
105{
106 const u_char *d;
107 size_t len;
108 int r;
109
110 if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0)
111 return r;
112 if ((r = get_ec(d, len, v, g)) != 0)
113 return r;
114 /* Skip string */
115 if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
116 /* Shouldn't happen */
117 SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
118 SSHBUF_ABORT();
119 return SSH_ERR_INTERNAL_ERROR;
120 }
121 return 0;
122}
123
124int
125sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v)
126{
127 EC_POINT *pt = EC_POINT_new(EC_KEY_get0_group(v));
128 int r;
129 const u_char *d;
130 size_t len;
131
132 if (pt == NULL) {
133 SSHBUF_DBG(("SSH_ERR_ALLOC_FAIL"));
134 return SSH_ERR_ALLOC_FAIL;
135 }
136 if ((r = sshbuf_peek_string_direct(buf, &d, &len)) < 0) {
137 EC_POINT_free(pt);
138 return r;
139 }
140 if ((r = get_ec(d, len, pt, EC_KEY_get0_group(v))) != 0) {
141 EC_POINT_free(pt);
142 return r;
143 }
144 if (EC_KEY_set_public_key(v, pt) != 1) {
145 EC_POINT_free(pt);
146 return SSH_ERR_ALLOC_FAIL; /* XXX assumption */
147 }
148 EC_POINT_free(pt);
149 /* Skip string */
150 if (sshbuf_get_string_direct(buf, NULL, NULL) != 0) {
151 /* Shouldn't happen */
152 SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
153 SSHBUF_ABORT();
154 return SSH_ERR_INTERNAL_ERROR;
155 }
156 return 0;
157}
158#endif /* OPENSSL_HAS_ECC */
159
160int
161sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v)
162{
163 u_char d[SSHBUF_MAX_BIGNUM + 1];
164 int len = BN_num_bytes(v), prepend = 0, r;
165
166 if (len < 0 || len > SSHBUF_MAX_BIGNUM)
167 return SSH_ERR_INVALID_ARGUMENT;
168 *d = '\0';
169 if (BN_bn2bin(v, d + 1) != len)
170 return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
171 /* If MSB is set, prepend a \0 */
172 if (len > 0 && (d[1] & 0x80) != 0)
173 prepend = 1;
174 if ((r = sshbuf_put_string(buf, d + 1 - prepend, len + prepend)) < 0) {
175 bzero(d, sizeof(d));
176 return r;
177 }
178 bzero(d, sizeof(d));
179 return 0;
180}
181
182int
183sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v)
184{
185 int r, len_bits = BN_num_bits(v);
186 size_t len_bytes = (len_bits + 7) / 8;
187 u_char d[SSHBUF_MAX_BIGNUM], *dp;
188
189 if (len_bits < 0 || len_bytes > SSHBUF_MAX_BIGNUM)
190 return SSH_ERR_INVALID_ARGUMENT;
191 if (BN_bn2bin(v, d) != (int)len_bytes)
192 return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
193 if ((r = sshbuf_reserve(buf, len_bytes + 2, &dp)) < 0) {
194 bzero(d, sizeof(d));
195 return r;
196 }
197 POKE_U16(dp, len_bits);
198 memcpy(dp + 2, d, len_bytes);
199 bzero(d, sizeof(d));
200 return 0;
201}
202
203#ifdef OPENSSL_HAS_ECC
204int
205sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g)
206{
207 u_char d[SSHBUF_MAX_ECPOINT];
208 BN_CTX *bn_ctx;
209 size_t len;
210 int ret;
211
212 if ((bn_ctx = BN_CTX_new()) == NULL)
213 return SSH_ERR_ALLOC_FAIL;
214 if ((len = EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
215 NULL, 0, bn_ctx)) > SSHBUF_MAX_ECPOINT) {
216 BN_CTX_free(bn_ctx);
217 return SSH_ERR_INVALID_ARGUMENT;
218 }
219 if (EC_POINT_point2oct(g, v, POINT_CONVERSION_UNCOMPRESSED,
220 d, len, bn_ctx) != len) {
221 BN_CTX_free(bn_ctx);
222 return SSH_ERR_INTERNAL_ERROR; /* Shouldn't happen */
223 }
224 BN_CTX_free(bn_ctx);
225 ret = sshbuf_put_string(buf, d, len);
226 bzero(d, len);
227 return ret;
228}
229
230int
231sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v)
232{
233 return sshbuf_put_ec(buf, EC_KEY_get0_public_key(v),
234 EC_KEY_get0_group(v));
235}
236#endif /* OPENSSL_HAS_ECC */
237
diff --git a/sshbuf-misc.c b/sshbuf-misc.c
new file mode 100644
index 000000000..bfeffe674
--- /dev/null
+++ b/sshbuf-misc.c
@@ -0,0 +1,135 @@
1/* $OpenBSD: sshbuf-misc.c,v 1.2 2014/06/24 01:13:21 djm Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include "includes.h"
19
20#include <sys/types.h>
21#include <sys/socket.h>
22#include <netinet/in.h>
23#include <errno.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <limits.h>
27#include <string.h>
28#include <resolv.h>
29#include <ctype.h>
30
31#include "ssherr.h"
32#define SSHBUF_INTERNAL
33#include "sshbuf.h"
34
35void
36sshbuf_dump_data(const void *s, size_t len, FILE *f)
37{
38 size_t i, j;
39 const u_char *p = (const u_char *)s;
40
41 for (i = 0; i < len; i += 16) {
42 fprintf(f, "%.4zd: ", i);
43 for (j = i; j < i + 16; j++) {
44 if (j < len)
45 fprintf(f, "%02x ", p[j]);
46 else
47 fprintf(f, " ");
48 }
49 fprintf(f, " ");
50 for (j = i; j < i + 16; j++) {
51 if (j < len) {
52 if (isascii(p[j]) && isprint(p[j]))
53 fprintf(f, "%c", p[j]);
54 else
55 fprintf(f, ".");
56 }
57 }
58 fprintf(f, "\n");
59 }
60}
61
62void
63sshbuf_dump(struct sshbuf *buf, FILE *f)
64{
65 fprintf(f, "buffer %p len = %zu\n", buf, sshbuf_len(buf));
66 sshbuf_dump_data(sshbuf_ptr(buf), sshbuf_len(buf), f);
67}
68
69char *
70sshbuf_dtob16(struct sshbuf *buf)
71{
72 size_t i, j, len = sshbuf_len(buf);
73 const u_char *p = sshbuf_ptr(buf);
74 char *ret;
75 const char hex[] = "0123456789abcdef";
76
77 if (len == 0)
78 return strdup("");
79 if (SIZE_MAX / 2 <= len || (ret = malloc(len * 2 + 1)) == NULL)
80 return NULL;
81 for (i = j = 0; i < len; i++) {
82 ret[j++] = hex[(p[i] >> 4) & 0xf];
83 ret[j++] = hex[p[i] & 0xf];
84 }
85 ret[j] = '\0';
86 return ret;
87}
88
89char *
90sshbuf_dtob64(struct sshbuf *buf)
91{
92 size_t len = sshbuf_len(buf), plen;
93 const u_char *p = sshbuf_ptr(buf);
94 char *ret;
95 int r;
96
97 if (len == 0)
98 return strdup("");
99 plen = ((len + 2) / 3) * 4 + 1;
100 if (SIZE_MAX / 2 <= len || (ret = malloc(plen)) == NULL)
101 return NULL;
102 if ((r = b64_ntop(p, len, ret, plen)) == -1) {
103 bzero(ret, plen);
104 free(ret);
105 return NULL;
106 }
107 return ret;
108}
109
110int
111sshbuf_b64tod(struct sshbuf *buf, const char *b64)
112{
113 size_t plen = strlen(b64);
114 int nlen, r;
115 u_char *p;
116
117 if (plen == 0)
118 return 0;
119 if ((p = malloc(plen)) == NULL)
120 return SSH_ERR_ALLOC_FAIL;
121 if ((nlen = b64_pton(b64, p, plen)) < 0) {
122 bzero(p, plen);
123 free(p);
124 return SSH_ERR_INVALID_FORMAT;
125 }
126 if ((r = sshbuf_put(buf, p, nlen)) < 0) {
127 bzero(p, plen);
128 free(p);
129 return r;
130 }
131 bzero(p, plen);
132 free(p);
133 return 0;
134}
135
diff --git a/sshbuf.c b/sshbuf.c
new file mode 100644
index 000000000..78f5340a1
--- /dev/null
+++ b/sshbuf.c
@@ -0,0 +1,406 @@
1/* $OpenBSD: sshbuf.c,v 1.2 2014/06/25 14:16:09 deraadt Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#define SSHBUF_INTERNAL
19#include "includes.h"
20
21#include <sys/types.h>
22#include <sys/param.h>
23#include <signal.h>
24#include <stdlib.h>
25#include <stdio.h>
26#include <string.h>
27
28#include "ssherr.h"
29#include "sshbuf.h"
30
31static inline int
32sshbuf_check_sanity(const struct sshbuf *buf)
33{
34 SSHBUF_TELL("sanity");
35 if (__predict_false(buf == NULL ||
36 (!buf->readonly && buf->d != buf->cd) ||
37 buf->refcount < 1 || buf->refcount > SSHBUF_REFS_MAX ||
38 buf->cd == NULL ||
39 (buf->dont_free && (buf->readonly || buf->parent != NULL)) ||
40 buf->max_size > SSHBUF_SIZE_MAX ||
41 buf->alloc > buf->max_size ||
42 buf->size > buf->alloc ||
43 buf->off > buf->size)) {
44 /* Do not try to recover from corrupted buffer internals */
45 SSHBUF_DBG(("SSH_ERR_INTERNAL_ERROR"));
46 signal(SIGSEGV, SIG_DFL);
47 raise(SIGSEGV);
48 return SSH_ERR_INTERNAL_ERROR;
49 }
50 return 0;
51}
52
53static void
54sshbuf_maybe_pack(struct sshbuf *buf, int force)
55{
56 SSHBUF_DBG(("force %d", force));
57 SSHBUF_TELL("pre-pack");
58 if (buf->off == 0 || buf->readonly || buf->refcount > 1)
59 return;
60 if (force ||
61 (buf->off >= SSHBUF_PACK_MIN && buf->off >= buf->size / 2)) {
62 memmove(buf->d, buf->d + buf->off, buf->size - buf->off);
63 buf->size -= buf->off;
64 buf->off = 0;
65 SSHBUF_TELL("packed");
66 }
67}
68
69struct sshbuf *
70sshbuf_new(void)
71{
72 struct sshbuf *ret;
73
74 if ((ret = calloc(sizeof(*ret), 1)) == NULL)
75 return NULL;
76 ret->alloc = SSHBUF_SIZE_INIT;
77 ret->max_size = SSHBUF_SIZE_MAX;
78 ret->readonly = 0;
79 ret->refcount = 1;
80 ret->parent = NULL;
81 if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL) {
82 free(ret);
83 return NULL;
84 }
85 return ret;
86}
87
88struct sshbuf *
89sshbuf_from(const void *blob, size_t len)
90{
91 struct sshbuf *ret;
92
93 if (blob == NULL || len > SSHBUF_SIZE_MAX ||
94 (ret = calloc(sizeof(*ret), 1)) == NULL)
95 return NULL;
96 ret->alloc = ret->size = ret->max_size = len;
97 ret->readonly = 1;
98 ret->refcount = 1;
99 ret->parent = NULL;
100 ret->cd = blob;
101 ret->d = NULL;
102 return ret;
103}
104
105int
106sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent)
107{
108 int r;
109
110 if ((r = sshbuf_check_sanity(child)) != 0 ||
111 (r = sshbuf_check_sanity(parent)) != 0)
112 return r;
113 child->parent = parent;
114 child->parent->refcount++;
115 return 0;
116}
117
118struct sshbuf *
119sshbuf_fromb(struct sshbuf *buf)
120{
121 struct sshbuf *ret;
122
123 if (sshbuf_check_sanity(buf) != 0)
124 return NULL;
125 if ((ret = sshbuf_from(sshbuf_ptr(buf), sshbuf_len(buf))) == NULL)
126 return NULL;
127 if (sshbuf_set_parent(ret, buf) != 0) {
128 sshbuf_free(ret);
129 return NULL;
130 }
131 return ret;
132}
133
134void
135sshbuf_init(struct sshbuf *ret)
136{
137 bzero(ret, sizeof(*ret));
138 ret->alloc = SSHBUF_SIZE_INIT;
139 ret->max_size = SSHBUF_SIZE_MAX;
140 ret->readonly = 0;
141 ret->dont_free = 1;
142 ret->refcount = 1;
143 if ((ret->cd = ret->d = calloc(1, ret->alloc)) == NULL)
144 ret->alloc = 0;
145}
146
147void
148sshbuf_free(struct sshbuf *buf)
149{
150 int dont_free = 0;
151
152 if (buf == NULL)
153 return;
154 /*
155 * The following will leak on insane buffers, but this is the safest
156 * course of action - an invalid pointer or already-freed pointer may
157 * have been passed to us and continuing to scribble over memory would
158 * be bad.
159 */
160 if (sshbuf_check_sanity(buf) != 0)
161 return;
162 /*
163 * If we are a child, the free our parent to decrement its reference
164 * count and possibly free it.
165 */
166 if (buf->parent != NULL) {
167 sshbuf_free(buf->parent);
168 buf->parent = NULL;
169 }
170 /*
171 * If we are a parent with still-extant children, then don't free just
172 * yet. The last child's call to sshbuf_free should decrement our
173 * refcount to 0 and trigger the actual free.
174 */
175 buf->refcount--;
176 if (buf->refcount > 0)
177 return;
178 dont_free = buf->dont_free;
179 if (!buf->readonly) {
180 bzero(buf->d, buf->alloc);
181 free(buf->d);
182 }
183 bzero(buf, sizeof(*buf));
184 if (!dont_free)
185 free(buf);
186}
187
188void
189sshbuf_reset(struct sshbuf *buf)
190{
191 u_char *d;
192
193 if (buf->readonly || buf->refcount > 1) {
194 /* Nonsensical. Just make buffer appear empty */
195 buf->off = buf->size;
196 return;
197 }
198 if (sshbuf_check_sanity(buf) == 0)
199 bzero(buf->d, buf->alloc);
200 buf->off = buf->size = 0;
201 if (buf->alloc != SSHBUF_SIZE_INIT) {
202 if ((d = realloc(buf->d, SSHBUF_SIZE_INIT)) != NULL) {
203 buf->cd = buf->d = d;
204 buf->alloc = SSHBUF_SIZE_INIT;
205 }
206 }
207}
208
209size_t
210sshbuf_max_size(const struct sshbuf *buf)
211{
212 return buf->max_size;
213}
214
215size_t
216sshbuf_alloc(const struct sshbuf *buf)
217{
218 return buf->alloc;
219}
220
221const struct sshbuf *
222sshbuf_parent(const struct sshbuf *buf)
223{
224 return buf->parent;
225}
226
227u_int
228sshbuf_refcount(const struct sshbuf *buf)
229{
230 return buf->refcount;
231}
232
233int
234sshbuf_set_max_size(struct sshbuf *buf, size_t max_size)
235{
236 size_t rlen;
237 u_char *dp;
238 int r;
239
240 SSHBUF_DBG(("set max buf = %p len = %zu", buf, max_size));
241 if ((r = sshbuf_check_sanity(buf)) != 0)
242 return r;
243 if (max_size == buf->max_size)
244 return 0;
245 if (buf->readonly || buf->refcount > 1)
246 return SSH_ERR_BUFFER_READ_ONLY;
247 if (max_size > SSHBUF_SIZE_MAX)
248 return SSH_ERR_NO_BUFFER_SPACE;
249 /* pack and realloc if necessary */
250 sshbuf_maybe_pack(buf, max_size < buf->size);
251 if (max_size < buf->alloc && max_size > buf->size) {
252 if (buf->size < SSHBUF_SIZE_INIT)
253 rlen = SSHBUF_SIZE_INIT;
254 else
255 rlen = roundup(buf->size, SSHBUF_SIZE_INC);
256 if (rlen > max_size)
257 rlen = max_size;
258 bzero(buf->d + buf->size, buf->alloc - buf->size);
259 SSHBUF_DBG(("new alloc = %zu", rlen));
260 if ((dp = realloc(buf->d, rlen)) == NULL)
261 return SSH_ERR_ALLOC_FAIL;
262 buf->cd = buf->d = dp;
263 buf->alloc = rlen;
264 }
265 SSHBUF_TELL("new-max");
266 if (max_size < buf->alloc)
267 return SSH_ERR_NO_BUFFER_SPACE;
268 buf->max_size = max_size;
269 return 0;
270}
271
272size_t
273sshbuf_len(const struct sshbuf *buf)
274{
275 if (sshbuf_check_sanity(buf) != 0)
276 return 0;
277 return buf->size - buf->off;
278}
279
280size_t
281sshbuf_avail(const struct sshbuf *buf)
282{
283 if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1)
284 return 0;
285 return buf->max_size - (buf->size - buf->off);
286}
287
288const u_char *
289sshbuf_ptr(const struct sshbuf *buf)
290{
291 if (sshbuf_check_sanity(buf) != 0)
292 return NULL;
293 return buf->cd + buf->off;
294}
295
296u_char *
297sshbuf_mutable_ptr(const struct sshbuf *buf)
298{
299 if (sshbuf_check_sanity(buf) != 0 || buf->readonly || buf->refcount > 1)
300 return NULL;
301 return buf->d + buf->off;
302}
303
304int
305sshbuf_check_reserve(const struct sshbuf *buf, size_t len)
306{
307 int r;
308
309 if ((r = sshbuf_check_sanity(buf)) != 0)
310 return r;
311 if (buf->readonly || buf->refcount > 1)
312 return SSH_ERR_BUFFER_READ_ONLY;
313 SSHBUF_TELL("check");
314 /* Check that len is reasonable and that max_size + available < len */
315 if (len > buf->max_size || buf->max_size - len < buf->size - buf->off)
316 return SSH_ERR_NO_BUFFER_SPACE;
317 return 0;
318}
319
320int
321sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp)
322{
323 size_t rlen, need;
324 u_char *dp;
325 int r;
326
327 if (dpp != NULL)
328 *dpp = NULL;
329
330 SSHBUF_DBG(("reserve buf = %p len = %zu", buf, len));
331 if ((r = sshbuf_check_reserve(buf, len)) != 0)
332 return r;
333 /*
334 * If the requested allocation appended would push us past max_size
335 * then pack the buffer, zeroing buf->off.
336 */
337 sshbuf_maybe_pack(buf, buf->size + len > buf->max_size);
338 SSHBUF_TELL("reserve");
339 if (len + buf->size > buf->alloc) {
340 /*
341 * Prefer to alloc in SSHBUF_SIZE_INC units, but
342 * allocate less if doing so would overflow max_size.
343 */
344 need = len + buf->size - buf->alloc;
345 rlen = roundup(buf->alloc + need, SSHBUF_SIZE_INC);
346 SSHBUF_DBG(("need %zu initial rlen %zu", need, rlen));
347 if (rlen > buf->max_size)
348 rlen = buf->alloc + need;
349 SSHBUF_DBG(("adjusted rlen %zu", rlen));
350 if ((dp = realloc(buf->d, rlen)) == NULL) {
351 SSHBUF_DBG(("realloc fail"));
352 if (dpp != NULL)
353 *dpp = NULL;
354 return SSH_ERR_ALLOC_FAIL;
355 }
356 buf->alloc = rlen;
357 buf->cd = buf->d = dp;
358 if ((r = sshbuf_check_reserve(buf, len)) < 0) {
359 /* shouldn't fail */
360 if (dpp != NULL)
361 *dpp = NULL;
362 return r;
363 }
364 }
365 dp = buf->d + buf->size;
366 buf->size += len;
367 SSHBUF_TELL("done");
368 if (dpp != NULL)
369 *dpp = dp;
370 return 0;
371}
372
373int
374sshbuf_consume(struct sshbuf *buf, size_t len)
375{
376 int r;
377
378 SSHBUF_DBG(("len = %zu", len));
379 if ((r = sshbuf_check_sanity(buf)) != 0)
380 return r;
381 if (len == 0)
382 return 0;
383 if (len > sshbuf_len(buf))
384 return SSH_ERR_MESSAGE_INCOMPLETE;
385 buf->off += len;
386 SSHBUF_TELL("done");
387 return 0;
388}
389
390int
391sshbuf_consume_end(struct sshbuf *buf, size_t len)
392{
393 int r;
394
395 SSHBUF_DBG(("len = %zu", len));
396 if ((r = sshbuf_check_sanity(buf)) != 0)
397 return r;
398 if (len == 0)
399 return 0;
400 if (len > sshbuf_len(buf))
401 return SSH_ERR_MESSAGE_INCOMPLETE;
402 buf->size -= len;
403 SSHBUF_TELL("done");
404 return 0;
405}
406
diff --git a/sshbuf.h b/sshbuf.h
new file mode 100644
index 000000000..3602bc53f
--- /dev/null
+++ b/sshbuf.h
@@ -0,0 +1,336 @@
1/* $OpenBSD: sshbuf.h,v 1.3 2014/06/24 01:13:21 djm Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef _SSHBUF_H
19#define _SSHBUF_H
20
21#include <sys/types.h>
22#include <stdarg.h>
23#include <stdio.h>
24#ifdef WITH_OPENSSL
25# include <openssl/bn.h>
26# ifdef OPENSSL_HAS_ECC
27# include <openssl/ec.h>
28# endif /* OPENSSL_HAS_ECC */
29#endif /* WITH_OPENSSL */
30
31#define SSHBUF_SIZE_MAX 0x8000000 /* Hard maximum size */
32#define SSHBUF_REFS_MAX 0x100000 /* Max child buffers */
33#define SSHBUF_MAX_BIGNUM (16384 / 8) /* Max bignum *bytes* */
34#define SSHBUF_MAX_ECPOINT ((528 * 2 / 8) + 1) /* Max EC point *bytes* */
35
36/*
37 * NB. do not depend on the internals of this. It will be made opaque
38 * one day.
39 */
40struct sshbuf {
41 u_char *d; /* Data */
42 const u_char *cd; /* Const data */
43 size_t off; /* First available byte is buf->d + buf->off */
44 size_t size; /* Last byte is buf->d + buf->size - 1 */
45 size_t max_size; /* Maximum size of buffer */
46 size_t alloc; /* Total bytes allocated to buf->d */
47 int readonly; /* Refers to external, const data */
48 int dont_free; /* Kludge to support sshbuf_init */
49 u_int refcount; /* Tracks self and number of child buffers */
50 struct sshbuf *parent; /* If child, pointer to parent */
51};
52
53#ifndef SSHBUF_NO_DEPREACTED
54/*
55 * NB. Please do not use sshbuf_init() in new code. Please use sshbuf_new()
56 * instead. sshbuf_init() is deprectated and will go away soon (it is
57 * only included to allow compat with buffer_* in OpenSSH)
58 */
59void sshbuf_init(struct sshbuf *buf);
60#endif
61
62/*
63 * Create a new sshbuf buffer.
64 * Returns pointer to buffer on success, or NULL on allocation failure.
65 */
66struct sshbuf *sshbuf_new(void);
67
68/*
69 * Create a new, read-only sshbuf buffer from existing data.
70 * Returns pointer to buffer on success, or NULL on allocation failure.
71 */
72struct sshbuf *sshbuf_from(const void *blob, size_t len);
73
74/*
75 * Create a new, read-only sshbuf buffer from the contents of an existing
76 * buffer. The contents of "buf" must not change in the lifetime of the
77 * resultant buffer.
78 * Returns pointer to buffer on success, or NULL on allocation failure.
79 */
80struct sshbuf *sshbuf_fromb(struct sshbuf *buf);
81
82/*
83 * Create a new, read-only sshbuf buffer from the contents of a string in
84 * an existing buffer (the string is consumed in the process).
85 * The contents of "buf" must not change in the lifetime of the resultant
86 * buffer.
87 * Returns pointer to buffer on success, or NULL on allocation failure.
88 */
89int sshbuf_froms(struct sshbuf *buf, struct sshbuf **bufp);
90
91/*
92 * Clear and free buf
93 */
94void sshbuf_free(struct sshbuf *buf);
95
96/*
97 * Reset buf, clearing its contents. NB. max_size is preserved.
98 */
99void sshbuf_reset(struct sshbuf *buf);
100
101/*
102 * Return the maximum size of buf
103 */
104size_t sshbuf_max_size(const struct sshbuf *buf);
105
106/*
107 * Set the maximum size of buf
108 * Returns 0 on success, or a negative SSH_ERR_* error code on failure.
109 */
110int sshbuf_set_max_size(struct sshbuf *buf, size_t max_size);
111
112/*
113 * Returns the length of data in buf
114 */
115size_t sshbuf_len(const struct sshbuf *buf);
116
117/*
118 * Returns number of bytes left in buffer before hitting max_size.
119 */
120size_t sshbuf_avail(const struct sshbuf *buf);
121
122/*
123 * Returns a read-only pointer to the start of the the data in buf
124 */
125const u_char *sshbuf_ptr(const struct sshbuf *buf);
126
127/*
128 * Returns a mutable pointer to the start of the the data in buf, or
129 * NULL if the buffer is read-only.
130 */
131u_char *sshbuf_mutable_ptr(const struct sshbuf *buf);
132
133/*
134 * Check whether a reservation of size len will succeed in buf
135 * Safer to use than direct comparisons again sshbuf_avail as it copes
136 * with unsigned overflows correctly.
137 * Returns 0 on success, or a negative SSH_ERR_* error code on failure.
138 */
139int sshbuf_check_reserve(const struct sshbuf *buf, size_t len);
140
141/*
142 * Reserve len bytes in buf.
143 * Returns 0 on success and a pointer to the first reserved byte via the
144 * optional dpp parameter or a negative * SSH_ERR_* error code on failure.
145 */
146int sshbuf_reserve(struct sshbuf *buf, size_t len, u_char **dpp);
147
148/*
149 * Consume len bytes from the start of buf
150 * Returns 0 on success, or a negative SSH_ERR_* error code on failure.
151 */
152int sshbuf_consume(struct sshbuf *buf, size_t len);
153
154/*
155 * Consume len bytes from the end of buf
156 * Returns 0 on success, or a negative SSH_ERR_* error code on failure.
157 */
158int sshbuf_consume_end(struct sshbuf *buf, size_t len);
159
160/* Extract or deposit some bytes */
161int sshbuf_get(struct sshbuf *buf, void *v, size_t len);
162int sshbuf_put(struct sshbuf *buf, const void *v, size_t len);
163int sshbuf_putb(struct sshbuf *buf, const struct sshbuf *v);
164
165/* Append using a printf(3) format */
166int sshbuf_putf(struct sshbuf *buf, const char *fmt, ...)
167 __attribute__((format(printf, 2, 3)));
168int sshbuf_putfv(struct sshbuf *buf, const char *fmt, va_list ap);
169
170/* Functions to extract or store big-endian words of various sizes */
171int sshbuf_get_u64(struct sshbuf *buf, u_int64_t *valp);
172int sshbuf_get_u32(struct sshbuf *buf, u_int32_t *valp);
173int sshbuf_get_u16(struct sshbuf *buf, u_int16_t *valp);
174int sshbuf_get_u8(struct sshbuf *buf, u_char *valp);
175int sshbuf_put_u64(struct sshbuf *buf, u_int64_t val);
176int sshbuf_put_u32(struct sshbuf *buf, u_int32_t val);
177int sshbuf_put_u16(struct sshbuf *buf, u_int16_t val);
178int sshbuf_put_u8(struct sshbuf *buf, u_char val);
179
180/*
181 * Functions to extract or store SSH wire encoded strings (u32 len || data)
182 * The "cstring" variants admit no \0 characters in the string contents.
183 * Caller must free *valp.
184 */
185int sshbuf_get_string(struct sshbuf *buf, u_char **valp, size_t *lenp);
186int sshbuf_get_cstring(struct sshbuf *buf, char **valp, size_t *lenp);
187int sshbuf_get_stringb(struct sshbuf *buf, struct sshbuf *v);
188int sshbuf_put_string(struct sshbuf *buf, const void *v, size_t len);
189int sshbuf_put_cstring(struct sshbuf *buf, const char *v);
190int sshbuf_put_stringb(struct sshbuf *buf, const struct sshbuf *v);
191
192/*
193 * "Direct" variant of sshbuf_get_string, returns pointer into the sshbuf to
194 * avoid an malloc+memcpy. The pointer is guaranteed to be valid until the
195 * next sshbuf-modifying function call. Caller does not free.
196 */
197int sshbuf_get_string_direct(struct sshbuf *buf, const u_char **valp,
198 size_t *lenp);
199
200/* Skip past a string */
201#define sshbuf_skip_string(buf) sshbuf_get_string_direct(buf, NULL, NULL)
202
203/* Another variant: "peeks" into the buffer without modifying it */
204int sshbuf_peek_string_direct(const struct sshbuf *buf, const u_char **valp,
205 size_t *lenp);
206
207/*
208 * Functions to extract or store SSH wire encoded bignums and elliptic
209 * curve points.
210 */
211int sshbuf_put_bignum2_bytes(struct sshbuf *buf, const void *v, size_t len);
212#ifdef WITH_OPENSSL
213int sshbuf_get_bignum2(struct sshbuf *buf, BIGNUM *v);
214int sshbuf_get_bignum1(struct sshbuf *buf, BIGNUM *v);
215int sshbuf_put_bignum2(struct sshbuf *buf, const BIGNUM *v);
216int sshbuf_put_bignum1(struct sshbuf *buf, const BIGNUM *v);
217# ifdef OPENSSL_HAS_ECC
218int sshbuf_get_ec(struct sshbuf *buf, EC_POINT *v, const EC_GROUP *g);
219int sshbuf_get_eckey(struct sshbuf *buf, EC_KEY *v);
220int sshbuf_put_ec(struct sshbuf *buf, const EC_POINT *v, const EC_GROUP *g);
221int sshbuf_put_eckey(struct sshbuf *buf, const EC_KEY *v);
222# endif /* OPENSSL_HAS_ECC */
223#endif /* WITH_OPENSSL */
224
225/* Dump the contents of the buffer in a human-readable format */
226void sshbuf_dump(struct sshbuf *buf, FILE *f);
227
228/* Dump specified memory in a human-readable format */
229void sshbuf_dump_data(const void *s, size_t len, FILE *f);
230
231/* Return the hexadecimal representation of the contents of the buffer */
232char *sshbuf_dtob16(struct sshbuf *buf);
233
234/* Encode the contents of the buffer as base64 */
235char *sshbuf_dtob64(struct sshbuf *buf);
236
237/* Decode base64 data and append it to the buffer */
238int sshbuf_b64tod(struct sshbuf *buf, const char *b64);
239
240/* Macros for decoding/encoding integers */
241#define PEEK_U64(p) \
242 (((u_int64_t)(((u_char *)(p))[0]) << 56) | \
243 ((u_int64_t)(((u_char *)(p))[1]) << 48) | \
244 ((u_int64_t)(((u_char *)(p))[2]) << 40) | \
245 ((u_int64_t)(((u_char *)(p))[3]) << 32) | \
246 ((u_int64_t)(((u_char *)(p))[4]) << 24) | \
247 ((u_int64_t)(((u_char *)(p))[5]) << 16) | \
248 ((u_int64_t)(((u_char *)(p))[6]) << 8) | \
249 (u_int64_t)(((u_char *)(p))[7]))
250#define PEEK_U32(p) \
251 (((u_int32_t)(((u_char *)(p))[0]) << 24) | \
252 ((u_int32_t)(((u_char *)(p))[1]) << 16) | \
253 ((u_int32_t)(((u_char *)(p))[2]) << 8) | \
254 (u_int32_t)(((u_char *)(p))[3]))
255#define PEEK_U16(p) \
256 (((u_int16_t)(((u_char *)(p))[0]) << 8) | \
257 (u_int16_t)(((u_char *)(p))[1]))
258
259#define POKE_U64(p, v) \
260 do { \
261 ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 56) & 0xff; \
262 ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 48) & 0xff; \
263 ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 40) & 0xff; \
264 ((u_char *)(p))[3] = (((u_int64_t)(v)) >> 32) & 0xff; \
265 ((u_char *)(p))[4] = (((u_int64_t)(v)) >> 24) & 0xff; \
266 ((u_char *)(p))[5] = (((u_int64_t)(v)) >> 16) & 0xff; \
267 ((u_char *)(p))[6] = (((u_int64_t)(v)) >> 8) & 0xff; \
268 ((u_char *)(p))[7] = ((u_int64_t)(v)) & 0xff; \
269 } while (0)
270#define POKE_U32(p, v) \
271 do { \
272 ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 24) & 0xff; \
273 ((u_char *)(p))[1] = (((u_int64_t)(v)) >> 16) & 0xff; \
274 ((u_char *)(p))[2] = (((u_int64_t)(v)) >> 8) & 0xff; \
275 ((u_char *)(p))[3] = ((u_int64_t)(v)) & 0xff; \
276 } while (0)
277#define POKE_U16(p, v) \
278 do { \
279 ((u_char *)(p))[0] = (((u_int64_t)(v)) >> 8) & 0xff; \
280 ((u_char *)(p))[1] = ((u_int64_t)(v)) & 0xff; \
281 } while (0)
282
283/* Internal definitions follow. Exposed for regress tests */
284#ifdef SSHBUF_INTERNAL
285
286/*
287 * Return the allocation size of buf
288 */
289size_t sshbuf_alloc(const struct sshbuf *buf);
290
291/*
292 * Increment the reference count of buf.
293 */
294int sshbuf_set_parent(struct sshbuf *child, struct sshbuf *parent);
295
296/*
297 * Return the parent buffer of buf, or NULL if it has no parent.
298 */
299const struct sshbuf *sshbuf_parent(const struct sshbuf *buf);
300
301/*
302 * Return the reference count of buf
303 */
304u_int sshbuf_refcount(const struct sshbuf *buf);
305
306# define SSHBUF_SIZE_INIT 256 /* Initial allocation */
307# define SSHBUF_SIZE_INC 256 /* Preferred increment length */
308# define SSHBUF_PACK_MIN 8192 /* Minimim packable offset */
309
310/* # define SSHBUF_ABORT abort */
311/* # define SSHBUF_DEBUG */
312
313# ifndef SSHBUF_ABORT
314# define SSHBUF_ABORT()
315# endif
316
317# ifdef SSHBUF_DEBUG
318# define SSHBUF_TELL(what) do { \
319 printf("%s:%d %s: %s size %zu alloc %zu off %zu max %zu\n", \
320 __FILE__, __LINE__, __func__, what, \
321 buf->size, buf->alloc, buf->off, buf->max_size); \
322 fflush(stdout); \
323 } while (0)
324# define SSHBUF_DBG(x) do { \
325 printf("%s:%d %s: ", __FILE__, __LINE__, __func__); \
326 printf x; \
327 printf("\n"); \
328 fflush(stdout); \
329 } while (0)
330# else
331# define SSHBUF_TELL(what)
332# define SSHBUF_DBG(x)
333# endif
334#endif /* SSHBUF_INTERNAL */
335
336#endif /* _SSHBUF_H */
diff --git a/sshconnect.c b/sshconnect.c
index 324f5e0a3..563405ecb 100644
--- a/sshconnect.c
+++ b/sshconnect.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect.c,v 1.246 2014/02/06 22:21:01 djm Exp $ */ 1/* $OpenBSD: sshconnect.c,v 1.251 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -54,9 +54,9 @@
54#include "sshconnect.h" 54#include "sshconnect.h"
55#include "hostfile.h" 55#include "hostfile.h"
56#include "log.h" 56#include "log.h"
57#include "misc.h"
57#include "readconf.h" 58#include "readconf.h"
58#include "atomicio.h" 59#include "atomicio.h"
59#include "misc.h"
60#include "dns.h" 60#include "dns.h"
61#include "roaming.h" 61#include "roaming.h"
62#include "monitor_fdpass.h" 62#include "monitor_fdpass.h"
@@ -65,6 +65,7 @@
65 65
66char *client_version_string = NULL; 66char *client_version_string = NULL;
67char *server_version_string = NULL; 67char *server_version_string = NULL;
68Key *previous_host_key = NULL;
68 69
69static int matching_host_key_dns = 0; 70static int matching_host_key_dns = 0;
70 71
@@ -709,7 +710,7 @@ check_host_cert(const char *host, const Key *host_key)
709 error("%s", reason); 710 error("%s", reason);
710 return 0; 711 return 0;
711 } 712 }
712 if (buffer_len(&host_key->cert->critical) != 0) { 713 if (buffer_len(host_key->cert->critical) != 0) {
713 error("Certificate for %s contains unsupported " 714 error("Certificate for %s contains unsupported "
714 "critical options(s)", host); 715 "critical options(s)", host);
715 return 0; 716 return 0;
@@ -1222,7 +1223,7 @@ fail:
1222int 1223int
1223verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key) 1224verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1224{ 1225{
1225 int flags = 0; 1226 int r = -1, flags = 0;
1226 char *fp; 1227 char *fp;
1227 Key *plain = NULL; 1228 Key *plain = NULL;
1228 1229
@@ -1230,6 +1231,11 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1230 debug("Server host key: %s %s", key_type(host_key), fp); 1231 debug("Server host key: %s %s", key_type(host_key), fp);
1231 free(fp); 1232 free(fp);
1232 1233
1234 if (key_equal(previous_host_key, host_key)) {
1235 debug("%s: server host key matches cached key", __func__);
1236 return 0;
1237 }
1238
1233 if (options.verify_host_key_dns) { 1239 if (options.verify_host_key_dns) {
1234 /* 1240 /*
1235 * XXX certs are not yet supported for DNS, so downgrade 1241 * XXX certs are not yet supported for DNS, so downgrade
@@ -1244,7 +1250,8 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1244 flags & DNS_VERIFY_MATCH && 1250 flags & DNS_VERIFY_MATCH &&
1245 flags & DNS_VERIFY_SECURE) { 1251 flags & DNS_VERIFY_SECURE) {
1246 key_free(plain); 1252 key_free(plain);
1247 return 0; 1253 r = 0;
1254 goto done;
1248 } 1255 }
1249 if (flags & DNS_VERIFY_MATCH) { 1256 if (flags & DNS_VERIFY_MATCH) {
1250 matching_host_key_dns = 1; 1257 matching_host_key_dns = 1;
@@ -1259,9 +1266,17 @@ verify_host_key(char *host, struct sockaddr *hostaddr, Key *host_key)
1259 key_free(plain); 1266 key_free(plain);
1260 } 1267 }
1261 1268
1262 return check_host_key(host, hostaddr, options.port, host_key, RDRW, 1269 r = check_host_key(host, hostaddr, options.port, host_key, RDRW,
1263 options.user_hostfiles, options.num_user_hostfiles, 1270 options.user_hostfiles, options.num_user_hostfiles,
1264 options.system_hostfiles, options.num_system_hostfiles); 1271 options.system_hostfiles, options.num_system_hostfiles);
1272
1273done:
1274 if (r == 0 && host_key != NULL) {
1275 key_free(previous_host_key);
1276 previous_host_key = key_from_private(host_key);
1277 }
1278
1279 return r;
1265} 1280}
1266 1281
1267/* 1282/*
@@ -1297,8 +1312,12 @@ ssh_login(Sensitive *sensitive, const char *orighost,
1297 ssh_kex2(host, hostaddr, port); 1312 ssh_kex2(host, hostaddr, port);
1298 ssh_userauth2(local_user, server_user, host, sensitive); 1313 ssh_userauth2(local_user, server_user, host, sensitive);
1299 } else { 1314 } else {
1315#ifdef WITH_SSH1
1300 ssh_kex(host, hostaddr); 1316 ssh_kex(host, hostaddr);
1301 ssh_userauth1(local_user, server_user, host, sensitive); 1317 ssh_userauth1(local_user, server_user, host, sensitive);
1318#else
1319 fatal("ssh1 is not unsupported");
1320#endif
1302 } 1321 }
1303 free(local_user); 1322 free(local_user);
1304} 1323}
diff --git a/sshconnect1.c b/sshconnect1.c
index 921408ec1..dd12a3af2 100644
--- a/sshconnect1.c
+++ b/sshconnect1.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect1.c,v 1.74 2014/02/02 03:44:32 djm Exp $ */ 1/* $OpenBSD: sshconnect1.c,v 1.76 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -38,11 +38,11 @@
38#include "kex.h" 38#include "kex.h"
39#include "uidswap.h" 39#include "uidswap.h"
40#include "log.h" 40#include "log.h"
41#include "misc.h"
41#include "readconf.h" 42#include "readconf.h"
42#include "authfd.h" 43#include "authfd.h"
43#include "sshconnect.h" 44#include "sshconnect.h"
44#include "authfile.h" 45#include "authfile.h"
45#include "misc.h"
46#include "canohost.h" 46#include "canohost.h"
47#include "hostfile.h" 47#include "hostfile.h"
48#include "auth.h" 48#include "auth.h"
@@ -166,7 +166,7 @@ respond_to_rsa_challenge(BIGNUM * challenge, RSA * prv)
166 166
167 /* Decrypt the challenge using the private key. */ 167 /* Decrypt the challenge using the private key. */
168 /* XXX think about Bleichenbacher, too */ 168 /* XXX think about Bleichenbacher, too */
169 if (rsa_private_decrypt(challenge, challenge, prv) <= 0) 169 if (rsa_private_decrypt(challenge, challenge, prv) != 0)
170 packet_disconnect( 170 packet_disconnect(
171 "respond_to_rsa_challenge: rsa_private_decrypt failed"); 171 "respond_to_rsa_challenge: rsa_private_decrypt failed");
172 172
@@ -253,7 +253,7 @@ try_rsa_authentication(int idx)
253 * load the private key. Try first with empty passphrase; if it 253 * load the private key. Try first with empty passphrase; if it
254 * fails, ask for a passphrase. 254 * fails, ask for a passphrase.
255 */ 255 */
256 if (public->flags & KEY_FLAG_EXT) 256 if (public->flags & SSHKEY_FLAG_EXT)
257 private = public; 257 private = public;
258 else 258 else
259 private = key_load_private_type(KEY_RSA1, authfile, "", NULL, 259 private = key_load_private_type(KEY_RSA1, authfile, "", NULL,
@@ -302,7 +302,7 @@ try_rsa_authentication(int idx)
302 respond_to_rsa_challenge(challenge, private->rsa); 302 respond_to_rsa_challenge(challenge, private->rsa);
303 303
304 /* Destroy the private key unless it in external hardware. */ 304 /* Destroy the private key unless it in external hardware. */
305 if (!(private->flags & KEY_FLAG_EXT)) 305 if (!(private->flags & SSHKEY_FLAG_EXT))
306 key_free(private); 306 key_free(private);
307 307
308 /* We no longer need the challenge. */ 308 /* We no longer need the challenge. */
@@ -592,8 +592,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
592 BN_num_bits(server_key->rsa->n), 592 BN_num_bits(server_key->rsa->n),
593 SSH_KEY_BITS_RESERVED); 593 SSH_KEY_BITS_RESERVED);
594 } 594 }
595 rsa_public_encrypt(key, key, server_key->rsa); 595 if (rsa_public_encrypt(key, key, server_key->rsa) != 0 ||
596 rsa_public_encrypt(key, key, host_key->rsa); 596 rsa_public_encrypt(key, key, host_key->rsa) != 0)
597 fatal("%s: rsa_public_encrypt failed", __func__);
597 } else { 598 } else {
598 /* Host key has smaller modulus (or they are equal). */ 599 /* Host key has smaller modulus (or they are equal). */
599 if (BN_num_bits(server_key->rsa->n) < 600 if (BN_num_bits(server_key->rsa->n) <
@@ -604,8 +605,9 @@ ssh_kex(char *host, struct sockaddr *hostaddr)
604 BN_num_bits(host_key->rsa->n), 605 BN_num_bits(host_key->rsa->n),
605 SSH_KEY_BITS_RESERVED); 606 SSH_KEY_BITS_RESERVED);
606 } 607 }
607 rsa_public_encrypt(key, key, host_key->rsa); 608 if (rsa_public_encrypt(key, key, host_key->rsa) != 0 ||
608 rsa_public_encrypt(key, key, server_key->rsa); 609 rsa_public_encrypt(key, key, server_key->rsa) != 0)
610 fatal("%s: rsa_public_encrypt failed", __func__);
609 } 611 }
610 612
611 /* Destroy the public keys since we no longer need them. */ 613 /* Destroy the public keys since we no longer need them. */
diff --git a/sshconnect2.c b/sshconnect2.c
index 1a4e55179..7b478f16d 100644
--- a/sshconnect2.c
+++ b/sshconnect2.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshconnect2.c,v 1.204 2014/02/02 03:44:32 djm Exp $ */ 1/* $OpenBSD: sshconnect2.c,v 1.210 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Copyright (c) 2000 Markus Friedl. All rights reserved. 3 * Copyright (c) 2000 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Damien Miller. All rights reserved. 4 * Copyright (c) 2008 Damien Miller. All rights reserved.
@@ -61,8 +61,8 @@
61#include "dh.h" 61#include "dh.h"
62#include "authfd.h" 62#include "authfd.h"
63#include "log.h" 63#include "log.h"
64#include "readconf.h"
65#include "misc.h" 64#include "misc.h"
65#include "readconf.h"
66#include "match.h" 66#include "match.h"
67#include "dispatch.h" 67#include "dispatch.h"
68#include "canohost.h" 68#include "canohost.h"
@@ -156,6 +156,7 @@ order_hostkeyalgs(char *host, struct sockaddr *hostaddr, u_short port)
156void 156void
157ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port) 157ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
158{ 158{
159 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
159 Kex *kex; 160 Kex *kex;
160 161
161#ifdef GSSAPI 162#ifdef GSSAPI
@@ -240,11 +241,13 @@ ssh_kex2(char *host, struct sockaddr *hostaddr, u_short port)
240 241
241 /* start key exchange */ 242 /* start key exchange */
242 kex = kex_setup(myproposal); 243 kex = kex_setup(myproposal);
244#ifdef WITH_OPENSSL
243 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client; 245 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_client;
244 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client; 246 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_client;
245 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client; 247 kex->kex[KEX_DH_GEX_SHA1] = kexgex_client;
246 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client; 248 kex->kex[KEX_DH_GEX_SHA256] = kexgex_client;
247 kex->kex[KEX_ECDH_SHA2] = kexecdh_client; 249 kex->kex[KEX_ECDH_SHA2] = kexecdh_client;
250#endif
248 kex->kex[KEX_C25519_SHA256] = kexc25519_client; 251 kex->kex[KEX_C25519_SHA256] = kexc25519_client;
249#ifdef GSSAPI 252#ifdef GSSAPI
250 if (options.gss_keyex) { 253 if (options.gss_keyex) {
@@ -1083,7 +1086,7 @@ identity_sign(Identity *id, u_char **sigp, u_int *lenp,
1083 * we have already loaded the private key or 1086 * we have already loaded the private key or
1084 * the private key is stored in external hardware 1087 * the private key is stored in external hardware
1085 */ 1088 */
1086 if (id->isprivate || (id->key->flags & KEY_FLAG_EXT)) 1089 if (id->isprivate || (id->key->flags & SSHKEY_FLAG_EXT))
1087 return (key_sign(id->key, sigp, lenp, data, datalen)); 1090 return (key_sign(id->key, sigp, lenp, data, datalen));
1088 /* load the private key from the file */ 1091 /* load the private key from the file */
1089 if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL) 1092 if ((prv = load_identity_file(id->filename, id->userprovided)) == NULL)
@@ -1291,12 +1294,12 @@ pubkey_prepare(Authctxt *authctxt)
1291 } 1294 }
1292 /* Prefer PKCS11 keys that are explicitly listed */ 1295 /* Prefer PKCS11 keys that are explicitly listed */
1293 TAILQ_FOREACH_SAFE(id, &files, next, tmp) { 1296 TAILQ_FOREACH_SAFE(id, &files, next, tmp) {
1294 if (id->key == NULL || (id->key->flags & KEY_FLAG_EXT) == 0) 1297 if (id->key == NULL || (id->key->flags & SSHKEY_FLAG_EXT) == 0)
1295 continue; 1298 continue;
1296 found = 0; 1299 found = 0;
1297 TAILQ_FOREACH(id2, &files, next) { 1300 TAILQ_FOREACH(id2, &files, next) {
1298 if (id2->key == NULL || 1301 if (id2->key == NULL ||
1299 (id2->key->flags & KEY_FLAG_EXT) != 0) 1302 (id2->key->flags & SSHKEY_FLAG_EXT) == 0)
1300 continue; 1303 continue;
1301 if (key_equal(id->key, id2->key)) { 1304 if (key_equal(id->key, id2->key)) {
1302 TAILQ_REMOVE(&files, id, next); 1305 TAILQ_REMOVE(&files, id, next);
diff --git a/sshd.0 b/sshd.0
index c61d51535..3008e01bd 100644
--- a/sshd.0
+++ b/sshd.0
@@ -1,4 +1,4 @@
1SSHD(8) OpenBSD System Manager's Manual SSHD(8) 1SSHD(8) System Manager's Manual SSHD(8)
2 2
3NAME 3NAME
4 sshd - OpenSSH SSH daemon 4 sshd - OpenSSH SSH daemon
@@ -11,7 +11,7 @@ SYNOPSIS
11 11
12DESCRIPTION 12DESCRIPTION
13 sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these 13 sshd (OpenSSH Daemon) is the daemon program for ssh(1). Together these
14 programs replace rlogin(1) and rsh(1), and provide secure encrypted 14 programs replace rlogin and rsh, and provide secure encrypted
15 communications between two untrusted hosts over an insecure network. 15 communications between two untrusted hosts over an insecure network.
16 16
17 sshd listens for connections from clients. It is normally started at 17 sshd listens for connections from clients. It is normally started at
@@ -228,9 +228,10 @@ LOGIN PROCESS
228 228
229 7. Changes to user's home directory. 229 7. Changes to user's home directory.
230 230
231 8. If ~/.ssh/rc exists, runs it; else if /etc/ssh/sshrc exists, 231 8. If ~/.ssh/rc exists and the sshd_config(5) PermitUserRC option
232 runs it; otherwise runs xauth. The ``rc'' files are given the 232 is set, runs it; else if /etc/ssh/sshrc exists, runs it;
233 X11 authentication protocol and cookie in standard input. See 233 otherwise runs xauth. The ``rc'' files are given the X11
234 authentication protocol and cookie in standard input. See
234 SSHRC, below. 235 SSHRC, below.
235 236
236 9. Runs user's shell or command. 237 9. Runs user's shell or command.
@@ -545,11 +546,6 @@ FILES
545 directory becomes accessible. This file should be writable only 546 directory becomes accessible. This file should be writable only
546 by the user, and need not be readable by anyone else. 547 by the user, and need not be readable by anyone else.
547 548
548 /etc/hosts.allow
549 /etc/hosts.deny
550 Access controls that should be enforced by tcp-wrappers are
551 defined here. Further details are described in hosts_access(5).
552
553 /etc/hosts.equiv 549 /etc/hosts.equiv
554 This file is for host-based authentication (see ssh(1)). It 550 This file is for host-based authentication (see ssh(1)). It
555 should only be writable by root. 551 should only be writable by root.
@@ -625,8 +621,8 @@ FILES
625 621
626SEE ALSO 622SEE ALSO
627 scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1), 623 scp(1), sftp(1), ssh(1), ssh-add(1), ssh-agent(1), ssh-keygen(1),
628 ssh-keyscan(1), chroot(2), hosts_access(5), login.conf(5), moduli(5), 624 ssh-keyscan(1), chroot(2), login.conf(5), moduli(5), sshd_config(5),
629 sshd_config(5), inetd(8), sftp-server(8) 625 inetd(8), sftp-server(8)
630 626
631AUTHORS 627AUTHORS
632 OpenSSH is a derivative of the original and free ssh 1.2.12 release by 628 OpenSSH is a derivative of the original and free ssh 1.2.12 release by
@@ -636,8 +632,4 @@ AUTHORS
636 versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support 632 versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support
637 for privilege separation. 633 for privilege separation.
638 634
639CAVEATS 635OpenBSD 5.6 July 3, 2014 OpenBSD 5.6
640 System security is not improved unless rshd, rlogind, and rexecd are
641 disabled (thus completely disabling rlogin and rsh into the machine).
642
643OpenBSD 5.5 December 7, 2013 OpenBSD 5.5
diff --git a/sshd.8 b/sshd.8
index cba168a8e..f8f9eac37 100644
--- a/sshd.8
+++ b/sshd.8
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd.8,v 1.273 2013/12/07 11:58:46 naddy Exp $ 36.\" $OpenBSD: sshd.8,v 1.276 2014/07/03 22:40:43 djm Exp $
37.Dd $Mdocdate: December 7 2013 $ 37.Dd $Mdocdate: July 3 2014 $
38.Dt SSHD 8 38.Dt SSHD 8
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -60,10 +60,7 @@
60.Nm 60.Nm
61(OpenSSH Daemon) is the daemon program for 61(OpenSSH Daemon) is the daemon program for
62.Xr ssh 1 . 62.Xr ssh 1 .
63Together these programs replace 63Together these programs replace rlogin and rsh,
64.Xr rlogin 1
65and
66.Xr rsh 1 ,
67and provide secure encrypted communications between two untrusted hosts 64and provide secure encrypted communications between two untrusted hosts
68over an insecure network. 65over an insecure network.
69.Pp 66.Pp
@@ -414,7 +411,10 @@ Changes to user's home directory.
414.It 411.It
415If 412If
416.Pa ~/.ssh/rc 413.Pa ~/.ssh/rc
417exists, runs it; else if 414exists and the
415.Xr sshd_config 5
416.Cm PermitUserRC
417option is set, runs it; else if
418.Pa /etc/ssh/sshrc 418.Pa /etc/ssh/sshrc
419exists, runs 419exists, runs
420it; otherwise runs xauth. 420it; otherwise runs xauth.
@@ -979,14 +979,3 @@ Markus Friedl contributed the support for SSH
979protocol versions 1.5 and 2.0. 979protocol versions 1.5 and 2.0.
980Niels Provos and Markus Friedl contributed support 980Niels Provos and Markus Friedl contributed support
981for privilege separation. 981for privilege separation.
982.Sh CAVEATS
983System security is not improved unless
984.Nm rshd ,
985.Nm rlogind ,
986and
987.Nm rexecd
988are disabled (thus completely disabling
989.Xr rlogin
990and
991.Xr rsh
992into the machine).
diff --git a/sshd.c b/sshd.c
index fe78d7b66..23d5a64f0 100644
--- a/sshd.c
+++ b/sshd.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshd.c,v 1.420 2014/02/26 21:53:37 markus Exp $ */ 1/* $OpenBSD: sshd.c,v 1.428 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -72,10 +72,12 @@
72#include <string.h> 72#include <string.h>
73#include <unistd.h> 73#include <unistd.h>
74 74
75#ifdef WITH_OPENSSL
75#include <openssl/dh.h> 76#include <openssl/dh.h>
76#include <openssl/bn.h> 77#include <openssl/bn.h>
77#include <openssl/rand.h> 78#include <openssl/rand.h>
78#include "openbsd-compat/openssl-compat.h" 79#include "openbsd-compat/openssl-compat.h"
80#endif
79 81
80#ifdef HAVE_SECUREWARE 82#ifdef HAVE_SECUREWARE
81#include <sys/security.h> 83#include <sys/security.h>
@@ -91,6 +93,7 @@
91#include "packet.h" 93#include "packet.h"
92#include "log.h" 94#include "log.h"
93#include "buffer.h" 95#include "buffer.h"
96#include "misc.h"
94#include "servconf.h" 97#include "servconf.h"
95#include "uidswap.h" 98#include "uidswap.h"
96#include "compat.h" 99#include "compat.h"
@@ -98,7 +101,6 @@
98#include "digest.h" 101#include "digest.h"
99#include "key.h" 102#include "key.h"
100#include "kex.h" 103#include "kex.h"
101#include "dh.h"
102#include "myproposal.h" 104#include "myproposal.h"
103#include "authfile.h" 105#include "authfile.h"
104#include "pathnames.h" 106#include "pathnames.h"
@@ -107,7 +109,6 @@
107#include "hostfile.h" 109#include "hostfile.h"
108#include "auth.h" 110#include "auth.h"
109#include "authfd.h" 111#include "authfd.h"
110#include "misc.h"
111#include "msg.h" 112#include "msg.h"
112#include "dispatch.h" 113#include "dispatch.h"
113#include "channels.h" 114#include "channels.h"
@@ -267,7 +268,9 @@ struct passwd *privsep_pw = NULL;
267void destroy_sensitive_data(void); 268void destroy_sensitive_data(void);
268void demote_sensitive_data(void); 269void demote_sensitive_data(void);
269 270
271#ifdef WITH_SSH1
270static void do_ssh1_kex(void); 272static void do_ssh1_kex(void);
273#endif
271static void do_ssh2_kex(void); 274static void do_ssh2_kex(void);
272 275
273/* 276/*
@@ -943,7 +946,13 @@ static void
943usage(void) 946usage(void)
944{ 947{
945 fprintf(stderr, "%s, %s\n", 948 fprintf(stderr, "%s, %s\n",
946 SSH_RELEASE, SSLeay_version(SSLEAY_VERSION)); 949 SSH_RELEASE,
950#ifdef WITH_OPENSSL
951 SSLeay_version(SSLEAY_VERSION)
952#else
953 "without OpenSSL"
954#endif
955 );
947 fprintf(stderr, 956 fprintf(stderr,
948"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n" 957"usage: sshd [-46DdeiqTt] [-b bits] [-C connection_spec] [-c host_cert_file]\n"
949" [-E log_file] [-f config_file] [-g login_grace_time]\n" 958" [-E log_file] [-f config_file] [-g login_grace_time]\n"
@@ -976,6 +985,7 @@ send_rexec_state(int fd, Buffer *conf)
976 buffer_init(&m); 985 buffer_init(&m);
977 buffer_put_cstring(&m, buffer_ptr(conf)); 986 buffer_put_cstring(&m, buffer_ptr(conf));
978 987
988#ifdef WITH_SSH1
979 if (sensitive_data.server_key != NULL && 989 if (sensitive_data.server_key != NULL &&
980 sensitive_data.server_key->type == KEY_RSA1) { 990 sensitive_data.server_key->type == KEY_RSA1) {
981 buffer_put_int(&m, 1); 991 buffer_put_int(&m, 1);
@@ -986,6 +996,7 @@ send_rexec_state(int fd, Buffer *conf)
986 buffer_put_bignum(&m, sensitive_data.server_key->rsa->p); 996 buffer_put_bignum(&m, sensitive_data.server_key->rsa->p);
987 buffer_put_bignum(&m, sensitive_data.server_key->rsa->q); 997 buffer_put_bignum(&m, sensitive_data.server_key->rsa->q);
988 } else 998 } else
999#endif
989 buffer_put_int(&m, 0); 1000 buffer_put_int(&m, 0);
990 1001
991#ifndef OPENSSL_PRNG_ONLY 1002#ifndef OPENSSL_PRNG_ONLY
@@ -1022,6 +1033,7 @@ recv_rexec_state(int fd, Buffer *conf)
1022 free(cp); 1033 free(cp);
1023 1034
1024 if (buffer_get_int(&m)) { 1035 if (buffer_get_int(&m)) {
1036#ifdef WITH_SSH1
1025 if (sensitive_data.server_key != NULL) 1037 if (sensitive_data.server_key != NULL)
1026 key_free(sensitive_data.server_key); 1038 key_free(sensitive_data.server_key);
1027 sensitive_data.server_key = key_new_private(KEY_RSA1); 1039 sensitive_data.server_key = key_new_private(KEY_RSA1);
@@ -1031,8 +1043,13 @@ recv_rexec_state(int fd, Buffer *conf)
1031 buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp); 1043 buffer_get_bignum(&m, sensitive_data.server_key->rsa->iqmp);
1032 buffer_get_bignum(&m, sensitive_data.server_key->rsa->p); 1044 buffer_get_bignum(&m, sensitive_data.server_key->rsa->p);
1033 buffer_get_bignum(&m, sensitive_data.server_key->rsa->q); 1045 buffer_get_bignum(&m, sensitive_data.server_key->rsa->q);
1034 rsa_generate_additional_parameters( 1046 if (rsa_generate_additional_parameters(
1035 sensitive_data.server_key->rsa); 1047 sensitive_data.server_key->rsa) != 0)
1048 fatal("%s: rsa_generate_additional_parameters "
1049 "error", __func__);
1050#else
1051 fatal("ssh1 not supported");
1052#endif
1036 } 1053 }
1037 1054
1038#ifndef OPENSSL_PRNG_ONLY 1055#ifndef OPENSSL_PRNG_ONLY
@@ -1555,7 +1572,9 @@ main(int ac, char **av)
1555 else 1572 else
1556 closefrom(REEXEC_DEVCRYPTO_RESERVED_FD); 1573 closefrom(REEXEC_DEVCRYPTO_RESERVED_FD);
1557 1574
1575#ifdef WITH_OPENSSL
1558 OpenSSL_add_all_algorithms(); 1576 OpenSSL_add_all_algorithms();
1577#endif
1559 1578
1560 /* If requested, redirect the logs to the specified logfile. */ 1579 /* If requested, redirect the logs to the specified logfile. */
1561 if (logfile != NULL) { 1580 if (logfile != NULL) {
@@ -1660,7 +1679,12 @@ main(int ac, char **av)
1660 } 1679 }
1661 1680
1662 debug("sshd version %s, %s", SSH_VERSION, 1681 debug("sshd version %s, %s", SSH_VERSION,
1663 SSLeay_version(SSLEAY_VERSION)); 1682#ifdef WITH_OPENSSL
1683 SSLeay_version(SSLEAY_VERSION)
1684#else
1685 "without OpenSSL"
1686#endif
1687 );
1664 1688
1665 /* Store privilege separation user for later use if required. */ 1689 /* Store privilege separation user for later use if required. */
1666 if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) { 1690 if ((privsep_pw = getpwnam(SSH_PRIVSEP_USER)) == NULL) {
@@ -1785,6 +1809,8 @@ main(int ac, char **av)
1785 debug("host certificate: #%d type %d %s", j, key->type, 1809 debug("host certificate: #%d type %d %s", j, key->type,
1786 key_type(key)); 1810 key_type(key));
1787 } 1811 }
1812
1813#ifdef WITH_SSH1
1788 /* Check certain values for sanity. */ 1814 /* Check certain values for sanity. */
1789 if (options.protocol & SSH_PROTO_1) { 1815 if (options.protocol & SSH_PROTO_1) {
1790 if (options.server_key_bits < 512 || 1816 if (options.server_key_bits < 512 ||
@@ -1809,6 +1835,7 @@ main(int ac, char **av)
1809 options.server_key_bits); 1835 options.server_key_bits);
1810 } 1836 }
1811 } 1837 }
1838#endif
1812 1839
1813 if (use_privsep) { 1840 if (use_privsep) {
1814 struct stat st; 1841 struct stat st;
@@ -2174,8 +2201,12 @@ main(int ac, char **av)
2174 do_ssh2_kex(); 2201 do_ssh2_kex();
2175 do_authentication2(authctxt); 2202 do_authentication2(authctxt);
2176 } else { 2203 } else {
2204#ifdef WITH_SSH1
2177 do_ssh1_kex(); 2205 do_ssh1_kex();
2178 do_authentication(authctxt); 2206 do_authentication(authctxt);
2207#else
2208 fatal("ssh1 not supported");
2209#endif
2179 } 2210 }
2180 /* 2211 /*
2181 * If we use privilege separation, the unprivileged child transfers 2212 * If we use privilege separation, the unprivileged child transfers
@@ -2259,6 +2290,7 @@ main(int ac, char **av)
2259 exit(0); 2290 exit(0);
2260} 2291}
2261 2292
2293#ifdef WITH_SSH1
2262/* 2294/*
2263 * Decrypt session_key_int using our private server key and private host key 2295 * Decrypt session_key_int using our private server key and private host key
2264 * (key with larger modulus first). 2296 * (key with larger modulus first).
@@ -2282,10 +2314,10 @@ ssh1_session_key(BIGNUM *session_key_int)
2282 SSH_KEY_BITS_RESERVED); 2314 SSH_KEY_BITS_RESERVED);
2283 } 2315 }
2284 if (rsa_private_decrypt(session_key_int, session_key_int, 2316 if (rsa_private_decrypt(session_key_int, session_key_int,
2285 sensitive_data.server_key->rsa) <= 0) 2317 sensitive_data.server_key->rsa) != 0)
2286 rsafail++; 2318 rsafail++;
2287 if (rsa_private_decrypt(session_key_int, session_key_int, 2319 if (rsa_private_decrypt(session_key_int, session_key_int,
2288 sensitive_data.ssh1_host_key->rsa) <= 0) 2320 sensitive_data.ssh1_host_key->rsa) != 0)
2289 rsafail++; 2321 rsafail++;
2290 } else { 2322 } else {
2291 /* Host key has bigger modulus (or they are equal). */ 2323 /* Host key has bigger modulus (or they are equal). */
@@ -2300,14 +2332,15 @@ ssh1_session_key(BIGNUM *session_key_int)
2300 SSH_KEY_BITS_RESERVED); 2332 SSH_KEY_BITS_RESERVED);
2301 } 2333 }
2302 if (rsa_private_decrypt(session_key_int, session_key_int, 2334 if (rsa_private_decrypt(session_key_int, session_key_int,
2303 sensitive_data.ssh1_host_key->rsa) < 0) 2335 sensitive_data.ssh1_host_key->rsa) != 0)
2304 rsafail++; 2336 rsafail++;
2305 if (rsa_private_decrypt(session_key_int, session_key_int, 2337 if (rsa_private_decrypt(session_key_int, session_key_int,
2306 sensitive_data.server_key->rsa) < 0) 2338 sensitive_data.server_key->rsa) != 0)
2307 rsafail++; 2339 rsafail++;
2308 } 2340 }
2309 return (rsafail); 2341 return (rsafail);
2310} 2342}
2343
2311/* 2344/*
2312 * SSH1 key exchange 2345 * SSH1 key exchange
2313 */ 2346 */
@@ -2485,6 +2518,7 @@ do_ssh1_kex(void)
2485 packet_send(); 2518 packet_send();
2486 packet_write_wait(); 2519 packet_write_wait();
2487} 2520}
2521#endif
2488 2522
2489void 2523void
2490sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen, 2524sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen,
@@ -2509,6 +2543,7 @@ sshd_hostkey_sign(Key *privkey, Key *pubkey, u_char **signature, u_int *slen,
2509static void 2543static void
2510do_ssh2_kex(void) 2544do_ssh2_kex(void)
2511{ 2545{
2546 char *myproposal[PROPOSAL_MAX] = { KEX_SERVER };
2512 Kex *kex; 2547 Kex *kex;
2513 2548
2514 if (options.ciphers != NULL) { 2549 if (options.ciphers != NULL) {
@@ -2588,11 +2623,13 @@ do_ssh2_kex(void)
2588 2623
2589 /* start key exchange */ 2624 /* start key exchange */
2590 kex = kex_setup(myproposal); 2625 kex = kex_setup(myproposal);
2626#ifdef WITH_OPENSSL
2591 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server; 2627 kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
2592 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server; 2628 kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
2593 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server; 2629 kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
2594 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server; 2630 kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
2595 kex->kex[KEX_ECDH_SHA2] = kexecdh_server; 2631 kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
2632#endif
2596 kex->kex[KEX_C25519_SHA256] = kexc25519_server; 2633 kex->kex[KEX_C25519_SHA256] = kexc25519_server;
2597#ifdef GSSAPI 2634#ifdef GSSAPI
2598 if (options.gss_keyex) { 2635 if (options.gss_keyex) {
@@ -2632,7 +2669,8 @@ cleanup_exit(int i)
2632{ 2669{
2633 if (the_authctxt) { 2670 if (the_authctxt) {
2634 do_cleanup(the_authctxt); 2671 do_cleanup(the_authctxt);
2635 if (use_privsep && privsep_is_preauth && pmonitor->m_pid > 1) { 2672 if (use_privsep && privsep_is_preauth &&
2673 pmonitor != NULL && pmonitor->m_pid > 1) {
2636 debug("Killing privsep child %d", pmonitor->m_pid); 2674 debug("Killing privsep child %d", pmonitor->m_pid);
2637 if (kill(pmonitor->m_pid, SIGKILL) != 0 && 2675 if (kill(pmonitor->m_pid, SIGKILL) != 0 &&
2638 errno != ESRCH) 2676 errno != ESRCH)
diff --git a/sshd_config.0 b/sshd_config.0
index 413c26008..1c82d449f 100644
--- a/sshd_config.0
+++ b/sshd_config.0
@@ -1,4 +1,4 @@
1SSHD_CONFIG(5) OpenBSD Programmer's Manual SSHD_CONFIG(5) 1SSHD_CONFIG(5) File Formats Manual SSHD_CONFIG(5)
2 2
3NAME 3NAME
4 sshd_config - OpenSSH SSH daemon configuration file 4 sshd_config - OpenSSH SSH daemon configuration file
@@ -62,6 +62,16 @@ DESCRIPTION
62 are also denied shell access, as they can always install their 62 are also denied shell access, as they can always install their
63 own forwarders. 63 own forwarders.
64 64
65 AllowStreamLocalForwarding
66 Specifies whether StreamLocal (Unix-domain socket) forwarding is
67 permitted. The available options are ``yes'' or ``all'' to allow
68 StreamLocal forwarding, ``no'' to prevent all StreamLocal
69 forwarding, ``local'' to allow local (from the perspective of
70 ssh(1)) forwarding only or ``remote'' to allow remote forwarding
71 only. The default is ``yes''. Note that disabling StreamLocal
72 forwarding does not improve security unless users are also denied
73 shell access, as they can always install their own forwarders.
74
65 AllowUsers 75 AllowUsers
66 This keyword can be followed by a list of user name patterns, 76 This keyword can be followed by a list of user name patterns,
67 separated by spaces. If specified, login is allowed only for 77 separated by spaces. If specified, login is allowed only for
@@ -168,7 +178,7 @@ DESCRIPTION
168 178
169 ChallengeResponseAuthentication 179 ChallengeResponseAuthentication
170 Specifies whether challenge-response authentication is allowed 180 Specifies whether challenge-response authentication is allowed
171 (e.g. via PAM or though authentication styles supported in 181 (e.g. via PAM or through authentication styles supported in
172 login.conf(5)) The default is ``yes''. 182 login.conf(5)) The default is ``yes''.
173 183
174 ChrootDirectory 184 ChrootDirectory
@@ -191,8 +201,9 @@ DESCRIPTION
191 stderr(4), arandom(4) and tty(4) devices. For file transfer 201 stderr(4), arandom(4) and tty(4) devices. For file transfer
192 sessions using ``sftp'', no additional configuration of the 202 sessions using ``sftp'', no additional configuration of the
193 environment is necessary if the in-process sftp server is used, 203 environment is necessary if the in-process sftp server is used,
194 though sessions which use logging do require /dev/log inside the 204 though sessions which use logging may require /dev/log inside the
195 chroot directory (see sftp-server(8) for details). 205 chroot directory on some operating systems (see sftp-server(8)
206 for details).
196 207
197 The default is not to chroot(2). 208 The default is not to chroot(2).
198 209
@@ -200,19 +211,27 @@ DESCRIPTION
200 Specifies the ciphers allowed for protocol version 2. Multiple 211 Specifies the ciphers allowed for protocol version 2. Multiple
201 ciphers must be comma-separated. The supported ciphers are: 212 ciphers must be comma-separated. The supported ciphers are:
202 213
203 ``3des-cbc'', ``aes128-cbc'', ``aes192-cbc'', ``aes256-cbc'', 214 3des-cbc
204 ``aes128-ctr'', ``aes192-ctr'', ``aes256-ctr'', 215 aes128-cbc
205 ``aes128-gcm@openssh.com'', ``aes256-gcm@openssh.com'', 216 aes192-cbc
206 ``arcfour128'', ``arcfour256'', ``arcfour'', ``blowfish-cbc'', 217 aes256-cbc
207 ``cast128-cbc'', and ``chacha20-poly1305@openssh.com''. 218 aes128-ctr
219 aes192-ctr
220 aes256-ctr
221 aes128-gcm@openssh.com
222 aes256-gcm@openssh.com
223 arcfour
224 arcfour128
225 arcfour256
226 blowfish-cbc
227 cast128-cbc
228 chacha20-poly1305@openssh.com
208 229
209 The default is: 230 The default is:
210 231
211 aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, 232 aes128-ctr,aes192-ctr,aes256-ctr,
212 aes128-gcm@openssh.com,aes256-gcm@openssh.com, 233 aes128-gcm@openssh.com,aes256-gcm@openssh.com,
213 chacha20-poly1305@openssh.com, 234 chacha20-poly1305@openssh.com
214 aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
215 aes256-cbc,arcfour
216 235
217 The list of available ciphers may also be obtained using the -Q 236 The list of available ciphers may also be obtained using the -Q
218 option of ssh(1). 237 option of ssh(1).
@@ -403,14 +422,24 @@ DESCRIPTION
403 422
404 KexAlgorithms 423 KexAlgorithms
405 Specifies the available KEX (Key Exchange) algorithms. Multiple 424 Specifies the available KEX (Key Exchange) algorithms. Multiple
406 algorithms must be comma-separated. The default is 425 algorithms must be comma-separated. The supported algorithms
426 are:
427
428 curve25519-sha256@libssh.org
429 diffie-hellman-group1-sha1
430 diffie-hellman-group14-sha1
431 diffie-hellman-group-exchange-sha1
432 diffie-hellman-group-exchange-sha256
433 ecdh-sha2-nistp256
434 ecdh-sha2-nistp384
435 ecdh-sha2-nistp521
436
437 The default is:
407 438
408 curve25519-sha256@libssh.org, 439 curve25519-sha256@libssh.org,
409 ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, 440 ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
410 diffie-hellman-group-exchange-sha256, 441 diffie-hellman-group-exchange-sha256,
411 diffie-hellman-group-exchange-sha1, 442 diffie-hellman-group14-sha1
412 diffie-hellman-group14-sha1,
413 diffie-hellman-group1-sha1
414 443
415 KeyRegenerationInterval 444 KeyRegenerationInterval
416 In protocol version 1, the ephemeral server key is automatically 445 In protocol version 1, the ephemeral server key is automatically
@@ -452,16 +481,33 @@ DESCRIPTION
452 data integrity protection. Multiple algorithms must be comma- 481 data integrity protection. Multiple algorithms must be comma-
453 separated. The algorithms that contain ``-etm'' calculate the 482 separated. The algorithms that contain ``-etm'' calculate the
454 MAC after encryption (encrypt-then-mac). These are considered 483 MAC after encryption (encrypt-then-mac). These are considered
455 safer and their use recommended. The default is: 484 safer and their use recommended. The supported MACs are:
485
486 hmac-md5
487 hmac-md5-96
488 hmac-ripemd160
489 hmac-sha1
490 hmac-sha1-96
491 hmac-sha2-256
492 hmac-sha2-512
493 umac-64@openssh.com
494 umac-128@openssh.com
495 hmac-md5-etm@openssh.com
496 hmac-md5-96-etm@openssh.com
497 hmac-ripemd160-etm@openssh.com
498 hmac-sha1-etm@openssh.com
499 hmac-sha1-96-etm@openssh.com
500 hmac-sha2-256-etm@openssh.com
501 hmac-sha2-512-etm@openssh.com
502 umac-64-etm@openssh.com
503 umac-128-etm@openssh.com
504
505 The default is:
456 506
457 hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
458 umac-64-etm@openssh.com,umac-128-etm@openssh.com, 507 umac-64-etm@openssh.com,umac-128-etm@openssh.com,
459 hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, 508 hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
460 hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, 509 umac-64@openssh.com,umac-128@openssh.com,
461 hmac-md5-96-etm@openssh.com, 510 hmac-sha2-256,hmac-sha2-512
462 hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
463 hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
464 hmac-sha1-96,hmac-md5-96
465 511
466 Match Introduces a conditional block. If all of the criteria on the 512 Match Introduces a conditional block. If all of the criteria on the
467 Match line are satisfied, the keywords on the following lines 513 Match line are satisfied, the keywords on the following lines
@@ -496,7 +542,7 @@ DESCRIPTION
496 KbdInteractiveAuthentication, KerberosAuthentication, 542 KbdInteractiveAuthentication, KerberosAuthentication,
497 MaxAuthTries, MaxSessions, PasswordAuthentication, 543 MaxAuthTries, MaxSessions, PasswordAuthentication,
498 PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY, 544 PermitEmptyPasswords, PermitOpen, PermitRootLogin, PermitTTY,
499 PermitTunnel, PubkeyAuthentication, RekeyLimit, 545 PermitTunnel, PermitUserRC, PubkeyAuthentication, RekeyLimit,
500 RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset, 546 RhostsRSAAuthentication, RSAAuthentication, X11DisplayOffset,
501 X11Forwarding and X11UseLocalHost. 547 X11Forwarding and X11UseLocalHost.
502 548
@@ -580,6 +626,10 @@ DESCRIPTION
580 bypass access restrictions in some configurations using 626 bypass access restrictions in some configurations using
581 mechanisms such as LD_PRELOAD. 627 mechanisms such as LD_PRELOAD.
582 628
629 PermitUserRC
630 Specifies whether any ~/.ssh/rc file is executed. The default is
631 ``yes''.
632
583 PidFile 633 PidFile
584 Specifies the file that contains the process ID of the SSH 634 Specifies the file that contains the process ID of the SSH
585 daemon. The default is /var/run/sshd.pid. 635 daemon. The default is /var/run/sshd.pid.
@@ -650,6 +700,27 @@ DESCRIPTION
650 Defines the number of bits in the ephemeral protocol version 1 700 Defines the number of bits in the ephemeral protocol version 1
651 server key. The minimum value is 512, and the default is 1024. 701 server key. The minimum value is 512, and the default is 1024.
652 702
703 StreamLocalBindMask
704 Sets the octal file creation mode mask (umask) used when creating
705 a Unix-domain socket file for local or remote port forwarding.
706 This option is only used for port forwarding to a Unix-domain
707 socket file.
708
709 The default value is 0177, which creates a Unix-domain socket
710 file that is readable and writable only by the owner. Note that
711 not all operating systems honor the file mode on Unix-domain
712 socket files.
713
714 StreamLocalBindUnlink
715 Specifies whether to remove an existing Unix-domain socket file
716 for local or remote port forwarding before creating a new one.
717 If the socket file already exists and StreamLocalBindUnlink is
718 not enabled, sshd will be unable to forward the port to the Unix-
719 domain socket file. This option is only used for port forwarding
720 to a Unix-domain socket file.
721
722 The argument must be ``yes'' or ``no''. The default is ``no''.
723
653 StrictModes 724 StrictModes
654 Specifies whether sshd(8) should check file modes and ownership 725 Specifies whether sshd(8) should check file modes and ownership
655 of the user's files and home directory before accepting login. 726 of the user's files and home directory before accepting login.
@@ -832,4 +903,4 @@ AUTHORS
832 versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support 903 versions 1.5 and 2.0. Niels Provos and Markus Friedl contributed support
833 for privilege separation. 904 for privilege separation.
834 905
835OpenBSD 5.5 February 27, 2014 OpenBSD 5.5 906OpenBSD 5.6 July 28, 2014 OpenBSD 5.6
diff --git a/sshd_config.5 b/sshd_config.5
index 90fd3f4a8..7aa7b4733 100644
--- a/sshd_config.5
+++ b/sshd_config.5
@@ -33,8 +33,8 @@
33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 33.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 34.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
35.\" 35.\"
36.\" $OpenBSD: sshd_config.5,v 1.172 2014/02/27 22:47:07 djm Exp $ 36.\" $OpenBSD: sshd_config.5,v 1.176 2014/07/28 15:40:08 schwarze Exp $
37.Dd $Mdocdate: February 27 2014 $ 37.Dd $Mdocdate: July 28 2014 $
38.Dt SSHD_CONFIG 5 38.Dt SSHD_CONFIG 5
39.Os 39.Os
40.Sh NAME 40.Sh NAME
@@ -165,6 +165,26 @@ The default is
165Note that disabling TCP forwarding does not improve security unless 165Note that disabling TCP forwarding does not improve security unless
166users are also denied shell access, as they can always install their 166users are also denied shell access, as they can always install their
167own forwarders. 167own forwarders.
168.It Cm AllowStreamLocalForwarding
169Specifies whether StreamLocal (Unix-domain socket) forwarding is permitted.
170The available options are
171.Dq yes
172or
173.Dq all
174to allow StreamLocal forwarding,
175.Dq no
176to prevent all StreamLocal forwarding,
177.Dq local
178to allow local (from the perspective of
179.Xr ssh 1 )
180forwarding only or
181.Dq remote
182to allow remote forwarding only.
183The default is
184.Dq yes .
185Note that disabling StreamLocal forwarding does not improve security unless
186users are also denied shell access, as they can always install their
187own forwarders.
168.It Cm AllowUsers 188.It Cm AllowUsers
169This keyword can be followed by a list of user name patterns, separated 189This keyword can be followed by a list of user name patterns, separated
170by spaces. 190by spaces.
@@ -348,9 +368,9 @@ For file transfer sessions using
348.Dq sftp , 368.Dq sftp ,
349no additional configuration of the environment is necessary if the 369no additional configuration of the environment is necessary if the
350in-process sftp server is used, 370in-process sftp server is used,
351though sessions which use logging do require 371though sessions which use logging may require
352.Pa /dev/log 372.Pa /dev/log
353inside the chroot directory (see 373inside the chroot directory on some operating systems (see
354.Xr sftp-server 8 374.Xr sftp-server 8
355for details). 375for details).
356.Pp 376.Pp
@@ -361,30 +381,44 @@ Specifies the ciphers allowed for protocol version 2.
361Multiple ciphers must be comma-separated. 381Multiple ciphers must be comma-separated.
362The supported ciphers are: 382The supported ciphers are:
363.Pp 383.Pp
364.Dq 3des-cbc , 384.Bl -item -compact -offset indent
365.Dq aes128-cbc , 385.It
366.Dq aes192-cbc , 3863des-cbc
367.Dq aes256-cbc , 387.It
368.Dq aes128-ctr , 388aes128-cbc
369.Dq aes192-ctr , 389.It
370.Dq aes256-ctr , 390aes192-cbc
371.Dq aes128-gcm@openssh.com , 391.It
372.Dq aes256-gcm@openssh.com , 392aes256-cbc
373.Dq arcfour128 , 393.It
374.Dq arcfour256 , 394aes128-ctr
375.Dq arcfour , 395.It
376.Dq blowfish-cbc , 396aes192-ctr
377.Dq cast128-cbc , 397.It
378and 398aes256-ctr
379.Dq chacha20-poly1305@openssh.com . 399.It
400aes128-gcm@openssh.com
401.It
402aes256-gcm@openssh.com
403.It
404arcfour
405.It
406arcfour128
407.It
408arcfour256
409.It
410blowfish-cbc
411.It
412cast128-cbc
413.It
414chacha20-poly1305@openssh.com
415.El
380.Pp 416.Pp
381The default is: 417The default is:
382.Bd -literal -offset 3n 418.Bd -literal -offset indent
383aes128-ctr,aes192-ctr,aes256-ctr,arcfour256,arcfour128, 419aes128-ctr,aes192-ctr,aes256-ctr,
384aes128-gcm@openssh.com,aes256-gcm@openssh.com, 420aes128-gcm@openssh.com,aes256-gcm@openssh.com,
385chacha20-poly1305@openssh.com, 421chacha20-poly1305@openssh.com
386aes128-cbc,3des-cbc,blowfish-cbc,cast128-cbc,aes192-cbc,
387aes256-cbc,arcfour
388.Ed 422.Ed
389.Pp 423.Pp
390The list of available ciphers may also be obtained using the 424The list of available ciphers may also be obtained using the
@@ -729,14 +763,33 @@ The default is
729.It Cm KexAlgorithms 763.It Cm KexAlgorithms
730Specifies the available KEX (Key Exchange) algorithms. 764Specifies the available KEX (Key Exchange) algorithms.
731Multiple algorithms must be comma-separated. 765Multiple algorithms must be comma-separated.
732The default is 766The supported algorithms are:
767.Pp
768.Bl -item -compact -offset indent
769.It
770curve25519-sha256@libssh.org
771.It
772diffie-hellman-group1-sha1
773.It
774diffie-hellman-group14-sha1
775.It
776diffie-hellman-group-exchange-sha1
777.It
778diffie-hellman-group-exchange-sha256
779.It
780ecdh-sha2-nistp256
781.It
782ecdh-sha2-nistp384
783.It
784ecdh-sha2-nistp521
785.El
786.Pp
787The default is:
733.Bd -literal -offset indent 788.Bd -literal -offset indent
734curve25519-sha256@libssh.org, 789curve25519-sha256@libssh.org,
735ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521, 790ecdh-sha2-nistp256,ecdh-sha2-nistp384,ecdh-sha2-nistp521,
736diffie-hellman-group-exchange-sha256, 791diffie-hellman-group-exchange-sha256,
737diffie-hellman-group-exchange-sha1, 792diffie-hellman-group14-sha1
738diffie-hellman-group14-sha1,
739diffie-hellman-group1-sha1
740.Ed 793.Ed
741.It Cm KeyRegenerationInterval 794.It Cm KeyRegenerationInterval
742In protocol version 1, the ephemeral server key is automatically regenerated 795In protocol version 1, the ephemeral server key is automatically regenerated
@@ -808,16 +861,53 @@ The algorithms that contain
808.Dq -etm 861.Dq -etm
809calculate the MAC after encryption (encrypt-then-mac). 862calculate the MAC after encryption (encrypt-then-mac).
810These are considered safer and their use recommended. 863These are considered safer and their use recommended.
864The supported MACs are:
865.Pp
866.Bl -item -compact -offset indent
867.It
868hmac-md5
869.It
870hmac-md5-96
871.It
872hmac-ripemd160
873.It
874hmac-sha1
875.It
876hmac-sha1-96
877.It
878hmac-sha2-256
879.It
880hmac-sha2-512
881.It
882umac-64@openssh.com
883.It
884umac-128@openssh.com
885.It
886hmac-md5-etm@openssh.com
887.It
888hmac-md5-96-etm@openssh.com
889.It
890hmac-ripemd160-etm@openssh.com
891.It
892hmac-sha1-etm@openssh.com
893.It
894hmac-sha1-96-etm@openssh.com
895.It
896hmac-sha2-256-etm@openssh.com
897.It
898hmac-sha2-512-etm@openssh.com
899.It
900umac-64-etm@openssh.com
901.It
902umac-128-etm@openssh.com
903.El
904.Pp
811The default is: 905The default is:
812.Bd -literal -offset indent 906.Bd -literal -offset indent
813hmac-md5-etm@openssh.com,hmac-sha1-etm@openssh.com,
814umac-64-etm@openssh.com,umac-128-etm@openssh.com, 907umac-64-etm@openssh.com,umac-128-etm@openssh.com,
815hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com, 908hmac-sha2-256-etm@openssh.com,hmac-sha2-512-etm@openssh.com,
816hmac-ripemd160-etm@openssh.com,hmac-sha1-96-etm@openssh.com, 909umac-64@openssh.com,umac-128@openssh.com,
817hmac-md5-96-etm@openssh.com, 910hmac-sha2-256,hmac-sha2-512
818hmac-md5,hmac-sha1,umac-64@openssh.com,umac-128@openssh.com,
819hmac-sha2-256,hmac-sha2-512,hmac-ripemd160,
820hmac-sha1-96,hmac-md5-96
821.Ed 911.Ed
822.It Cm Match 912.It Cm Match
823Introduces a conditional block. 913Introduces a conditional block.
@@ -899,6 +989,7 @@ Available keywords are
899.Cm PermitRootLogin , 989.Cm PermitRootLogin ,
900.Cm PermitTTY , 990.Cm PermitTTY ,
901.Cm PermitTunnel , 991.Cm PermitTunnel ,
992.Cm PermitUserRC ,
902.Cm PubkeyAuthentication , 993.Cm PubkeyAuthentication ,
903.Cm RekeyLimit , 994.Cm RekeyLimit ,
904.Cm RhostsRSAAuthentication , 995.Cm RhostsRSAAuthentication ,
@@ -1047,6 +1138,12 @@ The default is
1047Enabling environment processing may enable users to bypass access 1138Enabling environment processing may enable users to bypass access
1048restrictions in some configurations using mechanisms such as 1139restrictions in some configurations using mechanisms such as
1049.Ev LD_PRELOAD . 1140.Ev LD_PRELOAD .
1141.It Cm PermitUserRC
1142Specifies whether any
1143.Pa ~/.ssh/rc
1144file is executed.
1145The default is
1146.Dq yes .
1050.It Cm PidFile 1147.It Cm PidFile
1051Specifies the file that contains the process ID of the 1148Specifies the file that contains the process ID of the
1052SSH daemon. 1149SSH daemon.
@@ -1151,6 +1248,33 @@ This option applies to protocol version 1 only.
1151.It Cm ServerKeyBits 1248.It Cm ServerKeyBits
1152Defines the number of bits in the ephemeral protocol version 1 server key. 1249Defines the number of bits in the ephemeral protocol version 1 server key.
1153The minimum value is 512, and the default is 1024. 1250The minimum value is 512, and the default is 1024.
1251.It Cm StreamLocalBindMask
1252Sets the octal file creation mode mask
1253.Pq umask
1254used when creating a Unix-domain socket file for local or remote
1255port forwarding.
1256This option is only used for port forwarding to a Unix-domain socket file.
1257.Pp
1258The default value is 0177, which creates a Unix-domain socket file that is
1259readable and writable only by the owner.
1260Note that not all operating systems honor the file mode on Unix-domain
1261socket files.
1262.It Cm StreamLocalBindUnlink
1263Specifies whether to remove an existing Unix-domain socket file for local
1264or remote port forwarding before creating a new one.
1265If the socket file already exists and
1266.Cm StreamLocalBindUnlink
1267is not enabled,
1268.Nm sshd
1269will be unable to forward the port to the Unix-domain socket file.
1270This option is only used for port forwarding to a Unix-domain socket file.
1271.Pp
1272The argument must be
1273.Dq yes
1274or
1275.Dq no .
1276The default is
1277.Dq no .
1154.It Cm StrictModes 1278.It Cm StrictModes
1155Specifies whether 1279Specifies whether
1156.Xr sshd 8 1280.Xr sshd 8
diff --git a/ssherr.c b/ssherr.c
new file mode 100644
index 000000000..49fbb71de
--- /dev/null
+++ b/ssherr.c
@@ -0,0 +1,131 @@
1/* $OpenBSD: ssherr.c,v 1.1 2014/04/30 05:29:56 djm Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#include <errno.h>
19#include <string.h>
20#include "ssherr.h"
21
22const char *
23ssh_err(int n)
24{
25 switch (n) {
26 case SSH_ERR_SUCCESS:
27 return "success";
28 case SSH_ERR_INTERNAL_ERROR:
29 return "unexpected internal error";
30 case SSH_ERR_ALLOC_FAIL:
31 return "memory allocation failed";
32 case SSH_ERR_MESSAGE_INCOMPLETE:
33 return "incomplete message";
34 case SSH_ERR_INVALID_FORMAT:
35 return "invalid format";
36 case SSH_ERR_BIGNUM_IS_NEGATIVE:
37 return "bignum is negative";
38 case SSH_ERR_STRING_TOO_LARGE:
39 return "string is too large";
40 case SSH_ERR_BIGNUM_TOO_LARGE:
41 return "bignum is too large";
42 case SSH_ERR_ECPOINT_TOO_LARGE:
43 return "elliptic curve point is too large";
44 case SSH_ERR_NO_BUFFER_SPACE:
45 return "insufficient buffer space";
46 case SSH_ERR_INVALID_ARGUMENT:
47 return "invalid argument";
48 case SSH_ERR_KEY_BITS_MISMATCH:
49 return "key bits do not match";
50 case SSH_ERR_EC_CURVE_INVALID:
51 return "invalid elliptic curve";
52 case SSH_ERR_KEY_TYPE_MISMATCH:
53 return "key type does not match";
54 case SSH_ERR_KEY_TYPE_UNKNOWN:
55 return "unknown or unsupported key type";
56 case SSH_ERR_EC_CURVE_MISMATCH:
57 return "elliptic curve does not match";
58 case SSH_ERR_EXPECTED_CERT:
59 return "plain key provided where certificate required";
60 case SSH_ERR_KEY_LACKS_CERTBLOB:
61 return "key lacks certificate data";
62 case SSH_ERR_KEY_CERT_UNKNOWN_TYPE:
63 return "unknown/unsupported certificate type";
64 case SSH_ERR_KEY_CERT_INVALID_SIGN_KEY:
65 return "invalid certificate signing key";
66 case SSH_ERR_KEY_INVALID_EC_VALUE:
67 return "invalid elliptic curve value";
68 case SSH_ERR_SIGNATURE_INVALID:
69 return "incorrect signature";
70 case SSH_ERR_LIBCRYPTO_ERROR:
71 return "error in libcrypto"; /* XXX fetch and return */
72 case SSH_ERR_UNEXPECTED_TRAILING_DATA:
73 return "unexpected bytes remain after decoding";
74 case SSH_ERR_SYSTEM_ERROR:
75 return strerror(errno);
76 case SSH_ERR_KEY_CERT_INVALID:
77 return "invalid certificate";
78 case SSH_ERR_AGENT_COMMUNICATION:
79 return "communication with agent failed";
80 case SSH_ERR_AGENT_FAILURE:
81 return "agent refused operation";
82 case SSH_ERR_DH_GEX_OUT_OF_RANGE:
83 return "DH GEX group out of range";
84 case SSH_ERR_DISCONNECTED:
85 return "disconnected";
86 case SSH_ERR_MAC_INVALID:
87 return "message authentication code incorrect";
88 case SSH_ERR_NO_CIPHER_ALG_MATCH:
89 return "no matching cipher found";
90 case SSH_ERR_NO_MAC_ALG_MATCH:
91 return "no matching MAC found";
92 case SSH_ERR_NO_COMPRESS_ALG_MATCH:
93 return "no matching compression method found";
94 case SSH_ERR_NO_KEX_ALG_MATCH:
95 return "no matching key exchange method found";
96 case SSH_ERR_NO_HOSTKEY_ALG_MATCH:
97 return "no matching host key type found";
98 case SSH_ERR_PROTOCOL_MISMATCH:
99 return "protocol version mismatch";
100 case SSH_ERR_NO_PROTOCOL_VERSION:
101 return "could not read protocol version";
102 case SSH_ERR_NO_HOSTKEY_LOADED:
103 return "could not load host key";
104 case SSH_ERR_NEED_REKEY:
105 return "rekeying not supported by peer";
106 case SSH_ERR_PASSPHRASE_TOO_SHORT:
107 return "passphrase is too short (minimum four characters)";
108 case SSH_ERR_FILE_CHANGED:
109 return "file changed while reading";
110 case SSH_ERR_KEY_UNKNOWN_CIPHER:
111 return "key encrypted using unsupported cipher";
112 case SSH_ERR_KEY_WRONG_PASSPHRASE:
113 return "incorrect passphrase supplied to decrypt private key";
114 case SSH_ERR_KEY_BAD_PERMISSIONS:
115 return "bad permissions";
116 case SSH_ERR_KEY_CERT_MISMATCH:
117 return "certificate does not match key";
118 case SSH_ERR_KEY_NOT_FOUND:
119 return "key not found";
120 case SSH_ERR_AGENT_NOT_PRESENT:
121 return "agent not present";
122 case SSH_ERR_AGENT_NO_IDENTITIES:
123 return "agent contains no identities";
124 case SSH_ERR_KRL_BAD_MAGIC:
125 return "KRL file has invalid magic number";
126 case SSH_ERR_KEY_REVOKED:
127 return "Key is revoked";
128 default:
129 return "unknown error";
130 }
131}
diff --git a/ssherr.h b/ssherr.h
new file mode 100644
index 000000000..106f786ea
--- /dev/null
+++ b/ssherr.h
@@ -0,0 +1,80 @@
1/* $OpenBSD: ssherr.h,v 1.1 2014/04/30 05:29:56 djm Exp $ */
2/*
3 * Copyright (c) 2011 Damien Miller
4 *
5 * Permission to use, copy, modify, and distribute this software for any
6 * purpose with or without fee is hereby granted, provided that the above
7 * copyright notice and this permission notice appear in all copies.
8 *
9 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16 */
17
18#ifndef _SSHERR_H
19#define _SSHERR_H
20
21/* XXX are these too granular? not granular enough? I can't decide - djm */
22
23/* Error codes */
24#define SSH_ERR_SUCCESS 0
25#define SSH_ERR_INTERNAL_ERROR -1
26#define SSH_ERR_ALLOC_FAIL -2
27#define SSH_ERR_MESSAGE_INCOMPLETE -3
28#define SSH_ERR_INVALID_FORMAT -4
29#define SSH_ERR_BIGNUM_IS_NEGATIVE -5
30#define SSH_ERR_STRING_TOO_LARGE -6
31#define SSH_ERR_BIGNUM_TOO_LARGE -7
32#define SSH_ERR_ECPOINT_TOO_LARGE -8
33#define SSH_ERR_NO_BUFFER_SPACE -9
34#define SSH_ERR_INVALID_ARGUMENT -10
35#define SSH_ERR_KEY_BITS_MISMATCH -11
36#define SSH_ERR_EC_CURVE_INVALID -12
37#define SSH_ERR_KEY_TYPE_MISMATCH -13
38#define SSH_ERR_KEY_TYPE_UNKNOWN -14 /* XXX UNSUPPORTED? */
39#define SSH_ERR_EC_CURVE_MISMATCH -15
40#define SSH_ERR_EXPECTED_CERT -16
41#define SSH_ERR_KEY_LACKS_CERTBLOB -17
42#define SSH_ERR_KEY_CERT_UNKNOWN_TYPE -18
43#define SSH_ERR_KEY_CERT_INVALID_SIGN_KEY -19
44#define SSH_ERR_KEY_INVALID_EC_VALUE -20
45#define SSH_ERR_SIGNATURE_INVALID -21
46#define SSH_ERR_LIBCRYPTO_ERROR -22
47#define SSH_ERR_UNEXPECTED_TRAILING_DATA -23
48#define SSH_ERR_SYSTEM_ERROR -24
49#define SSH_ERR_KEY_CERT_INVALID -25
50#define SSH_ERR_AGENT_COMMUNICATION -26
51#define SSH_ERR_AGENT_FAILURE -27
52#define SSH_ERR_DH_GEX_OUT_OF_RANGE -28
53#define SSH_ERR_DISCONNECTED -29
54#define SSH_ERR_MAC_INVALID -30
55#define SSH_ERR_NO_CIPHER_ALG_MATCH -31
56#define SSH_ERR_NO_MAC_ALG_MATCH -32
57#define SSH_ERR_NO_COMPRESS_ALG_MATCH -33
58#define SSH_ERR_NO_KEX_ALG_MATCH -34
59#define SSH_ERR_NO_HOSTKEY_ALG_MATCH -35
60#define SSH_ERR_NO_HOSTKEY_LOADED -36
61#define SSH_ERR_PROTOCOL_MISMATCH -37
62#define SSH_ERR_NO_PROTOCOL_VERSION -38
63#define SSH_ERR_NEED_REKEY -39
64#define SSH_ERR_PASSPHRASE_TOO_SHORT -40
65#define SSH_ERR_FILE_CHANGED -41
66#define SSH_ERR_KEY_UNKNOWN_CIPHER -42
67#define SSH_ERR_KEY_WRONG_PASSPHRASE -43
68#define SSH_ERR_KEY_BAD_PERMISSIONS -44
69#define SSH_ERR_KEY_CERT_MISMATCH -45
70#define SSH_ERR_KEY_NOT_FOUND -46
71#define SSH_ERR_AGENT_NOT_PRESENT -47
72#define SSH_ERR_AGENT_NO_IDENTITIES -48
73#define SSH_ERR_BUFFER_READ_ONLY -49
74#define SSH_ERR_KRL_BAD_MAGIC -50
75#define SSH_ERR_KEY_REVOKED -51
76
77/* Translate a numeric error code to a human-readable error string */
78const char *ssh_err(int n);
79
80#endif /* _SSHERR_H */
diff --git a/sshkey.c b/sshkey.c
new file mode 100644
index 000000000..1a96eae19
--- /dev/null
+++ b/sshkey.c
@@ -0,0 +1,3857 @@
1/* $OpenBSD: sshkey.c,v 1.3 2014/07/03 01:45:38 djm Exp $ */
2/*
3 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
4 * Copyright (c) 2008 Alexander von Gernler. All rights reserved.
5 * Copyright (c) 2010,2011 Damien Miller. All rights reserved.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
9 * are met:
10 * 1. Redistributions of source code must retain the above copyright
11 * notice, this list of conditions and the following disclaimer.
12 * 2. Redistributions in binary form must reproduce the above copyright
13 * notice, this list of conditions and the following disclaimer in the
14 * documentation and/or other materials provided with the distribution.
15 *
16 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
17 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
18 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
19 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
20 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
21 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
22 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
23 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
24 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
25 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
26 */
27
28#include "includes.h"
29
30#include <sys/param.h>
31#include <sys/types.h>
32
33#include <openssl/evp.h>
34#include <openssl/err.h>
35#include <openssl/pem.h>
36
37#include "crypto_api.h"
38
39#include <errno.h>
40#include <stdio.h>
41#include <string.h>
42#ifdef HAVE_UTIL_H
43#include <util.h>
44#endif /* HAVE_UTIL_H */
45
46#include "ssh2.h"
47#include "ssherr.h"
48#include "misc.h"
49#include "sshbuf.h"
50#include "rsa.h"
51#include "cipher.h"
52#include "digest.h"
53#define SSHKEY_INTERNAL
54#include "sshkey.h"
55
56/* openssh private key file format */
57#define MARK_BEGIN "-----BEGIN OPENSSH PRIVATE KEY-----\n"
58#define MARK_END "-----END OPENSSH PRIVATE KEY-----\n"
59#define MARK_BEGIN_LEN (sizeof(MARK_BEGIN) - 1)
60#define MARK_END_LEN (sizeof(MARK_END) - 1)
61#define KDFNAME "bcrypt"
62#define AUTH_MAGIC "openssh-key-v1"
63#define SALT_LEN 16
64#define DEFAULT_CIPHERNAME "aes256-cbc"
65#define DEFAULT_ROUNDS 16
66
67/* Version identification string for SSH v1 identity files. */
68#define LEGACY_BEGIN "SSH PRIVATE KEY FILE FORMAT 1.1\n"
69
70static int sshkey_from_blob_internal(const u_char *blob, size_t blen,
71 struct sshkey **keyp, int allow_cert);
72
73/* Supported key types */
74struct keytype {
75 const char *name;
76 const char *shortname;
77 int type;
78 int nid;
79 int cert;
80};
81static const struct keytype keytypes[] = {
82 { "ssh-ed25519", "ED25519", KEY_ED25519, 0, 0 },
83 { "ssh-ed25519-cert-v01@openssh.com", "ED25519-CERT",
84 KEY_ED25519_CERT, 0, 1 },
85#ifdef WITH_OPENSSL
86 { NULL, "RSA1", KEY_RSA1, 0, 0 },
87 { "ssh-rsa", "RSA", KEY_RSA, 0, 0 },
88 { "ssh-dss", "DSA", KEY_DSA, 0, 0 },
89# ifdef OPENSSL_HAS_ECC
90 { "ecdsa-sha2-nistp256", "ECDSA", KEY_ECDSA, NID_X9_62_prime256v1, 0 },
91 { "ecdsa-sha2-nistp384", "ECDSA", KEY_ECDSA, NID_secp384r1, 0 },
92# ifdef OPENSSL_HAS_NISTP521
93 { "ecdsa-sha2-nistp521", "ECDSA", KEY_ECDSA, NID_secp521r1, 0 },
94# endif /* OPENSSL_HAS_NISTP521 */
95# endif /* OPENSSL_HAS_ECC */
96 { "ssh-rsa-cert-v01@openssh.com", "RSA-CERT", KEY_RSA_CERT, 0, 1 },
97 { "ssh-dss-cert-v01@openssh.com", "DSA-CERT", KEY_DSA_CERT, 0, 1 },
98# ifdef OPENSSL_HAS_ECC
99 { "ecdsa-sha2-nistp256-cert-v01@openssh.com", "ECDSA-CERT",
100 KEY_ECDSA_CERT, NID_X9_62_prime256v1, 1 },
101 { "ecdsa-sha2-nistp384-cert-v01@openssh.com", "ECDSA-CERT",
102 KEY_ECDSA_CERT, NID_secp384r1, 1 },
103# ifdef OPENSSL_HAS_NISTP521
104 { "ecdsa-sha2-nistp521-cert-v01@openssh.com", "ECDSA-CERT",
105 KEY_ECDSA_CERT, NID_secp521r1, 1 },
106# endif /* OPENSSL_HAS_NISTP521 */
107# endif /* OPENSSL_HAS_ECC */
108 { "ssh-rsa-cert-v00@openssh.com", "RSA-CERT-V00",
109 KEY_RSA_CERT_V00, 0, 1 },
110 { "ssh-dss-cert-v00@openssh.com", "DSA-CERT-V00",
111 KEY_DSA_CERT_V00, 0, 1 },
112#endif /* WITH_OPENSSL */
113 { "null", "null", KEY_NULL, 0, 0 },
114 { NULL, NULL, -1, -1, 0 }
115};
116
117const char *
118sshkey_type(const struct sshkey *k)
119{
120 const struct keytype *kt;
121
122 for (kt = keytypes; kt->type != -1; kt++) {
123 if (kt->type == k->type)
124 return kt->shortname;
125 }
126 return "unknown";
127}
128
129static const char *
130sshkey_ssh_name_from_type_nid(int type, int nid)
131{
132 const struct keytype *kt;
133
134 for (kt = keytypes; kt->type != -1; kt++) {
135 if (kt->type == type && (kt->nid == 0 || kt->nid == nid))
136 return kt->name;
137 }
138 return "ssh-unknown";
139}
140
141int
142sshkey_type_is_cert(int type)
143{
144 const struct keytype *kt;
145
146 for (kt = keytypes; kt->type != -1; kt++) {
147 if (kt->type == type)
148 return kt->cert;
149 }
150 return 0;
151}
152
153const char *
154sshkey_ssh_name(const struct sshkey *k)
155{
156 return sshkey_ssh_name_from_type_nid(k->type, k->ecdsa_nid);
157}
158
159const char *
160sshkey_ssh_name_plain(const struct sshkey *k)
161{
162 return sshkey_ssh_name_from_type_nid(sshkey_type_plain(k->type),
163 k->ecdsa_nid);
164}
165
166int
167sshkey_type_from_name(const char *name)
168{
169 const struct keytype *kt;
170
171 for (kt = keytypes; kt->type != -1; kt++) {
172 /* Only allow shortname matches for plain key types */
173 if ((kt->name != NULL && strcmp(name, kt->name) == 0) ||
174 (!kt->cert && strcasecmp(kt->shortname, name) == 0))
175 return kt->type;
176 }
177 return KEY_UNSPEC;
178}
179
180int
181sshkey_ecdsa_nid_from_name(const char *name)
182{
183 const struct keytype *kt;
184
185 for (kt = keytypes; kt->type != -1; kt++) {
186 if (kt->type != KEY_ECDSA && kt->type != KEY_ECDSA_CERT)
187 continue;
188 if (kt->name != NULL && strcmp(name, kt->name) == 0)
189 return kt->nid;
190 }
191 return -1;
192}
193
194char *
195key_alg_list(int certs_only, int plain_only)
196{
197 char *tmp, *ret = NULL;
198 size_t nlen, rlen = 0;
199 const struct keytype *kt;
200
201 for (kt = keytypes; kt->type != -1; kt++) {
202 if (kt->name == NULL || kt->type == KEY_NULL)
203 continue;
204 if ((certs_only && !kt->cert) || (plain_only && kt->cert))
205 continue;
206 if (ret != NULL)
207 ret[rlen++] = '\n';
208 nlen = strlen(kt->name);
209 if ((tmp = realloc(ret, rlen + nlen + 2)) == NULL) {
210 free(ret);
211 return NULL;
212 }
213 ret = tmp;
214 memcpy(ret + rlen, kt->name, nlen + 1);
215 rlen += nlen;
216 }
217 return ret;
218}
219
220int
221sshkey_names_valid2(const char *names)
222{
223 char *s, *cp, *p;
224
225 if (names == NULL || strcmp(names, "") == 0)
226 return 0;
227 if ((s = cp = strdup(names)) == NULL)
228 return 0;
229 for ((p = strsep(&cp, ",")); p && *p != '\0';
230 (p = strsep(&cp, ","))) {
231 switch (sshkey_type_from_name(p)) {
232 case KEY_RSA1:
233 case KEY_UNSPEC:
234 free(s);
235 return 0;
236 }
237 }
238 free(s);
239 return 1;
240}
241
242u_int
243sshkey_size(const struct sshkey *k)
244{
245 switch (k->type) {
246#ifdef WITH_OPENSSL
247 case KEY_RSA1:
248 case KEY_RSA:
249 case KEY_RSA_CERT_V00:
250 case KEY_RSA_CERT:
251 return BN_num_bits(k->rsa->n);
252 case KEY_DSA:
253 case KEY_DSA_CERT_V00:
254 case KEY_DSA_CERT:
255 return BN_num_bits(k->dsa->p);
256 case KEY_ECDSA:
257 case KEY_ECDSA_CERT:
258 return sshkey_curve_nid_to_bits(k->ecdsa_nid);
259#endif /* WITH_OPENSSL */
260 case KEY_ED25519:
261 case KEY_ED25519_CERT:
262 return 256; /* XXX */
263 }
264 return 0;
265}
266
267int
268sshkey_cert_is_legacy(const struct sshkey *k)
269{
270 switch (k->type) {
271 case KEY_DSA_CERT_V00:
272 case KEY_RSA_CERT_V00:
273 return 1;
274 default:
275 return 0;
276 }
277}
278
279static int
280sshkey_type_is_valid_ca(int type)
281{
282 switch (type) {
283 case KEY_RSA:
284 case KEY_DSA:
285 case KEY_ECDSA:
286 case KEY_ED25519:
287 return 1;
288 default:
289 return 0;
290 }
291}
292
293int
294sshkey_is_cert(const struct sshkey *k)
295{
296 if (k == NULL)
297 return 0;
298 return sshkey_type_is_cert(k->type);
299}
300
301/* Return the cert-less equivalent to a certified key type */
302int
303sshkey_type_plain(int type)
304{
305 switch (type) {
306 case KEY_RSA_CERT_V00:
307 case KEY_RSA_CERT:
308 return KEY_RSA;
309 case KEY_DSA_CERT_V00:
310 case KEY_DSA_CERT:
311 return KEY_DSA;
312 case KEY_ECDSA_CERT:
313 return KEY_ECDSA;
314 case KEY_ED25519_CERT:
315 return KEY_ED25519;
316 default:
317 return type;
318 }
319}
320
321#ifdef WITH_OPENSSL
322/* XXX: these are really begging for a table-driven approach */
323int
324sshkey_curve_name_to_nid(const char *name)
325{
326 if (strcmp(name, "nistp256") == 0)
327 return NID_X9_62_prime256v1;
328 else if (strcmp(name, "nistp384") == 0)
329 return NID_secp384r1;
330# ifdef OPENSSL_HAS_NISTP521
331 else if (strcmp(name, "nistp521") == 0)
332 return NID_secp521r1;
333# endif /* OPENSSL_HAS_NISTP521 */
334 else
335 return -1;
336}
337
338u_int
339sshkey_curve_nid_to_bits(int nid)
340{
341 switch (nid) {
342 case NID_X9_62_prime256v1:
343 return 256;
344 case NID_secp384r1:
345 return 384;
346# ifdef OPENSSL_HAS_NISTP521
347 case NID_secp521r1:
348 return 521;
349# endif /* OPENSSL_HAS_NISTP521 */
350 default:
351 return 0;
352 }
353}
354
355int
356sshkey_ecdsa_bits_to_nid(int bits)
357{
358 switch (bits) {
359 case 256:
360 return NID_X9_62_prime256v1;
361 case 384:
362 return NID_secp384r1;
363# ifdef OPENSSL_HAS_NISTP521
364 case 521:
365 return NID_secp521r1;
366# endif /* OPENSSL_HAS_NISTP521 */
367 default:
368 return -1;
369 }
370}
371
372const char *
373sshkey_curve_nid_to_name(int nid)
374{
375 switch (nid) {
376 case NID_X9_62_prime256v1:
377 return "nistp256";
378 case NID_secp384r1:
379 return "nistp384";
380# ifdef OPENSSL_HAS_NISTP521
381 case NID_secp521r1:
382 return "nistp521";
383# endif /* OPENSSL_HAS_NISTP521 */
384 default:
385 return NULL;
386 }
387}
388
389int
390sshkey_ec_nid_to_hash_alg(int nid)
391{
392 int kbits = sshkey_curve_nid_to_bits(nid);
393
394 if (kbits <= 0)
395 return -1;
396
397 /* RFC5656 section 6.2.1 */
398 if (kbits <= 256)
399 return SSH_DIGEST_SHA256;
400 else if (kbits <= 384)
401 return SSH_DIGEST_SHA384;
402 else
403 return SSH_DIGEST_SHA512;
404}
405#endif /* WITH_OPENSSL */
406
407static void
408cert_free(struct sshkey_cert *cert)
409{
410 u_int i;
411
412 if (cert == NULL)
413 return;
414 if (cert->certblob != NULL)
415 sshbuf_free(cert->certblob);
416 if (cert->critical != NULL)
417 sshbuf_free(cert->critical);
418 if (cert->extensions != NULL)
419 sshbuf_free(cert->extensions);
420 if (cert->key_id != NULL)
421 free(cert->key_id);
422 for (i = 0; i < cert->nprincipals; i++)
423 free(cert->principals[i]);
424 if (cert->principals != NULL)
425 free(cert->principals);
426 if (cert->signature_key != NULL)
427 sshkey_free(cert->signature_key);
428 explicit_bzero(cert, sizeof(*cert));
429 free(cert);
430}
431
432static struct sshkey_cert *
433cert_new(void)
434{
435 struct sshkey_cert *cert;
436
437 if ((cert = calloc(1, sizeof(*cert))) == NULL)
438 return NULL;
439 if ((cert->certblob = sshbuf_new()) == NULL ||
440 (cert->critical = sshbuf_new()) == NULL ||
441 (cert->extensions = sshbuf_new()) == NULL) {
442 cert_free(cert);
443 return NULL;
444 }
445 cert->key_id = NULL;
446 cert->principals = NULL;
447 cert->signature_key = NULL;
448 return cert;
449}
450
451struct sshkey *
452sshkey_new(int type)
453{
454 struct sshkey *k;
455#ifdef WITH_OPENSSL
456 RSA *rsa;
457 DSA *dsa;
458#endif /* WITH_OPENSSL */
459
460 if ((k = calloc(1, sizeof(*k))) == NULL)
461 return NULL;
462 k->type = type;
463 k->ecdsa = NULL;
464 k->ecdsa_nid = -1;
465 k->dsa = NULL;
466 k->rsa = NULL;
467 k->cert = NULL;
468 k->ed25519_sk = NULL;
469 k->ed25519_pk = NULL;
470 switch (k->type) {
471#ifdef WITH_OPENSSL
472 case KEY_RSA1:
473 case KEY_RSA:
474 case KEY_RSA_CERT_V00:
475 case KEY_RSA_CERT:
476 if ((rsa = RSA_new()) == NULL ||
477 (rsa->n = BN_new()) == NULL ||
478 (rsa->e = BN_new()) == NULL) {
479 if (rsa != NULL)
480 RSA_free(rsa);
481 free(k);
482 return NULL;
483 }
484 k->rsa = rsa;
485 break;
486 case KEY_DSA:
487 case KEY_DSA_CERT_V00:
488 case KEY_DSA_CERT:
489 if ((dsa = DSA_new()) == NULL ||
490 (dsa->p = BN_new()) == NULL ||
491 (dsa->q = BN_new()) == NULL ||
492 (dsa->g = BN_new()) == NULL ||
493 (dsa->pub_key = BN_new()) == NULL) {
494 if (dsa != NULL)
495 DSA_free(dsa);
496 free(k);
497 return NULL;
498 }
499 k->dsa = dsa;
500 break;
501 case KEY_ECDSA:
502 case KEY_ECDSA_CERT:
503 /* Cannot do anything until we know the group */
504 break;
505#endif /* WITH_OPENSSL */
506 case KEY_ED25519:
507 case KEY_ED25519_CERT:
508 /* no need to prealloc */
509 break;
510 case KEY_UNSPEC:
511 break;
512 default:
513 free(k);
514 return NULL;
515 break;
516 }
517
518 if (sshkey_is_cert(k)) {
519 if ((k->cert = cert_new()) == NULL) {
520 sshkey_free(k);
521 return NULL;
522 }
523 }
524
525 return k;
526}
527
528int
529sshkey_add_private(struct sshkey *k)
530{
531 switch (k->type) {
532#ifdef WITH_OPENSSL
533 case KEY_RSA1:
534 case KEY_RSA:
535 case KEY_RSA_CERT_V00:
536 case KEY_RSA_CERT:
537#define bn_maybe_alloc_failed(p) (p == NULL && (p = BN_new()) == NULL)
538 if (bn_maybe_alloc_failed(k->rsa->d) ||
539 bn_maybe_alloc_failed(k->rsa->iqmp) ||
540 bn_maybe_alloc_failed(k->rsa->q) ||
541 bn_maybe_alloc_failed(k->rsa->p) ||
542 bn_maybe_alloc_failed(k->rsa->dmq1) ||
543 bn_maybe_alloc_failed(k->rsa->dmp1))
544 return SSH_ERR_ALLOC_FAIL;
545 break;
546 case KEY_DSA:
547 case KEY_DSA_CERT_V00:
548 case KEY_DSA_CERT:
549 if (bn_maybe_alloc_failed(k->dsa->priv_key))
550 return SSH_ERR_ALLOC_FAIL;
551 break;
552#undef bn_maybe_alloc_failed
553 case KEY_ECDSA:
554 case KEY_ECDSA_CERT:
555 /* Cannot do anything until we know the group */
556 break;
557#endif /* WITH_OPENSSL */
558 case KEY_ED25519:
559 case KEY_ED25519_CERT:
560 /* no need to prealloc */
561 break;
562 case KEY_UNSPEC:
563 break;
564 default:
565 return SSH_ERR_INVALID_ARGUMENT;
566 }
567 return 0;
568}
569
570struct sshkey *
571sshkey_new_private(int type)
572{
573 struct sshkey *k = sshkey_new(type);
574
575 if (k == NULL)
576 return NULL;
577 if (sshkey_add_private(k) != 0) {
578 sshkey_free(k);
579 return NULL;
580 }
581 return k;
582}
583
584void
585sshkey_free(struct sshkey *k)
586{
587 if (k == NULL)
588 return;
589 switch (k->type) {
590#ifdef WITH_OPENSSL
591 case KEY_RSA1:
592 case KEY_RSA:
593 case KEY_RSA_CERT_V00:
594 case KEY_RSA_CERT:
595 if (k->rsa != NULL)
596 RSA_free(k->rsa);
597 k->rsa = NULL;
598 break;
599 case KEY_DSA:
600 case KEY_DSA_CERT_V00:
601 case KEY_DSA_CERT:
602 if (k->dsa != NULL)
603 DSA_free(k->dsa);
604 k->dsa = NULL;
605 break;
606# ifdef OPENSSL_HAS_ECC
607 case KEY_ECDSA:
608 case KEY_ECDSA_CERT:
609 if (k->ecdsa != NULL)
610 EC_KEY_free(k->ecdsa);
611 k->ecdsa = NULL;
612 break;
613# endif /* OPENSSL_HAS_ECC */
614#endif /* WITH_OPENSSL */
615 case KEY_ED25519:
616 case KEY_ED25519_CERT:
617 if (k->ed25519_pk) {
618 explicit_bzero(k->ed25519_pk, ED25519_PK_SZ);
619 free(k->ed25519_pk);
620 k->ed25519_pk = NULL;
621 }
622 if (k->ed25519_sk) {
623 explicit_bzero(k->ed25519_sk, ED25519_SK_SZ);
624 free(k->ed25519_sk);
625 k->ed25519_sk = NULL;
626 }
627 break;
628 case KEY_UNSPEC:
629 break;
630 default:
631 break;
632 }
633 if (sshkey_is_cert(k))
634 cert_free(k->cert);
635 explicit_bzero(k, sizeof(*k));
636 free(k);
637}
638
639static int
640cert_compare(struct sshkey_cert *a, struct sshkey_cert *b)
641{
642 if (a == NULL && b == NULL)
643 return 1;
644 if (a == NULL || b == NULL)
645 return 0;
646 if (sshbuf_len(a->certblob) != sshbuf_len(b->certblob))
647 return 0;
648 if (timingsafe_bcmp(sshbuf_ptr(a->certblob), sshbuf_ptr(b->certblob),
649 sshbuf_len(a->certblob)) != 0)
650 return 0;
651 return 1;
652}
653
654/*
655 * Compare public portions of key only, allowing comparisons between
656 * certificates and plain keys too.
657 */
658int
659sshkey_equal_public(const struct sshkey *a, const struct sshkey *b)
660{
661#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
662 BN_CTX *bnctx;
663#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
664
665 if (a == NULL || b == NULL ||
666 sshkey_type_plain(a->type) != sshkey_type_plain(b->type))
667 return 0;
668
669 switch (a->type) {
670#ifdef WITH_OPENSSL
671 case KEY_RSA1:
672 case KEY_RSA_CERT_V00:
673 case KEY_RSA_CERT:
674 case KEY_RSA:
675 return a->rsa != NULL && b->rsa != NULL &&
676 BN_cmp(a->rsa->e, b->rsa->e) == 0 &&
677 BN_cmp(a->rsa->n, b->rsa->n) == 0;
678 case KEY_DSA_CERT_V00:
679 case KEY_DSA_CERT:
680 case KEY_DSA:
681 return a->dsa != NULL && b->dsa != NULL &&
682 BN_cmp(a->dsa->p, b->dsa->p) == 0 &&
683 BN_cmp(a->dsa->q, b->dsa->q) == 0 &&
684 BN_cmp(a->dsa->g, b->dsa->g) == 0 &&
685 BN_cmp(a->dsa->pub_key, b->dsa->pub_key) == 0;
686# ifdef OPENSSL_HAS_ECC
687 case KEY_ECDSA_CERT:
688 case KEY_ECDSA:
689 if (a->ecdsa == NULL || b->ecdsa == NULL ||
690 EC_KEY_get0_public_key(a->ecdsa) == NULL ||
691 EC_KEY_get0_public_key(b->ecdsa) == NULL)
692 return 0;
693 if ((bnctx = BN_CTX_new()) == NULL)
694 return 0;
695 if (EC_GROUP_cmp(EC_KEY_get0_group(a->ecdsa),
696 EC_KEY_get0_group(b->ecdsa), bnctx) != 0 ||
697 EC_POINT_cmp(EC_KEY_get0_group(a->ecdsa),
698 EC_KEY_get0_public_key(a->ecdsa),
699 EC_KEY_get0_public_key(b->ecdsa), bnctx) != 0) {
700 BN_CTX_free(bnctx);
701 return 0;
702 }
703 BN_CTX_free(bnctx);
704 return 1;
705# endif /* OPENSSL_HAS_ECC */
706#endif /* WITH_OPENSSL */
707 case KEY_ED25519:
708 case KEY_ED25519_CERT:
709 return a->ed25519_pk != NULL && b->ed25519_pk != NULL &&
710 memcmp(a->ed25519_pk, b->ed25519_pk, ED25519_PK_SZ) == 0;
711 default:
712 return 0;
713 }
714 /* NOTREACHED */
715}
716
717int
718sshkey_equal(const struct sshkey *a, const struct sshkey *b)
719{
720 if (a == NULL || b == NULL || a->type != b->type)
721 return 0;
722 if (sshkey_is_cert(a)) {
723 if (!cert_compare(a->cert, b->cert))
724 return 0;
725 }
726 return sshkey_equal_public(a, b);
727}
728
729static int
730to_blob_buf(const struct sshkey *key, struct sshbuf *b, int force_plain)
731{
732 int type, ret = SSH_ERR_INTERNAL_ERROR;
733 const char *typename;
734
735 if (key == NULL)
736 return SSH_ERR_INVALID_ARGUMENT;
737
738 type = force_plain ? sshkey_type_plain(key->type) : key->type;
739 typename = sshkey_ssh_name_from_type_nid(type, key->ecdsa_nid);
740
741 switch (type) {
742#ifdef WITH_OPENSSL
743 case KEY_DSA_CERT_V00:
744 case KEY_RSA_CERT_V00:
745 case KEY_DSA_CERT:
746 case KEY_ECDSA_CERT:
747 case KEY_RSA_CERT:
748#endif /* WITH_OPENSSL */
749 case KEY_ED25519_CERT:
750 /* Use the existing blob */
751 /* XXX modified flag? */
752 if ((ret = sshbuf_putb(b, key->cert->certblob)) != 0)
753 return ret;
754 break;
755#ifdef WITH_OPENSSL
756 case KEY_DSA:
757 if (key->dsa == NULL)
758 return SSH_ERR_INVALID_ARGUMENT;
759 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
760 (ret = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
761 (ret = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
762 (ret = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
763 (ret = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0)
764 return ret;
765 break;
766# ifdef OPENSSL_HAS_ECC
767 case KEY_ECDSA:
768 if (key->ecdsa == NULL)
769 return SSH_ERR_INVALID_ARGUMENT;
770 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
771 (ret = sshbuf_put_cstring(b,
772 sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
773 (ret = sshbuf_put_eckey(b, key->ecdsa)) != 0)
774 return ret;
775 break;
776# endif
777 case KEY_RSA:
778 if (key->rsa == NULL)
779 return SSH_ERR_INVALID_ARGUMENT;
780 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
781 (ret = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
782 (ret = sshbuf_put_bignum2(b, key->rsa->n)) != 0)
783 return ret;
784 break;
785#endif /* WITH_OPENSSL */
786 case KEY_ED25519:
787 if (key->ed25519_pk == NULL)
788 return SSH_ERR_INVALID_ARGUMENT;
789 if ((ret = sshbuf_put_cstring(b, typename)) != 0 ||
790 (ret = sshbuf_put_string(b,
791 key->ed25519_pk, ED25519_PK_SZ)) != 0)
792 return ret;
793 break;
794 default:
795 return SSH_ERR_KEY_TYPE_UNKNOWN;
796 }
797 return 0;
798}
799
800int
801sshkey_to_blob_buf(const struct sshkey *key, struct sshbuf *b)
802{
803 return to_blob_buf(key, b, 0);
804}
805
806int
807sshkey_plain_to_blob_buf(const struct sshkey *key, struct sshbuf *b)
808{
809 return to_blob_buf(key, b, 1);
810}
811
812static int
813to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp, int force_plain)
814{
815 int ret = SSH_ERR_INTERNAL_ERROR;
816 size_t len;
817 struct sshbuf *b = NULL;
818
819 if (lenp != NULL)
820 *lenp = 0;
821 if (blobp != NULL)
822 *blobp = NULL;
823 if ((b = sshbuf_new()) == NULL)
824 return SSH_ERR_ALLOC_FAIL;
825 if ((ret = to_blob_buf(key, b, force_plain)) != 0)
826 goto out;
827 len = sshbuf_len(b);
828 if (lenp != NULL)
829 *lenp = len;
830 if (blobp != NULL) {
831 if ((*blobp = malloc(len)) == NULL) {
832 ret = SSH_ERR_ALLOC_FAIL;
833 goto out;
834 }
835 memcpy(*blobp, sshbuf_ptr(b), len);
836 }
837 ret = 0;
838 out:
839 sshbuf_free(b);
840 return ret;
841}
842
843int
844sshkey_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
845{
846 return to_blob(key, blobp, lenp, 0);
847}
848
849int
850sshkey_plain_to_blob(const struct sshkey *key, u_char **blobp, size_t *lenp)
851{
852 return to_blob(key, blobp, lenp, 1);
853}
854
855int
856sshkey_fingerprint_raw(const struct sshkey *k, enum sshkey_fp_type dgst_type,
857 u_char **retp, size_t *lenp)
858{
859 u_char *blob = NULL, *ret = NULL;
860 size_t blob_len = 0;
861 int hash_alg = -1, r = SSH_ERR_INTERNAL_ERROR;
862
863 if (retp != NULL)
864 *retp = NULL;
865 if (lenp != NULL)
866 *lenp = 0;
867
868 switch (dgst_type) {
869 case SSH_FP_MD5:
870 hash_alg = SSH_DIGEST_MD5;
871 break;
872 case SSH_FP_SHA1:
873 hash_alg = SSH_DIGEST_SHA1;
874 break;
875 case SSH_FP_SHA256:
876 hash_alg = SSH_DIGEST_SHA256;
877 break;
878 default:
879 r = SSH_ERR_INVALID_ARGUMENT;
880 goto out;
881 }
882
883 if (k->type == KEY_RSA1) {
884#ifdef WITH_OPENSSL
885 int nlen = BN_num_bytes(k->rsa->n);
886 int elen = BN_num_bytes(k->rsa->e);
887
888 blob_len = nlen + elen;
889 if (nlen >= INT_MAX - elen ||
890 (blob = malloc(blob_len)) == NULL) {
891 r = SSH_ERR_ALLOC_FAIL;
892 goto out;
893 }
894 BN_bn2bin(k->rsa->n, blob);
895 BN_bn2bin(k->rsa->e, blob + nlen);
896#endif /* WITH_OPENSSL */
897 } else if ((r = to_blob(k, &blob, &blob_len, 1)) != 0)
898 goto out;
899 if ((ret = calloc(1, SSH_DIGEST_MAX_LENGTH)) == NULL) {
900 r = SSH_ERR_ALLOC_FAIL;
901 goto out;
902 }
903 if ((r = ssh_digest_memory(hash_alg, blob, blob_len,
904 ret, SSH_DIGEST_MAX_LENGTH)) != 0)
905 goto out;
906 /* success */
907 if (retp != NULL) {
908 *retp = ret;
909 ret = NULL;
910 }
911 if (lenp != NULL)
912 *lenp = ssh_digest_bytes(hash_alg);
913 r = 0;
914 out:
915 free(ret);
916 if (blob != NULL) {
917 explicit_bzero(blob, blob_len);
918 free(blob);
919 }
920 return r;
921}
922
923static char *
924fingerprint_hex(u_char *dgst_raw, size_t dgst_raw_len)
925{
926 char *retval;
927 size_t i;
928
929 if ((retval = calloc(1, dgst_raw_len * 3 + 1)) == NULL)
930 return NULL;
931 for (i = 0; i < dgst_raw_len; i++) {
932 char hex[4];
933 snprintf(hex, sizeof(hex), "%02x:", dgst_raw[i]);
934 strlcat(retval, hex, dgst_raw_len * 3 + 1);
935 }
936
937 /* Remove the trailing ':' character */
938 retval[(dgst_raw_len * 3) - 1] = '\0';
939 return retval;
940}
941
942static char *
943fingerprint_bubblebabble(u_char *dgst_raw, size_t dgst_raw_len)
944{
945 char vowels[] = { 'a', 'e', 'i', 'o', 'u', 'y' };
946 char consonants[] = { 'b', 'c', 'd', 'f', 'g', 'h', 'k', 'l', 'm',
947 'n', 'p', 'r', 's', 't', 'v', 'z', 'x' };
948 u_int i, j = 0, rounds, seed = 1;
949 char *retval;
950
951 rounds = (dgst_raw_len / 2) + 1;
952 if ((retval = calloc(rounds, 6)) == NULL)
953 return NULL;
954 retval[j++] = 'x';
955 for (i = 0; i < rounds; i++) {
956 u_int idx0, idx1, idx2, idx3, idx4;
957 if ((i + 1 < rounds) || (dgst_raw_len % 2 != 0)) {
958 idx0 = (((((u_int)(dgst_raw[2 * i])) >> 6) & 3) +
959 seed) % 6;
960 idx1 = (((u_int)(dgst_raw[2 * i])) >> 2) & 15;
961 idx2 = ((((u_int)(dgst_raw[2 * i])) & 3) +
962 (seed / 6)) % 6;
963 retval[j++] = vowels[idx0];
964 retval[j++] = consonants[idx1];
965 retval[j++] = vowels[idx2];
966 if ((i + 1) < rounds) {
967 idx3 = (((u_int)(dgst_raw[(2 * i) + 1])) >> 4) & 15;
968 idx4 = (((u_int)(dgst_raw[(2 * i) + 1]))) & 15;
969 retval[j++] = consonants[idx3];
970 retval[j++] = '-';
971 retval[j++] = consonants[idx4];
972 seed = ((seed * 5) +
973 ((((u_int)(dgst_raw[2 * i])) * 7) +
974 ((u_int)(dgst_raw[(2 * i) + 1])))) % 36;
975 }
976 } else {
977 idx0 = seed % 6;
978 idx1 = 16;
979 idx2 = seed / 6;
980 retval[j++] = vowels[idx0];
981 retval[j++] = consonants[idx1];
982 retval[j++] = vowels[idx2];
983 }
984 }
985 retval[j++] = 'x';
986 retval[j++] = '\0';
987 return retval;
988}
989
990/*
991 * Draw an ASCII-Art representing the fingerprint so human brain can
992 * profit from its built-in pattern recognition ability.
993 * This technique is called "random art" and can be found in some
994 * scientific publications like this original paper:
995 *
996 * "Hash Visualization: a New Technique to improve Real-World Security",
997 * Perrig A. and Song D., 1999, International Workshop on Cryptographic
998 * Techniques and E-Commerce (CrypTEC '99)
999 * sparrow.ece.cmu.edu/~adrian/projects/validation/validation.pdf
1000 *
1001 * The subject came up in a talk by Dan Kaminsky, too.
1002 *
1003 * If you see the picture is different, the key is different.
1004 * If the picture looks the same, you still know nothing.
1005 *
1006 * The algorithm used here is a worm crawling over a discrete plane,
1007 * leaving a trace (augmenting the field) everywhere it goes.
1008 * Movement is taken from dgst_raw 2bit-wise. Bumping into walls
1009 * makes the respective movement vector be ignored for this turn.
1010 * Graphs are not unambiguous, because circles in graphs can be
1011 * walked in either direction.
1012 */
1013
1014/*
1015 * Field sizes for the random art. Have to be odd, so the starting point
1016 * can be in the exact middle of the picture, and FLDBASE should be >=8 .
1017 * Else pictures would be too dense, and drawing the frame would
1018 * fail, too, because the key type would not fit in anymore.
1019 */
1020#define FLDBASE 8
1021#define FLDSIZE_Y (FLDBASE + 1)
1022#define FLDSIZE_X (FLDBASE * 2 + 1)
1023static char *
1024fingerprint_randomart(u_char *dgst_raw, size_t dgst_raw_len,
1025 const struct sshkey *k)
1026{
1027 /*
1028 * Chars to be used after each other every time the worm
1029 * intersects with itself. Matter of taste.
1030 */
1031 char *augmentation_string = " .o+=*BOX@%&#/^SE";
1032 char *retval, *p, title[FLDSIZE_X];
1033 u_char field[FLDSIZE_X][FLDSIZE_Y];
1034 size_t i, tlen;
1035 u_int b;
1036 int x, y, r;
1037 size_t len = strlen(augmentation_string) - 1;
1038
1039 if ((retval = calloc((FLDSIZE_X + 3), (FLDSIZE_Y + 2))) == NULL)
1040 return NULL;
1041
1042 /* initialize field */
1043 memset(field, 0, FLDSIZE_X * FLDSIZE_Y * sizeof(char));
1044 x = FLDSIZE_X / 2;
1045 y = FLDSIZE_Y / 2;
1046
1047 /* process raw key */
1048 for (i = 0; i < dgst_raw_len; i++) {
1049 int input;
1050 /* each byte conveys four 2-bit move commands */
1051 input = dgst_raw[i];
1052 for (b = 0; b < 4; b++) {
1053 /* evaluate 2 bit, rest is shifted later */
1054 x += (input & 0x1) ? 1 : -1;
1055 y += (input & 0x2) ? 1 : -1;
1056
1057 /* assure we are still in bounds */
1058 x = MAX(x, 0);
1059 y = MAX(y, 0);
1060 x = MIN(x, FLDSIZE_X - 1);
1061 y = MIN(y, FLDSIZE_Y - 1);
1062
1063 /* augment the field */
1064 if (field[x][y] < len - 2)
1065 field[x][y]++;
1066 input = input >> 2;
1067 }
1068 }
1069
1070 /* mark starting point and end point*/
1071 field[FLDSIZE_X / 2][FLDSIZE_Y / 2] = len - 1;
1072 field[x][y] = len;
1073
1074 /* assemble title */
1075 r = snprintf(title, sizeof(title), "[%s %u]",
1076 sshkey_type(k), sshkey_size(k));
1077 /* If [type size] won't fit, then try [type]; fits "[ED25519-CERT]" */
1078 if (r < 0 || r > (int)sizeof(title))
1079 snprintf(title, sizeof(title), "[%s]", sshkey_type(k));
1080 tlen = strlen(title);
1081
1082 /* output upper border */
1083 p = retval;
1084 *p++ = '+';
1085 for (i = 0; i < (FLDSIZE_X - tlen) / 2; i++)
1086 *p++ = '-';
1087 memcpy(p, title, tlen);
1088 p += tlen;
1089 for (i = p - retval - 1; i < FLDSIZE_X; i++)
1090 *p++ = '-';
1091 *p++ = '+';
1092 *p++ = '\n';
1093
1094 /* output content */
1095 for (y = 0; y < FLDSIZE_Y; y++) {
1096 *p++ = '|';
1097 for (x = 0; x < FLDSIZE_X; x++)
1098 *p++ = augmentation_string[MIN(field[x][y], len)];
1099 *p++ = '|';
1100 *p++ = '\n';
1101 }
1102
1103 /* output lower border */
1104 *p++ = '+';
1105 for (i = 0; i < FLDSIZE_X; i++)
1106 *p++ = '-';
1107 *p++ = '+';
1108
1109 return retval;
1110}
1111
1112char *
1113sshkey_fingerprint(const struct sshkey *k, enum sshkey_fp_type dgst_type,
1114 enum sshkey_fp_rep dgst_rep)
1115{
1116 char *retval = NULL;
1117 u_char *dgst_raw;
1118 size_t dgst_raw_len;
1119
1120 if (sshkey_fingerprint_raw(k, dgst_type, &dgst_raw, &dgst_raw_len) != 0)
1121 return NULL;
1122 switch (dgst_rep) {
1123 case SSH_FP_HEX:
1124 retval = fingerprint_hex(dgst_raw, dgst_raw_len);
1125 break;
1126 case SSH_FP_BUBBLEBABBLE:
1127 retval = fingerprint_bubblebabble(dgst_raw, dgst_raw_len);
1128 break;
1129 case SSH_FP_RANDOMART:
1130 retval = fingerprint_randomart(dgst_raw, dgst_raw_len, k);
1131 break;
1132 default:
1133 explicit_bzero(dgst_raw, dgst_raw_len);
1134 free(dgst_raw);
1135 return NULL;
1136 }
1137 explicit_bzero(dgst_raw, dgst_raw_len);
1138 free(dgst_raw);
1139 return retval;
1140}
1141
1142#ifdef WITH_SSH1
1143/*
1144 * Reads a multiple-precision integer in decimal from the buffer, and advances
1145 * the pointer. The integer must already be initialized. This function is
1146 * permitted to modify the buffer. This leaves *cpp to point just beyond the
1147 * last processed character.
1148 */
1149static int
1150read_decimal_bignum(char **cpp, BIGNUM *v)
1151{
1152 char *cp;
1153 size_t e;
1154 int skip = 1; /* skip white space */
1155
1156 cp = *cpp;
1157 while (*cp == ' ' || *cp == '\t')
1158 cp++;
1159 e = strspn(cp, "0123456789");
1160 if (e == 0)
1161 return SSH_ERR_INVALID_FORMAT;
1162 if (e > SSHBUF_MAX_BIGNUM * 3)
1163 return SSH_ERR_BIGNUM_TOO_LARGE;
1164 if (cp[e] == '\0')
1165 skip = 0;
1166 else if (index(" \t\r\n", cp[e]) == NULL)
1167 return SSH_ERR_INVALID_FORMAT;
1168 cp[e] = '\0';
1169 if (BN_dec2bn(&v, cp) <= 0)
1170 return SSH_ERR_INVALID_FORMAT;
1171 *cpp = cp + e + skip;
1172 return 0;
1173}
1174#endif /* WITH_SSH1 */
1175
1176/* returns 0 ok, and < 0 error */
1177int
1178sshkey_read(struct sshkey *ret, char **cpp)
1179{
1180 struct sshkey *k;
1181 int retval = SSH_ERR_INVALID_FORMAT;
1182 char *cp, *space;
1183 int r, type, curve_nid = -1;
1184 struct sshbuf *blob;
1185#ifdef WITH_SSH1
1186 char *ep;
1187 u_long bits;
1188#endif /* WITH_SSH1 */
1189
1190 cp = *cpp;
1191
1192 switch (ret->type) {
1193 case KEY_RSA1:
1194#ifdef WITH_SSH1
1195 /* Get number of bits. */
1196 bits = strtoul(cp, &ep, 10);
1197 if (*cp == '\0' || index(" \t\r\n", *ep) == NULL ||
1198 bits == 0 || bits > SSHBUF_MAX_BIGNUM * 8)
1199 return SSH_ERR_INVALID_FORMAT; /* Bad bit count... */
1200 /* Get public exponent, public modulus. */
1201 if ((r = read_decimal_bignum(&ep, ret->rsa->e)) < 0)
1202 return r;
1203 if ((r = read_decimal_bignum(&ep, ret->rsa->n)) < 0)
1204 return r;
1205 *cpp = ep;
1206 /* validate the claimed number of bits */
1207 if (BN_num_bits(ret->rsa->n) != (int)bits)
1208 return SSH_ERR_KEY_BITS_MISMATCH;
1209 retval = 0;
1210#endif /* WITH_SSH1 */
1211 break;
1212 case KEY_UNSPEC:
1213 case KEY_RSA:
1214 case KEY_DSA:
1215 case KEY_ECDSA:
1216 case KEY_ED25519:
1217 case KEY_DSA_CERT_V00:
1218 case KEY_RSA_CERT_V00:
1219 case KEY_DSA_CERT:
1220 case KEY_ECDSA_CERT:
1221 case KEY_RSA_CERT:
1222 case KEY_ED25519_CERT:
1223 space = strchr(cp, ' ');
1224 if (space == NULL)
1225 return SSH_ERR_INVALID_FORMAT;
1226 *space = '\0';
1227 type = sshkey_type_from_name(cp);
1228 if (sshkey_type_plain(type) == KEY_ECDSA &&
1229 (curve_nid = sshkey_ecdsa_nid_from_name(cp)) == -1)
1230 return SSH_ERR_EC_CURVE_INVALID;
1231 *space = ' ';
1232 if (type == KEY_UNSPEC)
1233 return SSH_ERR_INVALID_FORMAT;
1234 cp = space+1;
1235 if (*cp == '\0')
1236 return SSH_ERR_INVALID_FORMAT;
1237 if (ret->type == KEY_UNSPEC) {
1238 ret->type = type;
1239 } else if (ret->type != type)
1240 return SSH_ERR_KEY_TYPE_MISMATCH;
1241 if ((blob = sshbuf_new()) == NULL)
1242 return SSH_ERR_ALLOC_FAIL;
1243 /* trim comment */
1244 space = strchr(cp, ' ');
1245 if (space)
1246 *space = '\0';
1247 if ((r = sshbuf_b64tod(blob, cp)) != 0) {
1248 sshbuf_free(blob);
1249 return r;
1250 }
1251 if ((r = sshkey_from_blob(sshbuf_ptr(blob),
1252 sshbuf_len(blob), &k)) != 0) {
1253 sshbuf_free(blob);
1254 return r;
1255 }
1256 sshbuf_free(blob);
1257 if (k->type != type) {
1258 sshkey_free(k);
1259 return SSH_ERR_KEY_TYPE_MISMATCH;
1260 }
1261 if (sshkey_type_plain(type) == KEY_ECDSA &&
1262 curve_nid != k->ecdsa_nid) {
1263 sshkey_free(k);
1264 return SSH_ERR_EC_CURVE_MISMATCH;
1265 }
1266/*XXXX*/
1267 if (sshkey_is_cert(ret)) {
1268 if (!sshkey_is_cert(k)) {
1269 sshkey_free(k);
1270 return SSH_ERR_EXPECTED_CERT;
1271 }
1272 if (ret->cert != NULL)
1273 cert_free(ret->cert);
1274 ret->cert = k->cert;
1275 k->cert = NULL;
1276 }
1277#ifdef WITH_OPENSSL
1278 if (sshkey_type_plain(ret->type) == KEY_RSA) {
1279 if (ret->rsa != NULL)
1280 RSA_free(ret->rsa);
1281 ret->rsa = k->rsa;
1282 k->rsa = NULL;
1283#ifdef DEBUG_PK
1284 RSA_print_fp(stderr, ret->rsa, 8);
1285#endif
1286 }
1287 if (sshkey_type_plain(ret->type) == KEY_DSA) {
1288 if (ret->dsa != NULL)
1289 DSA_free(ret->dsa);
1290 ret->dsa = k->dsa;
1291 k->dsa = NULL;
1292#ifdef DEBUG_PK
1293 DSA_print_fp(stderr, ret->dsa, 8);
1294#endif
1295 }
1296# ifdef OPENSSL_HAS_ECC
1297 if (sshkey_type_plain(ret->type) == KEY_ECDSA) {
1298 if (ret->ecdsa != NULL)
1299 EC_KEY_free(ret->ecdsa);
1300 ret->ecdsa = k->ecdsa;
1301 ret->ecdsa_nid = k->ecdsa_nid;
1302 k->ecdsa = NULL;
1303 k->ecdsa_nid = -1;
1304#ifdef DEBUG_PK
1305 sshkey_dump_ec_key(ret->ecdsa);
1306#endif
1307 }
1308# endif /* OPENSSL_HAS_ECC */
1309#endif /* WITH_OPENSSL */
1310 if (sshkey_type_plain(ret->type) == KEY_ED25519) {
1311 free(ret->ed25519_pk);
1312 ret->ed25519_pk = k->ed25519_pk;
1313 k->ed25519_pk = NULL;
1314#ifdef DEBUG_PK
1315 /* XXX */
1316#endif
1317 }
1318 retval = 0;
1319/*XXXX*/
1320 sshkey_free(k);
1321 if (retval != 0)
1322 break;
1323 /* advance cp: skip whitespace and data */
1324 while (*cp == ' ' || *cp == '\t')
1325 cp++;
1326 while (*cp != '\0' && *cp != ' ' && *cp != '\t')
1327 cp++;
1328 *cpp = cp;
1329 break;
1330 default:
1331 return SSH_ERR_INVALID_ARGUMENT;
1332 }
1333 return retval;
1334}
1335
1336int
1337sshkey_write(const struct sshkey *key, FILE *f)
1338{
1339 int ret = SSH_ERR_INTERNAL_ERROR;
1340 struct sshbuf *b = NULL, *bb = NULL;
1341 char *uu = NULL;
1342#ifdef WITH_SSH1
1343 u_int bits = 0;
1344 char *dec_e = NULL, *dec_n = NULL;
1345#endif /* WITH_SSH1 */
1346
1347 if (sshkey_is_cert(key)) {
1348 if (key->cert == NULL)
1349 return SSH_ERR_EXPECTED_CERT;
1350 if (sshbuf_len(key->cert->certblob) == 0)
1351 return SSH_ERR_KEY_LACKS_CERTBLOB;
1352 }
1353 if ((b = sshbuf_new()) == NULL)
1354 return SSH_ERR_ALLOC_FAIL;
1355 switch (key->type) {
1356#ifdef WITH_SSH1
1357 case KEY_RSA1:
1358 if (key->rsa == NULL || key->rsa->e == NULL ||
1359 key->rsa->n == NULL) {
1360 ret = SSH_ERR_INVALID_ARGUMENT;
1361 goto out;
1362 }
1363 if ((dec_e = BN_bn2dec(key->rsa->e)) == NULL ||
1364 (dec_n = BN_bn2dec(key->rsa->n)) == NULL) {
1365 ret = SSH_ERR_ALLOC_FAIL;
1366 goto out;
1367 }
1368 /* size of modulus 'n' */
1369 if ((bits = BN_num_bits(key->rsa->n)) <= 0) {
1370 ret = SSH_ERR_INVALID_ARGUMENT;
1371 goto out;
1372 }
1373 if ((ret = sshbuf_putf(b, "%u %s %s", bits, dec_e, dec_n)) != 0)
1374 goto out;
1375#endif /* WITH_SSH1 */
1376 break;
1377#ifdef WITH_OPENSSL
1378 case KEY_DSA:
1379 case KEY_DSA_CERT_V00:
1380 case KEY_DSA_CERT:
1381 case KEY_ECDSA:
1382 case KEY_ECDSA_CERT:
1383 case KEY_RSA:
1384 case KEY_RSA_CERT_V00:
1385 case KEY_RSA_CERT:
1386#endif /* WITH_OPENSSL */
1387 case KEY_ED25519:
1388 case KEY_ED25519_CERT:
1389 if ((bb = sshbuf_new()) == NULL) {
1390 ret = SSH_ERR_ALLOC_FAIL;
1391 goto out;
1392 }
1393 if ((ret = sshkey_to_blob_buf(key, bb)) != 0)
1394 goto out;
1395 if ((uu = sshbuf_dtob64(bb)) == NULL) {
1396 ret = SSH_ERR_ALLOC_FAIL;
1397 goto out;
1398 }
1399 if ((ret = sshbuf_putf(b, "%s ", sshkey_ssh_name(key))) != 0)
1400 goto out;
1401 if ((ret = sshbuf_put(b, uu, strlen(uu))) != 0)
1402 goto out;
1403 break;
1404 default:
1405 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
1406 goto out;
1407 }
1408 if (fwrite(sshbuf_ptr(b), sshbuf_len(b), 1, f) != 1) {
1409 if (feof(f))
1410 errno = EPIPE;
1411 ret = SSH_ERR_SYSTEM_ERROR;
1412 goto out;
1413 }
1414 ret = 0;
1415 out:
1416 if (b != NULL)
1417 sshbuf_free(b);
1418 if (bb != NULL)
1419 sshbuf_free(bb);
1420 if (uu != NULL)
1421 free(uu);
1422#ifdef WITH_SSH1
1423 if (dec_e != NULL)
1424 OPENSSL_free(dec_e);
1425 if (dec_n != NULL)
1426 OPENSSL_free(dec_n);
1427#endif /* WITH_SSH1 */
1428 return ret;
1429}
1430
1431const char *
1432sshkey_cert_type(const struct sshkey *k)
1433{
1434 switch (k->cert->type) {
1435 case SSH2_CERT_TYPE_USER:
1436 return "user";
1437 case SSH2_CERT_TYPE_HOST:
1438 return "host";
1439 default:
1440 return "unknown";
1441 }
1442}
1443
1444#ifdef WITH_OPENSSL
1445static int
1446rsa_generate_private_key(u_int bits, RSA **rsap)
1447{
1448 RSA *private = NULL;
1449 BIGNUM *f4 = NULL;
1450 int ret = SSH_ERR_INTERNAL_ERROR;
1451
1452 if (rsap == NULL ||
1453 bits < SSH_RSA_MINIMUM_MODULUS_SIZE ||
1454 bits > SSHBUF_MAX_BIGNUM * 8)
1455 return SSH_ERR_INVALID_ARGUMENT;
1456 *rsap = NULL;
1457 if ((private = RSA_new()) == NULL || (f4 = BN_new()) == NULL) {
1458 ret = SSH_ERR_ALLOC_FAIL;
1459 goto out;
1460 }
1461 if (!BN_set_word(f4, RSA_F4) ||
1462 !RSA_generate_key_ex(private, bits, f4, NULL)) {
1463 ret = SSH_ERR_LIBCRYPTO_ERROR;
1464 goto out;
1465 }
1466 *rsap = private;
1467 private = NULL;
1468 ret = 0;
1469 out:
1470 if (private != NULL)
1471 RSA_free(private);
1472 if (f4 != NULL)
1473 BN_free(f4);
1474 return ret;
1475}
1476
1477static int
1478dsa_generate_private_key(u_int bits, DSA **dsap)
1479{
1480 DSA *private;
1481 int ret = SSH_ERR_INTERNAL_ERROR;
1482
1483 if (dsap == NULL || bits != 1024)
1484 return SSH_ERR_INVALID_ARGUMENT;
1485 if ((private = DSA_new()) == NULL) {
1486 ret = SSH_ERR_ALLOC_FAIL;
1487 goto out;
1488 }
1489 *dsap = NULL;
1490 if (!DSA_generate_parameters_ex(private, bits, NULL, 0, NULL,
1491 NULL, NULL) || !DSA_generate_key(private)) {
1492 DSA_free(private);
1493 ret = SSH_ERR_LIBCRYPTO_ERROR;
1494 goto out;
1495 }
1496 *dsap = private;
1497 private = NULL;
1498 ret = 0;
1499 out:
1500 if (private != NULL)
1501 DSA_free(private);
1502 return ret;
1503}
1504
1505# ifdef OPENSSL_HAS_ECC
1506int
1507sshkey_ecdsa_key_to_nid(EC_KEY *k)
1508{
1509 EC_GROUP *eg;
1510 int nids[] = {
1511 NID_X9_62_prime256v1,
1512 NID_secp384r1,
1513# ifdef OPENSSL_HAS_NISTP521
1514 NID_secp521r1,
1515# endif /* OPENSSL_HAS_NISTP521 */
1516 -1
1517 };
1518 int nid;
1519 u_int i;
1520 BN_CTX *bnctx;
1521 const EC_GROUP *g = EC_KEY_get0_group(k);
1522
1523 /*
1524 * The group may be stored in a ASN.1 encoded private key in one of two
1525 * ways: as a "named group", which is reconstituted by ASN.1 object ID
1526 * or explicit group parameters encoded into the key blob. Only the
1527 * "named group" case sets the group NID for us, but we can figure
1528 * it out for the other case by comparing against all the groups that
1529 * are supported.
1530 */
1531 if ((nid = EC_GROUP_get_curve_name(g)) > 0)
1532 return nid;
1533 if ((bnctx = BN_CTX_new()) == NULL)
1534 return -1;
1535 for (i = 0; nids[i] != -1; i++) {
1536 if ((eg = EC_GROUP_new_by_curve_name(nids[i])) == NULL) {
1537 BN_CTX_free(bnctx);
1538 return -1;
1539 }
1540 if (EC_GROUP_cmp(g, eg, bnctx) == 0)
1541 break;
1542 EC_GROUP_free(eg);
1543 }
1544 BN_CTX_free(bnctx);
1545 if (nids[i] != -1) {
1546 /* Use the group with the NID attached */
1547 EC_GROUP_set_asn1_flag(eg, OPENSSL_EC_NAMED_CURVE);
1548 if (EC_KEY_set_group(k, eg) != 1) {
1549 EC_GROUP_free(eg);
1550 return -1;
1551 }
1552 }
1553 return nids[i];
1554}
1555
1556static int
1557ecdsa_generate_private_key(u_int bits, int *nid, EC_KEY **ecdsap)
1558{
1559 EC_KEY *private;
1560 int ret = SSH_ERR_INTERNAL_ERROR;
1561
1562 if (nid == NULL || ecdsap == NULL ||
1563 (*nid = sshkey_ecdsa_bits_to_nid(bits)) == -1)
1564 return SSH_ERR_INVALID_ARGUMENT;
1565 *ecdsap = NULL;
1566 if ((private = EC_KEY_new_by_curve_name(*nid)) == NULL) {
1567 ret = SSH_ERR_ALLOC_FAIL;
1568 goto out;
1569 }
1570 if (EC_KEY_generate_key(private) != 1) {
1571 ret = SSH_ERR_LIBCRYPTO_ERROR;
1572 goto out;
1573 }
1574 EC_KEY_set_asn1_flag(private, OPENSSL_EC_NAMED_CURVE);
1575 *ecdsap = private;
1576 private = NULL;
1577 ret = 0;
1578 out:
1579 if (private != NULL)
1580 EC_KEY_free(private);
1581 return ret;
1582}
1583# endif /* OPENSSL_HAS_ECC */
1584#endif /* WITH_OPENSSL */
1585
1586int
1587sshkey_generate(int type, u_int bits, struct sshkey **keyp)
1588{
1589 struct sshkey *k;
1590 int ret = SSH_ERR_INTERNAL_ERROR;
1591
1592 if (keyp == NULL)
1593 return SSH_ERR_INVALID_ARGUMENT;
1594 *keyp = NULL;
1595 if ((k = sshkey_new(KEY_UNSPEC)) == NULL)
1596 return SSH_ERR_ALLOC_FAIL;
1597 switch (type) {
1598 case KEY_ED25519:
1599 if ((k->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL ||
1600 (k->ed25519_sk = malloc(ED25519_SK_SZ)) == NULL) {
1601 ret = SSH_ERR_ALLOC_FAIL;
1602 break;
1603 }
1604 crypto_sign_ed25519_keypair(k->ed25519_pk, k->ed25519_sk);
1605 ret = 0;
1606 break;
1607#ifdef WITH_OPENSSL
1608 case KEY_DSA:
1609 ret = dsa_generate_private_key(bits, &k->dsa);
1610 break;
1611# ifdef OPENSSL_HAS_ECC
1612 case KEY_ECDSA:
1613 ret = ecdsa_generate_private_key(bits, &k->ecdsa_nid,
1614 &k->ecdsa);
1615 break;
1616# endif /* OPENSSL_HAS_ECC */
1617 case KEY_RSA:
1618 case KEY_RSA1:
1619 ret = rsa_generate_private_key(bits, &k->rsa);
1620 break;
1621#endif /* WITH_OPENSSL */
1622 default:
1623 ret = SSH_ERR_INVALID_ARGUMENT;
1624 }
1625 if (ret == 0) {
1626 k->type = type;
1627 *keyp = k;
1628 } else
1629 sshkey_free(k);
1630 return ret;
1631}
1632
1633int
1634sshkey_cert_copy(const struct sshkey *from_key, struct sshkey *to_key)
1635{
1636 u_int i;
1637 const struct sshkey_cert *from;
1638 struct sshkey_cert *to;
1639 int ret = SSH_ERR_INTERNAL_ERROR;
1640
1641 if (to_key->cert != NULL) {
1642 cert_free(to_key->cert);
1643 to_key->cert = NULL;
1644 }
1645
1646 if ((from = from_key->cert) == NULL)
1647 return SSH_ERR_INVALID_ARGUMENT;
1648
1649 if ((to = to_key->cert = cert_new()) == NULL)
1650 return SSH_ERR_ALLOC_FAIL;
1651
1652 if ((ret = sshbuf_putb(to->certblob, from->certblob)) != 0 ||
1653 (ret = sshbuf_putb(to->critical, from->critical)) != 0 ||
1654 (ret = sshbuf_putb(to->extensions, from->extensions) != 0))
1655 return ret;
1656
1657 to->serial = from->serial;
1658 to->type = from->type;
1659 if (from->key_id == NULL)
1660 to->key_id = NULL;
1661 else if ((to->key_id = strdup(from->key_id)) == NULL)
1662 return SSH_ERR_ALLOC_FAIL;
1663 to->valid_after = from->valid_after;
1664 to->valid_before = from->valid_before;
1665 if (from->signature_key == NULL)
1666 to->signature_key = NULL;
1667 else if ((ret = sshkey_from_private(from->signature_key,
1668 &to->signature_key)) != 0)
1669 return ret;
1670
1671 if (from->nprincipals > SSHKEY_CERT_MAX_PRINCIPALS)
1672 return SSH_ERR_INVALID_ARGUMENT;
1673 if (from->nprincipals > 0) {
1674 if ((to->principals = calloc(from->nprincipals,
1675 sizeof(*to->principals))) == NULL)
1676 return SSH_ERR_ALLOC_FAIL;
1677 for (i = 0; i < from->nprincipals; i++) {
1678 to->principals[i] = strdup(from->principals[i]);
1679 if (to->principals[i] == NULL) {
1680 to->nprincipals = i;
1681 return SSH_ERR_ALLOC_FAIL;
1682 }
1683 }
1684 }
1685 to->nprincipals = from->nprincipals;
1686 return 0;
1687}
1688
1689int
1690sshkey_from_private(const struct sshkey *k, struct sshkey **pkp)
1691{
1692 struct sshkey *n = NULL;
1693 int ret = SSH_ERR_INTERNAL_ERROR;
1694
1695 if (pkp != NULL)
1696 *pkp = NULL;
1697
1698 switch (k->type) {
1699#ifdef WITH_OPENSSL
1700 case KEY_DSA:
1701 case KEY_DSA_CERT_V00:
1702 case KEY_DSA_CERT:
1703 if ((n = sshkey_new(k->type)) == NULL)
1704 return SSH_ERR_ALLOC_FAIL;
1705 if ((BN_copy(n->dsa->p, k->dsa->p) == NULL) ||
1706 (BN_copy(n->dsa->q, k->dsa->q) == NULL) ||
1707 (BN_copy(n->dsa->g, k->dsa->g) == NULL) ||
1708 (BN_copy(n->dsa->pub_key, k->dsa->pub_key) == NULL)) {
1709 sshkey_free(n);
1710 return SSH_ERR_ALLOC_FAIL;
1711 }
1712 break;
1713# ifdef OPENSSL_HAS_ECC
1714 case KEY_ECDSA:
1715 case KEY_ECDSA_CERT:
1716 if ((n = sshkey_new(k->type)) == NULL)
1717 return SSH_ERR_ALLOC_FAIL;
1718 n->ecdsa_nid = k->ecdsa_nid;
1719 n->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
1720 if (n->ecdsa == NULL) {
1721 sshkey_free(n);
1722 return SSH_ERR_ALLOC_FAIL;
1723 }
1724 if (EC_KEY_set_public_key(n->ecdsa,
1725 EC_KEY_get0_public_key(k->ecdsa)) != 1) {
1726 sshkey_free(n);
1727 return SSH_ERR_LIBCRYPTO_ERROR;
1728 }
1729 break;
1730# endif /* OPENSSL_HAS_ECC */
1731 case KEY_RSA:
1732 case KEY_RSA1:
1733 case KEY_RSA_CERT_V00:
1734 case KEY_RSA_CERT:
1735 if ((n = sshkey_new(k->type)) == NULL)
1736 return SSH_ERR_ALLOC_FAIL;
1737 if ((BN_copy(n->rsa->n, k->rsa->n) == NULL) ||
1738 (BN_copy(n->rsa->e, k->rsa->e) == NULL)) {
1739 sshkey_free(n);
1740 return SSH_ERR_ALLOC_FAIL;
1741 }
1742 break;
1743#endif /* WITH_OPENSSL */
1744 case KEY_ED25519:
1745 case KEY_ED25519_CERT:
1746 if ((n = sshkey_new(k->type)) == NULL)
1747 return SSH_ERR_ALLOC_FAIL;
1748 if (k->ed25519_pk != NULL) {
1749 if ((n->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
1750 sshkey_free(n);
1751 return SSH_ERR_ALLOC_FAIL;
1752 }
1753 memcpy(n->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
1754 }
1755 break;
1756 default:
1757 return SSH_ERR_KEY_TYPE_UNKNOWN;
1758 }
1759 if (sshkey_is_cert(k)) {
1760 if ((ret = sshkey_cert_copy(k, n)) != 0) {
1761 sshkey_free(n);
1762 return ret;
1763 }
1764 }
1765 *pkp = n;
1766 return 0;
1767}
1768
1769static int
1770cert_parse(struct sshbuf *b, struct sshkey *key, const u_char *blob,
1771 size_t blen)
1772{
1773 u_char *principals = NULL, *critical = NULL, *exts = NULL;
1774 u_char *sig_key = NULL, *sig = NULL;
1775 size_t signed_len, plen, clen, sklen, slen, kidlen, elen;
1776 struct sshbuf *tmp;
1777 char *principal;
1778 int ret = SSH_ERR_INTERNAL_ERROR;
1779 int v00 = sshkey_cert_is_legacy(key);
1780 char **oprincipals;
1781
1782 if ((tmp = sshbuf_new()) == NULL)
1783 return SSH_ERR_ALLOC_FAIL;
1784
1785 /* Copy the entire key blob for verification and later serialisation */
1786 if ((ret = sshbuf_put(key->cert->certblob, blob, blen)) != 0)
1787 return ret;
1788
1789 elen = 0; /* Not touched for v00 certs */
1790 principals = exts = critical = sig_key = sig = NULL;
1791 if ((!v00 && (ret = sshbuf_get_u64(b, &key->cert->serial)) != 0) ||
1792 (ret = sshbuf_get_u32(b, &key->cert->type)) != 0 ||
1793 (ret = sshbuf_get_cstring(b, &key->cert->key_id, &kidlen)) != 0 ||
1794 (ret = sshbuf_get_string(b, &principals, &plen)) != 0 ||
1795 (ret = sshbuf_get_u64(b, &key->cert->valid_after)) != 0 ||
1796 (ret = sshbuf_get_u64(b, &key->cert->valid_before)) != 0 ||
1797 (ret = sshbuf_get_string(b, &critical, &clen)) != 0 ||
1798 (!v00 && (ret = sshbuf_get_string(b, &exts, &elen)) != 0) ||
1799 (v00 && (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0) ||
1800 (ret = sshbuf_get_string_direct(b, NULL, NULL)) != 0 ||
1801 (ret = sshbuf_get_string(b, &sig_key, &sklen)) != 0) {
1802 /* XXX debug print error for ret */
1803 ret = SSH_ERR_INVALID_FORMAT;
1804 goto out;
1805 }
1806
1807 /* Signature is left in the buffer so we can calculate this length */
1808 signed_len = sshbuf_len(key->cert->certblob) - sshbuf_len(b);
1809
1810 if ((ret = sshbuf_get_string(b, &sig, &slen)) != 0) {
1811 ret = SSH_ERR_INVALID_FORMAT;
1812 goto out;
1813 }
1814
1815 if (key->cert->type != SSH2_CERT_TYPE_USER &&
1816 key->cert->type != SSH2_CERT_TYPE_HOST) {
1817 ret = SSH_ERR_KEY_CERT_UNKNOWN_TYPE;
1818 goto out;
1819 }
1820
1821 if ((ret = sshbuf_put(tmp, principals, plen)) != 0)
1822 goto out;
1823 while (sshbuf_len(tmp) > 0) {
1824 if (key->cert->nprincipals >= SSHKEY_CERT_MAX_PRINCIPALS) {
1825 ret = SSH_ERR_INVALID_FORMAT;
1826 goto out;
1827 }
1828 if ((ret = sshbuf_get_cstring(tmp, &principal, &plen)) != 0) {
1829 ret = SSH_ERR_INVALID_FORMAT;
1830 goto out;
1831 }
1832 oprincipals = key->cert->principals;
1833 key->cert->principals = realloc(key->cert->principals,
1834 (key->cert->nprincipals + 1) *
1835 sizeof(*key->cert->principals));
1836 if (key->cert->principals == NULL) {
1837 free(principal);
1838 key->cert->principals = oprincipals;
1839 ret = SSH_ERR_ALLOC_FAIL;
1840 goto out;
1841 }
1842 key->cert->principals[key->cert->nprincipals++] = principal;
1843 }
1844
1845 sshbuf_reset(tmp);
1846
1847 if ((ret = sshbuf_put(key->cert->critical, critical, clen)) != 0 ||
1848 (ret = sshbuf_put(tmp, critical, clen)) != 0)
1849 goto out;
1850
1851 /* validate structure */
1852 while (sshbuf_len(tmp) != 0) {
1853 if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 ||
1854 (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) {
1855 ret = SSH_ERR_INVALID_FORMAT;
1856 goto out;
1857 }
1858 }
1859 sshbuf_reset(tmp);
1860
1861 if ((ret = sshbuf_put(key->cert->extensions, exts, elen)) != 0 ||
1862 (ret = sshbuf_put(tmp, exts, elen)) != 0)
1863 goto out;
1864
1865 /* validate structure */
1866 while (sshbuf_len(tmp) != 0) {
1867 if ((ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0 ||
1868 (ret = sshbuf_get_string_direct(tmp, NULL, NULL)) != 0) {
1869 ret = SSH_ERR_INVALID_FORMAT;
1870 goto out;
1871 }
1872 }
1873 sshbuf_reset(tmp);
1874
1875 if (sshkey_from_blob_internal(sig_key, sklen,
1876 &key->cert->signature_key, 0) != 0) {
1877 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1878 goto out;
1879 }
1880 if (!sshkey_type_is_valid_ca(key->cert->signature_key->type)) {
1881 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1882 goto out;
1883 }
1884
1885 if ((ret = sshkey_verify(key->cert->signature_key, sig, slen,
1886 sshbuf_ptr(key->cert->certblob), signed_len, 0)) != 0)
1887 goto out;
1888 ret = 0;
1889
1890 out:
1891 sshbuf_free(tmp);
1892 free(principals);
1893 free(critical);
1894 free(exts);
1895 free(sig_key);
1896 free(sig);
1897 return ret;
1898}
1899
1900static int
1901sshkey_from_blob_internal(const u_char *blob, size_t blen,
1902 struct sshkey **keyp, int allow_cert)
1903{
1904 struct sshbuf *b = NULL;
1905 int type, nid = -1, ret = SSH_ERR_INTERNAL_ERROR;
1906 char *ktype = NULL, *curve = NULL;
1907 struct sshkey *key = NULL;
1908 size_t len;
1909 u_char *pk = NULL;
1910#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
1911 EC_POINT *q = NULL;
1912#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
1913
1914#ifdef DEBUG_PK /* XXX */
1915 dump_base64(stderr, blob, blen);
1916#endif
1917 *keyp = NULL;
1918 if ((b = sshbuf_from(blob, blen)) == NULL)
1919 return SSH_ERR_ALLOC_FAIL;
1920 if (sshbuf_get_cstring(b, &ktype, NULL) != 0) {
1921 ret = SSH_ERR_INVALID_FORMAT;
1922 goto out;
1923 }
1924
1925 type = sshkey_type_from_name(ktype);
1926 if (sshkey_type_plain(type) == KEY_ECDSA)
1927 nid = sshkey_ecdsa_nid_from_name(ktype);
1928 if (!allow_cert && sshkey_type_is_cert(type)) {
1929 ret = SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
1930 goto out;
1931 }
1932 switch (type) {
1933#ifdef WITH_OPENSSL
1934 case KEY_RSA_CERT:
1935 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1936 ret = SSH_ERR_INVALID_FORMAT;
1937 goto out;
1938 }
1939 /* FALLTHROUGH */
1940 case KEY_RSA:
1941 case KEY_RSA_CERT_V00:
1942 if ((key = sshkey_new(type)) == NULL) {
1943 ret = SSH_ERR_ALLOC_FAIL;
1944 goto out;
1945 }
1946 if (sshbuf_get_bignum2(b, key->rsa->e) == -1 ||
1947 sshbuf_get_bignum2(b, key->rsa->n) == -1) {
1948 ret = SSH_ERR_INVALID_FORMAT;
1949 goto out;
1950 }
1951#ifdef DEBUG_PK
1952 RSA_print_fp(stderr, key->rsa, 8);
1953#endif
1954 break;
1955 case KEY_DSA_CERT:
1956 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1957 ret = SSH_ERR_INVALID_FORMAT;
1958 goto out;
1959 }
1960 /* FALLTHROUGH */
1961 case KEY_DSA:
1962 case KEY_DSA_CERT_V00:
1963 if ((key = sshkey_new(type)) == NULL) {
1964 ret = SSH_ERR_ALLOC_FAIL;
1965 goto out;
1966 }
1967 if (sshbuf_get_bignum2(b, key->dsa->p) == -1 ||
1968 sshbuf_get_bignum2(b, key->dsa->q) == -1 ||
1969 sshbuf_get_bignum2(b, key->dsa->g) == -1 ||
1970 sshbuf_get_bignum2(b, key->dsa->pub_key) == -1) {
1971 ret = SSH_ERR_INVALID_FORMAT;
1972 goto out;
1973 }
1974#ifdef DEBUG_PK
1975 DSA_print_fp(stderr, key->dsa, 8);
1976#endif
1977 break;
1978 case KEY_ECDSA_CERT:
1979 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
1980 ret = SSH_ERR_INVALID_FORMAT;
1981 goto out;
1982 }
1983 /* FALLTHROUGH */
1984# ifdef OPENSSL_HAS_ECC
1985 case KEY_ECDSA:
1986 if ((key = sshkey_new(type)) == NULL) {
1987 ret = SSH_ERR_ALLOC_FAIL;
1988 goto out;
1989 }
1990 key->ecdsa_nid = nid;
1991 if (sshbuf_get_cstring(b, &curve, NULL) != 0) {
1992 ret = SSH_ERR_INVALID_FORMAT;
1993 goto out;
1994 }
1995 if (key->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
1996 ret = SSH_ERR_EC_CURVE_MISMATCH;
1997 goto out;
1998 }
1999 if (key->ecdsa != NULL)
2000 EC_KEY_free(key->ecdsa);
2001 if ((key->ecdsa = EC_KEY_new_by_curve_name(key->ecdsa_nid))
2002 == NULL) {
2003 ret = SSH_ERR_EC_CURVE_INVALID;
2004 goto out;
2005 }
2006 if ((q = EC_POINT_new(EC_KEY_get0_group(key->ecdsa))) == NULL) {
2007 ret = SSH_ERR_ALLOC_FAIL;
2008 goto out;
2009 }
2010 if (sshbuf_get_ec(b, q, EC_KEY_get0_group(key->ecdsa)) != 0) {
2011 ret = SSH_ERR_INVALID_FORMAT;
2012 goto out;
2013 }
2014 if (sshkey_ec_validate_public(EC_KEY_get0_group(key->ecdsa),
2015 q) != 0) {
2016 ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2017 goto out;
2018 }
2019 if (EC_KEY_set_public_key(key->ecdsa, q) != 1) {
2020 /* XXX assume it is a allocation error */
2021 ret = SSH_ERR_ALLOC_FAIL;
2022 goto out;
2023 }
2024#ifdef DEBUG_PK
2025 sshkey_dump_ec_point(EC_KEY_get0_group(key->ecdsa), q);
2026#endif
2027 break;
2028# endif /* OPENSSL_HAS_ECC */
2029#endif /* WITH_OPENSSL */
2030 case KEY_ED25519_CERT:
2031 if (sshbuf_get_string_direct(b, NULL, NULL) != 0) {
2032 ret = SSH_ERR_INVALID_FORMAT;
2033 goto out;
2034 }
2035 /* FALLTHROUGH */
2036 case KEY_ED25519:
2037 if ((ret = sshbuf_get_string(b, &pk, &len)) != 0)
2038 goto out;
2039 if (len != ED25519_PK_SZ) {
2040 ret = SSH_ERR_INVALID_FORMAT;
2041 goto out;
2042 }
2043 if ((key = sshkey_new(type)) == NULL) {
2044 ret = SSH_ERR_ALLOC_FAIL;
2045 goto out;
2046 }
2047 key->ed25519_pk = pk;
2048 pk = NULL;
2049 break;
2050 case KEY_UNSPEC:
2051 if ((key = sshkey_new(type)) == NULL) {
2052 ret = SSH_ERR_ALLOC_FAIL;
2053 goto out;
2054 }
2055 break;
2056 default:
2057 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2058 goto out;
2059 }
2060
2061 /* Parse certificate potion */
2062 if (sshkey_is_cert(key) &&
2063 (ret = cert_parse(b, key, blob, blen)) != 0)
2064 goto out;
2065
2066 if (key != NULL && sshbuf_len(b) != 0) {
2067 ret = SSH_ERR_INVALID_FORMAT;
2068 goto out;
2069 }
2070 ret = 0;
2071 *keyp = key;
2072 key = NULL;
2073 out:
2074 sshbuf_free(b);
2075 sshkey_free(key);
2076 free(ktype);
2077 free(curve);
2078 free(pk);
2079#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2080 if (q != NULL)
2081 EC_POINT_free(q);
2082#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2083 return ret;
2084}
2085
2086int
2087sshkey_from_blob(const u_char *blob, size_t blen, struct sshkey **keyp)
2088{
2089 return sshkey_from_blob_internal(blob, blen, keyp, 1);
2090}
2091
2092int
2093sshkey_sign(const struct sshkey *key,
2094 u_char **sigp, size_t *lenp,
2095 const u_char *data, size_t datalen, u_int compat)
2096{
2097 if (sigp != NULL)
2098 *sigp = NULL;
2099 if (lenp != NULL)
2100 *lenp = 0;
2101 if (datalen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2102 return SSH_ERR_INVALID_ARGUMENT;
2103 switch (key->type) {
2104#ifdef WITH_OPENSSL
2105 case KEY_DSA_CERT_V00:
2106 case KEY_DSA_CERT:
2107 case KEY_DSA:
2108 return ssh_dss_sign(key, sigp, lenp, data, datalen, compat);
2109# ifdef OPENSSL_HAS_ECC
2110 case KEY_ECDSA_CERT:
2111 case KEY_ECDSA:
2112 return ssh_ecdsa_sign(key, sigp, lenp, data, datalen, compat);
2113# endif /* OPENSSL_HAS_ECC */
2114 case KEY_RSA_CERT_V00:
2115 case KEY_RSA_CERT:
2116 case KEY_RSA:
2117 return ssh_rsa_sign(key, sigp, lenp, data, datalen, compat);
2118#endif /* WITH_OPENSSL */
2119 case KEY_ED25519:
2120 case KEY_ED25519_CERT:
2121 return ssh_ed25519_sign(key, sigp, lenp, data, datalen, compat);
2122 default:
2123 return SSH_ERR_KEY_TYPE_UNKNOWN;
2124 }
2125}
2126
2127/*
2128 * ssh_key_verify returns 0 for a correct signature and < 0 on error.
2129 */
2130int
2131sshkey_verify(const struct sshkey *key,
2132 const u_char *sig, size_t siglen,
2133 const u_char *data, size_t dlen, u_int compat)
2134{
2135 if (siglen == 0)
2136 return -1;
2137
2138 if (dlen > SSH_KEY_MAX_SIGN_DATA_SIZE)
2139 return SSH_ERR_INVALID_ARGUMENT;
2140 switch (key->type) {
2141#ifdef WITH_OPENSSL
2142 case KEY_DSA_CERT_V00:
2143 case KEY_DSA_CERT:
2144 case KEY_DSA:
2145 return ssh_dss_verify(key, sig, siglen, data, dlen, compat);
2146# ifdef OPENSSL_HAS_ECC
2147 case KEY_ECDSA_CERT:
2148 case KEY_ECDSA:
2149 return ssh_ecdsa_verify(key, sig, siglen, data, dlen, compat);
2150# endif /* OPENSSL_HAS_ECC */
2151 case KEY_RSA_CERT_V00:
2152 case KEY_RSA_CERT:
2153 case KEY_RSA:
2154 return ssh_rsa_verify(key, sig, siglen, data, dlen, compat);
2155#endif /* WITH_OPENSSL */
2156 case KEY_ED25519:
2157 case KEY_ED25519_CERT:
2158 return ssh_ed25519_verify(key, sig, siglen, data, dlen, compat);
2159 default:
2160 return SSH_ERR_KEY_TYPE_UNKNOWN;
2161 }
2162}
2163
2164/* Converts a private to a public key */
2165int
2166sshkey_demote(const struct sshkey *k, struct sshkey **dkp)
2167{
2168 struct sshkey *pk;
2169 int ret = SSH_ERR_INTERNAL_ERROR;
2170
2171 if (dkp != NULL)
2172 *dkp = NULL;
2173
2174 if ((pk = calloc(1, sizeof(*pk))) == NULL)
2175 return SSH_ERR_ALLOC_FAIL;
2176 pk->type = k->type;
2177 pk->flags = k->flags;
2178 pk->ecdsa_nid = k->ecdsa_nid;
2179 pk->dsa = NULL;
2180 pk->ecdsa = NULL;
2181 pk->rsa = NULL;
2182 pk->ed25519_pk = NULL;
2183 pk->ed25519_sk = NULL;
2184
2185 switch (k->type) {
2186#ifdef WITH_OPENSSL
2187 case KEY_RSA_CERT_V00:
2188 case KEY_RSA_CERT:
2189 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2190 goto fail;
2191 /* FALLTHROUGH */
2192 case KEY_RSA1:
2193 case KEY_RSA:
2194 if ((pk->rsa = RSA_new()) == NULL ||
2195 (pk->rsa->e = BN_dup(k->rsa->e)) == NULL ||
2196 (pk->rsa->n = BN_dup(k->rsa->n)) == NULL) {
2197 ret = SSH_ERR_ALLOC_FAIL;
2198 goto fail;
2199 }
2200 break;
2201 case KEY_DSA_CERT_V00:
2202 case KEY_DSA_CERT:
2203 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2204 goto fail;
2205 /* FALLTHROUGH */
2206 case KEY_DSA:
2207 if ((pk->dsa = DSA_new()) == NULL ||
2208 (pk->dsa->p = BN_dup(k->dsa->p)) == NULL ||
2209 (pk->dsa->q = BN_dup(k->dsa->q)) == NULL ||
2210 (pk->dsa->g = BN_dup(k->dsa->g)) == NULL ||
2211 (pk->dsa->pub_key = BN_dup(k->dsa->pub_key)) == NULL) {
2212 ret = SSH_ERR_ALLOC_FAIL;
2213 goto fail;
2214 }
2215 break;
2216 case KEY_ECDSA_CERT:
2217 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2218 goto fail;
2219 /* FALLTHROUGH */
2220# ifdef OPENSSL_HAS_ECC
2221 case KEY_ECDSA:
2222 pk->ecdsa = EC_KEY_new_by_curve_name(pk->ecdsa_nid);
2223 if (pk->ecdsa == NULL) {
2224 ret = SSH_ERR_ALLOC_FAIL;
2225 goto fail;
2226 }
2227 if (EC_KEY_set_public_key(pk->ecdsa,
2228 EC_KEY_get0_public_key(k->ecdsa)) != 1) {
2229 ret = SSH_ERR_LIBCRYPTO_ERROR;
2230 goto fail;
2231 }
2232 break;
2233# endif /* OPENSSL_HAS_ECC */
2234#endif /* WITH_OPENSSL */
2235 case KEY_ED25519_CERT:
2236 if ((ret = sshkey_cert_copy(k, pk)) != 0)
2237 goto fail;
2238 /* FALLTHROUGH */
2239 case KEY_ED25519:
2240 if (k->ed25519_pk != NULL) {
2241 if ((pk->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
2242 ret = SSH_ERR_ALLOC_FAIL;
2243 goto fail;
2244 }
2245 memcpy(pk->ed25519_pk, k->ed25519_pk, ED25519_PK_SZ);
2246 }
2247 break;
2248 default:
2249 ret = SSH_ERR_KEY_TYPE_UNKNOWN;
2250 fail:
2251 sshkey_free(pk);
2252 return ret;
2253 }
2254 *dkp = pk;
2255 return 0;
2256}
2257
2258/* Convert a plain key to their _CERT equivalent */
2259int
2260sshkey_to_certified(struct sshkey *k, int legacy)
2261{
2262 int newtype;
2263
2264 switch (k->type) {
2265#ifdef WITH_OPENSSL
2266 case KEY_RSA:
2267 newtype = legacy ? KEY_RSA_CERT_V00 : KEY_RSA_CERT;
2268 break;
2269 case KEY_DSA:
2270 newtype = legacy ? KEY_DSA_CERT_V00 : KEY_DSA_CERT;
2271 break;
2272 case KEY_ECDSA:
2273 if (legacy)
2274 return SSH_ERR_INVALID_ARGUMENT;
2275 newtype = KEY_ECDSA_CERT;
2276 break;
2277#endif /* WITH_OPENSSL */
2278 case KEY_ED25519:
2279 if (legacy)
2280 return SSH_ERR_INVALID_ARGUMENT;
2281 newtype = KEY_ED25519_CERT;
2282 break;
2283 default:
2284 return SSH_ERR_INVALID_ARGUMENT;
2285 }
2286 if ((k->cert = cert_new()) == NULL)
2287 return SSH_ERR_ALLOC_FAIL;
2288 k->type = newtype;
2289 return 0;
2290}
2291
2292/* Convert a certificate to its raw key equivalent */
2293int
2294sshkey_drop_cert(struct sshkey *k)
2295{
2296 if (!sshkey_type_is_cert(k->type))
2297 return SSH_ERR_KEY_TYPE_UNKNOWN;
2298 cert_free(k->cert);
2299 k->cert = NULL;
2300 k->type = sshkey_type_plain(k->type);
2301 return 0;
2302}
2303
2304/* Sign a certified key, (re-)generating the signed certblob. */
2305int
2306sshkey_certify(struct sshkey *k, struct sshkey *ca)
2307{
2308 struct sshbuf *principals = NULL;
2309 u_char *ca_blob = NULL, *sig_blob = NULL, nonce[32];
2310 size_t i, ca_len, sig_len;
2311 int ret = SSH_ERR_INTERNAL_ERROR;
2312 struct sshbuf *cert;
2313
2314 if (k == NULL || k->cert == NULL ||
2315 k->cert->certblob == NULL || ca == NULL)
2316 return SSH_ERR_INVALID_ARGUMENT;
2317 if (!sshkey_is_cert(k))
2318 return SSH_ERR_KEY_TYPE_UNKNOWN;
2319 if (!sshkey_type_is_valid_ca(ca->type))
2320 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2321
2322 if ((ret = sshkey_to_blob(ca, &ca_blob, &ca_len)) != 0)
2323 return SSH_ERR_KEY_CERT_INVALID_SIGN_KEY;
2324
2325 cert = k->cert->certblob; /* for readability */
2326 sshbuf_reset(cert);
2327 if ((ret = sshbuf_put_cstring(cert, sshkey_ssh_name(k))) != 0)
2328 goto out;
2329
2330 /* -v01 certs put nonce first */
2331 arc4random_buf(&nonce, sizeof(nonce));
2332 if (!sshkey_cert_is_legacy(k)) {
2333 if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2334 goto out;
2335 }
2336
2337 /* XXX this substantially duplicates to_blob(); refactor */
2338 switch (k->type) {
2339#ifdef WITH_OPENSSL
2340 case KEY_DSA_CERT_V00:
2341 case KEY_DSA_CERT:
2342 if ((ret = sshbuf_put_bignum2(cert, k->dsa->p)) != 0 ||
2343 (ret = sshbuf_put_bignum2(cert, k->dsa->q)) != 0 ||
2344 (ret = sshbuf_put_bignum2(cert, k->dsa->g)) != 0 ||
2345 (ret = sshbuf_put_bignum2(cert, k->dsa->pub_key)) != 0)
2346 goto out;
2347 break;
2348# ifdef OPENSSL_HAS_ECC
2349 case KEY_ECDSA_CERT:
2350 if ((ret = sshbuf_put_cstring(cert,
2351 sshkey_curve_nid_to_name(k->ecdsa_nid))) != 0 ||
2352 (ret = sshbuf_put_ec(cert,
2353 EC_KEY_get0_public_key(k->ecdsa),
2354 EC_KEY_get0_group(k->ecdsa))) != 0)
2355 goto out;
2356 break;
2357# endif /* OPENSSL_HAS_ECC */
2358 case KEY_RSA_CERT_V00:
2359 case KEY_RSA_CERT:
2360 if ((ret = sshbuf_put_bignum2(cert, k->rsa->e)) != 0 ||
2361 (ret = sshbuf_put_bignum2(cert, k->rsa->n)) != 0)
2362 goto out;
2363 break;
2364#endif /* WITH_OPENSSL */
2365 case KEY_ED25519_CERT:
2366 if ((ret = sshbuf_put_string(cert,
2367 k->ed25519_pk, ED25519_PK_SZ)) != 0)
2368 goto out;
2369 break;
2370 default:
2371 ret = SSH_ERR_INVALID_ARGUMENT;
2372 }
2373
2374 /* -v01 certs have a serial number next */
2375 if (!sshkey_cert_is_legacy(k)) {
2376 if ((ret = sshbuf_put_u64(cert, k->cert->serial)) != 0)
2377 goto out;
2378 }
2379
2380 if ((ret = sshbuf_put_u32(cert, k->cert->type)) != 0 ||
2381 (ret = sshbuf_put_cstring(cert, k->cert->key_id)) != 0)
2382 goto out;
2383
2384 if ((principals = sshbuf_new()) == NULL) {
2385 ret = SSH_ERR_ALLOC_FAIL;
2386 goto out;
2387 }
2388 for (i = 0; i < k->cert->nprincipals; i++) {
2389 if ((ret = sshbuf_put_cstring(principals,
2390 k->cert->principals[i])) != 0)
2391 goto out;
2392 }
2393 if ((ret = sshbuf_put_stringb(cert, principals)) != 0 ||
2394 (ret = sshbuf_put_u64(cert, k->cert->valid_after)) != 0 ||
2395 (ret = sshbuf_put_u64(cert, k->cert->valid_before)) != 0 ||
2396 (ret = sshbuf_put_stringb(cert, k->cert->critical)) != 0)
2397 goto out;
2398
2399 /* -v01 certs have non-critical options here */
2400 if (!sshkey_cert_is_legacy(k)) {
2401 if ((ret = sshbuf_put_stringb(cert, k->cert->extensions)) != 0)
2402 goto out;
2403 }
2404
2405 /* -v00 certs put the nonce at the end */
2406 if (sshkey_cert_is_legacy(k)) {
2407 if ((ret = sshbuf_put_string(cert, nonce, sizeof(nonce))) != 0)
2408 goto out;
2409 }
2410
2411 if ((ret = sshbuf_put_string(cert, NULL, 0)) != 0 || /* Reserved */
2412 (ret = sshbuf_put_string(cert, ca_blob, ca_len)) != 0)
2413 goto out;
2414
2415 /* Sign the whole mess */
2416 if ((ret = sshkey_sign(ca, &sig_blob, &sig_len, sshbuf_ptr(cert),
2417 sshbuf_len(cert), 0)) != 0)
2418 goto out;
2419
2420 /* Append signature and we are done */
2421 if ((ret = sshbuf_put_string(cert, sig_blob, sig_len)) != 0)
2422 goto out;
2423 ret = 0;
2424 out:
2425 if (ret != 0)
2426 sshbuf_reset(cert);
2427 if (sig_blob != NULL)
2428 free(sig_blob);
2429 if (ca_blob != NULL)
2430 free(ca_blob);
2431 if (principals != NULL)
2432 sshbuf_free(principals);
2433 return ret;
2434}
2435
2436int
2437sshkey_cert_check_authority(const struct sshkey *k,
2438 int want_host, int require_principal,
2439 const char *name, const char **reason)
2440{
2441 u_int i, principal_matches;
2442 time_t now = time(NULL);
2443
2444 if (reason != NULL)
2445 *reason = NULL;
2446
2447 if (want_host) {
2448 if (k->cert->type != SSH2_CERT_TYPE_HOST) {
2449 *reason = "Certificate invalid: not a host certificate";
2450 return SSH_ERR_KEY_CERT_INVALID;
2451 }
2452 } else {
2453 if (k->cert->type != SSH2_CERT_TYPE_USER) {
2454 *reason = "Certificate invalid: not a user certificate";
2455 return SSH_ERR_KEY_CERT_INVALID;
2456 }
2457 }
2458 if (now < 0) {
2459 /* yikes - system clock before epoch! */
2460 *reason = "Certificate invalid: not yet valid";
2461 return SSH_ERR_KEY_CERT_INVALID;
2462 }
2463 if ((u_int64_t)now < k->cert->valid_after) {
2464 *reason = "Certificate invalid: not yet valid";
2465 return SSH_ERR_KEY_CERT_INVALID;
2466 }
2467 if ((u_int64_t)now >= k->cert->valid_before) {
2468 *reason = "Certificate invalid: expired";
2469 return SSH_ERR_KEY_CERT_INVALID;
2470 }
2471 if (k->cert->nprincipals == 0) {
2472 if (require_principal) {
2473 *reason = "Certificate lacks principal list";
2474 return SSH_ERR_KEY_CERT_INVALID;
2475 }
2476 } else if (name != NULL) {
2477 principal_matches = 0;
2478 for (i = 0; i < k->cert->nprincipals; i++) {
2479 if (strcmp(name, k->cert->principals[i]) == 0) {
2480 principal_matches = 1;
2481 break;
2482 }
2483 }
2484 if (!principal_matches) {
2485 *reason = "Certificate invalid: name is not a listed "
2486 "principal";
2487 return SSH_ERR_KEY_CERT_INVALID;
2488 }
2489 }
2490 return 0;
2491}
2492
2493int
2494sshkey_private_serialize(const struct sshkey *key, struct sshbuf *b)
2495{
2496 int r = SSH_ERR_INTERNAL_ERROR;
2497
2498 if ((r = sshbuf_put_cstring(b, sshkey_ssh_name(key))) != 0)
2499 goto out;
2500 switch (key->type) {
2501#ifdef WITH_OPENSSL
2502 case KEY_RSA:
2503 if ((r = sshbuf_put_bignum2(b, key->rsa->n)) != 0 ||
2504 (r = sshbuf_put_bignum2(b, key->rsa->e)) != 0 ||
2505 (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
2506 (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
2507 (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
2508 (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
2509 goto out;
2510 break;
2511 case KEY_RSA_CERT_V00:
2512 case KEY_RSA_CERT:
2513 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2514 r = SSH_ERR_INVALID_ARGUMENT;
2515 goto out;
2516 }
2517 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2518 (r = sshbuf_put_bignum2(b, key->rsa->d)) != 0 ||
2519 (r = sshbuf_put_bignum2(b, key->rsa->iqmp)) != 0 ||
2520 (r = sshbuf_put_bignum2(b, key->rsa->p)) != 0 ||
2521 (r = sshbuf_put_bignum2(b, key->rsa->q)) != 0)
2522 goto out;
2523 break;
2524 case KEY_DSA:
2525 if ((r = sshbuf_put_bignum2(b, key->dsa->p)) != 0 ||
2526 (r = sshbuf_put_bignum2(b, key->dsa->q)) != 0 ||
2527 (r = sshbuf_put_bignum2(b, key->dsa->g)) != 0 ||
2528 (r = sshbuf_put_bignum2(b, key->dsa->pub_key)) != 0 ||
2529 (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
2530 goto out;
2531 break;
2532 case KEY_DSA_CERT_V00:
2533 case KEY_DSA_CERT:
2534 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2535 r = SSH_ERR_INVALID_ARGUMENT;
2536 goto out;
2537 }
2538 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2539 (r = sshbuf_put_bignum2(b, key->dsa->priv_key)) != 0)
2540 goto out;
2541 break;
2542# ifdef OPENSSL_HAS_ECC
2543 case KEY_ECDSA:
2544 if ((r = sshbuf_put_cstring(b,
2545 sshkey_curve_nid_to_name(key->ecdsa_nid))) != 0 ||
2546 (r = sshbuf_put_eckey(b, key->ecdsa)) != 0 ||
2547 (r = sshbuf_put_bignum2(b,
2548 EC_KEY_get0_private_key(key->ecdsa))) != 0)
2549 goto out;
2550 break;
2551 case KEY_ECDSA_CERT:
2552 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2553 r = SSH_ERR_INVALID_ARGUMENT;
2554 goto out;
2555 }
2556 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2557 (r = sshbuf_put_bignum2(b,
2558 EC_KEY_get0_private_key(key->ecdsa))) != 0)
2559 goto out;
2560 break;
2561# endif /* OPENSSL_HAS_ECC */
2562#endif /* WITH_OPENSSL */
2563 case KEY_ED25519:
2564 if ((r = sshbuf_put_string(b, key->ed25519_pk,
2565 ED25519_PK_SZ)) != 0 ||
2566 (r = sshbuf_put_string(b, key->ed25519_sk,
2567 ED25519_SK_SZ)) != 0)
2568 goto out;
2569 break;
2570 case KEY_ED25519_CERT:
2571 if (key->cert == NULL || sshbuf_len(key->cert->certblob) == 0) {
2572 r = SSH_ERR_INVALID_ARGUMENT;
2573 goto out;
2574 }
2575 if ((r = sshbuf_put_stringb(b, key->cert->certblob)) != 0 ||
2576 (r = sshbuf_put_string(b, key->ed25519_pk,
2577 ED25519_PK_SZ)) != 0 ||
2578 (r = sshbuf_put_string(b, key->ed25519_sk,
2579 ED25519_SK_SZ)) != 0)
2580 goto out;
2581 break;
2582 default:
2583 r = SSH_ERR_INVALID_ARGUMENT;
2584 goto out;
2585 }
2586 /* success */
2587 r = 0;
2588 out:
2589 return r;
2590}
2591
2592int
2593sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **kp)
2594{
2595 char *tname = NULL, *curve = NULL;
2596 struct sshkey *k = NULL;
2597 const u_char *cert;
2598 size_t len, pklen = 0, sklen = 0;
2599 int type, r = SSH_ERR_INTERNAL_ERROR;
2600 u_char *ed25519_pk = NULL, *ed25519_sk = NULL;
2601#ifdef WITH_OPENSSL
2602 BIGNUM *exponent = NULL;
2603#endif /* WITH_OPENSSL */
2604
2605 if (kp != NULL)
2606 *kp = NULL;
2607 if ((r = sshbuf_get_cstring(buf, &tname, NULL)) != 0)
2608 goto out;
2609 type = sshkey_type_from_name(tname);
2610 switch (type) {
2611#ifdef WITH_OPENSSL
2612 case KEY_DSA:
2613 if ((k = sshkey_new_private(type)) == NULL) {
2614 r = SSH_ERR_ALLOC_FAIL;
2615 goto out;
2616 }
2617 if ((r = sshbuf_get_bignum2(buf, k->dsa->p)) != 0 ||
2618 (r = sshbuf_get_bignum2(buf, k->dsa->q)) != 0 ||
2619 (r = sshbuf_get_bignum2(buf, k->dsa->g)) != 0 ||
2620 (r = sshbuf_get_bignum2(buf, k->dsa->pub_key)) != 0 ||
2621 (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
2622 goto out;
2623 break;
2624 case KEY_DSA_CERT_V00:
2625 case KEY_DSA_CERT:
2626 if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 ||
2627 (r = sshkey_from_blob(cert, len, &k)) != 0 ||
2628 (r = sshkey_add_private(k)) != 0 ||
2629 (r = sshbuf_get_bignum2(buf, k->dsa->priv_key)) != 0)
2630 goto out;
2631 break;
2632# ifdef OPENSSL_HAS_ECC
2633 case KEY_ECDSA:
2634 if ((k = sshkey_new_private(type)) == NULL) {
2635 r = SSH_ERR_ALLOC_FAIL;
2636 goto out;
2637 }
2638 if ((k->ecdsa_nid = sshkey_ecdsa_nid_from_name(tname)) == -1) {
2639 r = SSH_ERR_INVALID_ARGUMENT;
2640 goto out;
2641 }
2642 if ((r = sshbuf_get_cstring(buf, &curve, NULL)) != 0)
2643 goto out;
2644 if (k->ecdsa_nid != sshkey_curve_name_to_nid(curve)) {
2645 r = SSH_ERR_EC_CURVE_MISMATCH;
2646 goto out;
2647 }
2648 k->ecdsa = EC_KEY_new_by_curve_name(k->ecdsa_nid);
2649 if (k->ecdsa == NULL || (exponent = BN_new()) == NULL) {
2650 r = SSH_ERR_LIBCRYPTO_ERROR;
2651 goto out;
2652 }
2653 if ((r = sshbuf_get_eckey(buf, k->ecdsa)) != 0 ||
2654 (r = sshbuf_get_bignum2(buf, exponent)))
2655 goto out;
2656 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2657 r = SSH_ERR_LIBCRYPTO_ERROR;
2658 goto out;
2659 }
2660 if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2661 EC_KEY_get0_public_key(k->ecdsa)) != 0) ||
2662 (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
2663 goto out;
2664 break;
2665 case KEY_ECDSA_CERT:
2666 if ((exponent = BN_new()) == NULL) {
2667 r = SSH_ERR_LIBCRYPTO_ERROR;
2668 goto out;
2669 }
2670 if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 ||
2671 (r = sshkey_from_blob(cert, len, &k)) != 0 ||
2672 (r = sshkey_add_private(k)) != 0 ||
2673 (r = sshbuf_get_bignum2(buf, exponent)) != 0)
2674 goto out;
2675 if (EC_KEY_set_private_key(k->ecdsa, exponent) != 1) {
2676 r = SSH_ERR_LIBCRYPTO_ERROR;
2677 goto out;
2678 }
2679 if ((r = sshkey_ec_validate_public(EC_KEY_get0_group(k->ecdsa),
2680 EC_KEY_get0_public_key(k->ecdsa)) != 0) ||
2681 (r = sshkey_ec_validate_private(k->ecdsa)) != 0)
2682 goto out;
2683 break;
2684# endif /* OPENSSL_HAS_ECC */
2685 case KEY_RSA:
2686 if ((k = sshkey_new_private(type)) == NULL) {
2687 r = SSH_ERR_ALLOC_FAIL;
2688 goto out;
2689 }
2690 if ((r = sshbuf_get_bignum2(buf, k->rsa->n)) != 0 ||
2691 (r = sshbuf_get_bignum2(buf, k->rsa->e)) != 0 ||
2692 (r = sshbuf_get_bignum2(buf, k->rsa->d)) != 0 ||
2693 (r = sshbuf_get_bignum2(buf, k->rsa->iqmp)) != 0 ||
2694 (r = sshbuf_get_bignum2(buf, k->rsa->p)) != 0 ||
2695 (r = sshbuf_get_bignum2(buf, k->rsa->q)) != 0 ||
2696 (r = rsa_generate_additional_parameters(k->rsa)) != 0)
2697 goto out;
2698 break;
2699 case KEY_RSA_CERT_V00:
2700 case KEY_RSA_CERT:
2701 if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 ||
2702 (r = sshkey_from_blob(cert, len, &k)) != 0 ||
2703 (r = sshkey_add_private(k)) != 0 ||
2704 (r = sshbuf_get_bignum2(buf, k->rsa->d) != 0) ||
2705 (r = sshbuf_get_bignum2(buf, k->rsa->iqmp) != 0) ||
2706 (r = sshbuf_get_bignum2(buf, k->rsa->p) != 0) ||
2707 (r = sshbuf_get_bignum2(buf, k->rsa->q) != 0) ||
2708 (r = rsa_generate_additional_parameters(k->rsa)) != 0)
2709 goto out;
2710 break;
2711#endif /* WITH_OPENSSL */
2712 case KEY_ED25519:
2713 if ((k = sshkey_new_private(type)) == NULL) {
2714 r = SSH_ERR_ALLOC_FAIL;
2715 goto out;
2716 }
2717 if ((r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
2718 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
2719 goto out;
2720 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
2721 r = SSH_ERR_INVALID_FORMAT;
2722 goto out;
2723 }
2724 k->ed25519_pk = ed25519_pk;
2725 k->ed25519_sk = ed25519_sk;
2726 ed25519_pk = ed25519_sk = NULL;
2727 break;
2728 case KEY_ED25519_CERT:
2729 if ((r = sshbuf_get_string_direct(buf, &cert, &len)) != 0 ||
2730 (r = sshkey_from_blob(cert, len, &k)) != 0 ||
2731 (r = sshkey_add_private(k)) != 0 ||
2732 (r = sshbuf_get_string(buf, &ed25519_pk, &pklen)) != 0 ||
2733 (r = sshbuf_get_string(buf, &ed25519_sk, &sklen)) != 0)
2734 goto out;
2735 if (pklen != ED25519_PK_SZ || sklen != ED25519_SK_SZ) {
2736 r = SSH_ERR_INVALID_FORMAT;
2737 goto out;
2738 }
2739 k->ed25519_pk = ed25519_pk;
2740 k->ed25519_sk = ed25519_sk;
2741 ed25519_pk = ed25519_sk = NULL;
2742 break;
2743 default:
2744 r = SSH_ERR_KEY_TYPE_UNKNOWN;
2745 goto out;
2746 }
2747#ifdef WITH_OPENSSL
2748 /* enable blinding */
2749 switch (k->type) {
2750 case KEY_RSA:
2751 case KEY_RSA_CERT_V00:
2752 case KEY_RSA_CERT:
2753 case KEY_RSA1:
2754 if (RSA_blinding_on(k->rsa, NULL) != 1) {
2755 r = SSH_ERR_LIBCRYPTO_ERROR;
2756 goto out;
2757 }
2758 break;
2759 }
2760#endif /* WITH_OPENSSL */
2761 /* success */
2762 r = 0;
2763 if (kp != NULL) {
2764 *kp = k;
2765 k = NULL;
2766 }
2767 out:
2768 free(tname);
2769 free(curve);
2770#ifdef WITH_OPENSSL
2771 if (exponent != NULL)
2772 BN_clear_free(exponent);
2773#endif /* WITH_OPENSSL */
2774 sshkey_free(k);
2775 if (ed25519_pk != NULL) {
2776 explicit_bzero(ed25519_pk, pklen);
2777 free(ed25519_pk);
2778 }
2779 if (ed25519_sk != NULL) {
2780 explicit_bzero(ed25519_sk, sklen);
2781 free(ed25519_sk);
2782 }
2783 return r;
2784}
2785
2786#if defined(WITH_OPENSSL) && defined(OPENSSL_HAS_ECC)
2787int
2788sshkey_ec_validate_public(const EC_GROUP *group, const EC_POINT *public)
2789{
2790 BN_CTX *bnctx;
2791 EC_POINT *nq = NULL;
2792 BIGNUM *order, *x, *y, *tmp;
2793 int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2794
2795 if ((bnctx = BN_CTX_new()) == NULL)
2796 return SSH_ERR_ALLOC_FAIL;
2797 BN_CTX_start(bnctx);
2798
2799 /*
2800 * We shouldn't ever hit this case because bignum_get_ecpoint()
2801 * refuses to load GF2m points.
2802 */
2803 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2804 NID_X9_62_prime_field)
2805 goto out;
2806
2807 /* Q != infinity */
2808 if (EC_POINT_is_at_infinity(group, public))
2809 goto out;
2810
2811 if ((x = BN_CTX_get(bnctx)) == NULL ||
2812 (y = BN_CTX_get(bnctx)) == NULL ||
2813 (order = BN_CTX_get(bnctx)) == NULL ||
2814 (tmp = BN_CTX_get(bnctx)) == NULL) {
2815 ret = SSH_ERR_ALLOC_FAIL;
2816 goto out;
2817 }
2818
2819 /* log2(x) > log2(order)/2, log2(y) > log2(order)/2 */
2820 if (EC_GROUP_get_order(group, order, bnctx) != 1 ||
2821 EC_POINT_get_affine_coordinates_GFp(group, public,
2822 x, y, bnctx) != 1) {
2823 ret = SSH_ERR_LIBCRYPTO_ERROR;
2824 goto out;
2825 }
2826 if (BN_num_bits(x) <= BN_num_bits(order) / 2 ||
2827 BN_num_bits(y) <= BN_num_bits(order) / 2)
2828 goto out;
2829
2830 /* nQ == infinity (n == order of subgroup) */
2831 if ((nq = EC_POINT_new(group)) == NULL) {
2832 ret = SSH_ERR_ALLOC_FAIL;
2833 goto out;
2834 }
2835 if (EC_POINT_mul(group, nq, NULL, public, order, bnctx) != 1) {
2836 ret = SSH_ERR_LIBCRYPTO_ERROR;
2837 goto out;
2838 }
2839 if (EC_POINT_is_at_infinity(group, nq) != 1)
2840 goto out;
2841
2842 /* x < order - 1, y < order - 1 */
2843 if (!BN_sub(tmp, order, BN_value_one())) {
2844 ret = SSH_ERR_LIBCRYPTO_ERROR;
2845 goto out;
2846 }
2847 if (BN_cmp(x, tmp) >= 0 || BN_cmp(y, tmp) >= 0)
2848 goto out;
2849 ret = 0;
2850 out:
2851 BN_CTX_free(bnctx);
2852 if (nq != NULL)
2853 EC_POINT_free(nq);
2854 return ret;
2855}
2856
2857int
2858sshkey_ec_validate_private(const EC_KEY *key)
2859{
2860 BN_CTX *bnctx;
2861 BIGNUM *order, *tmp;
2862 int ret = SSH_ERR_KEY_INVALID_EC_VALUE;
2863
2864 if ((bnctx = BN_CTX_new()) == NULL)
2865 return SSH_ERR_ALLOC_FAIL;
2866 BN_CTX_start(bnctx);
2867
2868 if ((order = BN_CTX_get(bnctx)) == NULL ||
2869 (tmp = BN_CTX_get(bnctx)) == NULL) {
2870 ret = SSH_ERR_ALLOC_FAIL;
2871 goto out;
2872 }
2873
2874 /* log2(private) > log2(order)/2 */
2875 if (EC_GROUP_get_order(EC_KEY_get0_group(key), order, bnctx) != 1) {
2876 ret = SSH_ERR_LIBCRYPTO_ERROR;
2877 goto out;
2878 }
2879 if (BN_num_bits(EC_KEY_get0_private_key(key)) <=
2880 BN_num_bits(order) / 2)
2881 goto out;
2882
2883 /* private < order - 1 */
2884 if (!BN_sub(tmp, order, BN_value_one())) {
2885 ret = SSH_ERR_LIBCRYPTO_ERROR;
2886 goto out;
2887 }
2888 if (BN_cmp(EC_KEY_get0_private_key(key), tmp) >= 0)
2889 goto out;
2890 ret = 0;
2891 out:
2892 BN_CTX_free(bnctx);
2893 return ret;
2894}
2895
2896void
2897sshkey_dump_ec_point(const EC_GROUP *group, const EC_POINT *point)
2898{
2899 BIGNUM *x, *y;
2900 BN_CTX *bnctx;
2901
2902 if (point == NULL) {
2903 fputs("point=(NULL)\n", stderr);
2904 return;
2905 }
2906 if ((bnctx = BN_CTX_new()) == NULL) {
2907 fprintf(stderr, "%s: BN_CTX_new failed\n", __func__);
2908 return;
2909 }
2910 BN_CTX_start(bnctx);
2911 if ((x = BN_CTX_get(bnctx)) == NULL ||
2912 (y = BN_CTX_get(bnctx)) == NULL) {
2913 fprintf(stderr, "%s: BN_CTX_get failed\n", __func__);
2914 return;
2915 }
2916 if (EC_METHOD_get_field_type(EC_GROUP_method_of(group)) !=
2917 NID_X9_62_prime_field) {
2918 fprintf(stderr, "%s: group is not a prime field\n", __func__);
2919 return;
2920 }
2921 if (EC_POINT_get_affine_coordinates_GFp(group, point, x, y,
2922 bnctx) != 1) {
2923 fprintf(stderr, "%s: EC_POINT_get_affine_coordinates_GFp\n",
2924 __func__);
2925 return;
2926 }
2927 fputs("x=", stderr);
2928 BN_print_fp(stderr, x);
2929 fputs("\ny=", stderr);
2930 BN_print_fp(stderr, y);
2931 fputs("\n", stderr);
2932 BN_CTX_free(bnctx);
2933}
2934
2935void
2936sshkey_dump_ec_key(const EC_KEY *key)
2937{
2938 const BIGNUM *exponent;
2939
2940 sshkey_dump_ec_point(EC_KEY_get0_group(key),
2941 EC_KEY_get0_public_key(key));
2942 fputs("exponent=", stderr);
2943 if ((exponent = EC_KEY_get0_private_key(key)) == NULL)
2944 fputs("(NULL)", stderr);
2945 else
2946 BN_print_fp(stderr, EC_KEY_get0_private_key(key));
2947 fputs("\n", stderr);
2948}
2949#endif /* WITH_OPENSSL && OPENSSL_HAS_ECC */
2950
2951static int
2952sshkey_private_to_blob2(const struct sshkey *prv, struct sshbuf *blob,
2953 const char *passphrase, const char *comment, const char *ciphername,
2954 int rounds)
2955{
2956 u_char *cp, *b64 = NULL, *key = NULL, *pubkeyblob = NULL;
2957 u_char salt[SALT_LEN];
2958 size_t i, pubkeylen, keylen, ivlen, blocksize, authlen;
2959 u_int check;
2960 int r = SSH_ERR_INTERNAL_ERROR;
2961 struct sshcipher_ctx ciphercontext;
2962 const struct sshcipher *cipher;
2963 const char *kdfname = KDFNAME;
2964 struct sshbuf *encoded = NULL, *encrypted = NULL, *kdf = NULL;
2965
2966 memset(&ciphercontext, 0, sizeof(ciphercontext));
2967
2968 if (rounds <= 0)
2969 rounds = DEFAULT_ROUNDS;
2970 if (passphrase == NULL || !strlen(passphrase)) {
2971 ciphername = "none";
2972 kdfname = "none";
2973 } else if (ciphername == NULL)
2974 ciphername = DEFAULT_CIPHERNAME;
2975 else if (cipher_number(ciphername) != SSH_CIPHER_SSH2) {
2976 r = SSH_ERR_INVALID_ARGUMENT;
2977 goto out;
2978 }
2979 if ((cipher = cipher_by_name(ciphername)) == NULL) {
2980 r = SSH_ERR_INTERNAL_ERROR;
2981 goto out;
2982 }
2983
2984 if ((kdf = sshbuf_new()) == NULL ||
2985 (encoded = sshbuf_new()) == NULL ||
2986 (encrypted = sshbuf_new()) == NULL) {
2987 r = SSH_ERR_ALLOC_FAIL;
2988 goto out;
2989 }
2990 blocksize = cipher_blocksize(cipher);
2991 keylen = cipher_keylen(cipher);
2992 ivlen = cipher_ivlen(cipher);
2993 authlen = cipher_authlen(cipher);
2994 if ((key = calloc(1, keylen + ivlen)) == NULL) {
2995 r = SSH_ERR_ALLOC_FAIL;
2996 goto out;
2997 }
2998 if (strcmp(kdfname, "bcrypt") == 0) {
2999 arc4random_buf(salt, SALT_LEN);
3000 if (bcrypt_pbkdf(passphrase, strlen(passphrase),
3001 salt, SALT_LEN, key, keylen + ivlen, rounds) < 0) {
3002 r = SSH_ERR_INVALID_ARGUMENT;
3003 goto out;
3004 }
3005 if ((r = sshbuf_put_string(kdf, salt, SALT_LEN)) != 0 ||
3006 (r = sshbuf_put_u32(kdf, rounds)) != 0)
3007 goto out;
3008 } else if (strcmp(kdfname, "none") != 0) {
3009 /* Unsupported KDF type */
3010 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3011 goto out;
3012 }
3013 if ((r = cipher_init(&ciphercontext, cipher, key, keylen,
3014 key + keylen, ivlen, 1)) != 0)
3015 goto out;
3016
3017 if ((r = sshbuf_put(encoded, AUTH_MAGIC, sizeof(AUTH_MAGIC))) != 0 ||
3018 (r = sshbuf_put_cstring(encoded, ciphername)) != 0 ||
3019 (r = sshbuf_put_cstring(encoded, kdfname)) != 0 ||
3020 (r = sshbuf_put_stringb(encoded, kdf)) != 0 ||
3021 (r = sshbuf_put_u32(encoded, 1)) != 0 || /* number of keys */
3022 (r = sshkey_to_blob(prv, &pubkeyblob, &pubkeylen)) != 0 ||
3023 (r = sshbuf_put_string(encoded, pubkeyblob, pubkeylen)) != 0)
3024 goto out;
3025
3026 /* set up the buffer that will be encrypted */
3027
3028 /* Random check bytes */
3029 check = arc4random();
3030 if ((r = sshbuf_put_u32(encrypted, check)) != 0 ||
3031 (r = sshbuf_put_u32(encrypted, check)) != 0)
3032 goto out;
3033
3034 /* append private key and comment*/
3035 if ((r = sshkey_private_serialize(prv, encrypted)) != 0 ||
3036 (r = sshbuf_put_cstring(encrypted, comment)) != 0)
3037 goto out;
3038
3039 /* padding */
3040 i = 0;
3041 while (sshbuf_len(encrypted) % blocksize) {
3042 if ((r = sshbuf_put_u8(encrypted, ++i & 0xff)) != 0)
3043 goto out;
3044 }
3045
3046 /* length in destination buffer */
3047 if ((r = sshbuf_put_u32(encoded, sshbuf_len(encrypted))) != 0)
3048 goto out;
3049
3050 /* encrypt */
3051 if ((r = sshbuf_reserve(encoded,
3052 sshbuf_len(encrypted) + authlen, &cp)) != 0)
3053 goto out;
3054 if ((r = cipher_crypt(&ciphercontext, 0, cp,
3055 sshbuf_ptr(encrypted), sshbuf_len(encrypted), 0, authlen)) != 0)
3056 goto out;
3057
3058 /* uuencode */
3059 if ((b64 = sshbuf_dtob64(encoded)) == NULL) {
3060 r = SSH_ERR_ALLOC_FAIL;
3061 goto out;
3062 }
3063
3064 sshbuf_reset(blob);
3065 if ((r = sshbuf_put(blob, MARK_BEGIN, MARK_BEGIN_LEN)) != 0)
3066 goto out;
3067 for (i = 0; i < strlen(b64); i++) {
3068 if ((r = sshbuf_put_u8(blob, b64[i])) != 0)
3069 goto out;
3070 /* insert line breaks */
3071 if (i % 70 == 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3072 goto out;
3073 }
3074 if (i % 70 != 69 && (r = sshbuf_put_u8(blob, '\n')) != 0)
3075 goto out;
3076 if ((r = sshbuf_put(blob, MARK_END, MARK_END_LEN)) != 0)
3077 goto out;
3078
3079 /* success */
3080 r = 0;
3081
3082 out:
3083 sshbuf_free(kdf);
3084 sshbuf_free(encoded);
3085 sshbuf_free(encrypted);
3086 cipher_cleanup(&ciphercontext);
3087 explicit_bzero(salt, sizeof(salt));
3088 if (key != NULL) {
3089 explicit_bzero(key, keylen + ivlen);
3090 free(key);
3091 }
3092 if (pubkeyblob != NULL) {
3093 explicit_bzero(pubkeyblob, pubkeylen);
3094 free(pubkeyblob);
3095 }
3096 if (b64 != NULL) {
3097 explicit_bzero(b64, strlen(b64));
3098 free(b64);
3099 }
3100 return r;
3101}
3102
3103static int
3104sshkey_parse_private2(struct sshbuf *blob, int type, const char *passphrase,
3105 struct sshkey **keyp, char **commentp)
3106{
3107 char *comment = NULL, *ciphername = NULL, *kdfname = NULL;
3108 const struct sshcipher *cipher = NULL;
3109 const u_char *cp;
3110 int r = SSH_ERR_INTERNAL_ERROR;
3111 size_t encoded_len;
3112 size_t i, keylen = 0, ivlen = 0, slen = 0;
3113 struct sshbuf *encoded = NULL, *decoded = NULL;
3114 struct sshbuf *kdf = NULL, *decrypted = NULL;
3115 struct sshcipher_ctx ciphercontext;
3116 struct sshkey *k = NULL;
3117 u_char *key = NULL, *salt = NULL, *dp, pad, last;
3118 u_int blocksize, rounds, nkeys, encrypted_len, check1, check2;
3119
3120 memset(&ciphercontext, 0, sizeof(ciphercontext));
3121 if (keyp != NULL)
3122 *keyp = NULL;
3123 if (commentp != NULL)
3124 *commentp = NULL;
3125
3126 if ((encoded = sshbuf_new()) == NULL ||
3127 (decoded = sshbuf_new()) == NULL ||
3128 (decrypted = sshbuf_new()) == NULL) {
3129 r = SSH_ERR_ALLOC_FAIL;
3130 goto out;
3131 }
3132
3133 /* check preamble */
3134 cp = sshbuf_ptr(blob);
3135 encoded_len = sshbuf_len(blob);
3136 if (encoded_len < (MARK_BEGIN_LEN + MARK_END_LEN) ||
3137 memcmp(cp, MARK_BEGIN, MARK_BEGIN_LEN) != 0) {
3138 r = SSH_ERR_INVALID_FORMAT;
3139 goto out;
3140 }
3141 cp += MARK_BEGIN_LEN;
3142 encoded_len -= MARK_BEGIN_LEN;
3143
3144 /* Look for end marker, removing whitespace as we go */
3145 while (encoded_len > 0) {
3146 if (*cp != '\n' && *cp != '\r') {
3147 if ((r = sshbuf_put_u8(encoded, *cp)) != 0)
3148 goto out;
3149 }
3150 last = *cp;
3151 encoded_len--;
3152 cp++;
3153 if (last == '\n') {
3154 if (encoded_len >= MARK_END_LEN &&
3155 memcmp(cp, MARK_END, MARK_END_LEN) == 0) {
3156 /* \0 terminate */
3157 if ((r = sshbuf_put_u8(encoded, 0)) != 0)
3158 goto out;
3159 break;
3160 }
3161 }
3162 }
3163 if (encoded_len == 0) {
3164 r = SSH_ERR_INVALID_FORMAT;
3165 goto out;
3166 }
3167
3168 /* decode base64 */
3169 if ((r = sshbuf_b64tod(decoded, sshbuf_ptr(encoded))) != 0)
3170 goto out;
3171
3172 /* check magic */
3173 if (sshbuf_len(decoded) < sizeof(AUTH_MAGIC) ||
3174 memcmp(sshbuf_ptr(decoded), AUTH_MAGIC, sizeof(AUTH_MAGIC))) {
3175 r = SSH_ERR_INVALID_FORMAT;
3176 goto out;
3177 }
3178 /* parse public portion of key */
3179 if ((r = sshbuf_consume(decoded, sizeof(AUTH_MAGIC))) != 0 ||
3180 (r = sshbuf_get_cstring(decoded, &ciphername, NULL)) != 0 ||
3181 (r = sshbuf_get_cstring(decoded, &kdfname, NULL)) != 0 ||
3182 (r = sshbuf_froms(decoded, &kdf)) != 0 ||
3183 (r = sshbuf_get_u32(decoded, &nkeys)) != 0 ||
3184 (r = sshbuf_skip_string(decoded)) != 0 || /* pubkey */
3185 (r = sshbuf_get_u32(decoded, &encrypted_len)) != 0)
3186 goto out;
3187
3188 if ((cipher = cipher_by_name(ciphername)) == NULL) {
3189 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3190 goto out;
3191 }
3192 if ((passphrase == NULL || strlen(passphrase) == 0) &&
3193 strcmp(ciphername, "none") != 0) {
3194 /* passphrase required */
3195 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3196 goto out;
3197 }
3198 if (strcmp(kdfname, "none") != 0 && strcmp(kdfname, "bcrypt") != 0) {
3199 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3200 goto out;
3201 }
3202 if (!strcmp(kdfname, "none") && strcmp(ciphername, "none") != 0) {
3203 r = SSH_ERR_INVALID_FORMAT;
3204 goto out;
3205 }
3206 if (nkeys != 1) {
3207 /* XXX only one key supported */
3208 r = SSH_ERR_INVALID_FORMAT;
3209 goto out;
3210 }
3211
3212 /* check size of encrypted key blob */
3213 blocksize = cipher_blocksize(cipher);
3214 if (encrypted_len < blocksize || (encrypted_len % blocksize) != 0) {
3215 r = SSH_ERR_INVALID_FORMAT;
3216 goto out;
3217 }
3218
3219 /* setup key */
3220 keylen = cipher_keylen(cipher);
3221 ivlen = cipher_ivlen(cipher);
3222 if ((key = calloc(1, keylen + ivlen)) == NULL) {
3223 r = SSH_ERR_ALLOC_FAIL;
3224 goto out;
3225 }
3226 if (strcmp(kdfname, "bcrypt") == 0) {
3227 if ((r = sshbuf_get_string(kdf, &salt, &slen)) != 0 ||
3228 (r = sshbuf_get_u32(kdf, &rounds)) != 0)
3229 goto out;
3230 if (bcrypt_pbkdf(passphrase, strlen(passphrase), salt, slen,
3231 key, keylen + ivlen, rounds) < 0) {
3232 r = SSH_ERR_INVALID_FORMAT;
3233 goto out;
3234 }
3235 }
3236
3237 /* decrypt private portion of key */
3238 if ((r = sshbuf_reserve(decrypted, encrypted_len, &dp)) != 0 ||
3239 (r = cipher_init(&ciphercontext, cipher, key, keylen,
3240 key + keylen, ivlen, 0)) != 0)
3241 goto out;
3242 if ((r = cipher_crypt(&ciphercontext, 0, dp, sshbuf_ptr(decoded),
3243 sshbuf_len(decoded), 0, cipher_authlen(cipher))) != 0) {
3244 /* an integrity error here indicates an incorrect passphrase */
3245 if (r == SSH_ERR_MAC_INVALID)
3246 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3247 goto out;
3248 }
3249 if ((r = sshbuf_consume(decoded, encrypted_len)) != 0)
3250 goto out;
3251 /* there should be no trailing data */
3252 if (sshbuf_len(decoded) != 0) {
3253 r = SSH_ERR_INVALID_FORMAT;
3254 goto out;
3255 }
3256
3257 /* check check bytes */
3258 if ((r = sshbuf_get_u32(decrypted, &check1)) != 0 ||
3259 (r = sshbuf_get_u32(decrypted, &check2)) != 0)
3260 goto out;
3261 if (check1 != check2) {
3262 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3263 goto out;
3264 }
3265
3266 /* Load the private key and comment */
3267 if ((r = sshkey_private_deserialize(decrypted, &k)) != 0 ||
3268 (r = sshbuf_get_cstring(decrypted, &comment, NULL)) != 0)
3269 goto out;
3270
3271 /* Check deterministic padding */
3272 i = 0;
3273 while (sshbuf_len(decrypted)) {
3274 if ((r = sshbuf_get_u8(decrypted, &pad)) != 0)
3275 goto out;
3276 if (pad != (++i & 0xff)) {
3277 r = SSH_ERR_INVALID_FORMAT;
3278 goto out;
3279 }
3280 }
3281
3282 /* XXX decode pubkey and check against private */
3283
3284 /* success */
3285 r = 0;
3286 if (keyp != NULL) {
3287 *keyp = k;
3288 k = NULL;
3289 }
3290 if (commentp != NULL) {
3291 *commentp = comment;
3292 comment = NULL;
3293 }
3294 out:
3295 pad = 0;
3296 cipher_cleanup(&ciphercontext);
3297 free(ciphername);
3298 free(kdfname);
3299 free(comment);
3300 if (salt != NULL) {
3301 explicit_bzero(salt, slen);
3302 free(salt);
3303 }
3304 if (key != NULL) {
3305 explicit_bzero(key, keylen + ivlen);
3306 free(key);
3307 }
3308 sshbuf_free(encoded);
3309 sshbuf_free(decoded);
3310 sshbuf_free(kdf);
3311 sshbuf_free(decrypted);
3312 sshkey_free(k);
3313 return r;
3314}
3315
3316#if WITH_SSH1
3317/*
3318 * Serialises the authentication (private) key to a blob, encrypting it with
3319 * passphrase. The identification of the blob (lowest 64 bits of n) will
3320 * precede the key to provide identification of the key without needing a
3321 * passphrase.
3322 */
3323static int
3324sshkey_private_rsa1_to_blob(struct sshkey *key, struct sshbuf *blob,
3325 const char *passphrase, const char *comment)
3326{
3327 struct sshbuf *buffer = NULL, *encrypted = NULL;
3328 u_char buf[8];
3329 int r, cipher_num;
3330 struct sshcipher_ctx ciphercontext;
3331 const struct sshcipher *cipher;
3332 u_char *cp;
3333
3334 /*
3335 * If the passphrase is empty, use SSH_CIPHER_NONE to ease converting
3336 * to another cipher; otherwise use SSH_AUTHFILE_CIPHER.
3337 */
3338 cipher_num = (strcmp(passphrase, "") == 0) ?
3339 SSH_CIPHER_NONE : SSH_CIPHER_3DES;
3340 if ((cipher = cipher_by_number(cipher_num)) == NULL)
3341 return SSH_ERR_INTERNAL_ERROR;
3342
3343 /* This buffer is used to build the secret part of the private key. */
3344 if ((buffer = sshbuf_new()) == NULL)
3345 return SSH_ERR_ALLOC_FAIL;
3346
3347 /* Put checkbytes for checking passphrase validity. */
3348 if ((r = sshbuf_reserve(buffer, 4, &cp)) != 0)
3349 goto out;
3350 arc4random_buf(cp, 2);
3351 memcpy(cp + 2, cp, 2);
3352
3353 /*
3354 * Store the private key (n and e will not be stored because they
3355 * will be stored in plain text, and storing them also in encrypted
3356 * format would just give known plaintext).
3357 * Note: q and p are stored in reverse order to SSL.
3358 */
3359 if ((r = sshbuf_put_bignum1(buffer, key->rsa->d)) != 0 ||
3360 (r = sshbuf_put_bignum1(buffer, key->rsa->iqmp)) != 0 ||
3361 (r = sshbuf_put_bignum1(buffer, key->rsa->q)) != 0 ||
3362 (r = sshbuf_put_bignum1(buffer, key->rsa->p)) != 0)
3363 goto out;
3364
3365 /* Pad the part to be encrypted to a size that is a multiple of 8. */
3366 explicit_bzero(buf, 8);
3367 if ((r = sshbuf_put(buffer, buf, 8 - (sshbuf_len(buffer) % 8))) != 0)
3368 goto out;
3369
3370 /* This buffer will be used to contain the data in the file. */
3371 if ((encrypted = sshbuf_new()) == NULL) {
3372 r = SSH_ERR_ALLOC_FAIL;
3373 goto out;
3374 }
3375
3376 /* First store keyfile id string. */
3377 if ((r = sshbuf_put(encrypted, LEGACY_BEGIN,
3378 sizeof(LEGACY_BEGIN))) != 0)
3379 goto out;
3380
3381 /* Store cipher type and "reserved" field. */
3382 if ((r = sshbuf_put_u8(encrypted, cipher_num)) != 0 ||
3383 (r = sshbuf_put_u32(encrypted, 0)) != 0)
3384 goto out;
3385
3386 /* Store public key. This will be in plain text. */
3387 if ((r = sshbuf_put_u32(encrypted, BN_num_bits(key->rsa->n))) != 0 ||
3388 (r = sshbuf_put_bignum1(encrypted, key->rsa->n) != 0) ||
3389 (r = sshbuf_put_bignum1(encrypted, key->rsa->e) != 0) ||
3390 (r = sshbuf_put_cstring(encrypted, comment) != 0))
3391 goto out;
3392
3393 /* Allocate space for the private part of the key in the buffer. */
3394 if ((r = sshbuf_reserve(encrypted, sshbuf_len(buffer), &cp)) != 0)
3395 goto out;
3396
3397 if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
3398 CIPHER_ENCRYPT)) != 0)
3399 goto out;
3400 if ((r = cipher_crypt(&ciphercontext, 0, cp,
3401 sshbuf_ptr(buffer), sshbuf_len(buffer), 0, 0)) != 0)
3402 goto out;
3403 if ((r = cipher_cleanup(&ciphercontext)) != 0)
3404 goto out;
3405
3406 r = sshbuf_putb(blob, encrypted);
3407
3408 out:
3409 explicit_bzero(&ciphercontext, sizeof(ciphercontext));
3410 explicit_bzero(buf, sizeof(buf));
3411 if (buffer != NULL)
3412 sshbuf_free(buffer);
3413 if (encrypted != NULL)
3414 sshbuf_free(encrypted);
3415
3416 return r;
3417}
3418#endif /* WITH_SSH1 */
3419
3420#ifdef WITH_OPENSSL
3421/* convert SSH v2 key in OpenSSL PEM format */
3422static int
3423sshkey_private_pem_to_blob(struct sshkey *key, struct sshbuf *blob,
3424 const char *_passphrase, const char *comment)
3425{
3426 int success, r;
3427 int blen, len = strlen(_passphrase);
3428 u_char *passphrase = (len > 0) ? (u_char *)_passphrase : NULL;
3429#if (OPENSSL_VERSION_NUMBER < 0x00907000L)
3430 const EVP_CIPHER *cipher = (len > 0) ? EVP_des_ede3_cbc() : NULL;
3431#else
3432 const EVP_CIPHER *cipher = (len > 0) ? EVP_aes_128_cbc() : NULL;
3433#endif
3434 const u_char *bptr;
3435 BIO *bio = NULL;
3436
3437 if (len > 0 && len <= 4)
3438 return SSH_ERR_PASSPHRASE_TOO_SHORT;
3439 if ((bio = BIO_new(BIO_s_mem())) == NULL)
3440 return SSH_ERR_ALLOC_FAIL;
3441
3442 switch (key->type) {
3443 case KEY_DSA:
3444 success = PEM_write_bio_DSAPrivateKey(bio, key->dsa,
3445 cipher, passphrase, len, NULL, NULL);
3446 break;
3447#ifdef OPENSSL_HAS_ECC
3448 case KEY_ECDSA:
3449 success = PEM_write_bio_ECPrivateKey(bio, key->ecdsa,
3450 cipher, passphrase, len, NULL, NULL);
3451 break;
3452#endif
3453 case KEY_RSA:
3454 success = PEM_write_bio_RSAPrivateKey(bio, key->rsa,
3455 cipher, passphrase, len, NULL, NULL);
3456 break;
3457 default:
3458 success = 0;
3459 break;
3460 }
3461 if (success == 0) {
3462 r = SSH_ERR_LIBCRYPTO_ERROR;
3463 goto out;
3464 }
3465 if ((blen = BIO_get_mem_data(bio, &bptr)) <= 0) {
3466 r = SSH_ERR_INTERNAL_ERROR;
3467 goto out;
3468 }
3469 if ((r = sshbuf_put(blob, bptr, blen)) != 0)
3470 goto out;
3471 r = 0;
3472 out:
3473 BIO_free(bio);
3474 return r;
3475}
3476#endif /* WITH_OPENSSL */
3477
3478/* Serialise "key" to buffer "blob" */
3479int
3480sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
3481 const char *passphrase, const char *comment,
3482 int force_new_format, const char *new_format_cipher, int new_format_rounds)
3483{
3484 switch (key->type) {
3485#ifdef WITH_OPENSSL
3486 case KEY_RSA1:
3487 return sshkey_private_rsa1_to_blob(key, blob,
3488 passphrase, comment);
3489 case KEY_DSA:
3490 case KEY_ECDSA:
3491 case KEY_RSA:
3492 if (force_new_format) {
3493 return sshkey_private_to_blob2(key, blob, passphrase,
3494 comment, new_format_cipher, new_format_rounds);
3495 }
3496 return sshkey_private_pem_to_blob(key, blob,
3497 passphrase, comment);
3498#endif /* WITH_OPENSSL */
3499 case KEY_ED25519:
3500 return sshkey_private_to_blob2(key, blob, passphrase,
3501 comment, new_format_cipher, new_format_rounds);
3502 default:
3503 return SSH_ERR_KEY_TYPE_UNKNOWN;
3504 }
3505}
3506
3507#ifdef WITH_SSH1
3508/*
3509 * Parse the public, unencrypted portion of a RSA1 key.
3510 */
3511int
3512sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
3513 struct sshkey **keyp, char **commentp)
3514{
3515 int r;
3516 struct sshkey *pub = NULL;
3517 struct sshbuf *copy = NULL;
3518
3519 if (keyp != NULL)
3520 *keyp = NULL;
3521 if (commentp != NULL)
3522 *commentp = NULL;
3523
3524 /* Check that it is at least big enough to contain the ID string. */
3525 if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
3526 return SSH_ERR_INVALID_FORMAT;
3527
3528 /*
3529 * Make sure it begins with the id string. Consume the id string
3530 * from the buffer.
3531 */
3532 if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
3533 return SSH_ERR_INVALID_FORMAT;
3534 /* Make a working copy of the keyblob and skip past the magic */
3535 if ((copy = sshbuf_fromb(blob)) == NULL)
3536 return SSH_ERR_ALLOC_FAIL;
3537 if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
3538 goto out;
3539
3540 /* Skip cipher type, reserved data and key bits. */
3541 if ((r = sshbuf_get_u8(copy, NULL)) != 0 || /* cipher type */
3542 (r = sshbuf_get_u32(copy, NULL)) != 0 || /* reserved */
3543 (r = sshbuf_get_u32(copy, NULL)) != 0) /* key bits */
3544 goto out;
3545
3546 /* Read the public key from the buffer. */
3547 if ((pub = sshkey_new(KEY_RSA1)) == NULL ||
3548 (r = sshbuf_get_bignum1(copy, pub->rsa->n)) != 0 ||
3549 (r = sshbuf_get_bignum1(copy, pub->rsa->e)) != 0)
3550 goto out;
3551
3552 /* Finally, the comment */
3553 if ((r = sshbuf_get_string(copy, (u_char**)commentp, NULL)) != 0)
3554 goto out;
3555
3556 /* The encrypted private part is not parsed by this function. */
3557
3558 r = 0;
3559 if (keyp != NULL)
3560 *keyp = pub;
3561 else
3562 sshkey_free(pub);
3563 pub = NULL;
3564
3565 out:
3566 if (copy != NULL)
3567 sshbuf_free(copy);
3568 if (pub != NULL)
3569 sshkey_free(pub);
3570 return r;
3571}
3572
3573static int
3574sshkey_parse_private_rsa1(struct sshbuf *blob, const char *passphrase,
3575 struct sshkey **keyp, char **commentp)
3576{
3577 int r;
3578 u_int16_t check1, check2;
3579 u_int8_t cipher_type;
3580 struct sshbuf *decrypted = NULL, *copy = NULL;
3581 u_char *cp;
3582 char *comment = NULL;
3583 struct sshcipher_ctx ciphercontext;
3584 const struct sshcipher *cipher;
3585 struct sshkey *prv = NULL;
3586
3587 *keyp = NULL;
3588 if (commentp != NULL)
3589 *commentp = NULL;
3590
3591 /* Check that it is at least big enough to contain the ID string. */
3592 if (sshbuf_len(blob) < sizeof(LEGACY_BEGIN))
3593 return SSH_ERR_INVALID_FORMAT;
3594
3595 /*
3596 * Make sure it begins with the id string. Consume the id string
3597 * from the buffer.
3598 */
3599 if (memcmp(sshbuf_ptr(blob), LEGACY_BEGIN, sizeof(LEGACY_BEGIN)) != 0)
3600 return SSH_ERR_INVALID_FORMAT;
3601
3602 if ((prv = sshkey_new_private(KEY_RSA1)) == NULL) {
3603 r = SSH_ERR_ALLOC_FAIL;
3604 goto out;
3605 }
3606 if ((copy = sshbuf_fromb(blob)) == NULL ||
3607 (decrypted = sshbuf_new()) == NULL) {
3608 r = SSH_ERR_ALLOC_FAIL;
3609 goto out;
3610 }
3611 if ((r = sshbuf_consume(copy, sizeof(LEGACY_BEGIN))) != 0)
3612 goto out;
3613
3614 /* Read cipher type. */
3615 if ((r = sshbuf_get_u8(copy, &cipher_type)) != 0 ||
3616 (r = sshbuf_get_u32(copy, NULL)) != 0) /* reserved */
3617 goto out;
3618
3619 /* Read the public key and comment from the buffer. */
3620 if ((r = sshbuf_get_u32(copy, NULL)) != 0 || /* key bits */
3621 (r = sshbuf_get_bignum1(copy, prv->rsa->n)) != 0 ||
3622 (r = sshbuf_get_bignum1(copy, prv->rsa->e)) != 0 ||
3623 (r = sshbuf_get_cstring(copy, &comment, NULL)) != 0)
3624 goto out;
3625
3626 /* Check that it is a supported cipher. */
3627 cipher = cipher_by_number(cipher_type);
3628 if (cipher == NULL) {
3629 r = SSH_ERR_KEY_UNKNOWN_CIPHER;
3630 goto out;
3631 }
3632 /* Initialize space for decrypted data. */
3633 if ((r = sshbuf_reserve(decrypted, sshbuf_len(copy), &cp)) != 0)
3634 goto out;
3635
3636 /* Rest of the buffer is encrypted. Decrypt it using the passphrase. */
3637 if ((r = cipher_set_key_string(&ciphercontext, cipher, passphrase,
3638 CIPHER_DECRYPT)) != 0)
3639 goto out;
3640 if ((r = cipher_crypt(&ciphercontext, 0, cp,
3641 sshbuf_ptr(copy), sshbuf_len(copy), 0, 0)) != 0) {
3642 cipher_cleanup(&ciphercontext);
3643 goto out;
3644 }
3645 if ((r = cipher_cleanup(&ciphercontext)) != 0)
3646 goto out;
3647
3648 if ((r = sshbuf_get_u16(decrypted, &check1)) != 0 ||
3649 (r = sshbuf_get_u16(decrypted, &check2)) != 0)
3650 goto out;
3651 if (check1 != check2) {
3652 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3653 goto out;
3654 }
3655
3656 /* Read the rest of the private key. */
3657 if ((r = sshbuf_get_bignum1(decrypted, prv->rsa->d)) != 0 ||
3658 (r = sshbuf_get_bignum1(decrypted, prv->rsa->iqmp)) != 0 ||
3659 (r = sshbuf_get_bignum1(decrypted, prv->rsa->q)) != 0 ||
3660 (r = sshbuf_get_bignum1(decrypted, prv->rsa->p)) != 0)
3661 goto out;
3662
3663 /* calculate p-1 and q-1 */
3664 if ((r = rsa_generate_additional_parameters(prv->rsa)) != 0)
3665 goto out;
3666
3667 /* enable blinding */
3668 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3669 r = SSH_ERR_LIBCRYPTO_ERROR;
3670 goto out;
3671 }
3672 r = 0;
3673 *keyp = prv;
3674 prv = NULL;
3675 if (commentp != NULL) {
3676 *commentp = comment;
3677 comment = NULL;
3678 }
3679 out:
3680 explicit_bzero(&ciphercontext, sizeof(ciphercontext));
3681 if (comment != NULL)
3682 free(comment);
3683 if (prv != NULL)
3684 sshkey_free(prv);
3685 if (copy != NULL)
3686 sshbuf_free(copy);
3687 if (decrypted != NULL)
3688 sshbuf_free(decrypted);
3689 return r;
3690}
3691#endif /* WITH_SSH1 */
3692
3693#ifdef WITH_OPENSSL
3694/* XXX make private once ssh-keysign.c fixed */
3695int
3696sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
3697 const char *passphrase, struct sshkey **keyp, char **commentp)
3698{
3699 EVP_PKEY *pk = NULL;
3700 struct sshkey *prv = NULL;
3701 char *name = "<no key>";
3702 BIO *bio = NULL;
3703 int r;
3704
3705 *keyp = NULL;
3706 if (commentp != NULL)
3707 *commentp = NULL;
3708
3709 if ((bio = BIO_new(BIO_s_mem())) == NULL || sshbuf_len(blob) > INT_MAX)
3710 return SSH_ERR_ALLOC_FAIL;
3711 if (BIO_write(bio, sshbuf_ptr(blob), sshbuf_len(blob)) !=
3712 (int)sshbuf_len(blob)) {
3713 r = SSH_ERR_ALLOC_FAIL;
3714 goto out;
3715 }
3716
3717 if ((pk = PEM_read_bio_PrivateKey(bio, NULL, NULL,
3718 (char *)passphrase)) == NULL) {
3719 r = SSH_ERR_KEY_WRONG_PASSPHRASE;
3720 goto out;
3721 }
3722 if (pk->type == EVP_PKEY_RSA &&
3723 (type == KEY_UNSPEC || type == KEY_RSA)) {
3724 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3725 r = SSH_ERR_ALLOC_FAIL;
3726 goto out;
3727 }
3728 prv->rsa = EVP_PKEY_get1_RSA(pk);
3729 prv->type = KEY_RSA;
3730 name = "rsa w/o comment";
3731#ifdef DEBUG_PK
3732 RSA_print_fp(stderr, prv->rsa, 8);
3733#endif
3734 if (RSA_blinding_on(prv->rsa, NULL) != 1) {
3735 r = SSH_ERR_LIBCRYPTO_ERROR;
3736 goto out;
3737 }
3738 } else if (pk->type == EVP_PKEY_DSA &&
3739 (type == KEY_UNSPEC || type == KEY_DSA)) {
3740 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3741 r = SSH_ERR_ALLOC_FAIL;
3742 goto out;
3743 }
3744 prv->dsa = EVP_PKEY_get1_DSA(pk);
3745 prv->type = KEY_DSA;
3746 name = "dsa w/o comment";
3747#ifdef DEBUG_PK
3748 DSA_print_fp(stderr, prv->dsa, 8);
3749#endif
3750#ifdef OPENSSL_HAS_ECC
3751 } else if (pk->type == EVP_PKEY_EC &&
3752 (type == KEY_UNSPEC || type == KEY_ECDSA)) {
3753 if ((prv = sshkey_new(KEY_UNSPEC)) == NULL) {
3754 r = SSH_ERR_ALLOC_FAIL;
3755 goto out;
3756 }
3757 prv->ecdsa = EVP_PKEY_get1_EC_KEY(pk);
3758 prv->type = KEY_ECDSA;
3759 prv->ecdsa_nid = sshkey_ecdsa_key_to_nid(prv->ecdsa);
3760 if (prv->ecdsa_nid == -1 ||
3761 sshkey_curve_nid_to_name(prv->ecdsa_nid) == NULL ||
3762 sshkey_ec_validate_public(EC_KEY_get0_group(prv->ecdsa),
3763 EC_KEY_get0_public_key(prv->ecdsa)) != 0 ||
3764 sshkey_ec_validate_private(prv->ecdsa) != 0) {
3765 r = SSH_ERR_INVALID_FORMAT;
3766 goto out;
3767 }
3768 name = "ecdsa w/o comment";
3769# ifdef DEBUG_PK
3770 if (prv != NULL && prv->ecdsa != NULL)
3771 sshkey_dump_ec_key(prv->ecdsa);
3772# endif
3773#endif /* OPENSSL_HAS_ECC */
3774 } else {
3775 r = SSH_ERR_INVALID_FORMAT;
3776 goto out;
3777 }
3778 if (commentp != NULL &&
3779 (*commentp = strdup(name)) == NULL) {
3780 r = SSH_ERR_ALLOC_FAIL;
3781 goto out;
3782 }
3783 r = 0;
3784 *keyp = prv;
3785 prv = NULL;
3786 out:
3787 BIO_free(bio);
3788 if (pk != NULL)
3789 EVP_PKEY_free(pk);
3790 if (prv != NULL)
3791 sshkey_free(prv);
3792 return r;
3793}
3794#endif /* WITH_OPENSSL */
3795
3796int
3797sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
3798 const char *passphrase, struct sshkey **keyp, char **commentp)
3799{
3800 int r;
3801
3802 *keyp = NULL;
3803 if (commentp != NULL)
3804 *commentp = NULL;
3805
3806 switch (type) {
3807#ifdef WITH_OPENSSL
3808 case KEY_RSA1:
3809 return sshkey_parse_private_rsa1(blob, passphrase,
3810 keyp, commentp);
3811 case KEY_DSA:
3812 case KEY_ECDSA:
3813 case KEY_RSA:
3814 return sshkey_parse_private_pem_fileblob(blob, type, passphrase,
3815 keyp, commentp);
3816#endif /* WITH_OPENSSL */
3817 case KEY_ED25519:
3818 return sshkey_parse_private2(blob, type, passphrase,
3819 keyp, commentp);
3820 case KEY_UNSPEC:
3821 if ((r = sshkey_parse_private2(blob, type, passphrase, keyp,
3822 commentp)) == 0)
3823 return 0;
3824#ifdef WITH_OPENSSL
3825 return sshkey_parse_private_pem_fileblob(blob, type, passphrase,
3826 keyp, commentp);
3827#else
3828 return SSH_ERR_INVALID_FORMAT;
3829#endif /* WITH_OPENSSL */
3830 default:
3831 return SSH_ERR_KEY_TYPE_UNKNOWN;
3832 }
3833}
3834
3835int
3836sshkey_parse_private_fileblob(struct sshbuf *buffer, const char *passphrase,
3837 const char *filename, struct sshkey **keyp, char **commentp)
3838{
3839 int r;
3840
3841 if (keyp != NULL)
3842 *keyp = NULL;
3843 if (commentp != NULL)
3844 *commentp = NULL;
3845
3846#ifdef WITH_SSH1
3847 /* it's a SSH v1 key if the public key part is readable */
3848 if ((r = sshkey_parse_public_rsa1_fileblob(buffer, NULL, NULL)) == 0) {
3849 return sshkey_parse_private_fileblob_type(buffer, KEY_RSA1,
3850 passphrase, keyp, commentp);
3851 }
3852#endif /* WITH_SSH1 */
3853 if ((r = sshkey_parse_private_fileblob_type(buffer, KEY_UNSPEC,
3854 passphrase, keyp, commentp)) == 0)
3855 return 0;
3856 return r;
3857}
diff --git a/sshkey.h b/sshkey.h
new file mode 100644
index 000000000..b573e7f33
--- /dev/null
+++ b/sshkey.h
@@ -0,0 +1,233 @@
1/* $OpenBSD: sshkey.h,v 1.1 2014/06/24 01:16:58 djm Exp $ */
2
3/*
4 * Copyright (c) 2000, 2001 Markus Friedl. All rights reserved.
5 *
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
8 * are met:
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 *
15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
16 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
17 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
18 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
19 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
20 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
21 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
22 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
23 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
24 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25 */
26#ifndef SSHKEY_H
27#define SSHKEY_H
28
29#include <sys/types.h>
30
31#ifdef WITH_OPENSSL
32#include <openssl/rsa.h>
33#include <openssl/dsa.h>
34# ifdef OPENSSL_HAS_ECC
35# include <openssl/ec.h>
36# else /* OPENSSL_HAS_ECC */
37# define EC_KEY void
38# define EC_GROUP void
39# define EC_POINT void
40# endif /* OPENSSL_HAS_ECC */
41#else /* WITH_OPENSSL */
42# define RSA void
43# define DSA void
44# define EC_KEY void
45# define EC_GROUP void
46# define EC_POINT void
47#endif /* WITH_OPENSSL */
48
49#define SSH_RSA_MINIMUM_MODULUS_SIZE 768
50#define SSH_KEY_MAX_SIGN_DATA_SIZE (1 << 20)
51
52struct sshbuf;
53
54/* Key types */
55enum sshkey_types {
56 KEY_RSA1,
57 KEY_RSA,
58 KEY_DSA,
59 KEY_ECDSA,
60 KEY_ED25519,
61 KEY_RSA_CERT,
62 KEY_DSA_CERT,
63 KEY_ECDSA_CERT,
64 KEY_ED25519_CERT,
65 KEY_RSA_CERT_V00,
66 KEY_DSA_CERT_V00,
67 KEY_NULL,
68 KEY_UNSPEC
69};
70
71/* Fingerprint hash algorithms */
72enum sshkey_fp_type {
73 SSH_FP_SHA1,
74 SSH_FP_MD5,
75 SSH_FP_SHA256
76};
77
78/* Fingerprint representation formats */
79enum sshkey_fp_rep {
80 SSH_FP_HEX,
81 SSH_FP_BUBBLEBABBLE,
82 SSH_FP_RANDOMART
83};
84
85/* key is stored in external hardware */
86#define SSHKEY_FLAG_EXT 0x0001
87
88#define SSHKEY_CERT_MAX_PRINCIPALS 256
89/* XXX opaquify? */
90struct sshkey_cert {
91 struct sshbuf *certblob; /* Kept around for use on wire */
92 u_int type; /* SSH2_CERT_TYPE_USER or SSH2_CERT_TYPE_HOST */
93 u_int64_t serial;
94 char *key_id;
95 u_int nprincipals;
96 char **principals;
97 u_int64_t valid_after, valid_before;
98 struct sshbuf *critical;
99 struct sshbuf *extensions;
100 struct sshkey *signature_key;
101};
102
103/* XXX opaquify? */
104struct sshkey {
105 int type;
106 int flags;
107 RSA *rsa;
108 DSA *dsa;
109 int ecdsa_nid; /* NID of curve */
110 EC_KEY *ecdsa;
111 u_char *ed25519_sk;
112 u_char *ed25519_pk;
113 struct sshkey_cert *cert;
114};
115
116#define ED25519_SK_SZ crypto_sign_ed25519_SECRETKEYBYTES
117#define ED25519_PK_SZ crypto_sign_ed25519_PUBLICKEYBYTES
118
119struct sshkey *sshkey_new(int);
120int sshkey_add_private(struct sshkey *);
121struct sshkey *sshkey_new_private(int);
122void sshkey_free(struct sshkey *);
123int sshkey_demote(const struct sshkey *, struct sshkey **);
124int sshkey_equal_public(const struct sshkey *,
125 const struct sshkey *);
126int sshkey_equal(const struct sshkey *, const struct sshkey *);
127char *sshkey_fingerprint(const struct sshkey *,
128 enum sshkey_fp_type, enum sshkey_fp_rep);
129int sshkey_fingerprint_raw(const struct sshkey *k,
130 enum sshkey_fp_type dgst_type, u_char **retp, size_t *lenp);
131const char *sshkey_type(const struct sshkey *);
132const char *sshkey_cert_type(const struct sshkey *);
133int sshkey_write(const struct sshkey *, FILE *);
134int sshkey_read(struct sshkey *, char **);
135u_int sshkey_size(const struct sshkey *);
136
137int sshkey_generate(int type, u_int bits, struct sshkey **keyp);
138int sshkey_from_private(const struct sshkey *, struct sshkey **);
139int sshkey_type_from_name(const char *);
140int sshkey_is_cert(const struct sshkey *);
141int sshkey_type_is_cert(int);
142int sshkey_type_plain(int);
143int sshkey_to_certified(struct sshkey *, int);
144int sshkey_drop_cert(struct sshkey *);
145int sshkey_certify(struct sshkey *, struct sshkey *);
146int sshkey_cert_copy(const struct sshkey *, struct sshkey *);
147int sshkey_cert_check_authority(const struct sshkey *, int, int,
148 const char *, const char **);
149int sshkey_cert_is_legacy(const struct sshkey *);
150
151int sshkey_ecdsa_nid_from_name(const char *);
152int sshkey_curve_name_to_nid(const char *);
153const char * sshkey_curve_nid_to_name(int);
154u_int sshkey_curve_nid_to_bits(int);
155int sshkey_ecdsa_bits_to_nid(int);
156int sshkey_ecdsa_key_to_nid(EC_KEY *);
157int sshkey_ec_nid_to_hash_alg(int nid);
158int sshkey_ec_validate_public(const EC_GROUP *, const EC_POINT *);
159int sshkey_ec_validate_private(const EC_KEY *);
160const char *sshkey_ssh_name(const struct sshkey *);
161const char *sshkey_ssh_name_plain(const struct sshkey *);
162int sshkey_names_valid2(const char *);
163char *key_alg_list(int, int);
164
165int sshkey_from_blob(const u_char *, size_t, struct sshkey **);
166int sshkey_to_blob_buf(const struct sshkey *, struct sshbuf *);
167int sshkey_to_blob(const struct sshkey *, u_char **, size_t *);
168int sshkey_plain_to_blob_buf(const struct sshkey *, struct sshbuf *);
169int sshkey_plain_to_blob(const struct sshkey *, u_char **, size_t *);
170
171int sshkey_sign(const struct sshkey *, u_char **, size_t *,
172 const u_char *, size_t, u_int);
173int sshkey_verify(const struct sshkey *, const u_char *, size_t,
174 const u_char *, size_t, u_int);
175
176/* for debug */
177void sshkey_dump_ec_point(const EC_GROUP *, const EC_POINT *);
178void sshkey_dump_ec_key(const EC_KEY *);
179
180/* private key parsing and serialisation */
181int sshkey_private_serialize(const struct sshkey *key, struct sshbuf *buf);
182int sshkey_private_deserialize(struct sshbuf *buf, struct sshkey **keyp);
183
184/* private key file format parsing and serialisation */
185int sshkey_private_to_fileblob(struct sshkey *key, struct sshbuf *blob,
186 const char *passphrase, const char *comment,
187 int force_new_format, const char *new_format_cipher, int new_format_rounds);
188int sshkey_parse_public_rsa1_fileblob(struct sshbuf *blob,
189 struct sshkey **keyp, char **commentp);
190int sshkey_parse_private_pem_fileblob(struct sshbuf *blob, int type,
191 const char *passphrase, struct sshkey **keyp, char **commentp);
192int sshkey_parse_private_fileblob(struct sshbuf *buffer,
193 const char *passphrase, const char *filename, struct sshkey **keyp,
194 char **commentp);
195int sshkey_parse_private_fileblob_type(struct sshbuf *blob, int type,
196 const char *passphrase, struct sshkey **keyp, char **commentp);
197
198#ifdef SSHKEY_INTERNAL
199int ssh_rsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
200 const u_char *data, size_t datalen, u_int compat);
201int ssh_rsa_verify(const struct sshkey *key,
202 const u_char *signature, size_t signaturelen,
203 const u_char *data, size_t datalen, u_int compat);
204int ssh_dss_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
205 const u_char *data, size_t datalen, u_int compat);
206int ssh_dss_verify(const struct sshkey *key,
207 const u_char *signature, size_t signaturelen,
208 const u_char *data, size_t datalen, u_int compat);
209int ssh_ecdsa_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
210 const u_char *data, size_t datalen, u_int compat);
211int ssh_ecdsa_verify(const struct sshkey *key,
212 const u_char *signature, size_t signaturelen,
213 const u_char *data, size_t datalen, u_int compat);
214int ssh_ed25519_sign(const struct sshkey *key, u_char **sigp, size_t *lenp,
215 const u_char *data, size_t datalen, u_int compat);
216int ssh_ed25519_verify(const struct sshkey *key,
217 const u_char *signature, size_t signaturelen,
218 const u_char *data, size_t datalen, u_int compat);
219#endif
220
221#if !defined(WITH_OPENSSL)
222# undef RSA
223# undef DSA
224# undef EC_KEY
225# undef EC_GROUP
226# undef EC_POINT
227#elif !defined(OPENSSL_HAS_ECC)
228# undef EC_KEY
229# undef EC_GROUP
230# undef EC_POINT
231#endif
232
233#endif /* SSHKEY_H */
diff --git a/sshlogin.c b/sshlogin.c
index e79ca9b47..7b951c844 100644
--- a/sshlogin.c
+++ b/sshlogin.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: sshlogin.c,v 1.28 2014/01/31 16:39:19 tedu Exp $ */ 1/* $OpenBSD: sshlogin.c,v 1.29 2014/07/15 15:54:14 millert Exp $ */
2/* 2/*
3 * Author: Tatu Ylonen <ylo@cs.hut.fi> 3 * Author: Tatu Ylonen <ylo@cs.hut.fi>
4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland 4 * Copyright (c) 1995 Tatu Ylonen <ylo@cs.hut.fi>, Espoo, Finland
@@ -58,6 +58,7 @@
58#include "loginrec.h" 58#include "loginrec.h"
59#include "log.h" 59#include "log.h"
60#include "buffer.h" 60#include "buffer.h"
61#include "misc.h"
61#include "servconf.h" 62#include "servconf.h"
62 63
63extern Buffer loginmsg; 64extern Buffer loginmsg;
diff --git a/sshpty.c b/sshpty.c
index 8cc26a249..3512ec801 100644
--- a/sshpty.c
+++ b/sshpty.c
@@ -99,9 +99,6 @@ void
99pty_make_controlling_tty(int *ttyfd, const char *tty) 99pty_make_controlling_tty(int *ttyfd, const char *tty)
100{ 100{
101 int fd; 101 int fd;
102#ifdef USE_VHANGUP
103 void *old;
104#endif /* USE_VHANGUP */
105 102
106#ifdef _UNICOS 103#ifdef _UNICOS
107 if (setsid() < 0) 104 if (setsid() < 0)
@@ -157,21 +154,11 @@ pty_make_controlling_tty(int *ttyfd, const char *tty)
157 if (setpgrp(0,0) < 0) 154 if (setpgrp(0,0) < 0)
158 error("SETPGRP %s",strerror(errno)); 155 error("SETPGRP %s",strerror(errno));
159#endif /* NEED_SETPGRP */ 156#endif /* NEED_SETPGRP */
160#ifdef USE_VHANGUP
161 old = signal(SIGHUP, SIG_IGN);
162 vhangup();
163 signal(SIGHUP, old);
164#endif /* USE_VHANGUP */
165 fd = open(tty, O_RDWR); 157 fd = open(tty, O_RDWR);
166 if (fd < 0) { 158 if (fd < 0) {
167 error("%.100s: %.100s", tty, strerror(errno)); 159 error("%.100s: %.100s", tty, strerror(errno));
168 } else { 160 } else {
169#ifdef USE_VHANGUP
170 close(*ttyfd);
171 *ttyfd = fd;
172#else /* USE_VHANGUP */
173 close(fd); 161 close(fd);
174#endif /* USE_VHANGUP */
175 } 162 }
176 /* Verify that we now have a controlling tty. */ 163 /* Verify that we now have a controlling tty. */
177 fd = open(_PATH_TTY, O_WRONLY); 164 fd = open(_PATH_TTY, O_WRONLY);
diff --git a/umac.c b/umac.c
index 0c62145fa..6eb55b26e 100644
--- a/umac.c
+++ b/umac.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: umac.c,v 1.8 2013/11/08 00:39:15 djm Exp $ */ 1/* $OpenBSD: umac.c,v 1.11 2014/07/22 07:13:42 guenther Exp $ */
2/* ----------------------------------------------------------------------- 2/* -----------------------------------------------------------------------
3 * 3 *
4 * umac.c -- C Implementation UMAC Message Authentication 4 * umac.c -- C Implementation UMAC Message Authentication
@@ -73,13 +73,15 @@
73 73
74#include "includes.h" 74#include "includes.h"
75#include <sys/types.h> 75#include <sys/types.h>
76
77#include "xmalloc.h"
78#include "umac.h"
79#include <string.h> 76#include <string.h>
77#include <stdio.h>
80#include <stdlib.h> 78#include <stdlib.h>
81#include <stddef.h> 79#include <stddef.h>
82 80
81#include "xmalloc.h"
82#include "umac.h"
83#include "misc.h"
84
83/* ---------------------------------------------------------------------- */ 85/* ---------------------------------------------------------------------- */
84/* --- Primitive Data Types --- */ 86/* --- Primitive Data Types --- */
85/* ---------------------------------------------------------------------- */ 87/* ---------------------------------------------------------------------- */
@@ -131,41 +133,17 @@ typedef unsigned int UWORD; /* Register */
131/* --- Endian Conversion --- Forcing assembly on some platforms */ 133/* --- Endian Conversion --- Forcing assembly on some platforms */
132/* ---------------------------------------------------------------------- */ 134/* ---------------------------------------------------------------------- */
133 135
134#if HAVE_SWAP32
135#define LOAD_UINT32_REVERSED(p) (swap32(*(const UINT32 *)(p)))
136#define STORE_UINT32_REVERSED(p,v) (*(UINT32 *)(p) = swap32(v))
137#else /* HAVE_SWAP32 */
138
139static UINT32 LOAD_UINT32_REVERSED(const void *ptr)
140{
141 UINT32 temp = *(const UINT32 *)ptr;
142 temp = (temp >> 24) | ((temp & 0x00FF0000) >> 8 )
143 | ((temp & 0x0000FF00) << 8 ) | (temp << 24);
144 return (UINT32)temp;
145}
146
147# if (__LITTLE_ENDIAN__)
148static void STORE_UINT32_REVERSED(void *ptr, UINT32 x)
149{
150 UINT32 i = (UINT32)x;
151 *(UINT32 *)ptr = (i >> 24) | ((i & 0x00FF0000) >> 8 )
152 | ((i & 0x0000FF00) << 8 ) | (i << 24);
153}
154# endif /* __LITTLE_ENDIAN */
155#endif /* HAVE_SWAP32 */
156
157/* The following definitions use the above reversal-primitives to do the right
158 * thing on endian specific load and stores.
159 */
160
161#if (__LITTLE_ENDIAN__) 136#if (__LITTLE_ENDIAN__)
162#define LOAD_UINT32_LITTLE(ptr) (*(const UINT32 *)(ptr)) 137#define LOAD_UINT32_REVERSED(p) get_u32(p)
163#define STORE_UINT32_BIG(ptr,x) STORE_UINT32_REVERSED(ptr,x) 138#define STORE_UINT32_REVERSED(p,v) put_u32(p,v)
164#else 139#else
165#define LOAD_UINT32_LITTLE(ptr) LOAD_UINT32_REVERSED(ptr) 140#define LOAD_UINT32_REVERSED(p) get_u32_le(p)
166#define STORE_UINT32_BIG(ptr,x) (*(UINT32 *)(ptr) = (UINT32)(x)) 141#define STORE_UINT32_REVERSED(p,v) put_u32_le(p,v)
167#endif 142#endif
168 143
144#define LOAD_UINT32_LITTLE(p) (get_u32_le(p))
145#define STORE_UINT32_BIG(p,v) put_u32(p, v)
146
169/* ---------------------------------------------------------------------- */ 147/* ---------------------------------------------------------------------- */
170/* ---------------------------------------------------------------------- */ 148/* ---------------------------------------------------------------------- */
171/* ----- Begin KDF & PDF Section ---------------------------------------- */ 149/* ----- Begin KDF & PDF Section ---------------------------------------- */
@@ -176,6 +154,7 @@ static void STORE_UINT32_REVERSED(void *ptr, UINT32 x)
176#define AES_BLOCK_LEN 16 154#define AES_BLOCK_LEN 16
177 155
178/* OpenSSL's AES */ 156/* OpenSSL's AES */
157#ifdef WITH_OPENSSL
179#include "openbsd-compat/openssl-compat.h" 158#include "openbsd-compat/openssl-compat.h"
180#ifndef USE_BUILTIN_RIJNDAEL 159#ifndef USE_BUILTIN_RIJNDAEL
181# include <openssl/aes.h> 160# include <openssl/aes.h>
@@ -185,6 +164,16 @@ typedef AES_KEY aes_int_key[1];
185 AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key) 164 AES_encrypt((u_char *)(in),(u_char *)(out),(AES_KEY *)int_key)
186#define aes_key_setup(key,int_key) \ 165#define aes_key_setup(key,int_key) \
187 AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key) 166 AES_set_encrypt_key((const u_char *)(key),UMAC_KEY_LEN*8,int_key)
167#else
168#include "rijndael.h"
169#define AES_ROUNDS ((UMAC_KEY_LEN / 4) + 6)
170typedef UINT8 aes_int_key[AES_ROUNDS+1][4][4]; /* AES internal */
171#define aes_encryption(in,out,int_key) \
172 rijndaelEncrypt((u32 *)(int_key), AES_ROUNDS, (u8 *)(in), (u8 *)(out))
173#define aes_key_setup(key,int_key) \
174 rijndaelKeySetupEnc((u32 *)(int_key), (const unsigned char *)(key), \
175 UMAC_KEY_LEN*8)
176#endif
188 177
189/* The user-supplied UMAC key is stretched using AES in a counter 178/* The user-supplied UMAC key is stretched using AES in a counter
190 * mode to supply all random bits needed by UMAC. The kdf function takes 179 * mode to supply all random bits needed by UMAC. The kdf function takes
diff --git a/version.h b/version.h
index 065957661..0fee7c3c2 100644
--- a/version.h
+++ b/version.h
@@ -1,6 +1,6 @@
1/* $OpenBSD: version.h,v 1.70 2014/02/27 22:57:40 djm Exp $ */ 1/* $OpenBSD: version.h,v 1.71 2014/04/18 23:52:25 djm Exp $ */
2 2
3#define SSH_VERSION "OpenSSH_6.6.1" 3#define SSH_VERSION "OpenSSH_6.7"
4 4
5#define SSH_PORTABLE "p1" 5#define SSH_PORTABLE "p1"
6#define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE 6#define SSH_RELEASE_MINIMUM SSH_VERSION SSH_PORTABLE