3 # Tests to ensure that the monkeysphere is working
5 # unset MONKEYSPHERE_TEST_NO_EXAMINE to get a prompt to examine the
6 # test state after failure.
9 # Daniel Kahn Gillmor <dkg@fifthhorseman.net>
10 # Jameson Rollins <jrollins@fifthhorseman.net>
11 # Micah Anderson <micah@riseup.net>
13 # Copyright: © 2008-2010
14 # License: GPL v3 or later
16 # these tests should all be able to run as a non-privileged user.
18 # put all the test output to stdout
20 # all subcommands in this script should complete without failure:
22 # piped commands should return the code of the first non-zero return
25 # make sure the TESTDIR is an absolute path, not a relative one.
26 export TESTDIR=$(cd $(dirname "$0") && pwd)
28 source "$TESTDIR"/common
30 ## make sure that the right tools are installed to run the test. the
31 ## test has *more* requirements than plain ol' monkeysphere:
32 [ -f /usr/sbin/sshd ] || { echo "You must have sshd installed to run this test." ; exit 1; }
33 which socat >/dev/null || { echo "You must have socat installed to run this test." ; exit 1; }
35 perl -MCrypt::OpenSSL::RSA -e 1 2>/dev/null || { echo "You must have the perl module Crypt::OpenSSL::RSA installed to run this test.
36 On debian-derived systems, you can set this up with:
37 apt-get install libcrypt-openssl-rsa-perl" ; exit 1; }
39 perl -MDigest::SHA -e 1 2>/dev/null || { echo "You must have the perl module Digest::SHA installed to run this test.
40 On debian-derived systems, you can set this up with:
41 apt-get install libdigest-sha-perl" ; exit 1; }
43 ## FIXME: other checks?
45 ######################################################################
48 # gpg command for test admin user
50 chmod 0700 "$TEMPDIR"/admin "$TEMPDIR"/admin/.gnupg
51 GNUPGHOME="$TEMPDIR"/admin/.gnupg gpg --no-tty "$@"
55 # first argument is expected return code from ssh connection
58 local remote_command=${1:-true}
64 # start the ssh daemon on the socket
65 echo "##### starting ssh server..."
66 socat EXEC:"/usr/sbin/sshd -f ${SSHD_CONFIG} -i -D -e" "UNIX-LISTEN:${SOCKET}" 2> "$TEMPDIR"/sshd.log &
69 # wait until the socket is created before continuing
70 while [ ! -S "$SOCKET" ] ; do
74 # make a client connection to the socket
75 echo "##### starting ssh client..."
77 "monkeysphere subkey-to-ssh-agent && ssh -F $TEMPDIR/testuser/.ssh/config ${target_hostname:-testhost.example} $remote_command" \
80 # kill the sshd process if it's still running
81 kill "$SSHD_PID" || true
85 if [ "$RETURN" = "$CODE" ] ; then
86 echo "##### ssh connection test PASSED. returned: $RETURN"
89 echo "##### ssh connection test FAILED. returned: $RETURN, expected: $CODE"
94 # invoke this instead of ssh_test() if you want this test to be
95 # skipped when the working directory has bad permissions.
96 ssh_good_perm_test() {
97 if [ "$TEMPDIR_PERMISSIONS_SAFE" = no ] ; then
98 echo "WARNING!!! Test SKIPPED because we are running in an unsafe working directory."
108 trap failed_cleanup EXIT
111 ######################################################################
114 ## set up some variables to ensure that we're operating strictly in
115 ## the tests, not system-wide:
119 # NOTE: /tmp can not be used as the temp dir here, since the
120 # permissions on /tmp are usually such that they will not pass the
121 # monkeysphere/ssh path permission checking. If you need to use a
122 # different location than the current source, please set $TMPDIR
123 # somewhere with tighter permissions.
125 mkdir -p "$TESTDIR"/tmp
126 TEMPDIR=$(mktemp -d "${TMPDIR:-$TESTDIR/tmp}/monkeyspheretest.XXXXXXX")
128 # Use the local copy of executables first, instead of system ones.
129 # This should help us test without installing.
130 export PATH="$TESTDIR"/../src:"$PATH"
132 export MONKEYSPHERE_SYSDATADIR="$TEMPDIR"
133 export MONKEYSPHERE_SYSCONFIGDIR="$TEMPDIR"
134 export MONKEYSPHERE_SYSSHAREDIR="$TESTDIR"/../src/share
135 export MONKEYSPHERE_MONKEYSPHERE_USER=$(whoami)
137 HOST_KEY_FILE="$MONKEYSPHERE_SYSCONFIGDIR"/host_keys.pub.pgp
139 export MONKEYSPHERE_CHECK_KEYSERVER=false
140 # example.org does not respond to the HKP port, so this should cause
141 # any keyserver connection attempts that do happen (they shouldn't!)
142 # to hang, so we'll notice them:
143 export MONKEYSPHERE_KEYSERVER=example.org
145 export MONKEYSPHERE_LOG_LEVEL=DEBUG
146 export MONKEYSPHERE_CORE_KEYLENGTH=1024
147 export MONKEYSPHERE_PROMPT=false
149 # unset SUBKEYS_FOR_AGENT variable which, if set, would confuse the
150 # into trying to use the user's key, instead of the testuser's key
151 unset MONKEYSPHERE_SUBKEYS_FOR_AGENT
153 export SSHD_CONFIG="$TEMPDIR"/sshd_config
154 export SOCKET="$TEMPDIR"/ssh-socket
156 # Make sure $DISPLAY is set to convince ssh and monkeysphere to fall
157 # back on $SSH_ASKPASS. Make sure it's not set to the current actual
158 # $DISPLAY (if one exists) because this test suite should not be doing
159 # *anything* with any running X11 session.
160 export DISPLAY=monkeys
163 ## we cannot do proper directory permissions checking if the current
164 ## working directory has unsatisfactory permissions:
165 if "$MONKEYSPHERE_SYSSHAREDIR"/checkperms $(whoami) "$TEMPDIR"; then
166 echo "Permissions on temporary directory '$TEMPDIR' are OK for permissions checks."
167 TEMPDIR_PERMISSIONS_SAFE=yes
171 !!!WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING!!!
172 Permissions on testing directory '$TEMPDIR' are
173 too loose to do proper strict permissions checking. Some tests
174 will be disabled or ignored.
176 To avoid this warning (and to make sure that all tests are run
177 properly), please run these tests within a directory that meets
178 sshd's standards for "StrictModes yes" -- the directory (and every
179 one of its parents) should be owned only be the user running this
180 test or root, and should not be writable by group or other.
181 !!!WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING!!!
185 # FIXME: what else should we do with this knowledge to make sure
186 # that the appropriate tests are handled properly?
187 TEMPDIR_PERMISSIONS_SAFE=no
189 # this is a new option (as of 0.26) to disable filesystem
192 # it should operate by analogy with StrictModes from sshd_config(5)
193 export MONKEYSPHERE_STRICT_MODES=false
198 ######################################################################
199 ### CONFIGURE ENVIRONMENTS
201 # copy in admin and testuser home to tmp
203 echo "##################################################"
204 echo "### configuring testuser home..."
205 (cd "$TESTDIR"/home && find testuser | cpio -pdu "$TEMPDIR")
207 # set up environment for testuser
208 export TESTHOME="$TEMPDIR"/testuser
209 export GNUPGHOME="$TESTHOME"/.gnupg
210 chmod 0700 "$GNUPGHOME"
211 export SSH_ASKPASS="$TESTHOME"/.ssh/askpass
212 export MONKEYSPHERE_HOME="$TESTHOME"/.monkeysphere
213 cat <<EOF >> "$TESTHOME"/.ssh/config
214 UserKnownHostsFile $TESTHOME/.ssh/known_hosts
215 IdentityFile $TESTHOME/.ssh/no-such-identity
216 ProxyCommand $TESTHOME/.ssh/proxy-command %h %p $SOCKET
218 cat <<EOF >> "$MONKEYSPHERE_HOME"/monkeysphere.conf
219 KNOWN_HOSTS=$TESTHOME/.ssh/known_hosts
221 get_gpg_prng_arg >> "$GNUPGHOME"/gpg.conf
224 echo "##################################################"
225 echo "### configuring admin home..."
226 (cd "$TESTDIR"/home && find admin | cpio -pdu "$TEMPDIR")
230 echo "##################################################"
231 echo "### configuring sshd..."
232 cp "$TESTDIR"/etc/ssh/sshd_config "$SSHD_CONFIG"
233 # write the sshd_config
234 cat <<EOF >> "$SSHD_CONFIG"
235 HostKey ${MONKEYSPHERE_SYSDATADIR}/ssh_host_rsa_key
236 AuthorizedKeysFile ${MONKEYSPHERE_SYSDATADIR}/authorized_keys/%u
239 # disable sshd's strict permissions settings so that some tests can
240 # complete when running under a dubious path:
241 if [ "$TEMPDIR_PERMISSIONS_SAFE" != yes ] ; then
242 cat <<EOF >> "$SSHD_CONFIG"
248 ######################################################################
249 ### SERVER HOST SETUP
253 echo "##################################################"
254 echo "### import host key..."
255 ssh-keygen -b 1024 -t rsa -N '' -f "$TEMPDIR"/ssh_host_rsa_key
256 monkeysphere-host import-key "$TEMPDIR"/ssh_host_rsa_key ssh://testhost.example
259 echo "##################################################"
260 echo "### getting host key fingerprint..."
261 SSHHOSTKEYID=$( monkeysphere-host show-keys | grep '^OpenPGP fingerprint: ' | cut -f3 -d\ )
264 # change host key expiration
266 echo "##################################################"
267 echo "### setting host key expiration..."
268 monkeysphere-host set-expire 1
269 # FIXME: how do we check that the expiration has really been set?
271 # certify host key with the "Admin's Key".
272 # (this would normally be done via keyservers)
274 echo "##################################################"
275 echo "### certifying server host key..."
276 < "$HOST_KEY_FILE" gpgadmin --import
277 echo y | gpgadmin --command-fd 0 --sign-key "$SSHHOSTKEYID"
279 # FIXME: add revoker?
281 # FIXME: how can we test publish-key without flooding junk into the
284 # FIXME: should we run "diagnostics" here to test setup?
287 ######################################################################
288 ### SERVER AUTHENTICATION SETUP
290 # set up monkeysphere authentication
292 echo "##################################################"
293 echo "### setup monkeysphere authentication..."
294 cp "$TESTDIR"/etc/monkeysphere/monkeysphere-authentication.conf "$TEMPDIR"/
295 cat <<EOF >> "$TEMPDIR"/monkeysphere-authentication.conf
296 AUTHORIZED_USER_IDS="$MONKEYSPHERE_HOME/authorized_user_ids"
298 monkeysphere-authentication setup
299 get_gpg_prng_arg >> "$MONKEYSPHERE_SYSDATADIR"/authentication/sphere/gpg.conf
301 # add admin as identity certifier for testhost.example
303 echo "##################################################"
304 echo "### adding admin as certifier..."
305 monkeysphere-authentication add-id-certifier "$TEMPDIR"/admin/.gnupg/pubkey.gpg
308 echo "##################################################"
309 echo "### list certifiers..."
310 monkeysphere-authentication list-certifiers
312 # FIXME: should we run "diagnostics" here to test setup?
314 ######################################################################
317 # generate an auth subkey for the test user that expires in 2 days
319 echo "##################################################"
320 echo "### generating key for testuser..."
321 monkeysphere gen-subkey
323 # add server key to testuser keychain
325 echo "##################################################"
326 echo "### export server key to testuser..."
327 gpgadmin --armor --export "$SSHHOSTKEYID" | gpg --import
329 # teach the "server" about the testuser's key
331 echo "##################################################"
332 echo "### export testuser key to server..."
333 gpg --export testuser | monkeysphere-authentication gpg-cmd --import
335 # update authorized_keys for user
337 echo "##################################################"
338 echo "### update server authorized_keys file for this testuser..."
339 monkeysphere-authentication update-users $(whoami)
340 # FIXME: this is maybe not failing properly for:
341 # ms: improper group or other writability on path '/tmp'.
343 ######################################################################
346 ## see whether keys-for-userid works from the client's perspective:
348 echo "##################################################"
349 echo "### testing monkeysphere keys-for-userid ..."
350 diff -q <( monkeysphere keys-for-userid ssh://testhost.example ) <( cut -f1,2 -d' ' < "$TEMPDIR"/ssh_host_rsa_key.pub )
352 # connect to test sshd, using monkeysphere ssh-proxycommand to verify
353 # the identity before connection. This should work in both directions!
355 echo "##################################################"
356 echo "### ssh connection test for success..."
359 # Make sure it works if there is "armor" written in gpg.conf
360 # add other weirdnesses here as they come up.
362 echo "##################################################"
363 echo "### testing functionality in the face of unusual gpg.conf settings..."
364 echo 'armor' >> "$GNUPGHOME"/gpg.conf
367 # remove the testuser's authorized_user_ids file, update, and make
368 # sure that the ssh authentication FAILS
370 echo "##################################################"
371 echo "### removing testuser authorized_user_ids and updating..."
372 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{,.bak}
373 monkeysphere-authentication update-users $(whoami)
375 echo "##################################################"
376 echo "### ssh connection test for failure..."
378 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{.bak,}
380 # put improper permissions on authorized_user_ids file, update, and
381 # make sure ssh authentication FAILS
383 echo "##################################################"
384 echo "### setting group writability on authorized_user_ids and updating..."
385 chmod g+w "$TESTHOME"/.monkeysphere/authorized_user_ids
386 monkeysphere-authentication update-users $(whoami)
388 echo "##################################################"
389 echo "### ssh connection test for failure..."
390 ssh_good_perm_test true 255
391 chmod g-w "$TESTHOME"/.monkeysphere/authorized_user_ids
393 echo "##################################################"
394 echo "### setting other writability on authorized_user_ids and updating..."
395 chmod o+w "$TESTHOME"/.monkeysphere/authorized_user_ids
396 monkeysphere-authentication update-users $(whoami)
398 echo "##################################################"
399 echo "### ssh connection test for failure..."
400 ssh_good_perm_test true 255
401 chmod o-w "$TESTHOME"/.monkeysphere/authorized_user_ids
402 monkeysphere-authentication update-users $(whoami)
406 echo "##################################################"
407 echo "### setup for symlink tests..."
408 cp -a "$TESTHOME"/.monkeysphere{,.linktest}
411 echo "##################################################"
412 echo "### make authorized_user_ids an absolute symlink and updating..."
413 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{,.bak}
414 ln -s "$TESTHOME"/.monkeysphere{.linktest,}/authorized_user_ids
415 monkeysphere-authentication update-users $(whoami)
417 echo "##################################################"
418 echo "### ssh connection test for success..."
421 echo "##################################################"
422 echo "### create bad permissions on link dir and updating..."
423 chmod o+w "$TESTHOME"/.monkeysphere.linktest
424 monkeysphere-authentication update-users $(whoami)
426 echo "##################################################"
427 echo "### ssh connection test for failure..."
428 ssh_good_perm_test true 255
429 chmod o-w "$TESTHOME"/.monkeysphere.linktest
431 echo "##################################################"
432 echo "### make authorized_user_ids a relative symlink and updating..."
433 ln -sf ../.monkeysphere.linktest/authorized_user_ids "$TESTHOME"/.monkeysphere/authorized_user_ids
434 monkeysphere-authentication update-users $(whoami)
436 echo "##################################################"
437 echo "### ssh connection test for success..."
440 echo "##################################################"
441 echo "### create bad permissions on link dir updating..."
442 chmod o+w "$TESTHOME"/.monkeysphere.linktest
443 monkeysphere-authentication update-users $(whoami)
445 echo "##################################################"
446 echo "### ssh connection test for failure..."
447 ssh_good_perm_test true 255
448 chmod o-w "$TESTHOME"/.monkeysphere.linktest
449 # FIXME: implement check of link path, and uncomment this test
451 # echo "##################################################"
452 # echo "### create bad permissions on link dir and updating..."
453 # chmod o+w "$TESTHOME"/.monkeysphere
454 # monkeysphere-authentication update-users $(whoami)
456 # echo "##################################################"
457 # echo "### ssh connection test for failure..."
458 # ssh_good_perm_test true 255
459 # chmod o-w "$TESTHOME"/.monkeysphere
460 rm "$TESTHOME"/.monkeysphere/authorized_user_ids
461 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{.bak,}
464 echo "##################################################"
465 echo "### make .monkeysphere directory an absolute symlink and updating..."
466 mv "$TESTHOME"/.monkeysphere{,.bak}
467 ln -s "$TESTHOME"/.monkeysphere{.linktest,}
468 monkeysphere-authentication update-users $(whoami)
470 echo "##################################################"
471 echo "### ssh connection test for success..."
474 echo "##################################################"
475 echo "### create bad permissions on link dir and updating..."
476 chmod o+w "$TESTHOME"/.monkeysphere.linktest
477 monkeysphere-authentication update-users $(whoami)
479 echo "##################################################"
480 echo "### ssh connection test for failure..."
481 ssh_good_perm_test true 255
482 chmod o-w "$TESTHOME"/.monkeysphere.linktest
484 echo "##################################################"
485 echo "### make .monkeysphere directory a relative symlink and updating..."
486 ln -sfn .monkeysphere.linktest "$TESTHOME"/.monkeysphere
487 monkeysphere-authentication update-users $(whoami)
489 echo "##################################################"
490 echo "### ssh connection test for success..."
493 echo "##################################################"
494 echo "### create bad permissions on link dir updating..."
495 chmod o+w "$TESTHOME"/.monkeysphere.linktest
496 monkeysphere-authentication update-users $(whoami)
498 echo "##################################################"
499 echo "### ssh connection test for failure..."
500 ssh_good_perm_test true 255
501 chmod o-w "$TESTHOME"/.monkeysphere.linktest
502 rm "$TESTHOME"/.monkeysphere
503 mv "$TESTHOME"/.monkeysphere{.bak,}
505 # ensure we're back to normal:
507 echo "##################################################"
508 echo "### making sure we are back to normal..."
509 monkeysphere-authentication update-users $(whoami)
512 # check ssh authorized_key options
514 echo "##################################################"
515 echo "### checking ssh authorized_key option support..."
516 cp "$TESTHOME"/.monkeysphere/authorized_user_ids{,.bak}
517 echo ' no-X11-forwarding' >>"$TESTHOME"/.monkeysphere/authorized_user_ids
518 echo ' no-port-forwarding' >>"$TESTHOME"/.monkeysphere/authorized_user_ids
519 echo ' command="/bin/false"' >>"$TESTHOME"/.monkeysphere/authorized_user_ids
520 monkeysphere-authentication update-users $(whoami)
522 ssh_test /bin/false 1
523 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{.bak,}
525 # ensure we're back to normal:
527 echo "##################################################"
528 echo "### making sure we are back to normal..."
529 monkeysphere-authentication update-users $(whoami)
533 echo "##################################################"
534 echo "### ssh connection test directly to 'testhost2.example' without new name..."
535 target_hostname=testhost2.example ssh_test true 255
537 echo "##################################################"
538 echo "### add servicename, certify by admin, import by user..."
539 monkeysphere-host add-servicename ssh://testhost2.example
540 <"$HOST_KEY_FILE" gpgadmin --import
541 printf "y\ny\n" | gpgadmin --command-fd 0 --sign-key "$SSHHOSTKEYID"
544 echo "##################################################"
545 echo "### ssh connection test with hostname 'testhost2.example' added..."
546 gpgadmin --export "$SSHHOSTKEYID" | gpg --import
551 echo "##################################################"
552 echo "### ssh connection test directly to 'testhost2.example' ..."
553 gpg --import <"$HOST_KEY_FILE"
555 target_hostname=testhost2.example ssh_test true
558 echo "##################################################"
559 echo "### ssh connection test for failure with 'testhost2.example' revoked..."
560 monkeysphere-host revoke-servicename ssh://testhost2.example
561 gpg --import <"$HOST_KEY_FILE"
563 target_hostname=testhost2.example ssh_test true 255
565 # FIXME: addtest: remove admin as id-certifier and check ssh failure
567 # FIXME: addtest: how do we test that set-expire makes sense after new
568 # servicenames have been added?
571 echo "##################################################"
572 echo "### testing monkeysphere authentication keys-for-user"
573 diff -q <(monkeysphere-authentication keys-for-user $(whoami) | cut -d' ' -f1,2) <(cut -d' ' -f1,2 ${MONKEYSPHERE_SYSDATADIR}/authorized_keys/${MONKEYSPHERE_MONKEYSPHERE_USER})
575 # test to make sure things are OK after the previous tests:
577 echo "##################################################"
578 echo "### settings reset, updating..."
579 monkeysphere-authentication update-users $(whoami)
581 echo "##################################################"
582 echo "### ssh connection test for success..."
586 echo "##################################################"
587 echo "### Testing TLS setup..."
589 openssl req -config "$TESTDIR"/openssl.cnf -x509 -newkey rsa:1024 -subj '/DC=example/DC=testhost/CN=testhost.example/' -days 3 -keyout "$TEMPDIR"/tls_key.pem -nodes >"$TEMPDIR"/tls_cert.pem
590 monkeysphere-host import-key "$TEMPDIR"/tls_key.pem https://testhost.example
592 # FIXME: how can we test this via an https client?
593 # We don't currently provide one.
595 # FIXME: should we test other monkeysphere-host operations somehow now
596 # that we have more than one key in the host keyring?
599 echo "##################################################"
600 echo "### revoking ssh host key..."
601 # generate the revocation certificate and feed it directly to the test
602 # user's keyring (we're not publishing to the keyservers)
603 monkeysphere-host revoke-key "$SSHHOSTKEYID" | gpg --import
605 echo "##################################################"
606 echo "### ssh connection test for failure..."
610 ######################################################################
615 echo "##################################################"
616 echo " Monkeysphere basic tests completed successfully!"
617 echo "##################################################"