summaryrefslogtreecommitdiffstats
path: root/crypto/openssh/regress
diff options
context:
space:
mode:
authordes <des@FreeBSD.org>2016-01-19 18:28:23 +0000
committerdes <des@FreeBSD.org>2016-01-19 18:28:23 +0000
commit7a7bc643b5dd94f6333f2a1d91923165ad77176f (patch)
tree9d2b367395b2d3c9a63b4aecd1eb28b17b838703 /crypto/openssh/regress
parent834fb5aff44e0a606772591d869016a1d8d9aa95 (diff)
parent928d872bfcc9d49be194dc51d80555f1bbdbff6b (diff)
downloadFreeBSD-src-7a7bc643b5dd94f6333f2a1d91923165ad77176f.zip
FreeBSD-src-7a7bc643b5dd94f6333f2a1d91923165ad77176f.tar.gz
Upgrade to OpenSSH 6.8p1.
Diffstat (limited to 'crypto/openssh/regress')
-rw-r--r--crypto/openssh/regress/.cvsignore31
-rw-r--r--crypto/openssh/regress/Makefile47
-rwxr-xr-xcrypto/openssh/regress/agent-pkcs11.sh4
-rw-r--r--crypto/openssh/regress/agent-timeout.sh4
-rw-r--r--crypto/openssh/regress/agent.sh8
-rw-r--r--crypto/openssh/regress/broken-pipe.sh4
-rwxr-xr-xcrypto/openssh/regress/cert-hostkey.sh111
-rw-r--r--crypto/openssh/regress/cfgmatch.sh23
-rw-r--r--crypto/openssh/regress/cipher-speed.sh8
-rw-r--r--crypto/openssh/regress/connect-privsep.sh8
-rw-r--r--crypto/openssh/regress/connect.sh4
-rw-r--r--crypto/openssh/regress/dynamic-forward.sh4
-rw-r--r--crypto/openssh/regress/exit-status.sh4
-rw-r--r--crypto/openssh/regress/forcecommand.sh26
-rwxr-xr-xcrypto/openssh/regress/forward-control.sh6
-rw-r--r--crypto/openssh/regress/forwarding.sh20
-rwxr-xr-xcrypto/openssh/regress/host-expand.sh4
-rwxr-xr-xcrypto/openssh/regress/hostkey-agent.sh52
-rwxr-xr-xcrypto/openssh/regress/hostkey-rotate.sh128
-rwxr-xr-xcrypto/openssh/regress/integrity.sh6
-rwxr-xr-xcrypto/openssh/regress/key-options.sh10
-rw-r--r--crypto/openssh/regress/keygen-change.sh9
-rwxr-xr-xcrypto/openssh/regress/keygen-knownhosts.sh197
-rw-r--r--crypto/openssh/regress/keyscan.sh9
-rwxr-xr-xcrypto/openssh/regress/krl.sh90
-rwxr-xr-xcrypto/openssh/regress/limit-keytype.sh80
-rwxr-xr-xcrypto/openssh/regress/localcommand.sh4
-rw-r--r--crypto/openssh/regress/multiplex.sh25
-rwxr-xr-xcrypto/openssh/regress/multipubkey.sh66
-rw-r--r--crypto/openssh/regress/netcat.c1690
-rw-r--r--crypto/openssh/regress/proto-mismatch.sh6
-rw-r--r--crypto/openssh/regress/proto-version.sh10
-rw-r--r--crypto/openssh/regress/proxy-connect.sh6
-rw-r--r--crypto/openssh/regress/reconfigure.sh31
-rw-r--r--crypto/openssh/regress/reexec.sh4
-rw-r--r--crypto/openssh/regress/rekey.sh24
-rw-r--r--crypto/openssh/regress/sshd-log-wrapper.sh8
-rw-r--r--crypto/openssh/regress/stderr-data.sh4
-rw-r--r--crypto/openssh/regress/t11.ok1
-rw-r--r--crypto/openssh/regress/t4.ok2
-rw-r--r--crypto/openssh/regress/test-exec.sh88
-rw-r--r--crypto/openssh/regress/transfer.sh4
-rw-r--r--crypto/openssh/regress/try-ciphers.sh8
-rw-r--r--crypto/openssh/regress/unittests/Makefile6
-rw-r--r--crypto/openssh/regress/unittests/Makefile.inc4
-rw-r--r--crypto/openssh/regress/unittests/bitmap/Makefile12
-rw-r--r--crypto/openssh/regress/unittests/bitmap/tests.c135
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/Makefile12
-rwxr-xr-xcrypto/openssh/regress/unittests/hostkeys/mktestdata.sh94
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/test_iterate.c1171
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts61
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub1
-rw-r--r--crypto/openssh/regress/unittests/hostkeys/tests.c16
-rw-r--r--crypto/openssh/regress/unittests/kex/Makefile14
-rw-r--r--crypto/openssh/regress/unittests/kex/test_kex.c197
-rw-r--r--crypto/openssh/regress/unittests/kex/tests.c14
-rw-r--r--crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c8
-rw-r--r--crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c4
-rw-r--r--crypto/openssh/regress/unittests/sshkey/common.c4
-rwxr-xr-xcrypto/openssh/regress/unittests/sshkey/mktestdata.sh4
-rw-r--r--crypto/openssh/regress/unittests/sshkey/test_file.c33
-rw-r--r--crypto/openssh/regress/unittests/sshkey/test_fuzz.c13
-rw-r--r--crypto/openssh/regress/unittests/sshkey/test_sshkey.c192
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp2
-rw-r--r--crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp2
-rw-r--r--crypto/openssh/regress/unittests/test_helper/Makefile5
-rw-r--r--crypto/openssh/regress/unittests/test_helper/fuzz.c102
-rw-r--r--crypto/openssh/regress/unittests/test_helper/test_helper.c67
-rw-r--r--crypto/openssh/regress/unittests/test_helper/test_helper.h13
-rwxr-xr-xcrypto/openssh/regress/valgrind-unit.sh20
-rw-r--r--crypto/openssh/regress/yes-head.sh4
112 files changed, 4851 insertions, 290 deletions
diff --git a/crypto/openssh/regress/.cvsignore b/crypto/openssh/regress/.cvsignore
new file mode 100644
index 0000000..3fd25b0
--- /dev/null
+++ b/crypto/openssh/regress/.cvsignore
@@ -0,0 +1,31 @@
+*-agent
+*.copy
+*.log
+*.prv
+*.pub
+actual
+authorized_keys_*
+batch
+copy.dd*
+data
+expect
+host.rsa*
+key.*
+known_hosts
+krl-*
+modpipe
+remote_pid
+revoked-*
+revoked-ca
+revoked-keyid
+revoked-serials
+rsa
+rsa1
+sftp-server.sh
+ssh-log-wrapper.sh
+ssh_config
+ssh_proxy*
+sshd_config
+sshd_proxy*
+t*.out
+t*.out[0-9]
diff --git a/crypto/openssh/regress/Makefile b/crypto/openssh/regress/Makefile
index 3feb7a9..99a7d60 100644
--- a/crypto/openssh/regress/Makefile
+++ b/crypto/openssh/regress/Makefile
@@ -1,11 +1,14 @@
-# $OpenBSD: Makefile,v 1.70 2014/06/24 01:14:17 djm Exp $
+# $OpenBSD: Makefile,v 1.78 2015/01/26 06:12:18 djm Exp $
-REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec
-tests: $(REGRESS_TARGETS)
+REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec
+tests: prep $(REGRESS_TARGETS)
# Interop tests are not run by default
interop interop-tests: t-exec-interop
+prep:
+ test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out
+
clean:
for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done
test -z "${SUDO}" || ${SUDO} rm -f ${SUDO_CLEAN}
@@ -64,7 +67,14 @@ LTESTS= connect \
keys-command \
forward-control \
integrity \
- krl
+ krl \
+ multipubkey \
+ limit-keytype \
+ hostkey-agent \
+ keygen-knownhosts \
+ hostkey-rotate
+
+
# dhgex \
INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
@@ -75,6 +85,7 @@ INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
USER!= id -un
CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
t8.out t8.out.pub t9.out t9.out.pub t10.out t10.out.pub \
+ t12.out t12.out.pub \
authorized_keys_${USER} known_hosts pidfile testdata \
ssh_config sshd_config.orig ssh_proxy sshd_config sshd_proxy \
rsa.pub rsa rsa1.pub rsa1 host.rsa host.rsa1 \
@@ -91,7 +102,8 @@ CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
regress.log failed-regress.log ssh-log-wrapper.sh \
sftp-server.sh sftp-server.log sftp.log setuid-allowed \
data ed25519-agent ed25519-agent.pub key.ed25519-512 \
- key.ed25519-512.pub
+ key.ed25519-512.pub netcat host_krl_* host_revoked_* \
+ kh.* user_*key* agent-key.* known_hosts.* hkr.*
SUDO_CLEAN+= /var/run/testdata_${USER} /var/run/keycommand_${USER}
@@ -119,7 +131,7 @@ t3:
${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub
t4:
- ${TEST_SSH_SSHKEYGEN} -lf ${.CURDIR}/rsa_openssh.pub |\
+ ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\
awk '{print $$2}' | diff - ${.CURDIR}/t4.ok
t5:
@@ -164,6 +176,16 @@ t10: $(OBJ)/t10.out
${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null
${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null
+t11:
+ ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\
+ awk '{print $$2}' | diff - ${.CURDIR}/t11.ok
+
+t12.out:
+ ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $(OBJ)/$@
+
+t12: t12.out
+ ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null
+
t-exec: ${LTESTS:=.sh}
@if [ "x$?" = "x" ]; then exit 0; fi; \
for TEST in ""$?; do \
@@ -184,7 +206,14 @@ interop: ${INTEROP_TARGETS}
# Unit tests, built by top-level Makefile
unit:
set -e ; if test -z "${SKIP_UNIT}" ; then \
- ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
- ${.OBJDIR}/unittests/sshkey/test_sshkey \
- -d ${.CURDIR}//unittests/sshkey/testdata ; \
+ V="" ; \
+ test "x${USE_VALGRIND}" = "x" || \
+ V=${.CURDIR}/valgrind-unit.sh ; \
+ $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
+ $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
+ -d ${.CURDIR}/unittests/sshkey/testdata ; \
+ $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \
+ $$V ${.OBJDIR}/unittests/kex/test_kex ; \
+ $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \
+ -d ${.CURDIR}/unittests/hostkeys/testdata ; \
fi
diff --git a/crypto/openssh/regress/agent-pkcs11.sh b/crypto/openssh/regress/agent-pkcs11.sh
index db33ab3..3aa20c8 100755
--- a/crypto/openssh/regress/agent-pkcs11.sh
+++ b/crypto/openssh/regress/agent-pkcs11.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent-pkcs11.sh,v 1.1 2010/02/08 10:52:47 markus Exp $
+# $OpenBSD: agent-pkcs11.sh,v 1.2 2015/01/12 11:46:32 djm Exp $
# Placed in the Public Domain.
tid="pkcs11 agent test"
@@ -6,6 +6,8 @@ tid="pkcs11 agent test"
TEST_SSH_PIN=""
TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0
+test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"
+
# setup environment for soft-pkcs11 token
SOFTPKCS11RC=$OBJ/pkcs11.info
export SOFTPKCS11RC
diff --git a/crypto/openssh/regress/agent-timeout.sh b/crypto/openssh/regress/agent-timeout.sh
index 6882659..9598c20 100644
--- a/crypto/openssh/regress/agent-timeout.sh
+++ b/crypto/openssh/regress/agent-timeout.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent-timeout.sh,v 1.2 2013/05/17 01:16:09 dtucker Exp $
+# $OpenBSD: agent-timeout.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="agent timeout test"
@@ -12,7 +12,7 @@ if [ $r -ne 0 ]; then
fail "could not start ssh-agent: exit code $r"
else
trace "add keys with timeout"
- for t in rsa rsa1; do
+ for t in ${SSH_KEYTYPES}; do
${SSHADD} -t ${SSHAGENT_TIMEOUT} $OBJ/$t > /dev/null 2>&1
if [ $? -ne 0 ]; then
fail "ssh-add did succeed exit code 0"
diff --git a/crypto/openssh/regress/agent.sh b/crypto/openssh/regress/agent.sh
index caad3c8..c5e2794 100644
--- a/crypto/openssh/regress/agent.sh
+++ b/crypto/openssh/regress/agent.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent.sh,v 1.10 2014/02/27 21:21:25 djm Exp $
+# $OpenBSD: agent.sh,v 1.11 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="simple agent test"
@@ -20,7 +20,7 @@ else
fi
trace "overwrite authorized keys"
printf '' > $OBJ/authorized_keys_$USER
- for t in ed25519 rsa rsa1; do
+ for t in ${SSH_KEYTYPES}; do
# generate user key for agent
rm -f $OBJ/$t-agent
${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\
@@ -46,7 +46,7 @@ else
fi
trace "simple connect via agent"
- for p in 1 2; do
+ for p in ${SSH_PROTOCOLS}; do
${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p
r=$?
if [ $r -ne 5$p ]; then
@@ -55,7 +55,7 @@ else
done
trace "agent forwarding"
- for p in 1 2; do
+ for p in ${SSH_PROTOCOLS}; do
${SSH} -A -$p -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
diff --git a/crypto/openssh/regress/broken-pipe.sh b/crypto/openssh/regress/broken-pipe.sh
index c08c849..a416f7a 100644
--- a/crypto/openssh/regress/broken-pipe.sh
+++ b/crypto/openssh/regress/broken-pipe.sh
@@ -1,9 +1,9 @@
-# $OpenBSD: broken-pipe.sh,v 1.4 2002/03/15 13:08:56 markus Exp $
+# $OpenBSD: broken-pipe.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="broken pipe test"
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "protocol $p"
for i in 1 2 3 4; do
${SSH} -$p -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true
diff --git a/crypto/openssh/regress/cert-hostkey.sh b/crypto/openssh/regress/cert-hostkey.sh
index 1d9e0ed..51685dc 100755
--- a/crypto/openssh/regress/cert-hostkey.sh
+++ b/crypto/openssh/regress/cert-hostkey.sh
@@ -1,21 +1,29 @@
-# $OpenBSD: cert-hostkey.sh,v 1.9 2014/01/26 10:22:10 djm Exp $
+# $OpenBSD: cert-hostkey.sh,v 1.11 2015/01/19 06:01:32 djm Exp $
# Placed in the Public Domain.
tid="certified host keys"
-rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key*
+rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/host_revoked_*
+rm -f $OBJ/cert_host_key* $OBJ/host_krl_*
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
HOSTS='localhost-with-alias,127.0.0.1,::1'
-# Create a CA key and add it to known hosts
-${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/host_ca_key ||\
+# Create a CA key and add it to known hosts. Ed25519 chosed for speed.
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/host_ca_key ||\
fail "ssh-keygen of host_ca_key failed"
(
printf '@cert-authority '
printf "$HOSTS "
cat $OBJ/host_ca_key.pub
-) > $OBJ/known_hosts-cert
+) > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+
+# Plain text revocation files
+touch $OBJ/host_revoked_empty
+touch $OBJ/host_revoked_plain
+touch $OBJ/host_revoked_cert
+cp $OBJ/host_ca_key.pub $OBJ/host_revoked_ca
PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
@@ -26,17 +34,33 @@ type_has_legacy() {
return 0
}
+# Prepare certificate, plain key and CA KRLs
+${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed"
+${SSHKEYGEN} -kf $OBJ/host_krl_plain || fatal "KRL init failed"
+${SSHKEYGEN} -kf $OBJ/host_krl_cert || fatal "KRL init failed"
+${SSHKEYGEN} -kf $OBJ/host_krl_ca $OBJ/host_ca_key.pub \
+ || fatal "KRL init failed"
+
# Generate and sign host keys
+serial=1
for ktype in $PLAIN_TYPES ; do
verbose "$tid: sign host ${ktype} cert"
# Generate and sign a host key
${SSHKEYGEN} -q -N '' -t ${ktype} \
-f $OBJ/cert_host_key_${ktype} || \
- fail "ssh-keygen of cert_host_key_${ktype} failed"
- ${SSHKEYGEN} -h -q -s $OBJ/host_ca_key \
+ fatal "ssh-keygen of cert_host_key_${ktype} failed"
+ ${SSHKEYGEN} -ukf $OBJ/host_krl_plain \
+ $OBJ/cert_host_key_${ktype}.pub || fatal "KRL update failed"
+ cat $OBJ/cert_host_key_${ktype}.pub >> $OBJ/host_revoked_plain
+ ${SSHKEYGEN} -h -q -s $OBJ/host_ca_key -z $serial \
-I "regress host key for $USER" \
-n $HOSTS $OBJ/cert_host_key_${ktype} ||
- fail "couldn't sign cert_host_key_${ktype}"
+ fatal "couldn't sign cert_host_key_${ktype}"
+ ${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
+ $OBJ/cert_host_key_${ktype}-cert.pub || \
+ fatal "KRL update failed"
+ cat $OBJ/cert_host_key_${ktype}-cert.pub >> $OBJ/host_revoked_cert
+ serial=`expr $serial + 1`
type_has_legacy $ktype || continue
cp $OBJ/cert_host_key_${ktype} $OBJ/cert_host_key_${ktype}_v00
cp $OBJ/cert_host_key_${ktype}.pub $OBJ/cert_host_key_${ktype}_v00.pub
@@ -44,10 +68,35 @@ for ktype in $PLAIN_TYPES ; do
${SSHKEYGEN} -t v00 -h -q -s $OBJ/host_ca_key \
-I "regress host key for $USER" \
-n $HOSTS $OBJ/cert_host_key_${ktype}_v00 ||
- fail "couldn't sign cert_host_key_${ktype}_v00"
+ fatal "couldn't sign cert_host_key_${ktype}_v00"
+ ${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
+ $OBJ/cert_host_key_${ktype}_v00-cert.pub || \
+ fatal "KRL update failed"
+ cat $OBJ/cert_host_key_${ktype}_v00-cert.pub >> $OBJ/host_revoked_cert
done
-# Basic connect tests
+attempt_connect() {
+ _ident="$1"
+ _expect_success="$2"
+ shift; shift
+ verbose "$tid: $_ident expect success $_expect_success"
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
+ ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
+ -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
+ "$@" -F $OBJ/ssh_proxy somehost true
+ _r=$?
+ if [ "x$_expect_success" = "xyes" ] ; then
+ if [ $_r -ne 0 ]; then
+ fail "ssh cert connect $_ident failed"
+ fi
+ else
+ if [ $_r -eq 0 ]; then
+ fail "ssh cert connect $_ident succeeded unexpectedly"
+ fi
+ fi
+}
+
+# Basic connect and revocation tests.
for privsep in yes no ; do
for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do
verbose "$tid: host ${ktype} cert connect privsep $privsep"
@@ -58,12 +107,24 @@ for privsep in yes no ; do
echo UsePrivilegeSeparation $privsep
) > $OBJ/sshd_proxy
- ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
- -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
- -F $OBJ/ssh_proxy somehost true
- if [ $? -ne 0 ]; then
- fail "ssh cert connect failed"
- fi
+ # test name expect success
+ attempt_connect "$ktype basic connect" "yes"
+ attempt_connect "$ktype empty KRL" "yes" \
+ -oRevokedHostKeys=$OBJ/host_krl_empty
+ attempt_connect "$ktype KRL w/ plain key revoked" "no" \
+ -oRevokedHostKeys=$OBJ/host_krl_plain
+ attempt_connect "$ktype KRL w/ cert revoked" "no" \
+ -oRevokedHostKeys=$OBJ/host_krl_cert
+ attempt_connect "$ktype KRL w/ CA revoked" "no" \
+ -oRevokedHostKeys=$OBJ/host_krl_ca
+ attempt_connect "$ktype empty plaintext revocation" "yes" \
+ -oRevokedHostKeys=$OBJ/host_revoked_empty
+ attempt_connect "$ktype plain key plaintext revocation" "no" \
+ -oRevokedHostKeys=$OBJ/host_revoked_plain
+ attempt_connect "$ktype cert plaintext revocation" "no" \
+ -oRevokedHostKeys=$OBJ/host_revoked_cert
+ attempt_connect "$ktype CA plaintext revocation" "no" \
+ -oRevokedHostKeys=$OBJ/host_revoked_ca
done
done
@@ -76,7 +137,8 @@ done
test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey"
printf "@revoked * `cat $OBJ/cert_host_key_${ktype}.pub`\n"
done
-) > $OBJ/known_hosts-cert
+) > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
for privsep in yes no ; do
for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do
verbose "$tid: host ${ktype} revoked cert privsep $privsep"
@@ -87,6 +149,7 @@ for privsep in yes no ; do
echo UsePrivilegeSeparation $privsep
) > $OBJ/sshd_proxy
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
@@ -104,7 +167,8 @@ done
printf '@revoked '
printf "* "
cat $OBJ/host_ca_key.pub
-) > $OBJ/known_hosts-cert
+) > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do
verbose "$tid: host ${ktype} revoked cert"
(
@@ -112,6 +176,7 @@ for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do
echo HostKey $OBJ/cert_host_key_${ktype}
echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
) > $OBJ/sshd_proxy
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
@@ -125,7 +190,8 @@ done
printf '@cert-authority '
printf "$HOSTS "
cat $OBJ/host_ca_key.pub
-) > $OBJ/known_hosts-cert
+) > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
test_one() {
ident=$1
@@ -150,6 +216,7 @@ test_one() {
echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
) > $OBJ/sshd_proxy
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
@@ -212,7 +279,8 @@ done
printf '@cert-authority '
printf "$HOSTS "
cat $OBJ/host_ca_key.pub
-) > $OBJ/known_hosts-cert
+) > $OBJ/known_hosts-cert.orig
+cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
for v in v01 v00 ; do
for kt in $PLAIN_TYPES ; do
type_has_legacy $kt || continue
@@ -232,6 +300,7 @@ for v in v01 v00 ; do
echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
) > $OBJ/sshd_proxy
+ cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
-oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
-F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1
@@ -241,4 +310,4 @@ for v in v01 v00 ; do
done
done
-rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key*
+rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/cert_host_key*
diff --git a/crypto/openssh/regress/cfgmatch.sh b/crypto/openssh/regress/cfgmatch.sh
index 80cf229..0562963 100644
--- a/crypto/openssh/regress/cfgmatch.sh
+++ b/crypto/openssh/regress/cfgmatch.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cfgmatch.sh,v 1.8 2013/05/17 00:37:40 dtucker Exp $
+# $OpenBSD: cfgmatch.sh,v 1.9 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="sshd_config match"
@@ -56,7 +56,7 @@ start_sshd
#set -x
# Test Match + PermitOpen in sshd_config. This should be permitted
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "match permitopen localhost proto $p"
start_client -F $OBJ/ssh_config
${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \
@@ -65,7 +65,7 @@ for p in 1 2; do
done
# Same but from different source. This should not be permitted
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "match permitopen proxy proto $p"
start_client -F $OBJ/ssh_proxy
${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \
@@ -74,11 +74,12 @@ for p in 1 2; do
done
# Retry previous with key option, should also be denied.
-printf 'permitopen="127.0.0.1:'$PORT'" ' >$OBJ/authorized_keys_$USER
-cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER
-printf 'permitopen="127.0.0.1:'$PORT'" ' >>$OBJ/authorized_keys_$USER
-cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER
-for p in 1 2; do
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'permitopen="127.0.0.1:'$PORT'" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
+for p in ${SSH_PROTOCOLS}; do
trace "match permitopen proxy w/key opts proto $p"
start_client -F $OBJ/ssh_proxy
${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \
@@ -88,7 +89,7 @@ done
# Test both sshd_config and key options permitting the same dst/port pair.
# Should be permitted.
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "match permitopen localhost proto $p"
start_client -F $OBJ/ssh_config
${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \
@@ -102,7 +103,7 @@ echo "Match User $USER" >>$OBJ/sshd_proxy
echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
# Test that a Match overrides a PermitOpen in the global section
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "match permitopen proxy w/key opts proto $p"
start_client -F $OBJ/ssh_proxy
${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \
@@ -117,7 +118,7 @@ echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
# Test that a rule that doesn't match doesn't override, plus test a
# PermitOpen entry that's not at the start of the list
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "nomatch permitopen proxy w/key opts proto $p"
start_client -F $OBJ/ssh_proxy
${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \
diff --git a/crypto/openssh/regress/cipher-speed.sh b/crypto/openssh/regress/cipher-speed.sh
index a6d53a7..ad2f9b9 100644
--- a/crypto/openssh/regress/cipher-speed.sh
+++ b/crypto/openssh/regress/cipher-speed.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cipher-speed.sh,v 1.11 2013/11/21 03:18:51 djm Exp $
+# $OpenBSD: cipher-speed.sh,v 1.12 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="cipher speed"
@@ -31,7 +31,11 @@ for c in `${SSH} -Q cipher`; do n=0; for m in `${SSH} -Q mac`; do
n=`expr $n + 1`
done; done
-ciphers="3des blowfish"
+if ssh_version 1; then
+ ciphers="3des blowfish"
+else
+ ciphers=""
+fi
for c in $ciphers; do
trace "proto 1 cipher $c"
for x in $tries; do
diff --git a/crypto/openssh/regress/connect-privsep.sh b/crypto/openssh/regress/connect-privsep.sh
index 41cb7af..9a51f56 100644
--- a/crypto/openssh/regress/connect-privsep.sh
+++ b/crypto/openssh/regress/connect-privsep.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: connect-privsep.sh,v 1.5 2014/05/04 10:40:59 logan Exp $
+# $OpenBSD: connect-privsep.sh,v 1.6 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="proxy connect with privsep"
@@ -6,7 +6,7 @@ tid="proxy connect with privsep"
cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
if [ $? -ne 0 ]; then
fail "ssh privsep+proxyconnect protocol $p failed"
@@ -16,7 +16,7 @@ done
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
if [ $? -ne 0 ]; then
# XXX replace this with fail once sandbox has stabilised
@@ -27,7 +27,7 @@ done
# Because sandbox is sensitive to changes in libc, especially malloc, retest
# with every malloc.conf option (and none).
for m in '' A F G H J P R S X '<' '>'; do
- for p in 1 2; do
+ for p in ${SSH_PROTOCOLS}; do
env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
if [ $? -ne 0 ]; then
fail "ssh privsep/sandbox+proxyconnect protocol $p mopt '$m' failed"
diff --git a/crypto/openssh/regress/connect.sh b/crypto/openssh/regress/connect.sh
index 2186fa6..f0d55d3 100644
--- a/crypto/openssh/regress/connect.sh
+++ b/crypto/openssh/regress/connect.sh
@@ -1,11 +1,11 @@
-# $OpenBSD: connect.sh,v 1.4 2002/03/15 13:08:56 markus Exp $
+# $OpenBSD: connect.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="simple connect"
start_sshd
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
if [ $? -ne 0 ]; then
fail "ssh connect with protocol $p failed"
diff --git a/crypto/openssh/regress/dynamic-forward.sh b/crypto/openssh/regress/dynamic-forward.sh
index 42fa8ac..dd67c96 100644
--- a/crypto/openssh/regress/dynamic-forward.sh
+++ b/crypto/openssh/regress/dynamic-forward.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: dynamic-forward.sh,v 1.10 2013/05/17 04:29:14 dtucker Exp $
+# $OpenBSD: dynamic-forward.sh,v 1.11 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="dynamic forwarding"
@@ -17,7 +17,7 @@ trace "will use ProxyCommand $proxycmd"
start_sshd
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
n=0
error="1"
trace "start dynamic forwarding, fork to background"
diff --git a/crypto/openssh/regress/exit-status.sh b/crypto/openssh/regress/exit-status.sh
index 56b78a6..397d8d7 100644
--- a/crypto/openssh/regress/exit-status.sh
+++ b/crypto/openssh/regress/exit-status.sh
@@ -1,9 +1,9 @@
-# $OpenBSD: exit-status.sh,v 1.6 2002/03/15 13:08:56 markus Exp $
+# $OpenBSD: exit-status.sh,v 1.7 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="remote exit status"
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
for s in 0 1 4 5 44; do
trace "proto $p status $s"
verbose "test $tid: proto $p status $s"
diff --git a/crypto/openssh/regress/forcecommand.sh b/crypto/openssh/regress/forcecommand.sh
index 44d2b7f..8a9b090 100644
--- a/crypto/openssh/regress/forcecommand.sh
+++ b/crypto/openssh/regress/forcecommand.sh
@@ -1,30 +1,32 @@
-# $OpenBSD: forcecommand.sh,v 1.2 2013/05/17 00:37:40 dtucker Exp $
+# $OpenBSD: forcecommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="forced command"
cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
-printf 'command="true" ' >$OBJ/authorized_keys_$USER
-cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER
-printf 'command="true" ' >>$OBJ/authorized_keys_$USER
-cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'command="true" ' >>$OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "forced command in key option proto $p"
${SSH} -$p -F $OBJ/ssh_proxy somehost false \ ||
fail "forced command in key proto $p"
done
-printf 'command="false" ' >$OBJ/authorized_keys_$USER
-cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER
-printf 'command="false" ' >>$OBJ/authorized_keys_$USER
-cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER
+cp /dev/null $OBJ/authorized_keys_$USER
+for t in ${SSH_KEYTYPES}; do
+ printf 'command="false" ' >> $OBJ/authorized_keys_$USER
+ cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
+done
cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
echo "ForceCommand true" >> $OBJ/sshd_proxy
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "forced command in sshd_config overrides key option proto $p"
${SSH} -$p -F $OBJ/ssh_proxy somehost false \ ||
fail "forced command in key proto $p"
@@ -35,7 +37,7 @@ echo "ForceCommand false" >> $OBJ/sshd_proxy
echo "Match User $USER" >> $OBJ/sshd_proxy
echo " ForceCommand true" >> $OBJ/sshd_proxy
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "forced command with match proto $p"
${SSH} -$p -F $OBJ/ssh_proxy somehost false \ ||
fail "forced command in key proto $p"
diff --git a/crypto/openssh/regress/forward-control.sh b/crypto/openssh/regress/forward-control.sh
index 7f7d105..9195709 100755
--- a/crypto/openssh/regress/forward-control.sh
+++ b/crypto/openssh/regress/forward-control.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: forward-control.sh,v 1.2 2013/11/18 05:09:32 naddy Exp $
+# $OpenBSD: forward-control.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="sshd control of local and remote forwarding"
@@ -99,7 +99,7 @@ cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak
cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak
# Sanity check: ensure the default config allows forwarding
-for p in 1 2 ; do
+for p in ${SSH_PROTOCOLS} ; do
check_lfwd $p Y "proto $p, default configuration"
check_rfwd $p Y "proto $p, default configuration"
done
@@ -115,7 +115,7 @@ all_tests() {
_permit_rfwd=$7
_badfwd=127.0.0.1:22
_goodfwd=127.0.0.1:${PORT}
- for _proto in 1 2 ; do
+ for _proto in ${SSH_PROTOCOLS} ; do
cp ${OBJ}/authorized_keys_${USER}.bak \
${OBJ}/authorized_keys_${USER}
_prefix="proto $_proto, AllowTcpForwarding=$_tcpfwd"
diff --git a/crypto/openssh/regress/forwarding.sh b/crypto/openssh/regress/forwarding.sh
index f799d49..fb4f35a 100644
--- a/crypto/openssh/regress/forwarding.sh
+++ b/crypto/openssh/regress/forwarding.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: forwarding.sh,v 1.12 2014/07/15 15:54:15 millert Exp $
+# $OpenBSD: forwarding.sh,v 1.15 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="local and remote forwarding"
@@ -10,6 +10,9 @@ start_sshd
base=33
last=$PORT
fwd=""
+CTL=$OBJ/ctl-sock
+rm -f $CTL
+
for j in 0 1 2; do
for i in 0 1 2; do
a=$base$j$i
@@ -20,8 +23,11 @@ for j in 0 1 2; do
last=$a
done
done
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
q=`expr 3 - $p`
+ if ! ssh_version $q; then
+ q=$p
+ fi
trace "start forwarding, fork to background"
${SSH} -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10
@@ -34,7 +40,7 @@ for p in 1 2; do
sleep 10
done
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
for d in L R; do
trace "exit on -$d forward failure, proto $p"
@@ -64,7 +70,7 @@ for d in L R; do
done
done
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "simple clear forwarding proto $p"
${SSH} -$p -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true
@@ -107,9 +113,9 @@ done
echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config
echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
trace "config file: start forwarding, fork to background"
- ${SSH} -$p -F $OBJ/ssh_config -f somehost sleep 10
+ ${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f somehost sleep 10
trace "config file: transfer over forwarded channels and check result"
${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \
@@ -117,7 +123,7 @@ for p in 1 2; do
test -s ${COPY} || fail "failed copy of ${DATA}"
cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
- wait
+ ${SSH} -S $CTL -O exit somehost
done
for p in 2; do
diff --git a/crypto/openssh/regress/host-expand.sh b/crypto/openssh/regress/host-expand.sh
index 6cc0e60..2a95bfe 100755
--- a/crypto/openssh/regress/host-expand.sh
+++ b/crypto/openssh/regress/host-expand.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: host-expand.sh,v 1.3 2014/02/27 23:17:41 djm Exp $
+# $OpenBSD: host-expand.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="expand %h and %n"
@@ -11,7 +11,7 @@ somehost
127.0.0.1
EOE
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "test $tid: proto $p"
${SSH} -F $OBJ/ssh_proxy -$p somehost true >$OBJ/actual
diff $OBJ/expect $OBJ/actual || fail "$tid proto $p"
diff --git a/crypto/openssh/regress/hostkey-agent.sh b/crypto/openssh/regress/hostkey-agent.sh
new file mode 100755
index 0000000..a011ec8
--- /dev/null
+++ b/crypto/openssh/regress/hostkey-agent.sh
@@ -0,0 +1,52 @@
+# $OpenBSD: hostkey-agent.sh,v 1.5 2015/02/21 20:51:02 djm Exp $
+# Placed in the Public Domain.
+
+tid="hostkey agent"
+
+rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/known_hosts.orig
+
+trace "start agent"
+eval `${SSHAGENT} -s` > /dev/null
+r=$?
+[ $r -ne 0 ] && fatal "could not start ssh-agent: exit code $r"
+
+grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
+echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
+
+trace "load hostkeys"
+for k in `${SSH} -Q key-plain` ; do
+ ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
+ (
+ printf 'localhost-with-alias,127.0.0.1,::1 '
+ cat $OBJ/agent-key.$k.pub
+ ) >> $OBJ/known_hosts.orig
+ ${SSHADD} $OBJ/agent-key.$k >/dev/null 2>&1 || \
+ fatal "couldn't load key $OBJ/agent-key.$k"
+ echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy.orig
+ # Remove private key so the server can't use it.
+ rm $OBJ/agent-key.$k || fatal "couldn't rm $OBJ/agent-key.$k"
+done
+cp $OBJ/known_hosts.orig $OBJ/known_hosts
+
+unset SSH_AUTH_SOCK
+
+for ps in no yes; do
+ cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+ echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
+ for k in `${SSH} -Q key-plain` ; do
+ verbose "key type $k privsep=$ps"
+ opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
+ cp $OBJ/known_hosts.orig $OBJ/known_hosts
+ SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
+ if [ $? -ne 0 ]; then
+ fail "protocol $p privsep=$ps failed"
+ fi
+ if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
+ fail "bad SSH_CONNECTION key type $k privsep=$ps"
+ fi
+ done
+done
+
+trace "kill agent"
+${SSHAGENT} -k > /dev/null
+
diff --git a/crypto/openssh/regress/hostkey-rotate.sh b/crypto/openssh/regress/hostkey-rotate.sh
new file mode 100755
index 0000000..b5d542d
--- /dev/null
+++ b/crypto/openssh/regress/hostkey-rotate.sh
@@ -0,0 +1,128 @@
+# $OpenBSD: hostkey-rotate.sh,v 1.2 2015/03/03 17:53:40 djm Exp $
+# Placed in the Public Domain.
+
+tid="hostkey rotate"
+
+# Need full names here since they are used in HostKeyAlgorithms
+HOSTKEY_TYPES="ecdsa-sha2-nistp256 ssh-ed25519 ssh-rsa ssh-dss"
+
+rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig
+
+grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
+echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy
+rm $OBJ/known_hosts
+
+trace "prepare hostkeys"
+nkeys=0
+all_algs=""
+for k in `ssh -Q key-plain` ; do
+ ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k"
+ echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig
+ nkeys=`expr $nkeys + 1`
+ test "x$all_algs" = "x" || all_algs="${all_algs},"
+ all_algs="${all_algs}$k"
+done
+
+dossh() {
+ # All ssh should succeed in this test
+ ${SSH} -F $OBJ/ssh_proxy "$@" x true || fail "ssh $@ failed"
+}
+
+expect_nkeys() {
+ _expected=$1
+ _message=$2
+ _n=`wc -l $OBJ/known_hosts | awk '{ print $1 }'` || fatal "wc failed"
+ [ "x$_n" = "x$_expected" ] || fail "$_message (got $_n wanted $_expected)"
+}
+
+check_key_present() {
+ _type=$1
+ _kfile=$2
+ test "x$_kfile" = "x" && _kfile="$OBJ/hkr.${_type}.pub"
+ _kpub=`awk "/$_type /"' { print $2 }' < $_kfile` || \
+ fatal "awk failed"
+ fgrep "$_kpub" $OBJ/known_hosts > /dev/null
+}
+
+cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+
+# Connect to sshd with StrictHostkeyChecking=no
+verbose "learn hostkey with StrictHostKeyChecking=no"
+>$OBJ/known_hosts
+dossh -oHostKeyAlgorithms=ssh-ed25519 -oStrictHostKeyChecking=no
+# Verify no additional keys learned
+expect_nkeys 1 "unstrict connect keys"
+check_key_present ssh-ed25519 || fail "unstrict didn't learn key"
+
+# Connect to sshd as usual
+verbose "learn additional hostkeys"
+dossh -oStrictHostKeyChecking=yes
+# Check that other keys learned
+expect_nkeys $nkeys "learn hostkeys"
+check_key_present ssh-rsa || fail "didn't learn keys"
+
+# Check each key type
+for k in `ssh -Q key-plain` ; do
+ verbose "learn additional hostkeys, type=$k"
+ dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs
+ expect_nkeys $nkeys "learn hostkeys $k"
+ check_key_present $k || fail "didn't learn $k"
+done
+
+# Change one hostkey (non primary) and relearn
+verbose "learn changed non-primary hostkey"
+mv $OBJ/hkr.ssh-rsa.pub $OBJ/hkr.ssh-rsa.pub.old
+rm -f $OBJ/hkr.ssh-rsa
+${SSHKEYGEN} -qt ssh-rsa -f $OBJ/hkr.ssh-rsa -N '' || fatal "ssh-keygen $k"
+dossh -oStrictHostKeyChecking=yes
+# Check that the key was replaced
+expect_nkeys $nkeys "learn hostkeys"
+check_key_present ssh-rsa $OBJ/hkr.ssh-rsa.pub.old && fail "old key present"
+check_key_present ssh-rsa || fail "didn't learn changed key"
+
+# Add new hostkey (primary type) to sshd and connect
+verbose "learn new primary hostkey"
+${SSHKEYGEN} -qt ssh-rsa -f $OBJ/hkr.ssh-rsa-new -N '' || fatal "ssh-keygen $k"
+( cat $OBJ/sshd_proxy.orig ; echo HostKey $OBJ/hkr.ssh-rsa-new ) \
+ > $OBJ/sshd_proxy
+# Check new hostkey added
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa,$all_algs
+expect_nkeys `expr $nkeys + 1` "learn hostkeys"
+check_key_present ssh-rsa || fail "current key missing"
+check_key_present ssh-rsa $OBJ/hkr.ssh-rsa-new.pub || fail "new key missing"
+
+# Remove old hostkey (primary type) from sshd
+verbose "rotate primary hostkey"
+cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+mv $OBJ/hkr.ssh-rsa.pub $OBJ/hkr.ssh-rsa.pub.old
+mv $OBJ/hkr.ssh-rsa-new.pub $OBJ/hkr.ssh-rsa.pub
+mv $OBJ/hkr.ssh-rsa-new $OBJ/hkr.ssh-rsa
+# Check old hostkey removed
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa,$all_algs
+expect_nkeys $nkeys "learn hostkeys"
+check_key_present ssh-rsa $OBJ/hkr.ssh-rsa.pub.old && fail "old key present"
+check_key_present ssh-rsa || fail "didn't learn changed key"
+
+# Connect again, forcing rotated key
+verbose "check rotate primary hostkey"
+dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa
+expect_nkeys 1 "learn hostkeys"
+check_key_present ssh-rsa || fail "didn't learn changed key"
+
+# $OpenBSD: hostkey-rotate.sh,v 1.2 2015/03/03 17:53:40 djm Exp $
+# Placed in the Public Domain.
+
+tid="hostkey rotate"
+
+# Prepare hostkeys file with one key
+
+# Connect to sshd
+
+# Check that other keys learned
+
+# Change one hostkey (non primary)
+
+# Connect to sshd
+
+# Check that the key was replaced
+
diff --git a/crypto/openssh/regress/integrity.sh b/crypto/openssh/regress/integrity.sh
index d3a489f..2ff8b3f 100755
--- a/crypto/openssh/regress/integrity.sh
+++ b/crypto/openssh/regress/integrity.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: integrity.sh,v 1.14 2014/05/21 07:04:21 djm Exp $
+# $OpenBSD: integrity.sh,v 1.15 2015/01/19 20:42:31 markus Exp $
# Placed in the Public Domain.
tid="integrity"
@@ -20,7 +20,7 @@ echo "KexAlgorithms diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" \
>> $OBJ/ssh_proxy
# sshd-command for proxy (see test-exec.sh)
-cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy"
+cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy"
for m in $macs; do
trace "test $tid: mac $m"
@@ -58,7 +58,7 @@ for m in $macs; do
tr -s '\r\n' '.')
case "$out" in
Bad?packet*) elen=`expr $elen + 1`; skip=3;;
- Corrupted?MAC* | Decryption?integrity?check?failed*)
+ Corrupted?MAC* | *message?authentication?code?incorrect*)
emac=`expr $emac + 1`; skip=0;;
padding*) epad=`expr $epad + 1`; skip=0;;
*) fail "unexpected error mac $m at $off: $out";;
diff --git a/crypto/openssh/regress/key-options.sh b/crypto/openssh/regress/key-options.sh
index f98d78b..7a68ad3 100755
--- a/crypto/openssh/regress/key-options.sh
+++ b/crypto/openssh/regress/key-options.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: key-options.sh,v 1.2 2008/06/30 08:07:34 djm Exp $
+# $OpenBSD: key-options.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="key options"
@@ -8,7 +8,7 @@ authkeys="$OBJ/authorized_keys_${USER}"
cp $authkeys $origkeys
# Test command= forced command
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do
sed "s/.*/$c &/" $origkeys >$authkeys
verbose "key option proto $p $c"
@@ -24,7 +24,7 @@ done
# Test no-pty
sed 's/.*/no-pty &/' $origkeys >$authkeys
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "key option proto $p no-pty"
r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost tty`
if [ -f "$r" ]; then
@@ -35,7 +35,7 @@ done
# Test environment=
echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy
sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "key option proto $p environment"
r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo $FOO'`
if [ "$r" != "bar" ]; then
@@ -45,7 +45,7 @@ done
# Test from= restriction
start_sshd
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
for f in 127.0.0.1 '127.0.0.0\/8'; do
cat $origkeys >$authkeys
${SSH} -$p -q -F $OBJ/ssh_proxy somehost true
diff --git a/crypto/openssh/regress/keygen-change.sh b/crypto/openssh/regress/keygen-change.sh
index 08d3590..e561850 100644
--- a/crypto/openssh/regress/keygen-change.sh
+++ b/crypto/openssh/regress/keygen-change.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: keygen-change.sh,v 1.2 2002/07/16 09:15:55 markus Exp $
+# $OpenBSD: keygen-change.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="change passphrase for key"
@@ -6,7 +6,12 @@ tid="change passphrase for key"
S1="secret1"
S2="2secret"
-for t in rsa dsa rsa1; do
+KEYTYPES=`${SSH} -Q key-plain`
+if ssh_version 1; then
+ KEYTYPES="${KEYTYPES} rsa1"
+fi
+
+for t in $KEYTYPES; do
# generate user key for agent
trace "generating $t key"
rm -f $OBJ/$t-key
diff --git a/crypto/openssh/regress/keygen-knownhosts.sh b/crypto/openssh/regress/keygen-knownhosts.sh
new file mode 100755
index 0000000..085aac6
--- /dev/null
+++ b/crypto/openssh/regress/keygen-knownhosts.sh
@@ -0,0 +1,197 @@
+# $OpenBSD: keygen-knownhosts.sh,v 1.2 2015/01/27 12:01:36 djm Exp $
+# Placed in the Public Domain.
+
+tid="ssh-keygen known_hosts"
+
+rm -f $OBJ/kh.*
+
+# Generate some keys for testing (just ed25519 for speed) and make a hosts file.
+for x in host-a host-b host-c host-d host-e host-f host-a2 host-b2; do
+ ${SSHKEYGEN} -qt ed25519 -f $OBJ/kh.$x -C "$x" -N "" || \
+ fatal "ssh-keygen failed"
+ # Add a comment that we expect should be preserved.
+ echo "# $x" >> $OBJ/kh.hosts
+ (
+ case "$x" in
+ host-a|host-b) printf "$x " ;;
+ host-c) printf "@cert-authority $x " ;;
+ host-d) printf "@revoked $x " ;;
+ host-e) printf "host-e* " ;;
+ host-f) printf "host-f,host-g,host-h " ;;
+ host-a2) printf "host-a " ;;
+ host-b2) printf "host-b " ;;
+ esac
+ cat $OBJ/kh.${x}.pub
+ # Blank line should be preserved.
+ echo "" >> $OBJ/kh.hosts
+ ) >> $OBJ/kh.hosts
+done
+
+# Generate a variant with an invalid line. We'll use this for most tests,
+# because keygen should be able to cope and it should be preserved in any
+# output file.
+cat $OBJ/kh.hosts >> $OBJ/kh.invalid
+echo "host-i " >> $OBJ/kh.invalid
+
+cp $OBJ/kh.invalid $OBJ/kh.invalid.orig
+cp $OBJ/kh.hosts $OBJ/kh.hosts.orig
+
+expect_key() {
+ _host=$1
+ _hosts=$2
+ _key=$3
+ _line=$4
+ _mark=$5
+ _marker=""
+ test "x$_mark" = "xCA" && _marker="@cert-authority "
+ test "x$_mark" = "xREVOKED" && _marker="@revoked "
+ test "x$_line" != "x" &&
+ echo "# Host $_host found: line $_line $_mark" >> $OBJ/kh.expect
+ printf "${_marker}$_hosts " >> $OBJ/kh.expect
+ cat $OBJ/kh.${_key}.pub >> $OBJ/kh.expect ||
+ fatal "${_key}.pub missing"
+}
+
+check_find() {
+ _host=$1
+ _name=$2
+ _keygenopt=$3
+ ${SSHKEYGEN} $_keygenopt -f $OBJ/kh.invalid -F $_host > $OBJ/kh.result
+ if ! diff -uw $OBJ/kh.expect $OBJ/kh.result ; then
+ fail "didn't find $_name"
+ fi
+}
+
+# Find key
+rm -f $OBJ/kh.expect
+expect_key host-a host-a host-a 2
+expect_key host-a host-a host-a2 20
+check_find host-a "simple find"
+
+# find CA key
+rm -f $OBJ/kh.expect
+expect_key host-c host-c host-c 8 CA
+check_find host-c "find CA key"
+
+# find revoked key
+rm -f $OBJ/kh.expect
+expect_key host-d host-d host-d 11 REVOKED
+check_find host-d "find revoked key"
+
+# find key with wildcard
+rm -f $OBJ/kh.expect
+expect_key host-e.somedomain "host-e*" host-e 14
+check_find host-e.somedomain "find wildcard key"
+
+# find key among multiple hosts
+rm -f $OBJ/kh.expect
+expect_key host-h "host-f,host-g,host-h " host-f 17
+check_find host-h "find multiple hosts"
+
+check_hashed_find() {
+ _host=$1
+ _name=$2
+ _file=$3
+ test "x$_file" = "x" && _file=$OBJ/kh.invalid
+ ${SSHKEYGEN} -f $_file -HF $_host | grep '|1|' | \
+ sed "s/^[^ ]*/$_host/" > $OBJ/kh.result
+ if ! diff -uw $OBJ/kh.expect $OBJ/kh.result ; then
+ fail "didn't find $_name"
+ fi
+}
+
+# Find key and hash
+rm -f $OBJ/kh.expect
+expect_key host-a host-a host-a
+expect_key host-a host-a host-a2
+check_hashed_find host-a "find simple and hash"
+
+# Find CA key and hash
+rm -f $OBJ/kh.expect
+expect_key host-c host-c host-c "" CA
+# CA key output is not hashed.
+check_find host-c "find simple and hash" -H
+
+# Find revoked key and hash
+rm -f $OBJ/kh.expect
+expect_key host-d host-d host-d "" REVOKED
+# Revoked key output is not hashed.
+check_find host-d "find simple and hash" -H
+
+# find key with wildcard and hash
+rm -f $OBJ/kh.expect
+expect_key host-e "host-e*" host-e ""
+# Key with wildcard hostname should not be hashed.
+check_find host-e "find wildcard key" -H
+
+# find key among multiple hosts
+rm -f $OBJ/kh.expect
+# Comma-separated hostnames should be expanded and hashed.
+expect_key host-f "host-h " host-f
+expect_key host-g "host-h " host-f
+expect_key host-h "host-h " host-f
+check_hashed_find host-h "find multiple hosts"
+
+# Attempt remove key on invalid file.
+cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
+${SSHKEYGEN} -qf $OBJ/kh.invalid -R host-a 2>/dev/null
+diff -u $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded"
+
+# Remove key
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-a 2>/dev/null
+grep -v "^host-a " $OBJ/kh.hosts.orig > $OBJ/kh.expect
+diff -u $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple"
+
+# Remove CA key
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-c 2>/dev/null
+# CA key should not be removed.
+diff -u $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA"
+
+# Remove revoked key
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-d 2>/dev/null
+# revoked key should not be removed.
+diff -u $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked"
+
+# Remove wildcard
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-e.blahblah 2>/dev/null
+grep -v "^host-e[*] " $OBJ/kh.hosts.orig > $OBJ/kh.expect
+diff -u $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
+
+# Remove multiple
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-h 2>/dev/null
+grep -v "^host-f," $OBJ/kh.hosts.orig > $OBJ/kh.expect
+diff -u $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
+
+# Attempt hash on invalid file
+cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
+${SSHKEYGEN} -qf $OBJ/kh.invalid -H 2>/dev/null && fail "hash invalid succeeded"
+diff -u $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified"
+
+# Hash valid file
+cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
+${SSHKEYGEN} -qf $OBJ/kh.hosts -H 2>/dev/null || fail "hash failed"
+diff -u $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs"
+grep "^host-[abfgh]" $OBJ/kh.hosts && fail "original hostnames persist"
+
+cp $OBJ/kh.hosts $OBJ/kh.hashed.orig
+
+# Test lookup
+rm -f $OBJ/kh.expect
+expect_key host-a host-a host-a
+expect_key host-a host-a host-a2
+check_hashed_find host-a "find simple in hashed" $OBJ/kh.hosts
+
+# Test multiple expanded
+rm -f $OBJ/kh.expect
+expect_key host-h host-h host-f
+check_hashed_find host-h "find simple in hashed" $OBJ/kh.hosts
+
+# Test remove
+cp $OBJ/kh.hashed.orig $OBJ/kh.hashed
+${SSHKEYGEN} -qf $OBJ/kh.hashed -R host-a 2>/dev/null
+${SSHKEYGEN} -qf $OBJ/kh.hashed -F host-a && fail "found key after hashed remove"
diff --git a/crypto/openssh/regress/keyscan.sh b/crypto/openssh/regress/keyscan.sh
index 33f14f0..886f329 100644
--- a/crypto/openssh/regress/keyscan.sh
+++ b/crypto/openssh/regress/keyscan.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: keyscan.sh,v 1.3 2002/03/15 13:08:56 markus Exp $
+# $OpenBSD: keyscan.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="keyscan"
@@ -8,7 +8,12 @@ rm -f ${OBJ}/host.dsa
start_sshd
-for t in rsa1 rsa dsa; do
+KEYTYPES="rsa dsa"
+if ssh_version 1; then
+ KEYTYPES="${KEYTYPES} rsa1"
+fi
+
+for t in $KEYTYPES; do
trace "keyscan type $t"
${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \
> /dev/null 2>&1
diff --git a/crypto/openssh/regress/krl.sh b/crypto/openssh/regress/krl.sh
index 287384b..1077358 100755
--- a/crypto/openssh/regress/krl.sh
+++ b/crypto/openssh/regress/krl.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: krl.sh,v 1.3 2014/06/24 01:04:43 djm Exp $
+# $OpenBSD: krl.sh,v 1.6 2015/01/30 01:11:39 djm Exp $
# Placed in the Public Domain.
tid="key revocation lists"
@@ -17,6 +17,8 @@ rm -f $OBJ/revoked-* $OBJ/krl-*
# Generate a CA key
$SSHKEYGEN -t $ECDSA -f $OBJ/revoked-ca -C "" -N "" > /dev/null ||
fatal "$SSHKEYGEN CA failed"
+$SSHKEYGEN -t ed25519 -f $OBJ/revoked-ca2 -C "" -N "" > /dev/null ||
+ fatal "$SSHKEYGEN CA2 failed"
# A specification that revokes some certificates by serial numbers
# The serial pattern is chosen to ensure the KRL includes list, range and
@@ -45,6 +47,7 @@ EOF
# A specification that revokes some certificated by key ID.
touch $OBJ/revoked-keyid
for n in 1 2 3 4 10 15 30 50 `jot 500 300` 999 1000 1001 1002; do
+ test "x$n" = "x499" && continue
# Fill in by-ID revocation spec.
echo "id: revoked $n" >> $OBJ/revoked-keyid
done
@@ -56,7 +59,7 @@ keygen() {
keytype=$ECDSA
case $N in
2 | 10 | 510 | 1001) keytype=rsa;;
- 4 | 30 | 520 | 1002) keytype=dsa;;
+ 4 | 30 | 520 | 1002) keytype=ed25519;;
esac
$SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \
|| fatal "$SSHKEYGEN failed"
@@ -71,37 +74,48 @@ verbose "$tid: generating test keys"
REVOKED_SERIALS="1 4 10 50 500 510 520 799 999"
for n in $REVOKED_SERIALS ; do
f=`keygen $n`
- REVOKED_KEYS="$REVOKED_KEYS ${f}.pub"
- REVOKED_CERTS="$REVOKED_CERTS ${f}-cert.pub"
+ RKEYS="$RKEYS ${f}.pub"
+ RCERTS="$RCERTS ${f}-cert.pub"
done
-NOTREVOKED_SERIALS="5 9 14 16 29 30 49 51 499 800 1000 1001"
-NOTREVOKED=""
-for n in $NOTREVOKED_SERIALS ; do
- NOTREVOKED_KEYS="$NOTREVOKED_KEYS ${f}.pub"
- NOTREVOKED_CERTS="$NOTREVOKED_CERTS ${f}-cert.pub"
+UNREVOKED_SERIALS="5 9 14 16 29 49 51 499 800 1010 1011"
+UNREVOKED=""
+for n in $UNREVOKED_SERIALS ; do
+ f=`keygen $n`
+ UKEYS="$UKEYS ${f}.pub"
+ UCERTS="$UCERTS ${f}-cert.pub"
done
genkrls() {
OPTS=$1
$SSHKEYGEN $OPTS -kf $OBJ/krl-empty - </dev/null \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
-$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $REVOKED_KEYS \
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $RKEYS \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
-$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $REVOKED_CERTS \
+$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $RCERTS \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
-$SSHKEYGEN $OPTS -kf $OBJ/krl-all $REVOKED_KEYS $REVOKED_CERTS \
+$SSHKEYGEN $OPTS -kf $OBJ/krl-all $RKEYS $RCERTS \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
$SSHKEYGEN $OPTS -kf $OBJ/krl-ca $OBJ/revoked-ca.pub \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
-# KRLs from serial/key-id spec need the CA specified.
+# This should fail as KRLs from serial/key-id spec need the CA specified.
$SSHKEYGEN $OPTS -kf $OBJ/krl-serial $OBJ/revoked-serials \
>/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly"
$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid $OBJ/revoked-keyid \
>/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly"
-$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca $OBJ/revoked-serials \
+# These should succeed; they specify an explicit CA key.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca \
+ $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed"
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub \
+ $OBJ/revoked-keyid >/dev/null || fatal "$SSHKEYGEN KRL failed"
+# These should succeed; they specify an wildcard CA key.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial-wild -s NONE $OBJ/revoked-serials \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
-$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub $OBJ/revoked-keyid \
+$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid-wild -s NONE $OBJ/revoked-keyid \
>/dev/null || fatal "$SSHKEYGEN KRL failed"
+# Revoke the same serials with the second CA key to ensure a multi-CA
+# KRL is generated.
+$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -u -s $OBJ/revoked-ca2 \
+ $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed"
}
## XXX dump with trace and grep for set cert serials
@@ -123,7 +137,7 @@ check_krl() {
fatal "key $KEY unexpectedly revoked by KRL $KRL: $TAG"
fi
}
-test_all() {
+test_rev() {
FILES=$1
TAG=$2
KEYS_RESULT=$3
@@ -132,32 +146,40 @@ test_all() {
KEYID_RESULT=$6
CERTS_RESULT=$7
CA_RESULT=$8
+ SERIAL_WRESULT=$9
+ KEYID_WRESULT=$10
verbose "$tid: checking revocations for $TAG"
for f in $FILES ; do
- check_krl $f $OBJ/krl-empty no "$TAG"
- check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG"
- check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG"
- check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG"
- check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG"
- check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG"
- check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG"
+ check_krl $f $OBJ/krl-empty no "$TAG"
+ check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG"
+ check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG"
+ check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG"
+ check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG"
+ check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG"
+ check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG"
+ check_krl $f $OBJ/krl-serial-wild $SERIAL_WRESULT "$TAG"
+ check_krl $f $OBJ/krl-keyid-wild $KEYID_WRESULT "$TAG"
done
}
-# keys all serial keyid certs CA
-test_all "$REVOKED_KEYS" "revoked keys" yes yes no no no no
-test_all "$UNREVOKED_KEYS" "unrevoked keys" no no no no no no
-test_all "$REVOKED_CERTS" "revoked certs" yes yes yes yes yes yes
-test_all "$UNREVOKED_CERTS" "unrevoked certs" no no no no no yes
+
+test_all() {
+ # wildcard
+ # keys all sr# k.ID cert CA sr.# k.ID
+ test_rev "$RKEYS" "revoked keys" yes yes no no no no no no
+ test_rev "$UKEYS" "unrevoked keys" no no no no no no no no
+ test_rev "$RCERTS" "revoked certs" yes yes yes yes yes yes yes yes
+ test_rev "$UCERTS" "unrevoked certs" no no no no no yes no no
+}
+
+test_all
# Check update. Results should be identical.
verbose "$tid: testing KRL update"
for f in $OBJ/krl-keys $OBJ/krl-cert $OBJ/krl-all \
- $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid ; do
+ $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid \
+ $OBJ/krl-serial-wild $OBJ/krl-keyid-wild; do
cp -f $OBJ/krl-empty $f
genkrls -u
done
-# keys all serial keyid certs CA
-test_all "$REVOKED_KEYS" "revoked keys" yes yes no no no no
-test_all "$UNREVOKED_KEYS" "unrevoked keys" no no no no no no
-test_all "$REVOKED_CERTS" "revoked certs" yes yes yes yes yes yes
-test_all "$UNREVOKED_CERTS" "unrevoked certs" no no no no no yes
+
+test_all
diff --git a/crypto/openssh/regress/limit-keytype.sh b/crypto/openssh/regress/limit-keytype.sh
new file mode 100755
index 0000000..2de037b
--- /dev/null
+++ b/crypto/openssh/regress/limit-keytype.sh
@@ -0,0 +1,80 @@
+# $OpenBSD: limit-keytype.sh,v 1.1 2015/01/13 07:49:49 djm Exp $
+# Placed in the Public Domain.
+
+tid="restrict pubkey type"
+
+rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
+rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
+
+mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+
+# Create a CA key
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\
+ fatal "ssh-keygen failed"
+
+# Make some keys and a certificate.
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_key2 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_key3 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
+ -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key3 ||
+ fatal "couldn't sign user_key1"
+# Copy the private key alongside the cert to allow better control of when
+# it is offered.
+mv $OBJ/user_key3-cert.pub $OBJ/cert_user_key3.pub
+cp -p $OBJ/user_key3 $OBJ/cert_user_key3
+
+grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
+
+opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
+fullopts="$opts -i $OBJ/cert_user_key3 -i $OBJ/user_key1 -i $OBJ/user_key2"
+
+echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
+cat $OBJ/user_key2.pub >> $OBJ/authorized_keys_$USER
+
+prepare_config() {
+ (
+ grep -v "Protocol" $OBJ/sshd_proxy.orig
+ echo "Protocol 2"
+ echo "AuthenticationMethods publickey"
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+ for x in "$@" ; do
+ echo "$x"
+ done
+ ) > $OBJ/sshd_proxy
+}
+
+prepare_config
+
+# Check we can log in with all key types.
+${SSH} $opts -i $OBJ/cert_user_key3 proxy true || fatal "cert failed"
+${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
+${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
+
+# Allow plain Ed25519 and RSA. The certificate should fail.
+verbose "privsep=$privsep allow rsa,ed25519"
+prepare_config "PubkeyAcceptedKeyTypes ssh-rsa,ssh-ed25519"
+${SSH} $opts -i $OBJ/cert_user_key3 proxy true && fatal "cert succeeded"
+${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
+${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
+
+# Allow Ed25519 only.
+verbose "privsep=$privsep allow ed25519"
+prepare_config "PubkeyAcceptedKeyTypes ssh-ed25519"
+${SSH} $opts -i $OBJ/cert_user_key3 proxy true && fatal "cert succeeded"
+${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
+${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded"
+
+# Allow all certs. Plain keys should fail.
+verbose "privsep=$privsep allow cert only"
+prepare_config "PubkeyAcceptedKeyTypes ssh-*-cert-v01@openssh.com"
+${SSH} $opts -i $OBJ/cert_user_key3 proxy true || fatal "cert failed"
+${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded"
+${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded"
+
diff --git a/crypto/openssh/regress/localcommand.sh b/crypto/openssh/regress/localcommand.sh
index 8a9b569..220f19a 100755
--- a/crypto/openssh/regress/localcommand.sh
+++ b/crypto/openssh/regress/localcommand.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: localcommand.sh,v 1.2 2013/05/17 10:24:48 dtucker Exp $
+# $OpenBSD: localcommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="localcommand"
@@ -6,7 +6,7 @@ tid="localcommand"
echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy
echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "test $tid: proto $p localcommand"
a=`${SSH} -F $OBJ/ssh_proxy -$p somehost true`
if [ "$a" != "foo" ] ; then
diff --git a/crypto/openssh/regress/multiplex.sh b/crypto/openssh/regress/multiplex.sh
index 8ee140b..acb9234 100644
--- a/crypto/openssh/regress/multiplex.sh
+++ b/crypto/openssh/regress/multiplex.sh
@@ -1,24 +1,11 @@
-# $OpenBSD: multiplex.sh,v 1.25 2014/07/22 01:32:12 djm Exp $
+# $OpenBSD: multiplex.sh,v 1.27 2014/12/22 06:14:29 djm Exp $
# Placed in the Public Domain.
CTL=/tmp/openssh.regress.ctl-sock.$$
tid="connection multiplexing"
-if have_prog nc ; then
- if nc -h 2>&1 | grep -- -N >/dev/null; then
- NC="nc -N";
- elif nc -h 2>&1 | grep -- "-U.*Use UNIX" >/dev/null ; then
- NC="nc"
- else
- echo "nc is incompatible"
- fi
-fi
-
-if test -z "$NC" ; then
- echo "skipped (no compatible nc found)"
- exit 0
-fi
+NC=$OBJ/netcat
trace "will use ProxyCommand $proxycmd"
if config_defined DISABLE_FD_PASSING ; then
@@ -90,20 +77,20 @@ cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
rm -f ${COPY}
verbose "test $tid: forward"
trace "forward over TCP/IP and check result"
-$NC -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} &
+$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
netcat_pid=$!
${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
-$NC -d 127.0.0.1 $((${PORT} + 2)) > ${COPY} < /dev/null
+$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
kill $netcat_pid 2>/dev/null
rm -f ${COPY} $OBJ/unix-[123].fwd
trace "forward over UNIX and check result"
-$NC -Ul $OBJ/unix-1.fwd < ${DATA} &
+$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
netcat_pid=$!
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
-$NC -d -U $OBJ/unix-3.fwd > ${COPY} </dev/null
+$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY} 2>/dev/null
cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
kill $netcat_pid 2>/dev/null
rm -f ${COPY} $OBJ/unix-[123].fwd
diff --git a/crypto/openssh/regress/multipubkey.sh b/crypto/openssh/regress/multipubkey.sh
new file mode 100755
index 0000000..e9d1530
--- /dev/null
+++ b/crypto/openssh/regress/multipubkey.sh
@@ -0,0 +1,66 @@
+# $OpenBSD: multipubkey.sh,v 1.1 2014/12/22 08:06:03 djm Exp $
+# Placed in the Public Domain.
+
+tid="multiple pubkey"
+
+rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
+rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
+
+mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
+mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+
+# Create a CA key
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\
+ fatal "ssh-keygen failed"
+
+# Make some keys and a certificate.
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
+ fatal "ssh-keygen failed"
+${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
+ -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key1 ||
+ fail "couldn't sign user_key1"
+# Copy the private key alongside the cert to allow better control of when
+# it is offered.
+mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1.pub
+cp -p $OBJ/user_key1 $OBJ/cert_user_key1
+
+grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
+
+opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
+opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2"
+
+for privsep in no yes; do
+ (
+ grep -v "Protocol" $OBJ/sshd_proxy.orig
+ echo "Protocol 2"
+ echo "UsePrivilegeSeparation $privsep"
+ echo "AuthenticationMethods publickey,publickey"
+ echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
+ echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+ ) > $OBJ/sshd_proxy
+
+ # Single key should fail.
+ rm -f $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true && fail "ssh succeeded with key"
+
+ # Single key with same-public cert should fail.
+ echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true && fail "ssh succeeded with key+cert"
+
+ # Multiple plain keys should succeed.
+ rm -f $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \
+ $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true || fail "ssh failed with multiple keys"
+ # Cert and different key should succeed
+
+ # Key and different-public cert should succeed.
+ echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER
+ ${SSH} $opts proxy true || fail "ssh failed with key/cert"
+done
+
diff --git a/crypto/openssh/regress/netcat.c b/crypto/openssh/regress/netcat.c
new file mode 100644
index 0000000..1a9fc87
--- /dev/null
+++ b/crypto/openssh/regress/netcat.c
@@ -0,0 +1,1690 @@
+/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */
+/*
+ * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. The name of the author may not be used to endorse or promote products
+ * derived from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+/*
+ * Re-written nc(1) for OpenBSD. Original implementation by
+ * *Hobbit* <hobbit@avian.org>.
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <sys/time.h>
+#include <sys/uio.h>
+#include <sys/un.h>
+
+#include <netinet/in.h>
+#include <netinet/tcp.h>
+#include <netinet/ip.h>
+#include <arpa/telnet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+#include <limits.h>
+#include "atomicio.h"
+
+#ifdef HAVE_POLL_H
+#include <poll.h>
+#else
+# ifdef HAVE_SYS_POLL_H
+# include <sys/poll.h>
+# endif
+#endif
+
+#ifndef SUN_LEN
+#define SUN_LEN(su) \
+ (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
+#endif
+
+#define PORT_MAX 65535
+#define PORT_MAX_LEN 6
+#define UNIX_DG_TMP_SOCKET_SIZE 19
+
+#define POLL_STDIN 0
+#define POLL_NETOUT 1
+#define POLL_NETIN 2
+#define POLL_STDOUT 3
+#define BUFSIZE 16384
+
+/* Command Line Options */
+int dflag; /* detached, no stdin */
+int Fflag; /* fdpass sock to stdout */
+unsigned int iflag; /* Interval Flag */
+int kflag; /* More than one connect */
+int lflag; /* Bind to local port */
+int Nflag; /* shutdown() network socket */
+int nflag; /* Don't do name look up */
+char *Pflag; /* Proxy username */
+char *pflag; /* Localport flag */
+int rflag; /* Random ports flag */
+char *sflag; /* Source Address */
+int tflag; /* Telnet Emulation */
+int uflag; /* UDP - Default to TCP */
+int vflag; /* Verbosity */
+int xflag; /* Socks proxy */
+int zflag; /* Port Scan Flag */
+int Dflag; /* sodebug */
+int Iflag; /* TCP receive buffer size */
+int Oflag; /* TCP send buffer size */
+int Sflag; /* TCP MD5 signature option */
+int Tflag = -1; /* IP Type of Service */
+int rtableid = -1;
+
+int timeout = -1;
+int family = AF_UNSPEC;
+char *portlist[PORT_MAX+1];
+char *unix_dg_tmp_socket;
+
+void atelnet(int, unsigned char *, unsigned int);
+void build_ports(char *);
+void help(void);
+int local_listen(char *, char *, struct addrinfo);
+void readwrite(int);
+void fdpass(int nfd) __attribute__((noreturn));
+int remote_connect(const char *, const char *, struct addrinfo);
+int timeout_connect(int, const struct sockaddr *, socklen_t);
+int socks_connect(const char *, const char *, struct addrinfo,
+ const char *, const char *, struct addrinfo, int, const char *);
+int udptest(int);
+int unix_bind(char *);
+int unix_connect(char *);
+int unix_listen(char *);
+void set_common_sockopts(int);
+int map_tos(char *, int *);
+void report_connect(const struct sockaddr *, socklen_t);
+void usage(int);
+ssize_t drainbuf(int, unsigned char *, size_t *);
+ssize_t fillbuf(int, unsigned char *, size_t *);
+
+static void err(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+static void errx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
+static void warn(const char *, ...) __attribute__((format(printf, 1, 2)));
+
+static void
+err(int r, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ fprintf(stderr, "%s: ", strerror(errno));
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+ exit(r);
+}
+
+static void
+errx(int r, const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+ exit(r);
+}
+
+static void
+warn(const char *fmt, ...)
+{
+ va_list args;
+
+ va_start(args, fmt);
+ fprintf(stderr, "%s: ", strerror(errno));
+ vfprintf(stderr, fmt, args);
+ fputc('\n', stderr);
+ va_end(args);
+}
+
+int
+main(int argc, char *argv[])
+{
+ int ch, s, ret, socksv;
+ char *host, *uport;
+ struct addrinfo hints;
+ struct servent *sv;
+ socklen_t len;
+ struct sockaddr_storage cliaddr;
+ char *proxy = NULL;
+ const char *errstr, *proxyhost = "", *proxyport = NULL;
+ struct addrinfo proxyhints;
+ char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
+
+ ret = 1;
+ s = 0;
+ socksv = 5;
+ host = NULL;
+ uport = NULL;
+ sv = NULL;
+
+ while ((ch = getopt(argc, argv,
+ "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
+ switch (ch) {
+ case '4':
+ family = AF_INET;
+ break;
+ case '6':
+ family = AF_INET6;
+ break;
+ case 'U':
+ family = AF_UNIX;
+ break;
+ case 'X':
+ if (strcasecmp(optarg, "connect") == 0)
+ socksv = -1; /* HTTP proxy CONNECT */
+ else if (strcmp(optarg, "4") == 0)
+ socksv = 4; /* SOCKS v.4 */
+ else if (strcmp(optarg, "5") == 0)
+ socksv = 5; /* SOCKS v.5 */
+ else
+ errx(1, "unsupported proxy protocol");
+ break;
+ case 'd':
+ dflag = 1;
+ break;
+ case 'F':
+ Fflag = 1;
+ break;
+ case 'h':
+ help();
+ break;
+ case 'i':
+ iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
+ if (errstr)
+ errx(1, "interval %s: %s", errstr, optarg);
+ break;
+ case 'k':
+ kflag = 1;
+ break;
+ case 'l':
+ lflag = 1;
+ break;
+ case 'N':
+ Nflag = 1;
+ break;
+ case 'n':
+ nflag = 1;
+ break;
+ case 'P':
+ Pflag = optarg;
+ break;
+ case 'p':
+ pflag = optarg;
+ break;
+ case 'r':
+ rflag = 1;
+ break;
+ case 's':
+ sflag = optarg;
+ break;
+ case 't':
+ tflag = 1;
+ break;
+ case 'u':
+ uflag = 1;
+ break;
+#ifdef SO_RTABLE
+ case 'V':
+ rtableid = (int)strtonum(optarg, 0,
+ RT_TABLEID_MAX, &errstr);
+ if (errstr)
+ errx(1, "rtable %s: %s", errstr, optarg);
+ break;
+#endif
+ case 'v':
+ vflag = 1;
+ break;
+ case 'w':
+ timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
+ if (errstr)
+ errx(1, "timeout %s: %s", errstr, optarg);
+ timeout *= 1000;
+ break;
+ case 'x':
+ xflag = 1;
+ if ((proxy = strdup(optarg)) == NULL)
+ errx(1, "strdup");
+ break;
+ case 'z':
+ zflag = 1;
+ break;
+ case 'D':
+ Dflag = 1;
+ break;
+ case 'I':
+ Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
+ if (errstr != NULL)
+ errx(1, "TCP receive window %s: %s",
+ errstr, optarg);
+ break;
+ case 'O':
+ Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
+ if (errstr != NULL)
+ errx(1, "TCP send window %s: %s",
+ errstr, optarg);
+ break;
+ case 'S':
+ Sflag = 1;
+ break;
+ case 'T':
+ errstr = NULL;
+ errno = 0;
+ if (map_tos(optarg, &Tflag))
+ break;
+ if (strlen(optarg) > 1 && optarg[0] == '0' &&
+ optarg[1] == 'x')
+ Tflag = (int)strtol(optarg, NULL, 16);
+ else
+ Tflag = (int)strtonum(optarg, 0, 255,
+ &errstr);
+ if (Tflag < 0 || Tflag > 255 || errstr || errno)
+ errx(1, "illegal tos value %s", optarg);
+ break;
+ default:
+ usage(1);
+ }
+ }
+ argc -= optind;
+ argv += optind;
+
+ /* Cruft to make sure options are clean, and used properly. */
+ if (argv[0] && !argv[1] && family == AF_UNIX) {
+ host = argv[0];
+ uport = NULL;
+ } else if (argv[0] && !argv[1]) {
+ if (!lflag)
+ usage(1);
+ uport = argv[0];
+ host = NULL;
+ } else if (argv[0] && argv[1]) {
+ host = argv[0];
+ uport = argv[1];
+ } else
+ usage(1);
+
+ if (lflag && sflag)
+ errx(1, "cannot use -s and -l");
+ if (lflag && pflag)
+ errx(1, "cannot use -p and -l");
+ if (lflag && zflag)
+ errx(1, "cannot use -z and -l");
+ if (!lflag && kflag)
+ errx(1, "must use -l with -k");
+
+ /* Get name of temporary socket for unix datagram client */
+ if ((family == AF_UNIX) && uflag && !lflag) {
+ if (sflag) {
+ unix_dg_tmp_socket = sflag;
+ } else {
+ strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
+ UNIX_DG_TMP_SOCKET_SIZE);
+ if (mktemp(unix_dg_tmp_socket_buf) == NULL)
+ err(1, "mktemp");
+ unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
+ }
+ }
+
+ /* Initialize addrinfo structure. */
+ if (family != AF_UNIX) {
+ memset(&hints, 0, sizeof(struct addrinfo));
+ hints.ai_family = family;
+ hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
+ hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
+ if (nflag)
+ hints.ai_flags |= AI_NUMERICHOST;
+ }
+
+ if (xflag) {
+ if (uflag)
+ errx(1, "no proxy support for UDP mode");
+
+ if (lflag)
+ errx(1, "no proxy support for listen");
+
+ if (family == AF_UNIX)
+ errx(1, "no proxy support for unix sockets");
+
+ /* XXX IPv6 transport to proxy would probably work */
+ if (family == AF_INET6)
+ errx(1, "no proxy support for IPv6");
+
+ if (sflag)
+ errx(1, "no proxy support for local source address");
+
+ proxyhost = strsep(&proxy, ":");
+ proxyport = proxy;
+
+ memset(&proxyhints, 0, sizeof(struct addrinfo));
+ proxyhints.ai_family = family;
+ proxyhints.ai_socktype = SOCK_STREAM;
+ proxyhints.ai_protocol = IPPROTO_TCP;
+ if (nflag)
+ proxyhints.ai_flags |= AI_NUMERICHOST;
+ }
+
+ if (lflag) {
+ int connfd;
+ ret = 0;
+
+ if (family == AF_UNIX) {
+ if (uflag)
+ s = unix_bind(host);
+ else
+ s = unix_listen(host);
+ }
+
+ /* Allow only one connection at a time, but stay alive. */
+ for (;;) {
+ if (family != AF_UNIX)
+ s = local_listen(host, uport, hints);
+ if (s < 0)
+ err(1, "local_listen");
+ /*
+ * For UDP and -k, don't connect the socket, let it
+ * receive datagrams from multiple socket pairs.
+ */
+ if (uflag && kflag)
+ readwrite(s);
+ /*
+ * For UDP and not -k, we will use recvfrom() initially
+ * to wait for a caller, then use the regular functions
+ * to talk to the caller.
+ */
+ else if (uflag && !kflag) {
+ int rv, plen;
+ char buf[16384];
+ struct sockaddr_storage z;
+
+ len = sizeof(z);
+ plen = 2048;
+ rv = recvfrom(s, buf, plen, MSG_PEEK,
+ (struct sockaddr *)&z, &len);
+ if (rv < 0)
+ err(1, "recvfrom");
+
+ rv = connect(s, (struct sockaddr *)&z, len);
+ if (rv < 0)
+ err(1, "connect");
+
+ if (vflag)
+ report_connect((struct sockaddr *)&z, len);
+
+ readwrite(s);
+ } else {
+ len = sizeof(cliaddr);
+ connfd = accept(s, (struct sockaddr *)&cliaddr,
+ &len);
+ if (connfd == -1) {
+ /* For now, all errnos are fatal */
+ err(1, "accept");
+ }
+ if (vflag)
+ report_connect((struct sockaddr *)&cliaddr, len);
+
+ readwrite(connfd);
+ close(connfd);
+ }
+
+ if (family != AF_UNIX)
+ close(s);
+ else if (uflag) {
+ if (connect(s, NULL, 0) < 0)
+ err(1, "connect");
+ }
+
+ if (!kflag)
+ break;
+ }
+ } else if (family == AF_UNIX) {
+ ret = 0;
+
+ if ((s = unix_connect(host)) > 0 && !zflag) {
+ readwrite(s);
+ close(s);
+ } else
+ ret = 1;
+
+ if (uflag)
+ unlink(unix_dg_tmp_socket);
+ exit(ret);
+
+ } else {
+ int i = 0;
+
+ /* Construct the portlist[] array. */
+ build_ports(uport);
+
+ /* Cycle through portlist, connecting to each port. */
+ for (i = 0; portlist[i] != NULL; i++) {
+ if (s)
+ close(s);
+
+ if (xflag)
+ s = socks_connect(host, portlist[i], hints,
+ proxyhost, proxyport, proxyhints, socksv,
+ Pflag);
+ else
+ s = remote_connect(host, portlist[i], hints);
+
+ if (s < 0)
+ continue;
+
+ ret = 0;
+ if (vflag || zflag) {
+ /* For UDP, make sure we are connected. */
+ if (uflag) {
+ if (udptest(s) == -1) {
+ ret = 1;
+ continue;
+ }
+ }
+
+ /* Don't look up port if -n. */
+ if (nflag)
+ sv = NULL;
+ else {
+ sv = getservbyport(
+ ntohs(atoi(portlist[i])),
+ uflag ? "udp" : "tcp");
+ }
+
+ fprintf(stderr,
+ "Connection to %s %s port [%s/%s] "
+ "succeeded!\n", host, portlist[i],
+ uflag ? "udp" : "tcp",
+ sv ? sv->s_name : "*");
+ }
+ if (Fflag)
+ fdpass(s);
+ else if (!zflag)
+ readwrite(s);
+ }
+ }
+
+ if (s)
+ close(s);
+
+ exit(ret);
+}
+
+/*
+ * unix_bind()
+ * Returns a unix socket bound to the given path
+ */
+int
+unix_bind(char *path)
+{
+ struct sockaddr_un sun_sa;
+ int s;
+
+ /* Create unix domain socket. */
+ if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
+ 0)) < 0)
+ return (-1);
+
+ memset(&sun_sa, 0, sizeof(struct sockaddr_un));
+ sun_sa.sun_family = AF_UNIX;
+
+ if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >=
+ sizeof(sun_sa.sun_path)) {
+ close(s);
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+
+ if (bind(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+}
+
+/*
+ * unix_connect()
+ * Returns a socket connected to a local unix socket. Returns -1 on failure.
+ */
+int
+unix_connect(char *path)
+{
+ struct sockaddr_un sun_sa;
+ int s;
+
+ if (uflag) {
+ if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
+ return (-1);
+ } else {
+ if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
+ return (-1);
+ }
+ (void)fcntl(s, F_SETFD, FD_CLOEXEC);
+
+ memset(&sun_sa, 0, sizeof(struct sockaddr_un));
+ sun_sa.sun_family = AF_UNIX;
+
+ if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >=
+ sizeof(sun_sa.sun_path)) {
+ close(s);
+ errno = ENAMETOOLONG;
+ return (-1);
+ }
+ if (connect(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+
+}
+
+/*
+ * unix_listen()
+ * Create a unix domain socket, and listen on it.
+ */
+int
+unix_listen(char *path)
+{
+ int s;
+ if ((s = unix_bind(path)) < 0)
+ return (-1);
+
+ if (listen(s, 5) < 0) {
+ close(s);
+ return (-1);
+ }
+ return (s);
+}
+
+/*
+ * remote_connect()
+ * Returns a socket connected to a remote host. Properly binds to a local
+ * port or source address if needed. Returns -1 on failure.
+ */
+int
+remote_connect(const char *host, const char *port, struct addrinfo hints)
+{
+ struct addrinfo *res, *res0;
+ int s, error;
+#if defined(SO_RTABLE) || defined(SO_BINDANY)
+ int on = 1;
+#endif
+
+ if ((error = getaddrinfo(host, port, &hints, &res)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ res0 = res;
+ do {
+ if ((s = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) < 0)
+ continue;
+
+#ifdef SO_RTABLE
+ if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
+ &rtableid, sizeof(rtableid)) == -1))
+ err(1, "setsockopt SO_RTABLE");
+#endif
+ /* Bind to a local port or source address if specified. */
+ if (sflag || pflag) {
+ struct addrinfo ahints, *ares;
+
+#ifdef SO_BINDANY
+ /* try SO_BINDANY, but don't insist */
+ setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
+#endif
+ memset(&ahints, 0, sizeof(struct addrinfo));
+ ahints.ai_family = res0->ai_family;
+ ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
+ ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
+ ahints.ai_flags = AI_PASSIVE;
+ if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ if (bind(s, (struct sockaddr *)ares->ai_addr,
+ ares->ai_addrlen) < 0)
+ err(1, "bind failed");
+ freeaddrinfo(ares);
+ }
+
+ set_common_sockopts(s);
+
+ if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
+ break;
+ else if (vflag)
+ warn("connect to %s port %s (%s) failed", host, port,
+ uflag ? "udp" : "tcp");
+
+ close(s);
+ s = -1;
+ } while ((res0 = res0->ai_next) != NULL);
+
+ freeaddrinfo(res);
+
+ return (s);
+}
+
+int
+timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
+{
+ struct pollfd pfd;
+ socklen_t optlen;
+ int flags = 0, optval;
+ int ret;
+
+ if (timeout != -1) {
+ flags = fcntl(s, F_GETFL, 0);
+ if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
+ err(1, "set non-blocking mode");
+ }
+
+ if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
+ pfd.fd = s;
+ pfd.events = POLLOUT;
+ if ((ret = poll(&pfd, 1, timeout)) == 1) {
+ optlen = sizeof(optval);
+ if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
+ &optval, &optlen)) == 0) {
+ errno = optval;
+ ret = optval == 0 ? 0 : -1;
+ }
+ } else if (ret == 0) {
+ errno = ETIMEDOUT;
+ ret = -1;
+ } else
+ err(1, "poll failed");
+ }
+
+ if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
+ err(1, "restoring flags");
+
+ return (ret);
+}
+
+/*
+ * local_listen()
+ * Returns a socket listening on a local port, binds to specified source
+ * address. Returns -1 on failure.
+ */
+int
+local_listen(char *host, char *port, struct addrinfo hints)
+{
+ struct addrinfo *res, *res0;
+ int s, ret, x = 1;
+ int error;
+
+ /* Allow nodename to be null. */
+ hints.ai_flags |= AI_PASSIVE;
+
+ /*
+ * In the case of binding to a wildcard address
+ * default to binding to an ipv4 address.
+ */
+ if (host == NULL && hints.ai_family == AF_UNSPEC)
+ hints.ai_family = AF_INET;
+
+ if ((error = getaddrinfo(host, port, &hints, &res)))
+ errx(1, "getaddrinfo: %s", gai_strerror(error));
+
+ res0 = res;
+ do {
+ if ((s = socket(res0->ai_family, res0->ai_socktype,
+ res0->ai_protocol)) < 0)
+ continue;
+
+#ifdef SO_RTABLE
+ if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
+ &rtableid, sizeof(rtableid)) == -1))
+ err(1, "setsockopt SO_RTABLE");
+#endif
+#ifdef SO_REUSEPORT
+ ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
+ if (ret == -1)
+ err(1, "setsockopt");
+#endif
+ set_common_sockopts(s);
+
+ if (bind(s, (struct sockaddr *)res0->ai_addr,
+ res0->ai_addrlen) == 0)
+ break;
+
+ close(s);
+ s = -1;
+ } while ((res0 = res0->ai_next) != NULL);
+
+ if (!uflag && s != -1) {
+ if (listen(s, 1) < 0)
+ err(1, "listen");
+ }
+
+ freeaddrinfo(res);
+
+ return (s);
+}
+
+/*
+ * readwrite()
+ * Loop that polls on the network file descriptor and stdin.
+ */
+void
+readwrite(int net_fd)
+{
+ struct pollfd pfd[4];
+ int stdin_fd = STDIN_FILENO;
+ int stdout_fd = STDOUT_FILENO;
+ unsigned char netinbuf[BUFSIZE];
+ size_t netinbufpos = 0;
+ unsigned char stdinbuf[BUFSIZE];
+ size_t stdinbufpos = 0;
+ int n, num_fds;
+ ssize_t ret;
+
+ /* don't read from stdin if requested */
+ if (dflag)
+ stdin_fd = -1;
+
+ /* stdin */
+ pfd[POLL_STDIN].fd = stdin_fd;
+ pfd[POLL_STDIN].events = POLLIN;
+
+ /* network out */
+ pfd[POLL_NETOUT].fd = net_fd;
+ pfd[POLL_NETOUT].events = 0;
+
+ /* network in */
+ pfd[POLL_NETIN].fd = net_fd;
+ pfd[POLL_NETIN].events = POLLIN;
+
+ /* stdout */
+ pfd[POLL_STDOUT].fd = stdout_fd;
+ pfd[POLL_STDOUT].events = 0;
+
+ while (1) {
+ /* both inputs are gone, buffers are empty, we are done */
+ if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
+ && stdinbufpos == 0 && netinbufpos == 0) {
+ close(net_fd);
+ return;
+ }
+ /* both outputs are gone, we can't continue */
+ if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
+ close(net_fd);
+ return;
+ }
+ /* listen and net in gone, queues empty, done */
+ if (lflag && pfd[POLL_NETIN].fd == -1
+ && stdinbufpos == 0 && netinbufpos == 0) {
+ close(net_fd);
+ return;
+ }
+
+ /* help says -i is for "wait between lines sent". We read and
+ * write arbitrary amounts of data, and we don't want to start
+ * scanning for newlines, so this is as good as it gets */
+ if (iflag)
+ sleep(iflag);
+
+ /* poll */
+ num_fds = poll(pfd, 4, timeout);
+
+ /* treat poll errors */
+ if (num_fds == -1) {
+ close(net_fd);
+ err(1, "polling error");
+ }
+
+ /* timeout happened */
+ if (num_fds == 0)
+ return;
+
+ /* treat socket error conditions */
+ for (n = 0; n < 4; n++) {
+ if (pfd[n].revents & (POLLERR|POLLNVAL)) {
+ pfd[n].fd = -1;
+ }
+ }
+ /* reading is possible after HUP */
+ if (pfd[POLL_STDIN].events & POLLIN &&
+ pfd[POLL_STDIN].revents & POLLHUP &&
+ ! (pfd[POLL_STDIN].revents & POLLIN))
+ pfd[POLL_STDIN].fd = -1;
+
+ if (pfd[POLL_NETIN].events & POLLIN &&
+ pfd[POLL_NETIN].revents & POLLHUP &&
+ ! (pfd[POLL_NETIN].revents & POLLIN))
+ pfd[POLL_NETIN].fd = -1;
+
+ if (pfd[POLL_NETOUT].revents & POLLHUP) {
+ if (Nflag)
+ shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
+ pfd[POLL_NETOUT].fd = -1;
+ }
+ /* if HUP, stop watching stdout */
+ if (pfd[POLL_STDOUT].revents & POLLHUP)
+ pfd[POLL_STDOUT].fd = -1;
+ /* if no net out, stop watching stdin */
+ if (pfd[POLL_NETOUT].fd == -1)
+ pfd[POLL_STDIN].fd = -1;
+ /* if no stdout, stop watching net in */
+ if (pfd[POLL_STDOUT].fd == -1) {
+ if (pfd[POLL_NETIN].fd != -1)
+ shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+ pfd[POLL_NETIN].fd = -1;
+ }
+
+ /* try to read from stdin */
+ if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
+ ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
+ &stdinbufpos);
+ /* error or eof on stdin - remove from pfd */
+ if (ret == 0 || ret == -1)
+ pfd[POLL_STDIN].fd = -1;
+ /* read something - poll net out */
+ if (stdinbufpos > 0)
+ pfd[POLL_NETOUT].events = POLLOUT;
+ /* filled buffer - remove self from polling */
+ if (stdinbufpos == BUFSIZE)
+ pfd[POLL_STDIN].events = 0;
+ }
+ /* try to write to network */
+ if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
+ ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
+ &stdinbufpos);
+ if (ret == -1)
+ pfd[POLL_NETOUT].fd = -1;
+ /* buffer empty - remove self from polling */
+ if (stdinbufpos == 0)
+ pfd[POLL_NETOUT].events = 0;
+ /* buffer no longer full - poll stdin again */
+ if (stdinbufpos < BUFSIZE)
+ pfd[POLL_STDIN].events = POLLIN;
+ }
+ /* try to read from network */
+ if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
+ ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
+ &netinbufpos);
+ if (ret == -1)
+ pfd[POLL_NETIN].fd = -1;
+ /* eof on net in - remove from pfd */
+ if (ret == 0) {
+ shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
+ pfd[POLL_NETIN].fd = -1;
+ }
+ /* read something - poll stdout */
+ if (netinbufpos > 0)
+ pfd[POLL_STDOUT].events = POLLOUT;
+ /* filled buffer - remove self from polling */
+ if (netinbufpos == BUFSIZE)
+ pfd[POLL_NETIN].events = 0;
+ /* handle telnet */
+ if (tflag)
+ atelnet(pfd[POLL_NETIN].fd, netinbuf,
+ netinbufpos);
+ }
+ /* try to write to stdout */
+ if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
+ ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
+ &netinbufpos);
+ if (ret == -1)
+ pfd[POLL_STDOUT].fd = -1;
+ /* buffer empty - remove self from polling */
+ if (netinbufpos == 0)
+ pfd[POLL_STDOUT].events = 0;
+ /* buffer no longer full - poll net in again */
+ if (netinbufpos < BUFSIZE)
+ pfd[POLL_NETIN].events = POLLIN;
+ }
+
+ /* stdin gone and queue empty? */
+ if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) {
+ if (pfd[POLL_NETOUT].fd != -1 && Nflag)
+ shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
+ pfd[POLL_NETOUT].fd = -1;
+ }
+ /* net in gone and queue empty? */
+ if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
+ pfd[POLL_STDOUT].fd = -1;
+ }
+ }
+}
+
+ssize_t
+drainbuf(int fd, unsigned char *buf, size_t *bufpos)
+{
+ ssize_t n;
+ ssize_t adjust;
+
+ n = write(fd, buf, *bufpos);
+ /* don't treat EAGAIN, EINTR as error */
+ if (n == -1 && (errno == EAGAIN || errno == EINTR))
+ n = -2;
+ if (n <= 0)
+ return n;
+ /* adjust buffer */
+ adjust = *bufpos - n;
+ if (adjust > 0)
+ memmove(buf, buf + n, adjust);
+ *bufpos -= n;
+ return n;
+}
+
+
+ssize_t
+fillbuf(int fd, unsigned char *buf, size_t *bufpos)
+{
+ size_t num = BUFSIZE - *bufpos;
+ ssize_t n;
+
+ n = read(fd, buf + *bufpos, num);
+ /* don't treat EAGAIN, EINTR as error */
+ if (n == -1 && (errno == EAGAIN || errno == EINTR))
+ n = -2;
+ if (n <= 0)
+ return n;
+ *bufpos += n;
+ return n;
+}
+
+/*
+ * fdpass()
+ * Pass the connected file descriptor to stdout and exit.
+ */
+void
+fdpass(int nfd)
+{
+#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
+ struct msghdr msg;
+#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
+ union {
+ struct cmsghdr hdr;
+ char buf[CMSG_SPACE(sizeof(int))];
+ } cmsgbuf;
+ struct cmsghdr *cmsg;
+#endif
+ struct iovec vec;
+ char ch = '\0';
+ struct pollfd pfd;
+ ssize_t r;
+
+ memset(&msg, 0, sizeof(msg));
+#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
+ msg.msg_accrights = (caddr_t)&nfd;
+ msg.msg_accrightslen = sizeof(nfd);
+#else
+ memset(&cmsgbuf, 0, sizeof(cmsgbuf));
+ msg.msg_control = (caddr_t)&cmsgbuf.buf;
+ msg.msg_controllen = sizeof(cmsgbuf.buf);
+ cmsg = CMSG_FIRSTHDR(&msg);
+ cmsg->cmsg_len = CMSG_LEN(sizeof(int));
+ cmsg->cmsg_level = SOL_SOCKET;
+ cmsg->cmsg_type = SCM_RIGHTS;
+ *(int *)CMSG_DATA(cmsg) = nfd;
+#endif
+
+ vec.iov_base = &ch;
+ vec.iov_len = 1;
+ msg.msg_iov = &vec;
+ msg.msg_iovlen = 1;
+
+ bzero(&pfd, sizeof(pfd));
+ pfd.fd = STDOUT_FILENO;
+ for (;;) {
+ r = sendmsg(STDOUT_FILENO, &msg, 0);
+ if (r == -1) {
+ if (errno == EAGAIN || errno == EINTR) {
+ pfd.events = POLLOUT;
+ if (poll(&pfd, 1, -1) == -1)
+ err(1, "poll");
+ continue;
+ }
+ err(1, "sendmsg");
+ } else if (r == -1)
+ errx(1, "sendmsg: unexpected return value %zd", r);
+ else
+ break;
+ }
+ exit(0);
+#else
+ errx(1, "%s: file descriptor passing not supported", __func__);
+#endif
+}
+
+/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
+void
+atelnet(int nfd, unsigned char *buf, unsigned int size)
+{
+ unsigned char *p, *end;
+ unsigned char obuf[4];
+
+ if (size < 3)
+ return;
+ end = buf + size - 2;
+
+ for (p = buf; p < end; p++) {
+ if (*p != IAC)
+ continue;
+
+ obuf[0] = IAC;
+ p++;
+ if ((*p == WILL) || (*p == WONT))
+ obuf[1] = DONT;
+ else if ((*p == DO) || (*p == DONT))
+ obuf[1] = WONT;
+ else
+ continue;
+
+ p++;
+ obuf[2] = *p;
+ if (atomicio(vwrite, nfd, obuf, 3) != 3)
+ warn("Write Error!");
+ }
+}
+
+/*
+ * build_ports()
+ * Build an array of ports in portlist[], listing each port
+ * that we should try to connect to.
+ */
+void
+build_ports(char *p)
+{
+ const char *errstr;
+ char *n;
+ int hi, lo, cp;
+ int x = 0;
+
+ if ((n = strchr(p, '-')) != NULL) {
+ *n = '\0';
+ n++;
+
+ /* Make sure the ports are in order: lowest->highest. */
+ hi = strtonum(n, 1, PORT_MAX, &errstr);
+ if (errstr)
+ errx(1, "port number %s: %s", errstr, n);
+ lo = strtonum(p, 1, PORT_MAX, &errstr);
+ if (errstr)
+ errx(1, "port number %s: %s", errstr, p);
+
+ if (lo > hi) {
+ cp = hi;
+ hi = lo;
+ lo = cp;
+ }
+
+ /* Load ports sequentially. */
+ for (cp = lo; cp <= hi; cp++) {
+ portlist[x] = calloc(1, PORT_MAX_LEN);
+ if (portlist[x] == NULL)
+ errx(1, "calloc");
+ snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
+ x++;
+ }
+
+ /* Randomly swap ports. */
+ if (rflag) {
+ int y;
+ char *c;
+
+ for (x = 0; x <= (hi - lo); x++) {
+ y = (arc4random() & 0xFFFF) % (hi - lo);
+ c = portlist[x];
+ portlist[x] = portlist[y];
+ portlist[y] = c;
+ }
+ }
+ } else {
+ hi = strtonum(p, 1, PORT_MAX, &errstr);
+ if (errstr)
+ errx(1, "port number %s: %s", errstr, p);
+ portlist[0] = strdup(p);
+ if (portlist[0] == NULL)
+ errx(1, "strdup");
+ }
+}
+
+/*
+ * udptest()
+ * Do a few writes to see if the UDP port is there.
+ * Fails once PF state table is full.
+ */
+int
+udptest(int s)
+{
+ int i, ret;
+
+ for (i = 0; i <= 3; i++) {
+ if (write(s, "X", 1) == 1)
+ ret = 1;
+ else
+ ret = -1;
+ }
+ return (ret);
+}
+
+void
+set_common_sockopts(int s)
+{
+ int x = 1;
+
+#ifdef TCP_MD5SIG
+ if (Sflag) {
+ if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
+ &x, sizeof(x)) == -1)
+ err(1, "setsockopt");
+ }
+#endif
+ if (Dflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
+ &x, sizeof(x)) == -1)
+ err(1, "setsockopt");
+ }
+ if (Tflag != -1) {
+ if (setsockopt(s, IPPROTO_IP, IP_TOS,
+ &Tflag, sizeof(Tflag)) == -1)
+ err(1, "set IP ToS");
+ }
+ if (Iflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
+ &Iflag, sizeof(Iflag)) == -1)
+ err(1, "set TCP receive buffer size");
+ }
+ if (Oflag) {
+ if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
+ &Oflag, sizeof(Oflag)) == -1)
+ err(1, "set TCP send buffer size");
+ }
+}
+
+int
+map_tos(char *s, int *val)
+{
+ /* DiffServ Codepoints and other TOS mappings */
+ const struct toskeywords {
+ const char *keyword;
+ int val;
+ } *t, toskeywords[] = {
+ { "af11", IPTOS_DSCP_AF11 },
+ { "af12", IPTOS_DSCP_AF12 },
+ { "af13", IPTOS_DSCP_AF13 },
+ { "af21", IPTOS_DSCP_AF21 },
+ { "af22", IPTOS_DSCP_AF22 },
+ { "af23", IPTOS_DSCP_AF23 },
+ { "af31", IPTOS_DSCP_AF31 },
+ { "af32", IPTOS_DSCP_AF32 },
+ { "af33", IPTOS_DSCP_AF33 },
+ { "af41", IPTOS_DSCP_AF41 },
+ { "af42", IPTOS_DSCP_AF42 },
+ { "af43", IPTOS_DSCP_AF43 },
+ { "critical", IPTOS_PREC_CRITIC_ECP },
+ { "cs0", IPTOS_DSCP_CS0 },
+ { "cs1", IPTOS_DSCP_CS1 },
+ { "cs2", IPTOS_DSCP_CS2 },
+ { "cs3", IPTOS_DSCP_CS3 },
+ { "cs4", IPTOS_DSCP_CS4 },
+ { "cs5", IPTOS_DSCP_CS5 },
+ { "cs6", IPTOS_DSCP_CS6 },
+ { "cs7", IPTOS_DSCP_CS7 },
+ { "ef", IPTOS_DSCP_EF },
+ { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
+ { "lowdelay", IPTOS_LOWDELAY },
+ { "netcontrol", IPTOS_PREC_NETCONTROL },
+ { "reliability", IPTOS_RELIABILITY },
+ { "throughput", IPTOS_THROUGHPUT },
+ { NULL, -1 },
+ };
+
+ for (t = toskeywords; t->keyword != NULL; t++) {
+ if (strcmp(s, t->keyword) == 0) {
+ *val = t->val;
+ return (1);
+ }
+ }
+
+ return (0);
+}
+
+void
+report_connect(const struct sockaddr *sa, socklen_t salen)
+{
+ char remote_host[NI_MAXHOST];
+ char remote_port[NI_MAXSERV];
+ int herr;
+ int flags = NI_NUMERICSERV;
+
+ if (nflag)
+ flags |= NI_NUMERICHOST;
+
+ if ((herr = getnameinfo(sa, salen,
+ remote_host, sizeof(remote_host),
+ remote_port, sizeof(remote_port),
+ flags)) != 0) {
+ if (herr == EAI_SYSTEM)
+ err(1, "getnameinfo");
+ else
+ errx(1, "getnameinfo: %s", gai_strerror(herr));
+ }
+
+ fprintf(stderr,
+ "Connection from %s %s "
+ "received!\n", remote_host, remote_port);
+}
+
+void
+help(void)
+{
+ usage(0);
+ fprintf(stderr, "\tCommand Summary:\n\
+ \t-4 Use IPv4\n\
+ \t-6 Use IPv6\n\
+ \t-D Enable the debug socket option\n\
+ \t-d Detach from stdin\n\
+ \t-F Pass socket fd\n\
+ \t-h This help text\n\
+ \t-I length TCP receive buffer length\n\
+ \t-i secs\t Delay interval for lines sent, ports scanned\n\
+ \t-k Keep inbound sockets open for multiple connects\n\
+ \t-l Listen mode, for inbound connects\n\
+ \t-N Shutdown the network socket after EOF on stdin\n\
+ \t-n Suppress name/port resolutions\n\
+ \t-O length TCP send buffer length\n\
+ \t-P proxyuser\tUsername for proxy authentication\n\
+ \t-p port\t Specify local port for remote connects\n\
+ \t-r Randomize remote ports\n\
+ \t-S Enable the TCP MD5 signature option\n\
+ \t-s addr\t Local source address\n\
+ \t-T toskeyword\tSet IP Type of Service\n\
+ \t-t Answer TELNET negotiation\n\
+ \t-U Use UNIX domain socket\n\
+ \t-u UDP mode\n\
+ \t-V rtable Specify alternate routing table\n\
+ \t-v Verbose\n\
+ \t-w secs\t Timeout for connects and final net reads\n\
+ \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
+ \t-x addr[:port]\tSpecify proxy address and port\n\
+ \t-z Zero-I/O mode [used for scanning]\n\
+ Port numbers can be individual or ranges: lo-hi [inclusive]\n");
+ exit(1);
+}
+
+void
+usage(int ret)
+{
+ fprintf(stderr,
+ "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
+ "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
+ "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
+ "\t [-x proxy_address[:port]] [destination] [port]\n");
+ if (ret)
+ exit(1);
+}
+
+/* *** src/usr.bin/nc/socks.c *** */
+
+
+/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */
+
+/*
+ * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
+ * Copyright (c) 2004, 2005 Damien Miller. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+ * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+ * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+ * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+ * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+ * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+#include <errno.h>
+#include <netdb.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <resolv.h>
+
+#define SOCKS_PORT "1080"
+#define HTTP_PROXY_PORT "3128"
+#define HTTP_MAXHDRS 64
+#define SOCKS_V5 5
+#define SOCKS_V4 4
+#define SOCKS_NOAUTH 0
+#define SOCKS_NOMETHOD 0xff
+#define SOCKS_CONNECT 1
+#define SOCKS_IPV4 1
+#define SOCKS_DOMAIN 3
+#define SOCKS_IPV6 4
+
+int remote_connect(const char *, const char *, struct addrinfo);
+int socks_connect(const char *, const char *, struct addrinfo,
+ const char *, const char *, struct addrinfo, int,
+ const char *);
+
+static int
+decode_addrport(const char *h, const char *p, struct sockaddr *addr,
+ socklen_t addrlen, int v4only, int numeric)
+{
+ int r;
+ struct addrinfo hints, *res;
+
+ bzero(&hints, sizeof(hints));
+ hints.ai_family = v4only ? PF_INET : PF_UNSPEC;
+ hints.ai_flags = numeric ? AI_NUMERICHOST : 0;
+ hints.ai_socktype = SOCK_STREAM;
+ r = getaddrinfo(h, p, &hints, &res);
+ /* Don't fatal when attempting to convert a numeric address */
+ if (r != 0) {
+ if (!numeric) {
+ errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p,
+ gai_strerror(r));
+ }
+ return (-1);
+ }
+ if (addrlen < res->ai_addrlen) {
+ freeaddrinfo(res);
+ errx(1, "internal error: addrlen < res->ai_addrlen");
+ }
+ memcpy(addr, res->ai_addr, res->ai_addrlen);
+ freeaddrinfo(res);
+ return (0);
+}
+
+static int
+proxy_read_line(int fd, char *buf, size_t bufsz)
+{
+ size_t off;
+
+ for(off = 0;;) {
+ if (off >= bufsz)
+ errx(1, "proxy read too long");
+ if (atomicio(read, fd, buf + off, 1) != 1)
+ err(1, "proxy read");
+ /* Skip CR */
+ if (buf[off] == '\r')
+ continue;
+ if (buf[off] == '\n') {
+ buf[off] = '\0';
+ break;
+ }
+ off++;
+ }
+ return (off);
+}
+
+static const char *
+getproxypass(const char *proxyuser, const char *proxyhost)
+{
+ char prompt[512];
+ static char pw[256];
+
+ snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
+ proxyuser, proxyhost);
+ if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
+ errx(1, "Unable to read proxy passphrase");
+ return (pw);
+}
+
+int
+socks_connect(const char *host, const char *port,
+ struct addrinfo hints __attribute__ ((__unused__)),
+ const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
+ int socksv, const char *proxyuser)
+{
+ int proxyfd, r, authretry = 0;
+ size_t hlen, wlen = 0;
+ unsigned char buf[1024];
+ size_t cnt;
+ struct sockaddr_storage addr;
+ struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
+ struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
+ in_port_t serverport;
+ const char *proxypass = NULL;
+
+ if (proxyport == NULL)
+ proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
+
+ /* Abuse API to lookup port */
+ if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
+ sizeof(addr), 1, 1) == -1)
+ errx(1, "unknown port \"%.64s\"", port);
+ serverport = in4->sin_port;
+
+ again:
+ if (authretry++ > 3)
+ errx(1, "Too many authentication failures");
+
+ proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
+
+ if (proxyfd < 0)
+ return (-1);
+
+ if (socksv == 5) {
+ if (decode_addrport(host, port, (struct sockaddr *)&addr,
+ sizeof(addr), 0, 1) == -1)
+ addr.ss_family = 0; /* used in switch below */
+
+ /* Version 5, one method: no authentication */
+ buf[0] = SOCKS_V5;
+ buf[1] = 1;
+ buf[2] = SOCKS_NOAUTH;
+ cnt = atomicio(vwrite, proxyfd, buf, 3);
+ if (cnt != 3)
+ err(1, "write failed (%zu/3)", cnt);
+
+ cnt = atomicio(read, proxyfd, buf, 2);
+ if (cnt != 2)
+ err(1, "read failed (%zu/3)", cnt);
+
+ if (buf[1] == SOCKS_NOMETHOD)
+ errx(1, "authentication method negotiation failed");
+
+ switch (addr.ss_family) {
+ case 0:
+ /* Version 5, connect: domain name */
+
+ /* Max domain name length is 255 bytes */
+ hlen = strlen(host);
+ if (hlen > 255)
+ errx(1, "host name too long for SOCKS5");
+ buf[0] = SOCKS_V5;
+ buf[1] = SOCKS_CONNECT;
+ buf[2] = 0;
+ buf[3] = SOCKS_DOMAIN;
+ buf[4] = hlen;
+ memcpy(buf + 5, host, hlen);
+ memcpy(buf + 5 + hlen, &serverport, sizeof serverport);
+ wlen = 7 + hlen;
+ break;
+ case AF_INET:
+ /* Version 5, connect: IPv4 address */
+ buf[0] = SOCKS_V5;
+ buf[1] = SOCKS_CONNECT;
+ buf[2] = 0;
+ buf[3] = SOCKS_IPV4;
+ memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
+ memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port);
+ wlen = 10;
+ break;
+ case AF_INET6:
+ /* Version 5, connect: IPv6 address */
+ buf[0] = SOCKS_V5;
+ buf[1] = SOCKS_CONNECT;
+ buf[2] = 0;
+ buf[3] = SOCKS_IPV6;
+ memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr);
+ memcpy(buf + 20, &in6->sin6_port,
+ sizeof in6->sin6_port);
+ wlen = 22;
+ break;
+ default:
+ errx(1, "internal error: silly AF");
+ }
+
+ cnt = atomicio(vwrite, proxyfd, buf, wlen);
+ if (cnt != wlen)
+ err(1, "write failed (%zu/%zu)", cnt, wlen);
+
+ cnt = atomicio(read, proxyfd, buf, 4);
+ if (cnt != 4)
+ err(1, "read failed (%zu/4)", cnt);
+ if (buf[1] != 0)
+ errx(1, "connection failed, SOCKS error %d", buf[1]);
+ switch (buf[3]) {
+ case SOCKS_IPV4:
+ cnt = atomicio(read, proxyfd, buf + 4, 6);
+ if (cnt != 6)
+ err(1, "read failed (%zu/6)", cnt);
+ break;
+ case SOCKS_IPV6:
+ cnt = atomicio(read, proxyfd, buf + 4, 18);
+ if (cnt != 18)
+ err(1, "read failed (%zu/18)", cnt);
+ break;
+ default:
+ errx(1, "connection failed, unsupported address type");
+ }
+ } else if (socksv == 4) {
+ /* This will exit on lookup failure */
+ decode_addrport(host, port, (struct sockaddr *)&addr,
+ sizeof(addr), 1, 0);
+
+ /* Version 4 */
+ buf[0] = SOCKS_V4;
+ buf[1] = SOCKS_CONNECT; /* connect */
+ memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
+ memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
+ buf[8] = 0; /* empty username */
+ wlen = 9;
+
+ cnt = atomicio(vwrite, proxyfd, buf, wlen);
+ if (cnt != wlen)
+ err(1, "write failed (%zu/%zu)", cnt, wlen);
+
+ cnt = atomicio(read, proxyfd, buf, 8);
+ if (cnt != 8)
+ err(1, "read failed (%zu/8)", cnt);
+ if (buf[1] != 90)
+ errx(1, "connection failed, SOCKS error %d", buf[1]);
+ } else if (socksv == -1) {
+ /* HTTP proxy CONNECT */
+
+ /* Disallow bad chars in hostname */
+ if (strcspn(host, "\r\n\t []:") != strlen(host))
+ errx(1, "Invalid hostname");
+
+ /* Try to be sane about numeric IPv6 addresses */
+ if (strchr(host, ':') != NULL) {
+ r = snprintf(buf, sizeof(buf),
+ "CONNECT [%s]:%d HTTP/1.0\r\n",
+ host, ntohs(serverport));
+ } else {
+ r = snprintf(buf, sizeof(buf),
+ "CONNECT %s:%d HTTP/1.0\r\n",
+ host, ntohs(serverport));
+ }
+ if (r == -1 || (size_t)r >= sizeof(buf))
+ errx(1, "hostname too long");
+ r = strlen(buf);
+
+ cnt = atomicio(vwrite, proxyfd, buf, r);
+ if (cnt != (size_t)r)
+ err(1, "write failed (%zu/%d)", cnt, r);
+
+ if (authretry > 1) {
+ char resp[1024];
+
+ proxypass = getproxypass(proxyuser, proxyhost);
+ r = snprintf(buf, sizeof(buf), "%s:%s",
+ proxyuser, proxypass);
+ if (r == -1 || (size_t)r >= sizeof(buf) ||
+ b64_ntop(buf, strlen(buf), resp,
+ sizeof(resp)) == -1)
+ errx(1, "Proxy username/password too long");
+ r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
+ "Basic %s\r\n", resp);
+ if (r == -1 || (size_t)r >= sizeof(buf))
+ errx(1, "Proxy auth response too long");
+ r = strlen(buf);
+ if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != (size_t)r)
+ err(1, "write failed (%zu/%d)", cnt, r);
+ }
+
+ /* Terminate headers */
+ if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
+ err(1, "write failed (2/%d)", r);
+
+ /* Read status reply */
+ proxy_read_line(proxyfd, buf, sizeof(buf));
+ if (proxyuser != NULL &&
+ strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
+ if (authretry > 1) {
+ fprintf(stderr, "Proxy authentication "
+ "failed\n");
+ }
+ close(proxyfd);
+ goto again;
+ } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
+ strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
+ errx(1, "Proxy error: \"%s\"", buf);
+
+ /* Headers continue until we hit an empty line */
+ for (r = 0; r < HTTP_MAXHDRS; r++) {
+ proxy_read_line(proxyfd, buf, sizeof(buf));
+ if (*buf == '\0')
+ break;
+ }
+ if (*buf != '\0')
+ errx(1, "Too many proxy headers received");
+ } else
+ errx(1, "Unknown proxy protocol %d", socksv);
+
+ return (proxyfd);
+}
+
diff --git a/crypto/openssh/regress/proto-mismatch.sh b/crypto/openssh/regress/proto-mismatch.sh
index fb521f2..9e8024b 100644
--- a/crypto/openssh/regress/proto-mismatch.sh
+++ b/crypto/openssh/regress/proto-mismatch.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: proto-mismatch.sh,v 1.3 2002/03/15 13:08:56 markus Exp $
+# $OpenBSD: proto-mismatch.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="protocol version mismatch"
@@ -16,4 +16,6 @@ mismatch ()
}
mismatch 2 SSH-1.5-HALLO
-mismatch 1 SSH-2.0-HALLO
+if ssh_version 1; then
+ mismatch 1 SSH-2.0-HALLO
+fi
diff --git a/crypto/openssh/regress/proto-version.sh b/crypto/openssh/regress/proto-version.sh
index b876dd7..cf49461 100644
--- a/crypto/openssh/regress/proto-version.sh
+++ b/crypto/openssh/regress/proto-version.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: proto-version.sh,v 1.4 2013/05/17 00:37:40 dtucker Exp $
+# $OpenBSD: proto-version.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="sshd version with different protocol combinations"
@@ -28,7 +28,9 @@ check_version ()
fi
}
-check_version 2,1 199
-check_version 1,2 199
check_version 2 20
-check_version 1 15
+if ssh_version 1; then
+ check_version 2,1 199
+ check_version 1,2 199
+ check_version 1 15
+fi
diff --git a/crypto/openssh/regress/proxy-connect.sh b/crypto/openssh/regress/proxy-connect.sh
index 023ba73..f816962 100644
--- a/crypto/openssh/regress/proxy-connect.sh
+++ b/crypto/openssh/regress/proxy-connect.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: proxy-connect.sh,v 1.7 2014/05/03 18:46:14 dtucker Exp $
+# $OpenBSD: proxy-connect.sh,v 1.8 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="proxy connect"
@@ -9,7 +9,7 @@ for ps in no yes; do
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
- for p in 1 2; do
+ for p in ${SSH_PROTOCOLS}; do
for c in no yes; do
verbose "plain username protocol $p privsep=$ps comp=$c"
opts="-$p -oCompression=$c -F $OBJ/ssh_proxy"
@@ -24,7 +24,7 @@ for ps in no yes; do
done
done
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "username with style protocol $p"
${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \
fail "ssh proxyconnect protocol $p failed"
diff --git a/crypto/openssh/regress/reconfigure.sh b/crypto/openssh/regress/reconfigure.sh
index 9fd2895..eecddd3 100644
--- a/crypto/openssh/regress/reconfigure.sh
+++ b/crypto/openssh/regress/reconfigure.sh
@@ -1,20 +1,30 @@
-# $OpenBSD: reconfigure.sh,v 1.2 2003/06/21 09:14:05 markus Exp $
+# $OpenBSD: reconfigure.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="simple connect after reconfigure"
# we need the full path to sshd for -HUP
-case $SSHD in
-/*)
- # full path is OK
- ;;
-*)
- # otherwise make fully qualified
- SSHD=$OBJ/$SSHD
-esac
+if test "x$USE_VALGRIND" = "x" ; then
+ case $SSHD in
+ /*)
+ # full path is OK
+ ;;
+ *)
+ # otherwise make fully qualified
+ SSHD=$OBJ/$SSHD
+ esac
+fi
start_sshd
+trace "connect before restart"
+for p in ${SSH_PROTOCOLS} ; do
+ ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
+ if [ $? -ne 0 ]; then
+ fail "ssh connect with protocol $p failed before reconfigure"
+ fi
+done
+
PID=`$SUDO cat $PIDFILE`
rm -f $PIDFILE
$SUDO kill -HUP $PID
@@ -28,7 +38,8 @@ done
test -f $PIDFILE || fatal "sshd did not restart"
-for p in 1 2; do
+trace "connect after restart"
+for p in ${SSH_PROTOCOLS} ; do
${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
if [ $? -ne 0 ]; then
fail "ssh connect with protocol $p failed after reconfigure"
diff --git a/crypto/openssh/regress/reexec.sh b/crypto/openssh/regress/reexec.sh
index 433573f..5c0a7b4 100644
--- a/crypto/openssh/regress/reexec.sh
+++ b/crypto/openssh/regress/reexec.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: reexec.sh,v 1.7 2013/05/17 10:23:52 dtucker Exp $
+# $OpenBSD: reexec.sh,v 1.8 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="reexec tests"
@@ -19,7 +19,7 @@ start_sshd_copy ()
copy_tests ()
{
rm -f ${COPY}
- for p in 1 2; do
+ for p in ${SSH_PROTOCOLS} ; do
verbose "$tid: proto $p"
${SSH} -nqo "Protocol=$p" -F $OBJ/ssh_config somehost \
cat ${DATA} > ${COPY}
diff --git a/crypto/openssh/regress/rekey.sh b/crypto/openssh/regress/rekey.sh
index fd452b0..0d4444d 100644
--- a/crypto/openssh/regress/rekey.sh
+++ b/crypto/openssh/regress/rekey.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: rekey.sh,v 1.15 2014/04/21 22:15:37 djm Exp $
+# $OpenBSD: rekey.sh,v 1.16 2015/02/14 12:43:16 markus Exp $
# Placed in the Public Domain.
tid="rekey"
@@ -100,9 +100,29 @@ for s in 5 10; do
fi
done
-echo "rekeylimit default 5" >>$OBJ/sshd_proxy
+for s in 16 1k 128k 256k; do
+ verbose "server rekeylimit ${s}"
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ echo "rekeylimit ${s}" >>$OBJ/sshd_proxy
+ rm -f ${COPY} ${LOG}
+ ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "cat ${DATA}" \
+ > ${COPY}
+ if [ $? -ne 0 ]; then
+ fail "ssh failed"
+ fi
+ cmp ${DATA} ${COPY} || fail "corrupted copy"
+ n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
+ n=`expr $n - 1`
+ trace "$n rekeying(s)"
+ if [ $n -lt 1 ]; then
+ fail "no rekeying occured"
+ fi
+done
+
for s in 5 10; do
verbose "server rekeylimit default ${s} no data"
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
+ echo "rekeylimit default ${s}" >>$OBJ/sshd_proxy
rm -f ${COPY} ${LOG}
${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 3"
if [ $? -ne 0 ]; then
diff --git a/crypto/openssh/regress/sshd-log-wrapper.sh b/crypto/openssh/regress/sshd-log-wrapper.sh
index a9386be..c00934c 100644
--- a/crypto/openssh/regress/sshd-log-wrapper.sh
+++ b/crypto/openssh/regress/sshd-log-wrapper.sh
@@ -3,11 +3,9 @@
# Placed in the Public Domain.
#
# simple wrapper for sshd proxy mode to catch stderr output
-# sh sshd-log-wrapper.sh /path/to/sshd /path/to/logfile
+# sh sshd-log-wrapper.sh /path/to/logfile /path/to/sshd [args...]
-sshd=$1
-log=$2
-shift
+log=$1
shift
-exec $sshd -E$log $@
+exec "$@" -E$log
diff --git a/crypto/openssh/regress/stderr-data.sh b/crypto/openssh/regress/stderr-data.sh
index b0bd235..8c8149a 100644
--- a/crypto/openssh/regress/stderr-data.sh
+++ b/crypto/openssh/regress/stderr-data.sh
@@ -1,10 +1,10 @@
-# $OpenBSD: stderr-data.sh,v 1.3 2013/05/17 04:29:14 dtucker Exp $
+# $OpenBSD: stderr-data.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="stderr data transfer"
for n in '' -n; do
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "test $tid: proto $p ($n)"
${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \
exec sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \
diff --git a/crypto/openssh/regress/t11.ok b/crypto/openssh/regress/t11.ok
new file mode 100644
index 0000000..1925bb4
--- /dev/null
+++ b/crypto/openssh/regress/t11.ok
@@ -0,0 +1 @@
+SHA256:4w1rnrek3klTJOTVhwuCIFd5k+pq9Bfo5KTxxb8BqbY
diff --git a/crypto/openssh/regress/t4.ok b/crypto/openssh/regress/t4.ok
index 8c4942b..4631ea8 100644
--- a/crypto/openssh/regress/t4.ok
+++ b/crypto/openssh/regress/t4.ok
@@ -1 +1 @@
-3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36
+MD5:3b:dd:44:e9:49:18:84:95:f1:e7:33:6b:9d:93:b1:36
diff --git a/crypto/openssh/regress/test-exec.sh b/crypto/openssh/regress/test-exec.sh
index a1bab83..0f76662 100644
--- a/crypto/openssh/regress/test-exec.sh
+++ b/crypto/openssh/regress/test-exec.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: test-exec.sh,v 1.48 2014/07/06 07:42:03 djm Exp $
+# $OpenBSD: test-exec.sh,v 1.51 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
#SUDO=sudo
@@ -130,6 +130,11 @@ if [ "x$TEST_SSH_CONCH" != "x" ]; then
esac
fi
+SSH_PROTOCOLS=`$SSH -Q protocol-version`
+if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then
+ SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}"
+fi
+
# Path to sshd must be absolute for rexec
case "$SSHD" in
/*) ;;
@@ -141,6 +146,55 @@ case "$SSHAGENT" in
*) SSHAGENT=`which $SSHAGENT` ;;
esac
+# Record the actual binaries used.
+SSH_BIN=${SSH}
+SSHD_BIN=${SSHD}
+SSHAGENT_BIN=${SSHAGENT}
+SSHADD_BIN=${SSHADD}
+SSHKEYGEN_BIN=${SSHKEYGEN}
+SSHKEYSCAN_BIN=${SSHKEYSCAN}
+SFTP_BIN=${SFTP}
+SFTPSERVER_BIN=${SFTPSERVER}
+SCP_BIN=${SCP}
+
+if [ "x$USE_VALGRIND" != "x" ]; then
+ mkdir -p $OBJ/valgrind-out
+ VG_TEST=`basename $SCRIPT .sh`
+
+ # Some tests are difficult to fix.
+ case "$VG_TEST" in
+ connect-privsep|reexec)
+ VG_SKIP=1 ;;
+ esac
+
+ if [ x"$VG_SKIP" = "x" ]; then
+ VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*"
+ VG_LOG="$OBJ/valgrind-out/${VG_TEST}."
+ VG_OPTS="--track-origins=yes --leak-check=full"
+ VG_OPTS="$VG_OPTS --trace-children=yes"
+ VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}"
+ VG_PATH="valgrind"
+ if [ "x$VALGRIND_PATH" != "x" ]; then
+ VG_PATH="$VALGRIND_PATH"
+ fi
+ VG="$VG_PATH $VG_OPTS"
+ SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH"
+ SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD"
+ SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT"
+ SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD"
+ SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN"
+ SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN"
+ SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}"
+ SCP="$VG --log-file=${VG_LOG}scp.%p $SCP"
+ cat > $OBJ/valgrind-sftp-server.sh << EOF
+#!/bin/sh
+exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@"
+EOF
+ chmod a+rx $OBJ/valgrind-sftp-server.sh
+ SFTPSERVER="$OBJ/valgrind-sftp-server.sh"
+ fi
+fi
+
# Logfiles.
# SSH_LOGFILE should be the debug output of ssh(1) only
# SSHD_LOGFILE should be the debug output of sshd(8) only
@@ -175,7 +229,7 @@ SSH="$SSHLOGWRAP"
# [kbytes] to ensure the file is at least that large.
DATANAME=data
DATA=$OBJ/${DATANAME}
-cat ${SSHAGENT} >${DATA}
+cat ${SSHAGENT_BIN} >${DATA}
chmod u+w ${DATA}
COPY=$OBJ/copy
rm -f ${COPY}
@@ -183,7 +237,7 @@ rm -f ${COPY}
increase_datafile_size()
{
while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do
- cat ${SSHAGENT} >>${DATA}
+ cat ${SSHAGENT_BIN} >>${DATA}
done
}
@@ -325,16 +379,27 @@ fatal ()
exit $RESULT
}
+ssh_version ()
+{
+ echo ${SSH_PROTOCOLS} | grep "$1" >/dev/null
+}
+
RESULT=0
PIDFILE=$OBJ/pidfile
trap fatal 3 2
+if ssh_version 1; then
+ PROTO="2,1"
+else
+ PROTO="2"
+fi
+
# create server config
cat << EOF > $OBJ/sshd_config
StrictModes no
Port $PORT
- Protocol 2,1
+ Protocol $PROTO
AddressFamily inet
ListenAddress 127.0.0.1
#ListenAddress ::1
@@ -360,7 +425,7 @@ echo 'StrictModes no' >> $OBJ/sshd_proxy
# create client config
cat << EOF > $OBJ/ssh_config
Host *
- Protocol 2,1
+ Protocol $PROTO
Hostname 127.0.0.1
HostKeyAlias localhost-with-alias
Port $PORT
@@ -385,10 +450,15 @@ fi
rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
+if ssh_version 1; then
+ SSH_KEYTYPES="rsa rsa1"
+else
+ SSH_KEYTYPES="rsa ed25519"
+fi
trace "generate keys"
-for t in rsa rsa1; do
+for t in ${SSH_KEYTYPES}; do
# generate user key
- if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then
+ if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then
rm -f $OBJ/$t
${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\
fail "ssh-keygen for $t failed"
@@ -451,7 +521,7 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy
echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy
- echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
+ echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
REGRESS_INTEROP_PUTTY=yes
fi
@@ -459,7 +529,7 @@ fi
# create a proxy version of the client config
(
cat $OBJ/ssh_config
- echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy
+ echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
) > $OBJ/ssh_proxy
# check proxy config
diff --git a/crypto/openssh/regress/transfer.sh b/crypto/openssh/regress/transfer.sh
index 1ae3ef5..36c1463 100644
--- a/crypto/openssh/regress/transfer.sh
+++ b/crypto/openssh/regress/transfer.sh
@@ -1,9 +1,9 @@
-# $OpenBSD: transfer.sh,v 1.2 2013/05/17 04:29:14 dtucker Exp $
+# $OpenBSD: transfer.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="transfer data"
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
verbose "$tid: proto $p"
rm -f ${COPY}
${SSH} -n -q -$p -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY}
diff --git a/crypto/openssh/regress/try-ciphers.sh b/crypto/openssh/regress/try-ciphers.sh
index 2881ce1..4165c7b 100644
--- a/crypto/openssh/regress/try-ciphers.sh
+++ b/crypto/openssh/regress/try-ciphers.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: try-ciphers.sh,v 1.23 2014/04/21 22:15:37 djm Exp $
+# $OpenBSD: try-ciphers.sh,v 1.24 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="try ciphers"
@@ -26,7 +26,11 @@ for c in `${SSH} -Q cipher`; do
done
done
-ciphers="3des blowfish"
+if ssh_version 1; then
+ ciphers="3des blowfish"
+else
+ ciphers=""
+fi
for c in $ciphers; do
trace "proto 1 cipher $c"
verbose "test $tid: proto 1 cipher $c"
diff --git a/crypto/openssh/regress/unittests/Makefile b/crypto/openssh/regress/unittests/Makefile
index bdb4574..d3d9082 100644
--- a/crypto/openssh/regress/unittests/Makefile
+++ b/crypto/openssh/regress/unittests/Makefile
@@ -1,5 +1,5 @@
-# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $
-
-SUBDIR= test_helper sshbuf sshkey
+# $OpenBSD: Makefile,v 1.5 2015/02/16 22:21:03 djm Exp $
+REGRESS_FAIL_EARLY= yes
+SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys
.include <bsd.subdir.mk>
diff --git a/crypto/openssh/regress/unittests/Makefile.inc b/crypto/openssh/regress/unittests/Makefile.inc
index 4c33637..c55d00c 100644
--- a/crypto/openssh/regress/unittests/Makefile.inc
+++ b/crypto/openssh/regress/unittests/Makefile.inc
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile.inc,v 1.1 2014/04/30 05:32:00 djm Exp $
+# $OpenBSD: Makefile.inc,v 1.3 2015/01/23 21:21:23 miod Exp $
.include <bsd.own.mk>
.include <bsd.obj.mk>
@@ -21,7 +21,6 @@ CDIAGFLAGS+= -Wmissing-declarations
CDIAGFLAGS+= -Wmissing-prototypes
CDIAGFLAGS+= -Wparentheses
CDIAGFLAGS+= -Wpointer-arith
-CDIAGFLAGS+= -Wpointer-sign
CDIAGFLAGS+= -Wreturn-type
CDIAGFLAGS+= -Wshadow
CDIAGFLAGS+= -Wsign-compare
@@ -32,6 +31,7 @@ CDIAGFLAGS+= -Wtrigraphs
CDIAGFLAGS+= -Wuninitialized
CDIAGFLAGS+= -Wunused
.if ${COMPILER_VERSION} == "gcc4"
+CDIAGFLAGS+= -Wpointer-sign
CDIAGFLAGS+= -Wold-style-definition
.endif
diff --git a/crypto/openssh/regress/unittests/bitmap/Makefile b/crypto/openssh/regress/unittests/bitmap/Makefile
new file mode 100644
index 0000000..b704d22
--- /dev/null
+++ b/crypto/openssh/regress/unittests/bitmap/Makefile
@@ -0,0 +1,12 @@
+# $OpenBSD: Makefile,v 1.1 2015/01/15 07:36:28 djm Exp $
+
+TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
+
+PROG=test_bitmap
+SRCS=tests.c
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
diff --git a/crypto/openssh/regress/unittests/bitmap/tests.c b/crypto/openssh/regress/unittests/bitmap/tests.c
new file mode 100644
index 0000000..23025f9
--- /dev/null
+++ b/crypto/openssh/regress/unittests/bitmap/tests.c
@@ -0,0 +1,135 @@
+/* $OpenBSD: tests.c,v 1.1 2015/01/15 07:36:28 djm Exp $ */
+/*
+ * Regress test for bitmap.h bitmap API
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include <openssl/bn.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "bitmap.h"
+
+#define NTESTS 131
+
+void
+tests(void)
+{
+ struct bitmap *b;
+ BIGNUM *bn;
+ size_t len;
+ int i, j, k, n;
+ u_char bbuf[1024], bnbuf[1024];
+ int r;
+
+ TEST_START("bitmap_new");
+ b = bitmap_new();
+ ASSERT_PTR_NE(b, NULL);
+ bn = BN_new();
+ ASSERT_PTR_NE(bn, NULL);
+ TEST_DONE();
+
+ TEST_START("bitmap_set_bit / bitmap_test_bit");
+ for (i = -1; i < NTESTS; i++) {
+ for (j = -1; j < NTESTS; j++) {
+ for (k = -1; k < NTESTS; k++) {
+ bitmap_zero(b);
+ BN_clear(bn);
+
+ test_subtest_info("set %d/%d/%d", i, j, k);
+ /* Set bits */
+ if (i >= 0) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, i), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, i), 1);
+ }
+ if (j >= 0) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, j), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, j), 1);
+ }
+ if (k >= 0) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, k), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, k), 1);
+ }
+
+ /* Check perfect match between bitmap and bn */
+ test_subtest_info("match %d/%d/%d", i, j, k);
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(BN_is_bit_set(bn, n),
+ bitmap_test_bit(b, n));
+ }
+
+ /* Test length calculations */
+ test_subtest_info("length %d/%d/%d", i, j, k);
+ ASSERT_INT_EQ(BN_num_bits(bn),
+ (int)bitmap_nbits(b));
+ ASSERT_INT_EQ(BN_num_bytes(bn),
+ (int)bitmap_nbytes(b));
+
+ /* Test serialisation */
+ test_subtest_info("serialise %d/%d/%d",
+ i, j, k);
+ len = bitmap_nbytes(b);
+ memset(bbuf, 0xfc, sizeof(bbuf));
+ ASSERT_INT_EQ(bitmap_to_string(b, bbuf,
+ sizeof(bbuf)), 0);
+ for (n = len; n < (int)sizeof(bbuf); n++)
+ ASSERT_U8_EQ(bbuf[n], 0xfc);
+ r = BN_bn2bin(bn, bnbuf);
+ ASSERT_INT_GE(r, 0);
+ ASSERT_INT_EQ(r, (int)len);
+ ASSERT_MEM_EQ(bbuf, bnbuf, len);
+
+ /* Test deserialisation */
+ test_subtest_info("deserialise %d/%d/%d",
+ i, j, k);
+ bitmap_zero(b);
+ ASSERT_INT_EQ(bitmap_from_string(b, bnbuf,
+ len), 0);
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(BN_is_bit_set(bn, n),
+ bitmap_test_bit(b, n));
+ }
+
+ /* Test clearing bits */
+ test_subtest_info("clear %d/%d/%d",
+ i, j, k);
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(bitmap_set_bit(b, n), 0);
+ ASSERT_INT_EQ(BN_set_bit(bn, n), 1);
+ }
+ if (i >= 0) {
+ bitmap_clear_bit(b, i);
+ BN_clear_bit(bn, i);
+ }
+ if (j >= 0) {
+ bitmap_clear_bit(b, j);
+ BN_clear_bit(bn, j);
+ }
+ if (k >= 0) {
+ bitmap_clear_bit(b, k);
+ BN_clear_bit(bn, k);
+ }
+ for (n = 0; n < NTESTS; n++) {
+ ASSERT_INT_EQ(BN_is_bit_set(bn, n),
+ bitmap_test_bit(b, n));
+ }
+ }
+ }
+ }
+ bitmap_free(b);
+ BN_free(bn);
+ TEST_DONE();
+}
+
diff --git a/crypto/openssh/regress/unittests/hostkeys/Makefile b/crypto/openssh/regress/unittests/hostkeys/Makefile
new file mode 100644
index 0000000..f52a85f
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/Makefile
@@ -0,0 +1,12 @@
+# $OpenBSD: Makefile,v 1.1 2015/02/16 22:18:34 djm Exp $
+
+TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
+
+PROG=test_hostkeys
+SRCS=tests.c test_iterate.c
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
+
+.include <bsd.regress.mk>
diff --git a/crypto/openssh/regress/unittests/hostkeys/mktestdata.sh b/crypto/openssh/regress/unittests/hostkeys/mktestdata.sh
new file mode 100755
index 0000000..36890ba
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/mktestdata.sh
@@ -0,0 +1,94 @@
+#!/bin/sh
+# $OpenBSD: mktestdata.sh,v 1.1 2015/02/16 22:18:34 djm Exp $
+
+set -ex
+
+cd testdata
+
+rm -f rsa1* rsa* dsa* ecdsa* ed25519*
+rm -f known_hosts*
+
+gen_all() {
+ _n=$1
+ _ecdsa_bits=256
+ test "x$_n" = "x1" && _ecdsa_bits=384
+ test "x$_n" = "x2" && _ecdsa_bits=521
+ ssh-keygen -qt rsa1 -b 1024 -C "RSA1 #$_n" -N "" -f rsa1_$_n
+ ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n
+ ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n
+ ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n
+ ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n
+ # Don't need private keys
+ rm -f rsa1_$_n rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n
+}
+
+hentries() {
+ _preamble=$1
+ _kspec=$2
+ for k in `ls -1 $_kspec | sort` ; do
+ printf "$_preamble "
+ cat $k
+ done
+ echo
+}
+
+gen_all 1
+gen_all 2
+gen_all 3
+gen_all 4
+gen_all 5
+gen_all 6
+
+# A section of known_hosts with hashed hostnames.
+(
+ hentries "sisyphus.example.com" "*_5.pub"
+ hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_6.pub"
+) > known_hosts_hash_frag
+ssh-keygen -Hf known_hosts_hash_frag
+rm -f known_hosts_hash_frag.old
+
+# Populated known_hosts, including comments, hashed names and invalid lines
+(
+ echo "# Plain host keys, plain host names"
+ hentries "sisyphus.example.com" "*_1.pub"
+
+ echo "# Plain host keys, hostnames + addresses"
+ hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_2.pub"
+
+ echo "# Some hosts with wildcard names / IPs"
+ hentries "*.example.com,192.0.2.*,2001:*" "*_3.pub"
+
+ echo "# Hashed hostname and address entries"
+ cat known_hosts_hash_frag
+ rm -f known_hosts_hash_frag
+ echo
+
+ echo "# Revoked and CA keys"
+ printf "@revoked sisyphus.example.com " ; cat rsa1_4.pub
+ printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub
+ printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub
+ printf "@cert-authority *.example.com " ; cat dsa_4.pub
+
+ printf "\n"
+ echo "# Some invalid lines"
+ # Invalid marker
+ printf "@what sisyphus.example.com " ; cat rsa1_1.pub
+ # Key missing
+ echo "sisyphus.example.com "
+ # Key blob missing
+ echo "prometheus.example.com ssh-ed25519 "
+ # Key blob truncated
+ echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz"
+ # RSA1 key truncated after key bits
+ echo "prometheus.example.com 1024 "
+ # RSA1 key truncated after exponent
+ echo "sisyphus.example.com 1024 65535 "
+ # RSA1 key incorrect key bits
+ printf "prometheus.example.com 1025 " ; cut -d' ' -f2- < rsa1_1.pub
+ # Invalid type
+ echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg=="
+ # Type mismatch with blob
+ echo "prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg=="
+) > known_hosts
+
+echo OK
diff --git a/crypto/openssh/regress/unittests/hostkeys/test_iterate.c b/crypto/openssh/regress/unittests/hostkeys/test_iterate.c
new file mode 100644
index 0000000..d81291b
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/test_iterate.c
@@ -0,0 +1,1171 @@
+/* $OpenBSD: test_iterate.c,v 1.3 2015/03/07 04:41:48 djm Exp $ */
+/*
+ * Regress test for hostfile.h hostkeys_foreach()
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "sshkey.h"
+#include "authfile.h"
+#include "hostfile.h"
+
+struct expected {
+ const char *key_file; /* Path for key, NULL for none */
+ int no_parse_status; /* Expected status w/o key parsing */
+ int no_parse_keytype; /* Expected keytype w/o key parsing */
+ int match_host_p; /* Match 'prometheus.example.com' */
+ int match_host_s; /* Match 'sisyphus.example.com' */
+ int match_ipv4; /* Match '192.0.2.1' */
+ int match_ipv6; /* Match '2001:db8::1' */
+ int match_flags; /* Expected flags from match */
+ struct hostkey_foreach_line l; /* Expected line contents */
+};
+
+struct cbctx {
+ const struct expected *expected;
+ size_t nexpected;
+ size_t i;
+ int flags;
+ int match_host_p;
+ int match_host_s;
+ int match_ipv4;
+ int match_ipv6;
+};
+
+/*
+ * hostkeys_foreach() iterator callback that verifies the line passed
+ * against an array of expected entries.
+ */
+static int
+check(struct hostkey_foreach_line *l, void *_ctx)
+{
+ struct cbctx *ctx = (struct cbctx *)_ctx;
+ const struct expected *expected;
+ int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0;
+ const int matching = (ctx->flags & HKF_WANT_MATCH) != 0;
+ u_int expected_status, expected_match;
+ int expected_keytype;
+
+ test_subtest_info("entry %zu/%zu, file line %ld",
+ ctx->i + 1, ctx->nexpected, l->linenum);
+
+ for (;;) {
+ ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected);
+ expected = ctx->expected + ctx->i++;
+ /* If we are matching host/IP then skip entries that don't */
+ if (!matching)
+ break;
+ if (ctx->match_host_p && expected->match_host_p)
+ break;
+ if (ctx->match_host_s && expected->match_host_s)
+ break;
+ if (ctx->match_ipv4 && expected->match_ipv4)
+ break;
+ if (ctx->match_ipv6 && expected->match_ipv6)
+ break;
+ }
+ expected_status = (parse_key || expected->no_parse_status < 0) ?
+ expected->l.status : (u_int)expected->no_parse_status;
+ expected_match = expected->l.match;
+#define UPDATE_MATCH_STATUS(x) do { \
+ if (ctx->x && expected->x) { \
+ expected_match |= expected->x; \
+ if (expected_status == HKF_STATUS_OK) \
+ expected_status = HKF_STATUS_MATCHED; \
+ } \
+ } while (0)
+ expected_keytype = (parse_key || expected->no_parse_keytype < 0) ?
+ expected->l.keytype : expected->no_parse_keytype;
+
+#ifndef WITH_SSH1
+ if (expected->l.keytype == KEY_RSA1 ||
+ expected->no_parse_keytype == KEY_RSA1) {
+ expected_status = HKF_STATUS_INVALID;
+ expected_keytype = KEY_UNSPEC;
+ parse_key = 0;
+ }
+#endif
+#ifndef OPENSSL_HAS_ECC
+ if (expected->l.keytype == KEY_ECDSA ||
+ expected->no_parse_keytype == KEY_ECDSA) {
+ expected_status = HKF_STATUS_INVALID;
+ expected_keytype = KEY_UNSPEC;
+ parse_key = 0;
+ }
+#endif
+
+ UPDATE_MATCH_STATUS(match_host_p);
+ UPDATE_MATCH_STATUS(match_host_s);
+ UPDATE_MATCH_STATUS(match_ipv4);
+ UPDATE_MATCH_STATUS(match_ipv6);
+
+ ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */
+ ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum);
+ ASSERT_U_INT_EQ(l->status, expected_status);
+ ASSERT_U_INT_EQ(l->match, expected_match);
+ /* Not all test entries contain fulltext */
+ if (expected->l.line != NULL)
+ ASSERT_STRING_EQ(l->line, expected->l.line);
+ ASSERT_INT_EQ(l->marker, expected->l.marker);
+ /* XXX we skip hashed hostnames for now; implement checking */
+ if (expected->l.hosts != NULL)
+ ASSERT_STRING_EQ(l->hosts, expected->l.hosts);
+ /* Not all test entries contain raw keys */
+ if (expected->l.rawkey != NULL)
+ ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey);
+ /* XXX synthesise raw key for cases lacking and compare */
+ ASSERT_INT_EQ(l->keytype, expected_keytype);
+ if (parse_key) {
+ if (expected->l.key == NULL)
+ ASSERT_PTR_EQ(l->key, NULL);
+ if (expected->l.key != NULL) {
+ ASSERT_PTR_NE(l->key, NULL);
+ ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1);
+ }
+ }
+ if (parse_key && !(l->comment == NULL && expected->l.comment == NULL))
+ ASSERT_STRING_EQ(l->comment, expected->l.comment);
+ return 0;
+}
+
+/* Loads public keys for a set of expected results */
+static void
+prepare_expected(struct expected *expected, size_t n)
+{
+ size_t i;
+
+ for (i = 0; i < n; i++) {
+ if (expected[i].key_file == NULL)
+ continue;
+#ifndef WITH_SSH1
+ if (expected[i].l.keytype == KEY_RSA1)
+ continue;
+#endif
+#ifndef OPENSSL_HAS_ECC
+ if (expected[i].l.keytype == KEY_ECDSA)
+ continue;
+#endif
+ ASSERT_INT_EQ(sshkey_load_public(
+ test_data_file(expected[i].key_file), &expected[i].l.key,
+ NULL), 0);
+ }
+}
+
+struct expected expected_full[] = {
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL, /* path, don't care */
+ 1, /* line number */
+ HKF_STATUS_COMMENT, /* status */
+ 0, /* match flags */
+ "# Plain host keys, plain host names", /* full line, optional */
+ MRK_NONE, /* marker (CA / revoked) */
+ NULL, /* hosts text */
+ NULL, /* raw key, optional */
+ KEY_UNSPEC, /* key type */
+ NULL, /* deserialised key */
+ NULL, /* comment */
+ } },
+ { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 2,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #1",
+ } },
+ { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 3,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #1",
+ } },
+ { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 4,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #1",
+ } },
+ { "rsa1_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 5,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #1",
+ } },
+ { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 6,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #1",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 7,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 8,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Plain host keys, hostnames + addresses",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 9,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #2",
+ } },
+ { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 10,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #2",
+ } },
+ { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 11,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #2",
+ } },
+ { "rsa1_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 12,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #2",
+ } },
+ { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 13,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com,192.0.2.1,2001:db8::1",
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #2",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 14,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 15,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Some hosts with wildcard names / IPs",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 16,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #3",
+ } },
+ { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 17,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #3",
+ } },
+ { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 18,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #3",
+ } },
+ { "rsa1_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 19,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #3",
+ } },
+ { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
+ NULL,
+ 20,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ "*.example.com,192.0.2.*,2001:*",
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #3",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 21,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 22,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Hashed hostname and address entries",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 23,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #5",
+ } },
+ { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 24,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #5",
+ } },
+ { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 25,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #5",
+ } },
+ { "rsa1_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 26,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #5",
+ } },
+ { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
+ NULL,
+ 27,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #5",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 28,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ /*
+ * The next series have each key listed multiple times, as the
+ * hostname and addresses in the pre-hashed known_hosts are split
+ * to separate lines.
+ */
+ { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 29,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #6",
+ } },
+ { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 30,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #6",
+ } },
+ { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 31,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #6",
+ } },
+ { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 32,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #6",
+ } },
+ { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 33,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #6",
+ } },
+ { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 34,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #6",
+ } },
+ { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 35,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #6",
+ } },
+ { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 36,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #6",
+ } },
+ { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 37,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #6",
+ } },
+ { "rsa1_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 38,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #6",
+ } },
+ { "rsa1_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 39,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #6",
+ } },
+ { "rsa1_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 40,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #6",
+ } },
+ { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
+ NULL,
+ 41,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #6",
+ } },
+ { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
+ NULL,
+ 42,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #6",
+ } },
+ { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
+ NULL,
+ 43,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_RSA,
+ NULL, /* filled at runtime */
+ "RSA #6",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 44,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 45,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 46,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Revoked and CA keys",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { "rsa1_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 47,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_REVOKE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_RSA1,
+ NULL, /* filled at runtime */
+ "RSA1 #4",
+ } },
+ { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 48,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_REVOKE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_ED25519,
+ NULL, /* filled at runtime */
+ "ED25519 #4",
+ } },
+ { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 49,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_CA,
+ "prometheus.example.com",
+ NULL,
+ KEY_ECDSA,
+ NULL, /* filled at runtime */
+ "ECDSA #4",
+ } },
+ { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 50,
+ HKF_STATUS_OK,
+ 0,
+ NULL,
+ MRK_CA,
+ "*.example.com",
+ NULL,
+ KEY_DSA,
+ NULL, /* filled at runtime */
+ "DSA #4",
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 51,
+ HKF_STATUS_COMMENT,
+ 0,
+ "",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 52,
+ HKF_STATUS_COMMENT,
+ 0,
+ "# Some invalid lines",
+ MRK_NONE,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, 0, 0, 0, -1, {
+ NULL,
+ 53,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_ERROR,
+ NULL,
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 54,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 55,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 56,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 57,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, HKF_STATUS_OK, KEY_RSA1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 58,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL,
+ NULL,
+ } },
+ { NULL, HKF_STATUS_OK, KEY_RSA1, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 59,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL, /* filled at runtime */
+ NULL,
+ } },
+ { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
+ NULL,
+ 60,
+ HKF_STATUS_INVALID,
+ 0,
+ NULL,
+ MRK_NONE,
+ "sisyphus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL, /* filled at runtime */
+ NULL,
+ } },
+ { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, {
+ NULL,
+ 61,
+ HKF_STATUS_INVALID, /* Would be ok if key not parsed */
+ 0,
+ NULL,
+ MRK_NONE,
+ "prometheus.example.com",
+ NULL,
+ KEY_UNSPEC,
+ NULL, /* filled at runtime */
+ NULL,
+ } },
+};
+
+void test_iterate(void);
+
+void
+test_iterate(void)
+{
+ struct cbctx ctx;
+
+ TEST_START("hostkeys_iterate all with key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_PARSE_KEY;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, NULL, NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate all without key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, NULL, NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 1");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ ctx.match_host_p = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 2");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ ctx.match_host_s = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 1");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ ctx.match_host_p = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 2");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ ctx.match_host_s = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify IPv4");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ ctx.match_ipv4 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify IPv6");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ ctx.match_ipv6 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match IPv4");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ ctx.match_ipv4 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match IPv6");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ ctx.match_ipv6 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify addr missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match addr missing");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 2 and IPv4");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = 0;
+ ctx.match_host_s = 1;
+ ctx.match_ipv4 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 1 and IPv6");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH;
+ ctx.match_host_p = 1;
+ ctx.match_ipv6 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "prometheus.example.com", "2001:db8::1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_PARSE_KEY;
+ ctx.match_host_s = 1;
+ ctx.match_ipv4 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
+ TEST_DONE();
+
+ TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse");
+ memset(&ctx, 0, sizeof(ctx));
+ ctx.expected = expected_full;
+ ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
+ ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY;
+ ctx.match_host_p = 1;
+ ctx.match_ipv6 = 1;
+ prepare_expected(expected_full, ctx.nexpected);
+ ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
+ check, &ctx, "prometheus.example.com", "2001:db8::1", ctx.flags), 0);
+ TEST_DONE();
+}
+
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub
new file mode 100644
index 0000000..56e1e37
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_1.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub
new file mode 100644
index 0000000..394e0bf
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_2.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub
new file mode 100644
index 0000000..e506ea4
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_3.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub
new file mode 100644
index 0000000..8552c38
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_4.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub
new file mode 100644
index 0000000..149e1ef
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_5.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub
new file mode 100644
index 0000000..edbb976
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/dsa_6.pub
@@ -0,0 +1 @@
+ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub
new file mode 100644
index 0000000..16a535b
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_1.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub
new file mode 100644
index 0000000..d2bad11
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_2.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub
new file mode 100644
index 0000000..e3ea925
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_3.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub
new file mode 100644
index 0000000..2d616f5
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_4.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub
new file mode 100644
index 0000000..a3df9b3
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_5.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub
new file mode 100644
index 0000000..139f5a7
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ecdsa_6.pub
@@ -0,0 +1 @@
+ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub
new file mode 100644
index 0000000..0b12efe
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_1.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub
new file mode 100644
index 0000000..78e262b
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_2.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub
new file mode 100644
index 0000000..64e5f12
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_3.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub
new file mode 100644
index 0000000..47b6724
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_4.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub
new file mode 100644
index 0000000..72ccae6
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_5.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub
new file mode 100644
index 0000000..0f71973
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/ed25519_6.pub
@@ -0,0 +1 @@
+ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts b/crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts
new file mode 100644
index 0000000..3740f67
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/known_hosts
@@ -0,0 +1,61 @@
+# Plain host keys, plain host names
+sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1
+sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1
+sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1
+sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
+sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1
+
+# Plain host keys, hostnames + addresses
+prometheus.example.com,192.0.2.1,2001:db8::1 ssh-dss AAAAB3NzaC1kc3MAAACBAI38Hy/61/O5Bp6yUG8J5XQCeNjRS0xvjlCdzKLyXCueMa+L+X2L/u9PWUsy5SVbTjGgpB8sF6UkCNsV+va7S8zCCHas2MZ7GPlxP6GZBkRPTIFR0N/Pu7wfBzDQz0t0iL4VmxBfTBQv/SxkGWZg+yHihIQP9fwdSAwD/7aVh6ItAAAAFQDSyihIUlINlswM0PJ8wXSti3yIMwAAAIB+oqzaB6ozqs8YxpN5oQOBa/9HEBQEsp8RSIlQmVubXRNgktp42n+Ii1waU9UUk8DX5ahhIeR6B7ojWkqmDAji4SKpoHf4kmr6HvYo85ZSTSx0W4YK/gJHSpDJwhlT52tAfb1JCbWSObjl09B4STv7KedCHcR5oXQvvrV+XoKOSAAAAIAue/EXrs2INw1RfaKNHC0oqOMxmRitv0BFMuNVPo1VDj39CE5kA7AHjwvS1TNeaHtK5Hhgeb6vsmLmNPTOc8xCob0ilyQbt9O0GbONeF2Ge7D2UJyULA/hxql+tCYFIC6yUrmo35fF9XiNisXLoaflk9fjp7ROWWVwnki/jstaQw== DSA #2
+prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2
+prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2
+prometheus.example.com,192.0.2.1,2001:db8::1 1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2
+prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2
+
+# Some hosts with wildcard names / IPs
+*.example.com,192.0.2.*,2001:* ssh-dss AAAAB3NzaC1kc3MAAACBAI6lz2Ip9bzE7TGuDD4SjO9S4Ac90gq0h6ai1O06eI8t/Ot2uJ5Jk2QyVr2jvIZHDl/5bwBx7+5oyjlwRoUrAPPD814wf5tU2tSnmdu1Wbf0cBswif5q0r4tevzmopp/AtgH11QHo3u0/pfyJd10qBDLV2FaYSKMmZvyPfZJ0s9pAAAAFQD5Eqjl6Rx2qVePodD9OwAPT0bU6wAAAIAfnDm6csZF0sFaJR3NIJvaYgSGr8s7cqlsk2gLltB/1wOOO2yX+NeEC+B0H93hlMfaUsPa08bwgmYxnavSMqEBpmtPceefJiEd68zwYqXd38f88wyWZ9Z5iwaI/6OVZPHzCbDxOa4ewVTevRNYUKP1xUTZNT8/gSMfZLYPk4T2AQAAAIAUKroozRMyV+3V/rxt0gFnNxRXBKk+9cl3vgsQ7ktkI9cYg7V1T2K0XF21AVMK9gODszy6PBJjV6ruXBV6TRiqIbQauivp3bHHKYsG6wiJNqwdbVwIjfvv8nn1qFoZQLXG3sdONr9NwN8KzrX89OV0BlR2dVM5qqp+YxOXymP9yg== DSA #3
+*.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3
+*.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3
+*.example.com,192.0.2.*,2001:* 1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3
+*.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3
+
+# Hashed hostname and address entries
+|1|6FWxoqTCAfm8sZ7T/q73OmxCFGM=|S4eQmusok4cbyDzzGEFGIAthDbw= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5
+|1|hTrfD0CuuB9ZbOa1CHFYvIk/gKE=|tPmW50t7flncm1UyM+DR97ubDNU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5
+|1|fOGqe75X5ZpTz4c7DitP4E8/y30=|Lmcch2fh54bUYoV//S2VqDFVeiY= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5
+|1|0RVzLjY3lwE3MRweguaAXaCCWk8=|DbcIgJQcRZJMYI6NYDOM6oJycPk= 1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5
+|1|4q79XnHpKBNQhyMLAqbPPDN+JKo=|k1Wvjjb52zDdrXWM801+wX5oH8U= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5
+
+|1|0M6PIx6THA3ipIOvTl3fcgn2z+A=|bwEJAOwJz+Sm7orFdgj170mD/zY= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
+|1|a6WGHcL+9gX3e96tMlgDSDJwtSg=|5Dqlb/yqNEf7jgfllrp/ygLmRV8= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
+|1|OeCpi7Pn5Q6c8la4fPf9G8YctT8=|sC6D7lDXTafIpokZJ1+1xWg2R6Q= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
+|1|BHESVyiJ7G2NN0lxrw7vT109jmk=|TKof+015J77bXqibsh0N1Lp0MKk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
+|1|wY53mZNASDJ5/P3JYCJ4FUNa6WQ=|v8p0MfV5lqlZB2J0yLxl/gsWVQo= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
+|1|horeoyFPwfKhyFN+zJZ5LCfOo/I=|2ofvp0tNwCbKsV8FuiFA4gQG2Z8= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
+|1|Aw4fXumZfx6jEIJuDGIyeEMd81A=|5FdLtdm2JeKNsS8IQeQlGYIadOE= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
+|1|+dGUNpv6GblrDd5fgHLlOWpSbEo=|He/pQ1yJjtiCyTNWpGwjBD4sZFI= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
+|1|E/PACGl8m1T7QnPedOoooozstP0=|w6DQAFT8yZgj0Hlkz5R1TppYHCA= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
+|1|SaoyMStgxpYfwedSXBAghi8Zo0s=|Gz78k69GaE6iViV3OOvbStKqyTA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
+|1|8qfGeiT5WTCzWYbXPQ+lsLg7km4=|1sIBwiSUr8IGkvrUGm3/9QYurmA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
+|1|87M1OtyHg1BZiDY3rT6lYsZFnAU=|eddAQVcMNbn2OB87XWXFQnYo6R4= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
+|1|60w3wFfC0XWI+rRmRlxIRhh8lwE=|yMhsGrzBJKiesAdSQ/PVgkCrDKk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
+|1|5gdEMmLUJC7grqWhRJPy2OTaSyE=|/XTfmLMa/B8npcVCGFRdaHl+d/0= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
+|1|6FGCWUr42GHdMB/eifnHNCuwgdk=|ONJvYZ/ANmi59R5HrOhLPmvYENM= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
+
+
+# Revoked and CA keys
+@revoked sisyphus.example.com 1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4
+@revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4
+@cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4
+@cert-authority *.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAKvjnFHm0VvMr5h2Zu3nURsxQKGoxm+DCzYDxRYcilK07Cm5c4XTrFbA2X86+9sGs++W7QRMcTJUYIg0a+UtIMtAjwORd6ZPXM2K5dBW+gh1oHyvKi767tWX7I2c+1ZPJDY95mUUfZQUEfdy9eGDSBmw/pSsveQ1ur6XNUh/MtP/AAAAFQDHnXk/9jBJAdce1pHtLWnbdPSGdQAAAIEAm2OLy8tZBfiEO3c3X1yyB/GTcDwrQCqRMDkhnsmrliec3dWkOfNTzu+MrdvF8ymTWLEqPpbMheYtvNyZ3TF0HO5W7aVBpdGZbOdOAIfB+6skqGbI8A5Up1d7dak/bSsqL2r5NjwbDOdq+1hBzzvbl/qjh+sQarV2zHrpKoQaV28AAACANtkBVedBbqIAdphCrN/LbUi9WlyuF9UZz+tlpVLYrj8GJVwnplV2tvOmUw6yP5/pzCimTsao8dpL5PWxm7fKxLWVxA+lEsA4WeC885CiZn8xhdaJOCN+NyJ2bqkz+4VPI7oDGBm0aFwUqJn+M1PiSgvI50XdF2dBsFRTRNY0wzA= DSA #4
+
+# Some invalid lines
+@what sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
+sisyphus.example.com
+prometheus.example.com ssh-ed25519
+sisyphus.example.com ssh-dsa AAAATgAAAAdz
+prometheus.example.com 1024
+sisyphus.example.com 1024 65535
+prometheus.example.com 1025 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
+sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==
+prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub
new file mode 100644
index 0000000..772ce9c
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_1.pub
@@ -0,0 +1 @@
+1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub
new file mode 100644
index 0000000..78794b9
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_2.pub
@@ -0,0 +1 @@
+1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub
new file mode 100644
index 0000000..0c035fe
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_3.pub
@@ -0,0 +1 @@
+1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub
new file mode 100644
index 0000000..00064423
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_4.pub
@@ -0,0 +1 @@
+1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub
new file mode 100644
index 0000000..bb53c26
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_5.pub
@@ -0,0 +1 @@
+1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub
new file mode 100644
index 0000000..85d6576
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa1_6.pub
@@ -0,0 +1 @@
+1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub
new file mode 100644
index 0000000..2b87885
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_1.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub
new file mode 100644
index 0000000..33f1fd9
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_2.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub
new file mode 100644
index 0000000..c2f6b20
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_3.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub
new file mode 100644
index 0000000..35545a7
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_4.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDI8AdjBAozcdRnIikVlt69iyDHKyrtxmpdkbRy9bWaL86OH+PTmLUk5e+T/ufiakpeE2pm0hkE3e4Sh/FsY+rsQdRoraWVNFfchcMeVlKvuy5RZN0ElvmaQebOJUeNeBn2LLw8aL8bJ4CP/bQRKrmrSSqjz3+4H9YNVyyk1OGBPQ== RSA #4
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub
new file mode 100644
index 0000000..befbaa7
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_5.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5
diff --git a/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub
new file mode 100644
index 0000000..393e116
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/testdata/rsa_6.pub
@@ -0,0 +1 @@
+ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
diff --git a/crypto/openssh/regress/unittests/hostkeys/tests.c b/crypto/openssh/regress/unittests/hostkeys/tests.c
new file mode 100644
index 0000000..92c7646
--- /dev/null
+++ b/crypto/openssh/regress/unittests/hostkeys/tests.c
@@ -0,0 +1,16 @@
+/* $OpenBSD: tests.c,v 1.1 2015/02/16 22:18:34 djm Exp $ */
+/*
+ * Regress test for known_hosts-related API.
+ *
+ * Placed in the public domain
+ */
+
+void tests(void);
+void test_iterate(void); /* test_iterate.c */
+
+void
+tests(void)
+{
+ test_iterate();
+}
+
diff --git a/crypto/openssh/regress/unittests/kex/Makefile b/crypto/openssh/regress/unittests/kex/Makefile
new file mode 100644
index 0000000..6532cb0
--- /dev/null
+++ b/crypto/openssh/regress/unittests/kex/Makefile
@@ -0,0 +1,14 @@
+# $OpenBSD: Makefile,v 1.2 2015/01/24 10:39:21 miod Exp $
+
+TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
+
+PROG=test_kex
+SRCS=tests.c test_kex.c
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>
+
+LDADD+=-lz
diff --git a/crypto/openssh/regress/unittests/kex/test_kex.c b/crypto/openssh/regress/unittests/kex/test_kex.c
new file mode 100644
index 0000000..c61e2bd
--- /dev/null
+++ b/crypto/openssh/regress/unittests/kex/test_kex.c
@@ -0,0 +1,197 @@
+/* $OpenBSD: test_kex.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */
+/*
+ * Regress test KEX
+ *
+ * Placed in the public domain
+ */
+
+#include "includes.h"
+
+#include <sys/types.h>
+#include <sys/param.h>
+#include <stdio.h>
+#ifdef HAVE_STDINT_H
+#include <stdint.h>
+#endif
+#include <stdlib.h>
+#include <string.h>
+
+#include "../test_helper/test_helper.h"
+
+#include "ssherr.h"
+#include "ssh_api.h"
+#include "sshbuf.h"
+#include "packet.h"
+#include "myproposal.h"
+
+struct ssh *active_state = NULL; /* XXX - needed for linking */
+
+void kex_tests(void);
+static int do_debug = 0;
+
+static int
+do_send_and_receive(struct ssh *from, struct ssh *to)
+{
+ u_char type;
+ size_t len;
+ const u_char *buf;
+ int r;
+
+ for (;;) {
+ if ((r = ssh_packet_next(from, &type)) != 0) {
+ fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
+ return r;
+ }
+ if (type != 0)
+ return 0;
+ buf = ssh_output_ptr(from, &len);
+ if (do_debug)
+ printf("%zu", len);
+ if (len == 0)
+ return 0;
+ if ((r = ssh_output_consume(from, len)) != 0 ||
+ (r = ssh_input_append(to, buf, len)) != 0)
+ return r;
+ }
+}
+
+static void
+run_kex(struct ssh *client, struct ssh *server)
+{
+ int r = 0;
+
+ while (!server->kex->done || !client->kex->done) {
+ if (do_debug)
+ printf(" S:");
+ if ((r = do_send_and_receive(server, client)))
+ break;
+ if (do_debug)
+ printf(" C:");
+ if ((r = do_send_and_receive(client, server)))
+ break;
+ }
+ if (do_debug)
+ printf("done: %s\n", ssh_err(r));
+ ASSERT_INT_EQ(r, 0);
+ ASSERT_INT_EQ(server->kex->done, 1);
+ ASSERT_INT_EQ(client->kex->done, 1);
+}
+
+static void
+do_kex_with_key(char *kex, int keytype, int bits)
+{
+ struct ssh *client = NULL, *server = NULL, *server2 = NULL;
+ struct sshkey *private, *public;
+ struct sshbuf *state;
+ struct kex_params kex_params;
+ char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
+
+ TEST_START("sshkey_generate");
+ ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0);
+ TEST_DONE();
+
+ TEST_START("sshkey_from_private");
+ ASSERT_INT_EQ(sshkey_from_private(private, &public), 0);
+ TEST_DONE();
+
+ TEST_START("ssh_init");
+ memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
+ if (kex != NULL)
+ kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
+ ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
+ ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
+ ASSERT_PTR_NE(client, NULL);
+ ASSERT_PTR_NE(server, NULL);
+ TEST_DONE();
+
+ TEST_START("ssh_add_hostkey");
+ ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0);
+ ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0);
+ TEST_DONE();
+
+ TEST_START("kex");
+ run_kex(client, server);
+ TEST_DONE();
+
+ TEST_START("rekeying client");
+ ASSERT_INT_EQ(kex_send_kexinit(client), 0);
+ run_kex(client, server);
+ TEST_DONE();
+
+ TEST_START("rekeying server");
+ ASSERT_INT_EQ(kex_send_kexinit(server), 0);
+ run_kex(client, server);
+ TEST_DONE();
+
+ TEST_START("ssh_packet_get_state");
+ state = sshbuf_new();
+ ASSERT_PTR_NE(state, NULL);
+ ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
+ ASSERT_INT_GE(sshbuf_len(state), 1);
+ TEST_DONE();
+
+ TEST_START("ssh_packet_set_state");
+ server2 = NULL;
+ ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
+ ASSERT_PTR_NE(server2, NULL);
+ ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0);
+ kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */
+ ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
+ ASSERT_INT_EQ(sshbuf_len(state), 0);
+ sshbuf_free(state);
+ ASSERT_PTR_NE(server2->kex, NULL);
+ /* XXX we need to set the callbacks */
+ server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
+ server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
+ server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
+ server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
+#ifdef OPENSSL_HAS_ECC
+ server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
+#endif
+ server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
+ server2->kex->load_host_public_key = server->kex->load_host_public_key;
+ server2->kex->load_host_private_key = server->kex->load_host_private_key;
+ server2->kex->sign = server->kex->sign;
+ TEST_DONE();
+
+ TEST_START("rekeying server2");
+ ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
+ run_kex(client, server2);
+ ASSERT_INT_EQ(kex_send_kexinit(client), 0);
+ run_kex(client, server2);
+ TEST_DONE();
+
+ TEST_START("cleanup");
+ sshkey_free(private);
+ sshkey_free(public);
+ ssh_free(client);
+ ssh_free(server);
+ ssh_free(server2);
+ TEST_DONE();
+}
+
+static void
+do_kex(char *kex)
+{
+ do_kex_with_key(kex, KEY_RSA, 2048);
+ do_kex_with_key(kex, KEY_DSA, 1024);
+#ifdef OPENSSL_HAS_ECC
+ do_kex_with_key(kex, KEY_ECDSA, 256);
+#endif
+ do_kex_with_key(kex, KEY_ED25519, 256);
+}
+
+void
+kex_tests(void)
+{
+ do_kex("curve25519-sha256@libssh.org");
+#ifdef OPENSSL_HAS_ECC
+ do_kex("ecdh-sha2-nistp256");
+ do_kex("ecdh-sha2-nistp384");
+ do_kex("ecdh-sha2-nistp521");
+#endif
+ do_kex("diffie-hellman-group-exchange-sha256");
+ do_kex("diffie-hellman-group-exchange-sha1");
+ do_kex("diffie-hellman-group14-sha1");
+ do_kex("diffie-hellman-group1-sha1");
+}
diff --git a/crypto/openssh/regress/unittests/kex/tests.c b/crypto/openssh/regress/unittests/kex/tests.c
new file mode 100644
index 0000000..e7036ec
--- /dev/null
+++ b/crypto/openssh/regress/unittests/kex/tests.c
@@ -0,0 +1,14 @@
+/* $OpenBSD: tests.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */
+/*
+ * Placed in the public domain
+ */
+
+#include "../test_helper/test_helper.h"
+
+void kex_tests(void);
+
+void
+tests(void)
+{
+ kex_tests();
+}
diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
index 0c4c71e..a68e132 100644
--- a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
+++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
@@ -32,8 +32,6 @@ void
sshbuf_getput_crypto_tests(void)
{
struct sshbuf *p1;
- const u_char *d;
- size_t s;
BIGNUM *bn, *bn2;
/* This one has num_bits != num_bytes * 8 to test bignum1 encoding */
const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10";
@@ -48,7 +46,9 @@ sshbuf_getput_crypto_tests(void)
0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
0x7f, 0xff, 0x11
};
-#ifdef OPENSSL_HAS_NISTP256
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
+ const u_char *d;
+ size_t s;
BIGNUM *bn_x, *bn_y;
int ec256_nid = NID_X9_62_prime256v1;
char *ec256_x = "0C828004839D0106AA59575216191357"
@@ -352,7 +352,7 @@ sshbuf_getput_crypto_tests(void)
sshbuf_free(p1);
TEST_DONE();
-#ifdef OPENSSL_HAS_NISTP256
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
TEST_START("sshbuf_put_ec");
eck = EC_KEY_new_by_curve_name(ec256_nid);
ASSERT_PTR_NE(eck, NULL);
diff --git a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
index 8c3269b..c6b5c29 100644
--- a/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
+++ b/crypto/openssh/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
@@ -33,7 +33,7 @@ attempt_parse_blob(u_char *blob, size_t len)
{
struct sshbuf *p1;
BIGNUM *bn;
-#ifdef OPENSSL_HAS_NISTP256
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
EC_KEY *eck;
#endif
u_char *s;
@@ -60,7 +60,7 @@ attempt_parse_blob(u_char *blob, size_t len)
bn = BN_new();
sshbuf_get_bignum2(p1, bn);
BN_clear_free(bn);
-#ifdef OPENSSL_HAS_NISTP256
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
ASSERT_PTR_NE(eck, NULL);
sshbuf_get_eckey(p1, eck);
diff --git a/crypto/openssh/regress/unittests/sshkey/common.c b/crypto/openssh/regress/unittests/sshkey/common.c
index 0a4b3a9..b598f05 100644
--- a/crypto/openssh/regress/unittests/sshkey/common.c
+++ b/crypto/openssh/regress/unittests/sshkey/common.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: common.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
+/* $OpenBSD: common.c,v 1.2 2015/01/08 13:10:58 djm Exp $ */
/*
* Helpers for key API tests
*
@@ -44,7 +44,7 @@ load_file(const char *name)
ASSERT_PTR_NE(ret = sshbuf_new(), NULL);
ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1);
- ASSERT_INT_EQ(sshkey_load_file(fd, name, ret), 0);
+ ASSERT_INT_EQ(sshkey_load_file(fd, ret), 0);
close(fd);
return ret;
}
diff --git a/crypto/openssh/regress/unittests/sshkey/mktestdata.sh b/crypto/openssh/regress/unittests/sshkey/mktestdata.sh
index ee1fe39..09165af 100755
--- a/crypto/openssh/regress/unittests/sshkey/mktestdata.sh
+++ b/crypto/openssh/regress/unittests/sshkey/mktestdata.sh
@@ -1,5 +1,5 @@
#!/bin/sh
-# $OpenBSD: mktestdata.sh,v 1.3 2014/07/22 23:57:40 dtucker Exp $
+# $OpenBSD: mktestdata.sh,v 1.4 2015/01/18 19:54:46 djm Exp $
PW=mekmitasdigoat
@@ -187,4 +187,6 @@ ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb
ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb
ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb
+# XXX Extend ssh-keygen to do detached signatures (better to test/fuzz against)
+
echo "$PW" > pw
diff --git a/crypto/openssh/regress/unittests/sshkey/test_file.c b/crypto/openssh/regress/unittests/sshkey/test_file.c
index 764f7fb..fa95212 100644
--- a/crypto/openssh/regress/unittests/sshkey/test_file.c
+++ b/crypto/openssh/regress/unittests/sshkey/test_file.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_file.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
+/* $OpenBSD: test_file.c,v 1.3 2015/03/04 23:22:35 djm Exp $ */
/*
* Regress test for sshkey.h key management API
*
@@ -33,6 +33,7 @@
#include "authfile.h"
#include "sshkey.h"
#include "sshbuf.h"
+#include "digest.h"
#include "common.h"
@@ -50,6 +51,7 @@ sshkey_file_tests(void)
pw = load_text_file("pw");
TEST_DONE();
+#ifdef WITH_SSH1
TEST_START("parse RSA1 from private");
buf = load_file("rsa1_1");
ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa1_1",
@@ -81,7 +83,7 @@ sshkey_file_tests(void)
TEST_START("RSA1 key hex fingerprint");
buf = load_text_file("rsa1_1.fp");
- cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -90,7 +92,7 @@ sshkey_file_tests(void)
TEST_START("RSA1 key bubblebabble fingerprint");
buf = load_text_file("rsa1_1.fp.bb");
- cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -98,6 +100,7 @@ sshkey_file_tests(void)
TEST_DONE();
sshkey_free(k1);
+#endif
TEST_START("parse RSA from private");
buf = load_file("rsa_1");
@@ -164,7 +167,7 @@ sshkey_file_tests(void)
TEST_START("RSA key hex fingerprint");
buf = load_text_file("rsa_1.fp");
- cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -173,7 +176,7 @@ sshkey_file_tests(void)
TEST_START("RSA cert hex fingerprint");
buf = load_text_file("rsa_1-cert.fp");
- cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -183,7 +186,7 @@ sshkey_file_tests(void)
TEST_START("RSA key bubblebabble fingerprint");
buf = load_text_file("rsa_1.fp.bb");
- cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -257,7 +260,7 @@ sshkey_file_tests(void)
TEST_START("DSA key hex fingerprint");
buf = load_text_file("dsa_1.fp");
- cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -266,7 +269,7 @@ sshkey_file_tests(void)
TEST_START("DSA cert hex fingerprint");
buf = load_text_file("dsa_1-cert.fp");
- cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -276,7 +279,7 @@ sshkey_file_tests(void)
TEST_START("DSA key bubblebabble fingerprint");
buf = load_text_file("dsa_1.fp.bb");
- cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -357,7 +360,7 @@ sshkey_file_tests(void)
TEST_START("ECDSA key hex fingerprint");
buf = load_text_file("ecdsa_1.fp");
- cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -366,7 +369,7 @@ sshkey_file_tests(void)
TEST_START("ECDSA cert hex fingerprint");
buf = load_text_file("ecdsa_1-cert.fp");
- cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -376,7 +379,7 @@ sshkey_file_tests(void)
TEST_START("ECDSA key bubblebabble fingerprint");
buf = load_text_file("ecdsa_1.fp.bb");
- cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -424,7 +427,7 @@ sshkey_file_tests(void)
TEST_START("Ed25519 key hex fingerprint");
buf = load_text_file("ed25519_1.fp");
- cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -433,7 +436,7 @@ sshkey_file_tests(void)
TEST_START("Ed25519 cert hex fingerprint");
buf = load_text_file("ed25519_1-cert.fp");
- cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX);
+ cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
@@ -443,7 +446,7 @@ sshkey_file_tests(void)
TEST_START("Ed25519 key bubblebabble fingerprint");
buf = load_text_file("ed25519_1.fp.bb");
- cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE);
+ cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
ASSERT_PTR_NE(cp, NULL);
ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
sshbuf_free(buf);
diff --git a/crypto/openssh/regress/unittests/sshkey/test_fuzz.c b/crypto/openssh/regress/unittests/sshkey/test_fuzz.c
index a3f61a6..1f08a2e4 100644
--- a/crypto/openssh/regress/unittests/sshkey/test_fuzz.c
+++ b/crypto/openssh/regress/unittests/sshkey/test_fuzz.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_fuzz.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
+/* $OpenBSD: test_fuzz.c,v 1.4 2015/03/04 23:22:35 djm Exp $ */
/*
* Fuzz tests for key parsing
*
@@ -53,7 +53,7 @@ public_fuzz(struct sshkey *k)
struct fuzz *fuzz;
ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
- ASSERT_INT_EQ(sshkey_to_blob_buf(k, buf), 0);
+ ASSERT_INT_EQ(sshkey_putb(k, buf), 0);
/* XXX need a way to run the tests in "slow, but complete" mode */
fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */
FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */
@@ -87,8 +87,11 @@ sig_fuzz(struct sshkey *k)
free(sig);
TEST_ONERROR(onerror, fuzz);
for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
- sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
- c, sizeof(c), 0);
+ /* Ensure 1-bit difference at least */
+ if (fuzz_matches_original(fuzz))
+ continue;
+ ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
+ c, sizeof(c), 0), 0);
}
fuzz_cleanup(fuzz);
}
@@ -101,6 +104,7 @@ sshkey_fuzz_tests(void)
struct fuzz *fuzz;
int r;
+#ifdef WITH_SSH1
TEST_START("fuzz RSA1 private");
buf = load_file("rsa1_1");
fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
@@ -144,6 +148,7 @@ sshkey_fuzz_tests(void)
sshbuf_free(fuzzed);
fuzz_cleanup(fuzz);
TEST_DONE();
+#endif
TEST_START("fuzz RSA private");
buf = load_file("rsa_1");
diff --git a/crypto/openssh/regress/unittests/sshkey/test_sshkey.c b/crypto/openssh/regress/unittests/sshkey/test_sshkey.c
index ef0c679..ad10c9b 100644
--- a/crypto/openssh/regress/unittests/sshkey/test_sshkey.c
+++ b/crypto/openssh/regress/unittests/sshkey/test_sshkey.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_sshkey.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */
+/* $OpenBSD: test_sshkey.c,v 1.3 2015/01/26 06:11:28 djm Exp $ */
/*
* Regress test for sshkey.h key management API
*
@@ -19,7 +19,7 @@
#include <openssl/bn.h>
#include <openssl/rsa.h>
#include <openssl/dsa.h>
-#ifdef OPENSSL_HAS_NISTP256
+#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
# include <openssl/ec.h>
#endif
@@ -37,6 +37,20 @@
void sshkey_tests(void);
static void
+put_opt(struct sshbuf *b, const char *name, const char *value)
+{
+ struct sshbuf *sect;
+
+ sect = sshbuf_new();
+ ASSERT_PTR_NE(sect, NULL);
+ ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0);
+ if (value != NULL)
+ ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0);
+ ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0);
+ sshbuf_free(sect);
+}
+
+static void
build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
const struct sshkey *sign_key, const struct sshkey *ca_key)
{
@@ -45,25 +59,31 @@ build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
size_t siglen;
ca_buf = sshbuf_new();
- ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0);
+ ASSERT_PTR_NE(ca_buf, NULL);
+ ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0);
/*
* Get the public key serialisation by rendering the key and skipping
* the type string. This is a bit of a hack :/
*/
pk = sshbuf_new();
- ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0);
+ ASSERT_PTR_NE(pk, NULL);
+ ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0);
ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);
principals = sshbuf_new();
+ ASSERT_PTR_NE(principals, NULL);
ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);
critopts = sshbuf_new();
- /* XXX fill this in */
+ ASSERT_PTR_NE(critopts, NULL);
+ put_opt(critopts, "force-command", "/usr/local/bin/nethack");
+ put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1");
exts = sshbuf_new();
- /* XXX fill this in */
+ ASSERT_PTR_NE(exts, NULL);
+ put_opt(critopts, "permit-X11-forwarding", NULL);
ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */
@@ -90,10 +110,74 @@ build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
sshbuf_free(pk);
}
+static void
+signature_test(struct sshkey *k, struct sshkey *bad, const u_char *d, size_t l)
+{
+ size_t len;
+ u_char *sig;
+
+ ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, 0), 0);
+ ASSERT_SIZE_T_GT(len, 8);
+ ASSERT_PTR_NE(sig, NULL);
+ ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, 0), 0);
+ ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, 0), 0);
+ /* Fuzz test is more comprehensive, this is just a smoke test */
+ sig[len - 5] ^= 0x10;
+ ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, 0), 0);
+ free(sig);
+}
+
+static void
+banana(u_char *s, size_t l)
+{
+ size_t o;
+ const u_char the_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a' };
+
+ for (o = 0; o < l; o += sizeof(the_banana)) {
+ if (l - o < sizeof(the_banana)) {
+ memcpy(s + o, "nanananana", l - o);
+ break;
+ }
+ memcpy(s + o, banana, sizeof(the_banana));
+ }
+}
+
+static void
+signature_tests(struct sshkey *k, struct sshkey *bad)
+{
+ u_char i, buf[2049];
+ size_t lens[] = {
+ 1, 2, 7, 8, 9, 15, 16, 17, 31, 32, 33, 127, 128, 129,
+ 255, 256, 257, 1023, 1024, 1025, 2047, 2048, 2049
+ };
+
+ for (i = 0; i < (sizeof(lens)/sizeof(lens[0])); i++) {
+ test_subtest_info("%s key, banana length %zu",
+ sshkey_type(k), lens[i]);
+ banana(buf, lens[i]);
+ signature_test(k, bad, buf, lens[i]);
+ }
+}
+
+static struct sshkey *
+get_private(const char *n)
+{
+ struct sshbuf *b;
+ struct sshkey *ret;
+
+ b = load_file(n);
+ ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", n, &ret, NULL), 0);
+ sshbuf_free(b);
+ return ret;
+}
+
void
sshkey_tests(void)
{
- struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *ke, *kf;
+ struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *kf;
+#ifdef OPENSSL_HAS_ECC
+ struct sshkey *ke;
+#endif
struct sshbuf *b;
TEST_START("new invalid");
@@ -136,12 +220,14 @@ sshkey_tests(void)
sshkey_free(k1);
TEST_DONE();
+#ifdef OPENSSL_HAS_ECC
TEST_START("new/free KEY_ECDSA");
k1 = sshkey_new(KEY_ECDSA);
ASSERT_PTR_NE(k1, NULL);
ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */
sshkey_free(k1);
TEST_DONE();
+#endif
TEST_START("new/free KEY_ED25519");
k1 = sshkey_new(KEY_ED25519);
@@ -192,12 +278,14 @@ sshkey_tests(void)
sshkey_free(k1);
TEST_DONE();
+#ifdef OPENSSL_HAS_ECC
TEST_START("generate KEY_ECDSA wrong bits");
ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1),
SSH_ERR_INVALID_ARGUMENT);
ASSERT_PTR_EQ(k1, NULL);
sshkey_free(k1);
TEST_DONE();
+#endif
TEST_START("generate KEY_RSA");
ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &kr), 0);
@@ -332,26 +420,100 @@ sshkey_tests(void)
#endif
sshkey_free(kf);
-/* XXX certify test */
-/* XXX sign test */
-/* XXX verify test */
+ TEST_START("certify key");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"),
+ &k1, NULL), 0);
+ k2 = get_private("ed25519_2");
+ ASSERT_INT_EQ(sshkey_to_certified(k1, 0), 0);
+ ASSERT_PTR_NE(k1->cert, NULL);
+ k1->cert->type = SSH2_CERT_TYPE_USER;
+ k1->cert->serial = 1234;
+ k1->cert->key_id = strdup("estragon");
+ ASSERT_PTR_NE(k1->cert->key_id, NULL);
+ k1->cert->principals = calloc(4, sizeof(*k1->cert->principals));
+ ASSERT_PTR_NE(k1->cert->principals, NULL);
+ k1->cert->principals[0] = strdup("estragon");
+ k1->cert->principals[1] = strdup("vladimir");
+ k1->cert->principals[2] = strdup("pozzo");
+ k1->cert->principals[3] = strdup("lucky");
+ ASSERT_PTR_NE(k1->cert->principals[0], NULL);
+ ASSERT_PTR_NE(k1->cert->principals[1], NULL);
+ ASSERT_PTR_NE(k1->cert->principals[2], NULL);
+ ASSERT_PTR_NE(k1->cert->principals[3], NULL);
+ k1->cert->valid_after = 0;
+ k1->cert->valid_before = (u_int64_t)-1;
+ k1->cert->critical = sshbuf_new();
+ ASSERT_PTR_NE(k1->cert->critical, NULL);
+ k1->cert->extensions = sshbuf_new();
+ ASSERT_PTR_NE(k1->cert->extensions, NULL);
+ put_opt(k1->cert->critical, "force-command", "/usr/bin/true");
+ put_opt(k1->cert->critical, "source-address", "127.0.0.1");
+ put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL);
+ put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL);
+ ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0);
+ ASSERT_INT_EQ(sshkey_certify(k1, k2), 0);
+ b = sshbuf_new();
+ ASSERT_PTR_NE(b, NULL);
+ ASSERT_INT_EQ(sshkey_putb(k1, b), 0);
+ ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k3), 0);
+
+ sshkey_free(k1);
+ sshkey_free(k2);
+ sshkey_free(k3);
+ sshbuf_reset(b);
+ TEST_DONE();
+
+ TEST_START("sign and verify RSA");
+ k1 = get_private("rsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+ TEST_START("sign and verify DSA");
+ k1 = get_private("dsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+
+#ifdef OPENSSL_HAS_ECC
+ TEST_START("sign and verify ECDSA");
+ k1 = get_private("ecdsa_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
+#endif
+
+ TEST_START("sign and verify ED25519");
+ k1 = get_private("ed25519_1");
+ ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_2.pub"), &k2,
+ NULL), 0);
+ signature_tests(k1, k2);
+ sshkey_free(k1);
+ sshkey_free(k2);
+ TEST_DONE();
TEST_START("nested certificate");
ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
NULL), 0);
- b = load_file("rsa_2");
- ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", "rsa_1",
- &k3, NULL), 0);
- sshbuf_reset(b);
+ k3 = get_private("ed25519_2");
build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1);
ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
ASSERT_PTR_EQ(k4, NULL);
- sshbuf_free(b);
sshkey_free(k1);
sshkey_free(k2);
sshkey_free(k3);
+ sshbuf_free(b);
TEST_DONE();
}
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp
index 56ee1f8..b26145b 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1-cert.fp
@@ -1 +1 @@
-5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74
+MD5:5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp
index 56ee1f8..b26145b 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_1.fp
@@ -1 +1 @@
-5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74
+MD5:5a:4a:41:8c:4e:fa:4c:52:19:f9:39:49:31:fb:fd:74
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp
index ba9de82..8226574 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/dsa_2.fp
@@ -1 +1 @@
-72:5f:50:6b:e5:64:c5:62:21:92:3f:8b:10:9b:9f:1a
+MD5:72:5f:50:6b:e5:64:c5:62:21:92:3f:8b:10:9b:9f:1a
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
index a56dbc8..c3d747a 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
@@ -1 +1 @@
-f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44
+MD5:f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp
index a56dbc8..c3d747a 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_1.fp
@@ -1 +1 @@
-f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44
+MD5:f7:be:4c:02:65:ed:4c:11:af:ab:a8:dd:0a:92:e7:44
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp
index eb4bbdf..fe7526b 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/ecdsa_2.fp
@@ -1 +1 @@
-51:bd:ff:2b:6d:26:9b:90:f9:e1:4a:ca:a0:29:8e:70
+MD5:51:bd:ff:2b:6d:26:9b:90:f9:e1:4a:ca:a0:29:8e:70
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
index e6d23d0..fbde87a 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
@@ -1 +1 @@
-19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f
+MD5:19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp
index e6d23d0..fbde87a 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_1.fp
@@ -1 +1 @@
-19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f
+MD5:19:08:8e:7e:4d:e5:de:86:2a:09:47:65:eb:0a:51:2f
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp
index 02c684f..ec1cdbb 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/ed25519_2.fp
@@ -1 +1 @@
-5c:c9:ae:a3:0c:aa:28:29:b8:fc:7c:64:ba:6e:e9:c9
+MD5:5c:c9:ae:a3:0c:aa:28:29:b8:fc:7c:64:ba:6e:e9:c9
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp
index 782ece0..2e1068c 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_1.fp
@@ -1 +1 @@
-a8:82:9b:98:c5:e6:19:d6:83:39:9f:4d:3a:8f:7c:80
+MD5:a8:82:9b:98:c5:e6:19:d6:83:39:9f:4d:3a:8f:7c:80
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp
index c332537..cd00393 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa1_2.fp
@@ -1 +1 @@
-c0:83:1c:97:5f:32:77:7e:e4:e3:e9:29:b9:eb:76:9c
+MD5:c0:83:1c:97:5f:32:77:7e:e4:e3:e9:29:b9:eb:76:9c
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp
index bf9c2e3..1cf780d 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1-cert.fp
@@ -1 +1 @@
-be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b
+MD5:be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp
index bf9c2e3..1cf780d 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_1.fp
@@ -1 +1 @@
-be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b
+MD5:be:27:4c:16:27:f5:04:03:62:a8:b7:91:df:a5:b1:3b
diff --git a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp
index 53939f4..8d43676 100644
--- a/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp
+++ b/crypto/openssh/regress/unittests/sshkey/testdata/rsa_2.fp
@@ -1 +1 @@
-fb:8f:7b:26:3d:42:40:ef:ed:f1:ed:ee:66:9e:ba:b0
+MD5:fb:8f:7b:26:3d:42:40:ef:ed:f1:ed:ee:66:9e:ba:b0
diff --git a/crypto/openssh/regress/unittests/test_helper/Makefile b/crypto/openssh/regress/unittests/test_helper/Makefile
index 3e90903..5b3894c 100644
--- a/crypto/openssh/regress/unittests/test_helper/Makefile
+++ b/crypto/openssh/regress/unittests/test_helper/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $
+# $OpenBSD: Makefile,v 1.2 2015/01/20 22:58:57 djm Exp $
LIB= test_helper
SRCS= test_helper.c fuzz.c
@@ -7,6 +7,9 @@ DEBUGLIBS= no
NOPROFILE= yes
NOPIC= yes
+# Hack to allow building with SUBDIR in ../../Makefile
+regress: all
+
install:
@echo -n
diff --git a/crypto/openssh/regress/unittests/test_helper/fuzz.c b/crypto/openssh/regress/unittests/test_helper/fuzz.c
index 77c6e7c..99f1d03 100644
--- a/crypto/openssh/regress/unittests/test_helper/fuzz.c
+++ b/crypto/openssh/regress/unittests/test_helper/fuzz.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: fuzz.c,v 1.3 2014/05/02 09:41:32 andre Exp $ */
+/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@@ -20,6 +20,7 @@
#include "includes.h"
#include <sys/types.h>
+#include <sys/uio.h>
#include <assert.h>
#include <ctype.h>
@@ -29,9 +30,11 @@
#endif
#include <stdlib.h>
#include <string.h>
-#include <assert.h>
+#include <signal.h>
+#include <unistd.h>
#include "test_helper.h"
+#include "atomicio.h"
/* #define FUZZ_DEBUG */
@@ -96,60 +99,66 @@ fuzz_ntop(u_int n)
}
}
-void
-fuzz_dump(struct fuzz *fuzz)
+static int
+fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
{
- u_char *p = fuzz_ptr(fuzz);
- size_t i, j, len = fuzz_len(fuzz);
+ if (fuzz == NULL)
+ return -1;
switch (fuzz->strategy) {
case FUZZ_1_BIT_FLIP:
- fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n",
+ snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
fuzz_ntop(fuzz->strategy),
fuzz->o1, fuzz->slen * 8, fuzz->o1);
- break;
+ return 0;
case FUZZ_2_BIT_FLIP:
- fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n",
+ snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
fuzz_ntop(fuzz->strategy),
(((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
fuzz->o1, fuzz->o2);
- break;
+ return 0;
case FUZZ_1_BYTE_FLIP:
- fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n",
+ snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
fuzz_ntop(fuzz->strategy),
fuzz->o1, fuzz->slen, fuzz->o1);
- break;
+ return 0;
case FUZZ_2_BYTE_FLIP:
- fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n",
+ snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
fuzz_ntop(fuzz->strategy),
(((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
((fuzz_ullong)fuzz->slen) * fuzz->slen,
fuzz->o1, fuzz->o2);
- break;
+ return 0;
case FUZZ_TRUNCATE_START:
- fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
+ snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
fuzz_ntop(fuzz->strategy),
fuzz->o1, fuzz->slen, fuzz->o1);
- break;
+ return 0;
case FUZZ_TRUNCATE_END:
- fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n",
+ snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
fuzz_ntop(fuzz->strategy),
fuzz->o1, fuzz->slen, fuzz->o1);
- break;
+ return 0;
case FUZZ_BASE64:
assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
- fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n",
+ snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
fuzz_ntop(fuzz->strategy),
(fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
fuzz->slen * (fuzz_ullong)64, fuzz->o1,
fuzz_b64chars[fuzz->o2]);
- break;
+ return 0;
default:
+ return -1;
abort();
}
+}
+
+static void
+dump(u_char *p, size_t len)
+{
+ size_t i, j;
- fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len);
for (i = 0; i < len; i += 16) {
fprintf(stderr, "%.4zd: ", i);
for (j = i; j < i + 16; j++) {
@@ -171,6 +180,39 @@ fuzz_dump(struct fuzz *fuzz)
}
}
+void
+fuzz_dump(struct fuzz *fuzz)
+{
+ char buf[256];
+
+ if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
+ fprintf(stderr, "%s: fuzz invalid\n", __func__);
+ abort();
+ }
+ fputs(buf, stderr);
+ fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
+ dump(fuzz->seed, fuzz->slen);
+ fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
+ dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
+}
+
+#ifdef SIGINFO
+static struct fuzz *last_fuzz;
+
+static void
+siginfo(int unused __attribute__((__unused__)))
+{
+ char buf[256];
+
+ test_info(buf, sizeof(buf));
+ atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+ if (last_fuzz != NULL) {
+ fuzz_fmt(last_fuzz, buf, sizeof(buf));
+ atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+ }
+}
+#endif
+
struct fuzz *
fuzz_begin(u_int strategies, const void *p, size_t l)
{
@@ -190,6 +232,12 @@ fuzz_begin(u_int strategies, const void *p, size_t l)
FUZZ_DBG(("begin, ret = %p", ret));
fuzz_next(ret);
+
+#ifdef SIGINFO
+ last_fuzz = ret;
+ signal(SIGINFO, siginfo);
+#endif
+
return ret;
}
@@ -197,6 +245,10 @@ void
fuzz_cleanup(struct fuzz *fuzz)
{
FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
+#ifdef SIGINFO
+ last_fuzz = NULL;
+ signal(SIGINFO, SIG_DFL);
+#endif
assert(fuzz != NULL);
assert(fuzz->seed != NULL);
assert(fuzz->fuzzed != NULL);
@@ -326,6 +378,14 @@ fuzz_next(struct fuzz *fuzz)
}
int
+fuzz_matches_original(struct fuzz *fuzz)
+{
+ if (fuzz_len(fuzz) != fuzz->slen)
+ return 0;
+ return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
+}
+
+int
fuzz_done(struct fuzz *fuzz)
{
FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
diff --git a/crypto/openssh/regress/unittests/test_helper/test_helper.c b/crypto/openssh/regress/unittests/test_helper/test_helper.c
index d0bc678..26ca26b 100644
--- a/crypto/openssh/regress/unittests/test_helper/test_helper.c
+++ b/crypto/openssh/regress/unittests/test_helper/test_helper.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_helper.c,v 1.2 2014/05/02 09:41:32 andre Exp $ */
+/* $OpenBSD: test_helper.c,v 1.6 2015/03/03 20:42:49 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@@ -21,6 +21,7 @@
#include <sys/types.h>
#include <sys/param.h>
+#include <sys/uio.h>
#include <fcntl.h>
#include <stdio.h>
@@ -31,6 +32,7 @@
#include <string.h>
#include <assert.h>
#include <unistd.h>
+#include <signal.h>
#include <openssl/bn.h>
@@ -39,6 +41,7 @@
#endif
#include "test_helper.h"
+#include "atomicio.h"
#define TEST_CHECK_INT(r, pred) do { \
switch (pred) { \
@@ -111,6 +114,7 @@ static u_int test_number = 0;
static test_onerror_func_t *test_onerror = NULL;
static void *onerror_ctx = NULL;
static const char *data_dir = NULL;
+static char subtest_info[512];
int
main(int argc, char **argv)
@@ -180,13 +184,36 @@ test_data_file(const char *name)
}
void
+test_info(char *s, size_t len)
+{
+ snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number,
+ active_test_name == NULL ? "<none>" : active_test_name,
+ *subtest_info != '\0' ? " - " : "", subtest_info);
+}
+
+#ifdef SIGINFO
+static void
+siginfo(int unused __attribute__((__unused__)))
+{
+ char buf[256];
+
+ test_info(buf, sizeof(buf));
+ atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
+}
+#endif
+
+void
test_start(const char *n)
{
assert(active_test_name == NULL);
assert((active_test_name = strdup(n)) != NULL);
+ *subtest_info = '\0';
if (verbose_mode)
printf("test %u - \"%s\": ", test_number, active_test_name);
test_number++;
+#ifdef SIGINFO
+ signal(SIGINFO, siginfo);
+#endif
}
void
@@ -199,6 +226,7 @@ set_onerror_func(test_onerror_func_t *f, void *ctx)
void
test_done(void)
{
+ *subtest_info = '\0';
assert(active_test_name != NULL);
free(active_test_name);
active_test_name = NULL;
@@ -211,6 +239,16 @@ test_done(void)
}
void
+test_subtest_info(const char *fmt, ...)
+{
+ va_list ap;
+
+ va_start(ap, fmt);
+ vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap);
+ va_end(ap);
+}
+
+void
ssl_err_check(const char *file, int line)
{
long openssl_error = ERR_get_error();
@@ -256,8 +294,9 @@ static void
test_header(const char *file, int line, const char *a1, const char *a2,
const char *name, enum test_predicate pred)
{
- fprintf(stderr, "\n%s:%d test #%u \"%s\"\n",
- file, line, test_number, active_test_name);
+ fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n",
+ file, line, test_number, active_test_name,
+ *subtest_info != '\0' ? " - " : "", subtest_info);
fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
name, pred_name(pred), a1,
a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
@@ -280,8 +319,13 @@ void
assert_string(const char *file, int line, const char *a1, const char *a2,
const char *aa1, const char *aa2, enum test_predicate pred)
{
- int r = strcmp(aa1, aa2);
+ int r;
+ /* Verify pointers are not NULL */
+ assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
+ assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
+
+ r = strcmp(aa1, aa2);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, a2, "STRING", pred);
fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
@@ -310,8 +354,15 @@ void
assert_mem(const char *file, int line, const char *a1, const char *a2,
const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
{
- int r = memcmp(aa1, aa2, l);
+ int r;
+ if (l == 0)
+ return;
+ /* If length is >0, then verify pointers are not NULL */
+ assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
+ assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
+
+ r = memcmp(aa1, aa2, l);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, a2, "STRING", pred);
fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l);
@@ -338,11 +389,15 @@ assert_mem_filled(const char *file, int line, const char *a1,
const void *aa1, u_char v, size_t l, enum test_predicate pred)
{
size_t where = -1;
- int r = memvalcmp(aa1, v, l, &where);
+ int r;
char tmp[64];
if (l == 0)
return;
+ /* If length is >0, then verify the pointer is not NULL */
+ assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
+
+ r = memvalcmp(aa1, v, l, &where);
TEST_CHECK_INT(r, pred);
test_header(file, line, a1, NULL, "MEM_ZERO", pred);
fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
diff --git a/crypto/openssh/regress/unittests/test_helper/test_helper.h b/crypto/openssh/regress/unittests/test_helper/test_helper.h
index a398c61..1d9c669 100644
--- a/crypto/openssh/regress/unittests/test_helper/test_helper.h
+++ b/crypto/openssh/regress/unittests/test_helper/test_helper.h
@@ -1,4 +1,4 @@
-/* $OpenBSD: test_helper.h,v 1.3 2014/05/02 09:41:32 andre Exp $ */
+/* $OpenBSD: test_helper.h,v 1.6 2015/01/18 19:52:44 djm Exp $ */
/*
* Copyright (c) 2011 Damien Miller <djm@mindrot.org>
*
@@ -40,8 +40,11 @@ void tests(void);
const char *test_data_file(const char *name);
void test_start(const char *n);
+void test_info(char *s, size_t len);
void set_onerror_func(test_onerror_func_t *f, void *ctx);
void test_done(void);
+void test_subtest_info(const char *fmt, ...)
+ __attribute__((format(printf, 1, 2)));
void ssl_err_check(const char *file, int line);
void assert_bignum(const char *file, int line,
const char *a1, const char *a2,
@@ -280,6 +283,13 @@ void fuzz_cleanup(struct fuzz *fuzz);
/* Prepare the next fuzz case in the series */
void fuzz_next(struct fuzz *fuzz);
+/*
+ * Check whether this fuzz case is identical to the original
+ * This is slow, but useful if the caller needs to ensure that all tests
+ * generated change the input (e.g. when fuzzing signatures).
+ */
+int fuzz_matches_original(struct fuzz *fuzz);
+
/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */
int fuzz_done(struct fuzz *fuzz);
@@ -289,4 +299,5 @@ u_char *fuzz_ptr(struct fuzz *fuzz);
/* Dump the current fuzz case to stderr */
void fuzz_dump(struct fuzz *fuzz);
+
#endif /* _TEST_HELPER_H */
diff --git a/crypto/openssh/regress/valgrind-unit.sh b/crypto/openssh/regress/valgrind-unit.sh
new file mode 100755
index 0000000..433cb06
--- /dev/null
+++ b/crypto/openssh/regress/valgrind-unit.sh
@@ -0,0 +1,20 @@
+#!/bin/sh
+
+UNIT_BINARY="$1"
+shift
+UNIT_ARGS="$@"
+
+test "x$OBJ" = "x" && OBJ=$PWD
+
+# This mostly replicates the logic in test-exec.sh for running the
+# regress tests under valgrind.
+VG_TEST=`basename $UNIT_BINARY`
+VG_LOG="$OBJ/valgrind-out/${VG_TEST}.%p"
+VG_OPTS="--track-origins=yes --leak-check=full --log-file=${VG_LOG}"
+VG_OPTS="$VG_OPTS --trace-children=yes"
+VG_PATH="valgrind"
+if [ "x$VALGRIND_PATH" != "x" ]; then
+ VG_PATH="$VALGRIND_PATH"
+fi
+
+exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS
diff --git a/crypto/openssh/regress/yes-head.sh b/crypto/openssh/regress/yes-head.sh
index a8e6bc8..1fc7542 100644
--- a/crypto/openssh/regress/yes-head.sh
+++ b/crypto/openssh/regress/yes-head.sh
@@ -1,9 +1,9 @@
-# $OpenBSD: yes-head.sh,v 1.4 2002/03/15 13:08:56 markus Exp $
+# $OpenBSD: yes-head.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
# Placed in the Public Domain.
tid="yes pipe head"
-for p in 1 2; do
+for p in ${SSH_PROTOCOLS}; do
lines=`${SSH} -$p -F $OBJ/ssh_proxy thishost 'sh -c "while true;do echo yes;done | _POSIX2_VERSION=199209 head -2000"' | (sleep 3 ; wc -l)`
if [ $? -ne 0 ]; then
fail "yes|head test failed"
OpenPOWER on IntegriCloud