aboutsummaryrefslogtreecommitdiff
path: root/crypto/openssh/regress
diff options
context:
space:
mode:
Diffstat (limited to 'crypto/openssh/regress')
-rw-r--r--crypto/openssh/regress/Makefile3
-rw-r--r--crypto/openssh/regress/agent-restrict.sh6
-rw-r--r--crypto/openssh/regress/agent.sh27
-rw-r--r--crypto/openssh/regress/cert-userkey.sh62
-rw-r--r--crypto/openssh/regress/cfginclude.sh14
-rw-r--r--crypto/openssh/regress/cfgmatch.sh70
-rw-r--r--crypto/openssh/regress/dropbear-ciphers.sh4
-rw-r--r--crypto/openssh/regress/dropbear-kex.sh17
-rw-r--r--crypto/openssh/regress/hostkey-agent.sh28
-rw-r--r--crypto/openssh/regress/key-options.sh7
-rw-r--r--crypto/openssh/regress/misc/fuzz-harness/agent_fuzz_helper.c1
-rw-r--r--crypto/openssh/regress/misc/sk-dummy/Makefile66
-rw-r--r--crypto/openssh/regress/misc/ssh-verify-attestation/Makefile79
-rw-r--r--crypto/openssh/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c433
-rw-r--r--crypto/openssh/regress/percent.sh42
-rw-r--r--crypto/openssh/regress/servcfginclude.sh14
-rw-r--r--crypto/openssh/regress/sftp-resume.sh43
-rw-r--r--crypto/openssh/regress/sshfp-connect.sh8
-rw-r--r--crypto/openssh/regress/test-exec.sh27
-rw-r--r--crypto/openssh/regress/unittests/authopt/Makefile27
-rw-r--r--crypto/openssh/regress/unittests/misc/Makefile33
21 files changed, 907 insertions, 104 deletions
diff --git a/crypto/openssh/regress/Makefile b/crypto/openssh/regress/Makefile
index 7f7349706be1..7e7f95b58a2c 100644
--- a/crypto/openssh/regress/Makefile
+++ b/crypto/openssh/regress/Makefile
@@ -1,4 +1,4 @@
-# $OpenBSD: Makefile,v 1.135 2024/06/14 04:43:11 djm Exp $
+# $OpenBSD: Makefile,v 1.136 2025/03/11 07:50:20 dtucker Exp $
tests: prep file-tests t-exec unit
@@ -65,6 +65,7 @@ LTESTS= connect \
sftp-batch \
sftp-glob \
sftp-perm \
+ sftp-resume \
sftp-uri \
reconfigure \
dynamic-forward \
diff --git a/crypto/openssh/regress/agent-restrict.sh b/crypto/openssh/regress/agent-restrict.sh
index 62cea85225e7..057856f1bbdf 100644
--- a/crypto/openssh/regress/agent-restrict.sh
+++ b/crypto/openssh/regress/agent-restrict.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent-restrict.sh,v 1.6 2023/03/01 09:29:32 dtucker Exp $
+# $OpenBSD: agent-restrict.sh,v 1.7 2025/03/28 21:45:55 dtucker Exp $
# Placed in the Public Domain.
tid="agent restrictions"
@@ -39,14 +39,14 @@ Host host_$h
Hostname host_$h
HostkeyAlias host_$h
IdentityFile $OBJ/user_$h
- ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h
+ ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${TEST_SSH_SSHD_ENV} ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h
_EOF
# Variant with no specified keys.
cat << _EOF >> $OBJ/ssh_proxy_noid
Host host_$h
Hostname host_$h
HostkeyAlias host_$h
- ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h
+ ProxyCommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${TEST_SSH_SSHD_ENV} ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy_host_$h
_EOF
done
cat $OBJ/ssh_proxy.bak >> $OBJ/ssh_proxy
diff --git a/crypto/openssh/regress/agent.sh b/crypto/openssh/regress/agent.sh
index 5f1060608eb5..f0022aca5528 100644
--- a/crypto/openssh/regress/agent.sh
+++ b/crypto/openssh/regress/agent.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: agent.sh,v 1.21 2023/03/01 09:29:32 dtucker Exp $
+# $OpenBSD: agent.sh,v 1.22 2024/10/24 03:28:34 djm Exp $
# Placed in the Public Domain.
tid="simple agent test"
@@ -157,7 +157,7 @@ done
## Deletion tests.
-trace "delete all agent keys"
+trace "delete all agent keys using -D"
${SSHADD} -D > /dev/null 2>&1
r=$?
if [ $r -ne 0 ]; then
@@ -181,6 +181,29 @@ r=$?
if [ $r -ne 0 ]; then
fail "ssh-add -l failed: exit code $r"
fi
+trace "delete all agent keys using SIGUSR1"
+kill -s USR1 $SSH_AGENT_PID
+r=$?
+if [ $r -ne 0 ]; then
+ fail "kill -s USR1 failed: exit code $r"
+fi
+# make sure they're gone
+${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 1 ]; then
+ fail "ssh-add -l returned unexpected exit code: $r"
+fi
+# re-add keys/certs to agent
+for t in ${SSH_KEYTYPES}; do
+ ${SSHADD} $OBJ/$t-agent-private >/dev/null 2>&1 || \
+ fail "ssh-add failed exit code $?"
+done
+# make sure they are there
+${SSHADD} -l > /dev/null 2>&1
+r=$?
+if [ $r -ne 0 ]; then
+ fail "ssh-add -l failed: exit code $r"
+fi
check_key_absent() {
${SSHADD} -L | grep "^$1 " >/dev/null
diff --git a/crypto/openssh/regress/cert-userkey.sh b/crypto/openssh/regress/cert-userkey.sh
index 4ea29b7cdbb4..2ab0a1e9e65c 100644
--- a/crypto/openssh/regress/cert-userkey.sh
+++ b/crypto/openssh/regress/cert-userkey.sh
@@ -1,12 +1,15 @@
-# $OpenBSD: cert-userkey.sh,v 1.28 2021/09/30 05:26:26 dtucker Exp $
+# $OpenBSD: cert-userkey.sh,v 1.29 2024/12/06 16:25:58 djm Exp $
# Placed in the Public Domain.
tid="certified user keys"
-rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
-cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
+rm -f $OBJ/authorized_keys_${USER}* $OBJ/user_ca_key* $OBJ/cert_user_key*
+rm -f $OBJ/authorized_principals*
cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
+grep -v AuthorizedKeysFile $OBJ/sshd_proxy > $OBJ/sshd_proxy_bak
+echo "AuthorizedKeysFile $OBJ/authorized_keys_%u_*" >> $OBJ/sshd_proxy_bak
+
PLAIN_TYPES=`$SSH -Q key-plain | maybe_filter_sk | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
EXTRA_TYPES=""
rsa=""
@@ -63,11 +66,15 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
_prefix="${ktype}"
# Setup for AuthorizedPrincipalsFile
- rm -f $OBJ/authorized_keys_$USER
+ rm -f $OBJ/authorized_keys_${USER}* $OBJ/authorized_principals_${USER}*
+ touch $OBJ/authorized_keys_${USER}_A
+ touch $OBJ/authorized_keys_${USER}_Z
+ touch $OBJ/authorized_principals_${USER}_A
+ touch $OBJ/authorized_principals_${USER}_Z
(
cat $OBJ/sshd_proxy_bak
echo "AuthorizedPrincipalsFile " \
- "$OBJ/authorized_principals_%u"
+ "$OBJ/authorized_principals_%u_*"
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
echo "PubkeyAcceptedAlgorithms ${t}"
) > $OBJ/sshd_proxy
@@ -78,7 +85,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# Missing authorized_principals
verbose "$tid: ${_prefix} missing authorized_principals"
- rm -f $OBJ/authorized_principals_$USER
+ rm -f $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
@@ -87,7 +94,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# Empty authorized_principals
verbose "$tid: ${_prefix} empty authorized_principals"
- echo > $OBJ/authorized_principals_$USER
+ echo > $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
@@ -96,7 +103,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# Wrong authorized_principals
verbose "$tid: ${_prefix} wrong authorized_principals"
- echo gregorsamsa > $OBJ/authorized_principals_$USER
+ echo gregorsamsa > $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
@@ -105,7 +112,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# Correct authorized_principals
verbose "$tid: ${_prefix} correct authorized_principals"
- echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+ echo mekmitasdigoat > $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
@@ -114,7 +121,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# authorized_principals with bad key option
verbose "$tid: ${_prefix} authorized_principals bad key opt"
- echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
+ echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
@@ -124,7 +131,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# authorized_principals with command=false
verbose "$tid: ${_prefix} authorized_principals command=false"
echo 'command="false" mekmitasdigoat' > \
- $OBJ/authorized_principals_$USER
+ $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
@@ -135,7 +142,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
# authorized_principals with command=true
verbose "$tid: ${_prefix} authorized_principals command=true"
echo 'command="true" mekmitasdigoat' > \
- $OBJ/authorized_principals_$USER
+ $OBJ/authorized_principals_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
if [ $? -ne 0 ]; then
@@ -143,7 +150,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
fi
# Setup for principals= key option
- rm -f $OBJ/authorized_principals_$USER
+ rm -f $OBJ/authorized_principals_${USER}_X
(
cat $OBJ/sshd_proxy_bak
echo "PubkeyAcceptedAlgorithms ${t}"
@@ -158,7 +165,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
(
printf 'cert-authority,principals="gregorsamsa" '
cat $OBJ/user_ca_key.pub
- ) > $OBJ/authorized_keys_$USER
+ ) > $OBJ/authorized_keys_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -eq 0 ]; then
@@ -170,7 +177,7 @@ for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
(
printf 'cert-authority,principals="mekmitasdigoat" '
cat $OBJ/user_ca_key.pub
- ) > $OBJ/authorized_keys_$USER
+ ) > $OBJ/authorized_keys_${USER}_X
${SSH} -i $OBJ/cert_user_key_${ktype} \
-F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
if [ $? -ne 0 ]; then
@@ -180,14 +187,17 @@ done
basic_tests() {
auth=$1
+ rm -f $OBJ/authorized_keys_${USER}*
+ touch $OBJ/authorized_keys_${USER}_A
+ touch $OBJ/authorized_keys_${USER}_Z
if test "x$auth" = "xauthorized_keys" ; then
# Add CA to authorized_keys
(
printf 'cert-authority '
cat $OBJ/user_ca_key.pub
- ) > $OBJ/authorized_keys_$USER
+ ) > $OBJ/authorized_keys_${USER}_X
else
- echo > $OBJ/authorized_keys_$USER
+ echo > $OBJ/authorized_keys_${USER}_X
extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
fi
@@ -295,9 +305,9 @@ test_one() {
(
printf "cert-authority${auth_opt} "
cat $OBJ/user_ca_key.pub
- ) > $OBJ/authorized_keys_$USER
+ ) > $OBJ/authorized_keys_${USER}_X
else
- echo > $OBJ/authorized_keys_$USER
+ echo > $OBJ/authorized_keys_${USER}_X
echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
>> $OBJ/sshd_proxy
echo "PubkeyAcceptedAlgorithms ${t}*" \
@@ -346,15 +356,15 @@ test_one "empty principals" failure "" TrustedUserCAKeys
# should always be refused.
# AuthorizedPrincipalsFile
-rm -f $OBJ/authorized_keys_$USER
-echo mekmitasdigoat > $OBJ/authorized_principals_$USER
+rm -f $OBJ/authorized_keys_${USER}_X
+echo mekmitasdigoat > $OBJ/authorized_principals_${USER}_X
test_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
- TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+ TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u_*"
test_one "AuthorizedPrincipalsFile no principals" failure "" \
- TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
+ TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u_*"
# principals= key option
-rm -f $OBJ/authorized_principals_$USER
+rm -f $OBJ/authorized_principals_${USER}_X
test_one "principals key option principals" success "-n mekmitasdigoat" \
authorized_keys ',principals="mekmitasdigoat"'
test_one "principals key option no principals" failure "" \
@@ -391,6 +401,6 @@ for ktype in $PLAIN_TYPES ; do
fi
done
-rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
-rm -f $OBJ/authorized_principals_$USER
+rm -f $OBJ/authorized_keys_${USER}* $OBJ/user_ca_key* $OBJ/cert_user_key*
+rm -f $OBJ/authorized_principals*
diff --git a/crypto/openssh/regress/cfginclude.sh b/crypto/openssh/regress/cfginclude.sh
index d442cdd6eea8..97fd816f935f 100644
--- a/crypto/openssh/regress/cfginclude.sh
+++ b/crypto/openssh/regress/cfginclude.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $
+# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $
# Placed in the Public Domain.
tid="config include"
@@ -10,7 +10,7 @@ cat > $OBJ/ssh_config.i << _EOF
Match host a
Hostname aa
-Match host b # comment
+Match host=b # comment
Hostname bb
Include $OBJ/ssh_config.i.*
@@ -18,7 +18,7 @@ Match host c
Include $OBJ/ssh_config.i.*
Hostname cc
-Match host m
+Match host=m !user xxxyfake
Include $OBJ/ssh_config.i.* # comment
Host d
@@ -41,7 +41,7 @@ Match host xxxxxx
_EOF
cat > $OBJ/ssh_config.i.1 << _EOF
-Match host a
+Match host=a
Hostname aaa
Match host b
@@ -64,10 +64,10 @@ cat > $OBJ/ssh_config.i.2 << _EOF
Match host a
Hostname aaaa
-Match host b
+Match host=b !user blahblahfake
Hostname bbbb
-Match host c
+Match host=c
Hostname cccc
Host d
@@ -142,7 +142,7 @@ trial a aa
# cleanup
rm -f $OBJ/ssh_config.i $OBJ/ssh_config.i.* $OBJ/ssh_config.out
-# $OpenBSD: cfginclude.sh,v 1.4 2024/09/03 05:58:56 djm Exp $
+# $OpenBSD: cfginclude.sh,v 1.5 2024/09/27 01:05:54 djm Exp $
# Placed in the Public Domain.
tid="config include"
diff --git a/crypto/openssh/regress/cfgmatch.sh b/crypto/openssh/regress/cfgmatch.sh
index 05a6668551a9..2737a5f977ef 100644
--- a/crypto/openssh/regress/cfgmatch.sh
+++ b/crypto/openssh/regress/cfgmatch.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: cfgmatch.sh,v 1.13 2021/06/08 06:52:43 djm Exp $
+# $OpenBSD: cfgmatch.sh,v 1.14 2024/09/27 01:05:54 djm Exp $
# Placed in the Public Domain.
tid="sshd_config match"
@@ -26,7 +26,7 @@ start_client()
kill $client_pid
fatal "timeout waiting for background ssh"
fi
- done
+ done
}
stop_client()
@@ -119,40 +119,42 @@ stop_client
# requires knowledge of actual group memberships user running the test).
params="user:user:u1 host:host:h1 address:addr:1.2.3.4 \
localaddress:laddr:5.6.7.8 rdomain:rdomain:rdom1"
-cp $OBJ/sshd_proxy_bak $OBJ/sshd_config
-echo 'Banner /nomatch' >>$OBJ/sshd_config
-for i in $params; do
- config=`echo $i | cut -f1 -d:`
- criteria=`echo $i | cut -f2 -d:`
- value=`echo $i | cut -f3 -d:`
- cat >>$OBJ/sshd_config <<EOD
- Match $config $value
- Banner /$value
+for separator in " " "=" ; do
+ cp $OBJ/sshd_proxy_bak $OBJ/sshd_config
+ echo 'Banner /nomatch' >>$OBJ/sshd_config
+ for i in $params; do
+ config=`echo $i | cut -f1 -d:`
+ criteria=`echo $i | cut -f2 -d:`
+ value=`echo $i | cut -f3 -d:`
+ cat >>$OBJ/sshd_config <<EOD
+ Match ${config}${separator}${value}
+ Banner /$value
EOD
-done
+ done
-${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \
- fail "validate config for w/out spec"
-
-# Test matching each criteria.
-for i in $params; do
- testcriteria=`echo $i | cut -f2 -d:`
- expected=/`echo $i | cut -f3 -d:`
- spec=""
- for j in $params; do
- config=`echo $j | cut -f1 -d:`
- criteria=`echo $j | cut -f2 -d:`
- value=`echo $j | cut -f3 -d:`
- if [ "$criteria" = "$testcriteria" ]; then
- spec="$criteria=$value,$spec"
- else
- spec="$criteria=1$value,$spec"
+ ${SUDO} ${SSHD} -f $OBJ/sshd_config -T >/dev/null || \
+ fail "validate config for w/out spec"
+
+ # Test matching each criteria.
+ for i in $params; do
+ testcriteria=`echo $i | cut -f2 -d:`
+ expected=/`echo $i | cut -f3 -d:`
+ spec=""
+ for j in $params; do
+ config=`echo $j | cut -f1 -d:`
+ criteria=`echo $j | cut -f2 -d:`
+ value=`echo $j | cut -f3 -d:`
+ if [ "$criteria" = "$testcriteria" ]; then
+ spec="$criteria=$value,$spec"
+ else
+ spec="$criteria=1$value,$spec"
+ fi
+ done
+ trace "test spec $spec"
+ result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \
+ awk '$1=="banner"{print $2}'`
+ if [ "$result" != "$expected" ]; then
+ fail "match $config expected $expected got $result"
fi
done
- trace "test spec $spec"
- result=`${SUDO} ${SSHD} -f $OBJ/sshd_config -T -C "$spec" | \
- awk '$1=="banner"{print $2}'`
- if [ "$result" != "$expected" ]; then
- fail "match $config expected $expected got $result"
- fi
done
diff --git a/crypto/openssh/regress/dropbear-ciphers.sh b/crypto/openssh/regress/dropbear-ciphers.sh
index 1500fa0e725b..c58cb90c76c5 100644
--- a/crypto/openssh/regress/dropbear-ciphers.sh
+++ b/crypto/openssh/regress/dropbear-ciphers.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: dropbear-ciphers.sh,v 1.3 2024/06/20 08:23:18 dtucker Exp $
+# $OpenBSD: dropbear-ciphers.sh,v 1.4 2025/03/11 07:43:03 dtucker Exp $
# Placed in the Public Domain.
tid="dropbear ciphers"
@@ -26,7 +26,7 @@ for c in $ciphers ; do
for kt in $keytype; do
verbose "$tid: cipher $c mac $m kt $kt"
rm -f ${COPY}
- env HOME=$OBJ dbclient -y -i $OBJ/.dropbear/$kt 2>$OBJ/dbclient.log \
+ env HOME=$OBJ ${DBCLIENT} -y -i $OBJ/.dropbear/$kt 2>$OBJ/dbclient.log \
-c $c -m $m -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY}
if [ $? -ne 0 ]; then
fail "ssh cat $DATA failed"
diff --git a/crypto/openssh/regress/dropbear-kex.sh b/crypto/openssh/regress/dropbear-kex.sh
index d9f1b32c09d4..72717fbb7866 100644
--- a/crypto/openssh/regress/dropbear-kex.sh
+++ b/crypto/openssh/regress/dropbear-kex.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: dropbear-kex.sh,v 1.3 2024/06/19 10:10:46 dtucker Exp $
+# $OpenBSD: dropbear-kex.sh,v 1.4 2025/03/11 07:42:08 dtucker Exp $
# Placed in the Public Domain.
tid="dropbear kex"
@@ -10,8 +10,14 @@ fi
cp $OBJ/sshd_proxy $OBJ/sshd_proxy.bak
kex="curve25519-sha256 curve25519-sha256@libssh.org"
-if $SSH -Q kex | grep 'diffie-hellman-group14-sha1'; then
- kex="$kex diffie-hellman-group14-sha256 diffie-hellman-group14-sha1"
+if $SSH -Q kex | grep 'diffie-hellman-group14-sha256' >/dev/null; then
+ kex="$kex diffie-hellman-group14-sha256"
+fi
+# There's no flag to query KEX, so if MACs does not contain SHA1, assume
+# there's also SHA1-based KEX methods either.
+if $SSH -Q kex | grep 'diffie-hellman-group14-sha1' >/dev/null && \
+ $DBCLIENT -m help hst 2>&1 | grep -- '-sha1' >/dev/null ; then
+ kex="$kex diffie-hellman-group14-sha1"
fi
for k in $kex; do
@@ -19,8 +25,9 @@ for k in $kex; do
rm -f ${COPY}
# dbclient doesn't have switch for kex, so force in server
(cat $OBJ/sshd_proxy.bak; echo "KexAlgorithms $k") >$OBJ/sshd_proxy
- env HOME=$OBJ dbclient -y -i $OBJ/.dropbear/id_ed25519 2>$OBJ/dbclient.log \
- -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY}
+ env HOME=$OBJ \
+ ${DBCLIENT} -y -i $OBJ/.dropbear/id_ed25519 2>$OBJ/dbclient.log \
+ -J "$OBJ/ssh_proxy.sh" somehost cat ${DATA} > ${COPY}
if [ $? -ne 0 ]; then
fail "ssh cat $DATA failed"
fi
diff --git a/crypto/openssh/regress/hostkey-agent.sh b/crypto/openssh/regress/hostkey-agent.sh
index 222d424bd34f..28dcfe17068f 100644
--- a/crypto/openssh/regress/hostkey-agent.sh
+++ b/crypto/openssh/regress/hostkey-agent.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: hostkey-agent.sh,v 1.13 2021/09/30 05:20:08 dtucker Exp $
+# $OpenBSD: hostkey-agent.sh,v 1.15 2024/12/04 10:51:13 dtucker Exp $
# Placed in the Public Domain.
tid="hostkey agent"
@@ -49,7 +49,7 @@ for k in $SSH_KEYTYPES ; do
fi
done
-SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com'`
+SSH_CERTTYPES=`ssh -Q key-sig | grep 'cert-v01@openssh.com' | maybe_filter_sk`
# Prepare sshd_proxy for certificates.
cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
@@ -82,6 +82,30 @@ for k in $SSH_CERTTYPES ; do
fi
done
+verbose "multiple hostkeys"
+cp $OBJ/sshd_proxy.orig $OBJ/sshd_proxy
+cp $OBJ/ssh_proxy $OBJ/ssh_proxy.orig
+grep -vi 'globalknownhostsfile' $OBJ/ssh_proxy.orig > $OBJ/ssh_proxy
+echo "UpdateHostkeys=yes" >> $OBJ/ssh_proxy
+echo "GlobalKnownHostsFile=none" >> $OBJ/ssh_proxy
+
+for k in $SSH_KEYTYPES ; do
+ verbose "Addkey type $k"
+ echo "Hostkey $OBJ/agent-key.${k}" >> $OBJ/sshd_proxy
+
+ ( printf 'localhost-with-alias ' ;
+ cat $OBJ/agent-key.$k.pub) > $OBJ/known_hosts
+done
+
+opts="-oStrictHostKeyChecking=yes -F $OBJ/ssh_proxy"
+SSH_CONNECTION=`${SSH} $opts host 'echo $SSH_CONNECTION'`
+if [ $? -ne 0 ]; then
+ fail "connection to server with multiple hostkeys failed"
+fi
+if [ "$SSH_CONNECTION" != "UNKNOWN 65535 UNKNOWN 65535" ]; then
+ fail "bad SSH_CONNECTION key while using multiple hostkeys"
+fi
+
trace "kill agent"
${SSHAGENT} -k > /dev/null
diff --git a/crypto/openssh/regress/key-options.sh b/crypto/openssh/regress/key-options.sh
index 623128ca4e65..7f9b45fc0f60 100644
--- a/crypto/openssh/regress/key-options.sh
+++ b/crypto/openssh/regress/key-options.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: key-options.sh,v 1.10 2024/03/25 02:07:08 dtucker Exp $
+# $OpenBSD: key-options.sh,v 1.11 2024/12/05 14:28:39 dtucker Exp $
# Placed in the Public Domain.
tid="key options"
@@ -120,5 +120,8 @@ check_valid_before() {
check_valid_before "default" "" "pass"
check_valid_before "invalid" 'expiry-time="INVALID"' "fail"
check_valid_before "expired" 'expiry-time="19990101"' "fail"
+if config_defined "SIZEOF_TIME_T 4"; then
check_valid_before "valid" 'expiry-time="20380101"' "pass"
-
+else
+check_valid_before "valid-64b" 'expiry-time="25250101"' "pass"
+fi
diff --git a/crypto/openssh/regress/misc/fuzz-harness/agent_fuzz_helper.c b/crypto/openssh/regress/misc/fuzz-harness/agent_fuzz_helper.c
index 321343bbbbdc..2750221154e6 100644
--- a/crypto/openssh/regress/misc/fuzz-harness/agent_fuzz_helper.c
+++ b/crypto/openssh/regress/misc/fuzz-harness/agent_fuzz_helper.c
@@ -158,6 +158,7 @@ test_one(const uint8_t* s, size_t slen)
SYSLOG_FACILITY_AUTH, 1);
devnull = devnull_or_die();
allowed_providers = xstrdup("");
+ websafe_allowlist = xstrdup("*");
setenv("DISPLAY", "", 1); /* ban askpass */
}
diff --git a/crypto/openssh/regress/misc/sk-dummy/Makefile b/crypto/openssh/regress/misc/sk-dummy/Makefile
new file mode 100644
index 000000000000..18b0a243f664
--- /dev/null
+++ b/crypto/openssh/regress/misc/sk-dummy/Makefile
@@ -0,0 +1,66 @@
+# $OpenBSD: Makefile,v 1.3 2023/01/15 23:35:10 djm Exp $
+
+.include <bsd.own.mk>
+.include <bsd.obj.mk>
+
+PROG= sk-dummy.so
+NOMAN=
+
+SSHREL=../../../../../usr.bin/ssh
+.PATH: ${.CURDIR}/${SSHREL}
+
+SRCS=sk-dummy.c
+# From usr.bin/ssh
+SRCS+=ed25519.c hash.c
+OPENSSL?= yes
+
+CFLAGS+= -fPIC
+
+.if (${OPENSSL:L} == "yes")
+CFLAGS+= -DWITH_OPENSSL
+.endif
+
+# enable warnings
+WARNINGS=Yes
+
+DEBUG=-g
+CFLAGS+= -fstack-protector-all
+CDIAGFLAGS= -Wall
+CDIAGFLAGS+= -Wextra
+CDIAGFLAGS+= -Werror
+CDIAGFLAGS+= -Wchar-subscripts
+CDIAGFLAGS+= -Wcomment
+CDIAGFLAGS+= -Wformat
+CDIAGFLAGS+= -Wformat-security
+CDIAGFLAGS+= -Wimplicit
+CDIAGFLAGS+= -Winline
+CDIAGFLAGS+= -Wmissing-declarations
+CDIAGFLAGS+= -Wmissing-prototypes
+CDIAGFLAGS+= -Wparentheses
+CDIAGFLAGS+= -Wpointer-arith
+CDIAGFLAGS+= -Wreturn-type
+CDIAGFLAGS+= -Wshadow
+CDIAGFLAGS+= -Wsign-compare
+CDIAGFLAGS+= -Wstrict-aliasing
+CDIAGFLAGS+= -Wstrict-prototypes
+CDIAGFLAGS+= -Wswitch
+CDIAGFLAGS+= -Wtrigraphs
+CDIAGFLAGS+= -Wuninitialized
+CDIAGFLAGS+= -Wunused
+CDIAGFLAGS+= -Wno-unused-parameter
+.if ${COMPILER_VERSION:L} != "gcc3"
+CDIAGFLAGS+= -Wold-style-definition
+.endif
+
+CFLAGS+=-I${.CURDIR}/${SSHREL}
+
+.if (${OPENSSL:L} == "yes")
+LDADD+= -lcrypto
+DPADD+= ${LIBCRYPTO}
+.endif
+
+$(PROG): $(OBJS)
+ $(CC) $(LDFLAGS) -shared -o $@ $(OBJS) $(LDADD)
+
+.include <bsd.prog.mk>
+
diff --git a/crypto/openssh/regress/misc/ssh-verify-attestation/Makefile b/crypto/openssh/regress/misc/ssh-verify-attestation/Makefile
new file mode 100644
index 000000000000..2a797aecae46
--- /dev/null
+++ b/crypto/openssh/regress/misc/ssh-verify-attestation/Makefile
@@ -0,0 +1,79 @@
+# $OpenBSD: Makefile,v 1.1 2024/12/04 16:42:49 djm Exp $
+
+.include <bsd.own.mk>
+.include <bsd.obj.mk>
+
+PROG= ssh-verify-attestation
+NOMAN=
+
+SSHREL=../../../../../usr.bin/ssh
+.PATH: ${.CURDIR}/${SSHREL}
+
+SRCS=ssh-verify-attestation.c
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
+SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
+SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
+SRCS+=addr.c addrmatch.c bitmap.c
+SRCS+=ed25519.c hash.c
+SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
+SRCS+=ssh-ed25519-sk.c sk-usbhid.c
+
+SRCS+=digest-openssl.c
+#SRCS+=digest-libc.c
+SRCS+=utf8.c
+
+OPENSSL?= yes
+
+.if (${OPENSSL:L} == "yes")
+CFLAGS+= -DWITH_OPENSSL
+.endif
+
+# enable warnings
+WARNINGS=Yes
+
+DEBUG=-g
+CFLAGS+= -fstack-protector-all
+CDIAGFLAGS= -Wall
+CDIAGFLAGS+= -Wextra
+CDIAGFLAGS+= -Werror
+CDIAGFLAGS+= -Wchar-subscripts
+CDIAGFLAGS+= -Wcomment
+CDIAGFLAGS+= -Wformat
+CDIAGFLAGS+= -Wformat-security
+CDIAGFLAGS+= -Wimplicit
+CDIAGFLAGS+= -Winline
+CDIAGFLAGS+= -Wmissing-declarations
+CDIAGFLAGS+= -Wmissing-prototypes
+CDIAGFLAGS+= -Wparentheses
+CDIAGFLAGS+= -Wpointer-arith
+CDIAGFLAGS+= -Wreturn-type
+CDIAGFLAGS+= -Wshadow
+CDIAGFLAGS+= -Wsign-compare
+CDIAGFLAGS+= -Wstrict-aliasing
+CDIAGFLAGS+= -Wstrict-prototypes
+CDIAGFLAGS+= -Wswitch
+CDIAGFLAGS+= -Wtrigraphs
+CDIAGFLAGS+= -Wuninitialized
+CDIAGFLAGS+= -Wunused
+CDIAGFLAGS+= -Wno-unused-parameter
+.if ${COMPILER_VERSION:L} != "gcc3"
+CDIAGFLAGS+= -Wold-style-definition
+.endif
+
+CFLAGS+=-I${.CURDIR}/${SSHREL}
+
+.if (${OPENSSL:L} == "yes")
+LDADD+= -lcrypto
+DPADD+= ${LIBCRYPTO}
+.endif
+
+LDADD+= -lfido2 -lcbor
+DPADD+= ${LIBFIDO2} ${LIBCBOR}
+
+LDADD+= -lutil
+DPADD+= ${LIBUTIL}
+
+.include <bsd.prog.mk>
+
diff --git a/crypto/openssh/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c b/crypto/openssh/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c
new file mode 100644
index 000000000000..4d82a0390587
--- /dev/null
+++ b/crypto/openssh/regress/misc/ssh-verify-attestation/ssh-verify-attestation.c
@@ -0,0 +1,433 @@
+/* $OpenBSD: ssh-verify-attestation.c,v 1.2 2024/12/06 10:37:42 djm Exp $ */
+/*
+ * Copyright (c) 2022-2024 Damien Miller
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+
+/*
+ * This is a small program to verify FIDO attestation objects that
+ * ssh-keygen(1) can record when enrolling a FIDO key. It requires that
+ * the attestation object and challenge used when creating the key be
+ * recorded.
+ *
+ * Example usage:
+ *
+ * $ # Generate a random challenge.
+ * $ dd if=/dev/urandom of=key_ecdsa_sk.challenge bs=32 count=1
+ * $ # Generate a key, record the attestation blob.
+ * $ ssh-keygen -f key_ecdsa_sk -t ecdsa-sk \
+ * -Ochallenge=key_ecdsa_sk.challenge \
+ * -Owrite-attestation=key_ecdsa_sk.attest -N ''
+ * $ # Validate the challenge (-A = print attestation CA cert)
+ * $ ./obj/ssh-verify-attestation -A key_ecdsa_sk key_ecdsa_sk.challenge \
+ * key_ecdsa_sk.attest
+ *
+ * Limitations/TODO:
+ *
+ * 1) It doesn't automatically detect the attestation statement format. It
+ * assumes the "packed" format used by FIDO2 keys. If that doesn't work,
+ * then try using the -U option to select the "fido-u2f" format.
+ * 2) It makes assumptions about RK, UV, etc status of the key/cred.
+ * 3) Probably bugs.
+ *
+ * Thanks to Markus Friedl and Pedro Martelletto for help getting this
+ * working.
+ */
+
+#include "includes.h"
+
+#include <stdint.h>
+#include <inttypes.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <stdarg.h>
+
+#include "xmalloc.h"
+#include "log.h"
+#include "sshbuf.h"
+#include "sshkey.h"
+#include "authfile.h"
+#include "ssherr.h"
+#include "misc.h"
+#include "digest.h"
+#include "crypto_api.h"
+
+#include <fido.h>
+#include <openssl/x509.h>
+#include <openssl/x509v3.h>
+#include <openssl/bio.h>
+#include <openssl/err.h>
+#include <openssl/pem.h>
+
+extern char *__progname;
+
+#define ATTEST_MAGIC "ssh-sk-attest-v01"
+
+static int
+prepare_fido_cred(fido_cred_t *cred, int credtype, const char *attfmt,
+ const char *rp_id, struct sshbuf *b, const struct sshbuf *challenge,
+ struct sshbuf **attestation_certp)
+{
+ struct sshbuf *attestation_cert = NULL, *sig = NULL, *authdata = NULL;
+ char *magic = NULL;
+ int r = SSH_ERR_INTERNAL_ERROR;
+
+ *attestation_certp = NULL;
+
+ /* Make sure it's the format we're expecting */
+ if ((r = sshbuf_get_cstring(b, &magic, NULL)) != 0) {
+ error_fr(r, "parse header");
+ goto out;
+ }
+ if (strcmp(magic, ATTEST_MAGIC) != 0) {
+ error_f("unsupported format");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ /* Parse the remaining fields */
+ if ((r = sshbuf_froms(b, &attestation_cert)) != 0 ||
+ (r = sshbuf_froms(b, &sig)) != 0 ||
+ (r = sshbuf_froms(b, &authdata)) != 0 ||
+ (r = sshbuf_get_u32(b, NULL)) != 0 || /* reserved flags */
+ (r = sshbuf_get_string_direct(b, NULL, NULL)) != 0) { /* reserved */
+ error_fr(r, "parse body");
+ goto out;
+ }
+ debug3_f("attestation cert len=%zu, sig len=%zu, "
+ "authdata len=%zu challenge len=%zu", sshbuf_len(attestation_cert),
+ sshbuf_len(sig), sshbuf_len(authdata), sshbuf_len(challenge));
+
+ fido_cred_set_type(cred, credtype);
+ fido_cred_set_fmt(cred, attfmt);
+ fido_cred_set_clientdata(cred, sshbuf_ptr(challenge),
+ sshbuf_len(challenge));
+ fido_cred_set_rp(cred, rp_id, NULL);
+ fido_cred_set_authdata(cred, sshbuf_ptr(authdata),
+ sshbuf_len(authdata));
+ /* XXX set_extensions, set_rk, set_uv */
+ fido_cred_set_x509(cred, sshbuf_ptr(attestation_cert),
+ sshbuf_len(attestation_cert));
+ fido_cred_set_sig(cred, sshbuf_ptr(sig), sshbuf_len(sig));
+
+ /* success */
+ *attestation_certp = attestation_cert;
+ attestation_cert = NULL;
+ r = 0;
+ out:
+ free(magic);
+ sshbuf_free(attestation_cert);
+ sshbuf_free(sig);
+ sshbuf_free(authdata);
+ return r;
+}
+
+static uint8_t *
+get_pubkey_from_cred_ecdsa(const fido_cred_t *cred, size_t *pubkey_len)
+{
+ const uint8_t *ptr;
+ uint8_t *pubkey = NULL, *ret = NULL;
+ BIGNUM *x = NULL, *y = NULL;
+ EC_POINT *q = NULL;
+ EC_GROUP *g = NULL;
+
+ if ((x = BN_new()) == NULL ||
+ (y = BN_new()) == NULL ||
+ (g = EC_GROUP_new_by_curve_name(NID_X9_62_prime256v1)) == NULL ||
+ (q = EC_POINT_new(g)) == NULL) {
+ error_f("libcrypto setup failed");
+ goto out;
+ }
+ if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
+ error_f("fido_cred_pubkey_ptr failed");
+ goto out;
+ }
+ if (fido_cred_pubkey_len(cred) != 64) {
+ error_f("bad fido_cred_pubkey_len %zu",
+ fido_cred_pubkey_len(cred));
+ goto out;
+ }
+
+ if (BN_bin2bn(ptr, 32, x) == NULL ||
+ BN_bin2bn(ptr + 32, 32, y) == NULL) {
+ error_f("BN_bin2bn failed");
+ goto out;
+ }
+ if (EC_POINT_set_affine_coordinates_GFp(g, q, x, y, NULL) != 1) {
+ error_f("EC_POINT_set_affine_coordinates_GFp failed");
+ goto out;
+ }
+ *pubkey_len = EC_POINT_point2oct(g, q,
+ POINT_CONVERSION_UNCOMPRESSED, NULL, 0, NULL);
+ if (*pubkey_len == 0 || *pubkey_len > 2048) {
+ error_f("bad pubkey length %zu", *pubkey_len);
+ goto out;
+ }
+ if ((pubkey = malloc(*pubkey_len)) == NULL) {
+ error_f("malloc pubkey failed");
+ goto out;
+ }
+ if (EC_POINT_point2oct(g, q, POINT_CONVERSION_UNCOMPRESSED,
+ pubkey, *pubkey_len, NULL) == 0) {
+ error_f("EC_POINT_point2oct failed");
+ goto out;
+ }
+ /* success */
+ ret = pubkey;
+ pubkey = NULL;
+ out:
+ free(pubkey);
+ EC_POINT_free(q);
+ EC_GROUP_free(g);
+ BN_clear_free(x);
+ BN_clear_free(y);
+ return ret;
+}
+
+/* copied from sshsk_ecdsa_assemble() */
+static int
+cred_matches_key_ecdsa(const fido_cred_t *cred, const struct sshkey *k)
+{
+ struct sshkey *key = NULL;
+ struct sshbuf *b = NULL;
+ EC_KEY *ec = NULL;
+ uint8_t *pubkey = NULL;
+ size_t pubkey_len;
+ int r;
+
+ if ((key = sshkey_new(KEY_ECDSA_SK)) == NULL) {
+ error_f("sshkey_new failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ key->ecdsa_nid = NID_X9_62_prime256v1;
+ if ((key->pkey = EVP_PKEY_new()) == NULL ||
+ (ec = EC_KEY_new_by_curve_name(key->ecdsa_nid)) == NULL ||
+ (b = sshbuf_new()) == NULL) {
+ error_f("allocation failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((pubkey = get_pubkey_from_cred_ecdsa(cred, &pubkey_len)) == NULL) {
+ error_f("get_pubkey_from_cred_ecdsa failed");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if ((r = sshbuf_put_string(b, pubkey, pubkey_len)) != 0) {
+ error_fr(r, "sshbuf_put_string");
+ goto out;
+ }
+ if ((r = sshbuf_get_eckey(b, ec)) != 0) {
+ error_fr(r, "parse");
+ r = SSH_ERR_INVALID_FORMAT;
+ goto out;
+ }
+ if (sshkey_ec_validate_public(EC_KEY_get0_group(ec),
+ EC_KEY_get0_public_key(ec)) != 0) {
+ error("Authenticator returned invalid ECDSA key");
+ r = SSH_ERR_KEY_INVALID_EC_VALUE;
+ goto out;
+ }
+ if (EVP_PKEY_set1_EC_KEY(key->pkey, ec) != 1) {
+ /* XXX assume it is a allocation error */
+ error_f("allocation failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ key->sk_application = xstrdup(k->sk_application); /* XXX */
+ if (!sshkey_equal_public(key, k)) {
+ error("sshkey_equal_public failed");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ r = 0; /* success */
+ out:
+ EC_KEY_free(ec);
+ free(pubkey);
+ sshkey_free(key);
+ sshbuf_free(b);
+ return r;
+}
+
+
+/* copied from sshsk_ed25519_assemble() */
+static int
+cred_matches_key_ed25519(const fido_cred_t *cred, const struct sshkey *k)
+{
+ struct sshkey *key = NULL;
+ const uint8_t *ptr;
+ int r = -1;
+
+ if ((ptr = fido_cred_pubkey_ptr(cred)) == NULL) {
+ error_f("fido_cred_pubkey_ptr failed");
+ goto out;
+ }
+ if (fido_cred_pubkey_len(cred) != ED25519_PK_SZ) {
+ error_f("bad fido_cred_pubkey_len %zu",
+ fido_cred_pubkey_len(cred));
+ goto out;
+ }
+
+ if ((key = sshkey_new(KEY_ED25519_SK)) == NULL) {
+ error_f("sshkey_new failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ if ((key->ed25519_pk = malloc(ED25519_PK_SZ)) == NULL) {
+ error_f("malloc failed");
+ r = SSH_ERR_ALLOC_FAIL;
+ goto out;
+ }
+ memcpy(key->ed25519_pk, ptr, ED25519_PK_SZ);
+ key->sk_application = xstrdup(k->sk_application); /* XXX */
+ if (!sshkey_equal_public(key, k)) {
+ error("sshkey_equal_public failed");
+ r = SSH_ERR_INVALID_ARGUMENT;
+ goto out;
+ }
+ r = 0; /* success */
+ out:
+ sshkey_free(key);
+ return r;
+}
+
+static int
+cred_matches_key(const fido_cred_t *cred, const struct sshkey *k)
+{
+ switch (sshkey_type_plain(k->type)) {
+ case KEY_ECDSA_SK:
+ switch (k->ecdsa_nid) {
+ case NID_X9_62_prime256v1:
+ return cred_matches_key_ecdsa(cred, k);
+ break;
+ default:
+ fatal("Unsupported ECDSA key size");
+ }
+ break;
+ case KEY_ED25519_SK:
+ return cred_matches_key_ed25519(cred, k);
+ default:
+ error_f("key type %s not supported", sshkey_type(k));
+ return -1;
+ }
+}
+
+int
+main(int argc, char **argv)
+{
+ LogLevel log_level = SYSLOG_LEVEL_INFO;
+ int r, ch, credtype = -1;
+ struct sshkey *k = NULL;
+ struct sshbuf *attestation = NULL, *challenge = NULL;
+ struct sshbuf *attestation_cert = NULL;
+ char *fp;
+ const char *attfmt = "packed", *style = NULL;
+ fido_cred_t *cred = NULL;
+ int write_attestation_cert = 0;
+ extern int optind;
+ /* extern char *optarg; */
+
+ ERR_load_crypto_strings();
+
+ sanitise_stdfd();
+ log_init(__progname, log_level, SYSLOG_FACILITY_AUTH, 1);
+
+ while ((ch = getopt(argc, argv, "UAv")) != -1) {
+ switch (ch) {
+ case 'U':
+ attfmt = "fido-u2f";
+ break;
+ case 'A':
+ write_attestation_cert = 1;
+ break;
+ case 'v':
+ if (log_level == SYSLOG_LEVEL_ERROR)
+ log_level = SYSLOG_LEVEL_DEBUG1;
+ else if (log_level < SYSLOG_LEVEL_DEBUG3)
+ log_level++;
+ break;
+ default:
+ goto usage;
+ }
+ }
+ log_init(__progname, log_level, SYSLOG_FACILITY_AUTH, 1);
+ argv += optind;
+ argc -= optind;
+
+ if (argc < 3) {
+ usage:
+ fprintf(stderr, "usage: %s [-vAU] "
+ "pubkey challenge attestation-blob\n", __progname);
+ exit(1);
+ }
+ if ((r = sshkey_load_public(argv[0], &k, NULL)) != 0)
+ fatal_r(r, "load key %s", argv[0]);
+ if ((fp = sshkey_fingerprint(k, SSH_FP_HASH_DEFAULT,
+ SSH_FP_DEFAULT)) == NULL)
+ fatal("sshkey_fingerprint failed");
+ debug2("key %s: %s %s", argv[2], sshkey_type(k), fp);
+ free(fp);
+ if ((r = sshbuf_load_file(argv[1], &challenge)) != 0)
+ fatal_r(r, "load challenge %s", argv[1]);
+ if ((r = sshbuf_load_file(argv[2], &attestation)) != 0)
+ fatal_r(r, "load attestation %s", argv[2]);
+ if ((cred = fido_cred_new()) == NULL)
+ fatal("fido_cred_new failed");
+
+ switch (sshkey_type_plain(k->type)) {
+ case KEY_ECDSA_SK:
+ switch (k->ecdsa_nid) {
+ case NID_X9_62_prime256v1:
+ credtype = COSE_ES256;
+ break;
+ default:
+ fatal("Unsupported ECDSA key size");
+ }
+ break;
+ case KEY_ED25519_SK:
+ credtype = COSE_EDDSA;
+ break;
+ default:
+ fatal("unsupported key type %s", sshkey_type(k));
+ }
+
+ if ((r = prepare_fido_cred(cred, credtype, attfmt, k->sk_application,
+ attestation, challenge, &attestation_cert)) != 0)
+ fatal_r(r, "prepare_fido_cred %s", argv[2]);
+ if (fido_cred_x5c_ptr(cred) != NULL) {
+ debug("basic attestation");
+ if ((r = fido_cred_verify(cred)) != FIDO_OK)
+ fatal("basic attestation failed");
+ style = "basic";
+ } else {
+ debug("self attestation");
+ if ((r = fido_cred_verify_self(cred)) != FIDO_OK)
+ fatal("self attestation failed");
+ style = "self";
+ }
+ if (cred_matches_key(cred, k) != 0)
+ fatal("cred authdata does not match key");
+
+ fido_cred_free(&cred);
+
+ if (write_attestation_cert) {
+ PEM_write(stdout, "CERTIFICATE", NULL,
+ sshbuf_ptr(attestation_cert), sshbuf_len(attestation_cert));
+ }
+ sshbuf_free(attestation_cert);
+
+ logit("%s: verified %s attestation", argv[2], style);
+
+ return (0);
+}
diff --git a/crypto/openssh/regress/percent.sh b/crypto/openssh/regress/percent.sh
index 354854f97d55..7ce9e8a1dc30 100644
--- a/crypto/openssh/regress/percent.sh
+++ b/crypto/openssh/regress/percent.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: percent.sh,v 1.17 2023/03/27 03:56:50 dtucker Exp $
+# $OpenBSD: percent.sh,v 1.21 2025/04/08 23:10:46 djm Exp $
# Placed in the Public Domain.
tid="percent expansions"
@@ -29,6 +29,23 @@ trial()
somehost true
got=`cat $OBJ/actual`
;;
+ user|user-l|user-at)
+ if [ "$arg" = '%r' ] || [ "$arg" = '%C' ]; then
+ # User does not support %r, ie itself or %C. Skip test.
+ got="$expect"
+ elif [ "$i" = "user" ]; then
+ got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \
+ remuser@somehost | awk '$1=="'$opt'"{print $2}'`
+ elif [ "$i" = "user-l" ]; then
+ # Also test ssh -l
+ got=`${SSH} -F $OBJ/ssh_proxy -l "$arg" -G \
+ somehost | awk '$1=="'user'"{print $2}'`
+ elif [ "$i" = "user-at" ]; then
+ # Also test user@host
+ got=`${SSH} -F $OBJ/ssh_proxy -G "$arg@somehost" | \
+ awk '$1=="'user'"{print $2}'`
+ fi
+ ;;
userknownhostsfile)
# Move the userknownhosts file to what the expansion says,
# make sure ssh works then put it back.
@@ -51,6 +68,18 @@ trial()
remuser@somehost | awk '$1=="'$opt'"{print $2" "$3}'`
expect="/$expect /$expect"
;;
+ setenv)
+ # First make sure we don't expand variable names.
+ got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg=TESTVAL" -G \
+ remuser@somehost | awk '$1=="'$opt'"{print $2}'`
+ if [ "$got" != "$arg=TESTVAL" ]; then
+ fatal "incorrectly expanded setenv variable name"
+ fi
+ # Now check that the value expands as expected.
+ got=`${SSH} -F $OBJ/ssh_proxy -o $opt=TESTVAL="$arg" -G \
+ remuser@somehost | awk '$1=="'$opt'"{print $2}'`
+ got=`echo "$got" | sed 's/^TESTVAL=//'`
+ ;;
*)
got=`${SSH} -F $OBJ/ssh_proxy -o $opt="$arg" -G \
remuser@somehost | awk '$1=="'$opt'"{print $2}'`
@@ -62,7 +91,7 @@ trial()
for i in matchexec localcommand remotecommand controlpath identityagent \
forwardagent localforward remoteforward revokedhostkeys \
- userknownhostsfile; do
+ user user-l user-at setenv userknownhostsfile; do
verbose $tid $i percent
case "$i" in
localcommand|userknownhostsfile)
@@ -77,7 +106,7 @@ for i in matchexec localcommand remotecommand controlpath identityagent \
fi
# Matches implementation in readconf.c:ssh_connection_hash()
if [ ! -z "${OPENSSL_BIN}" ]; then
- HASH=`printf "${HOSTNAME}127.0.0.1${PORT}$REMUSER" |
+ HASH=`printf "${HOSTNAME}127.0.0.1${PORT}${REMUSER}" |
$OPENSSL_BIN sha1 | cut -f2 -d' '`
trial $i '%C' $HASH
fi
@@ -92,8 +121,9 @@ for i in matchexec localcommand remotecommand controlpath identityagent \
trial $i '%r' $REMUSER
trial $i '%u' $USER
# We can't specify a full path outside the regress dir, so skip tests
- # containing %d for UserKnownHostsFile
- if [ "$i" != "userknownhostsfile" ]; then
+ # containing %d for UserKnownHostsFile, and %r can't refer to itself.
+ if [ "$i" != "userknownhostsfile" ] && [ "$i" != "user" ] && \
+ [ "$i" != "user-l" ] && [ "$i" != "user-at" ]; then
trial $i '%d' $HOME
in='%%/%i/%h/%d/%L/%l/%n/%p/%r/%u'
out="%/$USERID/127.0.0.1/$HOME/$HOST/$HOSTNAME/somehost/$PORT/$REMUSER/$USER"
@@ -108,7 +138,7 @@ done
# Subset of above since we don't expand shell-style variables on anything that
# runs a command because the shell will expand those.
for i in controlpath identityagent forwardagent localforward remoteforward \
- userknownhostsfile; do
+ user user-l user-at setenv userknownhostsfile; do
verbose $tid $i dollar
FOO=bar
export FOO
diff --git a/crypto/openssh/regress/servcfginclude.sh b/crypto/openssh/regress/servcfginclude.sh
index 518a703d100e..f67c3caac626 100644
--- a/crypto/openssh/regress/servcfginclude.sh
+++ b/crypto/openssh/regress/servcfginclude.sh
@@ -4,14 +4,14 @@ tid="server config include"
cat > $OBJ/sshd_config.i << _EOF
HostKey $OBJ/host.ssh-ed25519
-Match host a
+Match host=a
Banner /aa
Match host b
Banner /bb
Include $OBJ/sshd_config.i.* # comment
-Match host c
+Match host=c
Include $OBJ/sshd_config.i.* # comment
Banner /cc
@@ -25,7 +25,7 @@ Match Host e
Banner /ee
Include $OBJ/sshd_config.i.*
-Match Host f
+Match Host=f
Include $OBJ/sshd_config.i.*
Banner /ff
@@ -47,13 +47,13 @@ Match host b
Match host c
Banner /ccc
-Match Host d
+Match Host=d
Banner /ddd
Match Host e
Banner /eee
-Match Host f
+Match Host=f
Banner /fff
_EOF
@@ -61,13 +61,13 @@ cat > $OBJ/sshd_config.i.2 << _EOF
Match host a
Banner /aaaa
-Match host b
+Match host=b
Banner /bbbb
Match host c # comment
Banner /cccc
-Match Host d
+Match Host=d
Banner /dddd
Match Host e
diff --git a/crypto/openssh/regress/sftp-resume.sh b/crypto/openssh/regress/sftp-resume.sh
new file mode 100644
index 000000000000..f4fe8f9281dc
--- /dev/null
+++ b/crypto/openssh/regress/sftp-resume.sh
@@ -0,0 +1,43 @@
+# $OpenBSD: sftp-resume.sh,v 1.2 2025/03/11 09:06:50 dtucker Exp $
+# Placed in the Public Domain.
+
+tid="sftp resume"
+
+CLIENT_LOG=${OBJ}/sftp.log
+
+# We test up to 1MB, ensure source data is large enough.
+increase_datafile_size 1200
+
+for cmd in put get; do
+ verbose "$tid: ${cmd}"
+ for size in 0 1 1k 1m size-1 same; do
+ trace "$tid: test ${cmd} ${size}"
+ rm -rf ${COPY}.1 ${COPY}.2
+ cp ${DATA} ${COPY}.1
+
+ # Set up requested source and destination file sizes.
+ case "${size}" in
+ 0) touch ${COPY}.2
+ ;;
+ size-1) dd if=${DATA} of=${COPY}.1 bs=1024 count=1 >/dev/null 2>&1
+ dd if=${DATA} of=${COPY}.2 bs=1023 count=1 >/dev/null 2>&1
+ ;;
+ same) cp ${DATA} ${COPY}.2
+ ;;
+ 1m) dd if=${COPY}.1 of=${COPY}.2 bs=1k count=1k >/dev/null 2<&1
+ ;;
+ *) dd if=${COPY}.1 of=${COPY}.2 bs=${size} count=1 >/dev/null 2>&1
+ ;;
+ esac
+
+ # Perform copy and check.
+ echo "${cmd} -a ${COPY}.1 ${COPY}.2" | \
+ ${SFTP} -D ${SFTPSERVER} -vvv >${CLIENT_LOG} 2>&1 \
+ || fail "${cmd} failed"
+ cmp ${COPY}.1 ${COPY}.2 || fail "corrupted copy after ${cmd} ${size}"
+ grep "reordered" ${CLIENT_LOG} >/dev/null && \
+ fail "server reordered requests ${cmd} ${size}"
+ done
+done
+
+rm -rf ${COPY}.1 ${COPY}.2
diff --git a/crypto/openssh/regress/sshfp-connect.sh b/crypto/openssh/regress/sshfp-connect.sh
index f78646922efe..3c73a35d05dd 100644
--- a/crypto/openssh/regress/sshfp-connect.sh
+++ b/crypto/openssh/regress/sshfp-connect.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: sshfp-connect.sh,v 1.4 2021/09/01 00:50:27 dtucker Exp $
+# $OpenBSD: sshfp-connect.sh,v 1.5 2025/03/11 11:46:44 dtucker Exp $
# Placed in the Public Domain.
# This test requires external setup and thus is skipped unless
@@ -29,6 +29,12 @@ if ! $SSH -Q key-plain | grep ssh-rsa >/dev/null; then
elif [ -z "${TEST_SSH_SSHFP_DOMAIN}" ]; then
skip "TEST_SSH_SSHFP_DOMAIN not set."
else
+ # Prime any DNS caches and resolvers.
+ for i in sshtest sshtest-sha1 sshtest-sha256; do
+ host -t sshfp ${i}.${TEST_SSH_SSHFP_DOMAIN} >/dev/null 2>&1
+ host -t sshfp ${i}-bad.${TEST_SSH_SSHFP_DOMAIN} >/dev/null 2>&1
+ done
+
# Set RSA host key to match fingerprints above.
mv $OBJ/sshd_proxy $OBJ/sshd_proxy.orig
$SUDO cp $SRC/rsa_openssh.prv $OBJ/host.ssh-rsa
diff --git a/crypto/openssh/regress/test-exec.sh b/crypto/openssh/regress/test-exec.sh
index 7afc2807299c..8a00c729cf67 100644
--- a/crypto/openssh/regress/test-exec.sh
+++ b/crypto/openssh/regress/test-exec.sh
@@ -1,4 +1,4 @@
-# $OpenBSD: test-exec.sh,v 1.119 2024/06/20 08:18:34 dtucker Exp $
+# $OpenBSD: test-exec.sh,v 1.127 2025/03/28 05:41:15 dtucker Exp $
# Placed in the Public Domain.
#SUDO=sudo
@@ -91,6 +91,7 @@ SSHKEYSCAN=ssh-keyscan
SFTP=sftp
SFTPSERVER=/usr/libexec/openssh/sftp-server
SSHD_SESSION=/usr/libexec/sshd-session
+SSHD_AUTH=/usr/libexec/sshd-auth
SCP=scp
# Set by make_tmpdir() on demand (below).
@@ -119,6 +120,9 @@ fi
if [ "x$TEST_SSH_SSHD_SESSION" != "x" ]; then
SSHD_SESSION="${TEST_SSH_SSHD_SESSION}"
fi
+if [ "x$TEST_SSH_SSHD_AUTH" != "x" ]; then
+ SSHD_AUTH="${TEST_SSH_SSHD_AUTH}"
+fi
if [ "x$TEST_SSH_SSHD" != "x" ]; then
SSHD="${TEST_SSH_SSHD}"
fi
@@ -180,6 +184,11 @@ case "$SSHD" in
*) SSHD=`which $SSHD` ;;
esac
+case "$SSH" in
+/*) ;;
+*) SSH=`which $SSH` ;;
+esac
+
case "$SSHAGENT" in
/*) ;;
*) SSHAGENT=`which $SSHAGENT` ;;
@@ -305,6 +314,7 @@ fi
# to preserve our debug logging. In the rare instance where -q is desirable
# -qq is equivalent and is not removed.
SSHLOGWRAP=$OBJ/ssh-log-wrapper.sh
+rm -f ${SSHLOGWRAP}
cat >$SSHLOGWRAP <<EOD
#!/bin/sh
timestamp="\`$OBJ/timestamp\`"
@@ -323,6 +333,7 @@ REAL_SSHD="$SSHD"
SSH="$SSHLOGWRAP"
SSHDLOGWRAP=$OBJ/sshd-log-wrapper.sh
+rm -f ${SSHDLOGWRAP}
cat >$SSHDLOGWRAP <<EOD
#!/bin/sh
timestamp="\`$OBJ/timestamp\`"
@@ -520,7 +531,7 @@ save_debug_log ()
for logfile in $TEST_SSH_LOGDIR $TEST_REGRESS_LOGFILE \
$TEST_SSH_LOGFILE $TEST_SSHD_LOGFILE; do
- if [ ! -z "$SUDO" ] && [ -f "$logfile" ]; then
+ if [ ! -z "$SUDO" ] && [ -e "$logfile" ]; then
$SUDO chown -R $USER $logfile
fi
done
@@ -621,6 +632,7 @@ cat << EOF > $OBJ/sshd_config
AcceptEnv _XXX_TEST
Subsystem sftp $SFTPSERVER
SshdSessionPath $SSHD_SESSION
+ SshdAuthPath $SSHD_AUTH
PerSourcePenalties no
EOF
@@ -845,7 +857,8 @@ esac
if test "$REGRESS_INTEROP_DROPBEAR" = "yes" ; then
trace Create dropbear keys and add to authorized_keys
- mkdir -p $OBJ/.dropbear
+ mkdir -p $OBJ/.dropbear $OBJ/.ssh
+ awk '{print "somehost "$2" "$3}' $OBJ/known_hosts >$OBJ/.ssh/known_hosts
kt="ed25519"
for i in dss rsa ecdsa; do
if $SSH -Q key-plain | grep "$i" >/dev/null; then
@@ -871,7 +884,7 @@ fi
# create a proxy version of the client config
(
cat $OBJ/ssh_config
- echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy
+ echo proxycommand ${SUDO} env SSH_SK_HELPER=\"$SSH_SK_HELPER\" ${TEST_SSH_SSHD_ENV} ${OBJ}/sshd-log-wrapper.sh -i -f $OBJ/sshd_proxy
) > $OBJ/ssh_proxy
# check proxy config
@@ -888,8 +901,9 @@ start_sshd ()
PIDFILE=$OBJ/pidfile
# start sshd
logfile="${TEST_SSH_LOGDIR}/sshd.`$OBJ/timestamp`.$$.log"
- $SUDO ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
- $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" \
+ $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" ${TEST_SSH_SSHD_ENV} \
+ ${SSHD} -f $OBJ/sshd_config "$@" -t || fatal "sshd_config broken"
+ $SUDO env SSH_SK_HELPER="$SSH_SK_HELPER" ${TEST_SSH_SSHD_ENV} \
${SSHD} -f $OBJ/sshd_config "$@" -E$TEST_SSHD_LOGFILE
trace "wait for sshd"
@@ -898,6 +912,7 @@ start_sshd ()
i=`expr $i + 1`
sleep $i
done
+ rm -f ${TEST_SSHD_LOGFILE}
ln -f -s ${logfile} $TEST_SSHD_LOGFILE
test -f $PIDFILE || fatal "no sshd running on port $PORT"
diff --git a/crypto/openssh/regress/unittests/authopt/Makefile b/crypto/openssh/regress/unittests/authopt/Makefile
new file mode 100644
index 000000000000..3045ec708165
--- /dev/null
+++ b/crypto/openssh/regress/unittests/authopt/Makefile
@@ -0,0 +1,27 @@
+# $OpenBSD: Makefile,v 1.7 2023/01/15 23:35:10 djm Exp $
+
+PROG=test_authopt
+SRCS=tests.c
+
+SRCS+=auth-options.c
+
+# From usr.bin/ssh
+SRCS+=sshbuf-getput-basic.c sshbuf-getput-crypto.c sshbuf-misc.c sshbuf.c
+SRCS+=sshbuf-io.c atomicio.c sshkey.c authfile.c cipher.c log.c ssh-rsa.c
+SRCS+=ssh-dss.c ssh-ecdsa.c ssh-ed25519.c mac.c umac.c umac128.c hmac.c misc.c
+SRCS+=ssherr.c uidswap.c cleanup.c xmalloc.c match.c krl.c fatal.c
+SRCS+=addr.c addrmatch.c bitmap.c
+SRCS+=ed25519.c hash.c
+SRCS+=cipher-chachapoly.c chacha.c poly1305.c ssh-ecdsa-sk.c ssh-sk.c
+SRCS+=ssh-ed25519-sk.c sk-usbhid.c
+
+SRCS+=digest-openssl.c
+#SRCS+=digest-libc.c
+SRCS+=utf8.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG} -d ${.CURDIR}/testdata
+
+.include <bsd.regress.mk>
diff --git a/crypto/openssh/regress/unittests/misc/Makefile b/crypto/openssh/regress/unittests/misc/Makefile
new file mode 100644
index 000000000000..d2be393ad703
--- /dev/null
+++ b/crypto/openssh/regress/unittests/misc/Makefile
@@ -0,0 +1,33 @@
+# $OpenBSD: Makefile,v 1.9 2023/01/06 02:59:50 djm Exp $
+
+PROG=test_misc
+SRCS=tests.c
+SRCS+= test_convtime.c
+SRCS+= test_expand.c
+SRCS+= test_parse.c
+SRCS+= test_argv.c
+SRCS+= test_strdelim.c
+SRCS+= test_hpdelim.c
+SRCS+= test_ptimeout.c
+
+# From usr.bin/ssh/Makefile.inc
+SRCS+= sshbuf.c
+SRCS+= sshbuf-getput-basic.c
+SRCS+= sshbuf-misc.c
+SRCS+= ssherr.c
+SRCS+= log.c
+SRCS+= xmalloc.c
+SRCS+= misc.c
+SRCS+= match.c
+SRCS+= addr.c
+SRCS+= addrmatch.c
+
+# From usr.bin/ssh/sshd/Makefile
+SRCS+= atomicio.c cleanup.c fatal.c
+
+REGRESS_TARGETS=run-regress-${PROG}
+
+run-regress-${PROG}: ${PROG}
+ env ${TEST_ENV} ./${PROG}
+
+.include <bsd.regress.mk>