Home | History | Annotate | Download | only in regress
      1 #	$OpenBSD: cert-userkey.sh,v 1.17 2016/11/30 03:01:33 djm Exp $
      2 #	Placed in the Public Domain.
      3 
      4 tid="certified user keys"
      5 
      6 rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
      7 cp $OBJ/sshd_proxy $OBJ/sshd_proxy_bak
      8 cp $OBJ/ssh_proxy $OBJ/ssh_proxy_bak
      9 
     10 PLAIN_TYPES=`$SSH -Q key-plain | sed 's/^ssh-dss/ssh-dsa/;s/^ssh-//'`
     11 
     12 if echo "$PLAIN_TYPES" | grep '^rsa$' >/dev/null 2>&1 ; then
     13 	PLAIN_TYPES="$PLAIN_TYPES rsa-sha2-256 rsa-sha2-512"
     14 fi
     15 
     16 kname() {
     17 	case $ktype in
     18 	rsa-sha2-*) ;;
     19 	# subshell because some seds will add a newline
     20 	*) n=$(echo $1 | sed 's/^dsa/ssh-dss/;s/^rsa/ssh-rsa/;s/^ed/ssh-ed/') ;;
     21 	esac
     22 	echo "$n*,ssh-rsa*,ssh-ed25519*"
     23 }
     24 
     25 # Create a CA key
     26 ${SSHKEYGEN} -q -N '' -t rsa  -f $OBJ/user_ca_key ||\
     27 	fail "ssh-keygen of user_ca_key failed"
     28 
     29 # Generate and sign user keys
     30 for ktype in $PLAIN_TYPES $EXTRA_TYPES ; do
     31 	verbose "$tid: sign user ${ktype} cert"
     32 	${SSHKEYGEN} -q -N '' -t ${ktype} \
     33 	    -f $OBJ/cert_user_key_${ktype} || \
     34 		fatal "ssh-keygen of cert_user_key_${ktype} failed"
     35 	# Generate RSA/SHA2 certs for rsa-sha2* keys.
     36 	case $ktype in
     37 	rsa-sha2-*)	tflag="-t $ktype" ;;
     38 	*)		tflag="" ;;
     39 	esac
     40 	${SSHKEYGEN} -q -s $OBJ/user_ca_key -z $$ \
     41 	    -I "regress user key for $USER" \
     42 	    -n ${USER},mekmitasdigoat $tflag $OBJ/cert_user_key_${ktype} || \
     43 		fatal "couldn't sign cert_user_key_${ktype}"
     44 done
     45 
     46 # Test explicitly-specified principals
     47 for ktype in $EXTRA_TYPES $PLAIN_TYPES ; do
     48 	t=$(kname $ktype)
     49 	for privsep in yes no ; do
     50 		_prefix="${ktype} privsep $privsep"
     51 
     52 		# Setup for AuthorizedPrincipalsFile
     53 		rm -f $OBJ/authorized_keys_$USER
     54 		(
     55 			cat $OBJ/sshd_proxy_bak
     56 			echo "UsePrivilegeSeparation $privsep"
     57 			echo "AuthorizedPrincipalsFile " \
     58 			    "$OBJ/authorized_principals_%u"
     59 			echo "TrustedUserCAKeys $OBJ/user_ca_key.pub"
     60 			echo "PubkeyAcceptedKeyTypes ${t}"
     61 		) > $OBJ/sshd_proxy
     62 		(
     63 			cat $OBJ/ssh_proxy_bak
     64 			echo "PubkeyAcceptedKeyTypes ${t}"
     65 		) > $OBJ/ssh_proxy
     66 
     67 		# Missing authorized_principals
     68 		verbose "$tid: ${_prefix} missing authorized_principals"
     69 		rm -f $OBJ/authorized_principals_$USER
     70 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
     71 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
     72 		if [ $? -eq 0 ]; then
     73 			fail "ssh cert connect succeeded unexpectedly"
     74 		fi
     75 
     76 		# Empty authorized_principals
     77 		verbose "$tid: ${_prefix} empty authorized_principals"
     78 		echo > $OBJ/authorized_principals_$USER
     79 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
     80 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
     81 		if [ $? -eq 0 ]; then
     82 			fail "ssh cert connect succeeded unexpectedly"
     83 		fi
     84 
     85 		# Wrong authorized_principals
     86 		verbose "$tid: ${_prefix} wrong authorized_principals"
     87 		echo gregorsamsa > $OBJ/authorized_principals_$USER
     88 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
     89 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
     90 		if [ $? -eq 0 ]; then
     91 			fail "ssh cert connect succeeded unexpectedly"
     92 		fi
     93 
     94 		# Correct authorized_principals
     95 		verbose "$tid: ${_prefix} correct authorized_principals"
     96 		echo mekmitasdigoat > $OBJ/authorized_principals_$USER
     97 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
     98 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
     99 		if [ $? -ne 0 ]; then
    100 			fail "ssh cert connect failed"
    101 		fi
    102 
    103 		# authorized_principals with bad key option
    104 		verbose "$tid: ${_prefix} authorized_principals bad key opt"
    105 		echo 'blah mekmitasdigoat' > $OBJ/authorized_principals_$USER
    106 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
    107 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    108 		if [ $? -eq 0 ]; then
    109 			fail "ssh cert connect succeeded unexpectedly"
    110 		fi
    111 
    112 		# authorized_principals with command=false
    113 		verbose "$tid: ${_prefix} authorized_principals command=false"
    114 		echo 'command="false" mekmitasdigoat' > \
    115 		    $OBJ/authorized_principals_$USER
    116 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
    117 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    118 		if [ $? -eq 0 ]; then
    119 			fail "ssh cert connect succeeded unexpectedly"
    120 		fi
    121 
    122 
    123 		# authorized_principals with command=true
    124 		verbose "$tid: ${_prefix} authorized_principals command=true"
    125 		echo 'command="true" mekmitasdigoat' > \
    126 		    $OBJ/authorized_principals_$USER
    127 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
    128 		    -F $OBJ/ssh_proxy somehost false >/dev/null 2>&1
    129 		if [ $? -ne 0 ]; then
    130 			fail "ssh cert connect failed"
    131 		fi
    132 
    133 		# Setup for principals= key option
    134 		rm -f $OBJ/authorized_principals_$USER
    135 		(
    136 			cat $OBJ/sshd_proxy_bak
    137 			echo "UsePrivilegeSeparation $privsep"
    138 			echo "PubkeyAcceptedKeyTypes ${t}"
    139 		) > $OBJ/sshd_proxy
    140 		(
    141 			cat $OBJ/ssh_proxy_bak
    142 			echo "PubkeyAcceptedKeyTypes ${t}"
    143 		) > $OBJ/ssh_proxy
    144 
    145 		# Wrong principals list
    146 		verbose "$tid: ${_prefix} wrong principals key option"
    147 		(
    148 			printf 'cert-authority,principals="gregorsamsa" '
    149 			cat $OBJ/user_ca_key.pub
    150 		) > $OBJ/authorized_keys_$USER
    151 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
    152 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    153 		if [ $? -eq 0 ]; then
    154 			fail "ssh cert connect succeeded unexpectedly"
    155 		fi
    156 
    157 		# Correct principals list
    158 		verbose "$tid: ${_prefix} correct principals key option"
    159 		(
    160 			printf 'cert-authority,principals="mekmitasdigoat" '
    161 			cat $OBJ/user_ca_key.pub
    162 		) > $OBJ/authorized_keys_$USER
    163 		${SSH} -2i $OBJ/cert_user_key_${ktype} \
    164 		    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    165 		if [ $? -ne 0 ]; then
    166 			fail "ssh cert connect failed"
    167 		fi
    168 	done
    169 done
    170 
    171 basic_tests() {
    172 	auth=$1
    173 	if test "x$auth" = "xauthorized_keys" ; then
    174 		# Add CA to authorized_keys
    175 		(
    176 			printf 'cert-authority '
    177 			cat $OBJ/user_ca_key.pub
    178 		) > $OBJ/authorized_keys_$USER
    179 	else
    180 		echo > $OBJ/authorized_keys_$USER
    181 		extra_sshd="TrustedUserCAKeys $OBJ/user_ca_key.pub"
    182 	fi
    183 
    184 	for ktype in $PLAIN_TYPES ; do
    185 		t=$(kname $ktype)
    186 		for privsep in yes no ; do
    187 			_prefix="${ktype} privsep $privsep $auth"
    188 			# Simple connect
    189 			verbose "$tid: ${_prefix} connect"
    190 			(
    191 				cat $OBJ/sshd_proxy_bak
    192 				echo "UsePrivilegeSeparation $privsep"
    193 				echo "PubkeyAcceptedKeyTypes ${t}"
    194 				echo "$extra_sshd"
    195 			) > $OBJ/sshd_proxy
    196 			(
    197 				cat $OBJ/ssh_proxy_bak
    198 				echo "PubkeyAcceptedKeyTypes ${t}"
    199 			) > $OBJ/ssh_proxy
    200 
    201 			${SSH} -2i $OBJ/cert_user_key_${ktype} \
    202 			    -F $OBJ/ssh_proxy somehost true
    203 			if [ $? -ne 0 ]; then
    204 				fail "ssh cert connect failed"
    205 			fi
    206 
    207 			# Revoked keys
    208 			verbose "$tid: ${_prefix} revoked key"
    209 			(
    210 				cat $OBJ/sshd_proxy_bak
    211 				echo "UsePrivilegeSeparation $privsep"
    212 				echo "RevokedKeys $OBJ/cert_user_key_revoked"
    213 				echo "PubkeyAcceptedKeyTypes ${t}"
    214 				echo "$extra_sshd"
    215 			) > $OBJ/sshd_proxy
    216 			cp $OBJ/cert_user_key_${ktype}.pub \
    217 			    $OBJ/cert_user_key_revoked
    218 			${SSH} -2i $OBJ/cert_user_key_${ktype} \
    219 			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    220 			if [ $? -eq 0 ]; then
    221 				fail "ssh cert connect succeeded unexpecedly"
    222 			fi
    223 			verbose "$tid: ${_prefix} revoked via KRL"
    224 			rm $OBJ/cert_user_key_revoked
    225 			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked \
    226 			    $OBJ/cert_user_key_${ktype}.pub
    227 			${SSH} -2i $OBJ/cert_user_key_${ktype} \
    228 			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    229 			if [ $? -eq 0 ]; then
    230 				fail "ssh cert connect succeeded unexpecedly"
    231 			fi
    232 			verbose "$tid: ${_prefix} empty KRL"
    233 			${SSHKEYGEN} -kqf $OBJ/cert_user_key_revoked
    234 			${SSH} -2i $OBJ/cert_user_key_${ktype} \
    235 			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    236 			if [ $? -ne 0 ]; then
    237 				fail "ssh cert connect failed"
    238 			fi
    239 		done
    240 
    241 		# Revoked CA
    242 		verbose "$tid: ${ktype} $auth revoked CA key"
    243 		(
    244 			cat $OBJ/sshd_proxy_bak
    245 			echo "RevokedKeys $OBJ/user_ca_key.pub"
    246 			echo "PubkeyAcceptedKeyTypes ${t}"
    247 			echo "$extra_sshd"
    248 		) > $OBJ/sshd_proxy
    249 		${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
    250 		    somehost true >/dev/null 2>&1
    251 		if [ $? -eq 0 ]; then
    252 			fail "ssh cert connect succeeded unexpecedly"
    253 		fi
    254 	done
    255 
    256 	verbose "$tid: $auth CA does not authenticate"
    257 	(
    258 		cat $OBJ/sshd_proxy_bak
    259 		echo "PubkeyAcceptedKeyTypes ${t}"
    260 		echo "$extra_sshd"
    261 	) > $OBJ/sshd_proxy
    262 	verbose "$tid: ensure CA key does not authenticate user"
    263 	${SSH} -2i $OBJ/user_ca_key \
    264 	    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    265 	if [ $? -eq 0 ]; then
    266 		fail "ssh cert connect with CA key succeeded unexpectedly"
    267 	fi
    268 }
    269 
    270 basic_tests authorized_keys
    271 basic_tests TrustedUserCAKeys
    272 
    273 test_one() {
    274 	ident=$1
    275 	result=$2
    276 	sign_opts=$3
    277 	auth_choice=$4
    278 	auth_opt=$5
    279 
    280 	if test "x$auth_choice" = "x" ; then
    281 		auth_choice="authorized_keys TrustedUserCAKeys"
    282 	fi
    283 
    284 	for auth in $auth_choice ; do
    285 		for ktype in rsa ed25519 ; do
    286 			cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
    287 			if test "x$auth" = "xauthorized_keys" ; then
    288 				# Add CA to authorized_keys
    289 				(
    290 					printf "cert-authority${auth_opt} "
    291 					cat $OBJ/user_ca_key.pub
    292 				) > $OBJ/authorized_keys_$USER
    293 			else
    294 				echo > $OBJ/authorized_keys_$USER
    295 				echo "TrustedUserCAKeys $OBJ/user_ca_key.pub" \
    296 				    >> $OBJ/sshd_proxy
    297 				echo "PubkeyAcceptedKeyTypes ${t}*" \
    298 				    >> $OBJ/sshd_proxy
    299 				if test "x$auth_opt" != "x" ; then
    300 					echo $auth_opt >> $OBJ/sshd_proxy
    301 				fi
    302 			fi
    303 
    304 			verbose "$tid: $ident auth $auth expect $result $ktype"
    305 			${SSHKEYGEN} -q -s $OBJ/user_ca_key \
    306 			    -I "regress user key for $USER" \
    307 			    $sign_opts $OBJ/cert_user_key_${ktype} ||
    308 				fail "couldn't sign cert_user_key_${ktype}"
    309 
    310 			${SSH} -2i $OBJ/cert_user_key_${ktype} \
    311 			    -F $OBJ/ssh_proxy somehost true >/dev/null 2>&1
    312 			rc=$?
    313 			if [ "x$result" = "xsuccess" ] ; then
    314 				if [ $rc -ne 0 ]; then
    315 					fail "$ident failed unexpectedly"
    316 				fi
    317 			else
    318 				if [ $rc -eq 0 ]; then
    319 					fail "$ident succeeded unexpectedly"
    320 				fi
    321 			fi
    322 		done
    323 	done
    324 }
    325 
    326 test_one "correct principal"	success "-n ${USER}"
    327 test_one "host-certificate"	failure "-n ${USER} -h"
    328 test_one "wrong principals"	failure "-n foo"
    329 test_one "cert not yet valid"	failure "-n ${USER} -V20200101:20300101"
    330 test_one "cert expired"		failure "-n ${USER} -V19800101:19900101"
    331 test_one "cert valid interval"	success "-n ${USER} -V-1w:+2w"
    332 test_one "wrong source-address"	failure "-n ${USER} -Osource-address=10.0.0.0/8"
    333 test_one "force-command"	failure "-n ${USER} -Oforce-command=false"
    334 
    335 # Behaviour is different here: TrustedUserCAKeys doesn't allow empty principals
    336 test_one "empty principals"	success "" authorized_keys
    337 test_one "empty principals"	failure "" TrustedUserCAKeys
    338 
    339 # Check explicitly-specified principals: an empty principals list in the cert
    340 # should always be refused.
    341 
    342 # AuthorizedPrincipalsFile
    343 rm -f $OBJ/authorized_keys_$USER
    344 echo mekmitasdigoat > $OBJ/authorized_principals_$USER
    345 test_one "AuthorizedPrincipalsFile principals" success "-n mekmitasdigoat" \
    346     TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
    347 test_one "AuthorizedPrincipalsFile no principals" failure "" \
    348     TrustedUserCAKeys "AuthorizedPrincipalsFile $OBJ/authorized_principals_%u"
    349 
    350 # principals= key option
    351 rm -f $OBJ/authorized_principals_$USER
    352 test_one "principals key option principals" success "-n mekmitasdigoat" \
    353     authorized_keys ',principals="mekmitasdigoat"'
    354 test_one "principals key option no principals" failure "" \
    355     authorized_keys ',principals="mekmitasdigoat"'
    356 
    357 # command= options vs. force-command in key
    358 test_one "force-command match true" success \
    359     "-n ${USER} -Oforce-command=true" \
    360     authorized_keys ',command="true"'
    361 test_one "force-command match true" failure \
    362     "-n ${USER} -Oforce-command=false" \
    363     authorized_keys ',command="false"'
    364 test_one "force-command mismatch 1" failure \
    365     "-n ${USER} -Oforce-command=false" \
    366     authorized_keys ',command="true"'
    367 test_one "force-command mismatch 2" failure \
    368     "-n ${USER} -Oforce-command=true" \
    369     authorized_keys ',command="false"'
    370 
    371 # Wrong certificate
    372 cat $OBJ/sshd_proxy_bak > $OBJ/sshd_proxy
    373 for ktype in $PLAIN_TYPES ; do
    374 	t=$(kname $ktype)
    375 	# Self-sign
    376 	${SSHKEYGEN} -q -s $OBJ/cert_user_key_${ktype} -I \
    377 	    "regress user key for $USER" \
    378 	    -n $USER $OBJ/cert_user_key_${ktype} ||
    379 		fatal "couldn't sign cert_user_key_${ktype}"
    380 	verbose "$tid: user ${ktype} connect wrong cert"
    381 	${SSH} -2i $OBJ/cert_user_key_${ktype} -F $OBJ/ssh_proxy \
    382 	    somehost true >/dev/null 2>&1
    383 	if [ $? -eq 0 ]; then
    384 		fail "ssh cert connect $ident succeeded unexpectedly"
    385 	fi
    386 done
    387 
    388 rm -f $OBJ/authorized_keys_$USER $OBJ/user_ca_key* $OBJ/cert_user_key*
    389 rm -f $OBJ/authorized_principals_$USER
    390 
    391