summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Goins <mjgoins@openflows.com>2009-02-21 16:54:39 -0500
committerMatt Goins <mjgoins@openflows.com>2009-02-21 16:54:39 -0500
commit4e0502a242b89c73535b00cc1b199dfea38ce4d4 (patch)
tree6bed970da1f85171b1c0b13095b702825a90754b
parentd41fe28eb49e42d7773a223a43fd108913410c99 (diff)
parenteb88374be90344d1808fe49a5bc69a547a09280d (diff)
Merge branch 'master' of git://lair.fifthhorseman.net/~dkg/monkeysphere
-rw-r--r--doc/TODO25
-rw-r--r--man/man8/monkeysphere-host.825
-rw-r--r--packaging/debian/changelog17
-rwxr-xr-xpackaging/debian/monkeysphere.prerm2
-rwxr-xr-xsrc/monkeysphere18
-rwxr-xr-xsrc/monkeysphere-host13
-rw-r--r--src/share/common17
-rw-r--r--src/share/m/ssh_proxycommand10
-rw-r--r--src/share/m/subkey_to_ssh_agent12
-rw-r--r--src/share/ma/add_certifier16
-rw-r--r--src/share/ma/diagnostics2
-rw-r--r--src/share/ma/remove_certifier2
-rw-r--r--src/share/ma/update_users5
-rw-r--r--src/share/mh/add_hostname6
-rw-r--r--src/share/mh/add_revoker16
-rw-r--r--src/share/mh/import_key15
-rw-r--r--src/share/mh/revoke_hostname6
-rw-r--r--src/share/mh/revoke_key70
-rwxr-xr-xtests/basic63
-rw-r--r--tests/common2
-rw-r--r--website/advanced-user.mdwn137
-rw-r--r--website/doc.mdwn4
-rw-r--r--website/getting-started-admin.mdwn120
-rw-r--r--website/getting-started-user.mdwn307
24 files changed, 565 insertions, 345 deletions
diff --git a/doc/TODO b/doc/TODO
index bd887d1..d365ac7 100644
--- a/doc/TODO
+++ b/doc/TODO
@@ -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/