diff options
-rw-r--r-- | doc/TODO | 25 | ||||
-rw-r--r-- | man/man8/monkeysphere-host.8 | 25 | ||||
-rw-r--r-- | packaging/debian/changelog | 17 | ||||
-rwxr-xr-x | packaging/debian/monkeysphere.prerm | 2 | ||||
-rwxr-xr-x | src/monkeysphere | 18 | ||||
-rwxr-xr-x | src/monkeysphere-host | 13 | ||||
-rw-r--r-- | src/share/common | 17 | ||||
-rw-r--r-- | src/share/m/ssh_proxycommand | 10 | ||||
-rw-r--r-- | src/share/m/subkey_to_ssh_agent | 12 | ||||
-rw-r--r-- | src/share/ma/add_certifier | 16 | ||||
-rw-r--r-- | src/share/ma/diagnostics | 2 | ||||
-rw-r--r-- | src/share/ma/remove_certifier | 2 | ||||
-rw-r--r-- | src/share/ma/update_users | 5 | ||||
-rw-r--r-- | src/share/mh/add_hostname | 6 | ||||
-rw-r--r-- | src/share/mh/add_revoker | 16 | ||||
-rw-r--r-- | src/share/mh/import_key | 15 | ||||
-rw-r--r-- | src/share/mh/revoke_hostname | 6 | ||||
-rw-r--r-- | src/share/mh/revoke_key | 70 | ||||
-rwxr-xr-x | tests/basic | 63 | ||||
-rw-r--r-- | tests/common | 2 | ||||
-rw-r--r-- | website/advanced-user.mdwn | 137 | ||||
-rw-r--r-- | website/doc.mdwn | 4 | ||||
-rw-r--r-- | website/getting-started-admin.mdwn | 120 | ||||
-rw-r--r-- | website/getting-started-user.mdwn | 307 |
24 files changed, 565 insertions, 345 deletions
@@ -9,17 +9,6 @@ Handle unverified monkeysphere hosts in such a way that they're not always removed from known_hosts file. Ask user to lsign the host key? -Work out the details (and describe a full use case) for assigning a - REVOKER during monkeysphere-server gen_key -- how is this set? How - do we export it so it's available when a second-party revocation is - needed? - -Provide a friendly interactive UI for marginal or failing client-side - hostkey verifications. Handle the common cases smoothly, and - provide good debugging info for the unusual cases. - -Create ssh2openpgp or convert to full-fledged keytrans. - Resolve the bugs listed in openpgp2ssh(1):BUGS. Understand and document the output of gpg --check-trustdb: @@ -44,12 +33,6 @@ Make it easier to do domain-relative ssh host trust signatures with Fix the order of questions when user does a tsign in gpg or gpg2. -File bug against ssh-keygen about how "-R" option removes comments - from known_hosts file. - -File bug against ssh-keygen to see if we can get it to write to hash a - known_hosts file to/from stdout/stdin. - When using ssh-proxycommand, if only host keys found are expired or revoked, then output loud warning with prompt, or fail hard. @@ -63,14 +46,6 @@ Optimize keyserver access, particularly on monkeysphere-server update-users -- is there a way to query the keyserver all in a chunk? -Create DSA authentication subkey for server during gen-key - -Fix behavior when add-identity-certifier fails to fetch a key from the - keyserver. - -Allow server administrators to add-identity-certifier from a key in - the filesystem (or on stdin, etc) - Think about packaging monkeysphere for other (non-apt-based) operating systems. RPM-based linux systems, FreeBSD ports, and Mac OS X seem like the most likely candidates. diff --git a/man/man8/monkeysphere-host.8 b/man/man8/monkeysphere-host.8 index 2ccaaec..7909b62 100644 --- a/man/man8/monkeysphere-host.8 +++ b/man/man8/monkeysphere-host.8 @@ -23,14 +23,13 @@ connection authentication. \fBmonkeysphere-host\fP takes various subcommands: .TP -.B import-key FILE [NAME[:PORT]] +.B import-key FILE NAME[:PORT] Import a pem-encoded ssh secret host key from file FILE. If FILE is '-', then the key will be imported from stdin. NAME[:PORT] is used -to specify the hostname (and port) used in the user ID of the new -OpenPGP key. If NAME is not specified, then the system -fully-qualified domain name will be used (ie. `hostname -f'). If PORT -is not specified, the no port is added to the user ID, which means -port 22 is assumed. `i' may be used in place of `import-key'. +to specify the fully-qualified hostname (and port) used in the user ID +of the new OpenPGP key. If PORT is not specified, the no port is +added to the user ID, which means port 22 is assumed. `i' may be used +in place of `import-key'. .TP .B show-key Output information about host's OpenPGP and SSH keys. `s' may be used @@ -62,15 +61,17 @@ in place of `revoke-hostname'. Add a revoker to the host's OpenPGP key. The key ID will be loaded from the keyserver. A file may be loaded instead of pulling the key from the keyserver by specifying the path to the file as the argument, -or by specifying `-` to load from stdin. `o' may be be used in place +or by specifying `-` to load from stdin. `r+' may be be used in place of `add-revoker'. .TP .B revoke-key -Revoke the host's OpenPGP key. This will ask you a series of -questions, and then generate a key revocation certificate on standard -out. If you publish this revocation certificate to the public -keyservers, your host key will be permanently revoked. `r' may be -used in place of `revoke-key'. +Generate (with the option to publish) a revocation certificate for the +host's OpenPGP key. If such a certificate is published, your host key +will be permanently revoked. This subcommand will ask you a series of +questions, and then generate a key revocation certificate, sending it +to stdout. If you explicitly tell it to publish the revocation +certificate immediately, it will send it to the public keyservers. +USE WITH CAUTION! .TP .B publish-key Publish the host's OpenPGP key to the keyserver. `p' may be used in diff --git a/packaging/debian/changelog b/packaging/debian/changelog index fc317d9..32b7388 100644 --- a/packaging/debian/changelog +++ b/packaging/debian/changelog @@ -7,21 +7,22 @@ monkeysphere (0.23~pre-1) UNRELEASED; urgency=low - replace monkeysphere-server with monkeysphere-{authentication,host} - fold monkeysphere-ssh-proxycommand into /usr/bin/monkeysphere - * new ability to import existing ssh key into monkeysphere - * simplify adding a host to the monkeysphere, automate the process - during debian installation + * new ability to import existing ssh host key into monkeysphere. So now + m-a import-key replaces m-s gen-key. * provide pem2openpgp for translating unencrypted PEM-encoded raw key - material into OpenPGP keys. - * added better checks for the existence of a host private key for - functions that require it to be there. + material into OpenPGP keys (introduces new perl dependencies) * get rid of getopts dependency * added version output option + * better checks for the existence of a host private key for + monkeysphere-host subcommands that need it. * better checks on validity of existing authentication subkeys when - doing monkeysphere {import,gen}_subkey. + doing monkeysphere gen_subkey. * add transition infrastructure for major changes between releases (see transitions/README.txt) + * implement and document two new monkeysphere-host subcommands: + revoke-key and add-revoker - -- Jameson Graef Rollins <jrollins@finestructure.net> Thu, 19 Feb 2009 15:11:04 -0500 + -- Daniel Kahn Gillmor <dkg@fifthhorseman.net> Fri, 20 Feb 2009 12:37:34 -0500 monkeysphere (0.22-1) unstable; urgency=low diff --git a/packaging/debian/monkeysphere.prerm b/packaging/debian/monkeysphere.prerm index 1fb2636..5835f53 100755 --- a/packaging/debian/monkeysphere.prerm +++ b/packaging/debian/monkeysphere.prerm @@ -5,6 +5,8 @@ # Author: Jameson Rollins <jrollins@finestructure.net> # Copyright 2008-2009 +true + # dh_installdeb will replace this with shell code automatically # generated by other debhelper scripts. diff --git a/src/monkeysphere b/src/monkeysphere index a65cef6..371983f 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -12,6 +12,8 @@ # or later. ######################################################################## +set -e + PGRM=$(basename $0) SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"} @@ -27,9 +29,6 @@ DATE=$(date -u '+%FT%T') # unset some environment variables that could screw things up unset GREP_OPTIONS -# default return code -RETURN=0 - # set the file creation mask to be only owner rw umask 077 @@ -87,9 +86,9 @@ check_gpg_sec_key_id() { echo "$gpgSecOut" | cut -d: -f5 ;; *) - echo "Multiple primary secret keys found:" | log error - echo "$gpgSecOut" | cut -d: -f5 | log error - echo "Please specify which primary key to use." | log error + echo "Multiple primary secret keys found:" + echo "$gpgSecOut" | cut -d: -f5 + echo "Please specify which primary key to use." failure ;; esac @@ -123,7 +122,7 @@ check_gpg_authentication_subkey() { fi # if authentication key is valid, prompt to continue if [ "$validity" = 'u' ] ; then - echo "A valid authentication key already exists for primary key '$keyID'." + echo "A valid authentication key already exists for primary key '$keyID'." 1>&2 if [ "$PROMPT" = "true" ] ; then read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N} if [ "${OK/y/Y}" != 'Y' ] ; then @@ -203,13 +202,11 @@ case $COMMAND in # those hosts if [ "$1" ] ; then update_known_hosts "$@" - RETURN="$?" # otherwise, if no hosts are specified, process every host # in the user's known_hosts file else process_known_hosts - RETURN="$?" fi ;; @@ -219,7 +216,6 @@ case $COMMAND in # process authorized_user_ids file process_authorized_user_ids "$AUTHORIZED_USER_IDS" - RETURN="$?" ;; 'import-subkey'|'i') @@ -255,5 +251,3 @@ case $COMMAND in Type '$PGRM help' for usage." ;; esac - -exit "$RETURN" diff --git a/src/monkeysphere-host b/src/monkeysphere-host index 4c7df88..540a8ab 100755 --- a/src/monkeysphere-host +++ b/src/monkeysphere-host @@ -54,14 +54,15 @@ usage: $PGRM <subcommand> [options] [args] Monkeysphere host admin tool. subcommands: - import-key (i) FILE [NAME[:PORT]] import existing ssh key to gpg + import-key (i) FILE NAME[:PORT] import existing ssh key to gpg show-key (s) output all host key information + publish-key (p) publish host key to keyserver set-expire (e) [EXPIRE] set host key expiration add-hostname (n+) NAME[:PORT] add hostname user ID to host key revoke-hostname (n-) NAME[:PORT] revoke hostname user ID - add-revoker (o) [KEYID|FILE] add a revoker to the host key - revoke-key (r) revoke host key - publish-key (p) publish host key to keyserver + add-revoker (r+) [KEYID|FILE] add a revoker to the host key + revoke-key generate and/or publish revocation + certificate for host key version (v) show version number help (h,?) this help @@ -268,14 +269,14 @@ case $COMMAND in revoke_hostname "$@" ;; - 'add-revoker'|'o') + 'add-revoker'|'r+') check_host_no_key load_fingerprint source "${MHSHAREDIR}/add_revoker" add_revoker "$@" ;; - 'revoke-key'|'r') + 'revoke-key') check_host_no_key load_fingerprint source "${MHSHAREDIR}/revoke_key" diff --git a/src/share/common b/src/share/common index 653d58b..5e0cb6a 100644 --- a/src/share/common +++ b/src/share/common @@ -586,8 +586,8 @@ gpg2authorized_keys() { # FIXME: need to figure out how to retrieve all matching keys # (not just first N (5 in this case)) gpg_fetch_userid() { + local returnCode=0 local userID - local returnCode if [ "$CHECK_KEYSERVER" != 'true' ] ; then return 0 @@ -626,6 +626,7 @@ gpg_fetch_userid() { # # expects global variable: "MODE" process_user_id() { + local returnCode=0 local userID local requiredCapability local requiredPubCapability @@ -657,10 +658,10 @@ process_user_id() { # output gpg info for (exact) userid and store gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \ --with-fingerprint --with-fingerprint \ - ="$userID" 2>/dev/null) + ="$userID" 2>/dev/null) || returnCode="$?" # if the gpg query return code is not 0, return 1 - if [ "$?" -ne 0 ] ; then + if [ "$returnCode" -ne 0 ] ; then log verbose " no primary keys found." return 1 fi @@ -890,6 +891,7 @@ process_host_known_hosts() { # update the known_hosts file for a set of hosts listed on command # line update_known_hosts() { + local returnCode=0 local nHosts local nHostsOK local nHostsBAD @@ -919,9 +921,9 @@ update_known_hosts() { for host ; do # process the host - process_host_known_hosts "$host" + process_host_known_hosts "$host" || returnCode="$?" # note the result - case "$?" in + case "$returnCode" in 0) nHostsOK=$((nHostsOK+1)) ;; @@ -1043,6 +1045,7 @@ process_uid_authorized_keys() { # update the authorized_keys files from a list of user IDs on command # line update_authorized_keys() { + local returnCode=0 local userID local nIDs local nIDsOK @@ -1072,10 +1075,10 @@ update_authorized_keys() { for userID ; do # process the user ID, change return code if key not found for # user ID - process_uid_authorized_keys "$userID" + process_uid_authorized_keys "$userID" || returnCode="$?" # note the result - case "$?" in + case "$returnCode" in 0) nIDsOK=$((nIDsOK+1)) ;; diff --git a/src/share/m/ssh_proxycommand b/src/share/m/ssh_proxycommand index bd09588..abe068d 100644 --- a/src/share/m/ssh_proxycommand +++ b/src/share/m/ssh_proxycommand @@ -18,6 +18,7 @@ # "marginal case" ouput in the case that there is not a full # validation path to the host output_no_valid_key() { + local returnCode=0 local sshKeyOffered local userID local type @@ -112,11 +113,11 @@ EOF fi ;; esac - done + done || returnCode="$?" # if no key match was made (and the "while read" subshell returned # 1) output how many keys were found - if (($? != 1)) ; then + if (( returnCode != 1 )) ; then cat <<EOF | log info None of the found keys matched the key offered by the host. Run the following command for more info about the found keys: @@ -200,12 +201,13 @@ fi CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER} # update the known_hosts file for the host -update_known_hosts "$HOSTP" +local returnCode=0 +update_known_hosts "$HOSTP" || returnCode="$?" # output on depending on the return of the update-known_hosts # subcommand, which is (ultimately) the return code of the # update_known_hosts function in common -case $? in +case "$returnCode" in 0) # acceptable host key found so continue to ssh true diff --git a/src/share/m/subkey_to_ssh_agent b/src/share/m/subkey_to_ssh_agent index 818f4f7..7fb2fdb 100644 --- a/src/share/m/subkey_to_ssh_agent +++ b/src/share/m/subkey_to_ssh_agent @@ -14,11 +14,11 @@ # try to add all authentication subkeys to the agent subkey_to_ssh_agent() { - local sshaddresponse + local sshaddresponse=0 local secretkeys local authsubkeys local workingdir - local keysuccess + local keysuccess=0 local subkey local publine local kname @@ -38,8 +38,7 @@ For more details, see: # and if it looks like it's running, but we can't actually talk to # it, bail out: - ssh-add -l >/dev/null - sshaddresponse="$?" + ssh-add -l >/dev/null || sshaddresponse="$?" if [ "$sshaddresponse" = "2" ]; then failure "Could not connect to ssh-agent" fi @@ -100,8 +99,7 @@ You might want to 'monkeysphere gen-subkey'" passphrase_prompt "Enter passphrase for key $kname: " "$workingdir/passphrase" wait %2 - fi - keysuccess="$?" + fi || keysuccess="$?" rm -f "$workingdir/$kname" done @@ -112,5 +110,5 @@ You might want to 'monkeysphere gen-subkey'" # FIXME: sort out the return values: we're just returning the # success or failure of the final authentication subkey in this # case. What if earlier ones failed? - exit "$keysuccess" + return "$keysuccess" } diff --git a/src/share/ma/add_certifier b/src/share/ma/add_certifier index f2cadf2..6f85ecf 100644 --- a/src/share/ma/add_certifier +++ b/src/share/ma/add_certifier @@ -120,14 +120,24 @@ else # get the full fingerprint of new certifier key log debug "getting fingerprint of certifier key..." fingerprint=$(gpg_sphere "--list-key --with-colons --with-fingerprint 0x${keyID}!" \ - | grep '^fpr:' | grep "$keyID" | cut -d: -f10) + | grep '^fpr:' | cut -d: -f10) + + # test that there is only a single fingerprint + if (( $(echo "$fingerprint" | wc -l) != 1 )) ; then + cat <<EOF +More than one fingerprint found: +$fingerprint +Please use a more specific key ID. +EOF + failure + fi log info "key found:" gpg_sphere "--fingerprint 0x${fingerprint}!" if [ "$PROMPT" = "true" ] ; then - echo "Are you sure you want to add the above key as a" - read -p "certifier of users on this system? (Y/n) " OK; OK=${OK:-Y} + echo "Are you sure you want to add the above key as a certifier" + read -p "of users on this system? (Y/n) " OK; OK=${OK:-Y} if [ "${OK/y/Y}" != 'Y' ] ; then failure "Identity certifier not added." fi diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics index ce463b2..8fc4b31 100644 --- a/src/share/ma/diagnostics +++ b/src/share/ma/diagnostics @@ -105,7 +105,7 @@ echo echo "Checking for Identity Certifiers..." if ! monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' then echo "! No Identity Certifiers found!" - echo " - Recommendation: once you know who should be able to certify identities for + echo " - Recommendation: once you know who should be able to certify the identities of connecting users, you should add their key, with: monkeysphere-authentication add-identity-certifier" problemsfound=$(($problemsfound+1)) diff --git a/src/share/ma/remove_certifier b/src/share/ma/remove_certifier index a9a1451..6c90358 100644 --- a/src/share/ma/remove_certifier +++ b/src/share/ma/remove_certifier @@ -27,7 +27,7 @@ fi gpg_core --list-key --fingerprint "0x${keyID}!" || failure if [ "$PROMPT" = "true" ] ; then - read -p "Really remove the identity certifier above? (Y/n) " OK; OK=${OK:-Y} + read -p "Really remove the above listed identity certifier? (Y/n) " OK; OK=${OK:-Y} if [ "${OK/y/Y}" != 'Y' ] ; then failure "Identity certifier not removed." fi diff --git a/src/share/ma/update_users b/src/share/ma/update_users index 092d108..bfefc31 100644 --- a/src/share/ma/update_users +++ b/src/share/ma/update_users @@ -93,8 +93,8 @@ for uname in $unames ; do # process authorized_user_ids file, as monkeysphere user su_monkeysphere_user \ - ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS" - RETURN="$?" + ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS" \ + || RETURN="$?" else log debug "not processing authorized_user_ids." fi @@ -154,4 +154,5 @@ for uname in $unames ; do rm -rf "$TMPLOC" done +return $RETURN } diff --git a/src/share/mh/add_hostname b/src/share/mh/add_hostname index 0da6a06..b08d688 100644 --- a/src/share/mh/add_hostname +++ b/src/share/mh/add_hostname @@ -32,9 +32,9 @@ find_host_userid > /dev/null && \ failure "Host userID '$userID' already exists." if [ "$PROMPT" = "true" ] ; then - echo "The following user ID will be added to the host key:" - echo " $userID" - read -p "Are you sure you would like to add this user ID? (Y/n) " OK; OK=${OK:=Y} + read -p "The following user ID will be added to the host key: + $userID +Are you sure you would like to add this user ID? (Y/n) " OK; OK=${OK:=Y} if [ "${OK/y/Y}" != 'Y' ] ; then failure "User ID not added." fi diff --git a/src/share/mh/add_revoker b/src/share/mh/add_revoker index 428b958..03ae56f 100644 --- a/src/share/mh/add_revoker +++ b/src/share/mh/add_revoker @@ -74,14 +74,24 @@ else # get the full fingerprint of new revoker key log debug "getting fingerprint of revoker key..." fingerprint=$(su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --list-key --with-colons --with-fingerprint 0x${keyID}!" \ - | grep '^fpr:' | grep "$keyID" | cut -d: -f10) + | grep '^fpr:' | cut -d: -f10) + + # test that there is only a single fingerprint + if (( $(echo "$fingerprint" | wc -l) != 1 )) ; then + cat <<EOF +More than one fingerprint found: +$fingerprint +Please use a more specific key ID. +EOF + failure + fi log info "key found:" su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --fingerprint 0x${fingerprint}!" if [ "$PROMPT" = "true" ] ; then - echo "Are you sure you want to add the above key as a" - read -p "revoker of the host key? (Y/n) " OK; OK=${OK:-Y} + read -p "Are you sure you want to add the above key as a revoker +of the host key? (Y/n) " OK; OK=${OK:-Y} if [ "${OK/y/Y}" != 'Y' ] ; then failure "revoker not added." fi diff --git a/src/share/mh/import_key b/src/share/mh/import_key index 040b41c..f7c69c3 100644 --- a/src/share/mh/import_key +++ b/src/share/mh/import_key @@ -26,20 +26,9 @@ if [ -z "$sshKeyFile" ] ; then failure "Must specify ssh key file to import, or specify '-' for stdin." fi -# use the default hostname if not specified +# fail if hostname not specified if [ -z "$hostName" ] ; then - hostName=$(hostname -f) || failure "Could not determine hostname." - # test that the domain is not obviously illegitimate - domain=${foo##*.} - case $domain in - 'local'|'localdomain') - failure "Host domain '$domain' is not legitimate. Aborting key import." - ;; - esac - # test that there are at least two parts - if (( $(echo "$hostName" | tr . ' ' | wc -w) < 2 )) ; then - failure "Host name '$hostName' is not legitimate. Aborting key import." - fi + failure "You must specify a fully-qualified domain name for use in the host certificate user ID." fi userID="ssh://${hostName}" diff --git a/src/share/mh/revoke_hostname b/src/share/mh/revoke_hostname index 71b56ed..2142af7 100644 --- a/src/share/mh/revoke_hostname +++ b/src/share/mh/revoke_hostname @@ -43,9 +43,9 @@ uidIndex=$(find_host_userid) || \ failure "No non-revoked user ID found matching '$userID'." if [ "$PROMPT" = "true" ] ; then - echo "The following host key user ID will be revoked:" - echo " $userID" - read -p "Are you sure you would like to revoke this user ID? (N/y) " OK; OK=${OK:=Y} + read -p "The following host key user ID will be revoked: + $userID +Are you sure you would like to revoke this user ID? (Y/n) " OK; OK=${OK:=Y} if [ "${OK/y/Y}" != 'Y' ] ; then failure "User ID not revoked." fi diff --git a/src/share/mh/revoke_key b/src/share/mh/revoke_key index 380236b..ad68d5f 100644 --- a/src/share/mh/revoke_key +++ b/src/share/mh/revoke_key @@ -18,6 +18,28 @@ revoke_key() { # Coming in here, we expect $HOST_FINGERPRINT to be set, and we # believe that there is in fact a key. + if [ "$PROMPT" = "false" ] ; then + publish=N + else + cat <<EOF >&2 +This will generate a revocation certificate for your host key +(fingerprint: $HOST_FINGERPRINT) and +dump the certificate to standard output. + +It can also directly publish the new revocation certificate +to the public keyservers via $KEYSERVER if you want it to. + +Publishing this certificate will IMMEDIATELY and PERMANENTLY revoke +your host key! + +EOF + read -p "Publish the certificate after generation? (y/n/Q) " publish + + if ! [ "${publish/y/Y}" = 'Y' -o "${publish/n/N}" = 'N' ] ; then + failure "aborting at user request" + fi + fi + # our current implementation is very simple: we just want to # generate the revocation certificate on stdout. This provides # for the two most likely (but hopefully not common) scenarios: @@ -28,18 +50,52 @@ revoke_key() { # transcribe from the terminal. # Alternately, an admin might want to publish the revocation - # certificate immediately. here's a quick way to do this: + # certificate immediately, which we can help them do as well. + + if [ "$PROMPT" = 'false' ] ; then + # FIXME: allow the end user to choose something other than + # "key was compromised" (1) and to supply their own revocation + # string. + local revoke_commands="y +1 +Monkeysphere host key revocation (automated) $(date '+%F_%T%z') - # tmp=$(mktemp -d) - # export GNUPGHOME="$tmp" - # gpg --import < /var/lib/monkeysphere/ssh_host_rsa_key.pub.gpg - # monkeysphere-host revoke-key | gpg --import - # gpg --keyserver pool.sks-keyservers.net --send $(hostname -f) +y +" + revcert=$(GNUPGHOME="$GNUPGHOME_HOST" gpg_host --command-fd 0 --armor --gen-revoke "0x${HOST_FINGERPRINT}!" <<<"$revoke_commands" ) \ + || failure "Failed to generate revocation certificate!" + + else # note: we're not using the gpg_host function because we actually # want to use gpg's UI in this case, so we want to omit --no-tty + revcert=$(GNUPGHOME="$GNUPGHOME_HOST" gpg --no-greeting --quiet --armor --gen-revoke "0x${HOST_FINGERPRINT}!") \ + || failure "Failed to generate revocation certificate!" + fi + + # if you run gpg --gen-revoke but cancel it or quit in the middle, + # it returns success, but emits no revocation certificate: + if ! [ "$revcert" ] ; then + failure "Revocation canceled." + fi + + ## ok, now we have the revocation certificate. Print it, and + ## offer to publish if originally requested: + printf "%s\n" "$revcert" - GNUPGHOME="$GNUPGHOME_HOST" gpg --no-greeting --quiet --armor --gen-revoke "0x${HOST_FINGERPRINT}!" + if [ "${publish/y/Y}" = 'Y' ] ; then + printf "\n" >&2 + read -p "Really publish this cert to $KEYSERVER ? (Y/n) " really + if [ "${really/n/N}" = 'N' ] ; then + printf "Not publishing.\n" >&2 + else + local newhome=$(mkmstempdir) + GNUPGHOME="$newhome" gpg --no-tty --quiet --import < "$HOST_KEY_FILE" + GNUPGHOME="$newhome" gpg --no-tty --quiet --import <<< "$revcert" + GNUPGHOME="$newhome" gpg --keyserver "$KEYSERVER" --send "0x${HOST_FINGERPRINT}!" + rm -rf "$newhome" + fi + fi } diff --git a/tests/basic b/tests/basic index 3d50977..9c5b280 100755 --- a/tests/basic +++ b/tests/basic @@ -12,6 +12,8 @@ # these tests should all be able to run as a non-privileged user. +# put all the test output to stdout +exec 2>&1 # all subcommands in this script should complete without failure: set -e # piped commands should return the code of the first non-zero return @@ -26,6 +28,14 @@ source "$TESTDIR"/common ## test has *more* requirements than plain ol' monkeysphere: which socat >/dev/null || { echo "You must have socat installed to run this test." ; exit 1; } +perl -MCrypt::OpenSSL::RSA -e 1 2>/dev/null || { echo "You must have the perl module Crypt::OpenSSL::RSA installed to run this test. +On debian-derived systems, you can set this up with: + apt-get install libcrypt-openssl-rsa-perl" ; exit 1; } + + +perl -MDigest::SHA1 -e 1 2>/dev/null || { echo "You must have the perl module Digest::SHA1 installed to run this test. +On debian-derived systems, you can set this up with: + apt-get install libdigest-sha1-perl" ; exit 1; } ## FIXME: other checks? @@ -35,7 +45,7 @@ which socat >/dev/null || { echo "You must have socat installed to run this test # gpg command for test admin user gpgadmin() { chmod 0700 "$TEMPDIR"/admin - GNUPGHOME="$TEMPDIR"/admin/.gnupg gpg "$@" + GNUPGHOME="$TEMPDIR"/admin/.gnupg gpg --no-tty "$@" } # test ssh connection @@ -55,20 +65,16 @@ ssh_test() { sleep 1 done - set +e - # make a client connection to the socket echo "##### starting ssh client..." ssh-agent bash -c \ - "monkeysphere subkey-to-ssh-agent && ssh -F $TEMPDIR/testuser/.ssh/config testhost true" - RETURN="$?" + "monkeysphere subkey-to-ssh-agent && ssh -F $TEMPDIR/testuser/.ssh/config testhost true" \ + || RETURN="$?" # kill the sshd process if it's still running kill "$SSHD_PID" SSHD_PID= - set -e - echo "##### return $RETURN" if [ "$RETURN" = "$CODE" ] ; then echo "##### ssh connection test returned as desired" @@ -110,7 +116,13 @@ export MONKEYSPHERE_SYSDATADIR="$TEMPDIR" export MONKEYSPHERE_SYSCONFIGDIR="$TEMPDIR" export MONKEYSPHERE_SYSSHAREDIR="$TESTDIR"/../src/share export MONKEYSPHERE_MONKEYSPHERE_USER=$(whoami) + export MONKEYSPHERE_CHECK_KEYSERVER=false +# example.org does not respond to the HKP port, so this should cause +# any keyserver connection attempts that do happen (they shouldn't!) +# to hang, so we'll notice them: +export MONKEYSPHERE_KEYSERVER=example.org + export MONKEYSPHERE_LOG_LEVEL=DEBUG export MONKEYSPHERE_CORE_KEYLENGTH=1024 export MONKEYSPHERE_PROMPT=false @@ -128,6 +140,7 @@ export DISPLAY=monkeys ## (don't bother if this is being run from the tests). if [ -f "$TESTDIR"/../packaging/debian/changelog ]; then + echo echo "##################################################" echo "### checking version string match..." repver=$(monkeysphere version) @@ -144,6 +157,7 @@ fi ### CONFIGURE ENVIRONMENTS # copy in admin and testuser home to tmp +echo echo "##################################################" echo "### configuring testuser home..." cp -a "$TESTDIR"/home/testuser "$TEMPDIR"/ @@ -163,11 +177,13 @@ KNOWN_HOSTS=$TESTHOME/.ssh/known_hosts EOF get_gpg_prng_arg >> "$GNUPGHOME"/gpg.conf +echo echo "##################################################" echo "### configuring admin home..." cp -a "$TESTDIR"/home/admin "$TEMPDIR"/ # set up sshd +echo echo "##################################################" echo "### configuring sshd..." cp "$TESTDIR"/etc/ssh/sshd_config "$SSHD_CONFIG" @@ -182,17 +198,20 @@ EOF ### SERVER HOST SETUP # import host key +echo echo "##################################################" echo "### import host key..." ssh-keygen -b 1024 -t rsa -N '' -f "$TEMPDIR"/ssh_host_rsa_key monkeysphere-host import-key "$TEMPDIR"/ssh_host_rsa_key testhost +echo echo "##################################################" echo "### getting host key fingerprint..." HOSTKEYID=$( monkeysphere-host show-key | grep '^OpenPGP fingerprint: ' | cut -f3 -d\ ) echo "$HOSTKEYID" # change host key expiration +echo echo "##################################################" echo "### setting host key expiration..." monkeysphere-host set-expire 1 @@ -200,9 +219,10 @@ monkeysphere-host set-expire 1 # certify host key with the "Admin's Key". # (this would normally be done via keyservers) +echo echo "##################################################" echo "### certifying server host key..." -GNUPGHOME="$MONKEYSPHERE_SYSCONFIGDIR"/host gpg --armor --export "$HOSTKEYID" | gpgadmin --import +< "$MONKEYSPHERE_SYSCONFIGDIR"/ssh_host_rsa_key.pub.gpg gpgadmin --import echo y | gpgadmin --command-fd 0 --sign-key "$HOSTKEYID" # FIXME: add revoker? @@ -217,6 +237,7 @@ echo y | gpgadmin --command-fd 0 --sign-key "$HOSTKEYID" ### SERVER AUTHENTICATION SETUP # set up monkeysphere authentication +echo echo "##################################################" echo "### setup monkeysphere authentication..." cp "$TESTDIR"/etc/monkeysphere/monkeysphere-authentication.conf "$TEMPDIR"/ @@ -227,10 +248,12 @@ monkeysphere-authentication setup get_gpg_prng_arg >> "$MONKEYSPHERE_SYSDATADIR"/authentication/sphere/gpg.conf # add admin as identity certifier for testhost +echo echo "##################################################" echo "### adding admin as certifier..." monkeysphere-authentication add-id-certifier "$TEMPDIR"/admin/.gnupg/pubkey.gpg +echo echo "##################################################" echo "### list certifiers..." monkeysphere-authentication list-certifiers @@ -241,21 +264,25 @@ monkeysphere-authentication list-certifiers ### TESTUSER SETUP # generate an auth subkey for the test user that expires in 2 days +echo echo "##################################################" echo "### generating key for testuser..." monkeysphere gen-subkey # add server key to testuser keychain +echo echo "##################################################" echo "### export server key to testuser..." gpgadmin --armor --export "$HOSTKEYID" | gpg --import # teach the "server" about the testuser's key +echo echo "##################################################" echo "### export testuser key to server..." gpg --export testuser | monkeysphere-authentication gpg-cmd --import # update authorized_keys for user +echo echo "##################################################" echo "### update server authorized_keys file for this testuser..." monkeysphere-authentication update-users $(whoami) @@ -268,16 +295,19 @@ monkeysphere-authentication update-users $(whoami) # connect to test sshd, using monkeysphere ssh-proxycommand to verify # the identity before connection. This should work in both directions! +echo echo "##################################################" echo "### ssh connection test for success..." ssh_test # remove the testuser's authorized_user_ids file, update, and make # sure that the ssh authentication FAILS +echo echo "##################################################" echo "### removing testuser authorized_user_ids and updating..." mv "$TESTHOME"/.monkeysphere/authorized_user_ids{,.bak} monkeysphere-authentication update-users $(whoami) +echo echo "##################################################" echo "### ssh connection test for server authentication denial..." ssh_test 255 @@ -285,35 +315,50 @@ mv "$TESTHOME"/.monkeysphere/authorized_user_ids{.bak,} # put improper permissions on authorized_user_ids file, update, and # make sure ssh authentication FAILS +echo echo "##################################################" echo "### setting group writability on authorized_user_ids and updating..." chmod g+w "$TESTHOME"/.monkeysphere/authorized_user_ids monkeysphere-authentication update-users $(whoami) +echo echo "##################################################" echo "### ssh connection test for server authentication denial..." ssh_test 255 chmod g-w "$TESTHOME"/.monkeysphere/authorized_user_ids +echo echo "##################################################" echo "### setting other writability on authorized_user_ids and updating..." chmod o+w "$TESTHOME"/.monkeysphere/authorized_user_ids monkeysphere-authentication update-users $(whoami) +echo echo "##################################################" echo "### ssh connection test for server authentication denial..." ssh_test 255 chmod o-w "$TESTHOME"/.monkeysphere/authorized_user_ids +monkeysphere-authentication update-users $(whoami) # FIXME: addtest: remove admin as id-certifier and check ssh failure # FIXME: addtest: add hostname on host key # FIXME: addtest: revoke hostname on host key and check ssh failure -# FIXME: addtest: revoke the host key and check ssh failure +# addtest: revoke the host key and check ssh failure +# test to make sure things are OK after the previous tests: +ssh_test +echo +echo "##################################################" +echo "### ssh connection test for server with revoked key..." +# generate the revocation certificate and feed it directly to the test +# user's keyring (we're not publishing to the keyservers) +monkeysphere-host revoke-key | gpg --import +ssh_test 255 ###################################################################### trap - EXIT +echo echo "##################################################" echo " Monkeysphere basic tests completed successfully!" echo "##################################################" diff --git a/tests/common b/tests/common index 0f90500..30c6a82 100644 --- a/tests/common +++ b/tests/common @@ -5,6 +5,8 @@ failed_cleanup() { echo 'FAILED!' read -p "press enter to cleanup and remove tmp (or type bash for a subshell to examine): " XX if [ "$XX" = bash ] ; then + echo "Entering subshell..." + cd "$TEMPDIR" bash fi diff --git a/website/advanced-user.mdwn b/website/advanced-user.mdwn new file mode 100644 index 0000000..7969018 --- /dev/null +++ b/website/advanced-user.mdwn @@ -0,0 +1,137 @@ +[[meta title="Advanced usage of the Monkeysphere"]] + +Advanced usage of the monkeysphere +================================== + + +Keeping your `known_hosts` file in sync with your keyring +--------------------------------------------------------- + +If you want to keep your keyring updated without attempting +connections to a remote host, you want to make sure that OpenSSH can +still see the most recent trusted information about who the various +hosts are. You might also want to check on hosts that were not +originally in the Monkeysphere, to see if their host key is now +published. + +You can do this kind of independent update with the +`update-known_hosts` command: + + $ monkeysphere update-known_hosts + +This command will check to see if there is an OpenPGP key for each +(non-hashed) host listed in the `known_hosts` file, and then add the +key for that host to the `known_hosts` file if one is found. This +command could be added to a crontab, if desired. + + + +Establishing trust +------------------ + +The Monkeysphere is predicated on the idea that users and +administrators know each other (or know people who know each other, +etc). It uses the Web of Trust to explicitly represent those links. +If you haven't used the Web of Trust explicitly, you will need to +establish an acceptable trust path to the admin(s) of the +monkeysphere-enabled servers that you will be connecting to. You need +to do this because the admin is certifying the host, and you need a +mechanism to validate that certification. The only way to do that is +by indicating who you trust to certify hosts. This is a two step +process: first you must sign the key, and then you have to indicate a +trust level. If you do not indicate that you trust the administrator +to certify host keys, then the monkeysphere will show you her +certification on every connection, but will not treat it as an +automatic verification. + +The process of signing another key is outside the scope of this +document, however the [gnupg +README](http://cvs.gnupg.org/cgi-bin/viewcvs.cgi/branches/STABLE-BRANCH-1-4/README?root=GnuPG&view=markup) +details the signing process and you can find good [documentation +](http://www.debian.org/events/keysigning) online detailing this +process. + +If you have signed your admins' key, you need to denote some kind of +trust to that key. To do this you should edit the key and use the +'trust' command. For the Monkeysphere to trust the assertions that are +made about a host, you need full calculated validity to the host +certifiers. This can be done either by giving full trust to one +host-certifying key, or by giving marginal trust to three different +host-certifiers. In the following we demonstrate how to add full trust +validity to a host-certifying key: + + + $ gpg --edit-key 'Jane Admin' + gpg (GnuPG) 1.4.9; Copyright (C) 2008 Free Software Foundation, Inc. + This is free software: you are free to change and redistribute it. + There is NO WARRANTY, to the extent permitted by law. + + + pub 4096R/ABCD123A created: 2007-06-02 expires: 2012-05-31 usage: SC + trust: unknown validity: full + sub 2048R/01DECAF7 created: 2007-06-02 expires: 2012-05-31 usage: E + [ full ] (1). Jane Admin <jane_admin@example.net> + + Command> trust + pub 4096R/ABCD123A created: 2007-06-02 expires: 2012-05-31 usage: SC + trust: unknown validity: full + sub 2048R/01DECAF7 created: 2007-06-02 expires: 2012-05-31 usage: E + [ full ] (1). Jane Admin <jane_admin@example.net> + + Please decide how far you trust this user to correctly verify other users' keys + (by looking at passports, checking fingerprints from different sources, etc.) + + 1 = I don't know or won't say + 2 = I do NOT trust + 3 = I trust marginally + 4 = I trust fully + 5 = I trust ultimately + m = back to the main menu + + Your decision? 4 + + pub 4096R/ABCD123A created: 2007-06-02 expires: 2012-05-31 usage: SC + trust: full validity: full + sub 2048R/01DECAF7 created: 2007-06-02 expires: 2012-05-31 usage: E + [ full ] (1). Jane Admin <jane_admin@example.net> + Please note that the shown key validity is not necessarily correct + unless you restart the program. + + Command> save + Key not changed so no update needed. + $ + +Note: Due to a limitation with gnupg, it is not currently possible to +limit the domain scope properly, which means that if you fully trust +an admin, you'll trust all their certifications. + +Because the Monkeysphere currently relies on GPG's definition of the +OpenPGP web of trust, it is important to understand [how GPG +calculates User ID validity for a key](/trust-models). + + +Miscellaneous +------------- + +Users can also maintain their own `~/.ssh/authorized_keys` files with +the Monkeysphere directly. This is primarily useful for accounts on +hosts that are not already systematically using the Monkeysphere for +user authentication. If you're not sure whether this is the case for +your host, ask your system administrator. + +If you want to do this as a regular user, use the +`update-authorized_keys` command: + + $ monkeysphere update-authorized_keys + +This command will take all the user IDs listed in the +`~/.monkeysphere/authorized_user_ids` file and check to see if +there are acceptable keys for those user IDs available. If so, they +will be added to the `~/.ssh/authorized_keys` file. + +You must have indicated reasonable ownertrust in some key for this +account, or no keys will be found with trusted certification paths. + +If you find this useful, you might want to place this command in your +crontab so that revocations and rekeyings can take place +automatically. diff --git a/website/doc.mdwn b/website/doc.mdwn index 28db2ef..47b173a 100644 --- a/website/doc.mdwn +++ b/website/doc.mdwn @@ -10,11 +10,13 @@ ## Going further ## + * [Advanced Monkeysphere usage](/advanced-user) * [Signing host keys](/signing-host-keys) + * [Understanding trust models](/trust-models) ## Under the hood ## - * [Developing the monkeysphere](/community) + * [Developing the Monkeysphere](/community) * [Technical details](/technical-details) ## References ## diff --git a/website/getting-started-admin.mdwn b/website/getting-started-admin.mdwn index 9010132..ca44956 100644 --- a/website/getting-started-admin.mdwn +++ b/website/getting-started-admin.mdwn @@ -2,21 +2,15 @@ Monkeysphere Server Administrator README ======================================== As the administrator of an SSH server, you can take advantage of the -monkeysphere in two ways: +Monkeysphere in two ways: 1. you can publish the host key of your machine to the Web of Trust -(WoT) so that your users can have it automatically verified, and +(WoT) so that your users can automatically verify it, and 2. you can set up your machine to automatically identify connecting users by their presence in the OpenPGP Web of Trust. -These things are not mutually required, and it is in fact possible to -do one without the other. However, it is highly recommend that you at -least do the first. Even if you decide that you do not want to use -the monkeysphere to authenticate users to your system, you should at -least the host key into the Web of Trust so that your users can be -sure they're connecting to the correct machine. - +These two pieces are independent: you can do one without the other. Monkeysphere for host verification (monkeysphere-host) ====================================================== @@ -28,33 +22,44 @@ To begin, you must first import an ssh host key. This assumes that you have the ssh server installed, and that you have generated a host RSA key. Once that has been done, import the key: - # monkeysphere-host /etc/ssh/ssh\_host\_rsa\_key + # monkeysphere-host import-key /etc/ssh/ssh_host_rsa_key server.example.net + +This will generate an OpenPGP certificate for the server. The primary +user ID for this certificate will be the ssh service URI for the host, +(eg. `ssh://server.example.net`). Remember that the name you provide +here should probably be a fully qualified domain name for the host in +order for your users to find it. -This will generate the key for server with the service URI -(`ssh://server.example.net`). You can output the new key information -with the 'show-key' command: +Now you can display information about the host key's certificate with +the 'show-key' command: # monkeysphere-host show-key -Once the key has been imported, it needs to be publish to the Web of -Trust: +Once the host key's certificate has been generated, you'll probably +want to publish it to the public keyservers which distribute the Web +of Trust: # monkeysphere-host publish-key -The server admin should now sign the server key so that people in the -admin's web of trust can identify the server without manual host key -checking. On your (the admin's) local machine retrieve the host key: - - $ gpg --search '=ssh://server.example.net' +But anyone could publish a simple self-signed certificate to the WoT +with any name attached. Your users should be able to tell that +someone they know and trust with the machine (e.g. *you*, the +administrator) has verified that this particular key is indeed the +correct key. So your next step is to sign the host's key with your +own OpenPGP key. -Now sign the server key: +On your (the admin's) local machine retrieve the host key (it may take +several minutes for the key to propagate across the keyserver +network), and sign it: + $ gpg --search '=ssh://server.example.net' $ gpg --sign-key '=ssh://server.example.net' -Make sure you compare the fingerprint of the retrieved with the one -output with the 'show-key' command above, to verify you are signing -the correct key. Finally, publish your signatures back to the -keyservers: +Make sure you compare the fingerprint of the retrieved certificate +with the output from the 'show-key' command above! + +Finally, publish your signatures back to the keyservers, so that your +users can automatically verify your machine when they connect: $ gpg --send-key '=ssh://server.example.net' @@ -64,10 +69,18 @@ signing host keys. Monkeysphere for user authentication (monkeysphere-authentication) ================================================================== -A host can maintain ssh `authorized_keys` files automatically for its -users with the Monkeysphere. These `authorized_keys` files can then -be used to enable users to use the monkeysphere to authenticate to -your machine using the OpenPGP web of trust. +A host can maintain ssh-style `authorized_keys` files automatically +for its users with the Monkeysphere. This frees you (the +administrator) from the task of manually checking/placing SSH keys, +and enables users to do relatively painless key transitions, and to +quickly and universally revoke access if they find that their ssh key +has become compromised. + +You simply tell the system what *person* (identified by her OpenPGP +User ID) should have access to an account, the Monkeysphere takes care +of generating the proper `authorized_keys` file and keeping it +up-to-date, and `sshd` reads the generated `authorized_keys` files +directly. Monkeysphere authorized_keys maintenance ---------------------------------------- @@ -77,20 +90,29 @@ to log into that account would be placed in: ~/.monkeysphere/authorized_user_ids -However, in order for users to become authenticated, the server must -determine that the user IDs on their keys have "full" validity. This -means that the server must fully trust at least one person whose -signature on the connecting user's key would validate the relevant -user ID. The individuals trusted to identify users like this are -known in the Monkeysphere as "Identity Certifiers". In a simple -scenario, the host's administrator would be a trusted identity -certifer. If the admin's OpenPGP keyid is `$GPGID`, then on the -server run: +The server will use the Monkeysphere to look up matching OpenPGP +certificates, validate them, and generate an `authorized_keys` file. + +To validate the OpenPGP certificates, the server needs to know who it +can trust to correctly identify users. The individuals trusted to +identify users like this are known in the Monkeysphere as "Identity +Certifiers". One obvious choice is to trust *you*, the administrator, +to be an Identity Certifier. If your OpenPGP keyid is `$GPGID`, then +run the following command on the server: # monkeysphere-authentication add-identity-certifier $GPGID -To update the monkeysphere `authorized_keys` file for user "bob" using -the current set of identity certifiers, run: +You'll probably only set up Identity Certifiers when you set up the +machine. After that, you'll only need to add or remove Identity +Certifiers when the roster of admins on the machine changes, or when +one of the admins switches OpenPGP keys. + +Now that the server knows who to trust to identify users, the +Monkeysphere can generate ssh-style `authorized_keys` quickly and +easily: + +To update the Monkeysphere-generated `authorized_keys` file for user +"bob", run: # monkeysphere-authentication update-users bob @@ -100,19 +122,21 @@ the system, run the same command with no arguments: # monkeysphere-authentication update-users You probably want to set up a regularly scheduled job (e.g. with cron) -to take care of this automatically. +to do this automatically. Update OpenSSH server AuthorizedKeysFile configuration ------------------------------------------------------ -SSH must be configured to point to the monkeysphere generated -`authorized_keys` file. Add this line to `/etc/ssh/sshd_config` -(again, making sure that no other AuthorizedKeysFile directive is left -uncommented): +Generating the `authorized_keys` files is not quite enough, because +`sshd` needs to know where to find the generated keys. + +You can do this by adding the following line to +`/etc/ssh/sshd_config`, commenting out any other `AuthorizedKeysFile` +directives: AuthorizedKeysFile /var/lib/monkeysphere/authorized_keys/%u You'll need to restart `sshd` to have your changes take effect. As -with any change to `sshd_config`, be sure to retain an existing -session to the machine while you test your changes so you don't get -locked out. +with any change to `sshd_config`, if you're doing this remotely, be +sure to retain an existing session to the machine while you test your +changes so you don't get locked out if something went wrong. diff --git a/website/getting-started-user.mdwn b/website/getting-started-user.mdwn index ec157ac..9e2be26 100644 --- a/website/getting-started-user.mdwn +++ b/website/getting-started-user.mdwn @@ -3,211 +3,178 @@ Monkeysphere User README You don't have to be an OpenSSH or OpenPGP expert to use the Monkeysphere. However, you should be comfortable using secure shell -(ssh), and you should already have GnuPG installed and an OpenPGP key -pair before you begin. +(ssh), and you should already have an OpenPGP key before you begin. -As a regular user on a system where the monkeysphere package is -installed, you probably want to do a few things: +As a user, the Monkeysphere lets you do two important things: +1. You can use the OpenPGP Web of Trust (WoT) to automatically verify +the identity of hosts you connect to. -Keep your keyring up-to-date ----------------------------- - -Regularly refresh your GnuPG keyring from the keyservers. This can be -done with a simple cronjob. An example of crontab line to do this is: - - 0 12 * * * /usr/bin/gpg --refresh-keys > /dev/null 2>&1 - -This would refresh your keychain every day at noon. - - -Install the monkeysphere software on your system ------------------------------------------------- - -If you haven't installed monkeysphere yet, you will need to [download -and install](/download) before continuing. - -Make sure that you have the GnuTLS library version 2.6 or later -installed on your system. If you can't (or don't want to) upgrade to -GnuTLS 2.6 or later, there are patches for GnuTLS 2.4 available in -[the Monkeysphere git repo](/community). +2. You can manage your own ssh identity on all Monkeysphere-enabled +servers using the WoT. +These two features are independent: you can do one without the other. -Keeping your `known_hosts` file in sync with your keyring ---------------------------------------------------------- -With your keyring updated, you want to make sure that OpenSSH can -still see the most recent trusted information about who the various -hosts are. This can be done with the monkeysphere-ssh-proxycommand -(see next section) or with the `update-known_hosts` command: +Identifying servers through the Web of Trust +============================================ - $ monkeysphere update-known_hosts +The simplest way to identify servers through the Web of Trust is to +tell `ssh` to use `monkeysphere ssh-proxycommand` to connect, instead +of connecting to the remote host directly. This command will make sure +the `known_hosts` file is up-to-date for the host you are connecting +to with ssh. -This command will check to see if there is an OpenPGP key for each -(non-hashed) host listed in the `known_hosts` file, and then add the -key for that host to the `known_hosts` file if one is found. This -command could be added to a crontab as well, if desired. +You can try this out when connecting to a server which has published +their host key to the monkeysphere with: + $ ssh -oProxyCommand='monkeysphere ssh-proxycommand %h %p' server.example.net -Using `monkeysphere-ssh-proxycommand`(1) ----------------------------------------- - -The best way to handle host keys is to use the monkeysphere ssh proxy -command. This command will make sure the `known_hosts` file is -up-to-date for the host you are connecting to with ssh. The best way -to integrate this is to add the following line to the "Host *" section -of your `~/.ssh/config` file: +If you want to have `ssh` always do this, just add the following line +to the "Host *" section of your `~/.ssh/config` file: ProxyCommand monkeysphere ssh-proxycommand %h %p The "Host *" section specifies what ssh options to use for all -connections. If you don't already have a "Host *" line, you can add it +connections. If you don't already have a "Host \*" line, you can add it by entering: Host * On a line by itself. Add the ProxyCommand line just below it. -Once you've completed this step - you are half-way there. You will now -be able to verify servers participating in the monkeysphere provided -their keys have been signed by someone that you trust. +Note that the Monkeysphere will help you identify servers whose host +keys are published in the WoT, and which are signed by people who you +know and trust to identify such things! -FIXME: We should setup a way for someone to download a test gpg key and -then connect to a test server that is signed by this gpg key so users -can establish that they are setup correctly. +If you aren't connected to your administrator(s) through the Web of +Trust, you should talk to them and establish that relationship. If +you have already established that relationship, but a server's host +key isn't published, you might suggest to your administrator that they +publish it. -The remaining steps will complete the second half: allowing servers to -verify you based on your OpenPGP key. +Managing your SSH identity through the Web of Trust +=================================================== -Setting up an OpenPGP authentication key ----------------------------------------- +You've already got an OpenPGP identity in the Web of Trust. But you +probably don't currently use it to identify yourself to SSH servers. -First things first: you'll need to have a OpenPGP "authentication" -subkey for your current key, if you don't already have one. If you -already have a GPG key, you can generate an authentication subkey with -the `gen-subkey` command: +To do that, you'll need to add an authentication-capable subkey to +your OpenPGP identity. You can do that with: $ monkeysphere gen-subkey If you have more than one secret key, you'll need to specify the key you want to add the subkey to on the command line. +Since this is a change to your key, you probably want to re-publish +your key to the public keyservers. If your key ID is $GPGID: + + $ gpg --keyserver pool.sks-keysevers.net --send-key $GPGID + +This way, remote services that use the monkeysphere for user +authentication will know about your SSH identity. + +You may need to wait a few minutes for your new key to propagate +around the keyserver network, and another little while for any remote +host running the monkeysphere to pick up the new subkey. -Using your OpenPGP authentication key for SSH ---------------------------------------------- + +Using your OpenPGP authentication key for SSH via ssh-agent(1) +-------------------------------------------------------------- Once you have created an OpenPGP authentication subkey, you will need -to feed it to your ssh agent. +to feed it to your `ssh-agent`. Your agent can then manage the key +for all of your ssh sessions. + +First make sure you have an agent running: + + $ ssh-add -l -The GnuTLS library supports this operation as of version 2.6, but -earlier versions do not. With a recent version of GnuTLS installed, -you can feed your authentication subkey to your ssh agent by running: +Then hand off the authentication subkey to the agent (Note: the GnuTLS +library supports this operation as of version 2.6, but earlier +versions do not): $ monkeysphere subkey-to-ssh-agent -FIXME: using the key with a single ssh connection? - - -Establish trust ---------------- - -Now that you have the above setup, you will need to establish an -acceptable trust path to the admin(s) of a monkeysphere-enabled server -that you will be connecting to. You need to do this because the admin -is certifying the host, and you need a mechanism to validate that -certification. The only way to do that is by indicating who you trust -to certify hosts. This is a two step process: first you must sign the -key, and then you have to indicate a trust level. - -The process of signing another key is outside the scope of this -document, however the [gnupg -README](http://cvs.gnupg.org/cgi-bin/viewcvs.cgi/branches/STABLE-BRANCH-1-4/README?root=GnuPG&view=markup) -details the signing process and you can find good [documentation -](http://www.debian.org/events/keysigning) online detailing this -process. - -If you have signed your admins' key, you need to denote some kind of -trust to that key. To do this you should edit the key and use the -'trust' command. For the Monkeysphere to trust the assertions that are -made about a host, you need full calculated validity to the host -certifiers. This can be done either by giving full trust to one -host-certifying key, or by giving marginal trust to three different -host-certifiers. In the following we demonstrate how to add full trust -validity to a host-certifying key: - - - $ gpg --edit-key 'Jane Admin' - gpg (GnuPG) 1.4.9; Copyright (C) 2008 Free Software Foundation, Inc. - This is free software: you are free to change and redistribute it. - There is NO WARRANTY, to the extent permitted by law. - - - pub 4096R/ABCD123A created: 2007-06-02 expires: 2012-05-31 usage: SC - trust: unknown validity: full - sub 2048R/01DECAF7 created: 2007-06-02 expires: 2012-05-31 usage: E - [ full ] (1). Jane Admin <jane_admin@example.net> - - Command> trust - pub 4096R/ABCD123A created: 2007-06-02 expires: 2012-05-31 usage: SC - trust: unknown validity: full - sub 2048R/01DECAF7 created: 2007-06-02 expires: 2012-05-31 usage: E - [ full ] (1). Jane Admin <jane_admin@example.net> - - Please decide how far you trust this user to correctly verify other users' keys - (by looking at passports, checking fingerprints from different sources, etc.) - - 1 = I don't know or won't say - 2 = I do NOT trust - 3 = I trust marginally - 4 = I trust fully - 5 = I trust ultimately - m = back to the main menu - - Your decision? 4 - - pub 4096R/ABCD123A created: 2007-06-02 expires: 2012-05-31 usage: SC - trust: full validity: full - sub 2048R/01DECAF7 created: 2007-06-02 expires: 2012-05-31 usage: E - [ full ] (1). Jane Admin <jane_admin@example.net> - Please note that the shown key validity is not necessarily correct - unless you restart the program. - - Command> save - Key not changed so no update needed. - $ - -Note: Due to a limitation with gnupg, it is not currently possible to -limit the domain scope properly, which means that if you fully trust -an admin, you'll trust all their certifications. - -Because the Monkeysphre relies on GPG's definition of the OpenPGP web -of trust, it is important to understand [how GPG calculates User ID -validity for a key](/trust-models). - - -Miscellaneous -------------- - -Users can also maintain their own `~/.ssh/authorized_keys` files with -the Monkeysphere. This is primarily useful for accounts on hosts that -are not already systematically using the Monkeysphere for user -authentication. If you're not sure whether this is the case for your -host, ask your system administrator. - -If you want to do this as a regular user, use the -`update-authorized_keys` command: - - $ monkeysphere update-authorized_keys - -This command will take all the user IDs listed in the -`~/.monkeysphere/authorized_user_ids` file and check to see if -there are acceptable keys for those user IDs available. If so, they -will be added to the `~/.ssh/authorized_keys` file. - -You must have indicated reasonable ownertrust in some key for this -account, or no keys will be found with trusted certification paths. - -If you find this useful, you might want to place this command in your -crontab so that revocations and rekeyings can take place -automatically. +You can supply normal ssh-add(1) flags to this command if you want to +give the agent different instructions. For example, if you want the +agent to always ask for confirmation before using this key, you should +do this instead: + + $ monkeysphere subkey-to-ssh-agent -c + +You can verify that the key is in the agent just as you normally +would: + + $ ssh-add -l + +Now you can connect to hosts that use the monkeysphere for user +authentication using that key: + + $ ssh server.example.net + + +Using your OpenPGP authentication key for SSH without the agent +--------------------------------------------------------------- + +Currently, the monkeysphere does not support using your SSH subkey +without the ssh-agent :( It's not impossible, we just haven't gotten +around to it yet. Patches are welcome! + +If you are not running an agent, and you just want a single session +with the key, you could cobble something together a one-shot agent +like this: + + $ ssh-agent sh -c 'monkeysphere subkey-to-ssh-agent && ssh server.example.net' + +Maintenance +=========== + +As a regular user of the monkeysphere, you probably want to do a few +things to make sure that you get automatically notified of any +re-keyings or revocation of monkeysphere-enabled hosts, and that your +keys are properly managed. + + +Keep your keyring up-to-date +---------------------------- + +Regularly refresh your GnuPG keyring from the keyservers. This can be +done with a simple cronjob. An example of crontab line to do this is: + + 0 12 * * * /usr/bin/gpg --refresh-keys > /dev/null 2>&1 + +This would refresh your keychain every day at noon. + + +Keep your SSH identity up-to-date +--------------------------------- + +If your SSH identity or your whole OpenPGP keyring is compromised, you +should be sure to revoke it and publish the revocations to the +keyserver. If only your SSH identity was compromised, you should just +revoke the authentication subkey. For keys with small sizes, or which +may have been otherwise compromised, you may wish to simply revoke the +old authentication subkey, add a new one, and publish those changes to +the public keyservers together. + +Many people believe that it is good security practice to only use +asymmetric keys (such as the RSA keys used by SSH and the +Monkeysphere) for a limited period of time, and prefer to transition +from key to key every year or two. + +Without the monkeysphere, you would have needed to update your +`authorized_keys` file on every host you connect to in order to effect +such a transition. But all hosts that use the Monkeysphere to +generate their authorized keys files will transition automatically to +your new key, if you publish/revoke as described above. + + +For those who want more +======================= + +More documentation and details are available on the web at: + + http://web.monkeysphere.info/ |