enforce --no-armor when exporting to openpgp2ssh in case weird gpg.conf options ...
[monkeysphere.git] / tests / basic
1 #!/usr/bin/env bash
2
3 # Tests to ensure that the monkeysphere is working
4 #
5 # unset MONKEYSPHERE_TEST_NO_EXAMINE to get a prompt to examine the
6 # test state after failure.
7
8 # Authors: 
9 #   Daniel Kahn Gillmor <dkg@fifthhorseman.net>
10 #   Jameson Rollins <jrollins@fifthhorseman.net>
11 #   Micah Anderson <micah@riseup.net> 
12 #
13 # Copyright: © 2008-2010
14 # License: GPL v3 or later
15
16 # these tests should all be able to run as a non-privileged user.
17
18 # put all the test output to stdout
19 exec 2>&1
20 # all subcommands in this script should complete without failure:
21 set -e
22 # piped commands should return the code of the first non-zero return
23 set -o pipefail
24
25 # make sure the TESTDIR is an absolute path, not a relative one.
26 export TESTDIR=$(cd $(dirname "$0") && pwd)
27
28 source "$TESTDIR"/common
29
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; }
34
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; }
38
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; }
42
43 ## FIXME: other checks?
44
45 ######################################################################
46 ### FUNCTIONS
47
48 # gpg command for test admin user
49 gpgadmin() {
50     chmod 0700 "$TEMPDIR"/admin "$TEMPDIR"/admin/.gnupg
51     GNUPGHOME="$TEMPDIR"/admin/.gnupg gpg --no-tty "$@"
52 }
53
54 # test ssh connection
55 # first argument is expected return code from ssh connection
56 ssh_test() {
57     local RETURN=0
58
59     umask 0077
60
61     CODE=${1:-0}
62
63     # start the ssh daemon on the socket
64     echo "##### starting ssh server..."
65     socat EXEC:"/usr/sbin/sshd -f ${SSHD_CONFIG} -i -D -e" "UNIX-LISTEN:${SOCKET}" 2> "$TEMPDIR"/sshd.log &
66     SSHD_PID="$!"
67
68     # wait until the socket is created before continuing
69     while [ ! -S "$SOCKET" ] ; do
70         sleep 1
71     done
72
73     # make a client connection to the socket
74     echo "##### starting ssh client..."
75     ssh-agent bash -c \
76         "monkeysphere subkey-to-ssh-agent && ssh -F $TEMPDIR/testuser/.ssh/config ${target_hostname:-testhost.example} true" \
77         || RETURN="$?"
78
79     # kill the sshd process if it's still running
80     kill "$SSHD_PID" || true
81     wait
82     SSHD_PID=
83
84     if [ "$RETURN" = "$CODE" ] ; then
85         echo "##### ssh connection test PASSED. returned: $RETURN"
86         return 0
87     else
88         echo "##### ssh connection test FAILED. returned: $RETURN, expected: $CODE"
89         return 1
90     fi
91 }
92
93 # invoke this instead of ssh_test() if you want this test to be
94 # skipped when the working directory has bad permissions.
95 ssh_good_perm_test() {
96     if [ "$TEMPDIR_PERMISSIONS_SAFE" = no ] ; then
97         echo "WARNING!!! Test SKIPPED because we are running in an unsafe working directory."
98     else
99         ssh_test "$@"
100     fi
101 }
102
103
104 SSHD_PID=
105
106 ## setup trap
107 trap failed_cleanup EXIT
108
109
110 ######################################################################
111 ### SETUP VARIABLES
112
113 ## set up some variables to ensure that we're operating strictly in
114 ## the tests, not system-wide:
115
116 # set up temp dir
117
118 # NOTE: /tmp can not be used as the temp dir here, since the
119 # permissions on /tmp are usually such that they will not pass the
120 # monkeysphere/ssh path permission checking.  If you need to use a
121 # different location than the current source, please set $TMPDIR
122 # somewhere with tighter permissions.
123
124 mkdir -p "$TESTDIR"/tmp
125 TEMPDIR=$(mktemp -d "${TMPDIR:-$TESTDIR/tmp}/monkeyspheretest.XXXXXXX")
126
127 # Use the local copy of executables first, instead of system ones.
128 # This should help us test without installing.
129 export PATH="$TESTDIR"/../src:"$PATH"
130
131 export MONKEYSPHERE_SYSDATADIR="$TEMPDIR"
132 export MONKEYSPHERE_SYSCONFIGDIR="$TEMPDIR"
133 export MONKEYSPHERE_SYSSHAREDIR="$TESTDIR"/../src/share
134 export MONKEYSPHERE_MONKEYSPHERE_USER=$(whoami)
135
136 HOST_KEY_FILE="$MONKEYSPHERE_SYSCONFIGDIR"/host_keys.pub.pgp
137
138 export MONKEYSPHERE_CHECK_KEYSERVER=false
139 # example.org does not respond to the HKP port, so this should cause
140 # any keyserver connection attempts that do happen (they shouldn't!)
141 # to hang, so we'll notice them:
142 export MONKEYSPHERE_KEYSERVER=example.org
143
144 export MONKEYSPHERE_LOG_LEVEL=DEBUG
145 export MONKEYSPHERE_CORE_KEYLENGTH=1024
146 export MONKEYSPHERE_PROMPT=false
147
148 # unset SUBKEYS_FOR_AGENT variable which, if set, would confuse the
149 # into trying to use the user's key, instead of the testuser's key
150 unset MONKEYSPHERE_SUBKEYS_FOR_AGENT
151
152 export SSHD_CONFIG="$TEMPDIR"/sshd_config
153 export SOCKET="$TEMPDIR"/ssh-socket
154
155 # Make sure $DISPLAY is set to convince ssh and monkeysphere to fall
156 # back on $SSH_ASKPASS.  Make sure it's not set to the current actual
157 # $DISPLAY (if one exists) because this test suite should not be doing
158 # *anything* with any running X11 session.
159 export DISPLAY=monkeys
160
161
162 ## we cannot do proper directory permissions checking if the current
163 ## working directory has unsatisfactory permissions:
164 if "$MONKEYSPHERE_SYSSHAREDIR"/checkperms $(whoami) "$TEMPDIR"; then 
165     echo "Permissions on temporary directory '$TEMPDIR' are OK for permissions checks."
166     TEMPDIR_PERMISSIONS_SAFE=yes
167 else
168     cat <<EOF
169
170 !!!WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING!!!
171  Permissions on testing directory '$TEMPDIR' are
172  too loose to do proper strict permissions checking.  Some tests 
173  will be disabled or ignored.
174
175  To avoid this warning (and to make sure that all tests are run
176  properly), please run these tests within a directory that meets
177  sshd's standards for "StrictModes yes" -- the directory (and every
178  one of its parents) should be owned only be the user running this
179  test or root, and should not be writable by group or other.
180 !!!WARNING WARNING WARNING WARNING WARNING WARNING WARNING WARNING!!!
181
182 EOF
183
184     # FIXME: what else should we do with this knowledge to make sure
185     # that the appropriate tests are handled properly?
186     TEMPDIR_PERMISSIONS_SAFE=no
187
188     # this is a new option (as of 0.26) to disable filesystem
189     # permission checks.
190
191     # it should operate by analogy with StrictModes from sshd_config(5)
192     export MONKEYSPHERE_STRICT_MODES=false
193 fi
194
195
196
197 ######################################################################
198 ### CONFIGURE ENVIRONMENTS
199
200 # copy in admin and testuser home to tmp
201 echo
202 echo "##################################################"
203 echo "### configuring testuser home..."
204 (cd "$TESTDIR"/home && find testuser | cpio -pdu "$TEMPDIR")
205
206 # set up environment for testuser
207 export TESTHOME="$TEMPDIR"/testuser
208 export GNUPGHOME="$TESTHOME"/.gnupg
209 chmod 0700 "$GNUPGHOME"
210 export SSH_ASKPASS="$TESTHOME"/.ssh/askpass
211 export MONKEYSPHERE_HOME="$TESTHOME"/.monkeysphere
212 cat <<EOF >> "$TESTHOME"/.ssh/config
213 UserKnownHostsFile $TESTHOME/.ssh/known_hosts
214 IdentityFile $TESTHOME/.ssh/no-such-identity
215 ProxyCommand $TESTHOME/.ssh/proxy-command %h %p $SOCKET
216 EOF
217 cat <<EOF >> "$MONKEYSPHERE_HOME"/monkeysphere.conf
218 KNOWN_HOSTS=$TESTHOME/.ssh/known_hosts
219 EOF
220 get_gpg_prng_arg >> "$GNUPGHOME"/gpg.conf
221
222 echo
223 echo "##################################################"
224 echo "### configuring admin home..."
225 (cd "$TESTDIR"/home && find admin | cpio -pdu "$TEMPDIR")
226
227 # set up sshd
228 echo
229 echo "##################################################"
230 echo "### configuring sshd..."
231 cp "$TESTDIR"/etc/ssh/sshd_config "$SSHD_CONFIG"
232 # write the sshd_config
233 cat <<EOF >> "$SSHD_CONFIG"
234 HostKey ${MONKEYSPHERE_SYSDATADIR}/ssh_host_rsa_key
235 AuthorizedKeysFile ${MONKEYSPHERE_SYSDATADIR}/authorized_keys/%u
236 EOF
237
238 # disable sshd's strict permissions settings so that some tests can
239 # complete when running under a dubious path:
240 if [ "$TEMPDIR_PERMISSIONS_SAFE" != yes ] ; then
241     cat <<EOF >> "$SSHD_CONFIG"
242 StrictModes no
243 EOF
244 fi
245
246
247 ######################################################################
248 ### SERVER HOST SETUP
249
250 # import host key
251 echo
252 echo "##################################################"
253 echo "### import host key..."
254 ssh-keygen -b 1024 -t rsa -N '' -f "$TEMPDIR"/ssh_host_rsa_key
255 monkeysphere-host import-key "$TEMPDIR"/ssh_host_rsa_key ssh://testhost.example
256
257 echo
258 echo "##################################################"
259 echo "### getting host key fingerprint..."
260 SSHHOSTKEYID=$( monkeysphere-host show-keys | grep '^OpenPGP fingerprint: ' | cut -f3 -d\  )
261 echo "$SSHHOSTKEYID"
262
263 # change host key expiration
264 echo
265 echo "##################################################"
266 echo "### setting host key expiration..."
267 monkeysphere-host set-expire 1
268 # FIXME: how do we check that the expiration has really been set?
269
270 # certify host key with the "Admin's Key".
271 # (this would normally be done via keyservers)
272 echo
273 echo "##################################################"
274 echo "### certifying server host key..."
275 < "$HOST_KEY_FILE" gpgadmin --import
276 echo y | gpgadmin --command-fd 0 --sign-key "$SSHHOSTKEYID"
277
278 # FIXME: add revoker?
279
280 # FIXME: how can we test publish-key without flooding junk into the
281 # keyservers?
282
283 # FIXME: should we run "diagnostics" here to test setup?
284
285
286 ######################################################################
287 ### SERVER AUTHENTICATION SETUP
288
289 # set up monkeysphere authentication
290 echo
291 echo "##################################################"
292 echo "### setup monkeysphere authentication..."
293 cp "$TESTDIR"/etc/monkeysphere/monkeysphere-authentication.conf "$TEMPDIR"/
294 cat <<EOF >> "$TEMPDIR"/monkeysphere-authentication.conf
295 AUTHORIZED_USER_IDS="$MONKEYSPHERE_HOME/authorized_user_ids"
296 EOF
297 monkeysphere-authentication setup
298 get_gpg_prng_arg >> "$MONKEYSPHERE_SYSDATADIR"/authentication/sphere/gpg.conf
299
300 # add admin as identity certifier for testhost.example
301 echo
302 echo "##################################################"
303 echo "### adding admin as certifier..."
304 monkeysphere-authentication add-id-certifier "$TEMPDIR"/admin/.gnupg/pubkey.gpg
305
306 echo
307 echo "##################################################"
308 echo "### list certifiers..."
309 monkeysphere-authentication list-certifiers
310
311 # FIXME: should we run "diagnostics" here to test setup?
312
313 ######################################################################
314 ### TESTUSER SETUP
315
316 # generate an auth subkey for the test user that expires in 2 days
317 echo
318 echo "##################################################"
319 echo "### generating key for testuser..."
320 monkeysphere gen-subkey
321
322 # add server key to testuser keychain
323 echo
324 echo "##################################################"
325 echo "### export server key to testuser..."
326 gpgadmin --armor --export "$SSHHOSTKEYID" | gpg --import
327
328 # teach the "server" about the testuser's key
329 echo
330 echo "##################################################"
331 echo "### export testuser key to server..."
332 gpg --export testuser | monkeysphere-authentication gpg-cmd --import
333
334 # update authorized_keys for user
335 echo
336 echo "##################################################"
337 echo "### update server authorized_keys file for this testuser..."
338 monkeysphere-authentication update-users $(whoami)
339 # FIXME: this is maybe not failing properly for:
340 # ms: improper group or other writability on path '/tmp'.
341
342 ######################################################################
343 ### TESTS
344
345 ## see whether keys-for-userid works from the client's perspective:
346 echo
347 echo "##################################################"
348 echo "### testing monkeysphere keys-for-userid ..."
349 diff -q <( monkeysphere keys-for-userid ssh://testhost.example ) <( cut -f1,2 -d' ' < "$TEMPDIR"/ssh_host_rsa_key.pub )
350
351 # connect to test sshd, using monkeysphere ssh-proxycommand to verify
352 # the identity before connection.  This should work in both directions!
353 echo
354 echo "##################################################"
355 echo "### ssh connection test for success..."
356 ssh_test
357
358 # Make sure it works if there is "armor" written in gpg.conf
359 # add other weirdnesses here as they come up.
360 echo
361 echo "##################################################"
362 echo "### testing functionality in the face of unusual gpg.conf settings..."
363 echo 'armor' >> "$GNUPGHOME"/gpg.conf
364 ssh_test
365
366 # remove the testuser's authorized_user_ids file, update, and make
367 # sure that the ssh authentication FAILS
368 echo
369 echo "##################################################"
370 echo "### removing testuser authorized_user_ids and updating..."
371 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{,.bak}
372 monkeysphere-authentication update-users $(whoami)
373 echo
374 echo "##################################################"
375 echo "### ssh connection test for failure..."
376 ssh_test 255
377 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{.bak,}
378
379 # put improper permissions on authorized_user_ids file, update, and
380 # make sure ssh authentication FAILS
381 echo
382 echo "##################################################"
383 echo "### setting group writability on authorized_user_ids and updating..."
384 chmod g+w "$TESTHOME"/.monkeysphere/authorized_user_ids
385 monkeysphere-authentication update-users $(whoami)
386 echo
387 echo "##################################################"
388 echo "### ssh connection test for failure..."
389 ssh_good_perm_test 255
390 chmod g-w "$TESTHOME"/.monkeysphere/authorized_user_ids
391 echo
392 echo "##################################################"
393 echo "### setting other writability on authorized_user_ids and updating..."
394 chmod o+w "$TESTHOME"/.monkeysphere/authorized_user_ids
395 monkeysphere-authentication update-users $(whoami)
396 echo
397 echo "##################################################"
398 echo "### ssh connection test for failure..."
399 ssh_good_perm_test 255
400 chmod o-w "$TESTHOME"/.monkeysphere/authorized_user_ids
401 monkeysphere-authentication update-users $(whoami)
402
403 # test symlinks
404 echo
405 echo "##################################################"
406 echo "### setup for symlink tests..."
407 cp -a "$TESTHOME"/.monkeysphere{,.linktest}
408
409 echo
410 echo "##################################################"
411 echo "### make authorized_user_ids an absolute symlink and updating..."
412 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{,.bak}
413 ln -s "$TESTHOME"/.monkeysphere{.linktest,}/authorized_user_ids
414 monkeysphere-authentication update-users $(whoami)
415 echo
416 echo "##################################################"
417 echo "### ssh connection test for success..."
418 ssh_test
419 echo
420 echo "##################################################"
421 echo "### create bad permissions on link dir and updating..."
422 chmod o+w "$TESTHOME"/.monkeysphere.linktest
423 monkeysphere-authentication update-users $(whoami)
424 echo
425 echo "##################################################"
426 echo "### ssh connection test for failure..."
427 ssh_good_perm_test 255
428 chmod o-w "$TESTHOME"/.monkeysphere.linktest
429 echo
430 echo "##################################################"
431 echo "### make authorized_user_ids a relative symlink and updating..."
432 ln -sf ../.monkeysphere.linktest/authorized_user_ids "$TESTHOME"/.monkeysphere/authorized_user_ids
433 monkeysphere-authentication update-users $(whoami)
434 echo
435 echo "##################################################"
436 echo "### ssh connection test for success..."
437 ssh_test
438 echo
439 echo "##################################################"
440 echo "### create bad permissions on link dir updating..."
441 chmod o+w "$TESTHOME"/.monkeysphere.linktest
442 monkeysphere-authentication update-users $(whoami)
443 echo
444 echo "##################################################"
445 echo "### ssh connection test for failure..."
446 ssh_good_perm_test 255
447 chmod o-w "$TESTHOME"/.monkeysphere.linktest
448 # FIXME: implement check of link path, and uncomment this test
449 # echo
450 # echo "##################################################"
451 # echo "### create bad permissions on link dir and updating..."
452 # chmod o+w "$TESTHOME"/.monkeysphere
453 # monkeysphere-authentication update-users $(whoami)
454 # echo
455 # echo "##################################################"
456 # echo "### ssh connection test for failure..."
457 # ssh_good_perm_test 255
458 # chmod o-w "$TESTHOME"/.monkeysphere
459 rm "$TESTHOME"/.monkeysphere/authorized_user_ids
460 mv "$TESTHOME"/.monkeysphere/authorized_user_ids{.bak,}
461
462 echo
463 echo "##################################################"
464 echo "### make .monkeysphere directory an absolute symlink and updating..."
465 mv "$TESTHOME"/.monkeysphere{,.bak}
466 ln -s "$TESTHOME"/.monkeysphere{.linktest,}
467 monkeysphere-authentication update-users $(whoami)
468 echo
469 echo "##################################################"
470 echo "### ssh connection test for success..."
471 ssh_test
472 echo
473 echo "##################################################"
474 echo "### create bad permissions on link dir and updating..."
475 chmod o+w "$TESTHOME"/.monkeysphere.linktest
476 monkeysphere-authentication update-users $(whoami)
477 echo
478 echo "##################################################"
479 echo "### ssh connection test for failure..."
480 ssh_good_perm_test 255
481 chmod o-w "$TESTHOME"/.monkeysphere.linktest
482 echo
483 echo "##################################################"
484 echo "### make .monkeysphere directory a relative symlink and updating..."
485 ln -sfn .monkeysphere.linktest "$TESTHOME"/.monkeysphere
486 monkeysphere-authentication update-users $(whoami)
487 echo
488 echo "##################################################"
489 echo "### ssh connection test for success..."
490 ssh_test
491 echo
492 echo "##################################################"
493 echo "### create bad permissions on link dir updating..."
494 chmod o+w "$TESTHOME"/.monkeysphere.linktest
495 monkeysphere-authentication update-users $(whoami)
496 echo
497 echo "##################################################"
498 echo "### ssh connection test for failure..."
499 ssh_good_perm_test 255
500 chmod o-w "$TESTHOME"/.monkeysphere.linktest
501 rm "$TESTHOME"/.monkeysphere
502 mv "$TESTHOME"/.monkeysphere{.bak,}
503
504 # ensure we're back to normal:
505 echo
506 echo "##################################################"
507 echo "### making sure we are back to normal..."
508 monkeysphere-authentication update-users $(whoami)
509 ssh_test
510
511
512 echo
513 echo "##################################################"
514 echo "### ssh connection test directly to 'testhost2.example' without new name..."
515 target_hostname=testhost2.example ssh_test 255
516 echo
517 echo "##################################################"
518 echo "### add servicename, certify by admin, import by user..."
519 monkeysphere-host add-servicename ssh://testhost2.example
520 <"$HOST_KEY_FILE" gpgadmin --import
521 printf "y\ny\n" | gpgadmin --command-fd 0 --sign-key "$SSHHOSTKEYID"
522
523 echo
524 echo "##################################################"
525 echo "### ssh connection test with hostname 'testhost2.example' added..."
526 gpgadmin --export "$SSHHOSTKEYID" | gpg --import
527 gpg --check-trustdb
528 ssh_test
529
530 echo
531 echo "##################################################"
532 echo "### ssh connection test directly to 'testhost2.example' ..."
533 gpg --import <"$HOST_KEY_FILE"
534 gpg --check-trustdb
535 target_hostname=testhost2.example ssh_test
536
537 echo
538 echo "##################################################"
539 echo "### ssh connection test for failure with 'testhost2.example' revoked..."
540 monkeysphere-host revoke-servicename ssh://testhost2.example
541 gpg --import <"$HOST_KEY_FILE"
542 gpg --check-trustdb
543 target_hostname=testhost2.example ssh_test 255
544
545 # FIXME: addtest: remove admin as id-certifier and check ssh failure
546
547 # FIXME: addtest: how do we test that set-expire makes sense after new
548 # servicenames have been added?
549
550 # test to make sure things are OK after the previous tests:
551 echo
552 echo "##################################################"
553 echo "### settings reset, updating..."
554 monkeysphere-authentication update-users $(whoami)
555 echo
556 echo "##################################################"
557 echo "### ssh connection test for success..."
558 ssh_test
559
560 echo
561 echo "##################################################"
562 echo "### Testing TLS setup..."
563
564 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
565 monkeysphere-host import-key "$TEMPDIR"/tls_key.pem https://testhost.example
566
567 # FIXME: how can we test this via an https client?  
568 # We don't currently provide one.
569
570 # FIXME: should we test other monkeysphere-host operations somehow now
571 # that we have more than one key in the host keyring?
572
573 echo
574 echo "##################################################"
575 echo "### revoking ssh host key..."
576 # generate the revocation certificate and feed it directly to the test
577 # user's keyring (we're not publishing to the keyservers)
578 monkeysphere-host revoke-key "$SSHHOSTKEYID" | gpg --import
579 echo
580 echo "##################################################"
581 echo "### ssh connection test for failure..."
582 ssh_test 255
583
584
585 ######################################################################
586
587 trap - EXIT
588
589 echo
590 echo "##################################################"
591 echo " Monkeysphere basic tests completed successfully!"
592 echo "##################################################"
593
594 cleanup