Merge commit 'jrollins/master'
authorMatt Goins <mjgoins@openflows.com>
Fri, 20 Feb 2009 16:42:10 +0000 (11:42 -0500)
committerMatt Goins <mjgoins@openflows.com>
Fri, 20 Feb 2009 16:42:10 +0000 (11:42 -0500)
36 files changed:
Makefile
man/man1/monkeysphere.1
man/man7/monkeysphere.7
man/man8/monkeysphere-authentication.8
man/man8/monkeysphere-host.8
packaging/debian/NEWS [new file with mode: 0644]
packaging/debian/changelog
packaging/debian/monkeysphere.postinst
src/monkeysphere
src/monkeysphere-authentication
src/monkeysphere-host
src/share/common
src/share/m/gen_subkey
src/share/m/import_subkey
src/share/m/ssh_proxycommand
src/share/m/subkey_to_ssh_agent
src/share/ma/add_certifier
src/share/ma/diagnostics
src/share/ma/list_certifiers
src/share/ma/remove_certifier
src/share/ma/setup
src/share/ma/update_users
src/share/mh/add_hostname
src/share/mh/add_revoker
src/share/mh/diagnostics
src/share/mh/import_key
src/share/mh/publish_key
src/share/mh/revoke_hostname
src/share/mh/revoke_key
src/share/mh/set_expire
src/transition_0.22_0.23 [deleted file]
src/transitions/0.23 [new file with mode: 0755]
src/transitions/README.txt [new file with mode: 0644]
tests/basic
website/getting-started-admin.mdwn
website/getting-started-user.mdwn

index 59b8887e1406a45ba59ef1e827c46913e36ce56e..71df92b935e1d955a0c596da784ed73a564275db 100755 (executable)
--- 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
index 0e8004700159d1bd4d88b0691dd779cf664be097..887b5df1d9de1a59b1179240ba08ca99c629949c 100644 (file)
@@ -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
 
index d221c87ba369dcafed6cb3f5bc6789dd44a58f31..578d96cef5f4408692478b569de7be6ae5cfb685 100644 (file)
@@ -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/
index 4d453d377337ed74452cad84b6eab9a13e7d9a43..361822d4382b9fe6bb742c50a3a2868a31c79e26 100644 (file)
@@ -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
index 330b6107a20a28c2b4c2ce355039e62b90fa8a41..2ccaaec59f6340e136b3722fcb4abcd7c35e5925 100644 (file)
@@ -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 (file)
index 0000000..3fceea2
--- /dev/null
@@ -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
+
index c825b646d95c41a80ed12e60aaec522db97f8e3c..fc317d9e1b3935bcb09a3e3a4f043368ab1b7760 100644 (file)
@@ -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
 
index 8e7977173b71fd370194613c7ebdfe88ac3e50be..3d0d66ff1417a365dd9bf0f1b4f2351a75c22bc2 100755 (executable)
@@ -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
 
index da5f406165469e942654c5865a99f66ea80cc3d6..a65cef62273e76671bc6fe658564195551a2ad8a 100755 (executable)
@@ -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"
index 8a4146f36c9df4a2fa1f417d29dd9532a6117c1e..497470dc88fc5d36d260c20f4832096042f0a2f7 100755 (executable)
@@ -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"}
index c7e011b6b1f759513c074e82c6290d8c7685c6b5..4c7df88e31a72fdd18b63a8e59ee87d47e0ec4d9 100755 (executable)
@@ -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"
        ;;
index 4120259b5f0054c6d42b5f69848cecb60b632e7f..653d58ba0154941887a340e7889b391079db1bae 100644 (file)
@@ -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
+}
index cbefaa3ecbf518e34a44d3c04ab5c3b9f7bf7cf2..dbd9dd69da0da47ae2fc51bf0508b550794fd9ad 100644 (file)
 
 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."
index aa89958a7d428344db9e23d5905fc1ae1d0eaec0..8d60f26aaa849cbeeabbeccd8fc2a6f3ea01a9b7 100644 (file)
 
 # 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."
index cd0a1fb14436b833055e2c6ab3bc736a1534abbf..bd095889e528f61b0a75a503fcb5a12ba7942c57 100644 (file)
@@ -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
index 012c95f80f5bbce1640821fb3eada10e15b1b078..818f4f70c3ae65a86ed58c169a02c31b89884d5e 100644 (file)
@@ -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
index d34f0dec08d44ce8f1a362cefc8090a543ebf49f..f2cadf20b37dff6d9ddc2d42bcd79fc900ecbd37 100644 (file)
@@ -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
index 0411080fb8cd3599fee36ecc0ab6cf11e997faf5..ce463b211c1a811d7db8c28e2f2026532e046918 100644 (file)
@@ -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.
index a02487dd033000eb2762e069a296730a85786d89..38a3222db32e721c7cb8adaf70913c8659be5f50 100644 (file)
@@ -86,5 +86,4 @@ gpg_sphere "--fingerprint --with-colons --fixed-list-mode --check-sigs" | \
     esac
 done
 
-
 }
index 10aa67b1dc820827b5517ba4c8c172292afc79fb..a9a1451159ba4c5b6a18897f85f6331cdda21416 100644 (file)
@@ -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
index a17e4f2cad07e18515fbfa30071a06526f85165b..e77afff4299795c7a442bccf43e74dea1f2884e3 100644 (file)
 
 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
index e9e3cc60387f899469c1361ae12d56c4bde3d0cc..092d10870c6e8356bbec956ec3ed4f844cf734a5 100644 (file)
@@ -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
index 70bbec3f535acc9149a6c401cc5682d7a88c8d7b..0da6a0655ea3063b2548082050271bea29d4d57f 100644 (file)
@@ -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
index b4113df309fe639f1e4282d343b2faf37859dfb8..428b95834927e840c145147478ac970a8ce16410 100644 (file)
 
 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"
+
 }
index d774723d512b892001c4d42a5c49bdba65f2fb12..2f65f899f4cfdd7f0e4aad9fe1304ee50bf46ec2 100644 (file)
@@ -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,
index 557bb7faaee6712942bfe5bdd0eb5b195013c505..040b41c57140862760b9e10dcac2189bdcb44f65 100644 (file)
 
 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
index b433ad726195554e454dd030ddf6a4256b3a7c99..b0ffd93b96ae124f4717b85e2256e88c67d6187a 100644 (file)
@@ -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
index 77f1f0dcc71ddb3eb82d3bc8919268baf9ae60cd..71b56ed2327fe936312eff438a45f29e283f96b8 100644 (file)
@@ -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
index cccdc224221dd30d5fe488c9f6c81b70d524ec07..380236b91b87daaf3d339b146dde59872f3fe966 100644 (file)
 
 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}!"
 }
index ae7c13a7089dedaa4baf37bc520f3053a6f137e9..63e5c5546addad6feb04356f3d29f81d9de488e8 100644 (file)
@@ -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 (executable)
index 3328e8c..0000000
+++ /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 (executable)
index 0000000..f09dfff
--- /dev/null
@@ -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 (file)
index 0000000..7488c74
--- /dev/null
@@ -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/
index 18e301936d52b0fc8c464742c8030420a00b6b00..3d5097791196055e89ab8c85d69d068839ef7cbd 100755 (executable)
@@ -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 "##################################################"
index 5c7203ddda6d8afc746bd34e61f6c05cdb680222..9010132db7412b7f054ab2050a97aaccf66ec62c 100644 (file)
@@ -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.
index 9b04edc819612249349d6b3b5dc9184b13aa642b..ec157ac1c85801ca45816661aab9d334a9110379 100644 (file)
@@ -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
 ---------------------------------------------