summaryrefslogtreecommitdiff
path: root/regress
diff options
context:
space:
mode:
authorColin Watson <cjwatson@debian.org>2015-08-19 14:23:51 +0100
committerColin Watson <cjwatson@debian.org>2015-08-19 16:48:11 +0100
commit0f0841b2d28b7463267d4d91577e72e3340a1d3a (patch)
treeba55fcd2b6e2cc22b30f5afb561dbb3da4c8b6c7 /regress
parentf2a5f5dae656759efb0b76c3d94890b65c197a02 (diff)
parent8698446b972003b63dfe5dcbdb86acfe986afb85 (diff)
New upstream release (6.8p1).
Diffstat (limited to 'regress')
-rw-r--r--regress/.cvsignore31
-rw-r--r--regress/Makefile47
-rw-r--r--regress/agent-pkcs11.sh4
-rw-r--r--regress/agent-timeout.sh4
-rw-r--r--regress/agent.sh8
-rw-r--r--regress/broken-pipe.sh4
-rw-r--r--regress/cert-hostkey.sh111
-rw-r--r--regress/cfgmatch.sh23
-rw-r--r--regress/cipher-speed.sh8
-rw-r--r--regress/connect-privsep.sh8
-rw-r--r--regress/connect.sh4
-rw-r--r--regress/dynamic-forward.sh4
-rw-r--r--regress/exit-status.sh4
-rw-r--r--regress/forcecommand.sh26
-rw-r--r--regress/forward-control.sh6
-rw-r--r--regress/forwarding.sh20
-rw-r--r--regress/host-expand.sh4
-rw-r--r--regress/hostkey-agent.sh52
-rw-r--r--regress/hostkey-rotate.sh128
-rw-r--r--regress/integrity.sh6
-rw-r--r--regress/key-options.sh10
-rw-r--r--regress/keygen-change.sh9
-rw-r--r--regress/keygen-knownhosts.sh197
-rw-r--r--regress/keyscan.sh9
-rw-r--r--regress/krl.sh90
-rw-r--r--regress/limit-keytype.sh80
-rw-r--r--regress/localcommand.sh4
-rw-r--r--regress/multiplex.sh25
-rw-r--r--regress/multipubkey.sh66
-rw-r--r--regress/netcat.c1690
-rw-r--r--regress/proto-mismatch.sh6
-rw-r--r--regress/proto-version.sh10
-rw-r--r--regress/proxy-connect.sh6
-rw-r--r--regress/reconfigure.sh31
-rw-r--r--regress/reexec.sh4
-rw-r--r--regress/rekey.sh24
-rw-r--r--regress/sshd-log-wrapper.sh8
-rw-r--r--regress/stderr-data.sh4
-rw-r--r--regress/t11.ok1
-rw-r--r--regress/t4.ok2
-rw-r--r--regress/test-exec.sh88
-rw-r--r--regress/transfer.sh4
-rw-r--r--regress/try-ciphers.sh8
-rw-r--r--regress/unittests/Makefile6
-rw-r--r--regress/unittests/Makefile.inc4
-rw-r--r--regress/unittests/bitmap/Makefile12
-rw-r--r--regress/unittests/bitmap/tests.c135
-rw-r--r--regress/unittests/hostkeys/Makefile12
-rw-r--r--regress/unittests/hostkeys/mktestdata.sh94
-rw-r--r--regress/unittests/hostkeys/test_iterate.c1171
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/dsa_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ecdsa_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/ed25519_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/known_hosts61
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa1_6.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_1.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_2.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_3.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_4.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_5.pub1
-rw-r--r--regress/unittests/hostkeys/testdata/rsa_6.pub1
-rw-r--r--regress/unittests/hostkeys/tests.c16
-rw-r--r--regress/unittests/kex/Makefile14
-rw-r--r--regress/unittests/kex/test_kex.c197
-rw-r--r--regress/unittests/kex/tests.c14
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_crypto.c8
-rw-r--r--regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c4
-rw-r--r--regress/unittests/sshkey/common.c4
-rwxr-xr-xregress/unittests/sshkey/mktestdata.sh4
-rw-r--r--regress/unittests/sshkey/test_file.c33
-rw-r--r--regress/unittests/sshkey/test_fuzz.c13
-rw-r--r--regress/unittests/sshkey/test_sshkey.c192
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1-cert.fp2
-rw-r--r--regress/unittests/sshkey/testdata/dsa_1.fp2
-rw-r--r--regress/unittests/sshkey/testdata/dsa_2.fp2
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1-cert.fp2
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_1.fp2
-rw-r--r--regress/unittests/sshkey/testdata/ecdsa_2.fp2
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1-cert.fp2
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_1.fp2
-rw-r--r--regress/unittests/sshkey/testdata/ed25519_2.fp2
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_1.fp2
-rw-r--r--regress/unittests/sshkey/testdata/rsa1_2.fp2
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1-cert.fp2
-rw-r--r--regress/unittests/sshkey/testdata/rsa_1.fp2
-rw-r--r--regress/unittests/sshkey/testdata/rsa_2.fp2
-rw-r--r--regress/unittests/test_helper/Makefile5
-rw-r--r--regress/unittests/test_helper/fuzz.c102
-rw-r--r--regress/unittests/test_helper/test_helper.c67
-rw-r--r--regress/unittests/test_helper/test_helper.h13
-rwxr-xr-xregress/valgrind-unit.sh20
-rw-r--r--regress/yes-head.sh4
112 files changed, 4851 insertions, 290 deletions
diff --git a/regress/.cvsignore b/regress/.cvsignore
new file mode 100644
index 000000000..3fd25b02e
--- /dev/null
+++ b/regress/.cvsignore
@@ -0,0 +1,31 @@
1*-agent
2*.copy
3*.log
4*.prv
5*.pub
6actual
7authorized_keys_*
8batch
9copy.dd*
10data
11expect
12host.rsa*
13key.*
14known_hosts
15krl-*
16modpipe
17remote_pid
18revoked-*
19revoked-ca
20revoked-keyid
21revoked-serials
22rsa
23rsa1
24sftp-server.sh
25ssh-log-wrapper.sh
26ssh_config
27ssh_proxy*
28sshd_config
29sshd_proxy*
30t*.out
31t*.out[0-9]
diff --git a/regress/Makefile b/regress/Makefile
index 3feb7a997..99a7d60f5 100644
--- a/regress/Makefile
+++ b/regress/Makefile
@@ -1,11 +1,14 @@
1# $OpenBSD: Makefile,v 1.70 2014/06/24 01:14:17 djm Exp $ 1# $OpenBSD: Makefile,v 1.78 2015/01/26 06:12:18 djm Exp $
2 2
3REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t-exec 3REGRESS_TARGETS= unit t1 t2 t3 t4 t5 t6 t7 t8 t9 t10 t11 t12 t-exec
4tests: $(REGRESS_TARGETS) 4tests: prep $(REGRESS_TARGETS)
5 5
6# Interop tests are not run by default 6# Interop tests are not run by default
7interop interop-tests: t-exec-interop 7interop interop-tests: t-exec-interop
8 8
9prep:
10 test "x${USE_VALGRIND}" = "x" || mkdir -p $(OBJ)/valgrind-out
11
9clean: 12clean:
10 for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done 13 for F in $(CLEANFILES); do rm -f $(OBJ)$$F; done
11 test -z "${SUDO}" || ${SUDO} rm -f ${SUDO_CLEAN} 14 test -z "${SUDO}" || ${SUDO} rm -f ${SUDO_CLEAN}
@@ -64,7 +67,14 @@ LTESTS= connect \
64 keys-command \ 67 keys-command \
65 forward-control \ 68 forward-control \
66 integrity \ 69 integrity \
67 krl 70 krl \
71 multipubkey \
72 limit-keytype \
73 hostkey-agent \
74 keygen-knownhosts \
75 hostkey-rotate
76
77
68# dhgex \ 78# dhgex \
69 79
70INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers 80INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
@@ -75,6 +85,7 @@ INTEROP_TESTS= putty-transfer putty-ciphers putty-kex conch-ciphers
75USER!= id -un 85USER!= id -un
76CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \ 86CLEANFILES= t2.out t3.out t6.out1 t6.out2 t7.out t7.out.pub copy.1 copy.2 \
77 t8.out t8.out.pub t9.out t9.out.pub t10.out t10.out.pub \ 87 t8.out t8.out.pub t9.out t9.out.pub t10.out t10.out.pub \
88 t12.out t12.out.pub \
78 authorized_keys_${USER} known_hosts pidfile testdata \ 89 authorized_keys_${USER} known_hosts pidfile testdata \
79 ssh_config sshd_config.orig ssh_proxy sshd_config sshd_proxy \ 90 ssh_config sshd_config.orig ssh_proxy sshd_config sshd_proxy \
80 rsa.pub rsa rsa1.pub rsa1 host.rsa host.rsa1 \ 91 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 \
91 regress.log failed-regress.log ssh-log-wrapper.sh \ 102 regress.log failed-regress.log ssh-log-wrapper.sh \
92 sftp-server.sh sftp-server.log sftp.log setuid-allowed \ 103 sftp-server.sh sftp-server.log sftp.log setuid-allowed \
93 data ed25519-agent ed25519-agent.pub key.ed25519-512 \ 104 data ed25519-agent ed25519-agent.pub key.ed25519-512 \
94 key.ed25519-512.pub 105 key.ed25519-512.pub netcat host_krl_* host_revoked_* \
106 kh.* user_*key* agent-key.* known_hosts.* hkr.*
95 107
96SUDO_CLEAN+= /var/run/testdata_${USER} /var/run/keycommand_${USER} 108SUDO_CLEAN+= /var/run/testdata_${USER} /var/run/keycommand_${USER}
97 109
@@ -119,7 +131,7 @@ t3:
119 ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub 131 ${TEST_SSH_SSHKEYGEN} -if $(OBJ)/t3.out | diff - ${.CURDIR}/rsa_openssh.pub
120 132
121t4: 133t4:
122 ${TEST_SSH_SSHKEYGEN} -lf ${.CURDIR}/rsa_openssh.pub |\ 134 ${TEST_SSH_SSHKEYGEN} -E md5 -lf ${.CURDIR}/rsa_openssh.pub |\
123 awk '{print $$2}' | diff - ${.CURDIR}/t4.ok 135 awk '{print $$2}' | diff - ${.CURDIR}/t4.ok
124 136
125t5: 137t5:
@@ -164,6 +176,16 @@ t10: $(OBJ)/t10.out
164 ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null 176 ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t10.out > /dev/null
165 ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null 177 ${TEST_SSH_SSHKEYGEN} -Bf $(OBJ)/t10.out > /dev/null
166 178
179t11:
180 ${TEST_SSH_SSHKEYGEN} -E sha256 -lf ${.CURDIR}/rsa_openssh.pub |\
181 awk '{print $$2}' | diff - ${.CURDIR}/t11.ok
182
183t12.out:
184 ${TEST_SSH_SSHKEYGEN} -q -t ed25519 -N '' -C 'test-comment-1234' -f $(OBJ)/$@
185
186t12: t12.out
187 ${TEST_SSH_SSHKEYGEN} -lf $(OBJ)/t12.out.pub | grep test-comment-1234 >/dev/null
188
167t-exec: ${LTESTS:=.sh} 189t-exec: ${LTESTS:=.sh}
168 @if [ "x$?" = "x" ]; then exit 0; fi; \ 190 @if [ "x$?" = "x" ]; then exit 0; fi; \
169 for TEST in ""$?; do \ 191 for TEST in ""$?; do \
@@ -184,7 +206,14 @@ interop: ${INTEROP_TARGETS}
184# Unit tests, built by top-level Makefile 206# Unit tests, built by top-level Makefile
185unit: 207unit:
186 set -e ; if test -z "${SKIP_UNIT}" ; then \ 208 set -e ; if test -z "${SKIP_UNIT}" ; then \
187 ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \ 209 V="" ; \
188 ${.OBJDIR}/unittests/sshkey/test_sshkey \ 210 test "x${USE_VALGRIND}" = "x" || \
189 -d ${.CURDIR}//unittests/sshkey/testdata ; \ 211 V=${.CURDIR}/valgrind-unit.sh ; \
212 $$V ${.OBJDIR}/unittests/sshbuf/test_sshbuf ; \
213 $$V ${.OBJDIR}/unittests/sshkey/test_sshkey \
214 -d ${.CURDIR}/unittests/sshkey/testdata ; \
215 $$V ${.OBJDIR}/unittests/bitmap/test_bitmap ; \
216 $$V ${.OBJDIR}/unittests/kex/test_kex ; \
217 $$V ${.OBJDIR}/unittests/hostkeys/test_hostkeys \
218 -d ${.CURDIR}/unittests/hostkeys/testdata ; \
190 fi 219 fi
diff --git a/regress/agent-pkcs11.sh b/regress/agent-pkcs11.sh
index db33ab37e..3aa20c8b1 100644
--- a/regress/agent-pkcs11.sh
+++ b/regress/agent-pkcs11.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: agent-pkcs11.sh,v 1.1 2010/02/08 10:52:47 markus Exp $ 1# $OpenBSD: agent-pkcs11.sh,v 1.2 2015/01/12 11:46:32 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="pkcs11 agent test" 4tid="pkcs11 agent test"
@@ -6,6 +6,8 @@ tid="pkcs11 agent test"
6TEST_SSH_PIN="" 6TEST_SSH_PIN=""
7TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0 7TEST_SSH_PKCS11=/usr/local/lib/soft-pkcs11.so.0.0
8 8
9test -f "$TEST_SSH_PKCS11" || fatal "$TEST_SSH_PKCS11 does not exist"
10
9# setup environment for soft-pkcs11 token 11# setup environment for soft-pkcs11 token
10SOFTPKCS11RC=$OBJ/pkcs11.info 12SOFTPKCS11RC=$OBJ/pkcs11.info
11export SOFTPKCS11RC 13export SOFTPKCS11RC
diff --git a/regress/agent-timeout.sh b/regress/agent-timeout.sh
index 68826594e..9598c2032 100644
--- a/regress/agent-timeout.sh
+++ b/regress/agent-timeout.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: agent-timeout.sh,v 1.2 2013/05/17 01:16:09 dtucker Exp $ 1# $OpenBSD: agent-timeout.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="agent timeout test" 4tid="agent timeout test"
@@ -12,7 +12,7 @@ if [ $r -ne 0 ]; then
12 fail "could not start ssh-agent: exit code $r" 12 fail "could not start ssh-agent: exit code $r"
13else 13else
14 trace "add keys with timeout" 14 trace "add keys with timeout"
15 for t in rsa rsa1; do 15 for t in ${SSH_KEYTYPES}; do
16 ${SSHADD} -t ${SSHAGENT_TIMEOUT} $OBJ/$t > /dev/null 2>&1 16 ${SSHADD} -t ${SSHAGENT_TIMEOUT} $OBJ/$t > /dev/null 2>&1
17 if [ $? -ne 0 ]; then 17 if [ $? -ne 0 ]; then
18 fail "ssh-add did succeed exit code 0" 18 fail "ssh-add did succeed exit code 0"
diff --git a/regress/agent.sh b/regress/agent.sh
index caad3c88e..c5e2794b7 100644
--- a/regress/agent.sh
+++ b/regress/agent.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: agent.sh,v 1.10 2014/02/27 21:21:25 djm Exp $ 1# $OpenBSD: agent.sh,v 1.11 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="simple agent test" 4tid="simple agent test"
@@ -20,7 +20,7 @@ else
20 fi 20 fi
21 trace "overwrite authorized keys" 21 trace "overwrite authorized keys"
22 printf '' > $OBJ/authorized_keys_$USER 22 printf '' > $OBJ/authorized_keys_$USER
23 for t in ed25519 rsa rsa1; do 23 for t in ${SSH_KEYTYPES}; do
24 # generate user key for agent 24 # generate user key for agent
25 rm -f $OBJ/$t-agent 25 rm -f $OBJ/$t-agent
26 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\ 26 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t-agent ||\
@@ -46,7 +46,7 @@ else
46 fi 46 fi
47 47
48 trace "simple connect via agent" 48 trace "simple connect via agent"
49 for p in 1 2; do 49 for p in ${SSH_PROTOCOLS}; do
50 ${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p 50 ${SSH} -$p -F $OBJ/ssh_proxy somehost exit 5$p
51 r=$? 51 r=$?
52 if [ $r -ne 5$p ]; then 52 if [ $r -ne 5$p ]; then
@@ -55,7 +55,7 @@ else
55 done 55 done
56 56
57 trace "agent forwarding" 57 trace "agent forwarding"
58 for p in 1 2; do 58 for p in ${SSH_PROTOCOLS}; do
59 ${SSH} -A -$p -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1 59 ${SSH} -A -$p -F $OBJ/ssh_proxy somehost ${SSHADD} -l > /dev/null 2>&1
60 r=$? 60 r=$?
61 if [ $r -ne 0 ]; then 61 if [ $r -ne 0 ]; then
diff --git a/regress/broken-pipe.sh b/regress/broken-pipe.sh
index c08c849a7..a416f7a3b 100644
--- a/regress/broken-pipe.sh
+++ b/regress/broken-pipe.sh
@@ -1,9 +1,9 @@
1# $OpenBSD: broken-pipe.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ 1# $OpenBSD: broken-pipe.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="broken pipe test" 4tid="broken pipe test"
5 5
6for p in 1 2; do 6for p in ${SSH_PROTOCOLS}; do
7 trace "protocol $p" 7 trace "protocol $p"
8 for i in 1 2 3 4; do 8 for i in 1 2 3 4; do
9 ${SSH} -$p -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true 9 ${SSH} -$p -F $OBJ/ssh_config_config nexthost echo $i 2> /dev/null | true
diff --git a/regress/cert-hostkey.sh b/regress/cert-hostkey.sh
index 1d9e0ed8e..51685dc2b 100644
--- a/regress/cert-hostkey.sh
+++ b/regress/cert-hostkey.sh
@@ -1,21 +1,29 @@
1# $OpenBSD: cert-hostkey.sh,v 1.9 2014/01/26 10:22:10 djm Exp $ 1# $OpenBSD: cert-hostkey.sh,v 1.11 2015/01/19 06:01:32 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="certified host keys" 4tid="certified host keys"
5 5
6rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key* 6rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/host_revoked_*
7rm -f $OBJ/cert_host_key* $OBJ/host_krl_*
7cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak 8cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
8 9
9HOSTS='localhost-with-alias,127.0.0.1,::1' 10HOSTS='localhost-with-alias,127.0.0.1,::1'
10 11
11# Create a CA key and add it to known hosts 12# Create a CA key and add it to known hosts. Ed25519 chosed for speed.
12${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/host_ca_key ||\ 13${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/host_ca_key ||\
13 fail "ssh-keygen of host_ca_key failed" 14 fail "ssh-keygen of host_ca_key failed"
14( 15(
15 printf '@cert-authority ' 16 printf '@cert-authority '
16 printf "$HOSTS " 17 printf "$HOSTS "
17 cat $OBJ/host_ca_key.pub 18 cat $OBJ/host_ca_key.pub
18) > $OBJ/known_hosts-cert 19) > $OBJ/known_hosts-cert.orig
20cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
21
22# Plain text revocation files
23touch $OBJ/host_revoked_empty
24touch $OBJ/host_revoked_plain
25touch $OBJ/host_revoked_cert
26cp $OBJ/host_ca_key.pub $OBJ/host_revoked_ca
19 27
20PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'` 28PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/g;s/^ssh-//'`
21 29
@@ -26,17 +34,33 @@ type_has_legacy() {
26 return 0 34 return 0
27} 35}
28 36
37# Prepare certificate, plain key and CA KRLs
38${SSHKEYGEN} -kf $OBJ/host_krl_empty || fatal "KRL init failed"
39${SSHKEYGEN} -kf $OBJ/host_krl_plain || fatal "KRL init failed"
40${SSHKEYGEN} -kf $OBJ/host_krl_cert || fatal "KRL init failed"
41${SSHKEYGEN} -kf $OBJ/host_krl_ca $OBJ/host_ca_key.pub \
42 || fatal "KRL init failed"
43
29# Generate and sign host keys 44# Generate and sign host keys
45serial=1
30for ktype in $PLAIN_TYPES ; do 46for ktype in $PLAIN_TYPES ; do
31 verbose "$tid: sign host ${ktype} cert" 47 verbose "$tid: sign host ${ktype} cert"
32 # Generate and sign a host key 48 # Generate and sign a host key
33 ${SSHKEYGEN} -q -N '' -t ${ktype} \ 49 ${SSHKEYGEN} -q -N '' -t ${ktype} \
34 -f $OBJ/cert_host_key_${ktype} || \ 50 -f $OBJ/cert_host_key_${ktype} || \
35 fail "ssh-keygen of cert_host_key_${ktype} failed" 51 fatal "ssh-keygen of cert_host_key_${ktype} failed"
36 ${SSHKEYGEN} -h -q -s $OBJ/host_ca_key \ 52 ${SSHKEYGEN} -ukf $OBJ/host_krl_plain \
53 $OBJ/cert_host_key_${ktype}.pub || fatal "KRL update failed"
54 cat $OBJ/cert_host_key_${ktype}.pub >> $OBJ/host_revoked_plain
55 ${SSHKEYGEN} -h -q -s $OBJ/host_ca_key -z $serial \
37 -I "regress host key for $USER" \ 56 -I "regress host key for $USER" \
38 -n $HOSTS $OBJ/cert_host_key_${ktype} || 57 -n $HOSTS $OBJ/cert_host_key_${ktype} ||
39 fail "couldn't sign cert_host_key_${ktype}" 58 fatal "couldn't sign cert_host_key_${ktype}"
59 ${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
60 $OBJ/cert_host_key_${ktype}-cert.pub || \
61 fatal "KRL update failed"
62 cat $OBJ/cert_host_key_${ktype}-cert.pub >> $OBJ/host_revoked_cert
63 serial=`expr $serial + 1`
40 type_has_legacy $ktype || continue 64 type_has_legacy $ktype || continue
41 cp $OBJ/cert_host_key_${ktype} $OBJ/cert_host_key_${ktype}_v00 65 cp $OBJ/cert_host_key_${ktype} $OBJ/cert_host_key_${ktype}_v00
42 cp $OBJ/cert_host_key_${ktype}.pub $OBJ/cert_host_key_${ktype}_v00.pub 66 cp $OBJ/cert_host_key_${ktype}.pub $OBJ/cert_host_key_${ktype}_v00.pub
@@ -44,10 +68,35 @@ for ktype in $PLAIN_TYPES ; do
44 ${SSHKEYGEN} -t v00 -h -q -s $OBJ/host_ca_key \ 68 ${SSHKEYGEN} -t v00 -h -q -s $OBJ/host_ca_key \
45 -I "regress host key for $USER" \ 69 -I "regress host key for $USER" \
46 -n $HOSTS $OBJ/cert_host_key_${ktype}_v00 || 70 -n $HOSTS $OBJ/cert_host_key_${ktype}_v00 ||
47 fail "couldn't sign cert_host_key_${ktype}_v00" 71 fatal "couldn't sign cert_host_key_${ktype}_v00"
72 ${SSHKEYGEN} -ukf $OBJ/host_krl_cert \
73 $OBJ/cert_host_key_${ktype}_v00-cert.pub || \
74 fatal "KRL update failed"
75 cat $OBJ/cert_host_key_${ktype}_v00-cert.pub >> $OBJ/host_revoked_cert
48done 76done
49 77
50# Basic connect tests 78attempt_connect() {
79 _ident="$1"
80 _expect_success="$2"
81 shift; shift
82 verbose "$tid: $_ident expect success $_expect_success"
83 cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
84 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
85 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
86 "$@" -F $OBJ/ssh_proxy somehost true
87 _r=$?
88 if [ "x$_expect_success" = "xyes" ] ; then
89 if [ $_r -ne 0 ]; then
90 fail "ssh cert connect $_ident failed"
91 fi
92 else
93 if [ $_r -eq 0 ]; then
94 fail "ssh cert connect $_ident succeeded unexpectedly"
95 fi
96 fi
97}
98
99# Basic connect and revocation tests.
51for privsep in yes no ; do 100for privsep in yes no ; do
52 for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do 101 for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do
53 verbose "$tid: host ${ktype} cert connect privsep $privsep" 102 verbose "$tid: host ${ktype} cert connect privsep $privsep"
@@ -58,12 +107,24 @@ for privsep in yes no ; do
58 echo UsePrivilegeSeparation $privsep 107 echo UsePrivilegeSeparation $privsep
59 ) > $OBJ/sshd_proxy 108 ) > $OBJ/sshd_proxy
60 109
61 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ 110 # test name expect success
62 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ 111 attempt_connect "$ktype basic connect" "yes"
63 -F $OBJ/ssh_proxy somehost true 112 attempt_connect "$ktype empty KRL" "yes" \
64 if [ $? -ne 0 ]; then 113 -oRevokedHostKeys=$OBJ/host_krl_empty
65 fail "ssh cert connect failed" 114 attempt_connect "$ktype KRL w/ plain key revoked" "no" \
66 fi 115 -oRevokedHostKeys=$OBJ/host_krl_plain
116 attempt_connect "$ktype KRL w/ cert revoked" "no" \
117 -oRevokedHostKeys=$OBJ/host_krl_cert
118 attempt_connect "$ktype KRL w/ CA revoked" "no" \
119 -oRevokedHostKeys=$OBJ/host_krl_ca
120 attempt_connect "$ktype empty plaintext revocation" "yes" \
121 -oRevokedHostKeys=$OBJ/host_revoked_empty
122 attempt_connect "$ktype plain key plaintext revocation" "no" \
123 -oRevokedHostKeys=$OBJ/host_revoked_plain
124 attempt_connect "$ktype cert plaintext revocation" "no" \
125 -oRevokedHostKeys=$OBJ/host_revoked_cert
126 attempt_connect "$ktype CA plaintext revocation" "no" \
127 -oRevokedHostKeys=$OBJ/host_revoked_ca
67 done 128 done
68done 129done
69 130
@@ -76,7 +137,8 @@ done
76 test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey" 137 test -f "$OBJ/cert_host_key_${ktype}.pub" || fatal "no pubkey"
77 printf "@revoked * `cat $OBJ/cert_host_key_${ktype}.pub`\n" 138 printf "@revoked * `cat $OBJ/cert_host_key_${ktype}.pub`\n"
78 done 139 done
79) > $OBJ/known_hosts-cert 140) > $OBJ/known_hosts-cert.orig
141cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
80for privsep in yes no ; do 142for privsep in yes no ; do
81 for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do 143 for ktype in $PLAIN_TYPES rsa_v00 dsa_v00; do
82 verbose "$tid: host ${ktype} revoked cert privsep $privsep" 144 verbose "$tid: host ${ktype} revoked cert privsep $privsep"
@@ -87,6 +149,7 @@ for privsep in yes no ; do
87 echo UsePrivilegeSeparation $privsep 149 echo UsePrivilegeSeparation $privsep
88 ) > $OBJ/sshd_proxy 150 ) > $OBJ/sshd_proxy
89 151
152 cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
90 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ 153 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
91 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ 154 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
92 -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 155 -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
@@ -104,7 +167,8 @@ done
104 printf '@revoked ' 167 printf '@revoked '
105 printf "* " 168 printf "* "
106 cat $OBJ/host_ca_key.pub 169 cat $OBJ/host_ca_key.pub
107) > $OBJ/known_hosts-cert 170) > $OBJ/known_hosts-cert.orig
171cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
108for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do 172for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do
109 verbose "$tid: host ${ktype} revoked cert" 173 verbose "$tid: host ${ktype} revoked cert"
110 ( 174 (
@@ -112,6 +176,7 @@ for ktype in $PLAIN_TYPES rsa_v00 dsa_v00 ; do
112 echo HostKey $OBJ/cert_host_key_${ktype} 176 echo HostKey $OBJ/cert_host_key_${ktype}
113 echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub 177 echo HostCertificate $OBJ/cert_host_key_${ktype}-cert.pub
114 ) > $OBJ/sshd_proxy 178 ) > $OBJ/sshd_proxy
179 cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
115 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ 180 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
116 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ 181 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
117 -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 182 -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
@@ -125,7 +190,8 @@ done
125 printf '@cert-authority ' 190 printf '@cert-authority '
126 printf "$HOSTS " 191 printf "$HOSTS "
127 cat $OBJ/host_ca_key.pub 192 cat $OBJ/host_ca_key.pub
128) > $OBJ/known_hosts-cert 193) > $OBJ/known_hosts-cert.orig
194cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
129 195
130test_one() { 196test_one() {
131 ident=$1 197 ident=$1
@@ -150,6 +216,7 @@ test_one() {
150 echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub 216 echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
151 ) > $OBJ/sshd_proxy 217 ) > $OBJ/sshd_proxy
152 218
219 cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
153 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ 220 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
154 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ 221 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
155 -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1 222 -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
@@ -212,7 +279,8 @@ done
212 printf '@cert-authority ' 279 printf '@cert-authority '
213 printf "$HOSTS " 280 printf "$HOSTS "
214 cat $OBJ/host_ca_key.pub 281 cat $OBJ/host_ca_key.pub
215) > $OBJ/known_hosts-cert 282) > $OBJ/known_hosts-cert.orig
283cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
216for v in v01 v00 ; do 284for v in v01 v00 ; do
217 for kt in $PLAIN_TYPES ; do 285 for kt in $PLAIN_TYPES ; do
218 type_has_legacy $kt || continue 286 type_has_legacy $kt || continue
@@ -232,6 +300,7 @@ for v in v01 v00 ; do
232 echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub 300 echo HostCertificate $OBJ/cert_host_key_${kt}-cert.pub
233 ) > $OBJ/sshd_proxy 301 ) > $OBJ/sshd_proxy
234 302
303 cp $OBJ/known_hosts-cert.orig $OBJ/known_hosts-cert
235 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \ 304 ${SSH} -2 -oUserKnownHostsFile=$OBJ/known_hosts-cert \
236 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \ 305 -oGlobalKnownHostsFile=$OBJ/known_hosts-cert \
237 -F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1 306 -F $OBJ/ssh_proxy -q somehost true >/dev/null 2>&1
@@ -241,4 +310,4 @@ for v in v01 v00 ; do
241 done 310 done
242done 311done
243 312
244rm -f $OBJ/known_hosts-cert $OBJ/host_ca_key* $OBJ/cert_host_key* 313rm -f $OBJ/known_hosts-cert* $OBJ/host_ca_key* $OBJ/cert_host_key*
diff --git a/regress/cfgmatch.sh b/regress/cfgmatch.sh
index 80cf22930..056296398 100644
--- a/regress/cfgmatch.sh
+++ b/regress/cfgmatch.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: cfgmatch.sh,v 1.8 2013/05/17 00:37:40 dtucker Exp $ 1# $OpenBSD: cfgmatch.sh,v 1.9 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="sshd_config match" 4tid="sshd_config match"
@@ -56,7 +56,7 @@ start_sshd
56#set -x 56#set -x
57 57
58# Test Match + PermitOpen in sshd_config. This should be permitted 58# Test Match + PermitOpen in sshd_config. This should be permitted
59for p in 1 2; do 59for p in ${SSH_PROTOCOLS}; do
60 trace "match permitopen localhost proto $p" 60 trace "match permitopen localhost proto $p"
61 start_client -F $OBJ/ssh_config 61 start_client -F $OBJ/ssh_config
62 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ 62 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \
@@ -65,7 +65,7 @@ for p in 1 2; do
65done 65done
66 66
67# Same but from different source. This should not be permitted 67# Same but from different source. This should not be permitted
68for p in 1 2; do 68for p in ${SSH_PROTOCOLS}; do
69 trace "match permitopen proxy proto $p" 69 trace "match permitopen proxy proto $p"
70 start_client -F $OBJ/ssh_proxy 70 start_client -F $OBJ/ssh_proxy
71 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ 71 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \
@@ -74,11 +74,12 @@ for p in 1 2; do
74done 74done
75 75
76# Retry previous with key option, should also be denied. 76# Retry previous with key option, should also be denied.
77printf 'permitopen="127.0.0.1:'$PORT'" ' >$OBJ/authorized_keys_$USER 77cp /dev/null $OBJ/authorized_keys_$USER
78cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER 78for t in ${SSH_KEYTYPES}; do
79printf 'permitopen="127.0.0.1:'$PORT'" ' >>$OBJ/authorized_keys_$USER 79 printf 'permitopen="127.0.0.1:'$PORT'" ' >> $OBJ/authorized_keys_$USER
80cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER 80 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
81for p in 1 2; do 81done
82for p in ${SSH_PROTOCOLS}; do
82 trace "match permitopen proxy w/key opts proto $p" 83 trace "match permitopen proxy w/key opts proto $p"
83 start_client -F $OBJ/ssh_proxy 84 start_client -F $OBJ/ssh_proxy
84 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ 85 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \
@@ -88,7 +89,7 @@ done
88 89
89# Test both sshd_config and key options permitting the same dst/port pair. 90# Test both sshd_config and key options permitting the same dst/port pair.
90# Should be permitted. 91# Should be permitted.
91for p in 1 2; do 92for p in ${SSH_PROTOCOLS}; do
92 trace "match permitopen localhost proto $p" 93 trace "match permitopen localhost proto $p"
93 start_client -F $OBJ/ssh_config 94 start_client -F $OBJ/ssh_config
94 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ 95 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \
@@ -102,7 +103,7 @@ echo "Match User $USER" >>$OBJ/sshd_proxy
102echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy 103echo "PermitOpen 127.0.0.1:1 127.0.0.1:2" >>$OBJ/sshd_proxy
103 104
104# Test that a Match overrides a PermitOpen in the global section 105# Test that a Match overrides a PermitOpen in the global section
105for p in 1 2; do 106for p in ${SSH_PROTOCOLS}; do
106 trace "match permitopen proxy w/key opts proto $p" 107 trace "match permitopen proxy w/key opts proto $p"
107 start_client -F $OBJ/ssh_proxy 108 start_client -F $OBJ/ssh_proxy
108 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true && \ 109 ${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
117 118
118# Test that a rule that doesn't match doesn't override, plus test a 119# Test that a rule that doesn't match doesn't override, plus test a
119# PermitOpen entry that's not at the start of the list 120# PermitOpen entry that's not at the start of the list
120for p in 1 2; do 121for p in ${SSH_PROTOCOLS}; do
121 trace "nomatch permitopen proxy w/key opts proto $p" 122 trace "nomatch permitopen proxy w/key opts proto $p"
122 start_client -F $OBJ/ssh_proxy 123 start_client -F $OBJ/ssh_proxy
123 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \ 124 ${SSH} -q -$p -p $fwdport -F $OBJ/ssh_config somehost true || \
diff --git a/regress/cipher-speed.sh b/regress/cipher-speed.sh
index a6d53a78d..ad2f9b90b 100644
--- a/regress/cipher-speed.sh
+++ b/regress/cipher-speed.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: cipher-speed.sh,v 1.11 2013/11/21 03:18:51 djm Exp $ 1# $OpenBSD: cipher-speed.sh,v 1.12 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="cipher speed" 4tid="cipher speed"
@@ -31,7 +31,11 @@ for c in `${SSH} -Q cipher`; do n=0; for m in `${SSH} -Q mac`; do
31 n=`expr $n + 1` 31 n=`expr $n + 1`
32done; done 32done; done
33 33
34ciphers="3des blowfish" 34if ssh_version 1; then
35 ciphers="3des blowfish"
36else
37 ciphers=""
38fi
35for c in $ciphers; do 39for c in $ciphers; do
36 trace "proto 1 cipher $c" 40 trace "proto 1 cipher $c"
37 for x in $tries; do 41 for x in $tries; do
diff --git a/regress/connect-privsep.sh b/regress/connect-privsep.sh
index 41cb7af69..9a51f5690 100644
--- a/regress/connect-privsep.sh
+++ b/regress/connect-privsep.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: connect-privsep.sh,v 1.5 2014/05/04 10:40:59 logan Exp $ 1# $OpenBSD: connect-privsep.sh,v 1.6 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="proxy connect with privsep" 4tid="proxy connect with privsep"
@@ -6,7 +6,7 @@ tid="proxy connect with privsep"
6cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig 6cp $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
7echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy 7echo 'UsePrivilegeSeparation yes' >> $OBJ/sshd_proxy
8 8
9for p in 1 2; do 9for p in ${SSH_PROTOCOLS}; do
10 ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true 10 ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
11 if [ $? -ne 0 ]; then 11 if [ $? -ne 0 ]; then
12 fail "ssh privsep+proxyconnect protocol $p failed" 12 fail "ssh privsep+proxyconnect protocol $p failed"
@@ -16,7 +16,7 @@ done
16cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy 16cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
17echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy 17echo 'UsePrivilegeSeparation sandbox' >> $OBJ/sshd_proxy
18 18
19for p in 1 2; do 19for p in ${SSH_PROTOCOLS}; do
20 ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true 20 ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
21 if [ $? -ne 0 ]; then 21 if [ $? -ne 0 ]; then
22 # XXX replace this with fail once sandbox has stabilised 22 # XXX replace this with fail once sandbox has stabilised
@@ -27,7 +27,7 @@ done
27# Because sandbox is sensitive to changes in libc, especially malloc, retest 27# Because sandbox is sensitive to changes in libc, especially malloc, retest
28# with every malloc.conf option (and none). 28# with every malloc.conf option (and none).
29for m in '' A F G H J P R S X '<' '>'; do 29for m in '' A F G H J P R S X '<' '>'; do
30 for p in 1 2; do 30 for p in ${SSH_PROTOCOLS}; do
31 env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true 31 env MALLOC_OPTIONS="$m" ${SSH} -$p -F $OBJ/ssh_proxy 999.999.999.999 true
32 if [ $? -ne 0 ]; then 32 if [ $? -ne 0 ]; then
33 fail "ssh privsep/sandbox+proxyconnect protocol $p mopt '$m' failed" 33 fail "ssh privsep/sandbox+proxyconnect protocol $p mopt '$m' failed"
diff --git a/regress/connect.sh b/regress/connect.sh
index 2186fa6e7..f0d55d343 100644
--- a/regress/connect.sh
+++ b/regress/connect.sh
@@ -1,11 +1,11 @@
1# $OpenBSD: connect.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ 1# $OpenBSD: connect.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="simple connect" 4tid="simple connect"
5 5
6start_sshd 6start_sshd
7 7
8for p in 1 2; do 8for p in ${SSH_PROTOCOLS}; do
9 ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true 9 ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
10 if [ $? -ne 0 ]; then 10 if [ $? -ne 0 ]; then
11 fail "ssh connect with protocol $p failed" 11 fail "ssh connect with protocol $p failed"
diff --git a/regress/dynamic-forward.sh b/regress/dynamic-forward.sh
index 42fa8acdc..dd67c9639 100644
--- a/regress/dynamic-forward.sh
+++ b/regress/dynamic-forward.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: dynamic-forward.sh,v 1.10 2013/05/17 04:29:14 dtucker Exp $ 1# $OpenBSD: dynamic-forward.sh,v 1.11 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="dynamic forwarding" 4tid="dynamic forwarding"
@@ -17,7 +17,7 @@ trace "will use ProxyCommand $proxycmd"
17 17
18start_sshd 18start_sshd
19 19
20for p in 1 2; do 20for p in ${SSH_PROTOCOLS}; do
21 n=0 21 n=0
22 error="1" 22 error="1"
23 trace "start dynamic forwarding, fork to background" 23 trace "start dynamic forwarding, fork to background"
diff --git a/regress/exit-status.sh b/regress/exit-status.sh
index 56b78a622..397d8d732 100644
--- a/regress/exit-status.sh
+++ b/regress/exit-status.sh
@@ -1,9 +1,9 @@
1# $OpenBSD: exit-status.sh,v 1.6 2002/03/15 13:08:56 markus Exp $ 1# $OpenBSD: exit-status.sh,v 1.7 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="remote exit status" 4tid="remote exit status"
5 5
6for p in 1 2; do 6for p in ${SSH_PROTOCOLS}; do
7 for s in 0 1 4 5 44; do 7 for s in 0 1 4 5 44; do
8 trace "proto $p status $s" 8 trace "proto $p status $s"
9 verbose "test $tid: proto $p status $s" 9 verbose "test $tid: proto $p status $s"
diff --git a/regress/forcecommand.sh b/regress/forcecommand.sh
index 44d2b7ffd..8a9b090ea 100644
--- a/regress/forcecommand.sh
+++ b/regress/forcecommand.sh
@@ -1,30 +1,32 @@
1# $OpenBSD: forcecommand.sh,v 1.2 2013/05/17 00:37:40 dtucker Exp $ 1# $OpenBSD: forcecommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="forced command" 4tid="forced command"
5 5
6cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak 6cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
7 7
8printf 'command="true" ' >$OBJ/authorized_keys_$USER 8cp /dev/null $OBJ/authorized_keys_$USER
9cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER 9for t in ${SSH_KEYTYPES}; do
10printf 'command="true" ' >>$OBJ/authorized_keys_$USER 10 printf 'command="true" ' >>$OBJ/authorized_keys_$USER
11cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER 11 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
12done
12 13
13for p in 1 2; do 14for p in ${SSH_PROTOCOLS}; do
14 trace "forced command in key option proto $p" 15 trace "forced command in key option proto $p"
15 ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || 16 ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ ||
16 fail "forced command in key proto $p" 17 fail "forced command in key proto $p"
17done 18done
18 19
19printf 'command="false" ' >$OBJ/authorized_keys_$USER 20cp /dev/null $OBJ/authorized_keys_$USER
20cat $OBJ/rsa.pub >> $OBJ/authorized_keys_$USER 21for t in ${SSH_KEYTYPES}; do
21printf 'command="false" ' >>$OBJ/authorized_keys_$USER 22 printf 'command="false" ' >> $OBJ/authorized_keys_$USER
22cat $OBJ/rsa1.pub >> $OBJ/authorized_keys_$USER 23 cat $OBJ/$t.pub >> $OBJ/authorized_keys_$USER
24done
23 25
24cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy 26cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
25echo "ForceCommand true" >> $OBJ/sshd_proxy 27echo "ForceCommand true" >> $OBJ/sshd_proxy
26 28
27for p in 1 2; do 29for p in ${SSH_PROTOCOLS}; do
28 trace "forced command in sshd_config overrides key option proto $p" 30 trace "forced command in sshd_config overrides key option proto $p"
29 ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || 31 ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ ||
30 fail "forced command in key proto $p" 32 fail "forced command in key proto $p"
@@ -35,7 +37,7 @@ echo "ForceCommand false" >> $OBJ/sshd_proxy
35echo "Match User $USER" >> $OBJ/sshd_proxy 37echo "Match User $USER" >> $OBJ/sshd_proxy
36echo " ForceCommand true" >> $OBJ/sshd_proxy 38echo " ForceCommand true" >> $OBJ/sshd_proxy
37 39
38for p in 1 2; do 40for p in ${SSH_PROTOCOLS}; do
39 trace "forced command with match proto $p" 41 trace "forced command with match proto $p"
40 ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ || 42 ${SSH} -$p -F $OBJ/ssh_proxy somehost false \ ||
41 fail "forced command in key proto $p" 43 fail "forced command in key proto $p"
diff --git a/regress/forward-control.sh b/regress/forward-control.sh
index 7f7d105e8..91957098f 100644
--- a/regress/forward-control.sh
+++ b/regress/forward-control.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: forward-control.sh,v 1.2 2013/11/18 05:09:32 naddy Exp $ 1# $OpenBSD: forward-control.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="sshd control of local and remote forwarding" 4tid="sshd control of local and remote forwarding"
@@ -99,7 +99,7 @@ cp ${OBJ}/sshd_proxy ${OBJ}/sshd_proxy.bak
99cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak 99cp ${OBJ}/authorized_keys_${USER} ${OBJ}/authorized_keys_${USER}.bak
100 100
101# Sanity check: ensure the default config allows forwarding 101# Sanity check: ensure the default config allows forwarding
102for p in 1 2 ; do 102for p in ${SSH_PROTOCOLS} ; do
103 check_lfwd $p Y "proto $p, default configuration" 103 check_lfwd $p Y "proto $p, default configuration"
104 check_rfwd $p Y "proto $p, default configuration" 104 check_rfwd $p Y "proto $p, default configuration"
105done 105done
@@ -115,7 +115,7 @@ all_tests() {
115 _permit_rfwd=$7 115 _permit_rfwd=$7
116 _badfwd=127.0.0.1:22 116 _badfwd=127.0.0.1:22
117 _goodfwd=127.0.0.1:${PORT} 117 _goodfwd=127.0.0.1:${PORT}
118 for _proto in 1 2 ; do 118 for _proto in ${SSH_PROTOCOLS} ; do
119 cp ${OBJ}/authorized_keys_${USER}.bak \ 119 cp ${OBJ}/authorized_keys_${USER}.bak \
120 ${OBJ}/authorized_keys_${USER} 120 ${OBJ}/authorized_keys_${USER}
121 _prefix="proto $_proto, AllowTcpForwarding=$_tcpfwd" 121 _prefix="proto $_proto, AllowTcpForwarding=$_tcpfwd"
diff --git a/regress/forwarding.sh b/regress/forwarding.sh
index f799d4951..fb4f35aff 100644
--- a/regress/forwarding.sh
+++ b/regress/forwarding.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: forwarding.sh,v 1.12 2014/07/15 15:54:15 millert Exp $ 1# $OpenBSD: forwarding.sh,v 1.15 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="local and remote forwarding" 4tid="local and remote forwarding"
@@ -10,6 +10,9 @@ start_sshd
10base=33 10base=33
11last=$PORT 11last=$PORT
12fwd="" 12fwd=""
13CTL=$OBJ/ctl-sock
14rm -f $CTL
15
13for j in 0 1 2; do 16for j in 0 1 2; do
14 for i in 0 1 2; do 17 for i in 0 1 2; do
15 a=$base$j$i 18 a=$base$j$i
@@ -20,8 +23,11 @@ for j in 0 1 2; do
20 last=$a 23 last=$a
21 done 24 done
22done 25done
23for p in 1 2; do 26for p in ${SSH_PROTOCOLS}; do
24 q=`expr 3 - $p` 27 q=`expr 3 - $p`
28 if ! ssh_version $q; then
29 q=$p
30 fi
25 trace "start forwarding, fork to background" 31 trace "start forwarding, fork to background"
26 ${SSH} -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10 32 ${SSH} -$p -F $OBJ/ssh_config -f $fwd somehost sleep 10
27 33
@@ -34,7 +40,7 @@ for p in 1 2; do
34 sleep 10 40 sleep 10
35done 41done
36 42
37for p in 1 2; do 43for p in ${SSH_PROTOCOLS}; do
38for d in L R; do 44for d in L R; do
39 trace "exit on -$d forward failure, proto $p" 45 trace "exit on -$d forward failure, proto $p"
40 46
@@ -64,7 +70,7 @@ for d in L R; do
64done 70done
65done 71done
66 72
67for p in 1 2; do 73for p in ${SSH_PROTOCOLS}; do
68 trace "simple clear forwarding proto $p" 74 trace "simple clear forwarding proto $p"
69 ${SSH} -$p -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true 75 ${SSH} -$p -F $OBJ/ssh_config -oClearAllForwardings=yes somehost true
70 76
@@ -107,9 +113,9 @@ done
107 113
108echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config 114echo "LocalForward ${base}01 127.0.0.1:$PORT" >> $OBJ/ssh_config
109echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config 115echo "RemoteForward ${base}02 127.0.0.1:${base}01" >> $OBJ/ssh_config
110for p in 1 2; do 116for p in ${SSH_PROTOCOLS}; do
111 trace "config file: start forwarding, fork to background" 117 trace "config file: start forwarding, fork to background"
112 ${SSH} -$p -F $OBJ/ssh_config -f somehost sleep 10 118 ${SSH} -S $CTL -M -$p -F $OBJ/ssh_config -f somehost sleep 10
113 119
114 trace "config file: transfer over forwarded channels and check result" 120 trace "config file: transfer over forwarded channels and check result"
115 ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \ 121 ${SSH} -F $OBJ/ssh_config -p${base}02 -o 'ConnectionAttempts=4' \
@@ -117,7 +123,7 @@ for p in 1 2; do
117 test -s ${COPY} || fail "failed copy of ${DATA}" 123 test -s ${COPY} || fail "failed copy of ${DATA}"
118 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}" 124 cmp ${DATA} ${COPY} || fail "corrupted copy of ${DATA}"
119 125
120 wait 126 ${SSH} -S $CTL -O exit somehost
121done 127done
122 128
123for p in 2; do 129for p in 2; do
diff --git a/regress/host-expand.sh b/regress/host-expand.sh
index 6cc0e6055..2a95bfe1b 100644
--- a/regress/host-expand.sh
+++ b/regress/host-expand.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: host-expand.sh,v 1.3 2014/02/27 23:17:41 djm Exp $ 1# $OpenBSD: host-expand.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="expand %h and %n" 4tid="expand %h and %n"
@@ -11,7 +11,7 @@ somehost
11127.0.0.1 11127.0.0.1
12EOE 12EOE
13 13
14for p in 1 2; do 14for p in ${SSH_PROTOCOLS}; do
15 verbose "test $tid: proto $p" 15 verbose "test $tid: proto $p"
16 ${SSH} -F $OBJ/ssh_proxy -$p somehost true >$OBJ/actual 16 ${SSH} -F $OBJ/ssh_proxy -$p somehost true >$OBJ/actual
17 diff $OBJ/expect $OBJ/actual || fail "$tid proto $p" 17 diff $OBJ/expect $OBJ/actual || fail "$tid proto $p"
diff --git a/regress/hostkey-agent.sh b/regress/hostkey-agent.sh
new file mode 100644
index 000000000..a011ec831
--- /dev/null
+++ b/regress/hostkey-agent.sh
@@ -0,0 +1,52 @@
1# $OpenBSD: hostkey-agent.sh,v 1.5 2015/02/21 20:51:02 djm Exp $
2# Placed in the Public Domain.
3
4tid="hostkey agent"
5
6rm -f $OBJ/agent-key.* $OBJ/ssh_proxy.orig $OBJ/known_hosts.orig
7
8trace "start agent"
9eval `${SSHAGENT} -s` > /dev/null
10r=$?
11[ $r -ne 0 ] && fatal "could not start ssh-agent: exit code $r"
12
13grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
14echo "HostKeyAgent $SSH_AUTH_SOCK" >> $OBJ/sshd_proxy.orig
15
16trace "load hostkeys"
17for k in `${SSH} -Q key-plain` ; do
18 ${SSHKEYGEN} -qt $k -f $OBJ/agent-key.$k -N '' || fatal "ssh-keygen $k"
19 (
20 printf 'localhost-with-alias,127.0.0.1,::1 '
21 cat $OBJ/agent-key.$k.pub
22 ) >> $OBJ/known_hosts.orig
23 ${SSHADD} $OBJ/agent-key.$k >/dev/null 2>&1 || \
24 fatal "couldn't load key $OBJ/agent-key.$k"
25 echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy.orig
26 # Remove private key so the server can't use it.
27 rm $OBJ/agent-key.$k || fatal "couldn't rm $OBJ/agent-key.$k"
28done
29cp $OBJ/known_hosts.orig $OBJ/known_hosts
30
31unset SSH_AUTH_SOCK
32
33for ps in no yes; do
34 cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
35 echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
36 for k in `${SSH} -Q key-plain` ; do
37 verbose "key type $k privsep=$ps"
38 opts="-oHostKeyAlgorithms=$k -F $OBJ/ssh_proxy"
39 cp $OBJ/known_hosts.orig $OBJ/known_hosts
40 SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
41 if [ $? -ne 0 ]; then
42 fail "protocol $p privsep=$ps failed"
43 fi
44 if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
45 fail "bad SSH_CONNECTION key type $k privsep=$ps"
46 fi
47 done
48done
49
50trace "kill agent"
51${SSHAGENT} -k > /dev/null
52
diff --git a/regress/hostkey-rotate.sh b/regress/hostkey-rotate.sh
new file mode 100644
index 000000000..b5d542d12
--- /dev/null
+++ b/regress/hostkey-rotate.sh
@@ -0,0 +1,128 @@
1# $OpenBSD: hostkey-rotate.sh,v 1.2 2015/03/03 17:53:40 djm Exp $
2# Placed in the Public Domain.
3
4tid="hostkey rotate"
5
6# Need full names here since they are used in HostKeyAlgorithms
7HOSTKEY_TYPES="ecdsa-sha2-nistp256 ssh-ed25519 ssh-rsa ssh-dss"
8
9rm -f $OBJ/hkr.* $OBJ/ssh_proxy.orig
10
11grep -vi 'hostkey' $OBJ/sshd_proxy > $OBJ/sshd_proxy.orig
12echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy
13rm $OBJ/known_hosts
14
15trace "prepare hostkeys"
16nkeys=0
17all_algs=""
18for k in `ssh -Q key-plain` ; do
19 ${SSHKEYGEN} -qt $k -f $OBJ/hkr.$k -N '' || fatal "ssh-keygen $k"
20 echo "Hostkey $OBJ/hkr.${k}" >> $OBJ/sshd_proxy.orig
21 nkeys=`expr $nkeys + 1`
22 test "x$all_algs" = "x" || all_algs="${all_algs},"
23 all_algs="${all_algs}$k"
24done
25
26dossh() {
27 # All ssh should succeed in this test
28 ${SSH} -F $OBJ/ssh_proxy "$@" x true || fail "ssh $@ failed"
29}
30
31expect_nkeys() {
32 _expected=$1
33 _message=$2
34 _n=`wc -l $OBJ/known_hosts | awk '{ print $1 }'` || fatal "wc failed"
35 [ "x$_n" = "x$_expected" ] || fail "$_message (got $_n wanted $_expected)"
36}
37
38check_key_present() {
39 _type=$1
40 _kfile=$2
41 test "x$_kfile" = "x" && _kfile="$OBJ/hkr.${_type}.pub"
42 _kpub=`awk "/$_type /"' { print $2 }' < $_kfile` || \
43 fatal "awk failed"
44 fgrep "$_kpub" $OBJ/known_hosts > /dev/null
45}
46
47cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
48
49# Connect to sshd with StrictHostkeyChecking=no
50verbose "learn hostkey with StrictHostKeyChecking=no"
51>$OBJ/known_hosts
52dossh -oHostKeyAlgorithms=ssh-ed25519 -oStrictHostKeyChecking=no
53# Verify no additional keys learned
54expect_nkeys 1 "unstrict connect keys"
55check_key_present ssh-ed25519 || fail "unstrict didn't learn key"
56
57# Connect to sshd as usual
58verbose "learn additional hostkeys"
59dossh -oStrictHostKeyChecking=yes
60# Check that other keys learned
61expect_nkeys $nkeys "learn hostkeys"
62check_key_present ssh-rsa || fail "didn't learn keys"
63
64# Check each key type
65for k in `ssh -Q key-plain` ; do
66 verbose "learn additional hostkeys, type=$k"
67 dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=$k,$all_algs
68 expect_nkeys $nkeys "learn hostkeys $k"
69 check_key_present $k || fail "didn't learn $k"
70done
71
72# Change one hostkey (non primary) and relearn
73verbose "learn changed non-primary hostkey"
74mv $OBJ/hkr.ssh-rsa.pub $OBJ/hkr.ssh-rsa.pub.old
75rm -f $OBJ/hkr.ssh-rsa
76${SSHKEYGEN} -qt ssh-rsa -f $OBJ/hkr.ssh-rsa -N '' || fatal "ssh-keygen $k"
77dossh -oStrictHostKeyChecking=yes
78# Check that the key was replaced
79expect_nkeys $nkeys "learn hostkeys"
80check_key_present ssh-rsa $OBJ/hkr.ssh-rsa.pub.old && fail "old key present"
81check_key_present ssh-rsa || fail "didn't learn changed key"
82
83# Add new hostkey (primary type) to sshd and connect
84verbose "learn new primary hostkey"
85${SSHKEYGEN} -qt ssh-rsa -f $OBJ/hkr.ssh-rsa-new -N '' || fatal "ssh-keygen $k"
86( cat $OBJ/sshd_proxy.orig ; echo HostKey $OBJ/hkr.ssh-rsa-new ) \
87 > $OBJ/sshd_proxy
88# Check new hostkey added
89dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa,$all_algs
90expect_nkeys `expr $nkeys + 1` "learn hostkeys"
91check_key_present ssh-rsa || fail "current key missing"
92check_key_present ssh-rsa $OBJ/hkr.ssh-rsa-new.pub || fail "new key missing"
93
94# Remove old hostkey (primary type) from sshd
95verbose "rotate primary hostkey"
96cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
97mv $OBJ/hkr.ssh-rsa.pub $OBJ/hkr.ssh-rsa.pub.old
98mv $OBJ/hkr.ssh-rsa-new.pub $OBJ/hkr.ssh-rsa.pub
99mv $OBJ/hkr.ssh-rsa-new $OBJ/hkr.ssh-rsa
100# Check old hostkey removed
101dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa,$all_algs
102expect_nkeys $nkeys "learn hostkeys"
103check_key_present ssh-rsa $OBJ/hkr.ssh-rsa.pub.old && fail "old key present"
104check_key_present ssh-rsa || fail "didn't learn changed key"
105
106# Connect again, forcing rotated key
107verbose "check rotate primary hostkey"
108dossh -oStrictHostKeyChecking=yes -oHostKeyAlgorithms=ssh-rsa
109expect_nkeys 1 "learn hostkeys"
110check_key_present ssh-rsa || fail "didn't learn changed key"
111
112# $OpenBSD: hostkey-rotate.sh,v 1.2 2015/03/03 17:53:40 djm Exp $
113# Placed in the Public Domain.
114
115tid="hostkey rotate"
116
117# Prepare hostkeys file with one key
118
119# Connect to sshd
120
121# Check that other keys learned
122
123# Change one hostkey (non primary)
124
125# Connect to sshd
126
127# Check that the key was replaced
128
diff --git a/regress/integrity.sh b/regress/integrity.sh
index d3a489ff7..2ff8b3f17 100644
--- a/regress/integrity.sh
+++ b/regress/integrity.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: integrity.sh,v 1.14 2014/05/21 07:04:21 djm Exp $ 1# $OpenBSD: integrity.sh,v 1.15 2015/01/19 20:42:31 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="integrity" 4tid="integrity"
@@ -20,7 +20,7 @@ echo "KexAlgorithms diffie-hellman-group14-sha1,diffie-hellman-group1-sha1" \
20 >> $OBJ/ssh_proxy 20 >> $OBJ/ssh_proxy
21 21
22# sshd-command for proxy (see test-exec.sh) 22# sshd-command for proxy (see test-exec.sh)
23cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" 23cmd="$SUDO sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy"
24 24
25for m in $macs; do 25for m in $macs; do
26 trace "test $tid: mac $m" 26 trace "test $tid: mac $m"
@@ -58,7 +58,7 @@ for m in $macs; do
58 tr -s '\r\n' '.') 58 tr -s '\r\n' '.')
59 case "$out" in 59 case "$out" in
60 Bad?packet*) elen=`expr $elen + 1`; skip=3;; 60 Bad?packet*) elen=`expr $elen + 1`; skip=3;;
61 Corrupted?MAC* | Decryption?integrity?check?failed*) 61 Corrupted?MAC* | *message?authentication?code?incorrect*)
62 emac=`expr $emac + 1`; skip=0;; 62 emac=`expr $emac + 1`; skip=0;;
63 padding*) epad=`expr $epad + 1`; skip=0;; 63 padding*) epad=`expr $epad + 1`; skip=0;;
64 *) fail "unexpected error mac $m at $off: $out";; 64 *) fail "unexpected error mac $m at $off: $out";;
diff --git a/regress/key-options.sh b/regress/key-options.sh
index f98d78b30..7a68ad358 100644
--- a/regress/key-options.sh
+++ b/regress/key-options.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: key-options.sh,v 1.2 2008/06/30 08:07:34 djm Exp $ 1# $OpenBSD: key-options.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="key options" 4tid="key options"
@@ -8,7 +8,7 @@ authkeys="$OBJ/authorized_keys_${USER}"
8cp $authkeys $origkeys 8cp $authkeys $origkeys
9 9
10# Test command= forced command 10# Test command= forced command
11for p in 1 2; do 11for p in ${SSH_PROTOCOLS}; do
12 for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do 12 for c in 'command="echo bar"' 'no-pty,command="echo bar"'; do
13 sed "s/.*/$c &/" $origkeys >$authkeys 13 sed "s/.*/$c &/" $origkeys >$authkeys
14 verbose "key option proto $p $c" 14 verbose "key option proto $p $c"
@@ -24,7 +24,7 @@ done
24 24
25# Test no-pty 25# Test no-pty
26sed 's/.*/no-pty &/' $origkeys >$authkeys 26sed 's/.*/no-pty &/' $origkeys >$authkeys
27for p in 1 2; do 27for p in ${SSH_PROTOCOLS}; do
28 verbose "key option proto $p no-pty" 28 verbose "key option proto $p no-pty"
29 r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost tty` 29 r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost tty`
30 if [ -f "$r" ]; then 30 if [ -f "$r" ]; then
@@ -35,7 +35,7 @@ done
35# Test environment= 35# Test environment=
36echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy 36echo 'PermitUserEnvironment yes' >> $OBJ/sshd_proxy
37sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys 37sed 's/.*/environment="FOO=bar" &/' $origkeys >$authkeys
38for p in 1 2; do 38for p in ${SSH_PROTOCOLS}; do
39 verbose "key option proto $p environment" 39 verbose "key option proto $p environment"
40 r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo $FOO'` 40 r=`${SSH} -$p -q -F $OBJ/ssh_proxy somehost 'echo $FOO'`
41 if [ "$r" != "bar" ]; then 41 if [ "$r" != "bar" ]; then
@@ -45,7 +45,7 @@ done
45 45
46# Test from= restriction 46# Test from= restriction
47start_sshd 47start_sshd
48for p in 1 2; do 48for p in ${SSH_PROTOCOLS}; do
49 for f in 127.0.0.1 '127.0.0.0\/8'; do 49 for f in 127.0.0.1 '127.0.0.0\/8'; do
50 cat $origkeys >$authkeys 50 cat $origkeys >$authkeys
51 ${SSH} -$p -q -F $OBJ/ssh_proxy somehost true 51 ${SSH} -$p -q -F $OBJ/ssh_proxy somehost true
diff --git a/regress/keygen-change.sh b/regress/keygen-change.sh
index 08d359023..e56185050 100644
--- a/regress/keygen-change.sh
+++ b/regress/keygen-change.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: keygen-change.sh,v 1.2 2002/07/16 09:15:55 markus Exp $ 1# $OpenBSD: keygen-change.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="change passphrase for key" 4tid="change passphrase for key"
@@ -6,7 +6,12 @@ tid="change passphrase for key"
6S1="secret1" 6S1="secret1"
7S2="2secret" 7S2="2secret"
8 8
9for t in rsa dsa rsa1; do 9KEYTYPES=`${SSH} -Q key-plain`
10if ssh_version 1; then
11 KEYTYPES="${KEYTYPES} rsa1"
12fi
13
14for t in $KEYTYPES; do
10 # generate user key for agent 15 # generate user key for agent
11 trace "generating $t key" 16 trace "generating $t key"
12 rm -f $OBJ/$t-key 17 rm -f $OBJ/$t-key
diff --git a/regress/keygen-knownhosts.sh b/regress/keygen-knownhosts.sh
new file mode 100644
index 000000000..085aac650
--- /dev/null
+++ b/regress/keygen-knownhosts.sh
@@ -0,0 +1,197 @@
1# $OpenBSD: keygen-knownhosts.sh,v 1.2 2015/01/27 12:01:36 djm Exp $
2# Placed in the Public Domain.
3
4tid="ssh-keygen known_hosts"
5
6rm -f $OBJ/kh.*
7
8# Generate some keys for testing (just ed25519 for speed) and make a hosts file.
9for x in host-a host-b host-c host-d host-e host-f host-a2 host-b2; do
10 ${SSHKEYGEN} -qt ed25519 -f $OBJ/kh.$x -C "$x" -N "" || \
11 fatal "ssh-keygen failed"
12 # Add a comment that we expect should be preserved.
13 echo "# $x" >> $OBJ/kh.hosts
14 (
15 case "$x" in
16 host-a|host-b) printf "$x " ;;
17 host-c) printf "@cert-authority $x " ;;
18 host-d) printf "@revoked $x " ;;
19 host-e) printf "host-e* " ;;
20 host-f) printf "host-f,host-g,host-h " ;;
21 host-a2) printf "host-a " ;;
22 host-b2) printf "host-b " ;;
23 esac
24 cat $OBJ/kh.${x}.pub
25 # Blank line should be preserved.
26 echo "" >> $OBJ/kh.hosts
27 ) >> $OBJ/kh.hosts
28done
29
30# Generate a variant with an invalid line. We'll use this for most tests,
31# because keygen should be able to cope and it should be preserved in any
32# output file.
33cat $OBJ/kh.hosts >> $OBJ/kh.invalid
34echo "host-i " >> $OBJ/kh.invalid
35
36cp $OBJ/kh.invalid $OBJ/kh.invalid.orig
37cp $OBJ/kh.hosts $OBJ/kh.hosts.orig
38
39expect_key() {
40 _host=$1
41 _hosts=$2
42 _key=$3
43 _line=$4
44 _mark=$5
45 _marker=""
46 test "x$_mark" = "xCA" && _marker="@cert-authority "
47 test "x$_mark" = "xREVOKED" && _marker="@revoked "
48 test "x$_line" != "x" &&
49 echo "# Host $_host found: line $_line $_mark" >> $OBJ/kh.expect
50 printf "${_marker}$_hosts " >> $OBJ/kh.expect
51 cat $OBJ/kh.${_key}.pub >> $OBJ/kh.expect ||
52 fatal "${_key}.pub missing"
53}
54
55check_find() {
56 _host=$1
57 _name=$2
58 _keygenopt=$3
59 ${SSHKEYGEN} $_keygenopt -f $OBJ/kh.invalid -F $_host > $OBJ/kh.result
60 if ! diff -uw $OBJ/kh.expect $OBJ/kh.result ; then
61 fail "didn't find $_name"
62 fi
63}
64
65# Find key
66rm -f $OBJ/kh.expect
67expect_key host-a host-a host-a 2
68expect_key host-a host-a host-a2 20
69check_find host-a "simple find"
70
71# find CA key
72rm -f $OBJ/kh.expect
73expect_key host-c host-c host-c 8 CA
74check_find host-c "find CA key"
75
76# find revoked key
77rm -f $OBJ/kh.expect
78expect_key host-d host-d host-d 11 REVOKED
79check_find host-d "find revoked key"
80
81# find key with wildcard
82rm -f $OBJ/kh.expect
83expect_key host-e.somedomain "host-e*" host-e 14
84check_find host-e.somedomain "find wildcard key"
85
86# find key among multiple hosts
87rm -f $OBJ/kh.expect
88expect_key host-h "host-f,host-g,host-h " host-f 17
89check_find host-h "find multiple hosts"
90
91check_hashed_find() {
92 _host=$1
93 _name=$2
94 _file=$3
95 test "x$_file" = "x" && _file=$OBJ/kh.invalid
96 ${SSHKEYGEN} -f $_file -HF $_host | grep '|1|' | \
97 sed "s/^[^ ]*/$_host/" > $OBJ/kh.result
98 if ! diff -uw $OBJ/kh.expect $OBJ/kh.result ; then
99 fail "didn't find $_name"
100 fi
101}
102
103# Find key and hash
104rm -f $OBJ/kh.expect
105expect_key host-a host-a host-a
106expect_key host-a host-a host-a2
107check_hashed_find host-a "find simple and hash"
108
109# Find CA key and hash
110rm -f $OBJ/kh.expect
111expect_key host-c host-c host-c "" CA
112# CA key output is not hashed.
113check_find host-c "find simple and hash" -H
114
115# Find revoked key and hash
116rm -f $OBJ/kh.expect
117expect_key host-d host-d host-d "" REVOKED
118# Revoked key output is not hashed.
119check_find host-d "find simple and hash" -H
120
121# find key with wildcard and hash
122rm -f $OBJ/kh.expect
123expect_key host-e "host-e*" host-e ""
124# Key with wildcard hostname should not be hashed.
125check_find host-e "find wildcard key" -H
126
127# find key among multiple hosts
128rm -f $OBJ/kh.expect
129# Comma-separated hostnames should be expanded and hashed.
130expect_key host-f "host-h " host-f
131expect_key host-g "host-h " host-f
132expect_key host-h "host-h " host-f
133check_hashed_find host-h "find multiple hosts"
134
135# Attempt remove key on invalid file.
136cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
137${SSHKEYGEN} -qf $OBJ/kh.invalid -R host-a 2>/dev/null
138diff -u $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "remove on invalid succeeded"
139
140# Remove key
141cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
142${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-a 2>/dev/null
143grep -v "^host-a " $OBJ/kh.hosts.orig > $OBJ/kh.expect
144diff -u $OBJ/kh.hosts $OBJ/kh.expect || fail "remove simple"
145
146# Remove CA key
147cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
148${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-c 2>/dev/null
149# CA key should not be removed.
150diff -u $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove CA"
151
152# Remove revoked key
153cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
154${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-d 2>/dev/null
155# revoked key should not be removed.
156diff -u $OBJ/kh.hosts $OBJ/kh.hosts.orig || fail "remove revoked"
157
158# Remove wildcard
159cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
160${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-e.blahblah 2>/dev/null
161grep -v "^host-e[*] " $OBJ/kh.hosts.orig > $OBJ/kh.expect
162diff -u $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
163
164# Remove multiple
165cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
166${SSHKEYGEN} -qf $OBJ/kh.hosts -R host-h 2>/dev/null
167grep -v "^host-f," $OBJ/kh.hosts.orig > $OBJ/kh.expect
168diff -u $OBJ/kh.hosts $OBJ/kh.expect || fail "remove wildcard"
169
170# Attempt hash on invalid file
171cp $OBJ/kh.invalid.orig $OBJ/kh.invalid
172${SSHKEYGEN} -qf $OBJ/kh.invalid -H 2>/dev/null && fail "hash invalid succeeded"
173diff -u $OBJ/kh.invalid $OBJ/kh.invalid.orig || fail "invalid file modified"
174
175# Hash valid file
176cp $OBJ/kh.hosts.orig $OBJ/kh.hosts
177${SSHKEYGEN} -qf $OBJ/kh.hosts -H 2>/dev/null || fail "hash failed"
178diff -u $OBJ/kh.hosts.old $OBJ/kh.hosts.orig || fail "backup differs"
179grep "^host-[abfgh]" $OBJ/kh.hosts && fail "original hostnames persist"
180
181cp $OBJ/kh.hosts $OBJ/kh.hashed.orig
182
183# Test lookup
184rm -f $OBJ/kh.expect
185expect_key host-a host-a host-a
186expect_key host-a host-a host-a2
187check_hashed_find host-a "find simple in hashed" $OBJ/kh.hosts
188
189# Test multiple expanded
190rm -f $OBJ/kh.expect
191expect_key host-h host-h host-f
192check_hashed_find host-h "find simple in hashed" $OBJ/kh.hosts
193
194# Test remove
195cp $OBJ/kh.hashed.orig $OBJ/kh.hashed
196${SSHKEYGEN} -qf $OBJ/kh.hashed -R host-a 2>/dev/null
197${SSHKEYGEN} -qf $OBJ/kh.hashed -F host-a && fail "found key after hashed remove"
diff --git a/regress/keyscan.sh b/regress/keyscan.sh
index 33f14f0fc..886f3295a 100644
--- a/regress/keyscan.sh
+++ b/regress/keyscan.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: keyscan.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ 1# $OpenBSD: keyscan.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="keyscan" 4tid="keyscan"
@@ -8,7 +8,12 @@ rm -f ${OBJ}/host.dsa
8 8
9start_sshd 9start_sshd
10 10
11for t in rsa1 rsa dsa; do 11KEYTYPES="rsa dsa"
12if ssh_version 1; then
13 KEYTYPES="${KEYTYPES} rsa1"
14fi
15
16for t in $KEYTYPES; do
12 trace "keyscan type $t" 17 trace "keyscan type $t"
13 ${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \ 18 ${SSHKEYSCAN} -t $t -p $PORT 127.0.0.1 127.0.0.1 127.0.0.1 \
14 > /dev/null 2>&1 19 > /dev/null 2>&1
diff --git a/regress/krl.sh b/regress/krl.sh
index 287384b4a..1077358ff 100644
--- a/regress/krl.sh
+++ b/regress/krl.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: krl.sh,v 1.3 2014/06/24 01:04:43 djm Exp $ 1# $OpenBSD: krl.sh,v 1.6 2015/01/30 01:11:39 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="key revocation lists" 4tid="key revocation lists"
@@ -17,6 +17,8 @@ rm -f $OBJ/revoked-* $OBJ/krl-*
17# Generate a CA key 17# Generate a CA key
18$SSHKEYGEN -t $ECDSA -f $OBJ/revoked-ca -C "" -N "" > /dev/null || 18$SSHKEYGEN -t $ECDSA -f $OBJ/revoked-ca -C "" -N "" > /dev/null ||
19 fatal "$SSHKEYGEN CA failed" 19 fatal "$SSHKEYGEN CA failed"
20$SSHKEYGEN -t ed25519 -f $OBJ/revoked-ca2 -C "" -N "" > /dev/null ||
21 fatal "$SSHKEYGEN CA2 failed"
20 22
21# A specification that revokes some certificates by serial numbers 23# A specification that revokes some certificates by serial numbers
22# The serial pattern is chosen to ensure the KRL includes list, range and 24# The serial pattern is chosen to ensure the KRL includes list, range and
@@ -45,6 +47,7 @@ EOF
45# A specification that revokes some certificated by key ID. 47# A specification that revokes some certificated by key ID.
46touch $OBJ/revoked-keyid 48touch $OBJ/revoked-keyid
47for n in 1 2 3 4 10 15 30 50 `jot 500 300` 999 1000 1001 1002; do 49for n in 1 2 3 4 10 15 30 50 `jot 500 300` 999 1000 1001 1002; do
50 test "x$n" = "x499" && continue
48 # Fill in by-ID revocation spec. 51 # Fill in by-ID revocation spec.
49 echo "id: revoked $n" >> $OBJ/revoked-keyid 52 echo "id: revoked $n" >> $OBJ/revoked-keyid
50done 53done
@@ -56,7 +59,7 @@ keygen() {
56 keytype=$ECDSA 59 keytype=$ECDSA
57 case $N in 60 case $N in
58 2 | 10 | 510 | 1001) keytype=rsa;; 61 2 | 10 | 510 | 1001) keytype=rsa;;
59 4 | 30 | 520 | 1002) keytype=dsa;; 62 4 | 30 | 520 | 1002) keytype=ed25519;;
60 esac 63 esac
61 $SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \ 64 $SSHKEYGEN -t $keytype -f $f -C "" -N "" > /dev/null \
62 || fatal "$SSHKEYGEN failed" 65 || fatal "$SSHKEYGEN failed"
@@ -71,37 +74,48 @@ verbose "$tid: generating test keys"
71REVOKED_SERIALS="1 4 10 50 500 510 520 799 999" 74REVOKED_SERIALS="1 4 10 50 500 510 520 799 999"
72for n in $REVOKED_SERIALS ; do 75for n in $REVOKED_SERIALS ; do
73 f=`keygen $n` 76 f=`keygen $n`
74 REVOKED_KEYS="$REVOKED_KEYS ${f}.pub" 77 RKEYS="$RKEYS ${f}.pub"
75 REVOKED_CERTS="$REVOKED_CERTS ${f}-cert.pub" 78 RCERTS="$RCERTS ${f}-cert.pub"
76done 79done
77NOTREVOKED_SERIALS="5 9 14 16 29 30 49 51 499 800 1000 1001" 80UNREVOKED_SERIALS="5 9 14 16 29 49 51 499 800 1010 1011"
78NOTREVOKED="" 81UNREVOKED=""
79for n in $NOTREVOKED_SERIALS ; do 82for n in $UNREVOKED_SERIALS ; do
80 NOTREVOKED_KEYS="$NOTREVOKED_KEYS ${f}.pub" 83 f=`keygen $n`
81 NOTREVOKED_CERTS="$NOTREVOKED_CERTS ${f}-cert.pub" 84 UKEYS="$UKEYS ${f}.pub"
85 UCERTS="$UCERTS ${f}-cert.pub"
82done 86done
83 87
84genkrls() { 88genkrls() {
85 OPTS=$1 89 OPTS=$1
86$SSHKEYGEN $OPTS -kf $OBJ/krl-empty - </dev/null \ 90$SSHKEYGEN $OPTS -kf $OBJ/krl-empty - </dev/null \
87 >/dev/null || fatal "$SSHKEYGEN KRL failed" 91 >/dev/null || fatal "$SSHKEYGEN KRL failed"
88$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $REVOKED_KEYS \ 92$SSHKEYGEN $OPTS -kf $OBJ/krl-keys $RKEYS \
89 >/dev/null || fatal "$SSHKEYGEN KRL failed" 93 >/dev/null || fatal "$SSHKEYGEN KRL failed"
90$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $REVOKED_CERTS \ 94$SSHKEYGEN $OPTS -kf $OBJ/krl-cert $RCERTS \
91 >/dev/null || fatal "$SSHKEYGEN KRL failed" 95 >/dev/null || fatal "$SSHKEYGEN KRL failed"
92$SSHKEYGEN $OPTS -kf $OBJ/krl-all $REVOKED_KEYS $REVOKED_CERTS \ 96$SSHKEYGEN $OPTS -kf $OBJ/krl-all $RKEYS $RCERTS \
93 >/dev/null || fatal "$SSHKEYGEN KRL failed" 97 >/dev/null || fatal "$SSHKEYGEN KRL failed"
94$SSHKEYGEN $OPTS -kf $OBJ/krl-ca $OBJ/revoked-ca.pub \ 98$SSHKEYGEN $OPTS -kf $OBJ/krl-ca $OBJ/revoked-ca.pub \
95 >/dev/null || fatal "$SSHKEYGEN KRL failed" 99 >/dev/null || fatal "$SSHKEYGEN KRL failed"
96# KRLs from serial/key-id spec need the CA specified. 100# This should fail as KRLs from serial/key-id spec need the CA specified.
97$SSHKEYGEN $OPTS -kf $OBJ/krl-serial $OBJ/revoked-serials \ 101$SSHKEYGEN $OPTS -kf $OBJ/krl-serial $OBJ/revoked-serials \
98 >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly" 102 >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly"
99$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid $OBJ/revoked-keyid \ 103$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid $OBJ/revoked-keyid \
100 >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly" 104 >/dev/null 2>&1 && fatal "$SSHKEYGEN KRL succeeded unexpectedly"
101$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca $OBJ/revoked-serials \ 105# These should succeed; they specify an explicit CA key.
106$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -s $OBJ/revoked-ca \
107 $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed"
108$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub \
109 $OBJ/revoked-keyid >/dev/null || fatal "$SSHKEYGEN KRL failed"
110# These should succeed; they specify an wildcard CA key.
111$SSHKEYGEN $OPTS -kf $OBJ/krl-serial-wild -s NONE $OBJ/revoked-serials \
102 >/dev/null || fatal "$SSHKEYGEN KRL failed" 112 >/dev/null || fatal "$SSHKEYGEN KRL failed"
103$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid -s $OBJ/revoked-ca.pub $OBJ/revoked-keyid \ 113$SSHKEYGEN $OPTS -kf $OBJ/krl-keyid-wild -s NONE $OBJ/revoked-keyid \
104 >/dev/null || fatal "$SSHKEYGEN KRL failed" 114 >/dev/null || fatal "$SSHKEYGEN KRL failed"
115# Revoke the same serials with the second CA key to ensure a multi-CA
116# KRL is generated.
117$SSHKEYGEN $OPTS -kf $OBJ/krl-serial -u -s $OBJ/revoked-ca2 \
118 $OBJ/revoked-serials >/dev/null || fatal "$SSHKEYGEN KRL failed"
105} 119}
106 120
107## XXX dump with trace and grep for set cert serials 121## XXX dump with trace and grep for set cert serials
@@ -123,7 +137,7 @@ check_krl() {
123 fatal "key $KEY unexpectedly revoked by KRL $KRL: $TAG" 137 fatal "key $KEY unexpectedly revoked by KRL $KRL: $TAG"
124 fi 138 fi
125} 139}
126test_all() { 140test_rev() {
127 FILES=$1 141 FILES=$1
128 TAG=$2 142 TAG=$2
129 KEYS_RESULT=$3 143 KEYS_RESULT=$3
@@ -132,32 +146,40 @@ test_all() {
132 KEYID_RESULT=$6 146 KEYID_RESULT=$6
133 CERTS_RESULT=$7 147 CERTS_RESULT=$7
134 CA_RESULT=$8 148 CA_RESULT=$8
149 SERIAL_WRESULT=$9
150 KEYID_WRESULT=$10
135 verbose "$tid: checking revocations for $TAG" 151 verbose "$tid: checking revocations for $TAG"
136 for f in $FILES ; do 152 for f in $FILES ; do
137 check_krl $f $OBJ/krl-empty no "$TAG" 153 check_krl $f $OBJ/krl-empty no "$TAG"
138 check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG" 154 check_krl $f $OBJ/krl-keys $KEYS_RESULT "$TAG"
139 check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG" 155 check_krl $f $OBJ/krl-all $ALL_RESULT "$TAG"
140 check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG" 156 check_krl $f $OBJ/krl-serial $SERIAL_RESULT "$TAG"
141 check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG" 157 check_krl $f $OBJ/krl-keyid $KEYID_RESULT "$TAG"
142 check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG" 158 check_krl $f $OBJ/krl-cert $CERTS_RESULT "$TAG"
143 check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG" 159 check_krl $f $OBJ/krl-ca $CA_RESULT "$TAG"
160 check_krl $f $OBJ/krl-serial-wild $SERIAL_WRESULT "$TAG"
161 check_krl $f $OBJ/krl-keyid-wild $KEYID_WRESULT "$TAG"
144 done 162 done
145} 163}
146# keys all serial keyid certs CA 164
147test_all "$REVOKED_KEYS" "revoked keys" yes yes no no no no 165test_all() {
148test_all "$UNREVOKED_KEYS" "unrevoked keys" no no no no no no 166 # wildcard
149test_all "$REVOKED_CERTS" "revoked certs" yes yes yes yes yes yes 167 # keys all sr# k.ID cert CA sr.# k.ID
150test_all "$UNREVOKED_CERTS" "unrevoked certs" no no no no no yes 168 test_rev "$RKEYS" "revoked keys" yes yes no no no no no no
169 test_rev "$UKEYS" "unrevoked keys" no no no no no no no no
170 test_rev "$RCERTS" "revoked certs" yes yes yes yes yes yes yes yes
171 test_rev "$UCERTS" "unrevoked certs" no no no no no yes no no
172}
173
174test_all
151 175
152# Check update. Results should be identical. 176# Check update. Results should be identical.
153verbose "$tid: testing KRL update" 177verbose "$tid: testing KRL update"
154for f in $OBJ/krl-keys $OBJ/krl-cert $OBJ/krl-all \ 178for f in $OBJ/krl-keys $OBJ/krl-cert $OBJ/krl-all \
155 $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid ; do 179 $OBJ/krl-ca $OBJ/krl-serial $OBJ/krl-keyid \
180 $OBJ/krl-serial-wild $OBJ/krl-keyid-wild; do
156 cp -f $OBJ/krl-empty $f 181 cp -f $OBJ/krl-empty $f
157 genkrls -u 182 genkrls -u
158done 183done
159# keys all serial keyid certs CA 184
160test_all "$REVOKED_KEYS" "revoked keys" yes yes no no no no 185test_all
161test_all "$UNREVOKED_KEYS" "unrevoked keys" no no no no no no
162test_all "$REVOKED_CERTS" "revoked certs" yes yes yes yes yes yes
163test_all "$UNREVOKED_CERTS" "unrevoked certs" no no no no no yes
diff --git a/regress/limit-keytype.sh b/regress/limit-keytype.sh
new file mode 100644
index 000000000..2de037bd1
--- /dev/null
+++ b/regress/limit-keytype.sh
@@ -0,0 +1,80 @@
1# $OpenBSD: limit-keytype.sh,v 1.1 2015/01/13 07:49:49 djm Exp $
2# Placed in the Public Domain.
3
4tid="restrict pubkey type"
5
6rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
7rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
8
9mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
10mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
11
12# Create a CA key
13${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\
14 fatal "ssh-keygen failed"
15
16# Make some keys and a certificate.
17${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
18 fatal "ssh-keygen failed"
19${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_key2 || \
20 fatal "ssh-keygen failed"
21${SSHKEYGEN} -q -N '' -t rsa -f $OBJ/user_key3 || \
22 fatal "ssh-keygen failed"
23${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
24 -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key3 ||
25 fatal "couldn't sign user_key1"
26# Copy the private key alongside the cert to allow better control of when
27# it is offered.
28mv $OBJ/user_key3-cert.pub $OBJ/cert_user_key3.pub
29cp -p $OBJ/user_key3 $OBJ/cert_user_key3
30
31grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
32
33opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
34fullopts="$opts -i $OBJ/cert_user_key3 -i $OBJ/user_key1 -i $OBJ/user_key2"
35
36echo mekmitasdigoat > $OBJ/authorized_principals_$USER
37cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
38cat $OBJ/user_key2.pub >> $OBJ/authorized_keys_$USER
39
40prepare_config() {
41 (
42 grep -v "Protocol" $OBJ/sshd_proxy.orig
43 echo "Protocol 2"
44 echo "AuthenticationMethods publickey"
45 echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
46 echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
47 for x in "$@" ; do
48 echo "$x"
49 done
50 ) > $OBJ/sshd_proxy
51}
52
53prepare_config
54
55# Check we can log in with all key types.
56${SSH} $opts -i $OBJ/cert_user_key3 proxy true || fatal "cert failed"
57${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
58${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
59
60# Allow plain Ed25519 and RSA. The certificate should fail.
61verbose "privsep=$privsep allow rsa,ed25519"
62prepare_config "PubkeyAcceptedKeyTypes ssh-rsa,ssh-ed25519"
63${SSH} $opts -i $OBJ/cert_user_key3 proxy true && fatal "cert succeeded"
64${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
65${SSH} $opts -i $OBJ/user_key2 proxy true || fatal "key2 failed"
66
67# Allow Ed25519 only.
68verbose "privsep=$privsep allow ed25519"
69prepare_config "PubkeyAcceptedKeyTypes ssh-ed25519"
70${SSH} $opts -i $OBJ/cert_user_key3 proxy true && fatal "cert succeeded"
71${SSH} $opts -i $OBJ/user_key1 proxy true || fatal "key1 failed"
72${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded"
73
74# Allow all certs. Plain keys should fail.
75verbose "privsep=$privsep allow cert only"
76prepare_config "PubkeyAcceptedKeyTypes ssh-*-cert-v01@openssh.com"
77${SSH} $opts -i $OBJ/cert_user_key3 proxy true || fatal "cert failed"
78${SSH} $opts -i $OBJ/user_key1 proxy true && fatal "key1 succeeded"
79${SSH} $opts -i $OBJ/user_key2 proxy true && fatal "key2 succeeded"
80
diff --git a/regress/localcommand.sh b/regress/localcommand.sh
index 8a9b56971..220f19a4d 100644
--- a/regress/localcommand.sh
+++ b/regress/localcommand.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: localcommand.sh,v 1.2 2013/05/17 10:24:48 dtucker Exp $ 1# $OpenBSD: localcommand.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="localcommand" 4tid="localcommand"
@@ -6,7 +6,7 @@ tid="localcommand"
6echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy 6echo 'PermitLocalCommand yes' >> $OBJ/ssh_proxy
7echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy 7echo 'LocalCommand echo foo' >> $OBJ/ssh_proxy
8 8
9for p in 1 2; do 9for p in ${SSH_PROTOCOLS}; do
10 verbose "test $tid: proto $p localcommand" 10 verbose "test $tid: proto $p localcommand"
11 a=`${SSH} -F $OBJ/ssh_proxy -$p somehost true` 11 a=`${SSH} -F $OBJ/ssh_proxy -$p somehost true`
12 if [ "$a" != "foo" ] ; then 12 if [ "$a" != "foo" ] ; then
diff --git a/regress/multiplex.sh b/regress/multiplex.sh
index 8ee140be6..acb9234d9 100644
--- a/regress/multiplex.sh
+++ b/regress/multiplex.sh
@@ -1,24 +1,11 @@
1# $OpenBSD: multiplex.sh,v 1.25 2014/07/22 01:32:12 djm Exp $ 1# $OpenBSD: multiplex.sh,v 1.27 2014/12/22 06:14:29 djm Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4CTL=/tmp/openssh.regress.ctl-sock.$$ 4CTL=/tmp/openssh.regress.ctl-sock.$$
5 5
6tid="connection multiplexing" 6tid="connection multiplexing"
7 7
8if have_prog nc ; then 8NC=$OBJ/netcat
9 if nc -h 2>&1 | grep -- -N >/dev/null; then
10 NC="nc -N";
11 elif nc -h 2>&1 | grep -- "-U.*Use UNIX" >/dev/null ; then
12 NC="nc"
13 else
14 echo "nc is incompatible"
15 fi
16fi
17
18if test -z "$NC" ; then
19 echo "skipped (no compatible nc found)"
20 exit 0
21fi
22 9
23trace "will use ProxyCommand $proxycmd" 10trace "will use ProxyCommand $proxycmd"
24if config_defined DISABLE_FD_PASSING ; then 11if config_defined DISABLE_FD_PASSING ; then
@@ -90,20 +77,20 @@ cmp ${DATA} ${COPY} || fail "scp: corrupted copy of ${DATA}"
90rm -f ${COPY} 77rm -f ${COPY}
91verbose "test $tid: forward" 78verbose "test $tid: forward"
92trace "forward over TCP/IP and check result" 79trace "forward over TCP/IP and check result"
93$NC -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} & 80$NC -N -l 127.0.0.1 $((${PORT} + 1)) < ${DATA} > /dev/null &
94netcat_pid=$! 81netcat_pid=$!
95${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1 82${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L127.0.0.1:$((${PORT} + 2)):127.0.0.1:$((${PORT} + 1)) otherhost >>$TEST_SSH_LOGFILE 2>&1
96$NC -d 127.0.0.1 $((${PORT} + 2)) > ${COPY} < /dev/null 83$NC 127.0.0.1 $((${PORT} + 2)) < /dev/null > ${COPY}
97cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" 84cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
98kill $netcat_pid 2>/dev/null 85kill $netcat_pid 2>/dev/null
99rm -f ${COPY} $OBJ/unix-[123].fwd 86rm -f ${COPY} $OBJ/unix-[123].fwd
100 87
101trace "forward over UNIX and check result" 88trace "forward over UNIX and check result"
102$NC -Ul $OBJ/unix-1.fwd < ${DATA} & 89$NC -N -Ul $OBJ/unix-1.fwd < ${DATA} > /dev/null &
103netcat_pid=$! 90netcat_pid=$!
104${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 91${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -L$OBJ/unix-2.fwd:$OBJ/unix-1.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
105${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1 92${SSH} -F $OBJ/ssh_config -S $CTL -Oforward -R$OBJ/unix-3.fwd:$OBJ/unix-2.fwd otherhost >>$TEST_SSH_LOGFILE 2>&1
106$NC -d -U $OBJ/unix-3.fwd > ${COPY} </dev/null 93$NC -U $OBJ/unix-3.fwd < /dev/null > ${COPY} 2>/dev/null
107cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}" 94cmp ${DATA} ${COPY} || fail "ssh: corrupted copy of ${DATA}"
108kill $netcat_pid 2>/dev/null 95kill $netcat_pid 2>/dev/null
109rm -f ${COPY} $OBJ/unix-[123].fwd 96rm -f ${COPY} $OBJ/unix-[123].fwd
diff --git a/regress/multipubkey.sh b/regress/multipubkey.sh
new file mode 100644
index 000000000..e9d15306f
--- /dev/null
+++ b/regress/multipubkey.sh
@@ -0,0 +1,66 @@
1# $OpenBSD: multipubkey.sh,v 1.1 2014/12/22 08:06:03 djm Exp $
2# Placed in the Public Domain.
3
4tid="multiple pubkey"
5
6rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/user_key*
7rm -f $OBJ/authorized_principals_$USER $OBJ/cert_user_key*
8
9mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
10mv $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
11
12# Create a CA key
13${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_ca_key ||\
14 fatal "ssh-keygen failed"
15
16# Make some keys and a certificate.
17${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key1 || \
18 fatal "ssh-keygen failed"
19${SSHKEYGEN} -q -N '' -t ed25519 -f $OBJ/user_key2 || \
20 fatal "ssh-keygen failed"
21${SSHKEYGEN} -q -s $OBJ/user_ca_key -I "regress user key for $USER" \
22 -z $$ -n ${USER},mekmitasdigoat $OBJ/user_key1 ||
23 fail "couldn't sign user_key1"
24# Copy the private key alongside the cert to allow better control of when
25# it is offered.
26mv $OBJ/user_key1-cert.pub $OBJ/cert_user_key1.pub
27cp -p $OBJ/user_key1 $OBJ/cert_user_key1
28
29grep -v IdentityFile $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
30
31opts="-oProtocol=2 -F $OBJ/ssh_proxy -oIdentitiesOnly=yes"
32opts="$opts -i $OBJ/cert_user_key1 -i $OBJ/user_key1 -i $OBJ/user_key2"
33
34for privsep in no yes; do
35 (
36 grep -v "Protocol" $OBJ/sshd_proxy.orig
37 echo "Protocol 2"
38 echo "UsePrivilegeSeparation $privsep"
39 echo "AuthenticationMethods publickey,publickey"
40 echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
41 echo "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
42 ) > $OBJ/sshd_proxy
43
44 # Single key should fail.
45 rm -f $OBJ/authorized_principals_$USER
46 cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
47 ${SSH} $opts proxy true && fail "ssh succeeded with key"
48
49 # Single key with same-public cert should fail.
50 echo mekmitasdigoat > $OBJ/authorized_principals_$USER
51 cat $OBJ/user_key1.pub > $OBJ/authorized_keys_$USER
52 ${SSH} $opts proxy true && fail "ssh succeeded with key+cert"
53
54 # Multiple plain keys should succeed.
55 rm -f $OBJ/authorized_principals_$USER
56 cat $OBJ/user_key1.pub $OBJ/user_key2.pub > \
57 $OBJ/authorized_keys_$USER
58 ${SSH} $opts proxy true || fail "ssh failed with multiple keys"
59 # Cert and different key should succeed
60
61 # Key and different-public cert should succeed.
62 echo mekmitasdigoat > $OBJ/authorized_principals_$USER
63 cat $OBJ/user_key2.pub > $OBJ/authorized_keys_$USER
64 ${SSH} $opts proxy true || fail "ssh failed with key/cert"
65done
66
diff --git a/regress/netcat.c b/regress/netcat.c
new file mode 100644
index 000000000..1a9fc8730
--- /dev/null
+++ b/regress/netcat.c
@@ -0,0 +1,1690 @@
1/* $OpenBSD: netcat.c,v 1.126 2014/10/30 16:08:31 tedu Exp $ */
2/*
3 * Copyright (c) 2001 Eric Jackson <ericj@monkey.org>
4 *
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
7 * are met:
8 *
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. The name of the author may not be used to endorse or promote products
15 * derived from this software without specific prior written permission.
16 *
17 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
18 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
19 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
20 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
21 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
22 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
23 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
24 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
25 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
26 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
27 */
28
29/*
30 * Re-written nc(1) for OpenBSD. Original implementation by
31 * *Hobbit* <hobbit@avian.org>.
32 */
33
34#include "includes.h"
35
36#include <sys/types.h>
37#include <sys/socket.h>
38#include <sys/time.h>
39#include <sys/uio.h>
40#include <sys/un.h>
41
42#include <netinet/in.h>
43#include <netinet/tcp.h>
44#include <netinet/ip.h>
45#include <arpa/telnet.h>
46
47#include <errno.h>
48#include <netdb.h>
49#include <stdarg.h>
50#include <stdio.h>
51#include <stdlib.h>
52#include <string.h>
53#include <unistd.h>
54#include <fcntl.h>
55#include <limits.h>
56#include "atomicio.h"
57
58#ifdef HAVE_POLL_H
59#include <poll.h>
60#else
61# ifdef HAVE_SYS_POLL_H
62# include <sys/poll.h>
63# endif
64#endif
65
66#ifndef SUN_LEN
67#define SUN_LEN(su) \
68 (sizeof(*(su)) - sizeof((su)->sun_path) + strlen((su)->sun_path))
69#endif
70
71#define PORT_MAX 65535
72#define PORT_MAX_LEN 6
73#define UNIX_DG_TMP_SOCKET_SIZE 19
74
75#define POLL_STDIN 0
76#define POLL_NETOUT 1
77#define POLL_NETIN 2
78#define POLL_STDOUT 3
79#define BUFSIZE 16384
80
81/* Command Line Options */
82int dflag; /* detached, no stdin */
83int Fflag; /* fdpass sock to stdout */
84unsigned int iflag; /* Interval Flag */
85int kflag; /* More than one connect */
86int lflag; /* Bind to local port */
87int Nflag; /* shutdown() network socket */
88int nflag; /* Don't do name look up */
89char *Pflag; /* Proxy username */
90char *pflag; /* Localport flag */
91int rflag; /* Random ports flag */
92char *sflag; /* Source Address */
93int tflag; /* Telnet Emulation */
94int uflag; /* UDP - Default to TCP */
95int vflag; /* Verbosity */
96int xflag; /* Socks proxy */
97int zflag; /* Port Scan Flag */
98int Dflag; /* sodebug */
99int Iflag; /* TCP receive buffer size */
100int Oflag; /* TCP send buffer size */
101int Sflag; /* TCP MD5 signature option */
102int Tflag = -1; /* IP Type of Service */
103int rtableid = -1;
104
105int timeout = -1;
106int family = AF_UNSPEC;
107char *portlist[PORT_MAX+1];
108char *unix_dg_tmp_socket;
109
110void atelnet(int, unsigned char *, unsigned int);
111void build_ports(char *);
112void help(void);
113int local_listen(char *, char *, struct addrinfo);
114void readwrite(int);
115void fdpass(int nfd) __attribute__((noreturn));
116int remote_connect(const char *, const char *, struct addrinfo);
117int timeout_connect(int, const struct sockaddr *, socklen_t);
118int socks_connect(const char *, const char *, struct addrinfo,
119 const char *, const char *, struct addrinfo, int, const char *);
120int udptest(int);
121int unix_bind(char *);
122int unix_connect(char *);
123int unix_listen(char *);
124void set_common_sockopts(int);
125int map_tos(char *, int *);
126void report_connect(const struct sockaddr *, socklen_t);
127void usage(int);
128ssize_t drainbuf(int, unsigned char *, size_t *);
129ssize_t fillbuf(int, unsigned char *, size_t *);
130
131static void err(int, const char *, ...) __attribute__((format(printf, 2, 3)));
132static void errx(int, const char *, ...) __attribute__((format(printf, 2, 3)));
133static void warn(const char *, ...) __attribute__((format(printf, 1, 2)));
134
135static void
136err(int r, const char *fmt, ...)
137{
138 va_list args;
139
140 va_start(args, fmt);
141 fprintf(stderr, "%s: ", strerror(errno));
142 vfprintf(stderr, fmt, args);
143 fputc('\n', stderr);
144 va_end(args);
145 exit(r);
146}
147
148static void
149errx(int r, const char *fmt, ...)
150{
151 va_list args;
152
153 va_start(args, fmt);
154 vfprintf(stderr, fmt, args);
155 fputc('\n', stderr);
156 va_end(args);
157 exit(r);
158}
159
160static void
161warn(const char *fmt, ...)
162{
163 va_list args;
164
165 va_start(args, fmt);
166 fprintf(stderr, "%s: ", strerror(errno));
167 vfprintf(stderr, fmt, args);
168 fputc('\n', stderr);
169 va_end(args);
170}
171
172int
173main(int argc, char *argv[])
174{
175 int ch, s, ret, socksv;
176 char *host, *uport;
177 struct addrinfo hints;
178 struct servent *sv;
179 socklen_t len;
180 struct sockaddr_storage cliaddr;
181 char *proxy = NULL;
182 const char *errstr, *proxyhost = "", *proxyport = NULL;
183 struct addrinfo proxyhints;
184 char unix_dg_tmp_socket_buf[UNIX_DG_TMP_SOCKET_SIZE];
185
186 ret = 1;
187 s = 0;
188 socksv = 5;
189 host = NULL;
190 uport = NULL;
191 sv = NULL;
192
193 while ((ch = getopt(argc, argv,
194 "46DdFhI:i:klNnO:P:p:rSs:tT:UuV:vw:X:x:z")) != -1) {
195 switch (ch) {
196 case '4':
197 family = AF_INET;
198 break;
199 case '6':
200 family = AF_INET6;
201 break;
202 case 'U':
203 family = AF_UNIX;
204 break;
205 case 'X':
206 if (strcasecmp(optarg, "connect") == 0)
207 socksv = -1; /* HTTP proxy CONNECT */
208 else if (strcmp(optarg, "4") == 0)
209 socksv = 4; /* SOCKS v.4 */
210 else if (strcmp(optarg, "5") == 0)
211 socksv = 5; /* SOCKS v.5 */
212 else
213 errx(1, "unsupported proxy protocol");
214 break;
215 case 'd':
216 dflag = 1;
217 break;
218 case 'F':
219 Fflag = 1;
220 break;
221 case 'h':
222 help();
223 break;
224 case 'i':
225 iflag = strtonum(optarg, 0, UINT_MAX, &errstr);
226 if (errstr)
227 errx(1, "interval %s: %s", errstr, optarg);
228 break;
229 case 'k':
230 kflag = 1;
231 break;
232 case 'l':
233 lflag = 1;
234 break;
235 case 'N':
236 Nflag = 1;
237 break;
238 case 'n':
239 nflag = 1;
240 break;
241 case 'P':
242 Pflag = optarg;
243 break;
244 case 'p':
245 pflag = optarg;
246 break;
247 case 'r':
248 rflag = 1;
249 break;
250 case 's':
251 sflag = optarg;
252 break;
253 case 't':
254 tflag = 1;
255 break;
256 case 'u':
257 uflag = 1;
258 break;
259#ifdef SO_RTABLE
260 case 'V':
261 rtableid = (int)strtonum(optarg, 0,
262 RT_TABLEID_MAX, &errstr);
263 if (errstr)
264 errx(1, "rtable %s: %s", errstr, optarg);
265 break;
266#endif
267 case 'v':
268 vflag = 1;
269 break;
270 case 'w':
271 timeout = strtonum(optarg, 0, INT_MAX / 1000, &errstr);
272 if (errstr)
273 errx(1, "timeout %s: %s", errstr, optarg);
274 timeout *= 1000;
275 break;
276 case 'x':
277 xflag = 1;
278 if ((proxy = strdup(optarg)) == NULL)
279 errx(1, "strdup");
280 break;
281 case 'z':
282 zflag = 1;
283 break;
284 case 'D':
285 Dflag = 1;
286 break;
287 case 'I':
288 Iflag = strtonum(optarg, 1, 65536 << 14, &errstr);
289 if (errstr != NULL)
290 errx(1, "TCP receive window %s: %s",
291 errstr, optarg);
292 break;
293 case 'O':
294 Oflag = strtonum(optarg, 1, 65536 << 14, &errstr);
295 if (errstr != NULL)
296 errx(1, "TCP send window %s: %s",
297 errstr, optarg);
298 break;
299 case 'S':
300 Sflag = 1;
301 break;
302 case 'T':
303 errstr = NULL;
304 errno = 0;
305 if (map_tos(optarg, &Tflag))
306 break;
307 if (strlen(optarg) > 1 && optarg[0] == '0' &&
308 optarg[1] == 'x')
309 Tflag = (int)strtol(optarg, NULL, 16);
310 else
311 Tflag = (int)strtonum(optarg, 0, 255,
312 &errstr);
313 if (Tflag < 0 || Tflag > 255 || errstr || errno)
314 errx(1, "illegal tos value %s", optarg);
315 break;
316 default:
317 usage(1);
318 }
319 }
320 argc -= optind;
321 argv += optind;
322
323 /* Cruft to make sure options are clean, and used properly. */
324 if (argv[0] && !argv[1] && family == AF_UNIX) {
325 host = argv[0];
326 uport = NULL;
327 } else if (argv[0] && !argv[1]) {
328 if (!lflag)
329 usage(1);
330 uport = argv[0];
331 host = NULL;
332 } else if (argv[0] && argv[1]) {
333 host = argv[0];
334 uport = argv[1];
335 } else
336 usage(1);
337
338 if (lflag && sflag)
339 errx(1, "cannot use -s and -l");
340 if (lflag && pflag)
341 errx(1, "cannot use -p and -l");
342 if (lflag && zflag)
343 errx(1, "cannot use -z and -l");
344 if (!lflag && kflag)
345 errx(1, "must use -l with -k");
346
347 /* Get name of temporary socket for unix datagram client */
348 if ((family == AF_UNIX) && uflag && !lflag) {
349 if (sflag) {
350 unix_dg_tmp_socket = sflag;
351 } else {
352 strlcpy(unix_dg_tmp_socket_buf, "/tmp/nc.XXXXXXXXXX",
353 UNIX_DG_TMP_SOCKET_SIZE);
354 if (mktemp(unix_dg_tmp_socket_buf) == NULL)
355 err(1, "mktemp");
356 unix_dg_tmp_socket = unix_dg_tmp_socket_buf;
357 }
358 }
359
360 /* Initialize addrinfo structure. */
361 if (family != AF_UNIX) {
362 memset(&hints, 0, sizeof(struct addrinfo));
363 hints.ai_family = family;
364 hints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
365 hints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
366 if (nflag)
367 hints.ai_flags |= AI_NUMERICHOST;
368 }
369
370 if (xflag) {
371 if (uflag)
372 errx(1, "no proxy support for UDP mode");
373
374 if (lflag)
375 errx(1, "no proxy support for listen");
376
377 if (family == AF_UNIX)
378 errx(1, "no proxy support for unix sockets");
379
380 /* XXX IPv6 transport to proxy would probably work */
381 if (family == AF_INET6)
382 errx(1, "no proxy support for IPv6");
383
384 if (sflag)
385 errx(1, "no proxy support for local source address");
386
387 proxyhost = strsep(&proxy, ":");
388 proxyport = proxy;
389
390 memset(&proxyhints, 0, sizeof(struct addrinfo));
391 proxyhints.ai_family = family;
392 proxyhints.ai_socktype = SOCK_STREAM;
393 proxyhints.ai_protocol = IPPROTO_TCP;
394 if (nflag)
395 proxyhints.ai_flags |= AI_NUMERICHOST;
396 }
397
398 if (lflag) {
399 int connfd;
400 ret = 0;
401
402 if (family == AF_UNIX) {
403 if (uflag)
404 s = unix_bind(host);
405 else
406 s = unix_listen(host);
407 }
408
409 /* Allow only one connection at a time, but stay alive. */
410 for (;;) {
411 if (family != AF_UNIX)
412 s = local_listen(host, uport, hints);
413 if (s < 0)
414 err(1, "local_listen");
415 /*
416 * For UDP and -k, don't connect the socket, let it
417 * receive datagrams from multiple socket pairs.
418 */
419 if (uflag && kflag)
420 readwrite(s);
421 /*
422 * For UDP and not -k, we will use recvfrom() initially
423 * to wait for a caller, then use the regular functions
424 * to talk to the caller.
425 */
426 else if (uflag && !kflag) {
427 int rv, plen;
428 char buf[16384];
429 struct sockaddr_storage z;
430
431 len = sizeof(z);
432 plen = 2048;
433 rv = recvfrom(s, buf, plen, MSG_PEEK,
434 (struct sockaddr *)&z, &len);
435 if (rv < 0)
436 err(1, "recvfrom");
437
438 rv = connect(s, (struct sockaddr *)&z, len);
439 if (rv < 0)
440 err(1, "connect");
441
442 if (vflag)
443 report_connect((struct sockaddr *)&z, len);
444
445 readwrite(s);
446 } else {
447 len = sizeof(cliaddr);
448 connfd = accept(s, (struct sockaddr *)&cliaddr,
449 &len);
450 if (connfd == -1) {
451 /* For now, all errnos are fatal */
452 err(1, "accept");
453 }
454 if (vflag)
455 report_connect((struct sockaddr *)&cliaddr, len);
456
457 readwrite(connfd);
458 close(connfd);
459 }
460
461 if (family != AF_UNIX)
462 close(s);
463 else if (uflag) {
464 if (connect(s, NULL, 0) < 0)
465 err(1, "connect");
466 }
467
468 if (!kflag)
469 break;
470 }
471 } else if (family == AF_UNIX) {
472 ret = 0;
473
474 if ((s = unix_connect(host)) > 0 && !zflag) {
475 readwrite(s);
476 close(s);
477 } else
478 ret = 1;
479
480 if (uflag)
481 unlink(unix_dg_tmp_socket);
482 exit(ret);
483
484 } else {
485 int i = 0;
486
487 /* Construct the portlist[] array. */
488 build_ports(uport);
489
490 /* Cycle through portlist, connecting to each port. */
491 for (i = 0; portlist[i] != NULL; i++) {
492 if (s)
493 close(s);
494
495 if (xflag)
496 s = socks_connect(host, portlist[i], hints,
497 proxyhost, proxyport, proxyhints, socksv,
498 Pflag);
499 else
500 s = remote_connect(host, portlist[i], hints);
501
502 if (s < 0)
503 continue;
504
505 ret = 0;
506 if (vflag || zflag) {
507 /* For UDP, make sure we are connected. */
508 if (uflag) {
509 if (udptest(s) == -1) {
510 ret = 1;
511 continue;
512 }
513 }
514
515 /* Don't look up port if -n. */
516 if (nflag)
517 sv = NULL;
518 else {
519 sv = getservbyport(
520 ntohs(atoi(portlist[i])),
521 uflag ? "udp" : "tcp");
522 }
523
524 fprintf(stderr,
525 "Connection to %s %s port [%s/%s] "
526 "succeeded!\n", host, portlist[i],
527 uflag ? "udp" : "tcp",
528 sv ? sv->s_name : "*");
529 }
530 if (Fflag)
531 fdpass(s);
532 else if (!zflag)
533 readwrite(s);
534 }
535 }
536
537 if (s)
538 close(s);
539
540 exit(ret);
541}
542
543/*
544 * unix_bind()
545 * Returns a unix socket bound to the given path
546 */
547int
548unix_bind(char *path)
549{
550 struct sockaddr_un sun_sa;
551 int s;
552
553 /* Create unix domain socket. */
554 if ((s = socket(AF_UNIX, uflag ? SOCK_DGRAM : SOCK_STREAM,
555 0)) < 0)
556 return (-1);
557
558 memset(&sun_sa, 0, sizeof(struct sockaddr_un));
559 sun_sa.sun_family = AF_UNIX;
560
561 if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >=
562 sizeof(sun_sa.sun_path)) {
563 close(s);
564 errno = ENAMETOOLONG;
565 return (-1);
566 }
567
568 if (bind(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) {
569 close(s);
570 return (-1);
571 }
572 return (s);
573}
574
575/*
576 * unix_connect()
577 * Returns a socket connected to a local unix socket. Returns -1 on failure.
578 */
579int
580unix_connect(char *path)
581{
582 struct sockaddr_un sun_sa;
583 int s;
584
585 if (uflag) {
586 if ((s = unix_bind(unix_dg_tmp_socket)) < 0)
587 return (-1);
588 } else {
589 if ((s = socket(AF_UNIX, SOCK_STREAM, 0)) < 0)
590 return (-1);
591 }
592 (void)fcntl(s, F_SETFD, FD_CLOEXEC);
593
594 memset(&sun_sa, 0, sizeof(struct sockaddr_un));
595 sun_sa.sun_family = AF_UNIX;
596
597 if (strlcpy(sun_sa.sun_path, path, sizeof(sun_sa.sun_path)) >=
598 sizeof(sun_sa.sun_path)) {
599 close(s);
600 errno = ENAMETOOLONG;
601 return (-1);
602 }
603 if (connect(s, (struct sockaddr *)&sun_sa, SUN_LEN(&sun_sa)) < 0) {
604 close(s);
605 return (-1);
606 }
607 return (s);
608
609}
610
611/*
612 * unix_listen()
613 * Create a unix domain socket, and listen on it.
614 */
615int
616unix_listen(char *path)
617{
618 int s;
619 if ((s = unix_bind(path)) < 0)
620 return (-1);
621
622 if (listen(s, 5) < 0) {
623 close(s);
624 return (-1);
625 }
626 return (s);
627}
628
629/*
630 * remote_connect()
631 * Returns a socket connected to a remote host. Properly binds to a local
632 * port or source address if needed. Returns -1 on failure.
633 */
634int
635remote_connect(const char *host, const char *port, struct addrinfo hints)
636{
637 struct addrinfo *res, *res0;
638 int s, error;
639#if defined(SO_RTABLE) || defined(SO_BINDANY)
640 int on = 1;
641#endif
642
643 if ((error = getaddrinfo(host, port, &hints, &res)))
644 errx(1, "getaddrinfo: %s", gai_strerror(error));
645
646 res0 = res;
647 do {
648 if ((s = socket(res0->ai_family, res0->ai_socktype,
649 res0->ai_protocol)) < 0)
650 continue;
651
652#ifdef SO_RTABLE
653 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
654 &rtableid, sizeof(rtableid)) == -1))
655 err(1, "setsockopt SO_RTABLE");
656#endif
657 /* Bind to a local port or source address if specified. */
658 if (sflag || pflag) {
659 struct addrinfo ahints, *ares;
660
661#ifdef SO_BINDANY
662 /* try SO_BINDANY, but don't insist */
663 setsockopt(s, SOL_SOCKET, SO_BINDANY, &on, sizeof(on));
664#endif
665 memset(&ahints, 0, sizeof(struct addrinfo));
666 ahints.ai_family = res0->ai_family;
667 ahints.ai_socktype = uflag ? SOCK_DGRAM : SOCK_STREAM;
668 ahints.ai_protocol = uflag ? IPPROTO_UDP : IPPROTO_TCP;
669 ahints.ai_flags = AI_PASSIVE;
670 if ((error = getaddrinfo(sflag, pflag, &ahints, &ares)))
671 errx(1, "getaddrinfo: %s", gai_strerror(error));
672
673 if (bind(s, (struct sockaddr *)ares->ai_addr,
674 ares->ai_addrlen) < 0)
675 err(1, "bind failed");
676 freeaddrinfo(ares);
677 }
678
679 set_common_sockopts(s);
680
681 if (timeout_connect(s, res0->ai_addr, res0->ai_addrlen) == 0)
682 break;
683 else if (vflag)
684 warn("connect to %s port %s (%s) failed", host, port,
685 uflag ? "udp" : "tcp");
686
687 close(s);
688 s = -1;
689 } while ((res0 = res0->ai_next) != NULL);
690
691 freeaddrinfo(res);
692
693 return (s);
694}
695
696int
697timeout_connect(int s, const struct sockaddr *name, socklen_t namelen)
698{
699 struct pollfd pfd;
700 socklen_t optlen;
701 int flags = 0, optval;
702 int ret;
703
704 if (timeout != -1) {
705 flags = fcntl(s, F_GETFL, 0);
706 if (fcntl(s, F_SETFL, flags | O_NONBLOCK) == -1)
707 err(1, "set non-blocking mode");
708 }
709
710 if ((ret = connect(s, name, namelen)) != 0 && errno == EINPROGRESS) {
711 pfd.fd = s;
712 pfd.events = POLLOUT;
713 if ((ret = poll(&pfd, 1, timeout)) == 1) {
714 optlen = sizeof(optval);
715 if ((ret = getsockopt(s, SOL_SOCKET, SO_ERROR,
716 &optval, &optlen)) == 0) {
717 errno = optval;
718 ret = optval == 0 ? 0 : -1;
719 }
720 } else if (ret == 0) {
721 errno = ETIMEDOUT;
722 ret = -1;
723 } else
724 err(1, "poll failed");
725 }
726
727 if (timeout != -1 && fcntl(s, F_SETFL, flags) == -1)
728 err(1, "restoring flags");
729
730 return (ret);
731}
732
733/*
734 * local_listen()
735 * Returns a socket listening on a local port, binds to specified source
736 * address. Returns -1 on failure.
737 */
738int
739local_listen(char *host, char *port, struct addrinfo hints)
740{
741 struct addrinfo *res, *res0;
742 int s, ret, x = 1;
743 int error;
744
745 /* Allow nodename to be null. */
746 hints.ai_flags |= AI_PASSIVE;
747
748 /*
749 * In the case of binding to a wildcard address
750 * default to binding to an ipv4 address.
751 */
752 if (host == NULL && hints.ai_family == AF_UNSPEC)
753 hints.ai_family = AF_INET;
754
755 if ((error = getaddrinfo(host, port, &hints, &res)))
756 errx(1, "getaddrinfo: %s", gai_strerror(error));
757
758 res0 = res;
759 do {
760 if ((s = socket(res0->ai_family, res0->ai_socktype,
761 res0->ai_protocol)) < 0)
762 continue;
763
764#ifdef SO_RTABLE
765 if (rtableid >= 0 && (setsockopt(s, SOL_SOCKET, SO_RTABLE,
766 &rtableid, sizeof(rtableid)) == -1))
767 err(1, "setsockopt SO_RTABLE");
768#endif
769#ifdef SO_REUSEPORT
770 ret = setsockopt(s, SOL_SOCKET, SO_REUSEPORT, &x, sizeof(x));
771 if (ret == -1)
772 err(1, "setsockopt");
773#endif
774 set_common_sockopts(s);
775
776 if (bind(s, (struct sockaddr *)res0->ai_addr,
777 res0->ai_addrlen) == 0)
778 break;
779
780 close(s);
781 s = -1;
782 } while ((res0 = res0->ai_next) != NULL);
783
784 if (!uflag && s != -1) {
785 if (listen(s, 1) < 0)
786 err(1, "listen");
787 }
788
789 freeaddrinfo(res);
790
791 return (s);
792}
793
794/*
795 * readwrite()
796 * Loop that polls on the network file descriptor and stdin.
797 */
798void
799readwrite(int net_fd)
800{
801 struct pollfd pfd[4];
802 int stdin_fd = STDIN_FILENO;
803 int stdout_fd = STDOUT_FILENO;
804 unsigned char netinbuf[BUFSIZE];
805 size_t netinbufpos = 0;
806 unsigned char stdinbuf[BUFSIZE];
807 size_t stdinbufpos = 0;
808 int n, num_fds;
809 ssize_t ret;
810
811 /* don't read from stdin if requested */
812 if (dflag)
813 stdin_fd = -1;
814
815 /* stdin */
816 pfd[POLL_STDIN].fd = stdin_fd;
817 pfd[POLL_STDIN].events = POLLIN;
818
819 /* network out */
820 pfd[POLL_NETOUT].fd = net_fd;
821 pfd[POLL_NETOUT].events = 0;
822
823 /* network in */
824 pfd[POLL_NETIN].fd = net_fd;
825 pfd[POLL_NETIN].events = POLLIN;
826
827 /* stdout */
828 pfd[POLL_STDOUT].fd = stdout_fd;
829 pfd[POLL_STDOUT].events = 0;
830
831 while (1) {
832 /* both inputs are gone, buffers are empty, we are done */
833 if (pfd[POLL_STDIN].fd == -1 && pfd[POLL_NETIN].fd == -1
834 && stdinbufpos == 0 && netinbufpos == 0) {
835 close(net_fd);
836 return;
837 }
838 /* both outputs are gone, we can't continue */
839 if (pfd[POLL_NETOUT].fd == -1 && pfd[POLL_STDOUT].fd == -1) {
840 close(net_fd);
841 return;
842 }
843 /* listen and net in gone, queues empty, done */
844 if (lflag && pfd[POLL_NETIN].fd == -1
845 && stdinbufpos == 0 && netinbufpos == 0) {
846 close(net_fd);
847 return;
848 }
849
850 /* help says -i is for "wait between lines sent". We read and
851 * write arbitrary amounts of data, and we don't want to start
852 * scanning for newlines, so this is as good as it gets */
853 if (iflag)
854 sleep(iflag);
855
856 /* poll */
857 num_fds = poll(pfd, 4, timeout);
858
859 /* treat poll errors */
860 if (num_fds == -1) {
861 close(net_fd);
862 err(1, "polling error");
863 }
864
865 /* timeout happened */
866 if (num_fds == 0)
867 return;
868
869 /* treat socket error conditions */
870 for (n = 0; n < 4; n++) {
871 if (pfd[n].revents & (POLLERR|POLLNVAL)) {
872 pfd[n].fd = -1;
873 }
874 }
875 /* reading is possible after HUP */
876 if (pfd[POLL_STDIN].events & POLLIN &&
877 pfd[POLL_STDIN].revents & POLLHUP &&
878 ! (pfd[POLL_STDIN].revents & POLLIN))
879 pfd[POLL_STDIN].fd = -1;
880
881 if (pfd[POLL_NETIN].events & POLLIN &&
882 pfd[POLL_NETIN].revents & POLLHUP &&
883 ! (pfd[POLL_NETIN].revents & POLLIN))
884 pfd[POLL_NETIN].fd = -1;
885
886 if (pfd[POLL_NETOUT].revents & POLLHUP) {
887 if (Nflag)
888 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
889 pfd[POLL_NETOUT].fd = -1;
890 }
891 /* if HUP, stop watching stdout */
892 if (pfd[POLL_STDOUT].revents & POLLHUP)
893 pfd[POLL_STDOUT].fd = -1;
894 /* if no net out, stop watching stdin */
895 if (pfd[POLL_NETOUT].fd == -1)
896 pfd[POLL_STDIN].fd = -1;
897 /* if no stdout, stop watching net in */
898 if (pfd[POLL_STDOUT].fd == -1) {
899 if (pfd[POLL_NETIN].fd != -1)
900 shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
901 pfd[POLL_NETIN].fd = -1;
902 }
903
904 /* try to read from stdin */
905 if (pfd[POLL_STDIN].revents & POLLIN && stdinbufpos < BUFSIZE) {
906 ret = fillbuf(pfd[POLL_STDIN].fd, stdinbuf,
907 &stdinbufpos);
908 /* error or eof on stdin - remove from pfd */
909 if (ret == 0 || ret == -1)
910 pfd[POLL_STDIN].fd = -1;
911 /* read something - poll net out */
912 if (stdinbufpos > 0)
913 pfd[POLL_NETOUT].events = POLLOUT;
914 /* filled buffer - remove self from polling */
915 if (stdinbufpos == BUFSIZE)
916 pfd[POLL_STDIN].events = 0;
917 }
918 /* try to write to network */
919 if (pfd[POLL_NETOUT].revents & POLLOUT && stdinbufpos > 0) {
920 ret = drainbuf(pfd[POLL_NETOUT].fd, stdinbuf,
921 &stdinbufpos);
922 if (ret == -1)
923 pfd[POLL_NETOUT].fd = -1;
924 /* buffer empty - remove self from polling */
925 if (stdinbufpos == 0)
926 pfd[POLL_NETOUT].events = 0;
927 /* buffer no longer full - poll stdin again */
928 if (stdinbufpos < BUFSIZE)
929 pfd[POLL_STDIN].events = POLLIN;
930 }
931 /* try to read from network */
932 if (pfd[POLL_NETIN].revents & POLLIN && netinbufpos < BUFSIZE) {
933 ret = fillbuf(pfd[POLL_NETIN].fd, netinbuf,
934 &netinbufpos);
935 if (ret == -1)
936 pfd[POLL_NETIN].fd = -1;
937 /* eof on net in - remove from pfd */
938 if (ret == 0) {
939 shutdown(pfd[POLL_NETIN].fd, SHUT_RD);
940 pfd[POLL_NETIN].fd = -1;
941 }
942 /* read something - poll stdout */
943 if (netinbufpos > 0)
944 pfd[POLL_STDOUT].events = POLLOUT;
945 /* filled buffer - remove self from polling */
946 if (netinbufpos == BUFSIZE)
947 pfd[POLL_NETIN].events = 0;
948 /* handle telnet */
949 if (tflag)
950 atelnet(pfd[POLL_NETIN].fd, netinbuf,
951 netinbufpos);
952 }
953 /* try to write to stdout */
954 if (pfd[POLL_STDOUT].revents & POLLOUT && netinbufpos > 0) {
955 ret = drainbuf(pfd[POLL_STDOUT].fd, netinbuf,
956 &netinbufpos);
957 if (ret == -1)
958 pfd[POLL_STDOUT].fd = -1;
959 /* buffer empty - remove self from polling */
960 if (netinbufpos == 0)
961 pfd[POLL_STDOUT].events = 0;
962 /* buffer no longer full - poll net in again */
963 if (netinbufpos < BUFSIZE)
964 pfd[POLL_NETIN].events = POLLIN;
965 }
966
967 /* stdin gone and queue empty? */
968 if (pfd[POLL_STDIN].fd == -1 && stdinbufpos == 0) {
969 if (pfd[POLL_NETOUT].fd != -1 && Nflag)
970 shutdown(pfd[POLL_NETOUT].fd, SHUT_WR);
971 pfd[POLL_NETOUT].fd = -1;
972 }
973 /* net in gone and queue empty? */
974 if (pfd[POLL_NETIN].fd == -1 && netinbufpos == 0) {
975 pfd[POLL_STDOUT].fd = -1;
976 }
977 }
978}
979
980ssize_t
981drainbuf(int fd, unsigned char *buf, size_t *bufpos)
982{
983 ssize_t n;
984 ssize_t adjust;
985
986 n = write(fd, buf, *bufpos);
987 /* don't treat EAGAIN, EINTR as error */
988 if (n == -1 && (errno == EAGAIN || errno == EINTR))
989 n = -2;
990 if (n <= 0)
991 return n;
992 /* adjust buffer */
993 adjust = *bufpos - n;
994 if (adjust > 0)
995 memmove(buf, buf + n, adjust);
996 *bufpos -= n;
997 return n;
998}
999
1000
1001ssize_t
1002fillbuf(int fd, unsigned char *buf, size_t *bufpos)
1003{
1004 size_t num = BUFSIZE - *bufpos;
1005 ssize_t n;
1006
1007 n = read(fd, buf + *bufpos, num);
1008 /* don't treat EAGAIN, EINTR as error */
1009 if (n == -1 && (errno == EAGAIN || errno == EINTR))
1010 n = -2;
1011 if (n <= 0)
1012 return n;
1013 *bufpos += n;
1014 return n;
1015}
1016
1017/*
1018 * fdpass()
1019 * Pass the connected file descriptor to stdout and exit.
1020 */
1021void
1022fdpass(int nfd)
1023{
1024#if defined(HAVE_SENDMSG) && (defined(HAVE_ACCRIGHTS_IN_MSGHDR) || defined(HAVE_CONTROL_IN_MSGHDR))
1025 struct msghdr msg;
1026#ifndef HAVE_ACCRIGHTS_IN_MSGHDR
1027 union {
1028 struct cmsghdr hdr;
1029 char buf[CMSG_SPACE(sizeof(int))];
1030 } cmsgbuf;
1031 struct cmsghdr *cmsg;
1032#endif
1033 struct iovec vec;
1034 char ch = '\0';
1035 struct pollfd pfd;
1036 ssize_t r;
1037
1038 memset(&msg, 0, sizeof(msg));
1039#ifdef HAVE_ACCRIGHTS_IN_MSGHDR
1040 msg.msg_accrights = (caddr_t)&nfd;
1041 msg.msg_accrightslen = sizeof(nfd);
1042#else
1043 memset(&cmsgbuf, 0, sizeof(cmsgbuf));
1044 msg.msg_control = (caddr_t)&cmsgbuf.buf;
1045 msg.msg_controllen = sizeof(cmsgbuf.buf);
1046 cmsg = CMSG_FIRSTHDR(&msg);
1047 cmsg->cmsg_len = CMSG_LEN(sizeof(int));
1048 cmsg->cmsg_level = SOL_SOCKET;
1049 cmsg->cmsg_type = SCM_RIGHTS;
1050 *(int *)CMSG_DATA(cmsg) = nfd;
1051#endif
1052
1053 vec.iov_base = &ch;
1054 vec.iov_len = 1;
1055 msg.msg_iov = &vec;
1056 msg.msg_iovlen = 1;
1057
1058 bzero(&pfd, sizeof(pfd));
1059 pfd.fd = STDOUT_FILENO;
1060 for (;;) {
1061 r = sendmsg(STDOUT_FILENO, &msg, 0);
1062 if (r == -1) {
1063 if (errno == EAGAIN || errno == EINTR) {
1064 pfd.events = POLLOUT;
1065 if (poll(&pfd, 1, -1) == -1)
1066 err(1, "poll");
1067 continue;
1068 }
1069 err(1, "sendmsg");
1070 } else if (r == -1)
1071 errx(1, "sendmsg: unexpected return value %zd", r);
1072 else
1073 break;
1074 }
1075 exit(0);
1076#else
1077 errx(1, "%s: file descriptor passing not supported", __func__);
1078#endif
1079}
1080
1081/* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */
1082void
1083atelnet(int nfd, unsigned char *buf, unsigned int size)
1084{
1085 unsigned char *p, *end;
1086 unsigned char obuf[4];
1087
1088 if (size < 3)
1089 return;
1090 end = buf + size - 2;
1091
1092 for (p = buf; p < end; p++) {
1093 if (*p != IAC)
1094 continue;
1095
1096 obuf[0] = IAC;
1097 p++;
1098 if ((*p == WILL) || (*p == WONT))
1099 obuf[1] = DONT;
1100 else if ((*p == DO) || (*p == DONT))
1101 obuf[1] = WONT;
1102 else
1103 continue;
1104
1105 p++;
1106 obuf[2] = *p;
1107 if (atomicio(vwrite, nfd, obuf, 3) != 3)
1108 warn("Write Error!");
1109 }
1110}
1111
1112/*
1113 * build_ports()
1114 * Build an array of ports in portlist[], listing each port
1115 * that we should try to connect to.
1116 */
1117void
1118build_ports(char *p)
1119{
1120 const char *errstr;
1121 char *n;
1122 int hi, lo, cp;
1123 int x = 0;
1124
1125 if ((n = strchr(p, '-')) != NULL) {
1126 *n = '\0';
1127 n++;
1128
1129 /* Make sure the ports are in order: lowest->highest. */
1130 hi = strtonum(n, 1, PORT_MAX, &errstr);
1131 if (errstr)
1132 errx(1, "port number %s: %s", errstr, n);
1133 lo = strtonum(p, 1, PORT_MAX, &errstr);
1134 if (errstr)
1135 errx(1, "port number %s: %s", errstr, p);
1136
1137 if (lo > hi) {
1138 cp = hi;
1139 hi = lo;
1140 lo = cp;
1141 }
1142
1143 /* Load ports sequentially. */
1144 for (cp = lo; cp <= hi; cp++) {
1145 portlist[x] = calloc(1, PORT_MAX_LEN);
1146 if (portlist[x] == NULL)
1147 errx(1, "calloc");
1148 snprintf(portlist[x], PORT_MAX_LEN, "%d", cp);
1149 x++;
1150 }
1151
1152 /* Randomly swap ports. */
1153 if (rflag) {
1154 int y;
1155 char *c;
1156
1157 for (x = 0; x <= (hi - lo); x++) {
1158 y = (arc4random() & 0xFFFF) % (hi - lo);
1159 c = portlist[x];
1160 portlist[x] = portlist[y];
1161 portlist[y] = c;
1162 }
1163 }
1164 } else {
1165 hi = strtonum(p, 1, PORT_MAX, &errstr);
1166 if (errstr)
1167 errx(1, "port number %s: %s", errstr, p);
1168 portlist[0] = strdup(p);
1169 if (portlist[0] == NULL)
1170 errx(1, "strdup");
1171 }
1172}
1173
1174/*
1175 * udptest()
1176 * Do a few writes to see if the UDP port is there.
1177 * Fails once PF state table is full.
1178 */
1179int
1180udptest(int s)
1181{
1182 int i, ret;
1183
1184 for (i = 0; i <= 3; i++) {
1185 if (write(s, "X", 1) == 1)
1186 ret = 1;
1187 else
1188 ret = -1;
1189 }
1190 return (ret);
1191}
1192
1193void
1194set_common_sockopts(int s)
1195{
1196 int x = 1;
1197
1198#ifdef TCP_MD5SIG
1199 if (Sflag) {
1200 if (setsockopt(s, IPPROTO_TCP, TCP_MD5SIG,
1201 &x, sizeof(x)) == -1)
1202 err(1, "setsockopt");
1203 }
1204#endif
1205 if (Dflag) {
1206 if (setsockopt(s, SOL_SOCKET, SO_DEBUG,
1207 &x, sizeof(x)) == -1)
1208 err(1, "setsockopt");
1209 }
1210 if (Tflag != -1) {
1211 if (setsockopt(s, IPPROTO_IP, IP_TOS,
1212 &Tflag, sizeof(Tflag)) == -1)
1213 err(1, "set IP ToS");
1214 }
1215 if (Iflag) {
1216 if (setsockopt(s, SOL_SOCKET, SO_RCVBUF,
1217 &Iflag, sizeof(Iflag)) == -1)
1218 err(1, "set TCP receive buffer size");
1219 }
1220 if (Oflag) {
1221 if (setsockopt(s, SOL_SOCKET, SO_SNDBUF,
1222 &Oflag, sizeof(Oflag)) == -1)
1223 err(1, "set TCP send buffer size");
1224 }
1225}
1226
1227int
1228map_tos(char *s, int *val)
1229{
1230 /* DiffServ Codepoints and other TOS mappings */
1231 const struct toskeywords {
1232 const char *keyword;
1233 int val;
1234 } *t, toskeywords[] = {
1235 { "af11", IPTOS_DSCP_AF11 },
1236 { "af12", IPTOS_DSCP_AF12 },
1237 { "af13", IPTOS_DSCP_AF13 },
1238 { "af21", IPTOS_DSCP_AF21 },
1239 { "af22", IPTOS_DSCP_AF22 },
1240 { "af23", IPTOS_DSCP_AF23 },
1241 { "af31", IPTOS_DSCP_AF31 },
1242 { "af32", IPTOS_DSCP_AF32 },
1243 { "af33", IPTOS_DSCP_AF33 },
1244 { "af41", IPTOS_DSCP_AF41 },
1245 { "af42", IPTOS_DSCP_AF42 },
1246 { "af43", IPTOS_DSCP_AF43 },
1247 { "critical", IPTOS_PREC_CRITIC_ECP },
1248 { "cs0", IPTOS_DSCP_CS0 },
1249 { "cs1", IPTOS_DSCP_CS1 },
1250 { "cs2", IPTOS_DSCP_CS2 },
1251 { "cs3", IPTOS_DSCP_CS3 },
1252 { "cs4", IPTOS_DSCP_CS4 },
1253 { "cs5", IPTOS_DSCP_CS5 },
1254 { "cs6", IPTOS_DSCP_CS6 },
1255 { "cs7", IPTOS_DSCP_CS7 },
1256 { "ef", IPTOS_DSCP_EF },
1257 { "inetcontrol", IPTOS_PREC_INTERNETCONTROL },
1258 { "lowdelay", IPTOS_LOWDELAY },
1259 { "netcontrol", IPTOS_PREC_NETCONTROL },
1260 { "reliability", IPTOS_RELIABILITY },
1261 { "throughput", IPTOS_THROUGHPUT },
1262 { NULL, -1 },
1263 };
1264
1265 for (t = toskeywords; t->keyword != NULL; t++) {
1266 if (strcmp(s, t->keyword) == 0) {
1267 *val = t->val;
1268 return (1);
1269 }
1270 }
1271
1272 return (0);
1273}
1274
1275void
1276report_connect(const struct sockaddr *sa, socklen_t salen)
1277{
1278 char remote_host[NI_MAXHOST];
1279 char remote_port[NI_MAXSERV];
1280 int herr;
1281 int flags = NI_NUMERICSERV;
1282
1283 if (nflag)
1284 flags |= NI_NUMERICHOST;
1285
1286 if ((herr = getnameinfo(sa, salen,
1287 remote_host, sizeof(remote_host),
1288 remote_port, sizeof(remote_port),
1289 flags)) != 0) {
1290 if (herr == EAI_SYSTEM)
1291 err(1, "getnameinfo");
1292 else
1293 errx(1, "getnameinfo: %s", gai_strerror(herr));
1294 }
1295
1296 fprintf(stderr,
1297 "Connection from %s %s "
1298 "received!\n", remote_host, remote_port);
1299}
1300
1301void
1302help(void)
1303{
1304 usage(0);
1305 fprintf(stderr, "\tCommand Summary:\n\
1306 \t-4 Use IPv4\n\
1307 \t-6 Use IPv6\n\
1308 \t-D Enable the debug socket option\n\
1309 \t-d Detach from stdin\n\
1310 \t-F Pass socket fd\n\
1311 \t-h This help text\n\
1312 \t-I length TCP receive buffer length\n\
1313 \t-i secs\t Delay interval for lines sent, ports scanned\n\
1314 \t-k Keep inbound sockets open for multiple connects\n\
1315 \t-l Listen mode, for inbound connects\n\
1316 \t-N Shutdown the network socket after EOF on stdin\n\
1317 \t-n Suppress name/port resolutions\n\
1318 \t-O length TCP send buffer length\n\
1319 \t-P proxyuser\tUsername for proxy authentication\n\
1320 \t-p port\t Specify local port for remote connects\n\
1321 \t-r Randomize remote ports\n\
1322 \t-S Enable the TCP MD5 signature option\n\
1323 \t-s addr\t Local source address\n\
1324 \t-T toskeyword\tSet IP Type of Service\n\
1325 \t-t Answer TELNET negotiation\n\
1326 \t-U Use UNIX domain socket\n\
1327 \t-u UDP mode\n\
1328 \t-V rtable Specify alternate routing table\n\
1329 \t-v Verbose\n\
1330 \t-w secs\t Timeout for connects and final net reads\n\
1331 \t-X proto Proxy protocol: \"4\", \"5\" (SOCKS) or \"connect\"\n\
1332 \t-x addr[:port]\tSpecify proxy address and port\n\
1333 \t-z Zero-I/O mode [used for scanning]\n\
1334 Port numbers can be individual or ranges: lo-hi [inclusive]\n");
1335 exit(1);
1336}
1337
1338void
1339usage(int ret)
1340{
1341 fprintf(stderr,
1342 "usage: nc [-46DdFhklNnrStUuvz] [-I length] [-i interval] [-O length]\n"
1343 "\t [-P proxy_username] [-p source_port] [-s source] [-T ToS]\n"
1344 "\t [-V rtable] [-w timeout] [-X proxy_protocol]\n"
1345 "\t [-x proxy_address[:port]] [destination] [port]\n");
1346 if (ret)
1347 exit(1);
1348}
1349
1350/* *** src/usr.bin/nc/socks.c *** */
1351
1352
1353/* $OpenBSD: socks.c,v 1.20 2012/03/08 09:56:28 espie Exp $ */
1354
1355/*
1356 * Copyright (c) 1999 Niklas Hallqvist. All rights reserved.
1357 * Copyright (c) 2004, 2005 Damien Miller. All rights reserved.
1358 *
1359 * Redistribution and use in source and binary forms, with or without
1360 * modification, are permitted provided that the following conditions
1361 * are met:
1362 * 1. Redistributions of source code must retain the above copyright
1363 * notice, this list of conditions and the following disclaimer.
1364 * 2. Redistributions in binary form must reproduce the above copyright
1365 * notice, this list of conditions and the following disclaimer in the
1366 * documentation and/or other materials provided with the distribution.
1367 *
1368 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
1369 * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
1370 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
1371 * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
1372 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
1373 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1374 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1375 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1376 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
1377 * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1378 */
1379
1380#include <sys/types.h>
1381#include <sys/socket.h>
1382#include <netinet/in.h>
1383#include <arpa/inet.h>
1384
1385#include <errno.h>
1386#include <netdb.h>
1387#include <stdio.h>
1388#include <stdlib.h>
1389#include <string.h>
1390#include <unistd.h>
1391#include <resolv.h>
1392
1393#define SOCKS_PORT "1080"
1394#define HTTP_PROXY_PORT "3128"
1395#define HTTP_MAXHDRS 64
1396#define SOCKS_V5 5
1397#define SOCKS_V4 4
1398#define SOCKS_NOAUTH 0
1399#define SOCKS_NOMETHOD 0xff
1400#define SOCKS_CONNECT 1
1401#define SOCKS_IPV4 1
1402#define SOCKS_DOMAIN 3
1403#define SOCKS_IPV6 4
1404
1405int remote_connect(const char *, const char *, struct addrinfo);
1406int socks_connect(const char *, const char *, struct addrinfo,
1407 const char *, const char *, struct addrinfo, int,
1408 const char *);
1409
1410static int
1411decode_addrport(const char *h, const char *p, struct sockaddr *addr,
1412 socklen_t addrlen, int v4only, int numeric)
1413{
1414 int r;
1415 struct addrinfo hints, *res;
1416
1417 bzero(&hints, sizeof(hints));
1418 hints.ai_family = v4only ? PF_INET : PF_UNSPEC;
1419 hints.ai_flags = numeric ? AI_NUMERICHOST : 0;
1420 hints.ai_socktype = SOCK_STREAM;
1421 r = getaddrinfo(h, p, &hints, &res);
1422 /* Don't fatal when attempting to convert a numeric address */
1423 if (r != 0) {
1424 if (!numeric) {
1425 errx(1, "getaddrinfo(\"%.64s\", \"%.64s\"): %s", h, p,
1426 gai_strerror(r));
1427 }
1428 return (-1);
1429 }
1430 if (addrlen < res->ai_addrlen) {
1431 freeaddrinfo(res);
1432 errx(1, "internal error: addrlen < res->ai_addrlen");
1433 }
1434 memcpy(addr, res->ai_addr, res->ai_addrlen);
1435 freeaddrinfo(res);
1436 return (0);
1437}
1438
1439static int
1440proxy_read_line(int fd, char *buf, size_t bufsz)
1441{
1442 size_t off;
1443
1444 for(off = 0;;) {
1445 if (off >= bufsz)
1446 errx(1, "proxy read too long");
1447 if (atomicio(read, fd, buf + off, 1) != 1)
1448 err(1, "proxy read");
1449 /* Skip CR */
1450 if (buf[off] == '\r')
1451 continue;
1452 if (buf[off] == '\n') {
1453 buf[off] = '\0';
1454 break;
1455 }
1456 off++;
1457 }
1458 return (off);
1459}
1460
1461static const char *
1462getproxypass(const char *proxyuser, const char *proxyhost)
1463{
1464 char prompt[512];
1465 static char pw[256];
1466
1467 snprintf(prompt, sizeof(prompt), "Proxy password for %s@%s: ",
1468 proxyuser, proxyhost);
1469 if (readpassphrase(prompt, pw, sizeof(pw), RPP_REQUIRE_TTY) == NULL)
1470 errx(1, "Unable to read proxy passphrase");
1471 return (pw);
1472}
1473
1474int
1475socks_connect(const char *host, const char *port,
1476 struct addrinfo hints __attribute__ ((__unused__)),
1477 const char *proxyhost, const char *proxyport, struct addrinfo proxyhints,
1478 int socksv, const char *proxyuser)
1479{
1480 int proxyfd, r, authretry = 0;
1481 size_t hlen, wlen = 0;
1482 unsigned char buf[1024];
1483 size_t cnt;
1484 struct sockaddr_storage addr;
1485 struct sockaddr_in *in4 = (struct sockaddr_in *)&addr;
1486 struct sockaddr_in6 *in6 = (struct sockaddr_in6 *)&addr;
1487 in_port_t serverport;
1488 const char *proxypass = NULL;
1489
1490 if (proxyport == NULL)
1491 proxyport = (socksv == -1) ? HTTP_PROXY_PORT : SOCKS_PORT;
1492
1493 /* Abuse API to lookup port */
1494 if (decode_addrport("0.0.0.0", port, (struct sockaddr *)&addr,
1495 sizeof(addr), 1, 1) == -1)
1496 errx(1, "unknown port \"%.64s\"", port);
1497 serverport = in4->sin_port;
1498
1499 again:
1500 if (authretry++ > 3)
1501 errx(1, "Too many authentication failures");
1502
1503 proxyfd = remote_connect(proxyhost, proxyport, proxyhints);
1504
1505 if (proxyfd < 0)
1506 return (-1);
1507
1508 if (socksv == 5) {
1509 if (decode_addrport(host, port, (struct sockaddr *)&addr,
1510 sizeof(addr), 0, 1) == -1)
1511 addr.ss_family = 0; /* used in switch below */
1512
1513 /* Version 5, one method: no authentication */
1514 buf[0] = SOCKS_V5;
1515 buf[1] = 1;
1516 buf[2] = SOCKS_NOAUTH;
1517 cnt = atomicio(vwrite, proxyfd, buf, 3);
1518 if (cnt != 3)
1519 err(1, "write failed (%zu/3)", cnt);
1520
1521 cnt = atomicio(read, proxyfd, buf, 2);
1522 if (cnt != 2)
1523 err(1, "read failed (%zu/3)", cnt);
1524
1525 if (buf[1] == SOCKS_NOMETHOD)
1526 errx(1, "authentication method negotiation failed");
1527
1528 switch (addr.ss_family) {
1529 case 0:
1530 /* Version 5, connect: domain name */
1531
1532 /* Max domain name length is 255 bytes */
1533 hlen = strlen(host);
1534 if (hlen > 255)
1535 errx(1, "host name too long for SOCKS5");
1536 buf[0] = SOCKS_V5;
1537 buf[1] = SOCKS_CONNECT;
1538 buf[2] = 0;
1539 buf[3] = SOCKS_DOMAIN;
1540 buf[4] = hlen;
1541 memcpy(buf + 5, host, hlen);
1542 memcpy(buf + 5 + hlen, &serverport, sizeof serverport);
1543 wlen = 7 + hlen;
1544 break;
1545 case AF_INET:
1546 /* Version 5, connect: IPv4 address */
1547 buf[0] = SOCKS_V5;
1548 buf[1] = SOCKS_CONNECT;
1549 buf[2] = 0;
1550 buf[3] = SOCKS_IPV4;
1551 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
1552 memcpy(buf + 8, &in4->sin_port, sizeof in4->sin_port);
1553 wlen = 10;
1554 break;
1555 case AF_INET6:
1556 /* Version 5, connect: IPv6 address */
1557 buf[0] = SOCKS_V5;
1558 buf[1] = SOCKS_CONNECT;
1559 buf[2] = 0;
1560 buf[3] = SOCKS_IPV6;
1561 memcpy(buf + 4, &in6->sin6_addr, sizeof in6->sin6_addr);
1562 memcpy(buf + 20, &in6->sin6_port,
1563 sizeof in6->sin6_port);
1564 wlen = 22;
1565 break;
1566 default:
1567 errx(1, "internal error: silly AF");
1568 }
1569
1570 cnt = atomicio(vwrite, proxyfd, buf, wlen);
1571 if (cnt != wlen)
1572 err(1, "write failed (%zu/%zu)", cnt, wlen);
1573
1574 cnt = atomicio(read, proxyfd, buf, 4);
1575 if (cnt != 4)
1576 err(1, "read failed (%zu/4)", cnt);
1577 if (buf[1] != 0)
1578 errx(1, "connection failed, SOCKS error %d", buf[1]);
1579 switch (buf[3]) {
1580 case SOCKS_IPV4:
1581 cnt = atomicio(read, proxyfd, buf + 4, 6);
1582 if (cnt != 6)
1583 err(1, "read failed (%zu/6)", cnt);
1584 break;
1585 case SOCKS_IPV6:
1586 cnt = atomicio(read, proxyfd, buf + 4, 18);
1587 if (cnt != 18)
1588 err(1, "read failed (%zu/18)", cnt);
1589 break;
1590 default:
1591 errx(1, "connection failed, unsupported address type");
1592 }
1593 } else if (socksv == 4) {
1594 /* This will exit on lookup failure */
1595 decode_addrport(host, port, (struct sockaddr *)&addr,
1596 sizeof(addr), 1, 0);
1597
1598 /* Version 4 */
1599 buf[0] = SOCKS_V4;
1600 buf[1] = SOCKS_CONNECT; /* connect */
1601 memcpy(buf + 2, &in4->sin_port, sizeof in4->sin_port);
1602 memcpy(buf + 4, &in4->sin_addr, sizeof in4->sin_addr);
1603 buf[8] = 0; /* empty username */
1604 wlen = 9;
1605
1606 cnt = atomicio(vwrite, proxyfd, buf, wlen);
1607 if (cnt != wlen)
1608 err(1, "write failed (%zu/%zu)", cnt, wlen);
1609
1610 cnt = atomicio(read, proxyfd, buf, 8);
1611 if (cnt != 8)
1612 err(1, "read failed (%zu/8)", cnt);
1613 if (buf[1] != 90)
1614 errx(1, "connection failed, SOCKS error %d", buf[1]);
1615 } else if (socksv == -1) {
1616 /* HTTP proxy CONNECT */
1617
1618 /* Disallow bad chars in hostname */
1619 if (strcspn(host, "\r\n\t []:") != strlen(host))
1620 errx(1, "Invalid hostname");
1621
1622 /* Try to be sane about numeric IPv6 addresses */
1623 if (strchr(host, ':') != NULL) {
1624 r = snprintf(buf, sizeof(buf),
1625 "CONNECT [%s]:%d HTTP/1.0\r\n",
1626 host, ntohs(serverport));
1627 } else {
1628 r = snprintf(buf, sizeof(buf),
1629 "CONNECT %s:%d HTTP/1.0\r\n",
1630 host, ntohs(serverport));
1631 }
1632 if (r == -1 || (size_t)r >= sizeof(buf))
1633 errx(1, "hostname too long");
1634 r = strlen(buf);
1635
1636 cnt = atomicio(vwrite, proxyfd, buf, r);
1637 if (cnt != (size_t)r)
1638 err(1, "write failed (%zu/%d)", cnt, r);
1639
1640 if (authretry > 1) {
1641 char resp[1024];
1642
1643 proxypass = getproxypass(proxyuser, proxyhost);
1644 r = snprintf(buf, sizeof(buf), "%s:%s",
1645 proxyuser, proxypass);
1646 if (r == -1 || (size_t)r >= sizeof(buf) ||
1647 b64_ntop(buf, strlen(buf), resp,
1648 sizeof(resp)) == -1)
1649 errx(1, "Proxy username/password too long");
1650 r = snprintf(buf, sizeof(buf), "Proxy-Authorization: "
1651 "Basic %s\r\n", resp);
1652 if (r == -1 || (size_t)r >= sizeof(buf))
1653 errx(1, "Proxy auth response too long");
1654 r = strlen(buf);
1655 if ((cnt = atomicio(vwrite, proxyfd, buf, r)) != (size_t)r)
1656 err(1, "write failed (%zu/%d)", cnt, r);
1657 }
1658
1659 /* Terminate headers */
1660 if ((r = atomicio(vwrite, proxyfd, "\r\n", 2)) != 2)
1661 err(1, "write failed (2/%d)", r);
1662
1663 /* Read status reply */
1664 proxy_read_line(proxyfd, buf, sizeof(buf));
1665 if (proxyuser != NULL &&
1666 strncmp(buf, "HTTP/1.0 407 ", 12) == 0) {
1667 if (authretry > 1) {
1668 fprintf(stderr, "Proxy authentication "
1669 "failed\n");
1670 }
1671 close(proxyfd);
1672 goto again;
1673 } else if (strncmp(buf, "HTTP/1.0 200 ", 12) != 0 &&
1674 strncmp(buf, "HTTP/1.1 200 ", 12) != 0)
1675 errx(1, "Proxy error: \"%s\"", buf);
1676
1677 /* Headers continue until we hit an empty line */
1678 for (r = 0; r < HTTP_MAXHDRS; r++) {
1679 proxy_read_line(proxyfd, buf, sizeof(buf));
1680 if (*buf == '\0')
1681 break;
1682 }
1683 if (*buf != '\0')
1684 errx(1, "Too many proxy headers received");
1685 } else
1686 errx(1, "Unknown proxy protocol %d", socksv);
1687
1688 return (proxyfd);
1689}
1690
diff --git a/regress/proto-mismatch.sh b/regress/proto-mismatch.sh
index fb521f214..9e8024beb 100644
--- a/regress/proto-mismatch.sh
+++ b/regress/proto-mismatch.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: proto-mismatch.sh,v 1.3 2002/03/15 13:08:56 markus Exp $ 1# $OpenBSD: proto-mismatch.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="protocol version mismatch" 4tid="protocol version mismatch"
@@ -16,4 +16,6 @@ mismatch ()
16} 16}
17 17
18mismatch 2 SSH-1.5-HALLO 18mismatch 2 SSH-1.5-HALLO
19mismatch 1 SSH-2.0-HALLO 19if ssh_version 1; then
20 mismatch 1 SSH-2.0-HALLO
21fi
diff --git a/regress/proto-version.sh b/regress/proto-version.sh
index b876dd7ec..cf4946115 100644
--- a/regress/proto-version.sh
+++ b/regress/proto-version.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: proto-version.sh,v 1.4 2013/05/17 00:37:40 dtucker Exp $ 1# $OpenBSD: proto-version.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="sshd version with different protocol combinations" 4tid="sshd version with different protocol combinations"
@@ -28,7 +28,9 @@ check_version ()
28 fi 28 fi
29} 29}
30 30
31check_version 2,1 199
32check_version 1,2 199
33check_version 2 20 31check_version 2 20
34check_version 1 15 32if ssh_version 1; then
33 check_version 2,1 199
34 check_version 1,2 199
35 check_version 1 15
36fi
diff --git a/regress/proxy-connect.sh b/regress/proxy-connect.sh
index 023ba7367..f816962b5 100644
--- a/regress/proxy-connect.sh
+++ b/regress/proxy-connect.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: proxy-connect.sh,v 1.7 2014/05/03 18:46:14 dtucker Exp $ 1# $OpenBSD: proxy-connect.sh,v 1.8 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="proxy connect" 4tid="proxy connect"
@@ -9,7 +9,7 @@ for ps in no yes; do
9 cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy 9 cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
10 echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy 10 echo "UsePrivilegeSeparation $ps" >> $OBJ/sshd_proxy
11 11
12 for p in 1 2; do 12 for p in ${SSH_PROTOCOLS}; do
13 for c in no yes; do 13 for c in no yes; do
14 verbose "plain username protocol $p privsep=$ps comp=$c" 14 verbose "plain username protocol $p privsep=$ps comp=$c"
15 opts="-$p -oCompression=$c -F $OBJ/ssh_proxy" 15 opts="-$p -oCompression=$c -F $OBJ/ssh_proxy"
@@ -24,7 +24,7 @@ for ps in no yes; do
24 done 24 done
25done 25done
26 26
27for p in 1 2; do 27for p in ${SSH_PROTOCOLS}; do
28 verbose "username with style protocol $p" 28 verbose "username with style protocol $p"
29 ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \ 29 ${SSH} -$p -F $OBJ/ssh_proxy ${USER}:style@999.999.999.999 true || \
30 fail "ssh proxyconnect protocol $p failed" 30 fail "ssh proxyconnect protocol $p failed"
diff --git a/regress/reconfigure.sh b/regress/reconfigure.sh
index 9fd289531..eecddd3c7 100644
--- a/regress/reconfigure.sh
+++ b/regress/reconfigure.sh
@@ -1,20 +1,30 @@
1# $OpenBSD: reconfigure.sh,v 1.2 2003/06/21 09:14:05 markus Exp $ 1# $OpenBSD: reconfigure.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="simple connect after reconfigure" 4tid="simple connect after reconfigure"
5 5
6# we need the full path to sshd for -HUP 6# we need the full path to sshd for -HUP
7case $SSHD in 7if test "x$USE_VALGRIND" = "x" ; then
8/*) 8 case $SSHD in
9 # full path is OK 9 /*)
10 ;; 10 # full path is OK
11*) 11 ;;
12 # otherwise make fully qualified 12 *)
13 SSHD=$OBJ/$SSHD 13 # otherwise make fully qualified
14esac 14 SSHD=$OBJ/$SSHD
15 esac
16fi
15 17
16start_sshd 18start_sshd
17 19
20trace "connect before restart"
21for p in ${SSH_PROTOCOLS} ; do
22 ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
23 if [ $? -ne 0 ]; then
24 fail "ssh connect with protocol $p failed before reconfigure"
25 fi
26done
27
18PID=`$SUDO cat $PIDFILE` 28PID=`$SUDO cat $PIDFILE`
19rm -f $PIDFILE 29rm -f $PIDFILE
20$SUDO kill -HUP $PID 30$SUDO kill -HUP $PID
@@ -28,7 +38,8 @@ done
28 38
29test -f $PIDFILE || fatal "sshd did not restart" 39test -f $PIDFILE || fatal "sshd did not restart"
30 40
31for p in 1 2; do 41trace "connect after restart"
42for p in ${SSH_PROTOCOLS} ; do
32 ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true 43 ${SSH} -o "Protocol=$p" -F $OBJ/ssh_config somehost true
33 if [ $? -ne 0 ]; then 44 if [ $? -ne 0 ]; then
34 fail "ssh connect with protocol $p failed after reconfigure" 45 fail "ssh connect with protocol $p failed after reconfigure"
diff --git a/regress/reexec.sh b/regress/reexec.sh
index 433573f06..5c0a7b46f 100644
--- a/regress/reexec.sh
+++ b/regress/reexec.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: reexec.sh,v 1.7 2013/05/17 10:23:52 dtucker Exp $ 1# $OpenBSD: reexec.sh,v 1.8 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="reexec tests" 4tid="reexec tests"
@@ -19,7 +19,7 @@ start_sshd_copy ()
19copy_tests () 19copy_tests ()
20{ 20{
21 rm -f ${COPY} 21 rm -f ${COPY}
22 for p in 1 2; do 22 for p in ${SSH_PROTOCOLS} ; do
23 verbose "$tid: proto $p" 23 verbose "$tid: proto $p"
24 ${SSH} -nqo "Protocol=$p" -F $OBJ/ssh_config somehost \ 24 ${SSH} -nqo "Protocol=$p" -F $OBJ/ssh_config somehost \
25 cat ${DATA} > ${COPY} 25 cat ${DATA} > ${COPY}
diff --git a/regress/rekey.sh b/regress/rekey.sh
index fd452b034..0d4444d03 100644
--- a/regress/rekey.sh
+++ b/regress/rekey.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: rekey.sh,v 1.15 2014/04/21 22:15:37 djm Exp $ 1# $OpenBSD: rekey.sh,v 1.16 2015/02/14 12:43:16 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="rekey" 4tid="rekey"
@@ -100,9 +100,29 @@ for s in 5 10; do
100 fi 100 fi
101done 101done
102 102
103echo "rekeylimit default 5" >>$OBJ/sshd_proxy 103for s in 16 1k 128k 256k; do
104 verbose "server rekeylimit ${s}"
105 cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
106 echo "rekeylimit ${s}" >>$OBJ/sshd_proxy
107 rm -f ${COPY} ${LOG}
108 ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "cat ${DATA}" \
109 > ${COPY}
110 if [ $? -ne 0 ]; then
111 fail "ssh failed"
112 fi
113 cmp ${DATA} ${COPY} || fail "corrupted copy"
114 n=`grep 'NEWKEYS sent' ${LOG} | wc -l`
115 n=`expr $n - 1`
116 trace "$n rekeying(s)"
117 if [ $n -lt 1 ]; then
118 fail "no rekeying occured"
119 fi
120done
121
104for s in 5 10; do 122for s in 5 10; do
105 verbose "server rekeylimit default ${s} no data" 123 verbose "server rekeylimit default ${s} no data"
124 cp $OBJ/sshd_proxy_bak $OBJ/sshd_proxy
125 echo "rekeylimit default ${s}" >>$OBJ/sshd_proxy
106 rm -f ${COPY} ${LOG} 126 rm -f ${COPY} ${LOG}
107 ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 3" 127 ${SSH} -oCompression=no -F $OBJ/ssh_proxy somehost "sleep $s;sleep 3"
108 if [ $? -ne 0 ]; then 128 if [ $? -ne 0 ]; then
diff --git a/regress/sshd-log-wrapper.sh b/regress/sshd-log-wrapper.sh
index a9386be4d..c00934c78 100644
--- a/regress/sshd-log-wrapper.sh
+++ b/regress/sshd-log-wrapper.sh
@@ -3,11 +3,9 @@
3# Placed in the Public Domain. 3# Placed in the Public Domain.
4# 4#
5# simple wrapper for sshd proxy mode to catch stderr output 5# simple wrapper for sshd proxy mode to catch stderr output
6# sh sshd-log-wrapper.sh /path/to/sshd /path/to/logfile 6# sh sshd-log-wrapper.sh /path/to/logfile /path/to/sshd [args...]
7 7
8sshd=$1 8log=$1
9log=$2
10shift
11shift 9shift
12 10
13exec $sshd -E$log $@ 11exec "$@" -E$log
diff --git a/regress/stderr-data.sh b/regress/stderr-data.sh
index b0bd2355c..8c8149a73 100644
--- a/regress/stderr-data.sh
+++ b/regress/stderr-data.sh
@@ -1,10 +1,10 @@
1# $OpenBSD: stderr-data.sh,v 1.3 2013/05/17 04:29:14 dtucker Exp $ 1# $OpenBSD: stderr-data.sh,v 1.4 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="stderr data transfer" 4tid="stderr data transfer"
5 5
6for n in '' -n; do 6for n in '' -n; do
7for p in 1 2; do 7for p in ${SSH_PROTOCOLS}; do
8 verbose "test $tid: proto $p ($n)" 8 verbose "test $tid: proto $p ($n)"
9 ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \ 9 ${SSH} $n -$p -F $OBJ/ssh_proxy otherhost \
10 exec sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \ 10 exec sh -c \'"exec > /dev/null; sleep 3; cat ${DATA} 1>&2 $s"\' \
diff --git a/regress/t11.ok b/regress/t11.ok
new file mode 100644
index 000000000..1925bb470
--- /dev/null
+++ b/regress/t11.ok
@@ -0,0 +1 @@
SHA256:4w1rnrek3klTJOTVhwuCIFd5k+pq9Bfo5KTxxb8BqbY
diff --git a/regress/t4.ok b/regress/t4.ok
index 8c4942bf1..4631ea8c7 100644
--- a/regress/t4.ok
+++ b/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/regress/test-exec.sh b/regress/test-exec.sh
index a1bab832f..0f766620d 100644
--- a/regress/test-exec.sh
+++ b/regress/test-exec.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: test-exec.sh,v 1.48 2014/07/06 07:42:03 djm Exp $ 1# $OpenBSD: test-exec.sh,v 1.51 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4#SUDO=sudo 4#SUDO=sudo
@@ -130,6 +130,11 @@ if [ "x$TEST_SSH_CONCH" != "x" ]; then
130 esac 130 esac
131fi 131fi
132 132
133SSH_PROTOCOLS=`$SSH -Q protocol-version`
134if [ "x$TEST_SSH_PROTOCOLS" != "x" ]; then
135 SSH_PROTOCOLS="${TEST_SSH_PROTOCOLS}"
136fi
137
133# Path to sshd must be absolute for rexec 138# Path to sshd must be absolute for rexec
134case "$SSHD" in 139case "$SSHD" in
135/*) ;; 140/*) ;;
@@ -141,6 +146,55 @@ case "$SSHAGENT" in
141*) SSHAGENT=`which $SSHAGENT` ;; 146*) SSHAGENT=`which $SSHAGENT` ;;
142esac 147esac
143 148
149# Record the actual binaries used.
150SSH_BIN=${SSH}
151SSHD_BIN=${SSHD}
152SSHAGENT_BIN=${SSHAGENT}
153SSHADD_BIN=${SSHADD}
154SSHKEYGEN_BIN=${SSHKEYGEN}
155SSHKEYSCAN_BIN=${SSHKEYSCAN}
156SFTP_BIN=${SFTP}
157SFTPSERVER_BIN=${SFTPSERVER}
158SCP_BIN=${SCP}
159
160if [ "x$USE_VALGRIND" != "x" ]; then
161 mkdir -p $OBJ/valgrind-out
162 VG_TEST=`basename $SCRIPT .sh`
163
164 # Some tests are difficult to fix.
165 case "$VG_TEST" in
166 connect-privsep|reexec)
167 VG_SKIP=1 ;;
168 esac
169
170 if [ x"$VG_SKIP" = "x" ]; then
171 VG_IGNORE="/bin/*,/sbin/*,/usr/*,/var/*"
172 VG_LOG="$OBJ/valgrind-out/${VG_TEST}."
173 VG_OPTS="--track-origins=yes --leak-check=full"
174 VG_OPTS="$VG_OPTS --trace-children=yes"
175 VG_OPTS="$VG_OPTS --trace-children-skip=${VG_IGNORE}"
176 VG_PATH="valgrind"
177 if [ "x$VALGRIND_PATH" != "x" ]; then
178 VG_PATH="$VALGRIND_PATH"
179 fi
180 VG="$VG_PATH $VG_OPTS"
181 SSH="$VG --log-file=${VG_LOG}ssh.%p $SSH"
182 SSHD="$VG --log-file=${VG_LOG}sshd.%p $SSHD"
183 SSHAGENT="$VG --log-file=${VG_LOG}ssh-agent.%p $SSHAGENT"
184 SSHADD="$VG --log-file=${VG_LOG}ssh-add.%p $SSHADD"
185 SSHKEYGEN="$VG --log-file=${VG_LOG}ssh-keygen.%p $SSHKEYGEN"
186 SSHKEYSCAN="$VG --log-file=${VG_LOG}ssh-keyscan.%p $SSHKEYSCAN"
187 SFTP="$VG --log-file=${VG_LOG}sftp.%p ${SFTP}"
188 SCP="$VG --log-file=${VG_LOG}scp.%p $SCP"
189 cat > $OBJ/valgrind-sftp-server.sh << EOF
190#!/bin/sh
191exec $VG --log-file=${VG_LOG}sftp-server.%p $SFTPSERVER "\$@"
192EOF
193 chmod a+rx $OBJ/valgrind-sftp-server.sh
194 SFTPSERVER="$OBJ/valgrind-sftp-server.sh"
195 fi
196fi
197
144# Logfiles. 198# Logfiles.
145# SSH_LOGFILE should be the debug output of ssh(1) only 199# SSH_LOGFILE should be the debug output of ssh(1) only
146# SSHD_LOGFILE should be the debug output of sshd(8) only 200# SSHD_LOGFILE should be the debug output of sshd(8) only
@@ -175,7 +229,7 @@ SSH="$SSHLOGWRAP"
175# [kbytes] to ensure the file is at least that large. 229# [kbytes] to ensure the file is at least that large.
176DATANAME=data 230DATANAME=data
177DATA=$OBJ/${DATANAME} 231DATA=$OBJ/${DATANAME}
178cat ${SSHAGENT} >${DATA} 232cat ${SSHAGENT_BIN} >${DATA}
179chmod u+w ${DATA} 233chmod u+w ${DATA}
180COPY=$OBJ/copy 234COPY=$OBJ/copy
181rm -f ${COPY} 235rm -f ${COPY}
@@ -183,7 +237,7 @@ rm -f ${COPY}
183increase_datafile_size() 237increase_datafile_size()
184{ 238{
185 while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do 239 while [ `du -k ${DATA} | cut -f1` -lt $1 ]; do
186 cat ${SSHAGENT} >>${DATA} 240 cat ${SSHAGENT_BIN} >>${DATA}
187 done 241 done
188} 242}
189 243
@@ -325,16 +379,27 @@ fatal ()
325 exit $RESULT 379 exit $RESULT
326} 380}
327 381
382ssh_version ()
383{
384 echo ${SSH_PROTOCOLS} | grep "$1" >/dev/null
385}
386
328RESULT=0 387RESULT=0
329PIDFILE=$OBJ/pidfile 388PIDFILE=$OBJ/pidfile
330 389
331trap fatal 3 2 390trap fatal 3 2
332 391
392if ssh_version 1; then
393 PROTO="2,1"
394else
395 PROTO="2"
396fi
397
333# create server config 398# create server config
334cat << EOF > $OBJ/sshd_config 399cat << EOF > $OBJ/sshd_config
335 StrictModes no 400 StrictModes no
336 Port $PORT 401 Port $PORT
337 Protocol 2,1 402 Protocol $PROTO
338 AddressFamily inet 403 AddressFamily inet
339 ListenAddress 127.0.0.1 404 ListenAddress 127.0.0.1
340 #ListenAddress ::1 405 #ListenAddress ::1
@@ -360,7 +425,7 @@ echo 'StrictModes no' >> $OBJ/sshd_proxy
360# create client config 425# create client config
361cat << EOF > $OBJ/ssh_config 426cat << EOF > $OBJ/ssh_config
362Host * 427Host *
363 Protocol 2,1 428 Protocol $PROTO
364 Hostname 127.0.0.1 429 Hostname 127.0.0.1
365 HostKeyAlias localhost-with-alias 430 HostKeyAlias localhost-with-alias
366 Port $PORT 431 Port $PORT
@@ -385,10 +450,15 @@ fi
385 450
386rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER 451rm -f $OBJ/known_hosts $OBJ/authorized_keys_$USER
387 452
453if ssh_version 1; then
454 SSH_KEYTYPES="rsa rsa1"
455else
456 SSH_KEYTYPES="rsa ed25519"
457fi
388trace "generate keys" 458trace "generate keys"
389for t in rsa rsa1; do 459for t in ${SSH_KEYTYPES}; do
390 # generate user key 460 # generate user key
391 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN} -nt $OBJ/$t ]; then 461 if [ ! -f $OBJ/$t ] || [ ${SSHKEYGEN_BIN} -nt $OBJ/$t ]; then
392 rm -f $OBJ/$t 462 rm -f $OBJ/$t
393 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\ 463 ${SSHKEYGEN} -q -N '' -t $t -f $OBJ/$t ||\
394 fail "ssh-keygen for $t failed" 464 fail "ssh-keygen for $t failed"
@@ -451,7 +521,7 @@ if test "$REGRESS_INTEROP_PUTTY" = "yes" ; then
451 echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy 521 echo "Hostname=127.0.0.1" >> ${OBJ}/.putty/sessions/localhost_proxy
452 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy 522 echo "PortNumber=$PORT" >> ${OBJ}/.putty/sessions/localhost_proxy
453 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy 523 echo "ProxyMethod=5" >> ${OBJ}/.putty/sessions/localhost_proxy
454 echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy 524 echo "ProxyTelnetCommand=sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy" >> ${OBJ}/.putty/sessions/localhost_proxy
455 525
456 REGRESS_INTEROP_PUTTY=yes 526 REGRESS_INTEROP_PUTTY=yes
457fi 527fi
@@ -459,7 +529,7 @@ fi
459# create a proxy version of the client config 529# create a proxy version of the client config
460( 530(
461 cat $OBJ/ssh_config 531 cat $OBJ/ssh_config
462 echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${SSHD} ${TEST_SSHD_LOGFILE} -i -f $OBJ/sshd_proxy 532 echo proxycommand ${SUDO} sh ${SRC}/sshd-log-wrapper.sh ${TEST_SSHD_LOGFILE} ${SSHD} -i -f $OBJ/sshd_proxy
463) > $OBJ/ssh_proxy 533) > $OBJ/ssh_proxy
464 534
465# check proxy config 535# check proxy config
diff --git a/regress/transfer.sh b/regress/transfer.sh
index 1ae3ef5bf..36c14634a 100644
--- a/regress/transfer.sh
+++ b/regress/transfer.sh
@@ -1,9 +1,9 @@
1# $OpenBSD: transfer.sh,v 1.2 2013/05/17 04:29:14 dtucker Exp $ 1# $OpenBSD: transfer.sh,v 1.3 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="transfer data" 4tid="transfer data"
5 5
6for p in 1 2; do 6for p in ${SSH_PROTOCOLS}; do
7 verbose "$tid: proto $p" 7 verbose "$tid: proto $p"
8 rm -f ${COPY} 8 rm -f ${COPY}
9 ${SSH} -n -q -$p -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY} 9 ${SSH} -n -q -$p -F $OBJ/ssh_proxy somehost cat ${DATA} > ${COPY}
diff --git a/regress/try-ciphers.sh b/regress/try-ciphers.sh
index 2881ce16c..4165c7b88 100644
--- a/regress/try-ciphers.sh
+++ b/regress/try-ciphers.sh
@@ -1,4 +1,4 @@
1# $OpenBSD: try-ciphers.sh,v 1.23 2014/04/21 22:15:37 djm Exp $ 1# $OpenBSD: try-ciphers.sh,v 1.24 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="try ciphers" 4tid="try ciphers"
@@ -26,7 +26,11 @@ for c in `${SSH} -Q cipher`; do
26 done 26 done
27done 27done
28 28
29ciphers="3des blowfish" 29if ssh_version 1; then
30 ciphers="3des blowfish"
31else
32 ciphers=""
33fi
30for c in $ciphers; do 34for c in $ciphers; do
31 trace "proto 1 cipher $c" 35 trace "proto 1 cipher $c"
32 verbose "test $tid: proto 1 cipher $c" 36 verbose "test $tid: proto 1 cipher $c"
diff --git a/regress/unittests/Makefile b/regress/unittests/Makefile
index bdb4574e2..d3d90823f 100644
--- a/regress/unittests/Makefile
+++ b/regress/unittests/Makefile
@@ -1,5 +1,5 @@
1# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $ 1# $OpenBSD: Makefile,v 1.5 2015/02/16 22:21:03 djm Exp $
2 2REGRESS_FAIL_EARLY= yes
3SUBDIR= test_helper sshbuf sshkey 3SUBDIR= test_helper sshbuf sshkey bitmap kex hostkeys
4 4
5.include <bsd.subdir.mk> 5.include <bsd.subdir.mk>
diff --git a/regress/unittests/Makefile.inc b/regress/unittests/Makefile.inc
index 4c3363749..c55d00c61 100644
--- a/regress/unittests/Makefile.inc
+++ b/regress/unittests/Makefile.inc
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile.inc,v 1.1 2014/04/30 05:32:00 djm Exp $ 1# $OpenBSD: Makefile.inc,v 1.3 2015/01/23 21:21:23 miod Exp $
2 2
3.include <bsd.own.mk> 3.include <bsd.own.mk>
4.include <bsd.obj.mk> 4.include <bsd.obj.mk>
@@ -21,7 +21,6 @@ CDIAGFLAGS+= -Wmissing-declarations
21CDIAGFLAGS+= -Wmissing-prototypes 21CDIAGFLAGS+= -Wmissing-prototypes
22CDIAGFLAGS+= -Wparentheses 22CDIAGFLAGS+= -Wparentheses
23CDIAGFLAGS+= -Wpointer-arith 23CDIAGFLAGS+= -Wpointer-arith
24CDIAGFLAGS+= -Wpointer-sign
25CDIAGFLAGS+= -Wreturn-type 24CDIAGFLAGS+= -Wreturn-type
26CDIAGFLAGS+= -Wshadow 25CDIAGFLAGS+= -Wshadow
27CDIAGFLAGS+= -Wsign-compare 26CDIAGFLAGS+= -Wsign-compare
@@ -32,6 +31,7 @@ CDIAGFLAGS+= -Wtrigraphs
32CDIAGFLAGS+= -Wuninitialized 31CDIAGFLAGS+= -Wuninitialized
33CDIAGFLAGS+= -Wunused 32CDIAGFLAGS+= -Wunused
34.if ${COMPILER_VERSION} == "gcc4" 33.if ${COMPILER_VERSION} == "gcc4"
34CDIAGFLAGS+= -Wpointer-sign
35CDIAGFLAGS+= -Wold-style-definition 35CDIAGFLAGS+= -Wold-style-definition
36.endif 36.endif
37 37
diff --git a/regress/unittests/bitmap/Makefile b/regress/unittests/bitmap/Makefile
new file mode 100644
index 000000000..b704d22d6
--- /dev/null
+++ b/regress/unittests/bitmap/Makefile
@@ -0,0 +1,12 @@
1# $OpenBSD: Makefile,v 1.1 2015/01/15 07:36:28 djm Exp $
2
3TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
4
5PROG=test_bitmap
6SRCS=tests.c
7REGRESS_TARGETS=run-regress-${PROG}
8
9run-regress-${PROG}: ${PROG}
10 env ${TEST_ENV} ./${PROG}
11
12.include <bsd.regress.mk>
diff --git a/regress/unittests/bitmap/tests.c b/regress/unittests/bitmap/tests.c
new file mode 100644
index 000000000..23025f90a
--- /dev/null
+++ b/regress/unittests/bitmap/tests.c
@@ -0,0 +1,135 @@
1/* $OpenBSD: tests.c,v 1.1 2015/01/15 07:36:28 djm Exp $ */
2/*
3 * Regress test for bitmap.h bitmap API
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14#include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include <openssl/bn.h>
20
21#include "../test_helper/test_helper.h"
22
23#include "bitmap.h"
24
25#define NTESTS 131
26
27void
28tests(void)
29{
30 struct bitmap *b;
31 BIGNUM *bn;
32 size_t len;
33 int i, j, k, n;
34 u_char bbuf[1024], bnbuf[1024];
35 int r;
36
37 TEST_START("bitmap_new");
38 b = bitmap_new();
39 ASSERT_PTR_NE(b, NULL);
40 bn = BN_new();
41 ASSERT_PTR_NE(bn, NULL);
42 TEST_DONE();
43
44 TEST_START("bitmap_set_bit / bitmap_test_bit");
45 for (i = -1; i < NTESTS; i++) {
46 for (j = -1; j < NTESTS; j++) {
47 for (k = -1; k < NTESTS; k++) {
48 bitmap_zero(b);
49 BN_clear(bn);
50
51 test_subtest_info("set %d/%d/%d", i, j, k);
52 /* Set bits */
53 if (i >= 0) {
54 ASSERT_INT_EQ(bitmap_set_bit(b, i), 0);
55 ASSERT_INT_EQ(BN_set_bit(bn, i), 1);
56 }
57 if (j >= 0) {
58 ASSERT_INT_EQ(bitmap_set_bit(b, j), 0);
59 ASSERT_INT_EQ(BN_set_bit(bn, j), 1);
60 }
61 if (k >= 0) {
62 ASSERT_INT_EQ(bitmap_set_bit(b, k), 0);
63 ASSERT_INT_EQ(BN_set_bit(bn, k), 1);
64 }
65
66 /* Check perfect match between bitmap and bn */
67 test_subtest_info("match %d/%d/%d", i, j, k);
68 for (n = 0; n < NTESTS; n++) {
69 ASSERT_INT_EQ(BN_is_bit_set(bn, n),
70 bitmap_test_bit(b, n));
71 }
72
73 /* Test length calculations */
74 test_subtest_info("length %d/%d/%d", i, j, k);
75 ASSERT_INT_EQ(BN_num_bits(bn),
76 (int)bitmap_nbits(b));
77 ASSERT_INT_EQ(BN_num_bytes(bn),
78 (int)bitmap_nbytes(b));
79
80 /* Test serialisation */
81 test_subtest_info("serialise %d/%d/%d",
82 i, j, k);
83 len = bitmap_nbytes(b);
84 memset(bbuf, 0xfc, sizeof(bbuf));
85 ASSERT_INT_EQ(bitmap_to_string(b, bbuf,
86 sizeof(bbuf)), 0);
87 for (n = len; n < (int)sizeof(bbuf); n++)
88 ASSERT_U8_EQ(bbuf[n], 0xfc);
89 r = BN_bn2bin(bn, bnbuf);
90 ASSERT_INT_GE(r, 0);
91 ASSERT_INT_EQ(r, (int)len);
92 ASSERT_MEM_EQ(bbuf, bnbuf, len);
93
94 /* Test deserialisation */
95 test_subtest_info("deserialise %d/%d/%d",
96 i, j, k);
97 bitmap_zero(b);
98 ASSERT_INT_EQ(bitmap_from_string(b, bnbuf,
99 len), 0);
100 for (n = 0; n < NTESTS; n++) {
101 ASSERT_INT_EQ(BN_is_bit_set(bn, n),
102 bitmap_test_bit(b, n));
103 }
104
105 /* Test clearing bits */
106 test_subtest_info("clear %d/%d/%d",
107 i, j, k);
108 for (n = 0; n < NTESTS; n++) {
109 ASSERT_INT_EQ(bitmap_set_bit(b, n), 0);
110 ASSERT_INT_EQ(BN_set_bit(bn, n), 1);
111 }
112 if (i >= 0) {
113 bitmap_clear_bit(b, i);
114 BN_clear_bit(bn, i);
115 }
116 if (j >= 0) {
117 bitmap_clear_bit(b, j);
118 BN_clear_bit(bn, j);
119 }
120 if (k >= 0) {
121 bitmap_clear_bit(b, k);
122 BN_clear_bit(bn, k);
123 }
124 for (n = 0; n < NTESTS; n++) {
125 ASSERT_INT_EQ(BN_is_bit_set(bn, n),
126 bitmap_test_bit(b, n));
127 }
128 }
129 }
130 }
131 bitmap_free(b);
132 BN_free(bn);
133 TEST_DONE();
134}
135
diff --git a/regress/unittests/hostkeys/Makefile b/regress/unittests/hostkeys/Makefile
new file mode 100644
index 000000000..f52a85fb1
--- /dev/null
+++ b/regress/unittests/hostkeys/Makefile
@@ -0,0 +1,12 @@
1# $OpenBSD: Makefile,v 1.1 2015/02/16 22:18:34 djm Exp $
2
3TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
4
5PROG=test_hostkeys
6SRCS=tests.c test_iterate.c
7REGRESS_TARGETS=run-regress-${PROG}
8
9run-regress-${PROG}: ${PROG}
10 env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
11
12.include <bsd.regress.mk>
diff --git a/regress/unittests/hostkeys/mktestdata.sh b/regress/unittests/hostkeys/mktestdata.sh
new file mode 100644
index 000000000..36890ba11
--- /dev/null
+++ b/regress/unittests/hostkeys/mktestdata.sh
@@ -0,0 +1,94 @@
1#!/bin/sh
2# $OpenBSD: mktestdata.sh,v 1.1 2015/02/16 22:18:34 djm Exp $
3
4set -ex
5
6cd testdata
7
8rm -f rsa1* rsa* dsa* ecdsa* ed25519*
9rm -f known_hosts*
10
11gen_all() {
12 _n=$1
13 _ecdsa_bits=256
14 test "x$_n" = "x1" && _ecdsa_bits=384
15 test "x$_n" = "x2" && _ecdsa_bits=521
16 ssh-keygen -qt rsa1 -b 1024 -C "RSA1 #$_n" -N "" -f rsa1_$_n
17 ssh-keygen -qt rsa -b 1024 -C "RSA #$_n" -N "" -f rsa_$_n
18 ssh-keygen -qt dsa -b 1024 -C "DSA #$_n" -N "" -f dsa_$_n
19 ssh-keygen -qt ecdsa -b $_ecdsa_bits -C "ECDSA #$_n" -N "" -f ecdsa_$_n
20 ssh-keygen -qt ed25519 -C "ED25519 #$_n" -N "" -f ed25519_$_n
21 # Don't need private keys
22 rm -f rsa1_$_n rsa_$_n dsa_$_n ecdsa_$_n ed25519_$_n
23}
24
25hentries() {
26 _preamble=$1
27 _kspec=$2
28 for k in `ls -1 $_kspec | sort` ; do
29 printf "$_preamble "
30 cat $k
31 done
32 echo
33}
34
35gen_all 1
36gen_all 2
37gen_all 3
38gen_all 4
39gen_all 5
40gen_all 6
41
42# A section of known_hosts with hashed hostnames.
43(
44 hentries "sisyphus.example.com" "*_5.pub"
45 hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_6.pub"
46) > known_hosts_hash_frag
47ssh-keygen -Hf known_hosts_hash_frag
48rm -f known_hosts_hash_frag.old
49
50# Populated known_hosts, including comments, hashed names and invalid lines
51(
52 echo "# Plain host keys, plain host names"
53 hentries "sisyphus.example.com" "*_1.pub"
54
55 echo "# Plain host keys, hostnames + addresses"
56 hentries "prometheus.example.com,192.0.2.1,2001:db8::1" "*_2.pub"
57
58 echo "# Some hosts with wildcard names / IPs"
59 hentries "*.example.com,192.0.2.*,2001:*" "*_3.pub"
60
61 echo "# Hashed hostname and address entries"
62 cat known_hosts_hash_frag
63 rm -f known_hosts_hash_frag
64 echo
65
66 echo "# Revoked and CA keys"
67 printf "@revoked sisyphus.example.com " ; cat rsa1_4.pub
68 printf "@revoked sisyphus.example.com " ; cat ed25519_4.pub
69 printf "@cert-authority prometheus.example.com " ; cat ecdsa_4.pub
70 printf "@cert-authority *.example.com " ; cat dsa_4.pub
71
72 printf "\n"
73 echo "# Some invalid lines"
74 # Invalid marker
75 printf "@what sisyphus.example.com " ; cat rsa1_1.pub
76 # Key missing
77 echo "sisyphus.example.com "
78 # Key blob missing
79 echo "prometheus.example.com ssh-ed25519 "
80 # Key blob truncated
81 echo "sisyphus.example.com ssh-dsa AAAATgAAAAdz"
82 # RSA1 key truncated after key bits
83 echo "prometheus.example.com 1024 "
84 # RSA1 key truncated after exponent
85 echo "sisyphus.example.com 1024 65535 "
86 # RSA1 key incorrect key bits
87 printf "prometheus.example.com 1025 " ; cut -d' ' -f2- < rsa1_1.pub
88 # Invalid type
89 echo "sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg=="
90 # Type mismatch with blob
91 echo "prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg=="
92) > known_hosts
93
94echo OK
diff --git a/regress/unittests/hostkeys/test_iterate.c b/regress/unittests/hostkeys/test_iterate.c
new file mode 100644
index 000000000..d81291b68
--- /dev/null
+++ b/regress/unittests/hostkeys/test_iterate.c
@@ -0,0 +1,1171 @@
1/* $OpenBSD: test_iterate.c,v 1.3 2015/03/07 04:41:48 djm Exp $ */
2/*
3 * Regress test for hostfile.h hostkeys_foreach()
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14#include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include "../test_helper/test_helper.h"
20
21#include "sshkey.h"
22#include "authfile.h"
23#include "hostfile.h"
24
25struct expected {
26 const char *key_file; /* Path for key, NULL for none */
27 int no_parse_status; /* Expected status w/o key parsing */
28 int no_parse_keytype; /* Expected keytype w/o key parsing */
29 int match_host_p; /* Match 'prometheus.example.com' */
30 int match_host_s; /* Match 'sisyphus.example.com' */
31 int match_ipv4; /* Match '192.0.2.1' */
32 int match_ipv6; /* Match '2001:db8::1' */
33 int match_flags; /* Expected flags from match */
34 struct hostkey_foreach_line l; /* Expected line contents */
35};
36
37struct cbctx {
38 const struct expected *expected;
39 size_t nexpected;
40 size_t i;
41 int flags;
42 int match_host_p;
43 int match_host_s;
44 int match_ipv4;
45 int match_ipv6;
46};
47
48/*
49 * hostkeys_foreach() iterator callback that verifies the line passed
50 * against an array of expected entries.
51 */
52static int
53check(struct hostkey_foreach_line *l, void *_ctx)
54{
55 struct cbctx *ctx = (struct cbctx *)_ctx;
56 const struct expected *expected;
57 int parse_key = (ctx->flags & HKF_WANT_PARSE_KEY) != 0;
58 const int matching = (ctx->flags & HKF_WANT_MATCH) != 0;
59 u_int expected_status, expected_match;
60 int expected_keytype;
61
62 test_subtest_info("entry %zu/%zu, file line %ld",
63 ctx->i + 1, ctx->nexpected, l->linenum);
64
65 for (;;) {
66 ASSERT_SIZE_T_LT(ctx->i, ctx->nexpected);
67 expected = ctx->expected + ctx->i++;
68 /* If we are matching host/IP then skip entries that don't */
69 if (!matching)
70 break;
71 if (ctx->match_host_p && expected->match_host_p)
72 break;
73 if (ctx->match_host_s && expected->match_host_s)
74 break;
75 if (ctx->match_ipv4 && expected->match_ipv4)
76 break;
77 if (ctx->match_ipv6 && expected->match_ipv6)
78 break;
79 }
80 expected_status = (parse_key || expected->no_parse_status < 0) ?
81 expected->l.status : (u_int)expected->no_parse_status;
82 expected_match = expected->l.match;
83#define UPDATE_MATCH_STATUS(x) do { \
84 if (ctx->x && expected->x) { \
85 expected_match |= expected->x; \
86 if (expected_status == HKF_STATUS_OK) \
87 expected_status = HKF_STATUS_MATCHED; \
88 } \
89 } while (0)
90 expected_keytype = (parse_key || expected->no_parse_keytype < 0) ?
91 expected->l.keytype : expected->no_parse_keytype;
92
93#ifndef WITH_SSH1
94 if (expected->l.keytype == KEY_RSA1 ||
95 expected->no_parse_keytype == KEY_RSA1) {
96 expected_status = HKF_STATUS_INVALID;
97 expected_keytype = KEY_UNSPEC;
98 parse_key = 0;
99 }
100#endif
101#ifndef OPENSSL_HAS_ECC
102 if (expected->l.keytype == KEY_ECDSA ||
103 expected->no_parse_keytype == KEY_ECDSA) {
104 expected_status = HKF_STATUS_INVALID;
105 expected_keytype = KEY_UNSPEC;
106 parse_key = 0;
107 }
108#endif
109
110 UPDATE_MATCH_STATUS(match_host_p);
111 UPDATE_MATCH_STATUS(match_host_s);
112 UPDATE_MATCH_STATUS(match_ipv4);
113 UPDATE_MATCH_STATUS(match_ipv6);
114
115 ASSERT_PTR_NE(l->path, NULL); /* Don't care about path */
116 ASSERT_LONG_LONG_EQ(l->linenum, expected->l.linenum);
117 ASSERT_U_INT_EQ(l->status, expected_status);
118 ASSERT_U_INT_EQ(l->match, expected_match);
119 /* Not all test entries contain fulltext */
120 if (expected->l.line != NULL)
121 ASSERT_STRING_EQ(l->line, expected->l.line);
122 ASSERT_INT_EQ(l->marker, expected->l.marker);
123 /* XXX we skip hashed hostnames for now; implement checking */
124 if (expected->l.hosts != NULL)
125 ASSERT_STRING_EQ(l->hosts, expected->l.hosts);
126 /* Not all test entries contain raw keys */
127 if (expected->l.rawkey != NULL)
128 ASSERT_STRING_EQ(l->rawkey, expected->l.rawkey);
129 /* XXX synthesise raw key for cases lacking and compare */
130 ASSERT_INT_EQ(l->keytype, expected_keytype);
131 if (parse_key) {
132 if (expected->l.key == NULL)
133 ASSERT_PTR_EQ(l->key, NULL);
134 if (expected->l.key != NULL) {
135 ASSERT_PTR_NE(l->key, NULL);
136 ASSERT_INT_EQ(sshkey_equal(l->key, expected->l.key), 1);
137 }
138 }
139 if (parse_key && !(l->comment == NULL && expected->l.comment == NULL))
140 ASSERT_STRING_EQ(l->comment, expected->l.comment);
141 return 0;
142}
143
144/* Loads public keys for a set of expected results */
145static void
146prepare_expected(struct expected *expected, size_t n)
147{
148 size_t i;
149
150 for (i = 0; i < n; i++) {
151 if (expected[i].key_file == NULL)
152 continue;
153#ifndef WITH_SSH1
154 if (expected[i].l.keytype == KEY_RSA1)
155 continue;
156#endif
157#ifndef OPENSSL_HAS_ECC
158 if (expected[i].l.keytype == KEY_ECDSA)
159 continue;
160#endif
161 ASSERT_INT_EQ(sshkey_load_public(
162 test_data_file(expected[i].key_file), &expected[i].l.key,
163 NULL), 0);
164 }
165}
166
167struct expected expected_full[] = {
168 { NULL, -1, -1, 0, 0, 0, 0, -1, {
169 NULL, /* path, don't care */
170 1, /* line number */
171 HKF_STATUS_COMMENT, /* status */
172 0, /* match flags */
173 "# Plain host keys, plain host names", /* full line, optional */
174 MRK_NONE, /* marker (CA / revoked) */
175 NULL, /* hosts text */
176 NULL, /* raw key, optional */
177 KEY_UNSPEC, /* key type */
178 NULL, /* deserialised key */
179 NULL, /* comment */
180 } },
181 { "dsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
182 NULL,
183 2,
184 HKF_STATUS_OK,
185 0,
186 NULL,
187 MRK_NONE,
188 "sisyphus.example.com",
189 NULL,
190 KEY_DSA,
191 NULL, /* filled at runtime */
192 "DSA #1",
193 } },
194 { "ecdsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
195 NULL,
196 3,
197 HKF_STATUS_OK,
198 0,
199 NULL,
200 MRK_NONE,
201 "sisyphus.example.com",
202 NULL,
203 KEY_ECDSA,
204 NULL, /* filled at runtime */
205 "ECDSA #1",
206 } },
207 { "ed25519_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
208 NULL,
209 4,
210 HKF_STATUS_OK,
211 0,
212 NULL,
213 MRK_NONE,
214 "sisyphus.example.com",
215 NULL,
216 KEY_ED25519,
217 NULL, /* filled at runtime */
218 "ED25519 #1",
219 } },
220 { "rsa1_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
221 NULL,
222 5,
223 HKF_STATUS_OK,
224 0,
225 NULL,
226 MRK_NONE,
227 "sisyphus.example.com",
228 NULL,
229 KEY_RSA1,
230 NULL, /* filled at runtime */
231 "RSA1 #1",
232 } },
233 { "rsa_1.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
234 NULL,
235 6,
236 HKF_STATUS_OK,
237 0,
238 NULL,
239 MRK_NONE,
240 "sisyphus.example.com",
241 NULL,
242 KEY_RSA,
243 NULL, /* filled at runtime */
244 "RSA #1",
245 } },
246 { NULL, -1, -1, 0, 0, 0, 0, -1, {
247 NULL,
248 7,
249 HKF_STATUS_COMMENT,
250 0,
251 "",
252 MRK_NONE,
253 NULL,
254 NULL,
255 KEY_UNSPEC,
256 NULL,
257 NULL,
258 } },
259 { NULL, -1, -1, 0, 0, 0, 0, -1, {
260 NULL,
261 8,
262 HKF_STATUS_COMMENT,
263 0,
264 "# Plain host keys, hostnames + addresses",
265 MRK_NONE,
266 NULL,
267 NULL,
268 KEY_UNSPEC,
269 NULL,
270 NULL,
271 } },
272 { "dsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
273 NULL,
274 9,
275 HKF_STATUS_OK,
276 0,
277 NULL,
278 MRK_NONE,
279 "prometheus.example.com,192.0.2.1,2001:db8::1",
280 NULL,
281 KEY_DSA,
282 NULL, /* filled at runtime */
283 "DSA #2",
284 } },
285 { "ecdsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
286 NULL,
287 10,
288 HKF_STATUS_OK,
289 0,
290 NULL,
291 MRK_NONE,
292 "prometheus.example.com,192.0.2.1,2001:db8::1",
293 NULL,
294 KEY_ECDSA,
295 NULL, /* filled at runtime */
296 "ECDSA #2",
297 } },
298 { "ed25519_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
299 NULL,
300 11,
301 HKF_STATUS_OK,
302 0,
303 NULL,
304 MRK_NONE,
305 "prometheus.example.com,192.0.2.1,2001:db8::1",
306 NULL,
307 KEY_ED25519,
308 NULL, /* filled at runtime */
309 "ED25519 #2",
310 } },
311 { "rsa1_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
312 NULL,
313 12,
314 HKF_STATUS_OK,
315 0,
316 NULL,
317 MRK_NONE,
318 "prometheus.example.com,192.0.2.1,2001:db8::1",
319 NULL,
320 KEY_RSA1,
321 NULL, /* filled at runtime */
322 "RSA1 #2",
323 } },
324 { "rsa_2.pub" , -1, -1, HKF_MATCH_HOST, 0, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
325 NULL,
326 13,
327 HKF_STATUS_OK,
328 0,
329 NULL,
330 MRK_NONE,
331 "prometheus.example.com,192.0.2.1,2001:db8::1",
332 NULL,
333 KEY_RSA,
334 NULL, /* filled at runtime */
335 "RSA #2",
336 } },
337 { NULL, -1, -1, 0, 0, 0, 0, -1, {
338 NULL,
339 14,
340 HKF_STATUS_COMMENT,
341 0,
342 "",
343 MRK_NONE,
344 NULL,
345 NULL,
346 KEY_UNSPEC,
347 NULL,
348 NULL,
349 } },
350 { NULL, -1, -1, 0, 0, 0, 0, -1, {
351 NULL,
352 15,
353 HKF_STATUS_COMMENT,
354 0,
355 "# Some hosts with wildcard names / IPs",
356 MRK_NONE,
357 NULL,
358 NULL,
359 KEY_UNSPEC,
360 NULL,
361 NULL,
362 } },
363 { "dsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
364 NULL,
365 16,
366 HKF_STATUS_OK,
367 0,
368 NULL,
369 MRK_NONE,
370 "*.example.com,192.0.2.*,2001:*",
371 NULL,
372 KEY_DSA,
373 NULL, /* filled at runtime */
374 "DSA #3",
375 } },
376 { "ecdsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
377 NULL,
378 17,
379 HKF_STATUS_OK,
380 0,
381 NULL,
382 MRK_NONE,
383 "*.example.com,192.0.2.*,2001:*",
384 NULL,
385 KEY_ECDSA,
386 NULL, /* filled at runtime */
387 "ECDSA #3",
388 } },
389 { "ed25519_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
390 NULL,
391 18,
392 HKF_STATUS_OK,
393 0,
394 NULL,
395 MRK_NONE,
396 "*.example.com,192.0.2.*,2001:*",
397 NULL,
398 KEY_ED25519,
399 NULL, /* filled at runtime */
400 "ED25519 #3",
401 } },
402 { "rsa1_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
403 NULL,
404 19,
405 HKF_STATUS_OK,
406 0,
407 NULL,
408 MRK_NONE,
409 "*.example.com,192.0.2.*,2001:*",
410 NULL,
411 KEY_RSA1,
412 NULL, /* filled at runtime */
413 "RSA1 #3",
414 } },
415 { "rsa_3.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, HKF_MATCH_IP, HKF_MATCH_IP, -1, {
416 NULL,
417 20,
418 HKF_STATUS_OK,
419 0,
420 NULL,
421 MRK_NONE,
422 "*.example.com,192.0.2.*,2001:*",
423 NULL,
424 KEY_RSA,
425 NULL, /* filled at runtime */
426 "RSA #3",
427 } },
428 { NULL, -1, -1, 0, 0, 0, 0, -1, {
429 NULL,
430 21,
431 HKF_STATUS_COMMENT,
432 0,
433 "",
434 MRK_NONE,
435 NULL,
436 NULL,
437 KEY_UNSPEC,
438 NULL,
439 NULL,
440 } },
441 { NULL, -1, -1, 0, 0, 0, 0, -1, {
442 NULL,
443 22,
444 HKF_STATUS_COMMENT,
445 0,
446 "# Hashed hostname and address entries",
447 MRK_NONE,
448 NULL,
449 NULL,
450 KEY_UNSPEC,
451 NULL,
452 NULL,
453 } },
454 { "dsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
455 NULL,
456 23,
457 HKF_STATUS_OK,
458 0,
459 NULL,
460 MRK_NONE,
461 NULL,
462 NULL,
463 KEY_DSA,
464 NULL, /* filled at runtime */
465 "DSA #5",
466 } },
467 { "ecdsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
468 NULL,
469 24,
470 HKF_STATUS_OK,
471 0,
472 NULL,
473 MRK_NONE,
474 NULL,
475 NULL,
476 KEY_ECDSA,
477 NULL, /* filled at runtime */
478 "ECDSA #5",
479 } },
480 { "ed25519_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
481 NULL,
482 25,
483 HKF_STATUS_OK,
484 0,
485 NULL,
486 MRK_NONE,
487 NULL,
488 NULL,
489 KEY_ED25519,
490 NULL, /* filled at runtime */
491 "ED25519 #5",
492 } },
493 { "rsa1_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
494 NULL,
495 26,
496 HKF_STATUS_OK,
497 0,
498 NULL,
499 MRK_NONE,
500 NULL,
501 NULL,
502 KEY_RSA1,
503 NULL, /* filled at runtime */
504 "RSA1 #5",
505 } },
506 { "rsa_5.pub" , -1, -1, 0, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, -1, {
507 NULL,
508 27,
509 HKF_STATUS_OK,
510 0,
511 NULL,
512 MRK_NONE,
513 NULL,
514 NULL,
515 KEY_RSA,
516 NULL, /* filled at runtime */
517 "RSA #5",
518 } },
519 { NULL, -1, -1, 0, 0, 0, 0, -1, {
520 NULL,
521 28,
522 HKF_STATUS_COMMENT,
523 0,
524 "",
525 MRK_NONE,
526 NULL,
527 NULL,
528 KEY_UNSPEC,
529 NULL,
530 NULL,
531 } },
532 /*
533 * The next series have each key listed multiple times, as the
534 * hostname and addresses in the pre-hashed known_hosts are split
535 * to separate lines.
536 */
537 { "dsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
538 NULL,
539 29,
540 HKF_STATUS_OK,
541 0,
542 NULL,
543 MRK_NONE,
544 NULL,
545 NULL,
546 KEY_DSA,
547 NULL, /* filled at runtime */
548 "DSA #6",
549 } },
550 { "dsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
551 NULL,
552 30,
553 HKF_STATUS_OK,
554 0,
555 NULL,
556 MRK_NONE,
557 NULL,
558 NULL,
559 KEY_DSA,
560 NULL, /* filled at runtime */
561 "DSA #6",
562 } },
563 { "dsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
564 NULL,
565 31,
566 HKF_STATUS_OK,
567 0,
568 NULL,
569 MRK_NONE,
570 NULL,
571 NULL,
572 KEY_DSA,
573 NULL, /* filled at runtime */
574 "DSA #6",
575 } },
576 { "ecdsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
577 NULL,
578 32,
579 HKF_STATUS_OK,
580 0,
581 NULL,
582 MRK_NONE,
583 NULL,
584 NULL,
585 KEY_ECDSA,
586 NULL, /* filled at runtime */
587 "ECDSA #6",
588 } },
589 { "ecdsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
590 NULL,
591 33,
592 HKF_STATUS_OK,
593 0,
594 NULL,
595 MRK_NONE,
596 NULL,
597 NULL,
598 KEY_ECDSA,
599 NULL, /* filled at runtime */
600 "ECDSA #6",
601 } },
602 { "ecdsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
603 NULL,
604 34,
605 HKF_STATUS_OK,
606 0,
607 NULL,
608 MRK_NONE,
609 NULL,
610 NULL,
611 KEY_ECDSA,
612 NULL, /* filled at runtime */
613 "ECDSA #6",
614 } },
615 { "ed25519_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
616 NULL,
617 35,
618 HKF_STATUS_OK,
619 0,
620 NULL,
621 MRK_NONE,
622 NULL,
623 NULL,
624 KEY_ED25519,
625 NULL, /* filled at runtime */
626 "ED25519 #6",
627 } },
628 { "ed25519_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
629 NULL,
630 36,
631 HKF_STATUS_OK,
632 0,
633 NULL,
634 MRK_NONE,
635 NULL,
636 NULL,
637 KEY_ED25519,
638 NULL, /* filled at runtime */
639 "ED25519 #6",
640 } },
641 { "ed25519_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
642 NULL,
643 37,
644 HKF_STATUS_OK,
645 0,
646 NULL,
647 MRK_NONE,
648 NULL,
649 NULL,
650 KEY_ED25519,
651 NULL, /* filled at runtime */
652 "ED25519 #6",
653 } },
654 { "rsa1_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
655 NULL,
656 38,
657 HKF_STATUS_OK,
658 0,
659 NULL,
660 MRK_NONE,
661 NULL,
662 NULL,
663 KEY_RSA1,
664 NULL, /* filled at runtime */
665 "RSA1 #6",
666 } },
667 { "rsa1_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
668 NULL,
669 39,
670 HKF_STATUS_OK,
671 0,
672 NULL,
673 MRK_NONE,
674 NULL,
675 NULL,
676 KEY_RSA1,
677 NULL, /* filled at runtime */
678 "RSA1 #6",
679 } },
680 { "rsa1_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
681 NULL,
682 40,
683 HKF_STATUS_OK,
684 0,
685 NULL,
686 MRK_NONE,
687 NULL,
688 NULL,
689 KEY_RSA1,
690 NULL, /* filled at runtime */
691 "RSA1 #6",
692 } },
693 { "rsa_6.pub" , -1, -1, HKF_MATCH_HOST|HKF_MATCH_HOST_HASHED, 0, 0, 0, -1, {
694 NULL,
695 41,
696 HKF_STATUS_OK,
697 0,
698 NULL,
699 MRK_NONE,
700 NULL,
701 NULL,
702 KEY_RSA,
703 NULL, /* filled at runtime */
704 "RSA #6",
705 } },
706 { "rsa_6.pub" , -1, -1, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, 0, -1, {
707 NULL,
708 42,
709 HKF_STATUS_OK,
710 0,
711 NULL,
712 MRK_NONE,
713 NULL,
714 NULL,
715 KEY_RSA,
716 NULL, /* filled at runtime */
717 "RSA #6",
718 } },
719 { "rsa_6.pub" , -1, -1, 0, 0, 0, HKF_MATCH_IP|HKF_MATCH_IP_HASHED, -1, {
720 NULL,
721 43,
722 HKF_STATUS_OK,
723 0,
724 NULL,
725 MRK_NONE,
726 NULL,
727 NULL,
728 KEY_RSA,
729 NULL, /* filled at runtime */
730 "RSA #6",
731 } },
732 { NULL, -1, -1, 0, 0, 0, 0, -1, {
733 NULL,
734 44,
735 HKF_STATUS_COMMENT,
736 0,
737 "",
738 MRK_NONE,
739 NULL,
740 NULL,
741 KEY_UNSPEC,
742 NULL,
743 NULL,
744 } },
745 { NULL, -1, -1, 0, 0, 0, 0, -1, {
746 NULL,
747 45,
748 HKF_STATUS_COMMENT,
749 0,
750 "",
751 MRK_NONE,
752 NULL,
753 NULL,
754 KEY_UNSPEC,
755 NULL,
756 NULL,
757 } },
758 { NULL, -1, -1, 0, 0, 0, 0, -1, {
759 NULL,
760 46,
761 HKF_STATUS_COMMENT,
762 0,
763 "# Revoked and CA keys",
764 MRK_NONE,
765 NULL,
766 NULL,
767 KEY_UNSPEC,
768 NULL,
769 NULL,
770 } },
771 { "rsa1_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
772 NULL,
773 47,
774 HKF_STATUS_OK,
775 0,
776 NULL,
777 MRK_REVOKE,
778 "sisyphus.example.com",
779 NULL,
780 KEY_RSA1,
781 NULL, /* filled at runtime */
782 "RSA1 #4",
783 } },
784 { "ed25519_4.pub" , -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
785 NULL,
786 48,
787 HKF_STATUS_OK,
788 0,
789 NULL,
790 MRK_REVOKE,
791 "sisyphus.example.com",
792 NULL,
793 KEY_ED25519,
794 NULL, /* filled at runtime */
795 "ED25519 #4",
796 } },
797 { "ecdsa_4.pub" , -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
798 NULL,
799 49,
800 HKF_STATUS_OK,
801 0,
802 NULL,
803 MRK_CA,
804 "prometheus.example.com",
805 NULL,
806 KEY_ECDSA,
807 NULL, /* filled at runtime */
808 "ECDSA #4",
809 } },
810 { "dsa_4.pub" , -1, -1, HKF_MATCH_HOST, HKF_MATCH_HOST, 0, 0, -1, {
811 NULL,
812 50,
813 HKF_STATUS_OK,
814 0,
815 NULL,
816 MRK_CA,
817 "*.example.com",
818 NULL,
819 KEY_DSA,
820 NULL, /* filled at runtime */
821 "DSA #4",
822 } },
823 { NULL, -1, -1, 0, 0, 0, 0, -1, {
824 NULL,
825 51,
826 HKF_STATUS_COMMENT,
827 0,
828 "",
829 MRK_NONE,
830 NULL,
831 NULL,
832 KEY_UNSPEC,
833 NULL,
834 NULL,
835 } },
836 { NULL, -1, -1, 0, 0, 0, 0, -1, {
837 NULL,
838 52,
839 HKF_STATUS_COMMENT,
840 0,
841 "# Some invalid lines",
842 MRK_NONE,
843 NULL,
844 NULL,
845 KEY_UNSPEC,
846 NULL,
847 NULL,
848 } },
849 { NULL, -1, -1, 0, 0, 0, 0, -1, {
850 NULL,
851 53,
852 HKF_STATUS_INVALID,
853 0,
854 NULL,
855 MRK_ERROR,
856 NULL,
857 NULL,
858 KEY_UNSPEC,
859 NULL,
860 NULL,
861 } },
862 { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
863 NULL,
864 54,
865 HKF_STATUS_INVALID,
866 0,
867 NULL,
868 MRK_NONE,
869 "sisyphus.example.com",
870 NULL,
871 KEY_UNSPEC,
872 NULL,
873 NULL,
874 } },
875 { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
876 NULL,
877 55,
878 HKF_STATUS_INVALID,
879 0,
880 NULL,
881 MRK_NONE,
882 "prometheus.example.com",
883 NULL,
884 KEY_UNSPEC,
885 NULL,
886 NULL,
887 } },
888 { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
889 NULL,
890 56,
891 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
892 0,
893 NULL,
894 MRK_NONE,
895 "sisyphus.example.com",
896 NULL,
897 KEY_UNSPEC,
898 NULL,
899 NULL,
900 } },
901 { NULL, -1, -1, HKF_MATCH_HOST, 0, 0, 0, -1, {
902 NULL,
903 57,
904 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
905 0,
906 NULL,
907 MRK_NONE,
908 "prometheus.example.com",
909 NULL,
910 KEY_UNSPEC,
911 NULL,
912 NULL,
913 } },
914 { NULL, HKF_STATUS_OK, KEY_RSA1, 0, HKF_MATCH_HOST, 0, 0, -1, {
915 NULL,
916 58,
917 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
918 0,
919 NULL,
920 MRK_NONE,
921 "sisyphus.example.com",
922 NULL,
923 KEY_UNSPEC,
924 NULL,
925 NULL,
926 } },
927 { NULL, HKF_STATUS_OK, KEY_RSA1, HKF_MATCH_HOST, 0, 0, 0, -1, {
928 NULL,
929 59,
930 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
931 0,
932 NULL,
933 MRK_NONE,
934 "prometheus.example.com",
935 NULL,
936 KEY_UNSPEC,
937 NULL, /* filled at runtime */
938 NULL,
939 } },
940 { NULL, -1, -1, 0, HKF_MATCH_HOST, 0, 0, -1, {
941 NULL,
942 60,
943 HKF_STATUS_INVALID,
944 0,
945 NULL,
946 MRK_NONE,
947 "sisyphus.example.com",
948 NULL,
949 KEY_UNSPEC,
950 NULL, /* filled at runtime */
951 NULL,
952 } },
953 { NULL, HKF_STATUS_OK, KEY_RSA, HKF_MATCH_HOST, 0, 0, 0, -1, {
954 NULL,
955 61,
956 HKF_STATUS_INVALID, /* Would be ok if key not parsed */
957 0,
958 NULL,
959 MRK_NONE,
960 "prometheus.example.com",
961 NULL,
962 KEY_UNSPEC,
963 NULL, /* filled at runtime */
964 NULL,
965 } },
966};
967
968void test_iterate(void);
969
970void
971test_iterate(void)
972{
973 struct cbctx ctx;
974
975 TEST_START("hostkeys_iterate all with key parse");
976 memset(&ctx, 0, sizeof(ctx));
977 ctx.expected = expected_full;
978 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
979 ctx.flags = HKF_WANT_PARSE_KEY;
980 prepare_expected(expected_full, ctx.nexpected);
981 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
982 check, &ctx, NULL, NULL, ctx.flags), 0);
983 TEST_DONE();
984
985 TEST_START("hostkeys_iterate all without key parse");
986 memset(&ctx, 0, sizeof(ctx));
987 ctx.expected = expected_full;
988 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
989 ctx.flags = 0;
990 prepare_expected(expected_full, ctx.nexpected);
991 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
992 check, &ctx, NULL, NULL, ctx.flags), 0);
993 TEST_DONE();
994
995 TEST_START("hostkeys_iterate specify host 1");
996 memset(&ctx, 0, sizeof(ctx));
997 ctx.expected = expected_full;
998 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
999 ctx.flags = 0;
1000 ctx.match_host_p = 1;
1001 prepare_expected(expected_full, ctx.nexpected);
1002 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1003 check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
1004 TEST_DONE();
1005
1006 TEST_START("hostkeys_iterate specify host 2");
1007 memset(&ctx, 0, sizeof(ctx));
1008 ctx.expected = expected_full;
1009 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1010 ctx.flags = 0;
1011 ctx.match_host_s = 1;
1012 prepare_expected(expected_full, ctx.nexpected);
1013 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1014 check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
1015 TEST_DONE();
1016
1017 TEST_START("hostkeys_iterate match host 1");
1018 memset(&ctx, 0, sizeof(ctx));
1019 ctx.expected = expected_full;
1020 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1021 ctx.flags = HKF_WANT_MATCH;
1022 ctx.match_host_p = 1;
1023 prepare_expected(expected_full, ctx.nexpected);
1024 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1025 check, &ctx, "prometheus.example.com", NULL, ctx.flags), 0);
1026 TEST_DONE();
1027
1028 TEST_START("hostkeys_iterate match host 2");
1029 memset(&ctx, 0, sizeof(ctx));
1030 ctx.expected = expected_full;
1031 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1032 ctx.flags = HKF_WANT_MATCH;
1033 ctx.match_host_s = 1;
1034 prepare_expected(expected_full, ctx.nexpected);
1035 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1036 check, &ctx, "sisyphus.example.com", NULL, ctx.flags), 0);
1037 TEST_DONE();
1038
1039 TEST_START("hostkeys_iterate specify host missing");
1040 memset(&ctx, 0, sizeof(ctx));
1041 ctx.expected = expected_full;
1042 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1043 ctx.flags = 0;
1044 prepare_expected(expected_full, ctx.nexpected);
1045 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1046 check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
1047 TEST_DONE();
1048
1049 TEST_START("hostkeys_iterate match host missing");
1050 memset(&ctx, 0, sizeof(ctx));
1051 ctx.expected = expected_full;
1052 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1053 ctx.flags = HKF_WANT_MATCH;
1054 prepare_expected(expected_full, ctx.nexpected);
1055 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1056 check, &ctx, "actaeon.example.org", NULL, ctx.flags), 0);
1057 TEST_DONE();
1058
1059 TEST_START("hostkeys_iterate specify IPv4");
1060 memset(&ctx, 0, sizeof(ctx));
1061 ctx.expected = expected_full;
1062 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1063 ctx.flags = 0;
1064 ctx.match_ipv4 = 1;
1065 prepare_expected(expected_full, ctx.nexpected);
1066 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1067 check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
1068 TEST_DONE();
1069
1070 TEST_START("hostkeys_iterate specify IPv6");
1071 memset(&ctx, 0, sizeof(ctx));
1072 ctx.expected = expected_full;
1073 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1074 ctx.flags = 0;
1075 ctx.match_ipv6 = 1;
1076 prepare_expected(expected_full, ctx.nexpected);
1077 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1078 check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
1079 TEST_DONE();
1080
1081 TEST_START("hostkeys_iterate match IPv4");
1082 memset(&ctx, 0, sizeof(ctx));
1083 ctx.expected = expected_full;
1084 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1085 ctx.flags = HKF_WANT_MATCH;
1086 ctx.match_ipv4 = 1;
1087 prepare_expected(expected_full, ctx.nexpected);
1088 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1089 check, &ctx, "tiresias.example.org", "192.0.2.1", ctx.flags), 0);
1090 TEST_DONE();
1091
1092 TEST_START("hostkeys_iterate match IPv6");
1093 memset(&ctx, 0, sizeof(ctx));
1094 ctx.expected = expected_full;
1095 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1096 ctx.flags = HKF_WANT_MATCH;
1097 ctx.match_ipv6 = 1;
1098 prepare_expected(expected_full, ctx.nexpected);
1099 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1100 check, &ctx, "tiresias.example.org", "2001:db8::1", ctx.flags), 0);
1101 TEST_DONE();
1102
1103 TEST_START("hostkeys_iterate specify addr missing");
1104 memset(&ctx, 0, sizeof(ctx));
1105 ctx.expected = expected_full;
1106 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1107 ctx.flags = 0;
1108 prepare_expected(expected_full, ctx.nexpected);
1109 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1110 check, &ctx, "tiresias.example.org", "192.168.0.1", ctx.flags), 0);
1111 TEST_DONE();
1112
1113 TEST_START("hostkeys_iterate match addr missing");
1114 memset(&ctx, 0, sizeof(ctx));
1115 ctx.expected = expected_full;
1116 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1117 ctx.flags = HKF_WANT_MATCH;
1118 prepare_expected(expected_full, ctx.nexpected);
1119 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1120 check, &ctx, "tiresias.example.org", "::1", ctx.flags), 0);
1121 TEST_DONE();
1122
1123 TEST_START("hostkeys_iterate specify host 2 and IPv4");
1124 memset(&ctx, 0, sizeof(ctx));
1125 ctx.expected = expected_full;
1126 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1127 ctx.flags = 0;
1128 ctx.match_host_s = 1;
1129 ctx.match_ipv4 = 1;
1130 prepare_expected(expected_full, ctx.nexpected);
1131 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1132 check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
1133 TEST_DONE();
1134
1135 TEST_START("hostkeys_iterate match host 1 and IPv6");
1136 memset(&ctx, 0, sizeof(ctx));
1137 ctx.expected = expected_full;
1138 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1139 ctx.flags = HKF_WANT_MATCH;
1140 ctx.match_host_p = 1;
1141 ctx.match_ipv6 = 1;
1142 prepare_expected(expected_full, ctx.nexpected);
1143 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1144 check, &ctx, "prometheus.example.com", "2001:db8::1", ctx.flags), 0);
1145 TEST_DONE();
1146
1147 TEST_START("hostkeys_iterate specify host 2 and IPv4 w/ key parse");
1148 memset(&ctx, 0, sizeof(ctx));
1149 ctx.expected = expected_full;
1150 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1151 ctx.flags = HKF_WANT_PARSE_KEY;
1152 ctx.match_host_s = 1;
1153 ctx.match_ipv4 = 1;
1154 prepare_expected(expected_full, ctx.nexpected);
1155 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1156 check, &ctx, "sisyphus.example.com", "192.0.2.1", ctx.flags), 0);
1157 TEST_DONE();
1158
1159 TEST_START("hostkeys_iterate match host 1 and IPv6 w/ key parse");
1160 memset(&ctx, 0, sizeof(ctx));
1161 ctx.expected = expected_full;
1162 ctx.nexpected = sizeof(expected_full)/sizeof(*expected_full);
1163 ctx.flags = HKF_WANT_MATCH|HKF_WANT_PARSE_KEY;
1164 ctx.match_host_p = 1;
1165 ctx.match_ipv6 = 1;
1166 prepare_expected(expected_full, ctx.nexpected);
1167 ASSERT_INT_EQ(hostkeys_foreach(test_data_file("known_hosts"),
1168 check, &ctx, "prometheus.example.com", "2001:db8::1", ctx.flags), 0);
1169 TEST_DONE();
1170}
1171
diff --git a/regress/unittests/hostkeys/testdata/dsa_1.pub b/regress/unittests/hostkeys/testdata/dsa_1.pub
new file mode 100644
index 000000000..56e1e3714
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/dsa_2.pub b/regress/unittests/hostkeys/testdata/dsa_2.pub
new file mode 100644
index 000000000..394e0bf00
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/dsa_3.pub b/regress/unittests/hostkeys/testdata/dsa_3.pub
new file mode 100644
index 000000000..e506ea422
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/dsa_4.pub b/regress/unittests/hostkeys/testdata/dsa_4.pub
new file mode 100644
index 000000000..8552c3819
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/dsa_5.pub b/regress/unittests/hostkeys/testdata/dsa_5.pub
new file mode 100644
index 000000000..149e1efd1
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/dsa_6.pub b/regress/unittests/hostkeys/testdata/dsa_6.pub
new file mode 100644
index 000000000..edbb97643
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/ecdsa_1.pub b/regress/unittests/hostkeys/testdata/ecdsa_1.pub
new file mode 100644
index 000000000..16a535bcc
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_1.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_2.pub b/regress/unittests/hostkeys/testdata/ecdsa_2.pub
new file mode 100644
index 000000000..d2bad11e2
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/ecdsa_3.pub b/regress/unittests/hostkeys/testdata/ecdsa_3.pub
new file mode 100644
index 000000000..e3ea9254e
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_3.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_4.pub b/regress/unittests/hostkeys/testdata/ecdsa_4.pub
new file mode 100644
index 000000000..2d616f5c6
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_4.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_5.pub b/regress/unittests/hostkeys/testdata/ecdsa_5.pub
new file mode 100644
index 000000000..a3df9b3f4
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_5.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5
diff --git a/regress/unittests/hostkeys/testdata/ecdsa_6.pub b/regress/unittests/hostkeys/testdata/ecdsa_6.pub
new file mode 100644
index 000000000..139f5a7bf
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ecdsa_6.pub
@@ -0,0 +1 @@
ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
diff --git a/regress/unittests/hostkeys/testdata/ed25519_1.pub b/regress/unittests/hostkeys/testdata/ed25519_1.pub
new file mode 100644
index 000000000..0b12efedb
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_1.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1
diff --git a/regress/unittests/hostkeys/testdata/ed25519_2.pub b/regress/unittests/hostkeys/testdata/ed25519_2.pub
new file mode 100644
index 000000000..78e262bcc
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_2.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2
diff --git a/regress/unittests/hostkeys/testdata/ed25519_3.pub b/regress/unittests/hostkeys/testdata/ed25519_3.pub
new file mode 100644
index 000000000..64e5f12a6
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_3.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3
diff --git a/regress/unittests/hostkeys/testdata/ed25519_4.pub b/regress/unittests/hostkeys/testdata/ed25519_4.pub
new file mode 100644
index 000000000..47b6724ec
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_4.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4
diff --git a/regress/unittests/hostkeys/testdata/ed25519_5.pub b/regress/unittests/hostkeys/testdata/ed25519_5.pub
new file mode 100644
index 000000000..72ccae6fe
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_5.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5
diff --git a/regress/unittests/hostkeys/testdata/ed25519_6.pub b/regress/unittests/hostkeys/testdata/ed25519_6.pub
new file mode 100644
index 000000000..0f719731d
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/ed25519_6.pub
@@ -0,0 +1 @@
ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
diff --git a/regress/unittests/hostkeys/testdata/known_hosts b/regress/unittests/hostkeys/testdata/known_hosts
new file mode 100644
index 000000000..3740f674b
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/known_hosts
@@ -0,0 +1,61 @@
1# Plain host keys, plain host names
2sisyphus.example.com ssh-dss AAAAB3NzaC1kc3MAAACBAOqffHxEW4c+Z9q/r3l4sYK8F7qrBsU8XF9upGsW62T9InROFFq9IO0x3pQ6mDA0Wtw0sqcDmkPCHPyP4Ok/fU3/drLaZusHoVYu8pBBrWsIDrKgkeX9TEodBsSrYdl4Sqtqq9EZv9+DttV6LStZrgYyUTOKwOF95wGantpLynX5AAAAFQDdt+zjRNlETDsgmxcSYFgREirJrQAAAIBQlrPaiPhR24FhnMLcHH4016vL7AqDDID6Qw7PhbXGa4/XlxWMIigjBKrIPKvnZ6p712LSnCKtcbfdx0MtmJlNa01CYqPaRhgRaf+uGdvTkTUcdaq8R5lLJL+JMNwUhcC8ijm3NqEjXjffuebGe1EzIeiITbA7Nndcd+GytwRDegAAAIEAkRYPjSVcUxfUHhHdpP6V8CuY1+CYSs9EPJ7iiWTDuXWVIBTU32oJLAnrmAcOwtIzEfPvm+rff5FI/Yhon2pB3VTXhPPEBjYzE5qANanAT4e6tzAVc5f3DUhHaDknwRYfDz86GFvuLtDjeE/UZ9t6OofYoEsCBpYozLAprBvNIQY= DSA #1
3sisyphus.example.com ecdsa-sha2-nistp384 AAAAE2VjZHNhLXNoYTItbmlzdHAzODQAAAAIbmlzdHAzODQAAABhBF6yQEtD9yBw9gmDRf477WBBzvWhAa0ioBI3nbA4emKykj0RbuQd5C4XdQAEOZGzE7v//FcCjwB2wi+JH5eKkxCtN6CjohDASZ1huoIV2UVyYIicZJEEOg1IWjjphvaxtw== ECDSA #1
4sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIK9ks7jkua5YWIwByRnnnc6UPJQWI75O0e/UJdPYU1JI ED25519 #1
5sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
6sisyphus.example.com ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDg4hB4vAZHJ0PVRiJajOv/GlytFWNpv5/9xgB9+5BIbvp8LOrFZ5D9K0Gsmwpd4G4rfaAz8j896DhMArg0vtkilIPPGt/6VzWMERgvaIQPJ/IE99X3+fjcAG56oAWwy29JX10lQMzBPU6XJIaN/zqpkb6qUBiAHBdLpxrFBBU0/w== RSA #1
7
8# Plain host keys, hostnames + addresses
9prometheus.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
10prometheus.example.com,192.0.2.1,2001:db8::1 ecdsa-sha2-nistp521 AAAAE2VjZHNhLXNoYTItbmlzdHA1MjEAAAAIbmlzdHA1MjEAAACFBAB8qVcXwgBM92NCmReQlPrZAoui4Bz/mW0VUBFOpHXXW1n+15b/Y7Pc6UBd/ITTZmaBciXY+PWaSBGdwc5GdqGdLgFyJ/QAGrFMPNpVutm/82gNQzlxpNwjbMcKyiZEXzSgnjS6DzMQ0WuSMdzIBXq8OW/Kafxg4ZkU6YqALUXxlQMZuQ== ECDSA #2
11prometheus.example.com,192.0.2.1,2001:db8::1 ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIIBp6PVW0z2o9C4Ukv/JOgmK7QMFe1pD1s3ADFF7IQob ED25519 #2
12prometheus.example.com,192.0.2.1,2001:db8::1 1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2
13prometheus.example.com,192.0.2.1,2001:db8::1 ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDmbUhNabB5AmBDX6GNHZ3lbn7pRxqfpW+f53QqNGlK0sLV+0gkMIrOfUp1kdE2ZLE6tfzdicatj/RlH6/wuo4yyYb+Pyx3G0vxdmAIiA4aANq38XweDucBC0TZkRWVHK+Gs5V/uV0z7N0axJvkkJujMLvST3CRiiWwlficBc6yVQ== RSA #2
14
15# Some hosts with wildcard names / IPs
16*.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
17*.example.com,192.0.2.*,2001:* ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBIb3BhJZk+vUQPg5TQc1koIzuGqloCq7wjr9LjlhG24IBeiFHLsdWw74HDlH4DrOmlxToVYk2lTdnjARleRByjk= ECDSA #3
18*.example.com,192.0.2.*,2001:* ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIBlYfExtYZAPqYvYdrlpGlSWhh/XNHcH3v3c2JzsVNbB ED25519 #3
19*.example.com,192.0.2.*,2001:* 1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3
20*.example.com,192.0.2.*,2001:* ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3
21
22# Hashed hostname and address entries
23|1|6FWxoqTCAfm8sZ7T/q73OmxCFGM=|S4eQmusok4cbyDzzGEFGIAthDbw= ssh-dss AAAAB3NzaC1kc3MAAACBALrFy7w5ihlaOG+qR+6fj+vm5EQaO3qwxgACLcgH+VfShuOG4mkx8qFJmf+OZ3fh5iKngjNZfKtfcqI7zHWdk6378TQfQC52/kbZukjNXOLCpyNkogahcjA00onIoTK1RUDuMW28edAHwPFbpttXDTaqis+8JPMY8hZwsZGENCzTAAAAFQD6+It5vozwGgaN9ROYPMlByhi6jwAAAIBz2mcAC694vNzz9b6614gkX9d9E99PzJYfU1MPkXDziKg7MrjBw7Opd5y1jL09S3iL6lSTlHkKwVKvQ3pOwWRwXXRrKVus4I0STveoApm526jmp6mY0YEtqR98vMJ0v97h1ydt8FikKlihefCsnXVicb8887PXs2Y8C6GuFT3tfQAAAIBbmHtV5tPcrMRDkULhaQ/Whap2VKvT2DUhIHA7lx6oy/KpkltOpxDZOIGUHKqffGbiR7Jh01/y090AY5L2eCf0S2Ytx93+eADwVVpJbFJo6zSwfeey2Gm6L2oA+rCz9zTdmtZoekpD3/RAOQjnJIAPwbs7mXwabZTw4xRtiYIRrw== DSA #5
24|1|hTrfD0CuuB9ZbOa1CHFYvIk/gKE=|tPmW50t7flncm1UyM+DR97ubDNU= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBPIudcagzq4QPtP1jkpje34+0POLB0jwT64hqrbCqhTH2T800KDZ0h2vwlJYa3OP3Oqru9AB5pnuHsKw7mAhUGY= ECDSA #5
25|1|fOGqe75X5ZpTz4c7DitP4E8/y30=|Lmcch2fh54bUYoV//S2VqDFVeiY= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAINf63qSV8rD57N+digID8t28WVhd3Yf2K2UhaoG8TsWQ ED25519 #5
26|1|0RVzLjY3lwE3MRweguaAXaCCWk8=|DbcIgJQcRZJMYI6NYDOM6oJycPk= 1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5
27|1|4q79XnHpKBNQhyMLAqbPPDN+JKo=|k1Wvjjb52zDdrXWM801+wX5oH8U= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5
28
29|1|0M6PIx6THA3ipIOvTl3fcgn2z+A=|bwEJAOwJz+Sm7orFdgj170mD/zY= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
30|1|a6WGHcL+9gX3e96tMlgDSDJwtSg=|5Dqlb/yqNEf7jgfllrp/ygLmRV8= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
31|1|OeCpi7Pn5Q6c8la4fPf9G8YctT8=|sC6D7lDXTafIpokZJ1+1xWg2R6Q= ssh-dss AAAAB3NzaC1kc3MAAACBAIutigAse65TCW6hHDOEGXenE9L4L0talHbs65hj3UUNtWflKdQeXLofqXgW8AwaDKmnuRPrxRoxVNXj84n45wtBEdt4ztmdAZteAbXSnHqpcxME3jDxh3EtxzGPXLs+RUmKPVguraSgo7W2oN7KFx6VM+AcAtxANSTlvDid3s47AAAAFQCd9Q3kkHSLWe77sW0eRaayI45ovwAAAIAw6srGF6xvFasI44Y3r9JJ2K+3ezozl3ldL3p2+p2HG3iWafC4SdV8pB6ZIxKlYAywiiFb3LzH/JweGFq1jtoFDRM3MlYORBevydU4zPz7b5QLDVB0sY4evYtWmg2BFJvoWRfhLnlZVW7h5N8v4fNIwdVmVsw4Ljes7iF2HRGhHgAAAIBDFT3fww2Oby1xUA6G9pDAcVikrQFqp1sJRylNTUyeyQ37SNAGzYxwHJFgQr8gZLdRQ1UW+idYpqVbVNcYFMOiw/zSqK2OfVwPZ9U+TTKdc992ChSup6vJEKM/ZVIyDWDbJr7igQ4ahy7jo9mFvm8ljN926EnspQzCvs0Dxk6tHA== DSA #6
32|1|BHESVyiJ7G2NN0lxrw7vT109jmk=|TKof+015J77bXqibsh0N1Lp0MKk= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
33|1|wY53mZNASDJ5/P3JYCJ4FUNa6WQ=|v8p0MfV5lqlZB2J0yLxl/gsWVQo= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
34|1|horeoyFPwfKhyFN+zJZ5LCfOo/I=|2ofvp0tNwCbKsV8FuiFA4gQG2Z8= ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBK1wRLyKtvK3Mmhd0XPkKwW4ev1KBVf8J4aG8lESq1TsaqqfOXYGyxMq5pN8fCGiD5UPOqyTYz/ZNzClRhJRHao= ECDSA #6
35|1|Aw4fXumZfx6jEIJuDGIyeEMd81A=|5FdLtdm2JeKNsS8IQeQlGYIadOE= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
36|1|+dGUNpv6GblrDd5fgHLlOWpSbEo=|He/pQ1yJjtiCyTNWpGwjBD4sZFI= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
37|1|E/PACGl8m1T7QnPedOoooozstP0=|w6DQAFT8yZgj0Hlkz5R1TppYHCA= ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIPLW0ZwCkRQldpLa4I5BpwGa/om+WE6OgC8jdVqakt0Z ED25519 #6
38|1|SaoyMStgxpYfwedSXBAghi8Zo0s=|Gz78k69GaE6iViV3OOvbStKqyTA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
39|1|8qfGeiT5WTCzWYbXPQ+lsLg7km4=|1sIBwiSUr8IGkvrUGm3/9QYurmA= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
40|1|87M1OtyHg1BZiDY3rT6lYsZFnAU=|eddAQVcMNbn2OB87XWXFQnYo6R4= 1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
41|1|60w3wFfC0XWI+rRmRlxIRhh8lwE=|yMhsGrzBJKiesAdSQ/PVgkCrDKk= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
42|1|5gdEMmLUJC7grqWhRJPy2OTaSyE=|/XTfmLMa/B8npcVCGFRdaHl+d/0= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
43|1|6FGCWUr42GHdMB/eifnHNCuwgdk=|ONJvYZ/ANmi59R5HrOhLPmvYENM= ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
44
45
46# Revoked and CA keys
47@revoked sisyphus.example.com 1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4
48@revoked sisyphus.example.com ssh-ed25519 AAAAC3NzaC1lZDI1NTE5AAAAIDFP8L9REfN/iYy1KIRtFqSCn3V2+vOCpoZYENFGLdOF ED25519 #4
49@cert-authority prometheus.example.com ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAABBBHZd0OXHIWwK3xnjAdMZ1tojxWycdu38pORO/UX5cqsKMgGCKQVBWWO3TFk1ePkGIE9VMWT1hCGqWRRwYlH+dSE= ECDSA #4
50@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
51
52# Some invalid lines
53@what sisyphus.example.com 1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
54sisyphus.example.com
55prometheus.example.com ssh-ed25519
56sisyphus.example.com ssh-dsa AAAATgAAAAdz
57prometheus.example.com 1024
58sisyphus.example.com 1024 65535
59prometheus.example.com 1025 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
60sisyphus.example.com ssh-XXX AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==
61prometheus.example.com ssh-rsa AAAATgAAAAdzc2gtWFhYAAAAP0ZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRkZVQ0tPRkZGVUNLT0ZGRlVDS09GRg==
diff --git a/regress/unittests/hostkeys/testdata/rsa1_1.pub b/regress/unittests/hostkeys/testdata/rsa1_1.pub
new file mode 100644
index 000000000..772ce9c05
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_1.pub
@@ -0,0 +1 @@
1024 65537 153895431603677073925890314548566704948446776958334195280085080329934839226701954473292358821568047724356487621573742372399387931887004184139835510820577359977148363519970774657801798872789118894962853659233045778161859413980935372685480527355016624825696983269800574755126132814333241868538220824608980319407 RSA1 #1
diff --git a/regress/unittests/hostkeys/testdata/rsa1_2.pub b/regress/unittests/hostkeys/testdata/rsa1_2.pub
new file mode 100644
index 000000000..78794b941
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_2.pub
@@ -0,0 +1 @@
1024 65537 135970715082947442639683969597180728933388298633245835186618852623800675939308729462220235058285909679252157995530180587329132927339620517781785310829060832352381015614725360278571924286986474946772141568893116432268565829418506866604294073334978275702221949783314402806080929601995102334442541344606109853641 RSA1 #2
diff --git a/regress/unittests/hostkeys/testdata/rsa1_3.pub b/regress/unittests/hostkeys/testdata/rsa1_3.pub
new file mode 100644
index 000000000..0c035fe0a
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_3.pub
@@ -0,0 +1 @@
1024 65537 125895605498029643697051635076028105429632810811904702876152645261610759866299221305725069141163240694267669117205342283569102183636228981857946763978553664895308762890072813014496700601576921921752482059207749978374872713540759920335553799711267170948655579130584031555334229966603000896364091459595522912269 RSA1 #3
diff --git a/regress/unittests/hostkeys/testdata/rsa1_4.pub b/regress/unittests/hostkeys/testdata/rsa1_4.pub
new file mode 100644
index 000000000..00064423e
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_4.pub
@@ -0,0 +1 @@
1024 65537 174143366122697048196335388217056770310345753698079464367148030836533360510864881734142526411160017107552815906024399248049666856133771656680462456979369587903909343046704480897527203474513676654933090991684252819423129896444427656841613263783484827101210734799449281639493127615902427443211183258155381810593 RSA1 #4
diff --git a/regress/unittests/hostkeys/testdata/rsa1_5.pub b/regress/unittests/hostkeys/testdata/rsa1_5.pub
new file mode 100644
index 000000000..bb53c2642
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_5.pub
@@ -0,0 +1 @@
1024 65537 127931411493401587586867047972295564331543694182352197506125410692673654572057908999642645524647232712160516076508316152810117209181150078352725299319149726341058893406440426414316276977768958023952319602422835879783057966985348561111880658922724668687074412548487722084792283453716871417610020757212399252171 RSA1 #5
diff --git a/regress/unittests/hostkeys/testdata/rsa1_6.pub b/regress/unittests/hostkeys/testdata/rsa1_6.pub
new file mode 100644
index 000000000..85d6576b5
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa1_6.pub
@@ -0,0 +1 @@
1024 65537 140883028436203600354693376066567741282115117509696517282419557936340193768851493584179972504103033755515036493433917203732876685813283050574208967197963391667532902202382549275760997891673884333346000558018002659506756213191532156293935482587878596032743105911487673274674568768638010598205190227631909167257 RSA1 #6
diff --git a/regress/unittests/hostkeys/testdata/rsa_1.pub b/regress/unittests/hostkeys/testdata/rsa_1.pub
new file mode 100644
index 000000000..2b87885a1
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/rsa_2.pub b/regress/unittests/hostkeys/testdata/rsa_2.pub
new file mode 100644
index 000000000..33f1fd93b
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/rsa_3.pub b/regress/unittests/hostkeys/testdata/rsa_3.pub
new file mode 100644
index 000000000..c2f6b208c
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_3.pub
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQDX8F93W3SH4ZSus4XUQ2cw9dqcuyUETTlKEeGv3zlknV3YCoe2Mp04naDhiuwj8sOsytrZSESzLY1ZEyzrjxE6ZFVv8NKgck/AbRjcwlRFOcx9oKUxOrXRa0IoXlTq0kyjKCJfaHBKnGitZThknCPTbVmpATkm5xx6J0WEDozfoQ== RSA #3
diff --git a/regress/unittests/hostkeys/testdata/rsa_4.pub b/regress/unittests/hostkeys/testdata/rsa_4.pub
new file mode 100644
index 000000000..35545a713
--- /dev/null
+++ b/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/regress/unittests/hostkeys/testdata/rsa_5.pub b/regress/unittests/hostkeys/testdata/rsa_5.pub
new file mode 100644
index 000000000..befbaa7d9
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_5.pub
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQC/C15Q4sfnk7BZff1er8bscay+5s51oD4eWArlHWMK/ZfYeeTAccTy+7B7Jv+MS4nKCpflrvJI2RQz4kS8vF0ATdBbi4jeWefStlHNg0HLhnCY7NAfDIlRdaN9lm3Pqm2vmr+CkqwcJaSpycDg8nPN9yNAuD6pv7NDuUnECezojQ== RSA #5
diff --git a/regress/unittests/hostkeys/testdata/rsa_6.pub b/regress/unittests/hostkeys/testdata/rsa_6.pub
new file mode 100644
index 000000000..393e11672
--- /dev/null
+++ b/regress/unittests/hostkeys/testdata/rsa_6.pub
@@ -0,0 +1 @@
ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAAAgQClu/3I6GG1Ai89Imnw0vXmWJ2OW0ftQwRrsbIAD0qzLFYpkJ76QWnzpCehvK9u0L5hcw7z2Y6mRLcSBsqONc+HVU73Qi7M4zHRvtjprPs3SOyLpf0J9sL1WiHBDwg2P0miHMCdqHDd5nVXkJB2d4eeecmgezGLa29NOHZjbza5yw== RSA #6
diff --git a/regress/unittests/hostkeys/tests.c b/regress/unittests/hostkeys/tests.c
new file mode 100644
index 000000000..92c7646ad
--- /dev/null
+++ b/regress/unittests/hostkeys/tests.c
@@ -0,0 +1,16 @@
1/* $OpenBSD: tests.c,v 1.1 2015/02/16 22:18:34 djm Exp $ */
2/*
3 * Regress test for known_hosts-related API.
4 *
5 * Placed in the public domain
6 */
7
8void tests(void);
9void test_iterate(void); /* test_iterate.c */
10
11void
12tests(void)
13{
14 test_iterate();
15}
16
diff --git a/regress/unittests/kex/Makefile b/regress/unittests/kex/Makefile
new file mode 100644
index 000000000..6532cb00a
--- /dev/null
+++ b/regress/unittests/kex/Makefile
@@ -0,0 +1,14 @@
1# $OpenBSD: Makefile,v 1.2 2015/01/24 10:39:21 miod Exp $
2
3TEST_ENV= "MALLOC_OPTIONS=AFGJPRX"
4
5PROG=test_kex
6SRCS=tests.c test_kex.c
7REGRESS_TARGETS=run-regress-${PROG}
8
9run-regress-${PROG}: ${PROG}
10 env ${TEST_ENV} ./${PROG}
11
12.include <bsd.regress.mk>
13
14LDADD+=-lz
diff --git a/regress/unittests/kex/test_kex.c b/regress/unittests/kex/test_kex.c
new file mode 100644
index 000000000..c61e2bdbb
--- /dev/null
+++ b/regress/unittests/kex/test_kex.c
@@ -0,0 +1,197 @@
1/* $OpenBSD: test_kex.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */
2/*
3 * Regress test KEX
4 *
5 * Placed in the public domain
6 */
7
8#include "includes.h"
9
10#include <sys/types.h>
11#include <sys/param.h>
12#include <stdio.h>
13#ifdef HAVE_STDINT_H
14#include <stdint.h>
15#endif
16#include <stdlib.h>
17#include <string.h>
18
19#include "../test_helper/test_helper.h"
20
21#include "ssherr.h"
22#include "ssh_api.h"
23#include "sshbuf.h"
24#include "packet.h"
25#include "myproposal.h"
26
27struct ssh *active_state = NULL; /* XXX - needed for linking */
28
29void kex_tests(void);
30static int do_debug = 0;
31
32static int
33do_send_and_receive(struct ssh *from, struct ssh *to)
34{
35 u_char type;
36 size_t len;
37 const u_char *buf;
38 int r;
39
40 for (;;) {
41 if ((r = ssh_packet_next(from, &type)) != 0) {
42 fprintf(stderr, "ssh_packet_next: %s\n", ssh_err(r));
43 return r;
44 }
45 if (type != 0)
46 return 0;
47 buf = ssh_output_ptr(from, &len);
48 if (do_debug)
49 printf("%zu", len);
50 if (len == 0)
51 return 0;
52 if ((r = ssh_output_consume(from, len)) != 0 ||
53 (r = ssh_input_append(to, buf, len)) != 0)
54 return r;
55 }
56}
57
58static void
59run_kex(struct ssh *client, struct ssh *server)
60{
61 int r = 0;
62
63 while (!server->kex->done || !client->kex->done) {
64 if (do_debug)
65 printf(" S:");
66 if ((r = do_send_and_receive(server, client)))
67 break;
68 if (do_debug)
69 printf(" C:");
70 if ((r = do_send_and_receive(client, server)))
71 break;
72 }
73 if (do_debug)
74 printf("done: %s\n", ssh_err(r));
75 ASSERT_INT_EQ(r, 0);
76 ASSERT_INT_EQ(server->kex->done, 1);
77 ASSERT_INT_EQ(client->kex->done, 1);
78}
79
80static void
81do_kex_with_key(char *kex, int keytype, int bits)
82{
83 struct ssh *client = NULL, *server = NULL, *server2 = NULL;
84 struct sshkey *private, *public;
85 struct sshbuf *state;
86 struct kex_params kex_params;
87 char *myproposal[PROPOSAL_MAX] = { KEX_CLIENT };
88
89 TEST_START("sshkey_generate");
90 ASSERT_INT_EQ(sshkey_generate(keytype, bits, &private), 0);
91 TEST_DONE();
92
93 TEST_START("sshkey_from_private");
94 ASSERT_INT_EQ(sshkey_from_private(private, &public), 0);
95 TEST_DONE();
96
97 TEST_START("ssh_init");
98 memcpy(kex_params.proposal, myproposal, sizeof(myproposal));
99 if (kex != NULL)
100 kex_params.proposal[PROPOSAL_KEX_ALGS] = kex;
101 ASSERT_INT_EQ(ssh_init(&client, 0, &kex_params), 0);
102 ASSERT_INT_EQ(ssh_init(&server, 1, &kex_params), 0);
103 ASSERT_PTR_NE(client, NULL);
104 ASSERT_PTR_NE(server, NULL);
105 TEST_DONE();
106
107 TEST_START("ssh_add_hostkey");
108 ASSERT_INT_EQ(ssh_add_hostkey(server, private), 0);
109 ASSERT_INT_EQ(ssh_add_hostkey(client, public), 0);
110 TEST_DONE();
111
112 TEST_START("kex");
113 run_kex(client, server);
114 TEST_DONE();
115
116 TEST_START("rekeying client");
117 ASSERT_INT_EQ(kex_send_kexinit(client), 0);
118 run_kex(client, server);
119 TEST_DONE();
120
121 TEST_START("rekeying server");
122 ASSERT_INT_EQ(kex_send_kexinit(server), 0);
123 run_kex(client, server);
124 TEST_DONE();
125
126 TEST_START("ssh_packet_get_state");
127 state = sshbuf_new();
128 ASSERT_PTR_NE(state, NULL);
129 ASSERT_INT_EQ(ssh_packet_get_state(server, state), 0);
130 ASSERT_INT_GE(sshbuf_len(state), 1);
131 TEST_DONE();
132
133 TEST_START("ssh_packet_set_state");
134 server2 = NULL;
135 ASSERT_INT_EQ(ssh_init(&server2, 1, NULL), 0);
136 ASSERT_PTR_NE(server2, NULL);
137 ASSERT_INT_EQ(ssh_add_hostkey(server2, private), 0);
138 kex_free(server2->kex); /* XXX or should ssh_packet_set_state()? */
139 ASSERT_INT_EQ(ssh_packet_set_state(server2, state), 0);
140 ASSERT_INT_EQ(sshbuf_len(state), 0);
141 sshbuf_free(state);
142 ASSERT_PTR_NE(server2->kex, NULL);
143 /* XXX we need to set the callbacks */
144 server2->kex->kex[KEX_DH_GRP1_SHA1] = kexdh_server;
145 server2->kex->kex[KEX_DH_GRP14_SHA1] = kexdh_server;
146 server2->kex->kex[KEX_DH_GEX_SHA1] = kexgex_server;
147 server2->kex->kex[KEX_DH_GEX_SHA256] = kexgex_server;
148#ifdef OPENSSL_HAS_ECC
149 server2->kex->kex[KEX_ECDH_SHA2] = kexecdh_server;
150#endif
151 server2->kex->kex[KEX_C25519_SHA256] = kexc25519_server;
152 server2->kex->load_host_public_key = server->kex->load_host_public_key;
153 server2->kex->load_host_private_key = server->kex->load_host_private_key;
154 server2->kex->sign = server->kex->sign;
155 TEST_DONE();
156
157 TEST_START("rekeying server2");
158 ASSERT_INT_EQ(kex_send_kexinit(server2), 0);
159 run_kex(client, server2);
160 ASSERT_INT_EQ(kex_send_kexinit(client), 0);
161 run_kex(client, server2);
162 TEST_DONE();
163
164 TEST_START("cleanup");
165 sshkey_free(private);
166 sshkey_free(public);
167 ssh_free(client);
168 ssh_free(server);
169 ssh_free(server2);
170 TEST_DONE();
171}
172
173static void
174do_kex(char *kex)
175{
176 do_kex_with_key(kex, KEY_RSA, 2048);
177 do_kex_with_key(kex, KEY_DSA, 1024);
178#ifdef OPENSSL_HAS_ECC
179 do_kex_with_key(kex, KEY_ECDSA, 256);
180#endif
181 do_kex_with_key(kex, KEY_ED25519, 256);
182}
183
184void
185kex_tests(void)
186{
187 do_kex("curve25519-sha256@libssh.org");
188#ifdef OPENSSL_HAS_ECC
189 do_kex("ecdh-sha2-nistp256");
190 do_kex("ecdh-sha2-nistp384");
191 do_kex("ecdh-sha2-nistp521");
192#endif
193 do_kex("diffie-hellman-group-exchange-sha256");
194 do_kex("diffie-hellman-group-exchange-sha1");
195 do_kex("diffie-hellman-group14-sha1");
196 do_kex("diffie-hellman-group1-sha1");
197}
diff --git a/regress/unittests/kex/tests.c b/regress/unittests/kex/tests.c
new file mode 100644
index 000000000..e7036ec17
--- /dev/null
+++ b/regress/unittests/kex/tests.c
@@ -0,0 +1,14 @@
1/* $OpenBSD: tests.c,v 1.1 2015/01/15 23:41:29 markus Exp $ */
2/*
3 * Placed in the public domain
4 */
5
6#include "../test_helper/test_helper.h"
7
8void kex_tests(void);
9
10void
11tests(void)
12{
13 kex_tests();
14}
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
index 0c4c71ecd..a68e1329e 100644
--- a/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_crypto.c
@@ -32,8 +32,6 @@ void
32sshbuf_getput_crypto_tests(void) 32sshbuf_getput_crypto_tests(void)
33{ 33{
34 struct sshbuf *p1; 34 struct sshbuf *p1;
35 const u_char *d;
36 size_t s;
37 BIGNUM *bn, *bn2; 35 BIGNUM *bn, *bn2;
38 /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */ 36 /* This one has num_bits != num_bytes * 8 to test bignum1 encoding */
39 const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10"; 37 const char *hexbn1 = "0102030405060708090a0b0c0d0e0f10";
@@ -48,7 +46,9 @@ sshbuf_getput_crypto_tests(void)
48 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00, 46 0x70, 0x60, 0x50, 0x40, 0x30, 0x20, 0x10, 0x00,
49 0x7f, 0xff, 0x11 47 0x7f, 0xff, 0x11
50 }; 48 };
51#ifdef OPENSSL_HAS_NISTP256 49#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
50 const u_char *d;
51 size_t s;
52 BIGNUM *bn_x, *bn_y; 52 BIGNUM *bn_x, *bn_y;
53 int ec256_nid = NID_X9_62_prime256v1; 53 int ec256_nid = NID_X9_62_prime256v1;
54 char *ec256_x = "0C828004839D0106AA59575216191357" 54 char *ec256_x = "0C828004839D0106AA59575216191357"
@@ -352,7 +352,7 @@ sshbuf_getput_crypto_tests(void)
352 sshbuf_free(p1); 352 sshbuf_free(p1);
353 TEST_DONE(); 353 TEST_DONE();
354 354
355#ifdef OPENSSL_HAS_NISTP256 355#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
356 TEST_START("sshbuf_put_ec"); 356 TEST_START("sshbuf_put_ec");
357 eck = EC_KEY_new_by_curve_name(ec256_nid); 357 eck = EC_KEY_new_by_curve_name(ec256_nid);
358 ASSERT_PTR_NE(eck, NULL); 358 ASSERT_PTR_NE(eck, NULL);
diff --git a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
index 8c3269b13..c6b5c29d1 100644
--- a/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
+++ b/regress/unittests/sshbuf/test_sshbuf_getput_fuzz.c
@@ -33,7 +33,7 @@ attempt_parse_blob(u_char *blob, size_t len)
33{ 33{
34 struct sshbuf *p1; 34 struct sshbuf *p1;
35 BIGNUM *bn; 35 BIGNUM *bn;
36#ifdef OPENSSL_HAS_NISTP256 36#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
37 EC_KEY *eck; 37 EC_KEY *eck;
38#endif 38#endif
39 u_char *s; 39 u_char *s;
@@ -60,7 +60,7 @@ attempt_parse_blob(u_char *blob, size_t len)
60 bn = BN_new(); 60 bn = BN_new();
61 sshbuf_get_bignum2(p1, bn); 61 sshbuf_get_bignum2(p1, bn);
62 BN_clear_free(bn); 62 BN_clear_free(bn);
63#ifdef OPENSSL_HAS_NISTP256 63#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
64 eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1); 64 eck = EC_KEY_new_by_curve_name(NID_X9_62_prime256v1);
65 ASSERT_PTR_NE(eck, NULL); 65 ASSERT_PTR_NE(eck, NULL);
66 sshbuf_get_eckey(p1, eck); 66 sshbuf_get_eckey(p1, eck);
diff --git a/regress/unittests/sshkey/common.c b/regress/unittests/sshkey/common.c
index 0a4b3a90c..b598f05cb 100644
--- a/regress/unittests/sshkey/common.c
+++ b/regress/unittests/sshkey/common.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: common.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ 1/* $OpenBSD: common.c,v 1.2 2015/01/08 13:10:58 djm Exp $ */
2/* 2/*
3 * Helpers for key API tests 3 * Helpers for key API tests
4 * 4 *
@@ -44,7 +44,7 @@ load_file(const char *name)
44 44
45 ASSERT_PTR_NE(ret = sshbuf_new(), NULL); 45 ASSERT_PTR_NE(ret = sshbuf_new(), NULL);
46 ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1); 46 ASSERT_INT_NE(fd = open(test_data_file(name), O_RDONLY), -1);
47 ASSERT_INT_EQ(sshkey_load_file(fd, name, ret), 0); 47 ASSERT_INT_EQ(sshkey_load_file(fd, ret), 0);
48 close(fd); 48 close(fd);
49 return ret; 49 return ret;
50} 50}
diff --git a/regress/unittests/sshkey/mktestdata.sh b/regress/unittests/sshkey/mktestdata.sh
index ee1fe3962..09165af02 100755
--- a/regress/unittests/sshkey/mktestdata.sh
+++ b/regress/unittests/sshkey/mktestdata.sh
@@ -1,5 +1,5 @@
1#!/bin/sh 1#!/bin/sh
2# $OpenBSD: mktestdata.sh,v 1.3 2014/07/22 23:57:40 dtucker Exp $ 2# $OpenBSD: mktestdata.sh,v 1.4 2015/01/18 19:54:46 djm Exp $
3 3
4PW=mekmitasdigoat 4PW=mekmitasdigoat
5 5
@@ -187,4 +187,6 @@ ssh-keygen -Bf dsa_2 | awk '{print $2}' > dsa_2.fp.bb
187ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb 187ssh-keygen -Bf ecdsa_2 | awk '{print $2}' > ecdsa_2.fp.bb
188ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb 188ssh-keygen -Bf ed25519_2 | awk '{print $2}' > ed25519_2.fp.bb
189 189
190# XXX Extend ssh-keygen to do detached signatures (better to test/fuzz against)
191
190echo "$PW" > pw 192echo "$PW" > pw
diff --git a/regress/unittests/sshkey/test_file.c b/regress/unittests/sshkey/test_file.c
index 764f7fb76..fa95212bf 100644
--- a/regress/unittests/sshkey/test_file.c
+++ b/regress/unittests/sshkey/test_file.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: test_file.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ 1/* $OpenBSD: test_file.c,v 1.3 2015/03/04 23:22:35 djm Exp $ */
2/* 2/*
3 * Regress test for sshkey.h key management API 3 * Regress test for sshkey.h key management API
4 * 4 *
@@ -33,6 +33,7 @@
33#include "authfile.h" 33#include "authfile.h"
34#include "sshkey.h" 34#include "sshkey.h"
35#include "sshbuf.h" 35#include "sshbuf.h"
36#include "digest.h"
36 37
37#include "common.h" 38#include "common.h"
38 39
@@ -50,6 +51,7 @@ sshkey_file_tests(void)
50 pw = load_text_file("pw"); 51 pw = load_text_file("pw");
51 TEST_DONE(); 52 TEST_DONE();
52 53
54#ifdef WITH_SSH1
53 TEST_START("parse RSA1 from private"); 55 TEST_START("parse RSA1 from private");
54 buf = load_file("rsa1_1"); 56 buf = load_file("rsa1_1");
55 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa1_1", 57 ASSERT_INT_EQ(sshkey_parse_private_fileblob(buf, "", "rsa1_1",
@@ -81,7 +83,7 @@ sshkey_file_tests(void)
81 83
82 TEST_START("RSA1 key hex fingerprint"); 84 TEST_START("RSA1 key hex fingerprint");
83 buf = load_text_file("rsa1_1.fp"); 85 buf = load_text_file("rsa1_1.fp");
84 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); 86 cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
85 ASSERT_PTR_NE(cp, NULL); 87 ASSERT_PTR_NE(cp, NULL);
86 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 88 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
87 sshbuf_free(buf); 89 sshbuf_free(buf);
@@ -90,7 +92,7 @@ sshkey_file_tests(void)
90 92
91 TEST_START("RSA1 key bubblebabble fingerprint"); 93 TEST_START("RSA1 key bubblebabble fingerprint");
92 buf = load_text_file("rsa1_1.fp.bb"); 94 buf = load_text_file("rsa1_1.fp.bb");
93 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); 95 cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
94 ASSERT_PTR_NE(cp, NULL); 96 ASSERT_PTR_NE(cp, NULL);
95 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 97 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
96 sshbuf_free(buf); 98 sshbuf_free(buf);
@@ -98,6 +100,7 @@ sshkey_file_tests(void)
98 TEST_DONE(); 100 TEST_DONE();
99 101
100 sshkey_free(k1); 102 sshkey_free(k1);
103#endif
101 104
102 TEST_START("parse RSA from private"); 105 TEST_START("parse RSA from private");
103 buf = load_file("rsa_1"); 106 buf = load_file("rsa_1");
@@ -164,7 +167,7 @@ sshkey_file_tests(void)
164 167
165 TEST_START("RSA key hex fingerprint"); 168 TEST_START("RSA key hex fingerprint");
166 buf = load_text_file("rsa_1.fp"); 169 buf = load_text_file("rsa_1.fp");
167 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); 170 cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
168 ASSERT_PTR_NE(cp, NULL); 171 ASSERT_PTR_NE(cp, NULL);
169 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 172 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
170 sshbuf_free(buf); 173 sshbuf_free(buf);
@@ -173,7 +176,7 @@ sshkey_file_tests(void)
173 176
174 TEST_START("RSA cert hex fingerprint"); 177 TEST_START("RSA cert hex fingerprint");
175 buf = load_text_file("rsa_1-cert.fp"); 178 buf = load_text_file("rsa_1-cert.fp");
176 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); 179 cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
177 ASSERT_PTR_NE(cp, NULL); 180 ASSERT_PTR_NE(cp, NULL);
178 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 181 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
179 sshbuf_free(buf); 182 sshbuf_free(buf);
@@ -183,7 +186,7 @@ sshkey_file_tests(void)
183 186
184 TEST_START("RSA key bubblebabble fingerprint"); 187 TEST_START("RSA key bubblebabble fingerprint");
185 buf = load_text_file("rsa_1.fp.bb"); 188 buf = load_text_file("rsa_1.fp.bb");
186 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); 189 cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
187 ASSERT_PTR_NE(cp, NULL); 190 ASSERT_PTR_NE(cp, NULL);
188 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 191 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
189 sshbuf_free(buf); 192 sshbuf_free(buf);
@@ -257,7 +260,7 @@ sshkey_file_tests(void)
257 260
258 TEST_START("DSA key hex fingerprint"); 261 TEST_START("DSA key hex fingerprint");
259 buf = load_text_file("dsa_1.fp"); 262 buf = load_text_file("dsa_1.fp");
260 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); 263 cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
261 ASSERT_PTR_NE(cp, NULL); 264 ASSERT_PTR_NE(cp, NULL);
262 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 265 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
263 sshbuf_free(buf); 266 sshbuf_free(buf);
@@ -266,7 +269,7 @@ sshkey_file_tests(void)
266 269
267 TEST_START("DSA cert hex fingerprint"); 270 TEST_START("DSA cert hex fingerprint");
268 buf = load_text_file("dsa_1-cert.fp"); 271 buf = load_text_file("dsa_1-cert.fp");
269 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); 272 cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
270 ASSERT_PTR_NE(cp, NULL); 273 ASSERT_PTR_NE(cp, NULL);
271 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 274 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
272 sshbuf_free(buf); 275 sshbuf_free(buf);
@@ -276,7 +279,7 @@ sshkey_file_tests(void)
276 279
277 TEST_START("DSA key bubblebabble fingerprint"); 280 TEST_START("DSA key bubblebabble fingerprint");
278 buf = load_text_file("dsa_1.fp.bb"); 281 buf = load_text_file("dsa_1.fp.bb");
279 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); 282 cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
280 ASSERT_PTR_NE(cp, NULL); 283 ASSERT_PTR_NE(cp, NULL);
281 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 284 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
282 sshbuf_free(buf); 285 sshbuf_free(buf);
@@ -357,7 +360,7 @@ sshkey_file_tests(void)
357 360
358 TEST_START("ECDSA key hex fingerprint"); 361 TEST_START("ECDSA key hex fingerprint");
359 buf = load_text_file("ecdsa_1.fp"); 362 buf = load_text_file("ecdsa_1.fp");
360 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); 363 cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
361 ASSERT_PTR_NE(cp, NULL); 364 ASSERT_PTR_NE(cp, NULL);
362 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 365 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
363 sshbuf_free(buf); 366 sshbuf_free(buf);
@@ -366,7 +369,7 @@ sshkey_file_tests(void)
366 369
367 TEST_START("ECDSA cert hex fingerprint"); 370 TEST_START("ECDSA cert hex fingerprint");
368 buf = load_text_file("ecdsa_1-cert.fp"); 371 buf = load_text_file("ecdsa_1-cert.fp");
369 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); 372 cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
370 ASSERT_PTR_NE(cp, NULL); 373 ASSERT_PTR_NE(cp, NULL);
371 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 374 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
372 sshbuf_free(buf); 375 sshbuf_free(buf);
@@ -376,7 +379,7 @@ sshkey_file_tests(void)
376 379
377 TEST_START("ECDSA key bubblebabble fingerprint"); 380 TEST_START("ECDSA key bubblebabble fingerprint");
378 buf = load_text_file("ecdsa_1.fp.bb"); 381 buf = load_text_file("ecdsa_1.fp.bb");
379 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); 382 cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
380 ASSERT_PTR_NE(cp, NULL); 383 ASSERT_PTR_NE(cp, NULL);
381 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 384 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
382 sshbuf_free(buf); 385 sshbuf_free(buf);
@@ -424,7 +427,7 @@ sshkey_file_tests(void)
424 427
425 TEST_START("Ed25519 key hex fingerprint"); 428 TEST_START("Ed25519 key hex fingerprint");
426 buf = load_text_file("ed25519_1.fp"); 429 buf = load_text_file("ed25519_1.fp");
427 cp = sshkey_fingerprint(k1, SSH_FP_MD5, SSH_FP_HEX); 430 cp = sshkey_fingerprint(k1, SSH_DIGEST_MD5, SSH_FP_HEX);
428 ASSERT_PTR_NE(cp, NULL); 431 ASSERT_PTR_NE(cp, NULL);
429 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 432 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
430 sshbuf_free(buf); 433 sshbuf_free(buf);
@@ -433,7 +436,7 @@ sshkey_file_tests(void)
433 436
434 TEST_START("Ed25519 cert hex fingerprint"); 437 TEST_START("Ed25519 cert hex fingerprint");
435 buf = load_text_file("ed25519_1-cert.fp"); 438 buf = load_text_file("ed25519_1-cert.fp");
436 cp = sshkey_fingerprint(k2, SSH_FP_MD5, SSH_FP_HEX); 439 cp = sshkey_fingerprint(k2, SSH_DIGEST_MD5, SSH_FP_HEX);
437 ASSERT_PTR_NE(cp, NULL); 440 ASSERT_PTR_NE(cp, NULL);
438 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 441 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
439 sshbuf_free(buf); 442 sshbuf_free(buf);
@@ -443,7 +446,7 @@ sshkey_file_tests(void)
443 446
444 TEST_START("Ed25519 key bubblebabble fingerprint"); 447 TEST_START("Ed25519 key bubblebabble fingerprint");
445 buf = load_text_file("ed25519_1.fp.bb"); 448 buf = load_text_file("ed25519_1.fp.bb");
446 cp = sshkey_fingerprint(k1, SSH_FP_SHA1, SSH_FP_BUBBLEBABBLE); 449 cp = sshkey_fingerprint(k1, SSH_DIGEST_SHA1, SSH_FP_BUBBLEBABBLE);
447 ASSERT_PTR_NE(cp, NULL); 450 ASSERT_PTR_NE(cp, NULL);
448 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf)); 451 ASSERT_STRING_EQ(cp, (const char *)sshbuf_ptr(buf));
449 sshbuf_free(buf); 452 sshbuf_free(buf);
diff --git a/regress/unittests/sshkey/test_fuzz.c b/regress/unittests/sshkey/test_fuzz.c
index a3f61a6df..1f08a2e43 100644
--- a/regress/unittests/sshkey/test_fuzz.c
+++ b/regress/unittests/sshkey/test_fuzz.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: test_fuzz.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ 1/* $OpenBSD: test_fuzz.c,v 1.4 2015/03/04 23:22:35 djm Exp $ */
2/* 2/*
3 * Fuzz tests for key parsing 3 * Fuzz tests for key parsing
4 * 4 *
@@ -53,7 +53,7 @@ public_fuzz(struct sshkey *k)
53 struct fuzz *fuzz; 53 struct fuzz *fuzz;
54 54
55 ASSERT_PTR_NE(buf = sshbuf_new(), NULL); 55 ASSERT_PTR_NE(buf = sshbuf_new(), NULL);
56 ASSERT_INT_EQ(sshkey_to_blob_buf(k, buf), 0); 56 ASSERT_INT_EQ(sshkey_putb(k, buf), 0);
57 /* XXX need a way to run the tests in "slow, but complete" mode */ 57 /* XXX need a way to run the tests in "slow, but complete" mode */
58 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */ 58 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | /* XXX too slow FUZZ_2_BIT_FLIP | */
59 FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */ 59 FUZZ_1_BYTE_FLIP | /* XXX too slow FUZZ_2_BYTE_FLIP | */
@@ -87,8 +87,11 @@ sig_fuzz(struct sshkey *k)
87 free(sig); 87 free(sig);
88 TEST_ONERROR(onerror, fuzz); 88 TEST_ONERROR(onerror, fuzz);
89 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) { 89 for(; !fuzz_done(fuzz); fuzz_next(fuzz)) {
90 sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz), 90 /* Ensure 1-bit difference at least */
91 c, sizeof(c), 0); 91 if (fuzz_matches_original(fuzz))
92 continue;
93 ASSERT_INT_NE(sshkey_verify(k, fuzz_ptr(fuzz), fuzz_len(fuzz),
94 c, sizeof(c), 0), 0);
92 } 95 }
93 fuzz_cleanup(fuzz); 96 fuzz_cleanup(fuzz);
94} 97}
@@ -101,6 +104,7 @@ sshkey_fuzz_tests(void)
101 struct fuzz *fuzz; 104 struct fuzz *fuzz;
102 int r; 105 int r;
103 106
107#ifdef WITH_SSH1
104 TEST_START("fuzz RSA1 private"); 108 TEST_START("fuzz RSA1 private");
105 buf = load_file("rsa1_1"); 109 buf = load_file("rsa1_1");
106 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP | 110 fuzz = fuzz_begin(FUZZ_1_BIT_FLIP | FUZZ_1_BYTE_FLIP |
@@ -144,6 +148,7 @@ sshkey_fuzz_tests(void)
144 sshbuf_free(fuzzed); 148 sshbuf_free(fuzzed);
145 fuzz_cleanup(fuzz); 149 fuzz_cleanup(fuzz);
146 TEST_DONE(); 150 TEST_DONE();
151#endif
147 152
148 TEST_START("fuzz RSA private"); 153 TEST_START("fuzz RSA private");
149 buf = load_file("rsa_1"); 154 buf = load_file("rsa_1");
diff --git a/regress/unittests/sshkey/test_sshkey.c b/regress/unittests/sshkey/test_sshkey.c
index ef0c67956..ad10c9be2 100644
--- a/regress/unittests/sshkey/test_sshkey.c
+++ b/regress/unittests/sshkey/test_sshkey.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: test_sshkey.c,v 1.1 2014/06/24 01:14:18 djm Exp $ */ 1/* $OpenBSD: test_sshkey.c,v 1.3 2015/01/26 06:11:28 djm Exp $ */
2/* 2/*
3 * Regress test for sshkey.h key management API 3 * Regress test for sshkey.h key management API
4 * 4 *
@@ -19,7 +19,7 @@
19#include <openssl/bn.h> 19#include <openssl/bn.h>
20#include <openssl/rsa.h> 20#include <openssl/rsa.h>
21#include <openssl/dsa.h> 21#include <openssl/dsa.h>
22#ifdef OPENSSL_HAS_NISTP256 22#if defined(OPENSSL_HAS_ECC) && defined(OPENSSL_HAS_NISTP256)
23# include <openssl/ec.h> 23# include <openssl/ec.h>
24#endif 24#endif
25 25
@@ -37,6 +37,20 @@
37void sshkey_tests(void); 37void sshkey_tests(void);
38 38
39static void 39static void
40put_opt(struct sshbuf *b, const char *name, const char *value)
41{
42 struct sshbuf *sect;
43
44 sect = sshbuf_new();
45 ASSERT_PTR_NE(sect, NULL);
46 ASSERT_INT_EQ(sshbuf_put_cstring(b, name), 0);
47 if (value != NULL)
48 ASSERT_INT_EQ(sshbuf_put_cstring(sect, value), 0);
49 ASSERT_INT_EQ(sshbuf_put_stringb(b, sect), 0);
50 sshbuf_free(sect);
51}
52
53static void
40build_cert(struct sshbuf *b, const struct sshkey *k, const char *type, 54build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
41 const struct sshkey *sign_key, const struct sshkey *ca_key) 55 const struct sshkey *sign_key, const struct sshkey *ca_key)
42{ 56{
@@ -45,25 +59,31 @@ build_cert(struct sshbuf *b, const struct sshkey *k, const char *type,
45 size_t siglen; 59 size_t siglen;
46 60
47 ca_buf = sshbuf_new(); 61 ca_buf = sshbuf_new();
48 ASSERT_INT_EQ(sshkey_to_blob_buf(ca_key, ca_buf), 0); 62 ASSERT_PTR_NE(ca_buf, NULL);
63 ASSERT_INT_EQ(sshkey_putb(ca_key, ca_buf), 0);
49 64
50 /* 65 /*
51 * Get the public key serialisation by rendering the key and skipping 66 * Get the public key serialisation by rendering the key and skipping
52 * the type string. This is a bit of a hack :/ 67 * the type string. This is a bit of a hack :/
53 */ 68 */
54 pk = sshbuf_new(); 69 pk = sshbuf_new();
55 ASSERT_INT_EQ(sshkey_plain_to_blob_buf(k, pk), 0); 70 ASSERT_PTR_NE(pk, NULL);
71 ASSERT_INT_EQ(sshkey_putb_plain(k, pk), 0);
56 ASSERT_INT_EQ(sshbuf_skip_string(pk), 0); 72 ASSERT_INT_EQ(sshbuf_skip_string(pk), 0);
57 73
58 principals = sshbuf_new(); 74 principals = sshbuf_new();
75 ASSERT_PTR_NE(principals, NULL);
59 ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0); 76 ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gsamsa"), 0);
60 ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0); 77 ASSERT_INT_EQ(sshbuf_put_cstring(principals, "gregor"), 0);
61 78
62 critopts = sshbuf_new(); 79 critopts = sshbuf_new();
63 /* XXX fill this in */ 80 ASSERT_PTR_NE(critopts, NULL);
81 put_opt(critopts, "force-command", "/usr/local/bin/nethack");
82 put_opt(critopts, "source-address", "192.168.0.0/24,127.0.0.1,::1");
64 83
65 exts = sshbuf_new(); 84 exts = sshbuf_new();
66 /* XXX fill this in */ 85 ASSERT_PTR_NE(exts, NULL);
86 put_opt(critopts, "permit-X11-forwarding", NULL);
67 87
68 ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0); 88 ASSERT_INT_EQ(sshbuf_put_cstring(b, type), 0);
69 ASSERT_INT_EQ(sshbuf_put_cstring(b, "noncenoncenonce!"), 0); /* nonce */ 89 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,
90 sshbuf_free(pk); 110 sshbuf_free(pk);
91} 111}
92 112
113static void
114signature_test(struct sshkey *k, struct sshkey *bad, const u_char *d, size_t l)
115{
116 size_t len;
117 u_char *sig;
118
119 ASSERT_INT_EQ(sshkey_sign(k, &sig, &len, d, l, 0), 0);
120 ASSERT_SIZE_T_GT(len, 8);
121 ASSERT_PTR_NE(sig, NULL);
122 ASSERT_INT_EQ(sshkey_verify(k, sig, len, d, l, 0), 0);
123 ASSERT_INT_NE(sshkey_verify(bad, sig, len, d, l, 0), 0);
124 /* Fuzz test is more comprehensive, this is just a smoke test */
125 sig[len - 5] ^= 0x10;
126 ASSERT_INT_NE(sshkey_verify(k, sig, len, d, l, 0), 0);
127 free(sig);
128}
129
130static void
131banana(u_char *s, size_t l)
132{
133 size_t o;
134 const u_char the_banana[] = { 'b', 'a', 'n', 'a', 'n', 'a' };
135
136 for (o = 0; o < l; o += sizeof(the_banana)) {
137 if (l - o < sizeof(the_banana)) {
138 memcpy(s + o, "nanananana", l - o);
139 break;
140 }
141 memcpy(s + o, banana, sizeof(the_banana));
142 }
143}
144
145static void
146signature_tests(struct sshkey *k, struct sshkey *bad)
147{
148 u_char i, buf[2049];
149 size_t lens[] = {
150 1, 2, 7, 8, 9, 15, 16, 17, 31, 32, 33, 127, 128, 129,
151 255, 256, 257, 1023, 1024, 1025, 2047, 2048, 2049
152 };
153
154 for (i = 0; i < (sizeof(lens)/sizeof(lens[0])); i++) {
155 test_subtest_info("%s key, banana length %zu",
156 sshkey_type(k), lens[i]);
157 banana(buf, lens[i]);
158 signature_test(k, bad, buf, lens[i]);
159 }
160}
161
162static struct sshkey *
163get_private(const char *n)
164{
165 struct sshbuf *b;
166 struct sshkey *ret;
167
168 b = load_file(n);
169 ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", n, &ret, NULL), 0);
170 sshbuf_free(b);
171 return ret;
172}
173
93void 174void
94sshkey_tests(void) 175sshkey_tests(void)
95{ 176{
96 struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *ke, *kf; 177 struct sshkey *k1, *k2, *k3, *k4, *kr, *kd, *kf;
178#ifdef OPENSSL_HAS_ECC
179 struct sshkey *ke;
180#endif
97 struct sshbuf *b; 181 struct sshbuf *b;
98 182
99 TEST_START("new invalid"); 183 TEST_START("new invalid");
@@ -136,12 +220,14 @@ sshkey_tests(void)
136 sshkey_free(k1); 220 sshkey_free(k1);
137 TEST_DONE(); 221 TEST_DONE();
138 222
223#ifdef OPENSSL_HAS_ECC
139 TEST_START("new/free KEY_ECDSA"); 224 TEST_START("new/free KEY_ECDSA");
140 k1 = sshkey_new(KEY_ECDSA); 225 k1 = sshkey_new(KEY_ECDSA);
141 ASSERT_PTR_NE(k1, NULL); 226 ASSERT_PTR_NE(k1, NULL);
142 ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */ 227 ASSERT_PTR_EQ(k1->ecdsa, NULL); /* Can't allocate without NID */
143 sshkey_free(k1); 228 sshkey_free(k1);
144 TEST_DONE(); 229 TEST_DONE();
230#endif
145 231
146 TEST_START("new/free KEY_ED25519"); 232 TEST_START("new/free KEY_ED25519");
147 k1 = sshkey_new(KEY_ED25519); 233 k1 = sshkey_new(KEY_ED25519);
@@ -192,12 +278,14 @@ sshkey_tests(void)
192 sshkey_free(k1); 278 sshkey_free(k1);
193 TEST_DONE(); 279 TEST_DONE();
194 280
281#ifdef OPENSSL_HAS_ECC
195 TEST_START("generate KEY_ECDSA wrong bits"); 282 TEST_START("generate KEY_ECDSA wrong bits");
196 ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1), 283 ASSERT_INT_EQ(sshkey_generate(KEY_ECDSA, 42, &k1),
197 SSH_ERR_INVALID_ARGUMENT); 284 SSH_ERR_INVALID_ARGUMENT);
198 ASSERT_PTR_EQ(k1, NULL); 285 ASSERT_PTR_EQ(k1, NULL);
199 sshkey_free(k1); 286 sshkey_free(k1);
200 TEST_DONE(); 287 TEST_DONE();
288#endif
201 289
202 TEST_START("generate KEY_RSA"); 290 TEST_START("generate KEY_RSA");
203 ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &kr), 0); 291 ASSERT_INT_EQ(sshkey_generate(KEY_RSA, 768, &kr), 0);
@@ -332,26 +420,100 @@ sshkey_tests(void)
332#endif 420#endif
333 sshkey_free(kf); 421 sshkey_free(kf);
334 422
335/* XXX certify test */ 423 TEST_START("certify key");
336/* XXX sign test */ 424 ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_1.pub"),
337/* XXX verify test */ 425 &k1, NULL), 0);
426 k2 = get_private("ed25519_2");
427 ASSERT_INT_EQ(sshkey_to_certified(k1, 0), 0);
428 ASSERT_PTR_NE(k1->cert, NULL);
429 k1->cert->type = SSH2_CERT_TYPE_USER;
430 k1->cert->serial = 1234;
431 k1->cert->key_id = strdup("estragon");
432 ASSERT_PTR_NE(k1->cert->key_id, NULL);
433 k1->cert->principals = calloc(4, sizeof(*k1->cert->principals));
434 ASSERT_PTR_NE(k1->cert->principals, NULL);
435 k1->cert->principals[0] = strdup("estragon");
436 k1->cert->principals[1] = strdup("vladimir");
437 k1->cert->principals[2] = strdup("pozzo");
438 k1->cert->principals[3] = strdup("lucky");
439 ASSERT_PTR_NE(k1->cert->principals[0], NULL);
440 ASSERT_PTR_NE(k1->cert->principals[1], NULL);
441 ASSERT_PTR_NE(k1->cert->principals[2], NULL);
442 ASSERT_PTR_NE(k1->cert->principals[3], NULL);
443 k1->cert->valid_after = 0;
444 k1->cert->valid_before = (u_int64_t)-1;
445 k1->cert->critical = sshbuf_new();
446 ASSERT_PTR_NE(k1->cert->critical, NULL);
447 k1->cert->extensions = sshbuf_new();
448 ASSERT_PTR_NE(k1->cert->extensions, NULL);
449 put_opt(k1->cert->critical, "force-command", "/usr/bin/true");
450 put_opt(k1->cert->critical, "source-address", "127.0.0.1");
451 put_opt(k1->cert->extensions, "permit-X11-forwarding", NULL);
452 put_opt(k1->cert->extensions, "permit-agent-forwarding", NULL);
453 ASSERT_INT_EQ(sshkey_from_private(k2, &k1->cert->signature_key), 0);
454 ASSERT_INT_EQ(sshkey_certify(k1, k2), 0);
455 b = sshbuf_new();
456 ASSERT_PTR_NE(b, NULL);
457 ASSERT_INT_EQ(sshkey_putb(k1, b), 0);
458 ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k3), 0);
459
460 sshkey_free(k1);
461 sshkey_free(k2);
462 sshkey_free(k3);
463 sshbuf_reset(b);
464 TEST_DONE();
465
466 TEST_START("sign and verify RSA");
467 k1 = get_private("rsa_1");
468 ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_2.pub"), &k2,
469 NULL), 0);
470 signature_tests(k1, k2);
471 sshkey_free(k1);
472 sshkey_free(k2);
473 TEST_DONE();
474
475 TEST_START("sign and verify DSA");
476 k1 = get_private("dsa_1");
477 ASSERT_INT_EQ(sshkey_load_public(test_data_file("dsa_2.pub"), &k2,
478 NULL), 0);
479 signature_tests(k1, k2);
480 sshkey_free(k1);
481 sshkey_free(k2);
482 TEST_DONE();
483
484#ifdef OPENSSL_HAS_ECC
485 TEST_START("sign and verify ECDSA");
486 k1 = get_private("ecdsa_1");
487 ASSERT_INT_EQ(sshkey_load_public(test_data_file("ecdsa_2.pub"), &k2,
488 NULL), 0);
489 signature_tests(k1, k2);
490 sshkey_free(k1);
491 sshkey_free(k2);
492 TEST_DONE();
493#endif
494
495 TEST_START("sign and verify ED25519");
496 k1 = get_private("ed25519_1");
497 ASSERT_INT_EQ(sshkey_load_public(test_data_file("ed25519_2.pub"), &k2,
498 NULL), 0);
499 signature_tests(k1, k2);
500 sshkey_free(k1);
501 sshkey_free(k2);
502 TEST_DONE();
338 503
339 TEST_START("nested certificate"); 504 TEST_START("nested certificate");
340 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0); 505 ASSERT_INT_EQ(sshkey_load_cert(test_data_file("rsa_1"), &k1), 0);
341 ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2, 506 ASSERT_INT_EQ(sshkey_load_public(test_data_file("rsa_1.pub"), &k2,
342 NULL), 0); 507 NULL), 0);
343 b = load_file("rsa_2"); 508 k3 = get_private("ed25519_2");
344 ASSERT_INT_EQ(sshkey_parse_private_fileblob(b, "", "rsa_1",
345 &k3, NULL), 0);
346 sshbuf_reset(b);
347 build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1); 509 build_cert(b, k2, "ssh-rsa-cert-v01@openssh.com", k3, k1);
348 ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4), 510 ASSERT_INT_EQ(sshkey_from_blob(sshbuf_ptr(b), sshbuf_len(b), &k4),
349 SSH_ERR_KEY_CERT_INVALID_SIGN_KEY); 511 SSH_ERR_KEY_CERT_INVALID_SIGN_KEY);
350 ASSERT_PTR_EQ(k4, NULL); 512 ASSERT_PTR_EQ(k4, NULL);
351 sshbuf_free(b);
352 sshkey_free(k1); 513 sshkey_free(k1);
353 sshkey_free(k2); 514 sshkey_free(k2);
354 sshkey_free(k3); 515 sshkey_free(k3);
516 sshbuf_free(b);
355 TEST_DONE(); 517 TEST_DONE();
356 518
357} 519}
diff --git a/regress/unittests/sshkey/testdata/dsa_1-cert.fp b/regress/unittests/sshkey/testdata/dsa_1-cert.fp
index 56ee1f89b..b26145b24 100644
--- a/regress/unittests/sshkey/testdata/dsa_1-cert.fp
+++ b/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/regress/unittests/sshkey/testdata/dsa_1.fp b/regress/unittests/sshkey/testdata/dsa_1.fp
index 56ee1f89b..b26145b24 100644
--- a/regress/unittests/sshkey/testdata/dsa_1.fp
+++ b/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/regress/unittests/sshkey/testdata/dsa_2.fp b/regress/unittests/sshkey/testdata/dsa_2.fp
index ba9de82a8..822657403 100644
--- a/regress/unittests/sshkey/testdata/dsa_2.fp
+++ b/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/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp b/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
index a56dbc8d0..c3d747aff 100644
--- a/regress/unittests/sshkey/testdata/ecdsa_1-cert.fp
+++ b/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/regress/unittests/sshkey/testdata/ecdsa_1.fp b/regress/unittests/sshkey/testdata/ecdsa_1.fp
index a56dbc8d0..c3d747aff 100644
--- a/regress/unittests/sshkey/testdata/ecdsa_1.fp
+++ b/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/regress/unittests/sshkey/testdata/ecdsa_2.fp b/regress/unittests/sshkey/testdata/ecdsa_2.fp
index eb4bbdf03..fe7526b92 100644
--- a/regress/unittests/sshkey/testdata/ecdsa_2.fp
+++ b/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/regress/unittests/sshkey/testdata/ed25519_1-cert.fp b/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
index e6d23d0b8..fbde87af0 100644
--- a/regress/unittests/sshkey/testdata/ed25519_1-cert.fp
+++ b/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/regress/unittests/sshkey/testdata/ed25519_1.fp b/regress/unittests/sshkey/testdata/ed25519_1.fp
index e6d23d0b8..fbde87af0 100644
--- a/regress/unittests/sshkey/testdata/ed25519_1.fp
+++ b/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/regress/unittests/sshkey/testdata/ed25519_2.fp b/regress/unittests/sshkey/testdata/ed25519_2.fp
index 02c684f36..ec1cdbb94 100644
--- a/regress/unittests/sshkey/testdata/ed25519_2.fp
+++ b/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/regress/unittests/sshkey/testdata/rsa1_1.fp b/regress/unittests/sshkey/testdata/rsa1_1.fp
index 782ece0db..2e1068c64 100644
--- a/regress/unittests/sshkey/testdata/rsa1_1.fp
+++ b/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/regress/unittests/sshkey/testdata/rsa1_2.fp b/regress/unittests/sshkey/testdata/rsa1_2.fp
index c3325371d..cd0039306 100644
--- a/regress/unittests/sshkey/testdata/rsa1_2.fp
+++ b/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/regress/unittests/sshkey/testdata/rsa_1-cert.fp b/regress/unittests/sshkey/testdata/rsa_1-cert.fp
index bf9c2e362..1cf780dd9 100644
--- a/regress/unittests/sshkey/testdata/rsa_1-cert.fp
+++ b/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/regress/unittests/sshkey/testdata/rsa_1.fp b/regress/unittests/sshkey/testdata/rsa_1.fp
index bf9c2e362..1cf780dd9 100644
--- a/regress/unittests/sshkey/testdata/rsa_1.fp
+++ b/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/regress/unittests/sshkey/testdata/rsa_2.fp b/regress/unittests/sshkey/testdata/rsa_2.fp
index 53939f413..8d4367610 100644
--- a/regress/unittests/sshkey/testdata/rsa_2.fp
+++ b/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/regress/unittests/test_helper/Makefile b/regress/unittests/test_helper/Makefile
index 3e90903ef..5b3894cbf 100644
--- a/regress/unittests/test_helper/Makefile
+++ b/regress/unittests/test_helper/Makefile
@@ -1,4 +1,4 @@
1# $OpenBSD: Makefile,v 1.1 2014/04/30 05:32:00 djm Exp $ 1# $OpenBSD: Makefile,v 1.2 2015/01/20 22:58:57 djm Exp $
2 2
3LIB= test_helper 3LIB= test_helper
4SRCS= test_helper.c fuzz.c 4SRCS= test_helper.c fuzz.c
@@ -7,6 +7,9 @@ DEBUGLIBS= no
7NOPROFILE= yes 7NOPROFILE= yes
8NOPIC= yes 8NOPIC= yes
9 9
10# Hack to allow building with SUBDIR in ../../Makefile
11regress: all
12
10install: 13install:
11 @echo -n 14 @echo -n
12 15
diff --git a/regress/unittests/test_helper/fuzz.c b/regress/unittests/test_helper/fuzz.c
index 77c6e7cad..99f1d036c 100644
--- a/regress/unittests/test_helper/fuzz.c
+++ b/regress/unittests/test_helper/fuzz.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: fuzz.c,v 1.3 2014/05/02 09:41:32 andre Exp $ */ 1/* $OpenBSD: fuzz.c,v 1.8 2015/03/03 20:42:49 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -20,6 +20,7 @@
20#include "includes.h" 20#include "includes.h"
21 21
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/uio.h>
23 24
24#include <assert.h> 25#include <assert.h>
25#include <ctype.h> 26#include <ctype.h>
@@ -29,9 +30,11 @@
29#endif 30#endif
30#include <stdlib.h> 31#include <stdlib.h>
31#include <string.h> 32#include <string.h>
32#include <assert.h> 33#include <signal.h>
34#include <unistd.h>
33 35
34#include "test_helper.h" 36#include "test_helper.h"
37#include "atomicio.h"
35 38
36/* #define FUZZ_DEBUG */ 39/* #define FUZZ_DEBUG */
37 40
@@ -96,60 +99,66 @@ fuzz_ntop(u_int n)
96 } 99 }
97} 100}
98 101
99void 102static int
100fuzz_dump(struct fuzz *fuzz) 103fuzz_fmt(struct fuzz *fuzz, char *s, size_t n)
101{ 104{
102 u_char *p = fuzz_ptr(fuzz); 105 if (fuzz == NULL)
103 size_t i, j, len = fuzz_len(fuzz); 106 return -1;
104 107
105 switch (fuzz->strategy) { 108 switch (fuzz->strategy) {
106 case FUZZ_1_BIT_FLIP: 109 case FUZZ_1_BIT_FLIP:
107 fprintf(stderr, "%s case %zu of %zu (bit: %zu)\n", 110 snprintf(s, n, "%s case %zu of %zu (bit: %zu)\n",
108 fuzz_ntop(fuzz->strategy), 111 fuzz_ntop(fuzz->strategy),
109 fuzz->o1, fuzz->slen * 8, fuzz->o1); 112 fuzz->o1, fuzz->slen * 8, fuzz->o1);
110 break; 113 return 0;
111 case FUZZ_2_BIT_FLIP: 114 case FUZZ_2_BIT_FLIP:
112 fprintf(stderr, "%s case %llu of %llu (bits: %zu, %zu)\n", 115 snprintf(s, n, "%s case %llu of %llu (bits: %zu, %zu)\n",
113 fuzz_ntop(fuzz->strategy), 116 fuzz_ntop(fuzz->strategy),
114 (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1, 117 (((fuzz_ullong)fuzz->o2) * fuzz->slen * 8) + fuzz->o1,
115 ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8, 118 ((fuzz_ullong)fuzz->slen * 8) * fuzz->slen * 8,
116 fuzz->o1, fuzz->o2); 119 fuzz->o1, fuzz->o2);
117 break; 120 return 0;
118 case FUZZ_1_BYTE_FLIP: 121 case FUZZ_1_BYTE_FLIP:
119 fprintf(stderr, "%s case %zu of %zu (byte: %zu)\n", 122 snprintf(s, n, "%s case %zu of %zu (byte: %zu)\n",
120 fuzz_ntop(fuzz->strategy), 123 fuzz_ntop(fuzz->strategy),
121 fuzz->o1, fuzz->slen, fuzz->o1); 124 fuzz->o1, fuzz->slen, fuzz->o1);
122 break; 125 return 0;
123 case FUZZ_2_BYTE_FLIP: 126 case FUZZ_2_BYTE_FLIP:
124 fprintf(stderr, "%s case %llu of %llu (bytes: %zu, %zu)\n", 127 snprintf(s, n, "%s case %llu of %llu (bytes: %zu, %zu)\n",
125 fuzz_ntop(fuzz->strategy), 128 fuzz_ntop(fuzz->strategy),
126 (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1, 129 (((fuzz_ullong)fuzz->o2) * fuzz->slen) + fuzz->o1,
127 ((fuzz_ullong)fuzz->slen) * fuzz->slen, 130 ((fuzz_ullong)fuzz->slen) * fuzz->slen,
128 fuzz->o1, fuzz->o2); 131 fuzz->o1, fuzz->o2);
129 break; 132 return 0;
130 case FUZZ_TRUNCATE_START: 133 case FUZZ_TRUNCATE_START:
131 fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", 134 snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
132 fuzz_ntop(fuzz->strategy), 135 fuzz_ntop(fuzz->strategy),
133 fuzz->o1, fuzz->slen, fuzz->o1); 136 fuzz->o1, fuzz->slen, fuzz->o1);
134 break; 137 return 0;
135 case FUZZ_TRUNCATE_END: 138 case FUZZ_TRUNCATE_END:
136 fprintf(stderr, "%s case %zu of %zu (offset: %zu)\n", 139 snprintf(s, n, "%s case %zu of %zu (offset: %zu)\n",
137 fuzz_ntop(fuzz->strategy), 140 fuzz_ntop(fuzz->strategy),
138 fuzz->o1, fuzz->slen, fuzz->o1); 141 fuzz->o1, fuzz->slen, fuzz->o1);
139 break; 142 return 0;
140 case FUZZ_BASE64: 143 case FUZZ_BASE64:
141 assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1); 144 assert(fuzz->o2 < sizeof(fuzz_b64chars) - 1);
142 fprintf(stderr, "%s case %llu of %llu (offset: %zu char: %c)\n", 145 snprintf(s, n, "%s case %llu of %llu (offset: %zu char: %c)\n",
143 fuzz_ntop(fuzz->strategy), 146 fuzz_ntop(fuzz->strategy),
144 (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2, 147 (fuzz->o1 * (fuzz_ullong)64) + fuzz->o2,
145 fuzz->slen * (fuzz_ullong)64, fuzz->o1, 148 fuzz->slen * (fuzz_ullong)64, fuzz->o1,
146 fuzz_b64chars[fuzz->o2]); 149 fuzz_b64chars[fuzz->o2]);
147 break; 150 return 0;
148 default: 151 default:
152 return -1;
149 abort(); 153 abort();
150 } 154 }
155}
156
157static void
158dump(u_char *p, size_t len)
159{
160 size_t i, j;
151 161
152 fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, len);
153 for (i = 0; i < len; i += 16) { 162 for (i = 0; i < len; i += 16) {
154 fprintf(stderr, "%.4zd: ", i); 163 fprintf(stderr, "%.4zd: ", i);
155 for (j = i; j < i + 16; j++) { 164 for (j = i; j < i + 16; j++) {
@@ -171,6 +180,39 @@ fuzz_dump(struct fuzz *fuzz)
171 } 180 }
172} 181}
173 182
183void
184fuzz_dump(struct fuzz *fuzz)
185{
186 char buf[256];
187
188 if (fuzz_fmt(fuzz, buf, sizeof(buf)) != 0) {
189 fprintf(stderr, "%s: fuzz invalid\n", __func__);
190 abort();
191 }
192 fputs(buf, stderr);
193 fprintf(stderr, "fuzz original %p len = %zu\n", fuzz->seed, fuzz->slen);
194 dump(fuzz->seed, fuzz->slen);
195 fprintf(stderr, "fuzz context %p len = %zu\n", fuzz, fuzz_len(fuzz));
196 dump(fuzz_ptr(fuzz), fuzz_len(fuzz));
197}
198
199#ifdef SIGINFO
200static struct fuzz *last_fuzz;
201
202static void
203siginfo(int unused __attribute__((__unused__)))
204{
205 char buf[256];
206
207 test_info(buf, sizeof(buf));
208 atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
209 if (last_fuzz != NULL) {
210 fuzz_fmt(last_fuzz, buf, sizeof(buf));
211 atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
212 }
213}
214#endif
215
174struct fuzz * 216struct fuzz *
175fuzz_begin(u_int strategies, const void *p, size_t l) 217fuzz_begin(u_int strategies, const void *p, size_t l)
176{ 218{
@@ -190,6 +232,12 @@ fuzz_begin(u_int strategies, const void *p, size_t l)
190 FUZZ_DBG(("begin, ret = %p", ret)); 232 FUZZ_DBG(("begin, ret = %p", ret));
191 233
192 fuzz_next(ret); 234 fuzz_next(ret);
235
236#ifdef SIGINFO
237 last_fuzz = ret;
238 signal(SIGINFO, siginfo);
239#endif
240
193 return ret; 241 return ret;
194} 242}
195 243
@@ -197,6 +245,10 @@ void
197fuzz_cleanup(struct fuzz *fuzz) 245fuzz_cleanup(struct fuzz *fuzz)
198{ 246{
199 FUZZ_DBG(("cleanup, fuzz = %p", fuzz)); 247 FUZZ_DBG(("cleanup, fuzz = %p", fuzz));
248#ifdef SIGINFO
249 last_fuzz = NULL;
250 signal(SIGINFO, SIG_DFL);
251#endif
200 assert(fuzz != NULL); 252 assert(fuzz != NULL);
201 assert(fuzz->seed != NULL); 253 assert(fuzz->seed != NULL);
202 assert(fuzz->fuzzed != NULL); 254 assert(fuzz->fuzzed != NULL);
@@ -326,6 +378,14 @@ fuzz_next(struct fuzz *fuzz)
326} 378}
327 379
328int 380int
381fuzz_matches_original(struct fuzz *fuzz)
382{
383 if (fuzz_len(fuzz) != fuzz->slen)
384 return 0;
385 return memcmp(fuzz_ptr(fuzz), fuzz->seed, fuzz->slen) == 0;
386}
387
388int
329fuzz_done(struct fuzz *fuzz) 389fuzz_done(struct fuzz *fuzz)
330{ 390{
331 FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz, 391 FUZZ_DBG(("fuzz = %p, strategies = 0x%lx", fuzz,
diff --git a/regress/unittests/test_helper/test_helper.c b/regress/unittests/test_helper/test_helper.c
index d0bc67833..26ca26b5e 100644
--- a/regress/unittests/test_helper/test_helper.c
+++ b/regress/unittests/test_helper/test_helper.c
@@ -1,4 +1,4 @@
1/* $OpenBSD: test_helper.c,v 1.2 2014/05/02 09:41:32 andre Exp $ */ 1/* $OpenBSD: test_helper.c,v 1.6 2015/03/03 20:42:49 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -21,6 +21,7 @@
21 21
22#include <sys/types.h> 22#include <sys/types.h>
23#include <sys/param.h> 23#include <sys/param.h>
24#include <sys/uio.h>
24 25
25#include <fcntl.h> 26#include <fcntl.h>
26#include <stdio.h> 27#include <stdio.h>
@@ -31,6 +32,7 @@
31#include <string.h> 32#include <string.h>
32#include <assert.h> 33#include <assert.h>
33#include <unistd.h> 34#include <unistd.h>
35#include <signal.h>
34 36
35#include <openssl/bn.h> 37#include <openssl/bn.h>
36 38
@@ -39,6 +41,7 @@
39#endif 41#endif
40 42
41#include "test_helper.h" 43#include "test_helper.h"
44#include "atomicio.h"
42 45
43#define TEST_CHECK_INT(r, pred) do { \ 46#define TEST_CHECK_INT(r, pred) do { \
44 switch (pred) { \ 47 switch (pred) { \
@@ -111,6 +114,7 @@ static u_int test_number = 0;
111static test_onerror_func_t *test_onerror = NULL; 114static test_onerror_func_t *test_onerror = NULL;
112static void *onerror_ctx = NULL; 115static void *onerror_ctx = NULL;
113static const char *data_dir = NULL; 116static const char *data_dir = NULL;
117static char subtest_info[512];
114 118
115int 119int
116main(int argc, char **argv) 120main(int argc, char **argv)
@@ -180,13 +184,36 @@ test_data_file(const char *name)
180} 184}
181 185
182void 186void
187test_info(char *s, size_t len)
188{
189 snprintf(s, len, "In test %u: \"%s\"%s%s\n", test_number,
190 active_test_name == NULL ? "<none>" : active_test_name,
191 *subtest_info != '\0' ? " - " : "", subtest_info);
192}
193
194#ifdef SIGINFO
195static void
196siginfo(int unused __attribute__((__unused__)))
197{
198 char buf[256];
199
200 test_info(buf, sizeof(buf));
201 atomicio(vwrite, STDERR_FILENO, buf, strlen(buf));
202}
203#endif
204
205void
183test_start(const char *n) 206test_start(const char *n)
184{ 207{
185 assert(active_test_name == NULL); 208 assert(active_test_name == NULL);
186 assert((active_test_name = strdup(n)) != NULL); 209 assert((active_test_name = strdup(n)) != NULL);
210 *subtest_info = '\0';
187 if (verbose_mode) 211 if (verbose_mode)
188 printf("test %u - \"%s\": ", test_number, active_test_name); 212 printf("test %u - \"%s\": ", test_number, active_test_name);
189 test_number++; 213 test_number++;
214#ifdef SIGINFO
215 signal(SIGINFO, siginfo);
216#endif
190} 217}
191 218
192void 219void
@@ -199,6 +226,7 @@ set_onerror_func(test_onerror_func_t *f, void *ctx)
199void 226void
200test_done(void) 227test_done(void)
201{ 228{
229 *subtest_info = '\0';
202 assert(active_test_name != NULL); 230 assert(active_test_name != NULL);
203 free(active_test_name); 231 free(active_test_name);
204 active_test_name = NULL; 232 active_test_name = NULL;
@@ -211,6 +239,16 @@ test_done(void)
211} 239}
212 240
213void 241void
242test_subtest_info(const char *fmt, ...)
243{
244 va_list ap;
245
246 va_start(ap, fmt);
247 vsnprintf(subtest_info, sizeof(subtest_info), fmt, ap);
248 va_end(ap);
249}
250
251void
214ssl_err_check(const char *file, int line) 252ssl_err_check(const char *file, int line)
215{ 253{
216 long openssl_error = ERR_get_error(); 254 long openssl_error = ERR_get_error();
@@ -256,8 +294,9 @@ static void
256test_header(const char *file, int line, const char *a1, const char *a2, 294test_header(const char *file, int line, const char *a1, const char *a2,
257 const char *name, enum test_predicate pred) 295 const char *name, enum test_predicate pred)
258{ 296{
259 fprintf(stderr, "\n%s:%d test #%u \"%s\"\n", 297 fprintf(stderr, "\n%s:%d test #%u \"%s\"%s%s\n",
260 file, line, test_number, active_test_name); 298 file, line, test_number, active_test_name,
299 *subtest_info != '\0' ? " - " : "", subtest_info);
261 fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n", 300 fprintf(stderr, "ASSERT_%s_%s(%s%s%s) failed:\n",
262 name, pred_name(pred), a1, 301 name, pred_name(pred), a1,
263 a2 != NULL ? ", " : "", a2 != NULL ? a2 : ""); 302 a2 != NULL ? ", " : "", a2 != NULL ? a2 : "");
@@ -280,8 +319,13 @@ void
280assert_string(const char *file, int line, const char *a1, const char *a2, 319assert_string(const char *file, int line, const char *a1, const char *a2,
281 const char *aa1, const char *aa2, enum test_predicate pred) 320 const char *aa1, const char *aa2, enum test_predicate pred)
282{ 321{
283 int r = strcmp(aa1, aa2); 322 int r;
284 323
324 /* Verify pointers are not NULL */
325 assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
326 assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
327
328 r = strcmp(aa1, aa2);
285 TEST_CHECK_INT(r, pred); 329 TEST_CHECK_INT(r, pred);
286 test_header(file, line, a1, a2, "STRING", pred); 330 test_header(file, line, a1, a2, "STRING", pred);
287 fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1)); 331 fprintf(stderr, "%12s = %s (len %zu)\n", a1, aa1, strlen(aa1));
@@ -310,8 +354,15 @@ void
310assert_mem(const char *file, int line, const char *a1, const char *a2, 354assert_mem(const char *file, int line, const char *a1, const char *a2,
311 const void *aa1, const void *aa2, size_t l, enum test_predicate pred) 355 const void *aa1, const void *aa2, size_t l, enum test_predicate pred)
312{ 356{
313 int r = memcmp(aa1, aa2, l); 357 int r;
314 358
359 if (l == 0)
360 return;
361 /* If length is >0, then verify pointers are not NULL */
362 assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
363 assert_ptr(file, line, a2, "NULL", aa2, NULL, TEST_NE);
364
365 r = memcmp(aa1, aa2, l);
315 TEST_CHECK_INT(r, pred); 366 TEST_CHECK_INT(r, pred);
316 test_header(file, line, a1, a2, "STRING", pred); 367 test_header(file, line, a1, a2, "STRING", pred);
317 fprintf(stderr, "%12s = %s (len %zu)\n", a1, tohex(aa1, MIN(l, 256)), l); 368 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,
338 const void *aa1, u_char v, size_t l, enum test_predicate pred) 389 const void *aa1, u_char v, size_t l, enum test_predicate pred)
339{ 390{
340 size_t where = -1; 391 size_t where = -1;
341 int r = memvalcmp(aa1, v, l, &where); 392 int r;
342 char tmp[64]; 393 char tmp[64];
343 394
344 if (l == 0) 395 if (l == 0)
345 return; 396 return;
397 /* If length is >0, then verify the pointer is not NULL */
398 assert_ptr(file, line, a1, "NULL", aa1, NULL, TEST_NE);
399
400 r = memvalcmp(aa1, v, l, &where);
346 TEST_CHECK_INT(r, pred); 401 TEST_CHECK_INT(r, pred);
347 test_header(file, line, a1, NULL, "MEM_ZERO", pred); 402 test_header(file, line, a1, NULL, "MEM_ZERO", pred);
348 fprintf(stderr, "%20s = %s%s (len %zu)\n", a1, 403 fprintf(stderr, "%20s = %s%s (len %zu)\n", a1,
diff --git a/regress/unittests/test_helper/test_helper.h b/regress/unittests/test_helper/test_helper.h
index a398c615f..1d9c66986 100644
--- a/regress/unittests/test_helper/test_helper.h
+++ b/regress/unittests/test_helper/test_helper.h
@@ -1,4 +1,4 @@
1/* $OpenBSD: test_helper.h,v 1.3 2014/05/02 09:41:32 andre Exp $ */ 1/* $OpenBSD: test_helper.h,v 1.6 2015/01/18 19:52:44 djm Exp $ */
2/* 2/*
3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org> 3 * Copyright (c) 2011 Damien Miller <djm@mindrot.org>
4 * 4 *
@@ -40,8 +40,11 @@ void tests(void);
40 40
41const char *test_data_file(const char *name); 41const char *test_data_file(const char *name);
42void test_start(const char *n); 42void test_start(const char *n);
43void test_info(char *s, size_t len);
43void set_onerror_func(test_onerror_func_t *f, void *ctx); 44void set_onerror_func(test_onerror_func_t *f, void *ctx);
44void test_done(void); 45void test_done(void);
46void test_subtest_info(const char *fmt, ...)
47 __attribute__((format(printf, 1, 2)));
45void ssl_err_check(const char *file, int line); 48void ssl_err_check(const char *file, int line);
46void assert_bignum(const char *file, int line, 49void assert_bignum(const char *file, int line,
47 const char *a1, const char *a2, 50 const char *a1, const char *a2,
@@ -280,6 +283,13 @@ void fuzz_cleanup(struct fuzz *fuzz);
280/* Prepare the next fuzz case in the series */ 283/* Prepare the next fuzz case in the series */
281void fuzz_next(struct fuzz *fuzz); 284void fuzz_next(struct fuzz *fuzz);
282 285
286/*
287 * Check whether this fuzz case is identical to the original
288 * This is slow, but useful if the caller needs to ensure that all tests
289 * generated change the input (e.g. when fuzzing signatures).
290 */
291int fuzz_matches_original(struct fuzz *fuzz);
292
283/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */ 293/* Determine whether the current fuzz sequence is exhausted (nonzero = yes) */
284int fuzz_done(struct fuzz *fuzz); 294int fuzz_done(struct fuzz *fuzz);
285 295
@@ -289,4 +299,5 @@ u_char *fuzz_ptr(struct fuzz *fuzz);
289 299
290/* Dump the current fuzz case to stderr */ 300/* Dump the current fuzz case to stderr */
291void fuzz_dump(struct fuzz *fuzz); 301void fuzz_dump(struct fuzz *fuzz);
302
292#endif /* _TEST_HELPER_H */ 303#endif /* _TEST_HELPER_H */
diff --git a/regress/valgrind-unit.sh b/regress/valgrind-unit.sh
new file mode 100755
index 000000000..433cb069a
--- /dev/null
+++ b/regress/valgrind-unit.sh
@@ -0,0 +1,20 @@
1#!/bin/sh
2
3UNIT_BINARY="$1"
4shift
5UNIT_ARGS="$@"
6
7test "x$OBJ" = "x" && OBJ=$PWD
8
9# This mostly replicates the logic in test-exec.sh for running the
10# regress tests under valgrind.
11VG_TEST=`basename $UNIT_BINARY`
12VG_LOG="$OBJ/valgrind-out/${VG_TEST}.%p"
13VG_OPTS="--track-origins=yes --leak-check=full --log-file=${VG_LOG}"
14VG_OPTS="$VG_OPTS --trace-children=yes"
15VG_PATH="valgrind"
16if [ "x$VALGRIND_PATH" != "x" ]; then
17 VG_PATH="$VALGRIND_PATH"
18fi
19
20exec $VG_PATH $VG_OPTS $UNIT_BINARY $UNIT_ARGS
diff --git a/regress/yes-head.sh b/regress/yes-head.sh
index a8e6bc800..1fc754211 100644
--- a/regress/yes-head.sh
+++ b/regress/yes-head.sh
@@ -1,9 +1,9 @@
1# $OpenBSD: yes-head.sh,v 1.4 2002/03/15 13:08:56 markus Exp $ 1# $OpenBSD: yes-head.sh,v 1.5 2015/03/03 22:35:19 markus Exp $
2# Placed in the Public Domain. 2# Placed in the Public Domain.
3 3
4tid="yes pipe head" 4tid="yes pipe head"
5 5
6for p in 1 2; do 6for p in ${SSH_PROTOCOLS}; do
7 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)` 7 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)`
8 if [ $? -ne 0 ]; then 8 if [ $? -ne 0 ]; then
9 fail "yes|head test failed" 9 fail "yes|head test failed"