summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMatt Goins <mjgoins@openflows.com>2009-02-20 11:42:10 -0500
committerMatt Goins <mjgoins@openflows.com>2009-02-20 11:42:10 -0500
commitd41fe28eb49e42d7773a223a43fd108913410c99 (patch)
treea109a88b02089a3f328730a9aa394e3155fda916
parent3b48f2e80fac8d0fc62537ed07b3d1f1946648cd (diff)
parent9b47ae89c3840eb2af9a57a885e19ccbe36957d5 (diff)
Merge commit 'jrollins/master'
-rwxr-xr-xMakefile7
-rw-r--r--man/man1/monkeysphere.136
-rw-r--r--man/man7/monkeysphere.72
-rw-r--r--man/man8/monkeysphere-authentication.830
-rw-r--r--man/man8/monkeysphere-host.831
-rw-r--r--packaging/debian/NEWS22
-rw-r--r--packaging/debian/changelog8
-rwxr-xr-xpackaging/debian/monkeysphere.postinst3
-rwxr-xr-xsrc/monkeysphere168
-rwxr-xr-xsrc/monkeysphere-authentication49
-rwxr-xr-xsrc/monkeysphere-host79
-rw-r--r--src/share/common110
-rw-r--r--src/share/m/gen_subkey83
-rw-r--r--src/share/m/import_subkey72
-rw-r--r--src/share/m/ssh_proxycommand39
-rw-r--r--src/share/m/subkey_to_ssh_agent15
-rw-r--r--src/share/ma/add_certifier125
-rw-r--r--src/share/ma/diagnostics18
-rw-r--r--src/share/ma/list_certifiers1
-rw-r--r--src/share/ma/remove_certifier2
-rw-r--r--src/share/ma/setup27
-rw-r--r--src/share/ma/update_users2
-rw-r--r--src/share/mh/add_hostname4
-rw-r--r--src/share/mh/add_revoker132
-rw-r--r--src/share/mh/diagnostics37
-rw-r--r--src/share/mh/import_key27
-rw-r--r--src/share/mh/publish_key8
-rw-r--r--src/share/mh/revoke_hostname6
-rw-r--r--src/share/mh/revoke_key28
-rw-r--r--src/share/mh/set_expire2
-rwxr-xr-xsrc/transition_0.22_0.2369
-rwxr-xr-xsrc/transitions/0.23180
-rw-r--r--src/transitions/README.txt16
-rwxr-xr-xtests/basic22
-rw-r--r--website/getting-started-admin.mdwn92
-rw-r--r--website/getting-started-user.mdwn11
36 files changed, 949 insertions, 614 deletions
diff --git a/Makefile b/Makefile
index 59b8887..71df92b 100755
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
# Makefile for monkeysphere
-# (c) 2008 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+# (c) 2008-2009 Daniel Kahn Gillmor <dkg@fifthhorseman.net>
# Licensed under GPL v3 or later
MONKEYSPHERE_VERSION = `head -n1 packaging/debian/changelog | sed 's/.*(\([^-]*\)-.*/\1/'`
@@ -29,7 +29,6 @@ tarball: clean
debian-package: tarball
tar xzf monkeysphere_$(MONKEYSPHERE_VERSION).orig.tar.gz
- sed -i "s|__VERSION__|$(MONKEYSPHERE_VERSION)|g" monkeysphere-$(MONKEYSPHERE_VERSION)/src/share/common
cp -a packaging/debian monkeysphere-$(MONKEYSPHERE_VERSION)
(cd monkeysphere-$(MONKEYSPHERE_VERSION) && debuild -uc -us)
rm -rf monkeysphere-$(MONKEYSPHERE_VERSION)
@@ -48,12 +47,14 @@ clean:
# working dir!
install: all installman
mkdir -p $(DESTDIR)$(PREFIX)/bin $(DESTDIR)$(PREFIX)/sbin
- mkdir -p $(DESTDIR)$(PREFIX)/share/monkeysphere/m $(DESTDIR)$(PREFIX)/share/monkeysphere/mh $(DESTDIR)$(PREFIX)/share/monkeysphere/ma
+ mkdir -p $(DESTDIR)$(PREFIX)/share/monkeysphere/m $(DESTDIR)$(PREFIX)/share/monkeysphere/mh $(DESTDIR)$(PREFIX)/share/monkeysphere/ma $(DESTDIR)$(PREFIX)/share/monkeysphere/transitions
mkdir -p $(DESTDIR)$(ETCPREFIX)/etc/monkeysphere
mkdir -p $(DESTDIR)$(PREFIX)/share/doc/monkeysphere
install src/monkeysphere src/keytrans/openpgp2ssh src/keytrans/pem2openpgp $(DESTDIR)$(PREFIX)/bin
install src/monkeysphere-host src/monkeysphere-authentication $(DESTDIR)$(PREFIX)/sbin
install -m 0644 src/share/common $(DESTDIR)$(PREFIX)/share/monkeysphere
+ install -m 0744 src/transitions/* $(DESTDIR)$(PREFIX)/share/monkeysphere/transitions
+ install -m 0644 src/transitions/README.txt $(DESTDIR)$(PREFIX)/share/monkeysphere/transitions
install -m 0644 src/share/m/* $(DESTDIR)$(PREFIX)/share/monkeysphere/m
install -m 0644 src/share/mh/* $(DESTDIR)$(PREFIX)/share/monkeysphere/mh
install -m 0644 src/share/ma/* $(DESTDIR)$(PREFIX)/share/monkeysphere/ma
diff --git a/man/man1/monkeysphere.1 b/man/man1/monkeysphere.1
index 0e80047..887b5df 100644
--- a/man/man1/monkeysphere.1
+++ b/man/man1/monkeysphere.1
@@ -58,22 +58,22 @@ were found but none were acceptable. `a' may be used in place of
.TP
.B gen-subkey [KEYID]
Generate an authentication subkey for a private key in your GnuPG
-keyring. For the primary key with the specified key ID, generate a
-subkey with "authentication" capability that can be used for
-monkeysphere transactions. An expiration length can be specified with
-the `-e' or `--expire' option (prompt otherwise). If no key ID is
+keyring. KEYID is the key ID for the primary key for which the subkey
+with "authentication" capability will be generated. If no key ID is
specified, but only one key exists in the secret keyring, that key
-will be used. `g' may be used in place of `gen-subkey'.
+will be used. The length of the generated key can be specified with
+the `--length` or `-l` option. `g' may be used in place of
+`gen-subkey'.
.TP
.B ssh-proxycommand
-an ssh proxy command that can be used
-to trigger a monkeysphere update of the ssh known_hosts file for a
-host that is being connected to with ssh. This works by updating the
-known_hosts file for the host first, before an attempted connection to
-the host is made. Once the known_hosts file has been updated, a TCP
-connection to the host is made by exec'ing netcat(1). Regular ssh
-communication is then done over this netcat TCP connection (see
-ProxyCommand in ssh_config(5) for more info).
+An ssh ProxyCommand that can be used to trigger a monkeysphere update
+of the ssh known_hosts file for a host that is being connected to with
+ssh. This works by updating the known_hosts file for the host first,
+before an attempted connection to the host is made. Once the
+known_hosts file has been updated, a TCP connection to the host is
+made by exec'ing netcat(1). Regular ssh communication is then done
+over this netcat TCP connection (see ProxyCommand in ssh_config(5) for
+more info).
This command is meant to be run as the ssh "ProxyCommand". This can
either be done by specifying the proxy command on the command line:
@@ -108,9 +108,10 @@ change in the future, possibly by adding a deferred check, so that
hosts that go from non-monkeysphere-enabled to monkeysphere-enabled
will be properly checked.
-Setting the MONKEYSPHERE_CHECK_KEYSERVER
-variable (to `true' or `false') will override the keyserver-checking policy
-defined above.
+Setting the CHECK_KEYSERVER variable in the config file or the
+MONKEYSPHERE_CHECK_KEYSERVER environment variable to either `true' or
+`false' will override the keyserver-checking policy defined above and
+either always or never check the keyserver for host key updates.
.TP
.B subkey-to-ssh-agent [ssh-add arguments]
@@ -152,6 +153,9 @@ Whether or not to hash to the known_hosts file entries (`true').
.TP
MONKEYSPHERE_AUTHORIZED_KEYS
Path to ssh authorized_keys file (~/.ssh/authorized_keys).
+.TP
+MONKEYSPHERE_PROMPT
+If set to `false', never prompt the user for confirmation. (true)
.SH FILES
diff --git a/man/man7/monkeysphere.7 b/man/man7/monkeysphere.7
index d221c87..578d96c 100644
--- a/man/man7/monkeysphere.7
+++ b/man/man7/monkeysphere.7
@@ -52,6 +52,6 @@ Daniel Kahn Gillmor <dkg@fifthhorseman.net>
.BR openpgp2ssh (1),
.BR pem2openpgp (1),
.BR gpg (1),
-.BR ssh (1),
.BR http://tools.ietf.org/html/rfc4880,
+.BR ssh (1),
.BR http://tools.ietf.org/wg/secsh/draft-ietf-secsh-scp-sftp-ssh-uri/
diff --git a/man/man8/monkeysphere-authentication.8 b/man/man8/monkeysphere-authentication.8
index 4d453d3..361822d 100644
--- a/man/man8/monkeysphere-authentication.8
+++ b/man/man8/monkeysphere-authentication.8
@@ -37,8 +37,11 @@ monkeysphere-controlled authorized_keys file. If no accounts are
specified, then all accounts on the system are processed. `u' may be
used in place of `update-users'.
.TP
-.B add-id-certifier KEYID
+.B add-id-certifier KEYID|FILE
Instruct system to trust user identity certifications made by KEYID.
+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.
Using the `-n' or `--domain' option allows you to indicate that you
only trust the given KEYID to make identifications within a specific
domain (e.g. "trust KEYID to certify user identities within the
@@ -131,22 +134,29 @@ The following environment variables will override those specified in
the config file (defaults in parentheses):
.TP
MONKEYSPHERE_MONKEYSPHERE_USER
-User to control authentication keychain (monkeysphere).
+User to control authentication keychain. (monkeysphere)
.TP
MONKEYSPHERE_LOG_LEVEL
-Set the log level (INFO). Can be SILENT, ERROR, INFO, VERBOSE, DEBUG, in
-increasing order of verbosity.
+Set the log level. Can be SILENT, ERROR, INFO, VERBOSE, DEBUG, in
+increasing order of verbosity. (INFO)
.TP
MONKEYSPHERE_KEYSERVER
-OpenPGP keyserver to use (pool.sks-keyservers.net).
+OpenPGP keyserver to use. (pool.sks-keyservers.net)
.TP
MONKEYSPHERE_AUTHORIZED_USER_IDS
-Path to user authorized_user_ids file
-(%h/.monkeysphere/authorized_user_ids).
+Path to user's authorized_user_ids file. %h gets replaced with the
+user's homedir, %u with the username.
+(%h/.monkeysphere/authorized_user_ids)
.TP
MONKEYSPHERE_RAW_AUTHORIZED_KEYS
-Path to user-controlled authorized_keys file. `-' means not to add
-user-controlled file (%h/.ssh/authorized_keys).
+Path to regular ssh-style authorized_keys file to append to
+monkeysphere-generated authorized_keys. `none' means not to add any
+raw authorized_keys file. %h gets replaced with the user's homedir,
+%u with the username. (%h/.ssh/authorized_keys)
+.TP
+MONKEYSPHERE_PROMPT
+If set to `false', never prompt the user for confirmation. (true)
+
.SH FILES
@@ -154,7 +164,7 @@ user-controlled file (%h/.ssh/authorized_keys).
/etc/monkeysphere/monkeysphere-authentication.conf
System monkeysphere-authentication config file.
.TP
-/var/lib/monkeysphere/authentication/authorized_keys/USER
+/var/lib/monkeysphere/authorized_keys/USER
Monkeysphere-generated user authorized_keys files.
.SH AUTHOR
diff --git a/man/man8/monkeysphere-host.8 b/man/man8/monkeysphere-host.8
index 330b610..2ccaaec 100644
--- a/man/man8/monkeysphere-host.8
+++ b/man/man8/monkeysphere-host.8
@@ -23,9 +23,10 @@ connection authentication.
\fBmonkeysphere-host\fP takes various subcommands:
.TP
-.B import-key [NAME[:PORT]]
-Import a pem-encoded ssh secret host key, from stdin. NAME[:PORT] is
-used to specify the hostname (and port) used in the user ID of the new
+.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
@@ -35,11 +36,11 @@ port 22 is assumed. `i' may be used in place of `import-key'.
Output information about host's OpenPGP and SSH keys. `s' may be used
in place of `show-key'.
.TP
-.B extend-key EXPIRE
+.B extend-key [EXPIRE]
Extend the validity of the OpenPGP key for the host until EXPIRE from
the present. If EXPIRE is not specified, then the user will be
-prompted for the extension term. Expiration is specified like GnuPG
-does:
+prompted for the extension term. Expiration is specified as with
+GnuPG:
.nf
0 = key does not expire
<n> = key expires in n days
@@ -57,13 +58,19 @@ place of `add-hostname'.
Revoke a hostname user ID from the server host key. `n-' may be used
in place of `revoke-hostname'.
.TP
-.B add-revoker FINGERPRINT
-Add a revoker to the host's OpenPGP key. `o' may be be used in place
+.B add-revoker KEYID|FILE
+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
of `add-revoker'.
.TP
.B revoke-key
-Revoke the host's OpenPGP key. `r' may be used in place of
-`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'.
.TP
.B publish-key
Publish the host's OpenPGP key to the keyserver. `p' may be used in
@@ -113,6 +120,10 @@ increasing order of verbosity.
.TP
MONKEYSPHERE_KEYSERVER
OpenPGP keyserver to use (pool.sks-keyservers.net).
+.TP
+MONKEYSPHERE_PROMPT
+If set to `false', never prompt the user for confirmation. (true)
+
.SH FILES
diff --git a/packaging/debian/NEWS b/packaging/debian/NEWS
new file mode 100644
index 0000000..3fceea2
--- /dev/null
+++ b/packaging/debian/NEWS
@@ -0,0 +1,22 @@
+monkeysphere (0.23-1) unstable; urgency=low
+
+ * There has been a major interface and data refactoring. Please see the
+ man pages for details. Major changes are listed here:
+ * For end users: monkeysphere-ssh-proxycommand is no more.
+ its functionality has been folded into monkeysphere as a subcommand.
+ So if you are currently using:
+ ssh -oProxyCommand='monkeysphere-ssh-proxycommand %h %p'
+ plese use instead:
+ ssh -oProxyCommand='monkeysphere ssh-proxycommand %h %p'
+ * For sysadmins: monkeysphere-server has been split into
+ monkeysphere-host (for publishing the ssh host key of your machine)
+ and monkeysphere-authentication (for setting up your machine to
+ authenticate users via the OpenPGP Web of Trust)
+ * For too-curious sysadmins: the layout of /var/lib/monkeysphere has
+ changed dramatically. If you did any tricky tweaking of the files in
+ there, you probably want to check that your changes have been
+ preserved after the upgrade. The old files can be found in
+ /var/lib/monkeysphere/backup-from-0.23-transition.
+
+ -- Daniel Kahn Gillmor <dkg@fifthhorseman.net> Wed, 18 Feb 2009 21:29:22 -0500
+
diff --git a/packaging/debian/changelog b/packaging/debian/changelog
index c825b64..fc317d9 100644
--- a/packaging/debian/changelog
+++ b/packaging/debian/changelog
@@ -16,10 +16,12 @@ monkeysphere (0.23~pre-1) UNRELEASED; urgency=low
functions that require it to be there.
* get rid of getopts dependency
* added version output option
- * check that existing authentication keys are valid in gen_key
- function.
+ * better checks on validity of existing authentication subkeys when
+ doing monkeysphere {import,gen}_subkey.
+ * add transition infrastructure for major changes between releases (see
+ transitions/README.txt)
- -- Jameson Graef Rollins <jrollins@finestructure.net> Thu, 12 Feb 2009 21:50:54 -0500
+ -- Jameson Graef Rollins <jrollins@finestructure.net> Thu, 19 Feb 2009 15:11:04 -0500
monkeysphere (0.22-1) unstable; urgency=low
diff --git a/packaging/debian/monkeysphere.postinst b/packaging/debian/monkeysphere.postinst
index 8e79771..3d0d66f 100755
--- a/packaging/debian/monkeysphere.postinst
+++ b/packaging/debian/monkeysphere.postinst
@@ -17,6 +17,9 @@ if ! getent passwd monkeysphere >/dev/null ; then
monkeysphere
fi
+# try to transition from to 0.23:
+/usr/share/monkeysphere/transitions/0.23
+
# setup monkeysphere authentication
monkeysphere-authentication setup
diff --git a/src/monkeysphere b/src/monkeysphere
index da5f406..a65cef6 100755
--- a/src/monkeysphere
+++ b/src/monkeysphere
@@ -45,12 +45,8 @@ Monkeysphere client tool.
subcommands:
update-known_hosts (k) [HOST]... update known_hosts file
update-authorized_keys (a) update authorized_keys file
- import-subkey (i) import existing ssh key as gpg subkey
- --keyfile (-f) FILE key file to import
- --expire (-e) EXPIRE date to expire
gen-subkey (g) [KEYID] generate an authentication subkey
--length (-l) BITS key length in bits (2048)
- --expire (-e) EXPIRE date to expire
ssh-proxycommand monkeysphere ssh ProxyCommand
subkey-to-ssh-agent (s) store authentication subkey in ssh-agent
version (v) show version number
@@ -59,45 +55,128 @@ subcommands:
EOF
}
+# user gpg command to define common options
+gpg_user() {
+ gpg --no-greeting --quiet --no-tty "$@"
+}
+
+# take a secret key ID and check that only zero or one ID is provided,
+# and that it corresponds to only a single secret key ID
+check_gpg_sec_key_id() {
+ local gpgSecOut
+
+ case "$#" in
+ 0)
+ gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
+ ;;
+ 1)
+ gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons "$keyID" | egrep '^sec:') || failure
+ ;;
+ *)
+ failure "You must specify only a single primary key ID."
+ ;;
+ esac
+
+ # check that only a single secret key was found
+ case $(echo "$gpgSecOut" | grep -c '^sec:') in
+ 0)
+ failure "No secret keys found. Create an OpenPGP key with the following command:
+ gpg --gen-key"
+ ;;
+ 1)
+ 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
+ failure
+ ;;
+ esac
+}
+
+# check that a valid authentication subkey does not already exist
+check_gpg_authentication_subkey() {
+ local keyID
+ local IFS
+ local line
+ local type
+ local validity
+ local usage
+
+ keyID="$1"
+
+ # check that a valid authentication key does not already exist
+ IFS=$'\n'
+ for line in $(gpg_user --fixed-list-mode --list-keys --with-colons "$keyID") ; do
+ type=$(echo "$line" | cut -d: -f1)
+ validity=$(echo "$line" | cut -d: -f2)
+ usage=$(echo "$line" | cut -d: -f12)
+
+ # look at keys only
+ if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
+ continue
+ fi
+ # check for authentication capability
+ if ! check_capability "$usage" 'a' ; then
+ continue
+ fi
+ # if authentication key is valid, prompt to continue
+ if [ "$validity" = 'u' ] ; then
+ echo "A valid authentication key already exists for primary key '$keyID'."
+ 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
+ failure "aborting."
+ fi
+ break
+ else
+ failure "aborting."
+ fi
+ fi
+ done
+}
+
########################################################################
# MAIN
########################################################################
-# unset variables that should be defined only in config file
-unset KEYSERVER
+# set unset default variables
+GNUPGHOME=${GNUPGHOME:="${HOME}/.gnupg"}
+KNOWN_HOSTS="${HOME}/.ssh/known_hosts"
+HASH_KNOWN_HOSTS="true"
+AUTHORIZED_KEYS="${HOME}/.ssh/authorized_keys"
+
+# unset the check keyserver variable, since that needs to have
+# different defaults for the different functions
unset CHECK_KEYSERVER
-unset KNOWN_HOSTS
-unset HASH_KNOWN_HOSTS
-unset AUTHORIZED_KEYS
# load global config
-[ -r "${SYSCONFIGDIR}/monkeysphere.conf" ] && . "${SYSCONFIGDIR}/monkeysphere.conf"
+[ -r "${SYSCONFIGDIR}/monkeysphere.conf" ] \
+ && . "${SYSCONFIGDIR}/monkeysphere.conf"
# set monkeysphere home directory
MONKEYSPHERE_HOME=${MONKEYSPHERE_HOME:="${HOME}/.monkeysphere"}
mkdir -p -m 0700 "$MONKEYSPHERE_HOME"
# load local config
-[ -e ${MONKEYSPHERE_CONFIG:="${MONKEYSPHERE_HOME}/monkeysphere.conf"} ] && . "$MONKEYSPHERE_CONFIG"
-
-# set empty config variables with ones from the environment, or from
-# config file, or with defaults
-LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
-GNUPGHOME=${MONKEYSPHERE_GNUPGHOME:=${GNUPGHOME:="${HOME}/.gnupg"}}
-KEYSERVER=${MONKEYSPHERE_KEYSERVER:="$KEYSERVER"}
-# if keyserver not specified in env or monkeysphere.conf,
-# look in gpg.conf
+[ -e ${MONKEYSPHERE_CONFIG:="${MONKEYSPHERE_HOME}/monkeysphere.conf"} ] \
+ && . "$MONKEYSPHERE_CONFIG"
+
+# set empty config variables with ones from the environment
+GNUPGHOME=${MONKEYSPHERE_GNUPGHOME:=$GNUPGHOME}
+LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=$LOG_LEVEL}
+KEYSERVER=${MONKEYSPHERE_KEYSERVER:=$KEYSERVER}
+# if keyserver not specified in env or conf, then look in gpg.conf
if [ -z "$KEYSERVER" ] ; then
if [ -f "${GNUPGHOME}/gpg.conf" ] ; then
KEYSERVER=$(grep -e "^[[:space:]]*keyserver " "${GNUPGHOME}/gpg.conf" | tail -1 | awk '{ print $2 }')
fi
fi
-# if it's still not specified, use the default
-KEYSERVER=${KEYSERVER:="subkeys.pgp.net"}
-CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=${CHECK_KEYSERVER:="true"}}
-KNOWN_HOSTS=${MONKEYSPHERE_KNOWN_HOSTS:=${KNOWN_HOSTS:="${HOME}/.ssh/known_hosts"}}
-HASH_KNOWN_HOSTS=${MONKEYSPHERE_HASH_KNOWN_HOSTS:=${HASH_KNOWN_HOSTS:="true"}}
-AUTHORIZED_KEYS=${MONKEYSPHERE_AUTHORIZED_KEYS:=${AUTHORIZED_KEYS:="${HOME}/.ssh/authorized_keys"}}
+PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT}
+KNOWN_HOSTS=${MONKEYSPHERE_KNOWN_HOSTS:=$KNOWN_HOSTS}
+HASH_KNOWN_HOSTS=${MONKEYSPHERE_HASH_KNOWN_HOSTS:=$HASH_KNOWN_HOSTS}
+AUTHORIZED_KEYS=${MONKEYSPHERE_AUTHORIZED_KEYS:=$AUTHORIZED_KEYS}
# other variables not in config file
AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:="${MONKEYSPHERE_HOME}/authorized_user_ids"}
@@ -117,49 +196,26 @@ shift
case $COMMAND in
'update-known_hosts'|'update-known-hosts'|'k')
- MODE='known_hosts'
-
- # touch the known_hosts file so that the file permission check
- # below won't fail upon not finding the file
- (umask 0022 && touch "$KNOWN_HOSTS")
-
- # check permissions on the known_hosts file path
- check_key_file_permissions "$USER" "$KNOWN_HOSTS" || failure
+ # whether or not to check keyservers
+ CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=${CHECK_KEYSERVER:="true"}}
- # if hosts are specified on the command line, process just
- # those hosts
+ # if hosts are specified on the command line, process just
+ # 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
+ # otherwise, if no hosts are specified, process every host
+ # in the user's known_hosts file
else
- # exit if the known_hosts file does not exist
- if [ ! -e "$KNOWN_HOSTS" ] ; then
- log error "known_hosts file '$KNOWN_HOSTS' does not exist."
- exit
- fi
-
process_known_hosts
RETURN="$?"
fi
;;
'update-authorized_keys'|'update-authorized-keys'|'a')
- MODE='authorized_keys'
-
- # check permissions on the authorized_user_ids file path
- check_key_file_permissions "$USER" "$AUTHORIZED_USER_IDS" || failure
-
- # check permissions on the authorized_keys file path
- check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure
-
- # exit if the authorized_user_ids file is empty
- if [ ! -e "$AUTHORIZED_USER_IDS" ] ; then
- log error "authorized_user_ids file '$AUTHORIZED_USER_IDS' does not exist."
- exit
- fi
+ # whether or not to check keyservers
+ CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=${CHECK_KEYSERVER:="true"}}
# process authorized_user_ids file
process_authorized_user_ids "$AUTHORIZED_USER_IDS"
diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication
index 8a4146f..497470d 100755
--- a/src/monkeysphere-authentication
+++ b/src/monkeysphere-authentication
@@ -56,7 +56,8 @@ Monkeysphere authentication admin tool.
subcommands:
update-users (u) [USER]... update user authorized_keys files
- add-id-certifier (c+) KEYID import and tsign a certification key
+
+ add-id-certifier (c+) [KEYID|FILE] import and tsign a certification key
--domain (-n) DOMAIN limit ID certifications to DOMAIN
--trust (-t) TRUST trust level of certifier (full)
--depth (-d) DEPTH trust depth for certifier (1)
@@ -75,7 +76,7 @@ gpg_core() {
GNUPGHOME="$GNUPGHOME_CORE"
export GNUPGHOME
- gpg "$@"
+ gpg --no-greeting --quiet --no-tty "$@"
}
# function to interact with the gpg sphere keyring
@@ -84,16 +85,16 @@ gpg_core() {
gpg_sphere() {
GNUPGHOME="$GNUPGHOME_SPHERE"
export GNUPGHOME
-
- su_monkeysphere_user "gpg $@"
+
+ su_monkeysphere_user "gpg --no-greeting --quiet --no-tty $@"
}
# output to stdout the core fingerprint from the gpg core secret
# keyring
core_fingerprint() {
log debug "determining core key fingerprint..."
- gpg_core --quiet --list-secret-key \
- --with-colons --fixed-list-mode --with-fingerprint \
+ gpg_core --list-secret-key --with-colons \
+ --fixed-list-mode --with-fingerprint \
| grep ^fpr: | cut -d: -f10
}
@@ -101,37 +102,31 @@ core_fingerprint() {
gpg_core_sphere_sig_transfer() {
log debug "exporting core local sigs to sphere..."
gpg_core --export-options export-local-sigs --export | \
- gpg_sphere "--import-options import-local-sigs --import" \
- 2>&1 | log debug
+ gpg_sphere "--import-options import-local-sigs --import"
}
########################################################################
# MAIN
########################################################################
-# unset variables that should be defined only in config file of in
-# MONKEYSPHERE_ variables
-unset LOG_LEVEL
-unset KEYSERVER
-unset AUTHORIZED_USER_IDS
-unset RAW_AUTHORIZED_KEYS
-unset MONKEYSPHERE_USER
-unset PROMPT
+# set unset default variables
+AUTHORIZED_USER_IDS="%h/.monkeysphere/authorized_user_ids"
+RAW_AUTHORIZED_KEYS="%h/.ssh/authorized_keys"
# load configuration file
-[ -e ${MONKEYSPHERE_AUTHENTICATION_CONFIG:="${SYSCONFIGDIR}/monkeysphere-authentication.conf"} ] && . "$MONKEYSPHERE_AUTHENTICATION_CONFIG"
-
-# set empty config variable with ones from the environment, or with
-# defaults
-LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
-KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
-AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.monkeysphere/authorized_user_ids"}}
-RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
-MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
-PROMPT=${MONKEYSPHERE_PROMPT:=${PROMPT:="true"}}
+[ -e ${MONKEYSPHERE_AUTHENTICATION_CONFIG:="${SYSCONFIGDIR}/monkeysphere-authentication.conf"} ] \
+ && . "$MONKEYSPHERE_AUTHENTICATION_CONFIG"
+
+# set empty config variable with ones from the environment
+LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=$LOG_LEVEL}
+KEYSERVER=${MONKEYSPHERE_KEYSERVER:=$KEYSERVER}
+CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER}
+MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=$MONKEYSPHERE_USER}
+PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT}
+AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=$AUTHORIZED_USER_IDS}
+RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=$RAW_AUTHORIZED_KEYS}
# other variables
-CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"}
GNUPGHOME_CORE=${MONKEYSPHERE_GNUPGHOME_CORE:="${MADATADIR}/core"}
GNUPGHOME_SPHERE=${MONKEYSPHERE_GNUPGHOME_SPHERE:="${MADATADIR}/sphere"}
diff --git a/src/monkeysphere-host b/src/monkeysphere-host
index c7e011b..4c7df88 100755
--- a/src/monkeysphere-host
+++ b/src/monkeysphere-host
@@ -32,10 +32,6 @@ MHSHAREDIR="${SYSSHAREDIR}/mh"
# datadir for host functions
MHDATADIR="${SYSDATADIR}/host"
-# temp directory for temp gnupghome directories for add_revoker
-MHTMPDIR="${MHDATADIR}/tmp"
-export MHTMPDIR
-
# host pub key files
HOST_KEY_FILE="${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
@@ -58,16 +54,15 @@ usage: $PGRM <subcommand> [options] [args]
Monkeysphere host admin tool.
subcommands:
+ import-key (i) FILE [NAME[:PORT]] import existing ssh key to gpg
show-key (s) output all host key information
- set-expire (e) EXPIRE set host key expiration
+ 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) FINGERPRINT add a revoker to the host key
+ 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
- import-key (i) [NAME[:PORT]] import existing ssh key to gpg
-
version (v) show version number
help (h,?) this help
@@ -77,7 +72,7 @@ EOF
# function to interact with the gpg keyring
gpg_host() {
- GNUPGHOME="$GNUPGHOME_HOST" gpg "$@"
+ GNUPGHOME="$GNUPGHOME_HOST" gpg --no-greeting --quiet --no-tty "$@"
}
# command to list the info about the host key, in colon format, to
@@ -90,12 +85,8 @@ gpg_host_list() {
}
# command for edit key scripts, takes scripts on stdin
-# FIXME: should we supress all the edit script spew? or pipe it
-# through log debug?
gpg_host_edit() {
- gpg_host --no-greeting --quiet \
- --command-fd 0 --no-tty --edit-key \
- "0x${HOST_FINGERPRINT}!" "$@" 2>&1 | log debug
+ gpg_host --command-fd 0 --edit-key "0x${HOST_FINGERPRINT}!" "$@"
}
# export the host public key to the monkeysphere gpg pub key file
@@ -119,7 +110,7 @@ load_fingerprint() {
&& rm -rf "$FUBAR") <"$HOST_KEY_FILE" \
| grep '^fpr:' | cut -d: -f10 )
else
- HOST_FINGERPRINT=
+ failure "host key gpg pub file not found."
fi
}
@@ -127,8 +118,7 @@ load_fingerprint() {
# gpg host secret key
load_fingerprint_secret() {
HOST_FINGERPRINT=$( \
- gpg_host --quiet --list-secret-key \
- --with-colons --with-fingerprint \
+ gpg_host --list-secret-key --with-colons --with-fingerprint \
| grep '^fpr:' | cut -d: -f10 )
}
@@ -142,7 +132,7 @@ check_host_key() {
check_host_no_key() {
[ -s "$HOST_KEY_FILE" ] \
|| failure "You don't appear to have a Monkeysphere host key on this server.
-Please run 'monkeysphere-host import-key' first."
+Please run 'monkeysphere-host import-key...' first."
}
# output the index of a user ID on the host key
@@ -174,7 +164,7 @@ show_key() {
local GNUPGHOME
# tmp gpghome dir
- export GNUPGHOME=$(mktemp -d)
+ export GNUPGHOME=$(msmktempdir)
# trap to remove tmp dir if break
trap "rm -rf $GNUPGHOME" EXIT
@@ -182,6 +172,11 @@ show_key() {
# import the host key into the tmp dir
gpg --quiet --import <"$HOST_KEY_FILE"
+ # create the ssh key
+ TMPSSH="$GNUPGHOME"/ssh_host_key_rsa_pub
+ openpgp2ssh <"$HOST_KEY_FILE" 2>/dev/null >"$TMPSSH"
+
+ # get the gpg fingerprint
HOST_FINGERPRINT=$(gpg --quiet --list-keys --with-colons --with-fingerprint \
| grep '^fpr:' | cut -d: -f10 )
@@ -198,9 +193,7 @@ show_key() {
# list the ssh fingerprint
echo -n "ssh fingerprint: "
- ssh-keygen -l -f /dev/stdin \
- <<<$(openpgp2ssh <"$HOST_KEY_FILE" 2>/dev/null) \
- | awk '{ print $1, $2, $4 }'
+ ssh-keygen -l -f "$TMPSSH" | awk '{ print $1, $2, $4 }'
# remove the tmp file
trap - EXIT
@@ -211,38 +204,31 @@ show_key() {
# MAIN
########################################################################
-# unset variables that should be defined only in config file or in
-# MONKEYSPHERE_ variables
-unset LOG_LEVEL
-unset KEYSERVER
-unset MONKEYSPHERE_USER
-unset PROMPT
-
# load configuration file
-[ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] && . "$MONKEYSPHERE_HOST_CONFIG"
+[ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] \
+ && . "$MONKEYSPHERE_HOST_CONFIG"
# set empty config variable with ones from the environment, or with
# defaults
-LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
-KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
-MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
-PROMPT=${MONKEYSPHERE_PROMPT:=${PROMPT:="true"}}
+LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=$LOG_LEVEL}
+KEYSERVER=${MONKEYSPHERE_KEYSERVER:=$KEYSERVER}
+CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER}
+MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=$MONKEYSPHERE_USER}
+PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT}
# other variables
-CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${MHDATADIR}"}
# export variables needed in su invocation
export DATE
-export MODE
export LOG_LEVEL
export KEYSERVER
+export CHECK_KEYSERVER
export MONKEYSPHERE_USER
export PROMPT
-export CHECK_KEYSERVER
export GNUPGHOME_HOST
export GNUPGHOME
-export HOST_FINGERPRINT=
+export HOST_FINGERPRINT
# get subcommand
COMMAND="$1"
@@ -250,6 +236,12 @@ COMMAND="$1"
shift
case $COMMAND in
+ 'import-key'|'i')
+ check_host_key
+ source "${MHSHAREDIR}/import_key"
+ import_key "$@"
+ ;;
+
'show-key'|'show'|'s')
check_host_no_key
show_key
@@ -297,18 +289,17 @@ case $COMMAND in
publish_key
;;
- 'import-key'|'i')
- check_host_key
- source "${MHSHAREDIR}/import_key"
- import_key "$@"
- ;;
-
'diagnostics'|'d')
load_fingerprint
source "${MHSHAREDIR}/diagnostics"
diagnostics
;;
+ 'update-gpg-pub-file')
+ load_fingerprint_secret
+ update_gpg_pub_file
+ ;;
+
'version'|'v')
echo "$VERSION"
;;
diff --git a/src/share/common b/src/share/common
index 4120259..653d58b 100644
--- a/src/share/common
+++ b/src/share/common
@@ -8,7 +8,7 @@
# Jamie McClelland <jm@mayfirst.org>
# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
#
-# Copyright 2008, released under the GPL, version 3 or later
+# Copyright 2008-2009, released under the GPL, version 3 or later
# all-caps variables are meant to be user supplied (ie. from config
# file) and are considered global
@@ -21,7 +21,22 @@ SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"}
export SYSCONFIGDIR
# monkeysphere version
-VERSION=__VERSION__
+VERSION=0.23~pre
+
+# default log level
+LOG_LEVEL="INFO"
+
+# default keyserver
+KEYSERVER="pool.sks-keyservers.net"
+
+# whether or not to check keyservers by defaul
+CHECK_KEYSERVER="true"
+
+# default monkeysphere user
+MONKEYSPHERE_USER="monkeysphere"
+
+# default about whether or not to prompt
+PROMPT="true"
########################################################################
### UTILITY FUNCTIONS
@@ -134,6 +149,16 @@ cutline() {
head --line="$1" "$2" | tail -1
}
+# make a temporary directory
+msmktempdir() {
+ mktemp -d ${TMPDIR:-/tmp}/monkeysphere.XXXXXXXXXX
+}
+
+# make a temporary file
+msmktempfile() {
+ mktemp ${TMPDIR:-/tmp}/monkeysphere.XXXXXXXXXX
+}
+
# this is a wrapper for doing lock functions.
#
# it lets us depend on either lockfile-progs (preferred) or procmail's
@@ -271,7 +296,7 @@ get_gpg_expiration() {
keyExpire="$1"
- if [ -z "$keyExpire" ]; then
+ if [ -z "$keyExpire" -a "$PROMPT" = 'true' ]; then
cat >&2 <<EOF
Please specify how long the key should be valid.
0 = key does not expire
@@ -795,6 +820,9 @@ process_host_known_hosts() {
local sshKey
local tmpfile
+ # set the key processing mode
+ export MODE='known_hosts'
+
host="$1"
userID="ssh://${host}"
@@ -874,6 +902,13 @@ update_known_hosts() {
nHostsOK=0
nHostsBAD=0
+ # touch the known_hosts file so that the file permission check
+ # below won't fail upon not finding the file
+ (umask 0022 && touch "$KNOWN_HOSTS")
+
+ # check permissions on the known_hosts file path
+ check_key_file_permissions "$USER" "$KNOWN_HOSTS" || failure
+
# create a lockfile on known_hosts:
lock create "$KNOWN_HOSTS"
# FIXME: we're discarding any pre-existing EXIT trap; is this bad?
@@ -928,6 +963,11 @@ update_known_hosts() {
process_known_hosts() {
local hosts
+ # exit if the known_hosts file does not exist
+ if [ ! -e "$KNOWN_HOSTS" ] ; then
+ failure "known_hosts file '$KNOWN_HOSTS' does not exist."
+ fi
+
log debug "processing known_hosts file..."
hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ')
@@ -951,6 +991,9 @@ process_uid_authorized_keys() {
local ok
local sshKey
+ # set the key processing mode
+ export MODE='authorized_keys'
+
userID="$1"
log verbose "processing: $userID"
@@ -1012,6 +1055,9 @@ update_authorized_keys() {
nIDsOK=0
nIDsBAD=0
+ # check permissions on the authorized_keys file path
+ check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure
+
# create a lockfile on authorized_keys
lock create "$AUTHORIZED_KEYS"
# FIXME: we're discarding any pre-existing EXIT trap; is this bad?
@@ -1077,6 +1123,14 @@ process_authorized_user_ids() {
authorizedUserIDs="$1"
+ # exit if the authorized_user_ids file is empty
+ if [ ! -e "$authorizedUserIDs" ] ; then
+ failure "authorized_user_ids file '$authorizedUserIDs' does not exist."
+ fi
+
+ # check permissions on the authorized_user_ids file path
+ check_key_file_permissions "$USER" "$authorizedUserIDs" || failure
+
log debug "processing authorized_user_ids file..."
if ! meat "$authorizedUserIDs" > /dev/null ; then
@@ -1095,3 +1149,53 @@ process_authorized_user_ids() {
update_authorized_keys "${userIDs[@]}"
}
+
+# takes a gpg key or keys on stdin, and outputs a list of
+# fingerprints, one per line:
+list_primary_fingerprints() {
+ local fake=$(msmktempdir)
+ GNUPGHOME="$fake" gpg --no-tty --quiet --import
+ GNUPGHOME="$fake" gpg --with-colons --fingerprint --list-keys | \
+ awk -F: '/^fpr:/{ print $10 }'
+ rm -rf "$fake"
+}
+
+
+check_cruft_file() {
+ local loc="$1"
+ local version="$2"
+
+ if [ -e "$loc" ] ; then
+ printf "! The file '%s' is no longer used by\n monkeysphere (as of version %s), and can be removed.\n\n" "$loc" "$version" | log info
+ fi
+}
+
+check_upgrade_dir() {
+ local loc="$1"
+ local version="$2"
+
+ if [ -d "$loc" ] ; then
+ printf "The presence of directory '%s' indicates that you have\nnot yet completed a monkeysphere upgrade.\nYou should probably run the following script:\n %s/transitions/%s\n\n" "$loc" "$SYSSHAREDIR" "$version" | log info
+ fi
+}
+
+## look for cruft from old versions of the monkeysphere, and notice if
+## upgrades have not been run:
+report_cruft() {
+ check_upgrade_dir "${SYSCONFIGDIR}/gnupg-host" 0.23
+ check_upgrade_dir "${SYSCONFIGDIR}/gnupg-authentication" 0.23
+
+ check_cruft_file "${SYSCONFIGDIR}/gnupg-authentication.conf" 0.23
+ check_cruft_file "${SYSCONFIGDIR}/gnupg-host.conf" 0.23
+
+ local found=
+ for foo in "${SYSDATADIR}/backup-from-"*"-transition" ; do
+ if [ -d "$foo" ] ; then
+ printf "! %s\n" "$foo" | log info
+ found=true
+ fi
+ done
+ if [ "$found" ] ; then
+ printf "The directories above are backups left over from a monkeysphere transition.\nThey may contain copies of sensitive data (host keys, certifier lists), but\nthey are no longer needed by monkeysphere.\nYou may remove them at any time.\n\n" | log info
+ fi
+}
diff --git a/src/share/m/gen_subkey b/src/share/m/gen_subkey
index cbefaa3..dbd9dd6 100644
--- a/src/share/m/gen_subkey
+++ b/src/share/m/gen_subkey
@@ -15,10 +15,10 @@
gen_subkey(){
local keyLength
- local keyExpire
+ local gpgSecOut
local keyID
- local gpgOut
- local userID
+ local editCommands
+ local fifoDir
# get options
while true ; do
@@ -27,10 +27,6 @@ gen_subkey(){
keyLength="$2"
shift 2
;;
- -e|--expire)
- keyExpire="$2"
- shift 2
- ;;
*)
if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
failure "Unknown option '$1'.
@@ -41,63 +37,11 @@ Type '$PGRM help' for usage."
esac
done
- case "$#" in
- 0)
- gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
- ;;
- 1)
- gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons "$1" | egrep '^sec:') || failure
- ;;
- *)
- failure "You must specify only a single primary key ID."
- ;;
- esac
-
- # check that only a single secret key was found
- case $(echo "$gpgSecOut" | grep -c '^sec:') in
- 0)
- failure "No secret keys found. Create an OpenPGP key with the following command:
- gpg --gen-key"
- ;;
- 1)
- keyID=$(echo "$gpgSecOut" | cut -d: -f5)
- ;;
- *)
- echo "Multiple primary secret keys found:"
- echo "$gpgSecOut" | cut -d: -f5
- failure "Please specify which primary key to use."
- ;;
- esac
+ # check that the keyID is unique
+ keyID=$(check_gpg_sec_key_id "$@")
- # check that a valid authentication key does not already exist
- IFS=$'\n'
- for line in $(gpg --quiet --fixed-list-mode --list-keys --with-colons "$keyID") ; do
- type=$(echo "$line" | cut -d: -f1)
- validity=$(echo "$line" | cut -d: -f2)
- usage=$(echo "$line" | cut -d: -f12)
-
- # look at keys only
- if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
- continue
- fi
- # check for authentication capability
- if ! check_capability "$usage" 'a' ; then
- continue
- fi
- # if authentication key is valid, prompt to continue
- if [ "$validity" = 'u' ] ; then
- echo "A valid authentication key already exists for primary key '$keyID'."
- read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N}
- if [ "${OK/y/Y}" != 'Y' ] ; then
- failure "aborting."
- fi
- break
- fi
- done
-
- # set subkey defaults
- # prompt about key expiration if not specified
- keyExpire=$(get_gpg_expiration "$keyExpire")
+ # check that an authentication subkey does not already exist
+ check_gpg_authentication_subkey "$keyID"
# generate the list of commands that will be passed to edit-key
editCommands=$(cat <<EOF
@@ -108,19 +52,24 @@ E
A
Q
$keyLength
-$keyExpire
+0
save
EOF
)
- log verbose "generating subkey..."
- fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+ # setup the temp fifo dir for retrieving the key password
+ log debug "creating password fifo..."
+ fifoDir=$(msmktempdir)
+ trap "rm -rf $fifoDir" EXIT
(umask 077 && mkfifo "$fifoDir/pass")
- echo "$editCommands" | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
+
+ log verbose "generating subkey..."
+ echo "$editCommands" | gpg_user --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
# FIXME: this needs to fail more gracefully if the passphrase is incorrect
passphrase_prompt "Please enter your passphrase for $keyID: " "$fifoDir/pass"
+ trap - EXIT
rm -rf "$fifoDir"
wait
log verbose "done."
diff --git a/src/share/m/import_subkey b/src/share/m/import_subkey
index aa89958..8d60f26 100644
--- a/src/share/m/import_subkey
+++ b/src/share/m/import_subkey
@@ -13,41 +13,55 @@
# import an existing ssh key as a gpg subkey
+## 2009-02-20 00:49:11-0500: This is not implemented yet, because we
+## don't currently have a good way to manipulate the user's OpenPGP
+## secret key such that we could make a proper subkey binding
+## signature.
+
import_subkey() {
- local keyFile="~/.ssh/id_rsa"
- local keyExpire
+ local sshKeyFile
local keyID
- local gpgOut
- local userID
-
- # get options
- while true ; do
- case "$1" in
- -f|--keyfile)
- keyFile="$2"
- shift 2
- ;;
- -e|--expire)
- keyExpire="$2"
- shift 2
- ;;
- *)
- if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
- failure "Unknown option '$1'.
-Type '$PGRM help' for usage."
- fi
- break
- ;;
- esac
- done
-
- log verbose "importing ssh key..."
- fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+ local gpgSecOut
+ local fifoDir
+
+ # FIXME: implement!
+ failure "import-subkey is not implemented yet. We welcome patches. Sorry!"
+
+ sshKeyFile="$1"
+ shift
+
+ # check that key file specified
+ if [ -z "$sshKeyFile" ] ; then
+ failure "Must specify ssh key file to import, or specify '-' for stdin."
+ fi
+
+ # check that the keyID is unique
+ keyID=$(check_gpg_sec_key_id "$@")
+
+ # check that an authentication subkey does not already exist
+ check_gpg_authentication_subkey "$keyID"
+
+ # setup the temp fifo dir for retrieving the key password
+ log debug "creating password fifo..."
+ fifoDir=$(msmktempdir)
+ trap "rm -rf $fifoDir" EXIT
(umask 077 && mkfifo "$fifoDir/pass")
- ssh2openpgp | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+ # import ssh key to as authentication subkey
+ if [ "$sshKeyFile" = '-' ] ; then
+ log verbose "importing ssh key from stdin..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
+ | gpg_user --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+ else
+ log verbose "importing ssh key from file '$sshKeyFile'..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" <"$sshKeyFile" \
+ | gpg_user --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+ fi
+
+ # get the password if needed
passphrase_prompt "Please enter your passphrase for $keyID: " "$fifoDir/pass"
+ trap - EXIT
rm -rf "$fifoDir"
wait
log verbose "done."
diff --git a/src/share/m/ssh_proxycommand b/src/share/m/ssh_proxycommand
index cd0a1fb..bd09588 100644
--- a/src/share/m/ssh_proxycommand
+++ b/src/share/m/ssh_proxycommand
@@ -15,8 +15,6 @@
# established. Can be added to ~/.ssh/config as follows:
# ProxyCommand monkeysphere ssh-proxycommand %h %p
-ssh_proxycommand() {
-
# "marginal case" ouput in the case that there is not a full
# validation path to the host
output_no_valid_key() {
@@ -45,7 +43,7 @@ EOF
# found?
# get the gpg info for userid
- gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \
+ gpgOut=$(gpg_user --list-key --fixed-list-mode --with-colon \
--with-fingerprint --with-fingerprint \
="$userID" 2>/dev/null)
@@ -66,14 +64,14 @@ An OpenPGP key matching the ssh key offered by the host was found:
EOF
- # do some crazy "Here Strings" redirection to get the key to
- # ssh-keygen, since it doesn't read from stdin cleanly
- sshFingerprint=$(ssh-keygen -l -f /dev/stdin \
- <<<$(echo "$sshKeyGPG") | \
+ sshKeyGPGFile=$(msmktempfile)
+ printf "%s" "$sshKeyGPG" >"$sshKeyGPGFile"
+ sshFingerprint=$(ssh-keygen -l -f "$sshKeyGPGFile" | \
awk '{ print $2 }')
+ rm -f "$sshKeyGPGFile"
# get the sigs for the matching key
- gpgSigOut=$(gpg --check-sigs \
+ gpgSigOut=$(gpg_user --check-sigs \
--list-options show-uid-validity \
"$keyid")
@@ -136,10 +134,9 @@ EOF
EOF
}
-########################################################################
-# export the monkeysphere log level
-export MONKEYSPHERE_LOG_LEVEL
+# the ssh proxycommand function itself
+ssh_proxycommand() {
if [ "$1" = '--no-connect' ] ; then
NO_CONNECT='true'
@@ -170,12 +167,13 @@ URI="ssh://${HOSTP}"
# intentionally different than that of running monkeyesphere normally,
# and keyserver checking is intentionally done under certain
# circumstances. This can be overridden by setting the
-# MONKEYSPHERE_CHECK_KEYSERVER environment variable.
+# MONKEYSPHERE_CHECK_KEYSERVER environment variable, or by setting the
+# CHECK_KEYSERVER variable in the monkeysphere.conf file.
# if the host is in the gpg keyring...
-if gpg --list-key ="${URI}" 2>&1 >/dev/null ; then
+if gpg_user --list-key ="${URI}" 2>&1 >/dev/null ; then
# do not check the keyserver
- CHECK_KEYSERVER="false"
+ CHECK_KEYSERVER=${CHECK_KEYSERVER:="false"}
# if the host is NOT in the keyring...
else
@@ -188,20 +186,21 @@ else
# FIXME: more nuanced checking should be done here to properly
# take into consideration hosts that join monkeysphere by
# converting an existing and known ssh key
- CHECK_KEYSERVER="false"
+ CHECK_KEYSERVER=${CHECK_KEYSERVER:="false"}
# if the host key is not found in the known_hosts file...
else
# check the keyserver
- CHECK_KEYSERVER="true"
+ CHECK_KEYSERVER=${CHECK_KEYSERVER:="true"}
fi
fi
-# set and export the variable for use by monkeysphere
-MONKEYSPHERE_CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="$CHECK_KEYSERVER"}
-export MONKEYSPHERE_CHECK_KEYSERVER
+
+# finally look in the MONKEYSPHERE_ environment variable for a
+# CHECK_KEYSERVER setting to override all else
+CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER}
# update the known_hosts file for the host
-monkeysphere update-known_hosts "$HOSTP"
+update_known_hosts "$HOSTP"
# output on depending on the return of the update-known_hosts
# subcommand, which is (ultimately) the return code of the
diff --git a/src/share/m/subkey_to_ssh_agent b/src/share/m/subkey_to_ssh_agent
index 012c95f..818f4f7 100644
--- a/src/share/m/subkey_to_ssh_agent
+++ b/src/share/m/subkey_to_ssh_agent
@@ -46,7 +46,8 @@ For more details, see:
# get list of secret keys (to work around bug
# https://bugs.g10code.com/gnupg/issue945):
- secretkeys=$(gpg --list-secret-keys --with-colons --fixed-list-mode --fingerprint | \
+ secretkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \
+ --fingerprint | \
grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }')
if [ -z "$secretkeys" ]; then
@@ -54,7 +55,7 @@ For more details, see:
You might want to run 'gpg --gen-key'."
fi
- authsubkeys=$(gpg --list-secret-keys --with-colons --fixed-list-mode \
+ authsubkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \
--fingerprint --fingerprint $secretkeys | \
cut -f1,5,10,12 -d: | grep -A1 '^ssb:[^:]*::[^:]*a[^:]*$' | \
grep '^fpr::' | cut -f3 -d: | sort -u)
@@ -64,7 +65,8 @@ You might want to run 'gpg --gen-key'."
You might want to 'monkeysphere gen-subkey'"
fi
- workingdir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+ workingdir=$(msmktempdir)
+ trap "rm -rf $workingdir" EXIT
umask 077
mkfifo "$workingdir/passphrase"
keysuccess=1
@@ -79,19 +81,19 @@ You might want to 'monkeysphere gen-subkey'"
# fingerprint, but filtering out all / characters to make sure
# the filename is legit.
- primaryuid=$(gpg --with-colons --list-key "0x${subkey}!" | grep '^pub:' | cut -f10 -d: | tr -d /)
+ primaryuid=$(gpg_user --with-colons --list-key "0x${subkey}!" | grep '^pub:' | cut -f10 -d: | tr -d /)
#kname="[monkeysphere] $primaryuid"
kname="$primaryuid"
if [ "$1" = '-d' ]; then
# we're removing the subkey:
- gpg --export "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname"
+ gpg_user --export "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname"
(cd "$workingdir" && ssh-add -d "$kname")
else
# we're adding the subkey:
mkfifo "$workingdir/$kname"
- gpg --quiet --passphrase-fd 3 3<"$workingdir/passphrase" \
+ gpg_user --passphrase-fd 3 3<"$workingdir/passphrase" \
--export-options export-reset-subkey-passwd,export-minimal,no-export-attributes \
--export-secret-subkeys "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname" &
(cd "$workingdir" && DISPLAY=nosuchdisplay SSH_ASKPASS=/bin/false ssh-add "$@" "$kname" </dev/null )&
@@ -104,6 +106,7 @@ You might want to 'monkeysphere gen-subkey'"
rm -f "$workingdir/$kname"
done
+ trap - EXIT
rm -rf "$workingdir"
# FIXME: sort out the return values: we're just returning the
diff --git a/src/share/ma/add_certifier b/src/share/ma/add_certifier
index d34f0de..f2cadf2 100644
--- a/src/share/ma/add_certifier
+++ b/src/share/ma/add_certifier
@@ -31,7 +31,6 @@ local domain=
local trust=full
local depth=1
local keyID
-local importinfo
local fingerprint
local ltsignCommand
local trustval
@@ -51,6 +50,9 @@ while true ; do
depth="$2"
shift 2
;;
+ -)
+ break
+ ;;
*)
if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
failure "Unknown option '$1'.
@@ -62,67 +64,13 @@ Type '$PGRM help' for usage."
done
keyID="$1"
+
+# check that key ID or file is specified
if [ -z "$keyID" ] ; then
failure "You must specify the key ID of a key to add, or specify a file to read the key from."
fi
-if [ -f "$keyID" ] ; then
- log info "Reading key from file '$keyID':"
- importinfo=$(gpg_sphere "--import" < "$keyID" 2>&1) || failure "could not read key from '$keyID'"
- # FIXME: if this is tried when the key database is not
- # up-to-date, i got these errors (using set -x):
-
- # ++ su -m monkeysphere -c '\''gpg --import'\''
- # Warning: using insecure memory!
- # gpg: key D21739E9: public key "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" imported
- # gpg: Total number processed: 1
- # gpg: imported: 1 (RSA: 1)
- # gpg: can'\''t create `/var/monkeysphere/gnupg-host/pubring.gpg.tmp'\'': Permission denied
- # gpg: failed to rebuild keyring cache: Permission denied
- # gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
- # gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
- # gpg: next trustdb check due at 2009-01-10'
- # + failure 'could not read key from '\''/root/dkg.gpg'\'''
- # + echo 'could not read key from '\''/root/dkg.gpg'\'''
-
- keyID=$(echo "$importinfo" | grep '^gpg: key ' | cut -f2 -d: | cut -f3 -d\ )
- if [ -z "$keyID" ] || [ $(echo "$keyID" | wc -l) -ne 1 ] ; then
- failure "There was not exactly one gpg key in the file."
- fi
-else
- # get the key from the key server
- log debug "retrieving key from keyserver..."
- gpg_sphere "--keyserver $KEYSERVER --recv-key '0x${keyID}!'" || failure "Could not receive a key with this ID from the '$KEYSERVER' keyserver."
-fi
-
-export keyID
-
-# 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)
-
-if [ -z "$fingerprint" ] ; then
- failure "Key '$keyID' not found."
-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:-N}
- if [ "${OK/y/Y}" != 'Y' ] ; then
- failure "Identity certifier not added."
- fi
-else
- log debug "adding key without prompting."
-fi
-
-# export the key to the core keyring so that the core can sign the
-# new certifier key
-log debug "exporting retrieved certifier key to core keyring..."
-gpg_sphere "--export 0x${fingerprint}!" | gpg_core --import
+# check the trust value
case "$trust" in
'marginal')
trustval=1
@@ -135,6 +83,64 @@ case "$trust" in
;;
esac
+# if file is specified
+if [ -f "$keyID" -o "$keyID" = '-' ] ; then
+ # load the key from stdin
+ if [ "$keyID" = '-' ] ; then
+ # make a temporary file to hold the key from stdin
+ keyID=$(msmktempfile)
+ trap "rm -f $keyID" EXIT
+ log verbose "reading key from stdin..."
+ cat > "$keyID"
+
+ # load the key from the file
+ elif [ -f "$keyID" ] ; then
+ log verbose "reading key from file '$keyID'..."
+ fi
+
+ # check the key is ok as monkeysphere user before loading
+ log debug "checking keys in file..."
+ fingerprint=$(su_monkeysphere_user \
+ ". ${SYSSHAREDIR}/common; list_primary_fingerprints" < "$keyID")
+
+ if [ $(printf "%s" "$fingerprint" | egrep -c '^[A-F0-9]{40}$') -ne 1 ] ; then
+ failure "There was not exactly one gpg key in the file."
+ fi
+
+ # load the key
+ gpg_sphere "--import" <"$keyID" \
+ || failure "could not read key from '$keyID'"
+
+# else, get the key from the keyserver
+else
+ log verbose "searching keyserver $KEYSERVER for keyID $keyID..."
+ gpg_sphere "--keyserver $KEYSERVER --recv-key '0x${keyID}!'" \
+ || failure "Could not receive a key with this ID from the '$KEYSERVER' keyserver."
+
+ # 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)
+
+ 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}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
+ failure "Identity certifier not added."
+ fi
+ else
+ log debug "adding key without prompting."
+ fi
+fi
+
+# export the key to the core keyring so that the core can sign the
+# new certifier key
+log debug "loading key into core keyring..."
+gpg_sphere "--export 0x${fingerprint}!" | gpg_core --import
+
# edit-key script to ltsign key
# NOTE: *all* user IDs will be ltsigned
ltsignCommand=$(cat <<EOF
@@ -151,8 +157,7 @@ EOF
# core ltsigns the newly imported certifier key
log debug "executing core ltsign script..."
if echo "$ltsignCommand" | \
- gpg_core --quiet --command-fd 0 --no-tty --edit-key "0x${fingerprint}!" \
- 2>&1 | log debug ; then
+ gpg_core --command-fd 0 --edit-key "0x${fingerprint}!" ; then
# transfer the new sigs back to the sphere keyring
gpg_core_sphere_sig_transfer
diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics
index 0411080..ce463b2 100644
--- a/src/share/ma/diagnostics
+++ b/src/share/ma/diagnostics
@@ -28,6 +28,8 @@ local badhostkeys
local sshd_config
local problemsfound=0
+report_cruft
+
if ! id monkeysphere >/dev/null ; then
echo "! No monkeysphere user found! Please create a monkeysphere system user with bash as its shell."
problemsfound=$(($problemsfound+1))
@@ -45,7 +47,10 @@ if ! [ -d "$MADATADIR" ] ; then
exit
fi
-# FIXME: what's the correct, cross-platform answer?
+# FIXME: what's the correct, cross-platform way to determine where
+# sshd_config lives?
+sshd_config=/etc/ssh/sshd_config
+
seckey=$(gpg_core --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
keysfound=$(echo "$seckey" | grep -c ^sec:)
curdate=$(date +%s)
@@ -95,7 +100,16 @@ fi
# FIXME: look to see that the ownertrust rules are set properly on the
# sphere keyring
-# FIXME: make sure that at least one identity certifier exists
+# make sure that at least one identity certifier exists
+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
+ connecting users, you should add their key, with:
+ monkeysphere-authentication add-identity-certifier"
+ problemsfound=$(($problemsfound+1))
+fi
# FIXME: look at the timestamps on the monkeysphere-generated
# authorized_keys files -- warn if they seem out-of-date.
diff --git a/src/share/ma/list_certifiers b/src/share/ma/list_certifiers
index a02487d..38a3222 100644
--- a/src/share/ma/list_certifiers
+++ b/src/share/ma/list_certifiers
@@ -86,5 +86,4 @@ gpg_sphere "--fingerprint --with-colons --fixed-list-mode --check-sigs" | \
esac
done
-
}
diff --git a/src/share/ma/remove_certifier b/src/share/ma/remove_certifier
index 10aa67b..a9a1451 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 above listed identity certifier? (y/N) " OK; OK=${OK:-N}
+ read -p "Really remove the identity certifier above? (Y/n) " OK; OK=${OK:-Y}
if [ "${OK/y/Y}" != 'Y' ] ; then
failure "Identity certifier not removed."
fi
diff --git a/src/share/ma/setup b/src/share/ma/setup
index a17e4f2..e77afff 100644
--- a/src/share/ma/setup
+++ b/src/share/ma/setup
@@ -13,13 +13,18 @@
setup() {
# make all needed directories
+ log debug "checking authentication directory structure..."
mkdir -p "${MADATADIR}"
+ chmod 0750 "${MADATADIR}"
+ chgrp "$MONKEYSPHERE_USER" "${MADATADIR}"
mkdir -p "${MATMPDIR}"
+ chmod 0750 "${MATMPDIR}"
+ chgrp "$MONKEYSPHERE_USER" "${MATMPDIR}"
mkdir -p "${GNUPGHOME_CORE}"
- chmod 700 "${GNUPGHOME_CORE}"
+ chmod 0700 "${GNUPGHOME_CORE}"
mkdir -p "${GNUPGHOME_SPHERE}"
- chmod 700 "${GNUPGHOME_SPHERE}"
- mkdir -p "${MADATADIR}"/authorized_keys
+ chmod 0700 "${GNUPGHOME_SPHERE}"
+ mkdir -p "${SYSDATADIR}"/authorized_keys
# deliberately replace the config files via truncation
# FIXME: should we be dumping to tmp files and then moving atomically?
@@ -29,7 +34,6 @@ setup() {
# This file is maintained by the Monkeysphere software.
# Edits will be overwritten.
no-greeting
-list-options show-uid-validity
EOF
log debug "writing sphere gpg.conf..."
@@ -43,9 +47,8 @@ EOF
# make sure the monkeysphere user owns everything in the sphere
# gnupghome
- log debuf "fixing sphere gnupg home ownership..."
- chown -R "$MONKEYSPHERE_USER" "${GNUPGHOME_SPHERE}"
- chgrp -R "$MONKEYSPHERE_USER" "${GNUPGHOME_SPHERE}"
+ log debug "fixing sphere gnupg home ownership..."
+ chown "$MONKEYSPHERE_USER:$MONKEYSPHERE_USER" "${GNUPGHOME_SPHERE}" "${GNUPGHOME_SPHERE}"/gpg.conf
# get fingerprint of core key. this should be empty on unconfigured systems.
local CORE_FPR=$(core_fingerprint)
@@ -59,7 +62,7 @@ EOF
log debug "generating monkeysphere authentication trust core key ($CORE_KEYLENGTH bits)..."
PEM2OPENPGP_USAGE_FLAGS=certify \
PEM2OPENPGP_NEWKEY=$CORE_KEYLENGTH pem2openpgp "$CORE_UID" \
- | gpg_core --import 2>&1 | log debug \
+ | gpg_core --import \
|| failure "Could not import new key for Monkeysphere authentication trust core"
# get fingerprint of core key. should definitely not be empty at this point
@@ -75,17 +78,17 @@ EOF
# export the core key to the sphere keyring
log debug "exporting core pub key to sphere keyring..."
- gpg_core --quiet --export | gpg_sphere "--quiet --import"
+ gpg_core --export | gpg_sphere "--import"
# ensure that the authentication sphere checker has absolute ownertrust on the expected key.
log debug "setting ultimate owner trust on core key in gpg_sphere..."
- printf "%s:6:\n" "$CORE_FPR" | gpg_sphere "--quiet --import-ownertrust"
+ printf "%s:6:\n" "$CORE_FPR" | gpg_sphere "--import-ownertrust"
gpg_sphere "--export-ownertrust" 2>&1 | log debug
# check the owner trust
log debug "checking gpg_sphere owner trust set properly..."
local ORIG_TRUST
- if ORIG_TRUST=$(gpg_sphere "--quiet --export-ownertrust" | grep '^[^#]') ; then
+ if ORIG_TRUST=$(gpg_sphere "--export-ownertrust" | grep '^[^#]') ; then
if [ "${CORE_FPR}:6:" != "$ORIG_TRUST" ] ; then
failure "Monkeysphere authentication trust sphere should explicitly trust the core. It does not have proper ownertrust settings."
fi
@@ -98,7 +101,7 @@ EOF
# our preferences are reasonable (i.e. 3 marginal OR 1 fully
# trusted certifications are sufficient to grant full validity.
log debug "checking trust model for authentication ..."
- local TRUST_MODEL=$(gpg_sphere "--quiet --with-colons --fixed-list-mode --list-keys" \
+ local TRUST_MODEL=$(gpg_sphere "--with-colons --fixed-list-mode --list-keys" \
| head -n1 | grep "^tru:" | cut -d: -f3,6,7)
log debug "sphere trust model: $TRUST_MODEL"
if [ "$TRUST_MODEL" != '1:3:1' ] ; then
diff --git a/src/share/ma/update_users b/src/share/ma/update_users
index e9e3cc6..092d108 100644
--- a/src/share/ma/update_users
+++ b/src/share/ma/update_users
@@ -35,7 +35,7 @@ MODE="authorized_keys"
GNUPGHOME="$GNUPGHOME_SPHERE"
# the authorized_keys directory
-authorizedKeysDir="${MADATADIR}/authorized_keys"
+authorizedKeysDir="${SYSDATADIR}/authorized_keys"
# check to see if the gpg trust database has been initialized
if [ ! -s "${GNUPGHOME}/trustdb.gpg" ] ; then
diff --git a/src/share/mh/add_hostname b/src/share/mh/add_hostname
index 70bbec3..0da6a06 100644
--- a/src/share/mh/add_hostname
+++ b/src/share/mh/add_hostname
@@ -34,8 +34,8 @@ find_host_userid > /dev/null && \
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:=N}
- if [ ${OK/y/Y} != 'Y' ] ; then
+ read -p "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
else
diff --git a/src/share/mh/add_revoker b/src/share/mh/add_revoker
index b4113df..428b958 100644
--- a/src/share/mh/add_revoker
+++ b/src/share/mh/add_revoker
@@ -15,91 +15,99 @@
add_revoker() {
-local domain=
-local trust=full
-local depth=1
local keyID
-local importinfo
+local tmpDir
local fingerprint
-local ltsignCommand
-local trustval
+local addrevokerCommand
keyID="$1"
+
+# check that key ID or file is specified
if [ -z "$keyID" ] ; then
failure "You must specify the key ID of a revoker key, or specify a file to read the key from."
fi
-if [ -f "$keyID" ] ; then
- log info "Reading key from file '$keyID':"
- importinfo=$(gpg_host --import < "$keyID" 2>&1) || failure "could not read key from '$keyID'"
- # FIXME: if this is tried when the key database is not
- # up-to-date, i got these errors (using set -x):
-
- # ++ su -m monkeysphere -c '\''gpg --import'\''
- # Warning: using insecure memory!
- # gpg: key D21739E9: public key "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" imported
- # gpg: Total number processed: 1
- # gpg: imported: 1 (RSA: 1)
- # gpg: can'\''t create `/var/monkeysphere/gnupg-host/pubring.gpg.tmp'\'': Permission denied
- # gpg: failed to rebuild keyring cache: Permission denied
- # gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
- # gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
- # gpg: next trustdb check due at 2009-01-10'
- # + failure 'could not read key from '\''/root/dkg.gpg'\'''
- # + echo 'could not read key from '\''/root/dkg.gpg'\'''
-
- keyID=$(echo "$importinfo" | grep '^gpg: key ' | cut -f2 -d: | cut -f3 -d\ )
- if [ -z "$keyID" ] || [ $(echo "$keyID" | wc -l) -ne 1 ] ; then
+
+# make a temporary directory for storing keys during import, and set
+# the trap to delete it on exit
+tmpDir=$(msmktempdir)
+trap "rm -rf $tmpDir" EXIT
+
+# if file is specified
+if [ -f "$keyID" -o "$keyID" = '-' ] ; then
+ # load the key from stdin
+ if [ "$keyID" = '-' ] ; then
+ # make a temporary file to hold the key from stdin
+ keyID="$tmpDir"/importkey
+ log verbose "reading key from stdin..."
+ cat > "$keyID"
+
+ # load the key from the file
+ elif [ -f "$keyID" ] ; then
+ log verbose "reading key from file '$keyID'..."
+ fi
+
+ # check the key is ok as monkeysphere user before loading
+ log debug "checking keys in file..."
+ fingerprint=$(su_monkeysphere_user \
+ ". ${SYSSHAREDIR}/common; list_primary_fingerprints" < "$keyID")
+
+ if [ $(printf "%s" "$fingerprint" | egrep -c '^[A-F0-9]{40}$') -ne 1 ] ; then
failure "There was not exactly one gpg key in the file."
fi
+
+ # load the key
+ gpg_host --import <"$keyID" \
+ || failure "could not read key from '$keyID'"
+
+# else, get the key from the keyserver
else
- # create a temporary directory for storing the downloaded key
- TMPLOC=$(mktemp -d "${MHTMPDIR}"/tmp.XXXXXXXXXX) || failure "Could not create temporary directory!"
+ # fix permissions and ownership on temporary directory which will
+ # be used by monkeysphere user for storing the downloaded key
+ chmod 0700 "$tmpDir"
+ chown "$MONKEYSPHERE_USER":"$MONKEYSPHERE_USER" "$tmpDir"
# download the key from the keyserver as the monkeysphere user
- su_monkeysphere_user \
- "GNUPGHOME=$TMPLOC gpg --keyserver $KEYSERVER --recv-key 0x${keyID}!"
+ log verbose "searching keyserver $KEYSERVER for keyID $keyID..."
+ su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --quiet --keyserver $KEYSERVER --recv-key 0x${keyID}!" \
+ || failure "Could not receive a key with this ID from the '$KEYSERVER' keyserver."
+
+ # 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)
+
+ 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}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
+ failure "revoker not added."
+ fi
+ else
+ log debug "adding revoker without prompting."
+ fi
# export the new key to the host keyring
- su_monkeysphere_user "GNUPGHOME=$TMPLOC gpg --export 0x${keyID}!" \
+ log debug "loading key into host keyring..."
+ su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --quiet --export 0x${fingerprint}!" \
| gpg_host --import
fi
-export keyID
-
-# get the full fingerprint of the revoker key ID
-fingerprint=$(gpg_host --list-key --with-colons --with-fingerprint "0x${keyID}!" \
- | grep '^fpr:' | grep "$keyID" | cut -d: -f10)
-
-if [ -z "$fingerprint" ] ; then
- failure "Key '$keyID' not found."
-fi
-
-log info "key found:"
-gpg_host --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:-N}
- if [ "${OK/y/Y}" != 'Y' ] ; then
- failure "revoker not added."
- fi
-else
- log debug "adding revoker without prompting."
-fi
-
# edit-key script to add revoker
addrevokerCommand=$(cat <<EOF
addrevoker
+$fingerprint
+y
+save
EOF
)
-# FIXME: implement!
-failure "not implemented yet!"
-
# core ltsigns the newly imported revoker key
-if echo "$addrevokerCommand" | \
- gpg_core_edit ; then
+log debug "executing add revoker script..."
+if echo "$addrevokerCommand" | gpg_host_edit ; then
update_gpg_pub_file
@@ -108,4 +116,8 @@ else
failure "Problem adding revoker."
fi
+# remove the temporary directory
+trap - EXIT
+rm -rf "$tmpDir"
+
}
diff --git a/src/share/mh/diagnostics b/src/share/mh/diagnostics
index d774723..2f65f89 100644
--- a/src/share/mh/diagnostics
+++ b/src/share/mh/diagnostics
@@ -25,11 +25,10 @@ local expire
local uid
local fingerprint
local badhostkeys
-local sshd_config
local problemsfound=0
-# FIXME: what's the correct, cross-platform answer?
-sshd_config=/etc/ssh/sshd_config
+report_cruft
+
seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
keysfound=$(echo "$seckey" | grep -c ^sec:)
curdate=$(date +%s)
@@ -50,7 +49,7 @@ fi
echo "Checking host GPG key..."
if (( "$keysfound" < 1 )); then
echo "! No host key found."
- echo " - Recommendation: run 'monkeysphere-host gen-key' or 'monkeysphere-host import-key'"
+ echo " - Recommendation: run 'monkeysphere-host import-key'"
problemsfound=$(($problemsfound+1))
elif (( "$keysfound" > 1 )); then
echo "! More than one host key found?"
@@ -114,35 +113,9 @@ else
# FIXME: propose adding a revoker to the host key if none exist (do we
# have a way to do that after key generation?)
- # Ensure that the ssh_host_rsa_key file is present and non-empty:
- echo
- echo "Checking host SSH key..."
- if [ ! -s "${SYSDATADIR}/ssh_host_rsa_key" ] ; then
- echo "! The host key as prepared for SSH (${SYSDATADIR}/ssh_host_rsa_key) is missing or empty."
- problemsfound=$(($problemsfound+1))
- else
- if [ $(ls -l "${SYSDATADIR}/ssh_host_rsa_key" | cut -f1 -d\ ) != '-rw-------' ] ; then
- echo "! Permissions seem wrong for ${SYSDATADIR}/ssh_host_rsa_key -- should be 0600."
- problemsfound=$(($problemsfound+1))
- fi
+# FIXME: test (with ssh-keyscan?) that the running ssh
+# daemon is actually offering the monkeysphere host key.
- # propose changes needed for sshd_config (if any)
- if ! grep -q "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$" "$sshd_config"; then
- echo "! $sshd_config does not point to the monkeysphere host key (${SYSDATADIR}/ssh_host_rsa_key)."
- echo " - Recommendation: add a line to $sshd_config: 'HostKey ${SYSDATADIR}/ssh_host_rsa_key'"
- problemsfound=$(($problemsfound+1))
- fi
- if badhostkeys=$(grep -i '^HostKey' "$sshd_config" | grep -v "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$") ; then
- echo "! $sshd_config refers to some non-monkeysphere host keys:"
- echo "$badhostkeys"
- echo " - Recommendation: remove the above HostKey lines from $sshd_config"
- problemsfound=$(($problemsfound+1))
- fi
-
- # FIXME: test (with ssh-keyscan?) that the running ssh
- # daemon is actually offering the monkeysphere host key.
-
- fi
fi
# FIXME: look at the ownership/privileges of the various keyrings,
diff --git a/src/share/mh/import_key b/src/share/mh/import_key
index 557bb7f..040b41c 100644
--- a/src/share/mh/import_key
+++ b/src/share/mh/import_key
@@ -13,15 +13,22 @@
import_key() {
+local sshKeyFile
local hostName
local domain
local userID
-hostName="$1"
+sshKeyFile="$1"
+hostName="$2"
+
+# check that key file specified
+if [ -z "$sshKeyFile" ] ; then
+ failure "Must specify ssh key file to import, or specify '-' for stdin."
+fi
# use the default hostname if not specified
if [ -z "$hostName" ] ; then
- hostName=$(hostname -f)
+ hostName=$(hostname -f) || failure "Could not determine hostname."
# test that the domain is not obviously illegitimate
domain=${foo##*.}
case $domain in
@@ -39,14 +46,20 @@ userID="ssh://${hostName}"
# create host home
mkdir -p "${MHDATADIR}"
-mkdir -p "${MHTMPDIR}"
mkdir -p "${GNUPGHOME_HOST}"
chmod 700 "${GNUPGHOME_HOST}"
-log verbose "importing ssh key..."
-# translate ssh key to a private key
-PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
- | gpg_host --import 2>&1 | log debug
+# import ssh key to a private key
+if [ "$sshKeyFile" = '-' ] ; then
+ log verbose "importing ssh key from stdin..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
+ | gpg_host --import
+else
+ log verbose "importing ssh key from file '$sshKeyFile'..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
+ <"$sshKeyFile" \
+ | gpg_host --import
+fi
# load the new host fpr into the fpr variable. this is so we can
# create the gpg pub key file. we have to do this from the secret key
diff --git a/src/share/mh/publish_key b/src/share/mh/publish_key
index b433ad7..b0ffd93 100644
--- a/src/share/mh/publish_key
+++ b/src/share/mh/publish_key
@@ -18,8 +18,8 @@ publish_key() {
local GNUPGHOME
if [ "$PROMPT" = "true" ] ; then
- read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
- if [ ${OK/y/Y} != 'Y' ] ; then
+ read -p "Really publish host key to $KEYSERVER? (Y/n) " OK; OK=${OK:=Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
failure "key not published."
fi
else
@@ -27,7 +27,9 @@ else
fi
# create a temporary gnupg directory from which to publish the key
-export GNUPGHOME=$(mktemp -d)
+export GNUPGHOME=$(msmktempdir)
+chmod 0700 "$GNUPGHOME"
+chown "$MONKEYSPHERE_USER":"$MONKEYSPHERE_USER" "$GNUPGHOME"
# trap to remove tmp dir if break
trap "rm -rf $GNUPGHOME" EXIT
diff --git a/src/share/mh/revoke_hostname b/src/share/mh/revoke_hostname
index 77f1f0d..71b56ed 100644
--- a/src/share/mh/revoke_hostname
+++ b/src/share/mh/revoke_hostname
@@ -28,7 +28,7 @@ if [ -z "$1" ] ; then
fi
echo "WARNING: There is a known bug in this function."
-echo "This function has been known to occasionally revoke the wrong user ID."
+echo "This function has been known to occasionally revoke the wrong hostname."
echo "Please see the following bug report for more information:"
echo "https://labs.riseup.net/code/issues/show/422"
read -p "Are you sure you would like to proceed? (y/N) " OK; OK=${OK:=N}
@@ -45,8 +45,8 @@ uidIndex=$(find_host_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? (y/N) " OK; OK=${OK:=N}
- if [ ${OK/y/Y} != 'Y' ] ; then
+ read -p "Are you sure you would like to revoke this user ID? (N/y) " OK; OK=${OK:=Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
failure "User ID not revoked."
fi
else
diff --git a/src/share/mh/revoke_key b/src/share/mh/revoke_key
index cccdc22..380236b 100644
--- a/src/share/mh/revoke_key
+++ b/src/share/mh/revoke_key
@@ -15,7 +15,31 @@
revoke_key() {
-# FIXME: implement!
-failure "not implemented yet!"
+# Coming in here, we expect $HOST_FINGERPRINT to be set, and we
+# believe that there is in fact a key.
+ # 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:
+
+ # an admin wants a revocation certificate for the host which they
+ # can store securely offline. In this case, the admin can
+ # redirect stdout to a file, or can simply copy/paste or
+ # transcribe from the terminal.
+
+ # Alternately, an admin might want to publish the revocation
+ # certificate immediately. here's a quick way to do this:
+
+
+ # 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)
+
+
+ # 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
+
+ GNUPGHOME="$GNUPGHOME_HOST" gpg --no-greeting --quiet --armor --gen-revoke "0x${HOST_FINGERPRINT}!"
}
diff --git a/src/share/mh/set_expire b/src/share/mh/set_expire
index ae7c13a..63e5c55 100644
--- a/src/share/mh/set_expire
+++ b/src/share/mh/set_expire
@@ -22,7 +22,7 @@ local extendTo
extendTo=$(get_gpg_expiration "$1")
if [ "$PROMPT" = "true" ] ; then
- read -p "Are you sure you want to change the expiration on the host key to '$extendTo'? (y/N) " OK; OK=${OK:-N}
+ read -p "Are you sure you want to change the expiration on the host key to '$extendTo'? (Y/n) " OK; OK=${OK:-Y}
if [ "${OK/y/Y}" != 'Y' ] ; then
failure "expiration not set."
fi
diff --git a/src/transition_0.22_0.23 b/src/transition_0.22_0.23
deleted file mode 100755
index 3328e8c..0000000
--- a/src/transition_0.22_0.23
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/bash
-
-# This is a post-install script for monkeysphere, to transition an old
-# (<=0.22) setup to the new (>0.22) setup
-
-SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
-
-MADATADIR="${SYSDATADIR}/authentication"
-MHDATADIR="${SYSDATADIR}/host"
-
-############################################################
-### transfer host setup
-
-if [ -d "$SYSDATADIR"/gnupg-host ] ; then
-
- if [ -s "$SYSDATADIR"/ssh_host_rsa_key ] ; then
-
- # This would be simple, but it would generate a new pgp key,
- #and we don't want that, right?
- #monkeysphere-host expert import_key "$SYSDATADIR"/ssh_host_rsa_key
-
- # create host home
- mkdir -p "${MHDATADIR}"
- mkdir -p "${MHTMPDIR}"
- mkdir -p "${GNUPGHOME_HOST}"
- chmod 700 "${GNUPGHOME_HOST}"
-
- # transfer the host secret key from the old home to the new
- GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --export-secret-keys \
- GNUPGHOME="$MHDATADIR" gpg --import
-
- # make sure the ssh_host_rsa_key.pub and ssh_host_rsa_key.pub.gpg
- # files exist
-
- # anything else?
-
- fi
-
- #rm -rf "$SYSDATADIR"/gnupg-host
-
-fi
-
-############################################################
-### transfer authentication setup
-
-# should we test for something else/better than the existence of this
-# directory to know that we should go through the setup?
-if [ -d "$SYSDATADIR"/gnupg-authentication ] ; then
-
- # run the authentication setup
- monkeysphere-authentication setup
-
- # transfer certifiers
- # FIXME: how?
- # i think we'll need to run something like
- # gpg_core_sphere_sig_transfer after transfering certifiers ltsigs
-
- # do we need to do some sort of transfer of ownertrust?
-
- # move the authorized_keys directory
- mv "$SYSDATADIR"/authorized_keys "$MADATADIR"/
-
- # do we need to transfer anything else? running update-users will
- # regenerate everything else in the sphere keyring, right?
-
- #rm -rf "$SYSDATADIR"/gnupg-authentication
-
-fi
-
diff --git a/src/transitions/0.23 b/src/transitions/0.23
new file mode 100755
index 0000000..f09dfff
--- /dev/null
+++ b/src/transitions/0.23
@@ -0,0 +1,180 @@
+#!/bin/bash
+
+# This is a post-install script for monkeysphere, to transition an old
+# (<0.23) setup to the new (>=0.23) setup.
+
+# You should be able to run this script after any version >= 0.23 is
+# installed. This script should be well-behaved, even if it is run
+# repeatedly.
+
+# Written by
+# Jameson Rollins <jrollins@finestructure.net>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# Copyright 2009, released under the GPL, version 3 or later
+
+# NOTE: the reverse operation (downgrading) is not directly supported,
+# and MAY LOCK YOU OUT OF YOUR SYSTEM, depending on how you have
+# configured the monkeysphere!
+
+# any unexpected errors should cause this script to bail:
+set -e
+
+SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
+
+MADATADIR="${SYSDATADIR}/authentication"
+MHDATADIR="${SYSDATADIR}/host"
+
+STASHDIR="${SYSDATADIR}/backup-from-0.23-transition"
+
+
+log() {
+ printf "$@" >&2
+}
+
+# FIXME: implement this function better. here, we only care about
+# dots, *and* about reversing the regexification of them.
+gpg_unescape_and_unregex() {
+ sed 's/\\x5c\././g'
+}
+
+
+is_domain_name() {
+ printf "%s" "$1" | egrep -q '^[[:alnum:]][[:alnum:]-.]*[[:alnum:]]$'
+}
+
+# run the authentication setup (this is also the first chance to bail
+# if 0.23 is not fully-installed, because m-a did not exist before
+# 0.23)
+monkeysphere-authentication setup
+
+# before 0.23, the old gnupg-host data directory used to contain the
+# trust core and the system's ssh host key.
+
+if [ -d "$SYSDATADIR"/gnupg-host ] ; then
+
+### transfer identity certifiers, if they don't already exist in the
+### current setup:
+
+ if monkeysphere-authentication list-identity-certifiers | \
+ grep -q '^[A-F0-9]{40}:$' ; then
+ log 'There are already certifiers in the new system!\nNot transferring any certifiers.\n'
+ else
+ # get the old host keygrip (don't know why there would be more
+ # than one, but we'll transfer all tsigs made by any key that
+ # had been given ultimate ownertrust):
+ for authgrip in $(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-ownertrust | \
+ grep ':6:$' | \
+ sed -r 's/^[A-F0-9]{24}([A-F0-9]{16}):6:$/\1/') ; do
+
+ # we're assuming that old id certifiers were only added by old
+ # versions of m-s c+, which added certifiers by ltsigning
+ # entire keys.
+
+ # so we'll walk the list of tsigs from the old host key, and
+ # add those keys as certifiers to the new system.
+
+ # FIXME: if an admin has run "m-s add-id-certifier $foo"
+ # multiple times for the same $foo, we'll only transfer
+ # one of those certifications (even if later
+ # certifications had different parameters).
+
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --fingerprint --with-colons --fixed-list-mode --check-sigs | \
+ cut -f 1,2,5,8,9,10 -d: | \
+ egrep '^(fpr:::::|sig:!:'"$authgrip"':[[:digit:]]+ [[:digit:]]+:)' | \
+ while IFS=: read -r type validity grip trustparams trustdomain fpr ; do
+ case $type in
+ 'fpr') # this is a new key
+ keyfpr=$fpr
+ ;;
+ 'sig') # deal with all trust signatures, including
+ # regexes if present.
+ if [ "$keyfpr" ] ; then
+ trustdepth=${trustparams%% *}
+ trustlevel=${trustparams##* }
+ if [ "$trustlevel" -ge 120 ] ; then
+ truststring=full
+ elif [ "$trustlevel" -ge 60 ] ; then
+ truststring=marginal
+ else
+ # trust levels below marginal are ignored.
+ continue
+ fi
+
+ finaldomain=
+ if [ "$trustdomain" ] ; then
+ # FIXME: deal with translating
+ # $trustdomain back to a domain.
+ if [ printf "%s" "$trustdomain" | egrep -q '^<\[\^>\]\+\[@\.\][^>]+>\$$' ] ; then
+ dpart=$(printf "%s" "$trustdomain" | sed -r 's/^<\[\^>\]\+\[@\.\]([^>]+)>\$$/\1/' | gpg_unescape_and_unregex)
+ if [ is_domain_name "$dpart" ]; then
+ finaldomain="--domain $dpart"
+ else
+ log "Does not seem to be a domain name (%s), not adding certifier\n" "$dpart"
+ continue
+ fi
+ else
+ log "Does not seem to be a standard gpg domain-based tsig (%s), not adding certifier\n" "$trustdomain"
+ continue
+ fi
+ fi
+
+ CERTKEY=$(mktemp ${TMPDIR:-/tmp}/mstransition.XXXXXXXX)
+ log "Adding identity certifier with fingerprint %s\n" "$keyfpr"
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export "0x$keyfpr" --export-options export-clean >"$CERTKEY"
+ MONKEYSPHERE_PROMPT=false monkeysphere-authentication add-identity-certifier $finaldomain --trust "$truststring" --depth "$trustdepth" "$CERTKEY"
+ rm -f "$CERTKEY"
+ # clear the fingerprint so that we don't
+ # make additional tsigs on it if more uids
+ # are present:
+ keyfpr=
+ fi
+ ;;
+ esac
+ done
+ done
+ fi
+
+### transfer host key information (if present) into the new spot
+
+ if [ -d "${MHDATADIR}" ] ; then
+ log "Not transferring host key info because host directory already exists.\n"
+ else
+ if [ -s "$SYSDATADIR"/ssh_host_rsa_key ] || \
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --list-secret-keys | grep -q '^sec:' ; then
+
+ # create host home
+ mkdir -p "${MHDATADIR}"
+ chmod 0700 "${MHDATADIR}"
+
+ log "importing host key from old monkeysphere installation\n"
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys | \
+ GNUPGHOME="$MHDATADIR" gpg --quiet --no-tty --import
+
+ monkeysphere-host update-gpg-pub-file
+ else
+ log "No host key found in old monkeysphere install; not importing any host key.\n"
+ fi
+ fi
+
+
+### get rid of this old stuff, since we've transferred it all:
+
+ mkdir -p "$STASHDIR"
+ chmod 0700 "$STASHDIR"
+ mv "${SYSDATADIR}/gnupg-host" "$STASHDIR"
+fi
+
+
+# There is nothing in the old authentication directory that we should
+# need to keep around, but it is not unreasonable to transfer keys to
+# the new authentication keyring.
+if [ -d "${SYSDATADIR}/gnupg-authentication" ] ; then
+
+ GNUPGHOME="${SYSDATADIR}/gnupg-authentication" gpg --no-permission-warning --export | \
+ monkeysphere-authentication gpg-cmd --import
+
+ mkdir -p "$STASHDIR"
+ chmod 0700 "$STASHDIR"
+ mv "${SYSDATADIR}/gnupg-authentication" "$STASHDIR"
+fi
diff --git a/src/transitions/README.txt b/src/transitions/README.txt
new file mode 100644
index 0000000..7488c74
--- /dev/null
+++ b/src/transitions/README.txt
@@ -0,0 +1,16 @@
+This directory contains transition scripts for major changes to
+monkeysphere infrastructure.
+
+They are expected to be run immediately after upgrading to the named
+version or later.
+
+For example: you upgrade to from version 0.8 to version 0.15, and the
+directory contains 0.6, 0.12 and 0.15, you should run 0.12 followed by
+0.15.
+
+The scripts are supposed to be cleverly-written enough that you can
+run them repeatedly, and they should only make their intended changes
+once. If they do not behave that way, this is a bug. Please report
+it!
+
+ https://labs.riseup.net/code/projects/monkeysphere/
diff --git a/tests/basic b/tests/basic
index 18e3019..3d50977 100755
--- a/tests/basic
+++ b/tests/basic
@@ -26,6 +26,7 @@ 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; }
+
## FIXME: other checks?
######################################################################
@@ -123,6 +124,21 @@ export SOCKET="$TEMPDIR"/ssh-socket
# *anything* with any running X11 session.
export DISPLAY=monkeys
+## make sure that the version number matches the debian changelog
+## (don't bother if this is being run from the tests).
+
+if [ -f "$TESTDIR"/../packaging/debian/changelog ]; then
+ echo "##################################################"
+ echo "### checking version string match..."
+ repver=$(monkeysphere version)
+ debver=$(head -n1 "$TESTDIR"/../packaging/debian/changelog | sed 's/.*(\([^-]*\)-.*/\1/')
+ if [ "$repver" = "$debver" ] ; then
+ echo "Versions match!"
+ else
+ printf "reported version string (%s) does not match debian changelog (%s)\n" "$repver" "$debver"
+ exit 1
+ fi
+fi
######################################################################
### CONFIGURE ENVIRONMENTS
@@ -158,7 +174,7 @@ cp "$TESTDIR"/etc/ssh/sshd_config "$SSHD_CONFIG"
# write the sshd_config
cat <<EOF >> "$SSHD_CONFIG"
HostKey ${MONKEYSPHERE_SYSDATADIR}/ssh_host_rsa_key
-AuthorizedKeysFile ${MONKEYSPHERE_SYSDATADIR}/authentication/authorized_keys/%u
+AuthorizedKeysFile ${MONKEYSPHERE_SYSDATADIR}/authorized_keys/%u
EOF
@@ -169,7 +185,7 @@ EOF
echo "##################################################"
echo "### import host key..."
ssh-keygen -b 1024 -t rsa -N '' -f "$TEMPDIR"/ssh_host_rsa_key
-monkeysphere-host import-key testhost < "$TEMPDIR"/ssh_host_rsa_key
+monkeysphere-host import-key "$TEMPDIR"/ssh_host_rsa_key testhost
echo "##################################################"
echo "### getting host key fingerprint..."
@@ -227,7 +243,7 @@ monkeysphere-authentication list-certifiers
# generate an auth subkey for the test user that expires in 2 days
echo "##################################################"
echo "### generating key for testuser..."
-monkeysphere gen-subkey --expire 2
+monkeysphere gen-subkey
# add server key to testuser keychain
echo "##################################################"
diff --git a/website/getting-started-admin.mdwn b/website/getting-started-admin.mdwn
index 5c7203d..9010132 100644
--- a/website/getting-started-admin.mdwn
+++ b/website/getting-started-admin.mdwn
@@ -4,11 +4,11 @@ Monkeysphere Server Administrator README
As the administrator of an SSH server, you can take advantage of the
monkeysphere in two ways:
-1. you can publish the host key of your machine so that your users can
-have it automatically verified, and
+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
2. you can set up your machine to automatically identify connecting
-users by their presence in the OpenPGP web of trust.
+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
@@ -18,26 +18,28 @@ least the host key into the Web of Trust so that your users can be
sure they're connecting to the correct machine.
-Monkeysphere for host verification
-==================================
+Monkeysphere for host verification (monkeysphere-host)
+======================================================
Server host key publication
---------------------------
-To begin, you must first generate a server host key:
+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-server gen-key
+ # monkeysphere-host /etc/ssh/ssh\_host\_rsa\_key
This will generate the key for server with the service URI
-(`ssh://server.example.net`). Output the new key information with the
-'show-key' command:
+(`ssh://server.example.net`). You can output the new key information
+with the 'show-key' command:
- # monkeysphere-server show-key
+ # monkeysphere-host show-key
-Once the key has been generated, it needs to be publish to the Web of
+Once the key has been imported, it needs to be publish to the Web of
Trust:
- # monkeysphere-server publish-key
+ # 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
@@ -56,49 +58,17 @@ keyservers:
$ gpg --send-key '=ssh://server.example.net'
-Update OpenSSH configuration files
-----------------------------------
+See http://web.monkeysphere.info/signing-host-keys/ for more info
+signing host keys.
-To use the newly-generated host key for ssh connections, put the
-following line in `/etc/ssh/sshd_config` (be sure to comment out or
-remove any other HostKey references):
-
- HostKey /var/lib/monkeysphere/ssh_host_rsa_key
-
-FIXME: What about DSA host keys? The SSH RFC seems to require
-implementations support DSA, though OpenSSH will work without a DSA
-host key.
-
-
-Monkeysphere for user authentication
-====================================
+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.
-Before this can happen, the host must first have a host key to use for
-user key verification. If you have not already generated a host key
-(as in the host verification instructions above), generate one now:
-
- # monkeysphere-server gen-key
-
-Update OpenSSH configuration files
-----------------------------------
-
-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):
-
- 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.
-
Monkeysphere authorized_keys maintenance
----------------------------------------
@@ -113,22 +83,36 @@ 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 trusted identity certifer.
-If the admin's OpenPGP keyid is `$GPGID`, then on the server run:
+scenario, the host's administrator would be a trusted identity
+certifer. If the admin's OpenPGP keyid is `$GPGID`, then on the
+server run:
- # monkeysphere-server add-identity-certifier $GPGID
+ # monkeysphere-authentication add-identity-certifier $GPGID
To update the monkeysphere `authorized_keys` file for user "bob" using
the current set of identity certifiers, run:
- # monkeysphere-server update-users bob
+ # monkeysphere-authentication update-users bob
To update the monkeysphere `authorized_keys` file for all users on the
the system, run the same command with no arguments:
- # monkeysphere-server update-users
+ # monkeysphere-authentication update-users
You probably want to set up a regularly scheduled job (e.g. with cron)
to take care of this automatically.
-FIXME: document other likely problems and troubleshooting techniques
+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):
+
+ 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.
diff --git a/website/getting-started-user.mdwn b/website/getting-started-user.mdwn
index 9b04edc..ec157ac 100644
--- a/website/getting-started-user.mdwn
+++ b/website/getting-started-user.mdwn
@@ -49,7 +49,6 @@ 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.
-
Using `monkeysphere-ssh-proxycommand`(1)
----------------------------------------
@@ -59,7 +58,7 @@ 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:
- ProxyCommand monkeysphere-ssh-proxycommand %h %p
+ 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
@@ -84,9 +83,10 @@ verify you based on your OpenPGP key.
Setting up an OpenPGP authentication key
----------------------------------------
-First things first: you'll need to create an "authentication" subkey
-for your current key, if you don't already have one. If you already
-have a GPG key, you can add an authentication subkey with:
+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:
$ monkeysphere gen-subkey
@@ -94,7 +94,6 @@ 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.
-
Using your OpenPGP authentication key for SSH
---------------------------------------------