118316Swollman#	$OpenBSD: cert-userkey.sh,v 1.16 2016/05/03 12:15:49 dtucker Exp $
218316Swollman#	Placed in the Public Domain.
318316Swollman
418316Swollmantid="certified user keys"
518316Swollman
618316Swollmanrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
718316Swollmancp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
818316Swollmancp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
918316Swollman
1018316SwollmanPLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
1118316Swollman
1218316Swollmanif echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
1318316Swollman	PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
1418316Swollmanfi
1518316Swollman
1618316Swollmankname() {
1718316Swollman	case $ktype in
1818316Swollman	rsa-sha2-*) ;;
1918316Swollman	# subshell because some seds will add a newline
2018316Swollman	*) n=$(echo $1 | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;;
2118316Swollman	esac
2218316Swollman	echo "$n*,ssh-rsa*,ssh-ed25519*"
2318316Swollman}
2418316Swollman
2518316Swollman# Create a CA key
2618316Swollman${SSHKEYGEN} -q -N '' -t rsa  -f $OBJ/user_ca_key ||\
2718316Swollman	fail "ssh-keygen of user_ca_key failed"
2846303Smarkm
2950476Speter# Generate and sign user keys
3018316Swollmanfor ktype in $PLAIN_TYPES $EXTRA_TYPES ; do
3118316Swollman	verbose "$tid: sign user ${ktype} cert"
3218316Swollman	${SSHKEYGEN} -q -N '' -t ${ktype} \
3318316Swollman	    -f $OBJ/cert_user_key_${ktype} || \
3418316Swollman		fatal "ssh-keygen of cert_user_key_${ktype} failed"
3518316Swollman	# Generate RSA/SHA2 certs for rsa-sha2* keys.
3646303Smarkm	case $ktype in
3718316Swollman	rsa-sha2-*)	tflag="-t $ktype" ;;
3818316Swollman	*)		tflag="" ;;
39126250Sbms	esac
4046303Smarkm	${SSHKEYGEN} -q -s $OBJ/user_ca_key -z $$ \
41126250Sbms	    -I "regress user key for $USER" \
42126250Sbms	    -n ${USER},mekmitasdigoat $tflag $OBJ/cert_user_key_${ktype} || \
43126250Sbms		fatal "couldn't sign cert_user_key_${ktype}"
44126250Sbmsdone
45126250Sbms
4646303Smarkm# Test explicitly-specified principals
4746303Smarkmfor ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
4846303Smarkm	t=$(kname $ktype)
4918316Swollman	for privsep in yes no ; do
50102231Strhodes		_prefix="${ktype} privsep $privsep"
5118316Swollman
5218316Swollman		# Setup for AuthorizedPrincipalsFile
5318316Swollman		rm -f $OBJ/authorized_keys_$USER
5418316Swollman		(
5518316Swollman			cat $OBJ/sshd_proxy_bak
5620339Swollman			echo "UsePrivilegeSeparation $privsep"
5781604Speter			echo "AuthorizedPrincipalsFile " \
5846303Smarkm			    "$OBJ/authorized_principals_%u"
59118582Simp			echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
60118582Simp			echo "PubkeyAcceptedKeyTypes ${t}"
6120339Swollman		) > $OBJ/sshd_proxy
6218316Swollman		(
6318316Swollman			cat $OBJ/ssh_proxy_bak
6446303Smarkm			echo "PubkeyAcceptedKeyTypes ${t}"
6518316Swollman		) > $OBJ/ssh_proxy
6618316Swollman
6719880Swollman		# Missing authorized_principals
6819880Swollman		verbose "$tid: ${_prefix} missing authorized_principals"
6919880Swollman		rm -f $OBJ/authorized_principals_$USER
7019880Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
7119880Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
7219880Swollman		if [ $? -eq 0 ]; then
7319880Swollman			fail "ssh cert connect succeeded unexpectedly"
7419880Swollman		fi
7519880Swollman
7619880Swollman		# Empty authorized_principals
7719880Swollman		verbose "$tid: ${_prefix} empty authorized_principals"
7819880Swollman		echo > $OBJ/authorized_principals_$USER
7919880Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
8019880Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
8119880Swollman		if [ $? -eq 0 ]; then
8219880Swollman			fail "ssh cert connect succeeded unexpectedly"
8319880Swollman		fi
8419880Swollman
8519880Swollman		# Wrong authorized_principals
8619880Swollman		verbose "$tid: ${_prefix} wrong authorized_principals"
8719880Swollman		echo gregorsamsa > $OBJ/authorized_principals_$USER
8819880Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
8919880Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
9019880Swollman		if [ $? -eq 0 ]; then
9119880Swollman			fail "ssh cert connect succeeded unexpectedly"
9219880Swollman		fi
9319880Swollman
9419880Swollman		# Correct authorized_principals
9519880Swollman		verbose "$tid: ${_prefix} correct authorized_principals"
9619880Swollman		echo mekmitasdigoat > $OBJ/authorized_principals_$USER
9719880Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
9819880Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
9919880Swollman		if [ $? -ne 0 ]; then
10019880Swollman			fail "ssh cert connect failed"
10119880Swollman		fi
10219880Swollman
10319880Swollman		# authorized_principals with bad key option
10419880Swollman		verbose "$tid: ${_prefix} authorized_principals bad key opt"
10519880Swollman		echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
10619880Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
10719880Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
10819880Swollman		if [ $? -eq 0 ]; then
10919880Swollman			fail "ssh cert connect succeeded unexpectedly"
11019880Swollman		fi
11119880Swollman
11219880Swollman		# authorized_principals with command=false
11319880Swollman		verbose "$tid: ${_prefix} authorized_principals command=false"
11419880Swollman		echo 'command="false" mekmitasdigoat' > \
11519880Swollman		    $OBJ/authorized_principals_$USER
11619880Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
11719880Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
11819880Swollman		if [ $? -eq 0 ]; then
11919880Swollman			fail "ssh cert connect succeeded unexpectedly"
12018316Swollman		fi
12118316Swollman
12218316Swollman
12318316Swollman		# authorized_principals with command=true
12418316Swollman		verbose "$tid: ${_prefix} authorized_principals command=true"
12518316Swollman		echo 'command="true" mekmitasdigoat' > \
12618316Swollman		    $OBJ/authorized_principals_$USER
12718316Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
12818316Swollman		    -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
12918316Swollman		if [ $? -ne 0 ]; then
13018316Swollman			fail "ssh cert connect failed"
13118316Swollman		fi
13218316Swollman
13318316Swollman		# Setup for principals= key option
13418316Swollman		rm -f $OBJ/authorized_principals_$USER
13518316Swollman		(
13618316Swollman			cat $OBJ/sshd_proxy_bak
13718316Swollman			echo "UsePrivilegeSeparation $privsep"
13818316Swollman			echo "PubkeyAcceptedKeyTypes ${t}"
13918316Swollman		) > $OBJ/sshd_proxy
14018316Swollman		(
14146303Smarkm			cat $OBJ/ssh_proxy_bak
14218316Swollman			echo "PubkeyAcceptedKeyTypes ${t}"
14318316Swollman		) > $OBJ/ssh_proxy
14418316Swollman
14518316Swollman		# Wrong principals list
14618316Swollman		verbose "$tid: ${_prefix} wrong principals key option"
14718316Swollman		(
14818316Swollman			printf 'cert-authority,principals="gregorsamsa" '
14918316Swollman			cat $OBJ/user_ca_key.pub
15018316Swollman		) > $OBJ/authorized_keys_$USER
15118316Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
15218316Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
15318316Swollman		if [ $? -eq 0 ]; then
15418316Swollman			fail "ssh cert connect succeeded unexpectedly"
15518316Swollman		fi
15646303Smarkm
15718316Swollman		# Correct principals list
15818316Swollman		verbose "$tid: ${_prefix} correct principals key option"
15918316Swollman		(
16018316Swollman			printf 'cert-authority,principals="mekmitasdigoat" '
16118316Swollman			cat $OBJ/user_ca_key.pub
16218316Swollman		) > $OBJ/authorized_keys_$USER
16318316Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} \
16418316Swollman		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
16518316Swollman		if [ $? -ne 0 ]; then
16618316Swollman			fail "ssh cert connect failed"
16720339Swollman		fi
16820339Swollman	done
16918316Swollmandone
17018316Swollman
17118316Swollmanbasic_tests() {
17220339Swollman	auth=$1
17320339Swollman	if test "x$auth" = "xauthorized_keys" ; then
17418316Swollman		# Add CA to authorized_keys
17520339Swollman		(
17618316Swollman			printf 'cert-authority '
17718316Swollman			cat $OBJ/user_ca_key.pub
17818316Swollman		) > $OBJ/authorized_keys_$USER
17918316Swollman	else
18018316Swollman		echo > $OBJ/authorized_keys_$USER
18146303Smarkm		extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
18218316Swollman	fi
18318316Swollman
18418316Swollman	for ktype in $PLAIN_TYPES ; do
18518316Swollman		t=$(kname $ktype)
18618316Swollman		for privsep in yes no ; do
18718316Swollman			_prefix="${ktype} privsep $privsep $auth"
18818316Swollman			# Simple connect
189126250Sbms			verbose "$tid: ${_prefix} connect"
19046303Smarkm			(
19118316Swollman				cat $OBJ/sshd_proxy_bak
19218316Swollman				echo "UsePrivilegeSeparation $privsep"
19318316Swollman				echo "PubkeyAcceptedKeyTypes ${t}"
19418316Swollman				echo "$extra_sshd"
19518316Swollman			) > $OBJ/sshd_proxy
19646303Smarkm			(
19746303Smarkm				cat $OBJ/ssh_proxy_bak
19818316Swollman				echo "PubkeyAcceptedKeyTypes ${t}"
19918316Swollman			) > $OBJ/ssh_proxy
20018316Swollman
20118316Swollman			${SSH} -2i $OBJ/cert_user_key_${ktype} \
20218316Swollman			    -F $OBJ/ssh_proxy somehost true
20318316Swollman			if [ $? -ne 0 ]; then
20418316Swollman				fail "ssh cert connect failed"
20546303Smarkm			fi
20620339Swollman
20720339Swollman			# Revoked keys
20820339Swollman			verbose "$tid: ${_prefix} revoked key"
20918316Swollman			(
21046303Smarkm				cat $OBJ/sshd_proxy_bak
21146303Smarkm				echo "UsePrivilegeSeparation $privsep"
21246303Smarkm				echo "RevokedKeys $OBJ/cert_user_key_revoked"
21346303Smarkm				echo "PubkeyAcceptedKeyTypes ${t}"
21446303Smarkm				echo "$extra_sshd"
21546303Smarkm			) > $OBJ/sshd_proxy
21618316Swollman			cp $OBJ/cert_user_key_${ktype}.pub \
21718316Swollman			    $OBJ/cert_user_key_revoked
21820339Swollman			${SSH} -2i $OBJ/cert_user_key_${ktype} \
21918316Swollman			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
22018316Swollman			if [ $? -eq 0 ]; then
22118316Swollman				fail "ssh cert connect succeeded unexpecedly"
22218316Swollman			fi
22318316Swollman			verbose "$tid: ${_prefix} revoked via KRL"
22418316Swollman			rm $OBJ/cert_user_key_revoked
22518316Swollman			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
22618316Swollman			    $OBJ/cert_user_key_${ktype}.pub
22718316Swollman			${SSH} -2i $OBJ/cert_user_key_${ktype} \
22846303Smarkm			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
22918316Swollman			if [ $? -eq 0 ]; then
23018316Swollman				fail "ssh cert connect succeeded unexpecedly"
23118316Swollman			fi
23218316Swollman			verbose "$tid: ${_prefix} empty KRL"
23318316Swollman			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
23446303Smarkm			${SSH} -2i $OBJ/cert_user_key_${ktype} \
23518316Swollman			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
23618316Swollman			if [ $? -ne 0 ]; then
23718316Swollman				fail "ssh cert connect failed"
23818316Swollman			fi
23918316Swollman		done
24018316Swollman
24118316Swollman		# Revoked CA
24218316Swollman		verbose "$tid: ${ktype} $auth revoked CA key"
243126250Sbms		(
24446303Smarkm			cat $OBJ/sshd_proxy_bak
24518316Swollman			echo "RevokedKeys $OBJ/user_ca_key.pub"
24646303Smarkm			echo "PubkeyAcceptedKeyTypes ${t}"
24718316Swollman			echo "$extra_sshd"
24818316Swollman		) > $OBJ/sshd_proxy
24918316Swollman		${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
25018316Swollman		    somehost true >/dev/null 2>&1
25118316Swollman		if [ $? -eq 0 ]; then
25220339Swollman			fail "ssh cert connect succeeded unexpecedly"
25320339Swollman		fi
25418316Swollman	done
25546303Smarkm
25620339Swollman	verbose "$tid: $auth CA does not authenticate"
25718316Swollman	(
25846303Smarkm		cat $OBJ/sshd_proxy_bak
25920339Swollman		echo "PubkeyAcceptedKeyTypes ${t}"
26020339Swollman		echo "$extra_sshd"
26120339Swollman	) > $OBJ/sshd_proxy
26220339Swollman	verbose "$tid: ensure CA key does not authenticate user"
26320339Swollman	${SSH} -2i $OBJ/user_ca_key \
26446303Smarkm	    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
26520339Swollman	if [ $? -eq 0 ]; then
26620339Swollman		fail "ssh cert connect with CA key succeeded unexpectedly"
26720339Swollman	fi
26820339Swollman}
26920339Swollman
27020339Swollmanbasic_tests authorized_keys
27120339Swollmanbasic_tests TrustedUserCAKeys
27220339Swollman
27320339Swollmantest_one() {
27420339Swollman	ident=$1
27520339Swollman	result=$2
27620339Swollman	sign_opts=$3
27720339Swollman	auth_choice=$4
27820339Swollman	auth_opt=$5
27920339Swollman
28020339Swollman	if test "x$auth_choice" = "x" ; then
28120339Swollman		auth_choice="authorized_keys TrustedUserCAKeys"
28220339Swollman	fi
28320339Swollman
28420339Swollman	for auth in $auth_choice ; do
28520339Swollman		for ktype in rsa ed25519 ; do
28620339Swollman			cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
28720339Swollman			if test "x$auth" = "xauthorized_keys" ; then
28820339Swollman				# Add CA to authorized_keys
28920339Swollman				(
29020339Swollman					printf "cert-authority${auth_opt} "
29120339Swollman					cat $OBJ/user_ca_key.pub
29220339Swollman				) > $OBJ/authorized_keys_$USER
29320339Swollman			else
29420339Swollman				echo > $OBJ/authorized_keys_$USER
29520339Swollman				echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
29620339Swollman				    >> $OBJ/sshd_proxy
29720339Swollman				echo "PubkeyAcceptedKeyTypes ${t}*" \
29820339Swollman				    >> $OBJ/sshd_proxy
29946303Smarkm				if test "x$auth_opt" != "x" ; then
30046303Smarkm					echo $auth_opt >> $OBJ/sshd_proxy
30120339Swollman				fi
30220339Swollman			fi
30318316Swollman
30418316Swollman			verbose "$tid: $ident auth $auth expect $result $ktype"
30546303Smarkm			${SSHKEYGEN} -q -s $OBJ/user_ca_key \
30618316Swollman			    -I "regress user key for $USER" \
30718316Swollman			    $sign_opts $OBJ/cert_user_key_${ktype} ||
30820339Swollman				fail "couldn't sign cert_user_key_${ktype}"
30920339Swollman
31020339Swollman			${SSH} -2i $OBJ/cert_user_key_${ktype} \
31118316Swollman			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
31220339Swollman			rc=$?
31320339Swollman			if [ "x$result" = "xsuccess" ] ; then
31420339Swollman				if [ $rc -ne 0 ]; then
31520339Swollman					fail "$ident failed unexpectedly"
31620339Swollman				fi
31720339Swollman			else
31820339Swollman				if [ $rc -eq 0 ]; then
31920339Swollman					fail "$ident succeeded unexpectedly"
32020339Swollman				fi
32120339Swollman			fi
32218316Swollman		done
32318316Swollman	done
32418316Swollman}
32518316Swollman
32618316Swollmantest_one "correct principal"	success "-n ${USER}"
32718316Swollmantest_one "host-certificate"	failure "-n ${USER} -h"
32818316Swollmantest_one "wrong principals"	failure "-n foo"
32920339Swollmantest_one "cert not yet valid"	failure "-n ${USER} -V20200101:20300101"
33020339Swollmantest_one "cert expired"		failure "-n ${USER} -V19800101:19900101"
33120339Swollmantest_one "cert valid interval"	success "-n ${USER} -V-1w:+2w"
33220339Swollmantest_one "wrong source-address"	failure "-n ${USER} -Osource-address=10.0.0.0/8"
33320339Swollmantest_one "force-command"	failure "-n ${USER} -Oforce-command=false"
33420339Swollman
33520339Swollman# Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
33620339Swollmantest_one "empty principals"	success "" authorized_keys
33720339Swollmantest_one "empty principals"	failure "" TrustedUserCAKeys
33820339Swollman
33920339Swollman# Check explicitly-specified principals: an empty principals list in the cert
34020339Swollman# should always be refused.
34120339Swollman
34220339Swollman# AuthorizedPrincipalsFile
34320339Swollmanrm -f $OBJ/authorized_keys_$USER
34420339Swollmanecho mekmitasdigoat > $OBJ/authorized_principals_$USER
34520339Swollmantest_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
34620339Swollman    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
34746303Smarkmtest_one "AuthorizedPrincipalsFile no principals" failure "" \
34818316Swollman    TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
34918316Swollman
35018316Swollman# principals= key option
35118316Swollmanrm -f $OBJ/authorized_principals_$USER
35218316Swollmantest_one "principals key option principals" success "-n mekmitasdigoat" \
35320339Swollman    authorized_keys ',principals="mekmitasdigoat"'
35420339Swollmantest_one "principals key option no principals" failure "" \
35520339Swollman    authorized_keys ',principals="mekmitasdigoat"'
35620339Swollman
35720339Swollman# Wrong certificate
35820339Swollmancat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
35920339Swollmanfor ktype in $PLAIN_TYPES ; do
36020339Swollman	t=$(kname $ktype)
36120339Swollman	# Self-sign
36220339Swollman	${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \
36318316Swollman	    "regress user key for $USER" \
36418316Swollman	    -n $USER $OBJ/cert_user_key_${ktype} ||
36518316Swollman		fatal "couldn't sign cert_user_key_${ktype}"
36646303Smarkm	verbose "$tid: user ${ktype} connect wrong cert"
36718316Swollman	${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
36846303Smarkm	    somehost true >/dev/null 2>&1
36918316Swollman	if [ $? -eq 0 ]; then
37020339Swollman		fail "ssh cert connect $ident succeeded unexpectedly"
37120339Swollman	fi
37220339Swollmandone
37318316Swollman
37420339Swollmanrm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
37520339Swollmanrm -f $OBJ/authorized_principals_$USER
37620339Swollman
37720339Swollman