Merge commit 'jrollins/master'
authorMatt Goins <mjgoins@openflows.com>
Sun, 1 Feb 2009 04:34:20 +0000 (23:34 -0500)
committerMatt Goins <mjgoins@openflows.com>
Sun, 1 Feb 2009 04:34:20 +0000 (23:34 -0500)
40 files changed:
Makefile
man/man1/pem2openpgp.1 [new file with mode: 0644]
src/common [deleted file]
src/share/common [new file with mode: 0644]
src/share/m/gen_subkey [new file with mode: 0644]
src/share/m/import_subkey [new file with mode: 0644]
src/share/m/ssh_proxycommand [new file with mode: 0644]
src/share/m/subkey_to_ssh_agent [new file with mode: 0644]
src/share/ma/add_certifier [new file with mode: 0644]
src/share/ma/diagnostics [new file with mode: 0644]
src/share/ma/list_certifiers [new file with mode: 0644]
src/share/ma/remove_certifier [new file with mode: 0644]
src/share/ma/update_users [new file with mode: 0644]
src/share/mh/add_hostname [new file with mode: 0644]
src/share/mh/add_revoker [new file with mode: 0644]
src/share/mh/diagnostics [new file with mode: 0644]
src/share/mh/extend_key [new file with mode: 0644]
src/share/mh/gen_key [new file with mode: 0644]
src/share/mh/import_key [new file with mode: 0644]
src/share/mh/publish_key [new file with mode: 0644]
src/share/mh/revoke_hostname [new file with mode: 0644]
src/share/mh/revoke_key [new file with mode: 0644]
src/subcommands/m/gen_subkey [deleted file]
src/subcommands/m/import_subkey [deleted file]
src/subcommands/m/ssh_proxycommand [deleted file]
src/subcommands/m/subkey_to_ssh_agent [deleted file]
src/subcommands/ma/add_certifier [deleted file]
src/subcommands/ma/diagnostics [deleted file]
src/subcommands/ma/list_certifiers [deleted file]
src/subcommands/ma/remove_certifier [deleted file]
src/subcommands/ma/update_users [deleted file]
src/subcommands/mh/add_hostname [deleted file]
src/subcommands/mh/add_revoker [deleted file]
src/subcommands/mh/diagnostics [deleted file]
src/subcommands/mh/extend_key [deleted file]
src/subcommands/mh/gen_key [deleted file]
src/subcommands/mh/import_key [deleted file]
src/subcommands/mh/publish_key [deleted file]
src/subcommands/mh/revoke_hostname [deleted file]
src/subcommands/mh/revoke_key [deleted file]

index 6acb3f43d46b66c32e1200c1986a0c6de85b1370..0ec2030f9e1c5eca4c8aedcb2450da230eacd086 100755 (executable)
--- a/Makefile
+++ b/Makefile
@@ -53,10 +53,10 @@ install: all installman
        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/common $(DESTDIR)$(PREFIX)/share/monkeysphere
-       install -m 0644 src/subcommands/m/* $(DESTDIR)$(PREFIX)/share/monkeysphere/m
-       install -m 0644 src/subcommands/mh/* $(DESTDIR)$(PREFIX)/share/monkeysphere/mh
-       install -m 0644 src/subcommands/ma/* $(DESTDIR)$(PREFIX)/share/monkeysphere/ma
+       install -m 0644 src/share/common $(DESTDIR)$(PREFIX)/share/monkeysphere
+       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
        install doc/* $(DESTDIR)$(PREFIX)/share/doc/monkeysphere
        install -m 0644 etc/monkeysphere.conf $(DESTDIR)$(ETCPREFIX)/etc/monkeysphere/monkeysphere.conf$(ETCSUFFIX)
        install -m 0644 etc/monkeysphere-host.conf $(DESTDIR)$(ETCPREFIX)/etc/monkeysphere/monkeysphere-host.conf$(ETCSUFFIX)
diff --git a/man/man1/pem2openpgp.1 b/man/man1/pem2openpgp.1
new file mode 100644 (file)
index 0000000..8ac230b
--- /dev/null
@@ -0,0 +1,27 @@
+.\"  -*- nroff -*-
+.Dd $Mdocdate: January 25, 2009 $
+.Dt PEM2OPENPGP 1
+.Os
+.Sh NAME
+pem2openpgp
+.Nd translate PEM encoded keys to OpenPGP keys
+.Sh SYNOPSIS
+.Nm pem2openpgp $USERID < mykey.pem 
+.Pp
+.Nm ??? gpg --export $KEYID | openpgp2ssh $KEYID
+.Pp
+.Nm ????gpg --export-secret-key $KEYID | openpgp2ssh $KEYID
+.Sh DESCRIPTION
+.Nm
+WRITE ME!!!
+.Sh AUTHOR
+.Nm
+and this man page were written by Daniel Kahn Gillmor
+<dkg@fifthhorseman.net>.
+.Sh BUGS
+.Sh SEE ALSO
+.Xr openpgp2ssh 1,
+.Xr monkeysphere 1 ,
+.Xr monkeysphere 7 ,
+.Xr ssh 1 ,
+.Xr monkeysphere-server 8
diff --git a/src/common b/src/common
deleted file mode 100644 (file)
index ef931ca..0000000
+++ /dev/null
@@ -1,1057 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Shared sh functions for the monkeysphere
-#
-# Written by
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# Copyright 2008, 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
-
-########################################################################
-### COMMON VARIABLES
-
-# managed directories
-SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"}
-export SYSCONFIGDIR
-
-# monkeysphere version
-VERSION=__VERSION__
-
-########################################################################
-### UTILITY FUNCTIONS
-
-# failure function.  exits with code 255, unless specified otherwise.
-failure() {
-    [ "$1" ] && echo "$1" >&2
-    exit ${2:-'255'}
-}
-
-# write output to stderr based on specified LOG_LEVEL the first
-# parameter is the priority of the output, and everything else is what
-# is echoed to stderr
-log() {
-    local priority
-    local level
-    local output
-    local alllevels
-    local found=
-
-    # don't include SILENT in alllevels: it's handled separately
-    # list in decreasing verbosity (all caps).
-    # separate with $IFS explicitly, since we do some fancy footwork
-    # elsewhere.
-    alllevels="DEBUG${IFS}VERBOSE${IFS}INFO${IFS}ERROR"
-
-    # translate lowers to uppers in global log level
-    LOG_LEVEL=$(echo "$LOG_LEVEL" | tr "[:lower:]" "[:upper:]")
-
-    # just go ahead and return if the log level is silent
-    if [ "$LOG_LEVEL" = 'SILENT' ] ; then
-       return
-    fi
-
-    for level in $alllevels ; do 
-       if [ "$LOG_LEVEL" = "$level" ] ; then
-           found=true
-       fi
-    done
-    if [ -z "$found" ] ; then
-       # default to INFO:
-       LOG_LEVEL=INFO
-    fi
-
-    # get priority from first parameter, translating all lower to
-    # uppers
-    priority=$(echo "$1" | tr "[:lower:]" "[:upper:]")
-    shift
-
-    # scan over available levels
-    for level in $alllevels ; do
-       # output if the log level matches, set output to true
-       # this will output for all subsequent loops as well.
-       if [ "$LOG_LEVEL" = "$level" ] ; then
-           output=true
-       fi
-       if [ "$priority" = "$level" -a "$output" = 'true' ] ; then
-           echo -n "ms: " >&2
-           echo "$@" >&2
-       fi
-    done
-}
-
-# cut out all comments(#) and blank lines from standard input
-meat() {
-    grep -v -e "^[[:space:]]*#" -e '^$' "$1"
-}
-
-# cut a specified line from standard input
-cutline() {
-    head --line="$1" "$2" | tail -1
-}
-
-# this is a wrapper for doing lock functions.
-#
-# it lets us depend on either lockfile-progs (preferred) or procmail's
-# lockfile, and should
-lock() {
-    local use_lockfileprogs=true
-    local action="$1"
-    local file="$2"
-
-    if ! ( which lockfile-create >/dev/null 2>/dev/null ) ; then
-       if ! ( which lockfile >/dev/null ); then
-           failure "Neither lockfile-create nor lockfile are in the path!"
-       fi
-       use_lockfileprogs=
-    fi
-    
-    case "$action" in
-       create)
-           if [ -n "$use_lockfileprogs" ] ; then
-               lockfile-create "$file" || failure "unable to lock '$file'"
-           else
-               lockfile -r 20 "${file}.lock" || failure "unable to lock '$file'"
-           fi
-           ;;
-       touch)  
-           if [ -n "$use_lockfileprogs" ] ; then
-               lockfile-touch --oneshot "$file"
-           else
-               : Nothing to do here
-           fi
-           ;;
-       remove)
-           if [ -n "$use_lockfileprogs" ] ; then
-               lockfile-remove "$file"
-           else
-               rm -f "${file}.lock"
-           fi
-           ;;
-       *)
-           failure "bad argument for lock subfunction '$action'"
-    esac
-}
-
-
-# for portability, between gnu date and BSD date.
-# arguments should be:  number longunits format
-
-# e.g. advance_date 20 seconds +%F
-advance_date() {
-    local gnutry
-    local number="$1"
-    local longunits="$2"
-    local format="$3"
-    local shortunits
-
-    # try things the GNU way first 
-    if date -d "$number $longunits" "$format" >/dev/null 2>&1; then
-       date -d "$number $longunits" "$format"
-    else
-       # otherwise, convert to (a limited version of) BSD date syntax:
-       case "$longunits" in
-           years)
-               shortunits=y
-               ;;
-           months)
-               shortunits=m
-               ;;
-           weeks)
-               shortunits=w
-               ;;
-           days)
-               shortunits=d
-               ;;
-           hours)
-               shortunits=H
-               ;;
-           minutes)
-               shortunits=M
-               ;;
-           seconds)
-               shortunits=S
-               ;;
-           *)
-               # this is a longshot, and will likely fail; oh well.
-               shortunits="$longunits"
-       esac
-       date "-v+${number}${shortunits}" "$format"
-    fi
-}
-
-
-# check that characters are in a string (in an AND fashion).
-# used for checking key capability
-# check_capability capability a [b...]
-check_capability() {
-    local usage
-    local capcheck
-
-    usage="$1"
-    shift 1
-
-    for capcheck ; do
-       if echo "$usage" | grep -q -v "$capcheck" ; then
-           return 1
-       fi
-    done
-    return 0
-}
-
-# hash of a file
-file_hash() {
-    md5sum "$1" 2> /dev/null
-}
-
-# convert escaped characters in pipeline from gpg output back into
-# original character
-# FIXME: undo all escape character translation in with-colons gpg
-# output
-gpg_unescape() {
-    sed 's/\\x3a/:/g'
-}
-
-# convert nasty chars into gpg-friendly form in pipeline
-# FIXME: escape everything, not just colons!
-gpg_escape() {
-    sed 's/:/\\x3a/g'
-}
-
-# prompt for GPG-formatted expiration, and emit result on stdout
-get_gpg_expiration() {
-    local keyExpire
-
-    keyExpire="$1"
-
-    if [ -z "$keyExpire" ]; then
-       cat >&2 <<EOF
-Please specify how long the key should be valid.
-         0 = key does not expire
-      <n>  = key expires in n days
-      <n>w = key expires in n weeks
-      <n>m = key expires in n months
-      <n>y = key expires in n years
-EOF
-       while [ -z "$keyExpire" ] ; do
-           read -p "Key is valid for? (0) " keyExpire
-           if ! test_gpg_expire ${keyExpire:=0} ; then
-               echo "invalid value" >&2
-               unset keyExpire
-           fi
-       done
-    elif ! test_gpg_expire "$keyExpire" ; then
-       failure "invalid key expiration value '$keyExpire'."
-    fi
-       
-    echo "$keyExpire"
-}
-
-passphrase_prompt() {
-    local prompt="$1"
-    local fifo="$2"
-    local PASS
-
-    if [ "$DISPLAY" ] && which "${SSH_ASKPASS:-ssh-askpass}" >/dev/null; then
-       "${SSH_ASKPASS:-ssh-askpass}" "$prompt" > "$fifo"
-    else
-       read -s -p "$prompt" PASS
-       # Uses the builtin echo, so should not put the passphrase into
-       # the process table.  I think. --dkg
-       echo "$PASS" > "$fifo"
-    fi
-}
-
-test_gnu_dummy_s2k_extension() {
-
-# this block contains a demonstration private key that has had the
-# primary key stripped out using the GNU S2K extension known as
-# "gnu-dummy" (see /usr/share/doc/gnupg/DETAILS.gz).  The subkey is
-# present in cleartext, however.
-
-# openpgp2ssh will be able to deal with this based on whether the
-# local copy of GnuTLS contains read_s2k support that can handle it.
-
-# read up on that here:
-
-# http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html
-
-echo "
------BEGIN PGP PRIVATE KEY BLOCK-----
-Version: GnuPG v1.4.9 (GNU/Linux)
-
-lQCVBEO3YdABBACRqqEnucag4+vyZny2M67Pai5+5suIRRvY+Ly8Ms5MvgCi3EVV
-xT05O/+0ShiRaf+QicCOFrhbU9PZzzU+seEvkeW2UCu4dQfILkmj+HBEIltGnHr3
-G0yegHj5pnqrcezERURf2e17gGFWX91cXB9Cm721FPXczuKraphKwCA9PwARAQAB
-/gNlAkdOVQG0OURlbW9uc3RyYXRpb24gS2V5IGZvciBTMksgR05VIGV4dGVuc2lv
-biAxMDAxIC0tIGdudS1kdW1teYi8BBMBAgAmBQJDt2HQAhsDBQkB4TOABgsJCAcD
-AgQVAggDBBYCAwECHgECF4AACgkQQZUwSa4UDezTOQP/TMQXUVrWzHYZGopoPZ2+
-ZS3qddiznBHsgb7MGYg1KlTiVJSroDUBCHIUJvdQKZV9zrzrFl47D07x6hGyUPHV
-aZXvuITW8t1o5MMHkCy3pmJ2KgfDvdUxrBvLfgPMICA4c6zA0mWquee43syEW9NY
-g3q61iPlQwD1J1kX1wlimLCdAdgEQ7dh0AEEANAwa63zlQbuy1Meliy8otwiOa+a
-mH6pxxUgUNggjyjO5qx+rl25mMjvGIRX4/L1QwIBXJBVi3SgvJW1COZxZqBYqj9U
-8HVT07mWKFEDf0rZLeUE2jTm16cF9fcW4DQhW+sfYm+hi2sY3HeMuwlUBK9KHfW2
-+bGeDzVZ4pqfUEudABEBAAEAA/0bemib+wxub9IyVFUp7nPobjQC83qxLSNzrGI/
-RHzgu/5CQi4tfLOnwbcQsLELfker2hYnjsLrT9PURqK4F7udrWEoZ1I1LymOtLG/
-4tNZ7Mnul3wRC2tCn7FKx8sGJwGh/3li8vZ6ALVJAyOia5TZ/buX0+QZzt6+hPKk
-7MU1WQIA4bUBjtrsqDwro94DvPj3/jBnMZbXr6WZIItLNeVDUcM8oHL807Am97K1
-ueO/f6v1sGAHG6lVPTmtekqPSTWBfwIA7CGFvEyvSALfB8NUa6jtk27NCiw0csql
-kuhCmwXGMVOiryKEfegkIahf2bAd/gnWHPrpWp7bUE20v8YoW22I4wIAhnm5Wr5Q
-Sy7EHDUxmJm5TzadFp9gq08qNzHBpXSYXXJ3JuWcL1/awUqp3tE1I6zZ0hZ38Ia6
-SdBMN88idnhDPqPoiKUEGAECAA8FAkO3YdACGyAFCQHhM4AACgkQQZUwSa4UDezm
-vQP/ZhK+2ly9oI2z7ZcNC/BJRch0/ybQ3haahII8pXXmOThpZohr/LUgoWgCZdXg
-vP6yiszNk2tIs8KphCAw7Lw/qzDC2hEORjWO4f46qk73RAgSqG/GyzI4ltWiDhqn
-vnQCFl3+QFSe4zinqykHnLwGPMXv428d/ZjkIc2ju8dRsn4=
-=CR5w
------END PGP PRIVATE KEY BLOCK-----
-" | openpgp2ssh 4129E89D17C1D591 >/dev/null 2>/dev/null
-
-}
-
-# remove all lines with specified string from specified file
-remove_line() {
-    local file
-    local string
-    local tempfile
-
-    file="$1"
-    string="$2"
-
-    if [ -z "$file" -o -z "$string" ] ; then
-       return 1
-    fi
-
-    if [ ! -e "$file" ] ; then
-       return 1
-    fi
-
-    # if the string is in the file...
-    if grep -q -F "$string" "$file" 2> /dev/null ; then
-       tempfile=$(mktemp "${file}.XXXXXXX") || \
-           failure "Unable to make temp file '${file}.XXXXXXX'"
-       
-       # remove the line with the string, and return 0
-       grep -v -F "$string" "$file" >"$tempfile"
-       cat "$tempfile" > "$file"
-       rm "$tempfile"
-       return 0
-    # otherwise return 1
-    else
-       return 1
-    fi
-}
-
-# remove all lines with MonkeySphere strings in file
-remove_monkeysphere_lines() {
-    local file
-    local tempfile
-
-    file="$1"
-
-    if [ -z "$file" ] ; then
-       return 1
-    fi
-
-    if [ ! -e "$file" ] ; then
-       return 1
-    fi
-
-    tempfile=$(mktemp "${file}.XXXXXXX") || \
-       failure "Could not make temporary file '${file}.XXXXXXX'."
-
-    egrep -v '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$' \
-       "$file" >"$tempfile"
-    cat "$tempfile" > "$file"
-    rm "$tempfile"
-}
-
-# translate ssh-style path variables %h and %u
-translate_ssh_variables() {
-    local uname
-    local home
-
-    uname="$1"
-    path="$2"
-
-    # get the user's home directory
-    userHome=$(getent passwd "$uname" | cut -d: -f6)
-
-    # translate '%u' to user name
-    path=${path/\%u/"$uname"}
-    # translate '%h' to user home directory
-    path=${path/\%h/"$userHome"}
-
-    echo "$path"
-}
-
-# test that a string to conforms to GPG's expiration format
-test_gpg_expire() {
-    echo "$1" | egrep -q "^[0-9]+[mwy]?$"
-}
-
-# check that a file is properly owned, and that all it's parent
-# directories are not group/other writable
-check_key_file_permissions() {
-    local uname
-    local path
-    local stat
-    local access
-    local gAccess
-    local oAccess
-
-    # function to check that the given permission corresponds to writability
-    is_write() {
-       [ "$1" = "w" ]
-    }
-
-    uname="$1"
-    path="$2"
-
-    # return 255 if cannot stat file
-    if ! stat=$(ls -ld "$path" 2>/dev/null) ; then
-        log error "could not stat path '$path'."
-       return 255
-    fi
-
-    owner=$(echo "$stat" | awk '{ print $3 }')
-    gAccess=$(echo "$stat" | cut -c6)
-    oAccess=$(echo "$stat" | cut -c9)
-
-    # return 1 if path has invalid owner
-    if [ "$owner" != "$uname" -a "$owner" != 'root' ] ; then
-       log error "improper ownership on path '$path'."
-       return 1
-    fi
-
-    # return 2 if path has group or other writability
-    if is_write "$gAccess" || is_write "$oAccess" ; then
-       log error "improper group or other writability on path '$path'."
-       return 2
-    fi
-
-    # return zero if all clear, or go to next path
-    if [ "$path" = '/' ] ; then
-       return 0
-    else
-       check_key_file_permissions "$uname" $(dirname "$path")
-    fi
-}
-
-### CONVERSION UTILITIES
-
-# output the ssh key for a given key ID
-gpg2ssh() {
-    local keyID
-    
-    keyID="$1"
-
-    gpg --export "$keyID" | openpgp2ssh "$keyID" 2> /dev/null
-}
-
-# output known_hosts line from ssh key
-ssh2known_hosts() {
-    local host
-    local key
-
-    host="$1"
-    key="$2"
-
-    echo -n "$host "
-    echo -n "$key" | tr -d '\n'
-    echo " MonkeySphere${DATE}"
-}
-
-# output authorized_keys line from ssh key
-ssh2authorized_keys() {
-    local userID
-    local key
-    
-    userID="$1"
-    key="$2"
-
-    echo -n "$key" | tr -d '\n'
-    echo " MonkeySphere${DATE} ${userID}"
-}
-
-# convert key from gpg to ssh known_hosts format
-gpg2known_hosts() {
-    local host
-    local keyID
-
-    host="$1"
-    keyID="$2"
-
-    # NOTE: it seems that ssh-keygen -R removes all comment fields from
-    # all lines in the known_hosts file.  why?
-    # NOTE: just in case, the COMMENT can be matched with the
-    # following regexp:
-    # '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$'
-    echo -n "$host "
-    gpg2ssh "$keyID" | tr -d '\n'
-    echo " MonkeySphere${DATE}"
-}
-
-# convert key from gpg to ssh authorized_keys format
-gpg2authorized_keys() {
-    local userID
-    local keyID
-
-    userID="$1"
-    keyID="$2"
-
-    # NOTE: just in case, the COMMENT can be matched with the
-    # following regexp:
-    # '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$'
-    gpg2ssh "$keyID" | tr -d '\n'
-    echo " MonkeySphere${DATE} ${userID}"
-}
-
-### GPG UTILITIES
-
-# retrieve all keys with given user id from keyserver
-# FIXME: need to figure out how to retrieve all matching keys
-# (not just first N (5 in this case))
-gpg_fetch_userid() {
-    local userID
-    local returnCode
-
-    if [ "$CHECK_KEYSERVER" != 'true' ] ; then
-       return 0
-    fi
-
-    userID="$1"
-
-    log verbose " checking keyserver $KEYSERVER... "
-    echo 1,2,3,4,5 | \
-       gpg --quiet --batch --with-colons \
-       --command-fd 0 --keyserver "$KEYSERVER" \
-       --search ="$userID" > /dev/null 2>&1
-    returnCode="$?"
-
-    # if the user is the monkeysphere user, then update the
-    # monkeysphere user's trustdb
-    if [ $(id -un) = "$MONKEYSPHERE_USER" ] ; then
-       gpg_authentication "--check-trustdb" > /dev/null 2>&1
-    fi
-
-    return "$returnCode"
-}
-
-########################################################################
-### PROCESSING FUNCTIONS
-
-# userid and key policy checking
-# the following checks policy on the returned keys
-# - checks that full key has appropriate valididy (u|f)
-# - checks key has specified capability (REQUIRED_*_KEY_CAPABILITY)
-# - checks that requested user ID has appropriate validity
-# (see /usr/share/doc/gnupg/DETAILS.gz)
-# output is one line for every found key, in the following format:
-#
-# flag:sshKey
-#
-# "flag" is an acceptability flag, 0 = ok, 1 = bad
-# "sshKey" is the translated gpg key
-#
-# all log output must go to stderr, as stdout is used to pass the
-# flag:sshKey to the calling function.
-#
-# expects global variable: "MODE"
-process_user_id() {
-    local userID
-    local requiredCapability
-    local requiredPubCapability
-    local gpgOut
-    local type
-    local validity
-    local keyid
-    local uidfpr
-    local usage
-    local keyOK
-    local uidOK
-    local lastKey
-    local lastKeyOK
-    local fingerprint
-
-    userID="$1"
-
-    # set the required key capability based on the mode
-    if [ "$MODE" = 'known_hosts' ] ; then
-       requiredCapability="$REQUIRED_HOST_KEY_CAPABILITY"
-    elif [ "$MODE" = 'authorized_keys' ] ; then
-       requiredCapability="$REQUIRED_USER_KEY_CAPABILITY"      
-    fi
-    requiredPubCapability=$(echo "$requiredCapability" | tr "[:lower:]" "[:upper:]")
-
-    # fetch the user ID if necessary/requested
-    gpg_fetch_userid "$userID"
-
-    # output gpg info for (exact) userid and store
-    gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \
-       --with-fingerprint --with-fingerprint \
-       ="$userID" 2>/dev/null)
-
-    # if the gpg query return code is not 0, return 1
-    if [ "$?" -ne 0 ] ; then
-        log verbose " no primary keys found."
-        return 1
-    fi
-
-    # loop over all lines in the gpg output and process.
-    echo "$gpgOut" | cut -d: -f1,2,5,10,12 | \
-    while IFS=: read -r type validity keyid uidfpr usage ; do
-       # process based on record type
-       case $type in
-           'pub') # primary keys
-               # new key, wipe the slate
-               keyOK=
-               uidOK=
-               lastKey=pub
-               lastKeyOK=
-               fingerprint=
-
-               log verbose " primary key found: $keyid"
-
-               # if overall key is not valid, skip
-               if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then
-                   log debug "  - unacceptable primary key validity ($validity)."
-                   continue
-               fi
-               # if overall key is disabled, skip
-               if check_capability "$usage" 'D' ; then
-                   log debug "  - key disabled."
-                   continue
-               fi
-               # if overall key capability is not ok, skip
-               if ! check_capability "$usage" $requiredPubCapability ; then
-                   log debug "  - unacceptable primary key capability ($usage)."
-                   continue
-               fi
-
-               # mark overall key as ok
-               keyOK=true
-
-               # mark primary key as ok if capability is ok
-               if check_capability "$usage" $requiredCapability ; then
-                   lastKeyOK=true
-               fi
-               ;;
-           'uid') # user ids
-               if [ "$lastKey" != pub ] ; then
-                   log verbose " ! got a user ID after a sub key?!  user IDs should only follow primary keys!"
-                   continue
-               fi
-               # if an acceptable user ID was already found, skip
-               if [ "$uidOK" = 'true' ] ; then
-                   continue
-               fi
-               # if the user ID does matches...
-               if [ "$(echo "$uidfpr" | gpg_unescape)" = "$userID" ] ; then
-                   # and the user ID validity is ok
-                   if [ "$validity" = 'u' -o "$validity" = 'f' ] ; then
-                       # mark user ID acceptable
-                       uidOK=true
-                   else
-                       log debug "  - unacceptable user ID validity ($validity)."
-                   fi
-               else
-                   continue
-               fi
-
-               # output a line for the primary key
-               # 0 = ok, 1 = bad
-               if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then
-                   log verbose "  * acceptable primary key."
-                   if [ -z "$sshKey" ] ; then
-                       log error "    ! primary key could not be translated (not RSA or DSA?)."
-                   else
-                       echo "0:${sshKey}"
-                   fi
-               else
-                   log debug "  - unacceptable primary key."
-                   if [ -z "$sshKey" ] ; then
-                       log debug "    ! primary key could not be translated (not RSA or DSA?)."
-                   else
-                       echo "1:${sshKey}"
-                   fi
-               fi
-               ;;
-           'sub') # sub keys
-               # unset acceptability of last key
-               lastKey=sub
-               lastKeyOK=
-               fingerprint=
-               
-               # don't bother with sub keys if the primary key is not valid
-               if [ "$keyOK" != true ] ; then
-                   continue
-               fi
-
-               # don't bother with sub keys if no user ID is acceptable:
-               if [ "$uidOK" != true ] ; then
-                   continue
-               fi
-               
-               # if sub key validity is not ok, skip
-               if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then
-                   log debug "  - unacceptable sub key validity ($validity)."
-                   continue
-               fi
-               # if sub key capability is not ok, skip
-               if ! check_capability "$usage" $requiredCapability ; then
-                   log debug "  - unacceptable sub key capability ($usage)."
-                   continue
-               fi
-
-               # mark sub key as ok
-               lastKeyOK=true
-               ;;
-           'fpr') # key fingerprint
-               fingerprint="$uidfpr"
-
-               sshKey=$(gpg2ssh "$fingerprint")
-
-               # if the last key was the pub key, skip
-               if [ "$lastKey" = pub ] ; then
-                   continue
-               fi
-
-               # output a line for the sub key
-               # 0 = ok, 1 = bad
-               if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then
-                   log verbose "  * acceptable sub key."
-                   if [ -z "$sshKey" ] ; then
-                       log error "    ! sub key could not be translated (not RSA or DSA?)."
-                   else
-                       echo "0:${sshKey}"
-                   fi
-               else
-                   log debug "  - unacceptable sub key."
-                   if [ -z "$sshKey" ] ; then
-                       log debug "    ! sub key could not be translated (not RSA or DSA?)."
-                   else
-                       echo "1:${sshKey}"
-                   fi
-               fi
-               ;;
-       esac
-    done | sort -t: -k1 -n -r
-    # NOTE: this last sort is important so that the "good" keys (key
-    # flag '0') come last.  This is so that they take precedence when
-    # being processed in the key files over "bad" keys (key flag '1')
-}
-
-# process a single host in the known_host file
-process_host_known_hosts() {
-    local host
-    local userID
-    local noKey=
-    local nKeys
-    local nKeysOK
-    local ok
-    local sshKey
-    local tmpfile
-
-    host="$1"
-    userID="ssh://${host}"
-
-    log verbose "processing: $host"
-
-    nKeys=0
-    nKeysOK=0
-
-    IFS=$'\n'
-    for line in $(process_user_id "${userID}") ; do
-       # note that key was found
-       nKeys=$((nKeys+1))
-
-       ok=$(echo "$line" | cut -d: -f1)
-       sshKey=$(echo "$line" | cut -d: -f2)
-
-        if [ -z "$sshKey" ] ; then
-            continue
-        fi
-
-       # remove any old host key line, and note if removed nothing is
-       # removed
-       remove_line "$KNOWN_HOSTS" "$sshKey" || noKey=true
-
-       # if key OK, add new host line
-       if [ "$ok" -eq '0' ] ; then
-           # note that key was found ok
-           nKeysOK=$((nKeysOK+1))
-
-           # hash if specified
-           if [ "$HASH_KNOWN_HOSTS" = 'true' ] ; then
-               # FIXME: this is really hackish cause ssh-keygen won't
-               # hash from stdin to stdout
-               tmpfile=$(mktemp ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
-               ssh2known_hosts "$host" "$sshKey" > "$tmpfile"
-               ssh-keygen -H -f "$tmpfile" 2> /dev/null
-               cat "$tmpfile" >> "$KNOWN_HOSTS"
-               rm -f "$tmpfile" "${tmpfile}.old"
-           else
-               ssh2known_hosts "$host" "$sshKey" >> "$KNOWN_HOSTS"
-           fi
-
-           # log if this is a new key to the known_hosts file
-           if [ "$noKey" ] ; then
-               log info "* new key for $host added to known_hosts file."
-           fi
-       fi
-    done
-
-    # if at least one key was found...
-    if [ "$nKeys" -gt 0 ] ; then
-       # if ok keys were found, return 0
-       if [ "$nKeysOK" -gt 0 ] ; then
-           return 0
-       # else return 2
-       else
-           return 2
-       fi
-    # if no keys were found, return 1
-    else
-       return 1
-    fi
-}
-
-# update the known_hosts file for a set of hosts listed on command
-# line
-update_known_hosts() {
-    local nHosts
-    local nHostsOK
-    local nHostsBAD
-    local fileCheck
-    local host
-
-    # the number of hosts specified on command line
-    nHosts="$#"
-
-    nHostsOK=0
-    nHostsBAD=0
-
-    # create a lockfile on known_hosts:
-    lock create "$KNOWN_HOSTS"
-    # FIXME: we're discarding any pre-existing EXIT trap; is this bad?
-    trap "lock remove $KNOWN_HOSTS" EXIT
-
-    # note pre update file checksum
-    fileCheck="$(file_hash "$KNOWN_HOSTS")"
-
-    for host ; do
-       # process the host
-       process_host_known_hosts "$host"
-       # note the result
-       case "$?" in
-           0)
-               nHostsOK=$((nHostsOK+1))
-               ;;
-           2)
-               nHostsBAD=$((nHostsBAD+1))
-               ;;
-       esac
-
-       # touch the lockfile, for good measure.
-       lock touch "$KNOWN_HOSTS"
-    done
-
-    # remove the lockfile and the trap
-    lock remove "$KNOWN_HOSTS"
-    trap - EXIT
-
-    # note if the known_hosts file was updated
-    if [ "$(file_hash "$KNOWN_HOSTS")" != "$fileCheck" ] ; then
-       log debug "known_hosts file updated."
-    fi
-
-    # if an acceptable host was found, return 0
-    if [ "$nHostsOK" -gt 0 ] ; then
-       return 0
-    # else if no ok hosts were found...
-    else
-       # if no bad host were found then no hosts were found at all,
-       # and return 1
-       if [ "$nHostsBAD" -eq 0 ] ; then
-           return 1
-       # else if at least one bad host was found, return 2
-       else
-           return 2
-       fi
-    fi
-}
-
-# process hosts from a known_hosts file
-process_known_hosts() {
-    local hosts
-
-    log debug "processing known_hosts file..."
-
-    hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ')
-
-    if [ -z "$hosts" ] ; then
-       log debug "no hosts to process."
-       return
-    fi
-
-    # take all the hosts from the known_hosts file (first
-    # field), grep out all the hashed hosts (lines starting
-    # with '|')...
-    update_known_hosts $hosts
-}
-
-# process uids for the authorized_keys file
-process_uid_authorized_keys() {
-    local userID
-    local nKeys
-    local nKeysOK
-    local ok
-    local sshKey
-
-    userID="$1"
-
-    log verbose "processing: $userID"
-
-    nKeys=0
-    nKeysOK=0
-
-    IFS=$'\n'
-    for line in $(process_user_id "$userID") ; do
-       # note that key was found
-       nKeys=$((nKeys+1))
-
-       ok=$(echo "$line" | cut -d: -f1)
-       sshKey=$(echo "$line" | cut -d: -f2)
-
-        if [ -z "$sshKey" ] ; then
-            continue
-        fi
-
-       # remove the old host key line
-       remove_line "$AUTHORIZED_KEYS" "$sshKey"
-
-       # if key OK, add new host line
-       if [ "$ok" -eq '0' ] ; then
-           # note that key was found ok
-           nKeysOK=$((nKeysOK+1))
-
-           ssh2authorized_keys "$userID" "$sshKey" >> "$AUTHORIZED_KEYS"
-       fi
-    done
-
-    # if at least one key was found...
-    if [ "$nKeys" -gt 0 ] ; then
-       # if ok keys were found, return 0
-       if [ "$nKeysOK" -gt 0 ] ; then
-           return 0
-       # else return 2
-       else
-           return 2
-       fi
-    # if no keys were found, return 1
-    else
-       return 1
-    fi
-}
-
-# update the authorized_keys files from a list of user IDs on command
-# line
-update_authorized_keys() {
-    local userID
-    local nIDs
-    local nIDsOK
-    local nIDsBAD
-    local fileCheck
-
-    # the number of ids specified on command line
-    nIDs="$#"
-
-    nIDsOK=0
-    nIDsBAD=0
-
-    # create a lockfile on authorized_keys
-    lock create "$AUTHORIZED_KEYS"
-    # FIXME: we're discarding any pre-existing EXIT trap; is this bad?
-    trap "lock remove $AUTHORIZED_KEYS" EXIT
-
-    # note pre update file checksum
-    fileCheck="$(file_hash "$AUTHORIZED_KEYS")"
-
-    # remove any monkeysphere lines from authorized_keys file
-    remove_monkeysphere_lines "$AUTHORIZED_KEYS"
-
-    for userID ; do
-       # process the user ID, change return code if key not found for
-       # user ID
-       process_uid_authorized_keys "$userID"
-
-       # note the result
-       case "$?" in
-           0)
-               nIDsOK=$((nIDsOK+1))
-               ;;
-           2)
-               nIDsBAD=$((nIDsBAD+1))
-               ;;
-       esac
-
-       # touch the lockfile, for good measure.
-       lock touch "$AUTHORIZED_KEYS"
-    done
-
-    # remove the lockfile and the trap
-    lock remove "$AUTHORIZED_KEYS"
-    trap - EXIT
-
-    # note if the authorized_keys file was updated
-    if [ "$(file_hash "$AUTHORIZED_KEYS")" != "$fileCheck" ] ; then
-       log debug "authorized_keys file updated."
-    fi
-
-    # if an acceptable id was found, return 0
-    if [ "$nIDsOK" -gt 0 ] ; then
-       return 0
-    # else if no ok ids were found...
-    else
-       # if no bad ids were found then no ids were found at all, and
-       # return 1
-       if [ "$nIDsBAD" -eq 0 ] ; then
-           return 1
-       # else if at least one bad id was found, return 2
-       else
-           return 2
-       fi
-    fi
-}
-
-# process an authorized_user_ids file for authorized_keys
-process_authorized_user_ids() {
-    local line
-    local nline
-    local userIDs
-
-    authorizedUserIDs="$1"
-
-    log debug "processing authorized_user_ids file..."
-
-    if ! meat "$authorizedUserIDs" > /dev/null ; then
-       log debug " no user IDs to process."
-       return
-    fi
-
-    nline=0
-
-    # extract user IDs from authorized_user_ids file
-    IFS=$'\n'
-    for line in $(meat "$authorizedUserIDs") ; do
-       userIDs["$nline"]="$line"
-       nline=$((nline+1))
-    done
-
-    update_authorized_keys "${userIDs[@]}"
-}
diff --git a/src/share/common b/src/share/common
new file mode 100644 (file)
index 0000000..ef931ca
--- /dev/null
@@ -0,0 +1,1057 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Shared sh functions for the monkeysphere
+#
+# Written by
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# Copyright 2008, 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
+
+########################################################################
+### COMMON VARIABLES
+
+# managed directories
+SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"}
+export SYSCONFIGDIR
+
+# monkeysphere version
+VERSION=__VERSION__
+
+########################################################################
+### UTILITY FUNCTIONS
+
+# failure function.  exits with code 255, unless specified otherwise.
+failure() {
+    [ "$1" ] && echo "$1" >&2
+    exit ${2:-'255'}
+}
+
+# write output to stderr based on specified LOG_LEVEL the first
+# parameter is the priority of the output, and everything else is what
+# is echoed to stderr
+log() {
+    local priority
+    local level
+    local output
+    local alllevels
+    local found=
+
+    # don't include SILENT in alllevels: it's handled separately
+    # list in decreasing verbosity (all caps).
+    # separate with $IFS explicitly, since we do some fancy footwork
+    # elsewhere.
+    alllevels="DEBUG${IFS}VERBOSE${IFS}INFO${IFS}ERROR"
+
+    # translate lowers to uppers in global log level
+    LOG_LEVEL=$(echo "$LOG_LEVEL" | tr "[:lower:]" "[:upper:]")
+
+    # just go ahead and return if the log level is silent
+    if [ "$LOG_LEVEL" = 'SILENT' ] ; then
+       return
+    fi
+
+    for level in $alllevels ; do 
+       if [ "$LOG_LEVEL" = "$level" ] ; then
+           found=true
+       fi
+    done
+    if [ -z "$found" ] ; then
+       # default to INFO:
+       LOG_LEVEL=INFO
+    fi
+
+    # get priority from first parameter, translating all lower to
+    # uppers
+    priority=$(echo "$1" | tr "[:lower:]" "[:upper:]")
+    shift
+
+    # scan over available levels
+    for level in $alllevels ; do
+       # output if the log level matches, set output to true
+       # this will output for all subsequent loops as well.
+       if [ "$LOG_LEVEL" = "$level" ] ; then
+           output=true
+       fi
+       if [ "$priority" = "$level" -a "$output" = 'true' ] ; then
+           echo -n "ms: " >&2
+           echo "$@" >&2
+       fi
+    done
+}
+
+# cut out all comments(#) and blank lines from standard input
+meat() {
+    grep -v -e "^[[:space:]]*#" -e '^$' "$1"
+}
+
+# cut a specified line from standard input
+cutline() {
+    head --line="$1" "$2" | tail -1
+}
+
+# this is a wrapper for doing lock functions.
+#
+# it lets us depend on either lockfile-progs (preferred) or procmail's
+# lockfile, and should
+lock() {
+    local use_lockfileprogs=true
+    local action="$1"
+    local file="$2"
+
+    if ! ( which lockfile-create >/dev/null 2>/dev/null ) ; then
+       if ! ( which lockfile >/dev/null ); then
+           failure "Neither lockfile-create nor lockfile are in the path!"
+       fi
+       use_lockfileprogs=
+    fi
+    
+    case "$action" in
+       create)
+           if [ -n "$use_lockfileprogs" ] ; then
+               lockfile-create "$file" || failure "unable to lock '$file'"
+           else
+               lockfile -r 20 "${file}.lock" || failure "unable to lock '$file'"
+           fi
+           ;;
+       touch)  
+           if [ -n "$use_lockfileprogs" ] ; then
+               lockfile-touch --oneshot "$file"
+           else
+               : Nothing to do here
+           fi
+           ;;
+       remove)
+           if [ -n "$use_lockfileprogs" ] ; then
+               lockfile-remove "$file"
+           else
+               rm -f "${file}.lock"
+           fi
+           ;;
+       *)
+           failure "bad argument for lock subfunction '$action'"
+    esac
+}
+
+
+# for portability, between gnu date and BSD date.
+# arguments should be:  number longunits format
+
+# e.g. advance_date 20 seconds +%F
+advance_date() {
+    local gnutry
+    local number="$1"
+    local longunits="$2"
+    local format="$3"
+    local shortunits
+
+    # try things the GNU way first 
+    if date -d "$number $longunits" "$format" >/dev/null 2>&1; then
+       date -d "$number $longunits" "$format"
+    else
+       # otherwise, convert to (a limited version of) BSD date syntax:
+       case "$longunits" in
+           years)
+               shortunits=y
+               ;;
+           months)
+               shortunits=m
+               ;;
+           weeks)
+               shortunits=w
+               ;;
+           days)
+               shortunits=d
+               ;;
+           hours)
+               shortunits=H
+               ;;
+           minutes)
+               shortunits=M
+               ;;
+           seconds)
+               shortunits=S
+               ;;
+           *)
+               # this is a longshot, and will likely fail; oh well.
+               shortunits="$longunits"
+       esac
+       date "-v+${number}${shortunits}" "$format"
+    fi
+}
+
+
+# check that characters are in a string (in an AND fashion).
+# used for checking key capability
+# check_capability capability a [b...]
+check_capability() {
+    local usage
+    local capcheck
+
+    usage="$1"
+    shift 1
+
+    for capcheck ; do
+       if echo "$usage" | grep -q -v "$capcheck" ; then
+           return 1
+       fi
+    done
+    return 0
+}
+
+# hash of a file
+file_hash() {
+    md5sum "$1" 2> /dev/null
+}
+
+# convert escaped characters in pipeline from gpg output back into
+# original character
+# FIXME: undo all escape character translation in with-colons gpg
+# output
+gpg_unescape() {
+    sed 's/\\x3a/:/g'
+}
+
+# convert nasty chars into gpg-friendly form in pipeline
+# FIXME: escape everything, not just colons!
+gpg_escape() {
+    sed 's/:/\\x3a/g'
+}
+
+# prompt for GPG-formatted expiration, and emit result on stdout
+get_gpg_expiration() {
+    local keyExpire
+
+    keyExpire="$1"
+
+    if [ -z "$keyExpire" ]; then
+       cat >&2 <<EOF
+Please specify how long the key should be valid.
+         0 = key does not expire
+      <n>  = key expires in n days
+      <n>w = key expires in n weeks
+      <n>m = key expires in n months
+      <n>y = key expires in n years
+EOF
+       while [ -z "$keyExpire" ] ; do
+           read -p "Key is valid for? (0) " keyExpire
+           if ! test_gpg_expire ${keyExpire:=0} ; then
+               echo "invalid value" >&2
+               unset keyExpire
+           fi
+       done
+    elif ! test_gpg_expire "$keyExpire" ; then
+       failure "invalid key expiration value '$keyExpire'."
+    fi
+       
+    echo "$keyExpire"
+}
+
+passphrase_prompt() {
+    local prompt="$1"
+    local fifo="$2"
+    local PASS
+
+    if [ "$DISPLAY" ] && which "${SSH_ASKPASS:-ssh-askpass}" >/dev/null; then
+       "${SSH_ASKPASS:-ssh-askpass}" "$prompt" > "$fifo"
+    else
+       read -s -p "$prompt" PASS
+       # Uses the builtin echo, so should not put the passphrase into
+       # the process table.  I think. --dkg
+       echo "$PASS" > "$fifo"
+    fi
+}
+
+test_gnu_dummy_s2k_extension() {
+
+# this block contains a demonstration private key that has had the
+# primary key stripped out using the GNU S2K extension known as
+# "gnu-dummy" (see /usr/share/doc/gnupg/DETAILS.gz).  The subkey is
+# present in cleartext, however.
+
+# openpgp2ssh will be able to deal with this based on whether the
+# local copy of GnuTLS contains read_s2k support that can handle it.
+
+# read up on that here:
+
+# http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html
+
+echo "
+-----BEGIN PGP PRIVATE KEY BLOCK-----
+Version: GnuPG v1.4.9 (GNU/Linux)
+
+lQCVBEO3YdABBACRqqEnucag4+vyZny2M67Pai5+5suIRRvY+Ly8Ms5MvgCi3EVV
+xT05O/+0ShiRaf+QicCOFrhbU9PZzzU+seEvkeW2UCu4dQfILkmj+HBEIltGnHr3
+G0yegHj5pnqrcezERURf2e17gGFWX91cXB9Cm721FPXczuKraphKwCA9PwARAQAB
+/gNlAkdOVQG0OURlbW9uc3RyYXRpb24gS2V5IGZvciBTMksgR05VIGV4dGVuc2lv
+biAxMDAxIC0tIGdudS1kdW1teYi8BBMBAgAmBQJDt2HQAhsDBQkB4TOABgsJCAcD
+AgQVAggDBBYCAwECHgECF4AACgkQQZUwSa4UDezTOQP/TMQXUVrWzHYZGopoPZ2+
+ZS3qddiznBHsgb7MGYg1KlTiVJSroDUBCHIUJvdQKZV9zrzrFl47D07x6hGyUPHV
+aZXvuITW8t1o5MMHkCy3pmJ2KgfDvdUxrBvLfgPMICA4c6zA0mWquee43syEW9NY
+g3q61iPlQwD1J1kX1wlimLCdAdgEQ7dh0AEEANAwa63zlQbuy1Meliy8otwiOa+a
+mH6pxxUgUNggjyjO5qx+rl25mMjvGIRX4/L1QwIBXJBVi3SgvJW1COZxZqBYqj9U
+8HVT07mWKFEDf0rZLeUE2jTm16cF9fcW4DQhW+sfYm+hi2sY3HeMuwlUBK9KHfW2
++bGeDzVZ4pqfUEudABEBAAEAA/0bemib+wxub9IyVFUp7nPobjQC83qxLSNzrGI/
+RHzgu/5CQi4tfLOnwbcQsLELfker2hYnjsLrT9PURqK4F7udrWEoZ1I1LymOtLG/
+4tNZ7Mnul3wRC2tCn7FKx8sGJwGh/3li8vZ6ALVJAyOia5TZ/buX0+QZzt6+hPKk
+7MU1WQIA4bUBjtrsqDwro94DvPj3/jBnMZbXr6WZIItLNeVDUcM8oHL807Am97K1
+ueO/f6v1sGAHG6lVPTmtekqPSTWBfwIA7CGFvEyvSALfB8NUa6jtk27NCiw0csql
+kuhCmwXGMVOiryKEfegkIahf2bAd/gnWHPrpWp7bUE20v8YoW22I4wIAhnm5Wr5Q
+Sy7EHDUxmJm5TzadFp9gq08qNzHBpXSYXXJ3JuWcL1/awUqp3tE1I6zZ0hZ38Ia6
+SdBMN88idnhDPqPoiKUEGAECAA8FAkO3YdACGyAFCQHhM4AACgkQQZUwSa4UDezm
+vQP/ZhK+2ly9oI2z7ZcNC/BJRch0/ybQ3haahII8pXXmOThpZohr/LUgoWgCZdXg
+vP6yiszNk2tIs8KphCAw7Lw/qzDC2hEORjWO4f46qk73RAgSqG/GyzI4ltWiDhqn
+vnQCFl3+QFSe4zinqykHnLwGPMXv428d/ZjkIc2ju8dRsn4=
+=CR5w
+-----END PGP PRIVATE KEY BLOCK-----
+" | openpgp2ssh 4129E89D17C1D591 >/dev/null 2>/dev/null
+
+}
+
+# remove all lines with specified string from specified file
+remove_line() {
+    local file
+    local string
+    local tempfile
+
+    file="$1"
+    string="$2"
+
+    if [ -z "$file" -o -z "$string" ] ; then
+       return 1
+    fi
+
+    if [ ! -e "$file" ] ; then
+       return 1
+    fi
+
+    # if the string is in the file...
+    if grep -q -F "$string" "$file" 2> /dev/null ; then
+       tempfile=$(mktemp "${file}.XXXXXXX") || \
+           failure "Unable to make temp file '${file}.XXXXXXX'"
+       
+       # remove the line with the string, and return 0
+       grep -v -F "$string" "$file" >"$tempfile"
+       cat "$tempfile" > "$file"
+       rm "$tempfile"
+       return 0
+    # otherwise return 1
+    else
+       return 1
+    fi
+}
+
+# remove all lines with MonkeySphere strings in file
+remove_monkeysphere_lines() {
+    local file
+    local tempfile
+
+    file="$1"
+
+    if [ -z "$file" ] ; then
+       return 1
+    fi
+
+    if [ ! -e "$file" ] ; then
+       return 1
+    fi
+
+    tempfile=$(mktemp "${file}.XXXXXXX") || \
+       failure "Could not make temporary file '${file}.XXXXXXX'."
+
+    egrep -v '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$' \
+       "$file" >"$tempfile"
+    cat "$tempfile" > "$file"
+    rm "$tempfile"
+}
+
+# translate ssh-style path variables %h and %u
+translate_ssh_variables() {
+    local uname
+    local home
+
+    uname="$1"
+    path="$2"
+
+    # get the user's home directory
+    userHome=$(getent passwd "$uname" | cut -d: -f6)
+
+    # translate '%u' to user name
+    path=${path/\%u/"$uname"}
+    # translate '%h' to user home directory
+    path=${path/\%h/"$userHome"}
+
+    echo "$path"
+}
+
+# test that a string to conforms to GPG's expiration format
+test_gpg_expire() {
+    echo "$1" | egrep -q "^[0-9]+[mwy]?$"
+}
+
+# check that a file is properly owned, and that all it's parent
+# directories are not group/other writable
+check_key_file_permissions() {
+    local uname
+    local path
+    local stat
+    local access
+    local gAccess
+    local oAccess
+
+    # function to check that the given permission corresponds to writability
+    is_write() {
+       [ "$1" = "w" ]
+    }
+
+    uname="$1"
+    path="$2"
+
+    # return 255 if cannot stat file
+    if ! stat=$(ls -ld "$path" 2>/dev/null) ; then
+        log error "could not stat path '$path'."
+       return 255
+    fi
+
+    owner=$(echo "$stat" | awk '{ print $3 }')
+    gAccess=$(echo "$stat" | cut -c6)
+    oAccess=$(echo "$stat" | cut -c9)
+
+    # return 1 if path has invalid owner
+    if [ "$owner" != "$uname" -a "$owner" != 'root' ] ; then
+       log error "improper ownership on path '$path'."
+       return 1
+    fi
+
+    # return 2 if path has group or other writability
+    if is_write "$gAccess" || is_write "$oAccess" ; then
+       log error "improper group or other writability on path '$path'."
+       return 2
+    fi
+
+    # return zero if all clear, or go to next path
+    if [ "$path" = '/' ] ; then
+       return 0
+    else
+       check_key_file_permissions "$uname" $(dirname "$path")
+    fi
+}
+
+### CONVERSION UTILITIES
+
+# output the ssh key for a given key ID
+gpg2ssh() {
+    local keyID
+    
+    keyID="$1"
+
+    gpg --export "$keyID" | openpgp2ssh "$keyID" 2> /dev/null
+}
+
+# output known_hosts line from ssh key
+ssh2known_hosts() {
+    local host
+    local key
+
+    host="$1"
+    key="$2"
+
+    echo -n "$host "
+    echo -n "$key" | tr -d '\n'
+    echo " MonkeySphere${DATE}"
+}
+
+# output authorized_keys line from ssh key
+ssh2authorized_keys() {
+    local userID
+    local key
+    
+    userID="$1"
+    key="$2"
+
+    echo -n "$key" | tr -d '\n'
+    echo " MonkeySphere${DATE} ${userID}"
+}
+
+# convert key from gpg to ssh known_hosts format
+gpg2known_hosts() {
+    local host
+    local keyID
+
+    host="$1"
+    keyID="$2"
+
+    # NOTE: it seems that ssh-keygen -R removes all comment fields from
+    # all lines in the known_hosts file.  why?
+    # NOTE: just in case, the COMMENT can be matched with the
+    # following regexp:
+    # '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$'
+    echo -n "$host "
+    gpg2ssh "$keyID" | tr -d '\n'
+    echo " MonkeySphere${DATE}"
+}
+
+# convert key from gpg to ssh authorized_keys format
+gpg2authorized_keys() {
+    local userID
+    local keyID
+
+    userID="$1"
+    keyID="$2"
+
+    # NOTE: just in case, the COMMENT can be matched with the
+    # following regexp:
+    # '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$'
+    gpg2ssh "$keyID" | tr -d '\n'
+    echo " MonkeySphere${DATE} ${userID}"
+}
+
+### GPG UTILITIES
+
+# retrieve all keys with given user id from keyserver
+# FIXME: need to figure out how to retrieve all matching keys
+# (not just first N (5 in this case))
+gpg_fetch_userid() {
+    local userID
+    local returnCode
+
+    if [ "$CHECK_KEYSERVER" != 'true' ] ; then
+       return 0
+    fi
+
+    userID="$1"
+
+    log verbose " checking keyserver $KEYSERVER... "
+    echo 1,2,3,4,5 | \
+       gpg --quiet --batch --with-colons \
+       --command-fd 0 --keyserver "$KEYSERVER" \
+       --search ="$userID" > /dev/null 2>&1
+    returnCode="$?"
+
+    # if the user is the monkeysphere user, then update the
+    # monkeysphere user's trustdb
+    if [ $(id -un) = "$MONKEYSPHERE_USER" ] ; then
+       gpg_authentication "--check-trustdb" > /dev/null 2>&1
+    fi
+
+    return "$returnCode"
+}
+
+########################################################################
+### PROCESSING FUNCTIONS
+
+# userid and key policy checking
+# the following checks policy on the returned keys
+# - checks that full key has appropriate valididy (u|f)
+# - checks key has specified capability (REQUIRED_*_KEY_CAPABILITY)
+# - checks that requested user ID has appropriate validity
+# (see /usr/share/doc/gnupg/DETAILS.gz)
+# output is one line for every found key, in the following format:
+#
+# flag:sshKey
+#
+# "flag" is an acceptability flag, 0 = ok, 1 = bad
+# "sshKey" is the translated gpg key
+#
+# all log output must go to stderr, as stdout is used to pass the
+# flag:sshKey to the calling function.
+#
+# expects global variable: "MODE"
+process_user_id() {
+    local userID
+    local requiredCapability
+    local requiredPubCapability
+    local gpgOut
+    local type
+    local validity
+    local keyid
+    local uidfpr
+    local usage
+    local keyOK
+    local uidOK
+    local lastKey
+    local lastKeyOK
+    local fingerprint
+
+    userID="$1"
+
+    # set the required key capability based on the mode
+    if [ "$MODE" = 'known_hosts' ] ; then
+       requiredCapability="$REQUIRED_HOST_KEY_CAPABILITY"
+    elif [ "$MODE" = 'authorized_keys' ] ; then
+       requiredCapability="$REQUIRED_USER_KEY_CAPABILITY"      
+    fi
+    requiredPubCapability=$(echo "$requiredCapability" | tr "[:lower:]" "[:upper:]")
+
+    # fetch the user ID if necessary/requested
+    gpg_fetch_userid "$userID"
+
+    # output gpg info for (exact) userid and store
+    gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \
+       --with-fingerprint --with-fingerprint \
+       ="$userID" 2>/dev/null)
+
+    # if the gpg query return code is not 0, return 1
+    if [ "$?" -ne 0 ] ; then
+        log verbose " no primary keys found."
+        return 1
+    fi
+
+    # loop over all lines in the gpg output and process.
+    echo "$gpgOut" | cut -d: -f1,2,5,10,12 | \
+    while IFS=: read -r type validity keyid uidfpr usage ; do
+       # process based on record type
+       case $type in
+           'pub') # primary keys
+               # new key, wipe the slate
+               keyOK=
+               uidOK=
+               lastKey=pub
+               lastKeyOK=
+               fingerprint=
+
+               log verbose " primary key found: $keyid"
+
+               # if overall key is not valid, skip
+               if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then
+                   log debug "  - unacceptable primary key validity ($validity)."
+                   continue
+               fi
+               # if overall key is disabled, skip
+               if check_capability "$usage" 'D' ; then
+                   log debug "  - key disabled."
+                   continue
+               fi
+               # if overall key capability is not ok, skip
+               if ! check_capability "$usage" $requiredPubCapability ; then
+                   log debug "  - unacceptable primary key capability ($usage)."
+                   continue
+               fi
+
+               # mark overall key as ok
+               keyOK=true
+
+               # mark primary key as ok if capability is ok
+               if check_capability "$usage" $requiredCapability ; then
+                   lastKeyOK=true
+               fi
+               ;;
+           'uid') # user ids
+               if [ "$lastKey" != pub ] ; then
+                   log verbose " ! got a user ID after a sub key?!  user IDs should only follow primary keys!"
+                   continue
+               fi
+               # if an acceptable user ID was already found, skip
+               if [ "$uidOK" = 'true' ] ; then
+                   continue
+               fi
+               # if the user ID does matches...
+               if [ "$(echo "$uidfpr" | gpg_unescape)" = "$userID" ] ; then
+                   # and the user ID validity is ok
+                   if [ "$validity" = 'u' -o "$validity" = 'f' ] ; then
+                       # mark user ID acceptable
+                       uidOK=true
+                   else
+                       log debug "  - unacceptable user ID validity ($validity)."
+                   fi
+               else
+                   continue
+               fi
+
+               # output a line for the primary key
+               # 0 = ok, 1 = bad
+               if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then
+                   log verbose "  * acceptable primary key."
+                   if [ -z "$sshKey" ] ; then
+                       log error "    ! primary key could not be translated (not RSA or DSA?)."
+                   else
+                       echo "0:${sshKey}"
+                   fi
+               else
+                   log debug "  - unacceptable primary key."
+                   if [ -z "$sshKey" ] ; then
+                       log debug "    ! primary key could not be translated (not RSA or DSA?)."
+                   else
+                       echo "1:${sshKey}"
+                   fi
+               fi
+               ;;
+           'sub') # sub keys
+               # unset acceptability of last key
+               lastKey=sub
+               lastKeyOK=
+               fingerprint=
+               
+               # don't bother with sub keys if the primary key is not valid
+               if [ "$keyOK" != true ] ; then
+                   continue
+               fi
+
+               # don't bother with sub keys if no user ID is acceptable:
+               if [ "$uidOK" != true ] ; then
+                   continue
+               fi
+               
+               # if sub key validity is not ok, skip
+               if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then
+                   log debug "  - unacceptable sub key validity ($validity)."
+                   continue
+               fi
+               # if sub key capability is not ok, skip
+               if ! check_capability "$usage" $requiredCapability ; then
+                   log debug "  - unacceptable sub key capability ($usage)."
+                   continue
+               fi
+
+               # mark sub key as ok
+               lastKeyOK=true
+               ;;
+           'fpr') # key fingerprint
+               fingerprint="$uidfpr"
+
+               sshKey=$(gpg2ssh "$fingerprint")
+
+               # if the last key was the pub key, skip
+               if [ "$lastKey" = pub ] ; then
+                   continue
+               fi
+
+               # output a line for the sub key
+               # 0 = ok, 1 = bad
+               if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then
+                   log verbose "  * acceptable sub key."
+                   if [ -z "$sshKey" ] ; then
+                       log error "    ! sub key could not be translated (not RSA or DSA?)."
+                   else
+                       echo "0:${sshKey}"
+                   fi
+               else
+                   log debug "  - unacceptable sub key."
+                   if [ -z "$sshKey" ] ; then
+                       log debug "    ! sub key could not be translated (not RSA or DSA?)."
+                   else
+                       echo "1:${sshKey}"
+                   fi
+               fi
+               ;;
+       esac
+    done | sort -t: -k1 -n -r
+    # NOTE: this last sort is important so that the "good" keys (key
+    # flag '0') come last.  This is so that they take precedence when
+    # being processed in the key files over "bad" keys (key flag '1')
+}
+
+# process a single host in the known_host file
+process_host_known_hosts() {
+    local host
+    local userID
+    local noKey=
+    local nKeys
+    local nKeysOK
+    local ok
+    local sshKey
+    local tmpfile
+
+    host="$1"
+    userID="ssh://${host}"
+
+    log verbose "processing: $host"
+
+    nKeys=0
+    nKeysOK=0
+
+    IFS=$'\n'
+    for line in $(process_user_id "${userID}") ; do
+       # note that key was found
+       nKeys=$((nKeys+1))
+
+       ok=$(echo "$line" | cut -d: -f1)
+       sshKey=$(echo "$line" | cut -d: -f2)
+
+        if [ -z "$sshKey" ] ; then
+            continue
+        fi
+
+       # remove any old host key line, and note if removed nothing is
+       # removed
+       remove_line "$KNOWN_HOSTS" "$sshKey" || noKey=true
+
+       # if key OK, add new host line
+       if [ "$ok" -eq '0' ] ; then
+           # note that key was found ok
+           nKeysOK=$((nKeysOK+1))
+
+           # hash if specified
+           if [ "$HASH_KNOWN_HOSTS" = 'true' ] ; then
+               # FIXME: this is really hackish cause ssh-keygen won't
+               # hash from stdin to stdout
+               tmpfile=$(mktemp ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+               ssh2known_hosts "$host" "$sshKey" > "$tmpfile"
+               ssh-keygen -H -f "$tmpfile" 2> /dev/null
+               cat "$tmpfile" >> "$KNOWN_HOSTS"
+               rm -f "$tmpfile" "${tmpfile}.old"
+           else
+               ssh2known_hosts "$host" "$sshKey" >> "$KNOWN_HOSTS"
+           fi
+
+           # log if this is a new key to the known_hosts file
+           if [ "$noKey" ] ; then
+               log info "* new key for $host added to known_hosts file."
+           fi
+       fi
+    done
+
+    # if at least one key was found...
+    if [ "$nKeys" -gt 0 ] ; then
+       # if ok keys were found, return 0
+       if [ "$nKeysOK" -gt 0 ] ; then
+           return 0
+       # else return 2
+       else
+           return 2
+       fi
+    # if no keys were found, return 1
+    else
+       return 1
+    fi
+}
+
+# update the known_hosts file for a set of hosts listed on command
+# line
+update_known_hosts() {
+    local nHosts
+    local nHostsOK
+    local nHostsBAD
+    local fileCheck
+    local host
+
+    # the number of hosts specified on command line
+    nHosts="$#"
+
+    nHostsOK=0
+    nHostsBAD=0
+
+    # create a lockfile on known_hosts:
+    lock create "$KNOWN_HOSTS"
+    # FIXME: we're discarding any pre-existing EXIT trap; is this bad?
+    trap "lock remove $KNOWN_HOSTS" EXIT
+
+    # note pre update file checksum
+    fileCheck="$(file_hash "$KNOWN_HOSTS")"
+
+    for host ; do
+       # process the host
+       process_host_known_hosts "$host"
+       # note the result
+       case "$?" in
+           0)
+               nHostsOK=$((nHostsOK+1))
+               ;;
+           2)
+               nHostsBAD=$((nHostsBAD+1))
+               ;;
+       esac
+
+       # touch the lockfile, for good measure.
+       lock touch "$KNOWN_HOSTS"
+    done
+
+    # remove the lockfile and the trap
+    lock remove "$KNOWN_HOSTS"
+    trap - EXIT
+
+    # note if the known_hosts file was updated
+    if [ "$(file_hash "$KNOWN_HOSTS")" != "$fileCheck" ] ; then
+       log debug "known_hosts file updated."
+    fi
+
+    # if an acceptable host was found, return 0
+    if [ "$nHostsOK" -gt 0 ] ; then
+       return 0
+    # else if no ok hosts were found...
+    else
+       # if no bad host were found then no hosts were found at all,
+       # and return 1
+       if [ "$nHostsBAD" -eq 0 ] ; then
+           return 1
+       # else if at least one bad host was found, return 2
+       else
+           return 2
+       fi
+    fi
+}
+
+# process hosts from a known_hosts file
+process_known_hosts() {
+    local hosts
+
+    log debug "processing known_hosts file..."
+
+    hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ')
+
+    if [ -z "$hosts" ] ; then
+       log debug "no hosts to process."
+       return
+    fi
+
+    # take all the hosts from the known_hosts file (first
+    # field), grep out all the hashed hosts (lines starting
+    # with '|')...
+    update_known_hosts $hosts
+}
+
+# process uids for the authorized_keys file
+process_uid_authorized_keys() {
+    local userID
+    local nKeys
+    local nKeysOK
+    local ok
+    local sshKey
+
+    userID="$1"
+
+    log verbose "processing: $userID"
+
+    nKeys=0
+    nKeysOK=0
+
+    IFS=$'\n'
+    for line in $(process_user_id "$userID") ; do
+       # note that key was found
+       nKeys=$((nKeys+1))
+
+       ok=$(echo "$line" | cut -d: -f1)
+       sshKey=$(echo "$line" | cut -d: -f2)
+
+        if [ -z "$sshKey" ] ; then
+            continue
+        fi
+
+       # remove the old host key line
+       remove_line "$AUTHORIZED_KEYS" "$sshKey"
+
+       # if key OK, add new host line
+       if [ "$ok" -eq '0' ] ; then
+           # note that key was found ok
+           nKeysOK=$((nKeysOK+1))
+
+           ssh2authorized_keys "$userID" "$sshKey" >> "$AUTHORIZED_KEYS"
+       fi
+    done
+
+    # if at least one key was found...
+    if [ "$nKeys" -gt 0 ] ; then
+       # if ok keys were found, return 0
+       if [ "$nKeysOK" -gt 0 ] ; then
+           return 0
+       # else return 2
+       else
+           return 2
+       fi
+    # if no keys were found, return 1
+    else
+       return 1
+    fi
+}
+
+# update the authorized_keys files from a list of user IDs on command
+# line
+update_authorized_keys() {
+    local userID
+    local nIDs
+    local nIDsOK
+    local nIDsBAD
+    local fileCheck
+
+    # the number of ids specified on command line
+    nIDs="$#"
+
+    nIDsOK=0
+    nIDsBAD=0
+
+    # create a lockfile on authorized_keys
+    lock create "$AUTHORIZED_KEYS"
+    # FIXME: we're discarding any pre-existing EXIT trap; is this bad?
+    trap "lock remove $AUTHORIZED_KEYS" EXIT
+
+    # note pre update file checksum
+    fileCheck="$(file_hash "$AUTHORIZED_KEYS")"
+
+    # remove any monkeysphere lines from authorized_keys file
+    remove_monkeysphere_lines "$AUTHORIZED_KEYS"
+
+    for userID ; do
+       # process the user ID, change return code if key not found for
+       # user ID
+       process_uid_authorized_keys "$userID"
+
+       # note the result
+       case "$?" in
+           0)
+               nIDsOK=$((nIDsOK+1))
+               ;;
+           2)
+               nIDsBAD=$((nIDsBAD+1))
+               ;;
+       esac
+
+       # touch the lockfile, for good measure.
+       lock touch "$AUTHORIZED_KEYS"
+    done
+
+    # remove the lockfile and the trap
+    lock remove "$AUTHORIZED_KEYS"
+    trap - EXIT
+
+    # note if the authorized_keys file was updated
+    if [ "$(file_hash "$AUTHORIZED_KEYS")" != "$fileCheck" ] ; then
+       log debug "authorized_keys file updated."
+    fi
+
+    # if an acceptable id was found, return 0
+    if [ "$nIDsOK" -gt 0 ] ; then
+       return 0
+    # else if no ok ids were found...
+    else
+       # if no bad ids were found then no ids were found at all, and
+       # return 1
+       if [ "$nIDsBAD" -eq 0 ] ; then
+           return 1
+       # else if at least one bad id was found, return 2
+       else
+           return 2
+       fi
+    fi
+}
+
+# process an authorized_user_ids file for authorized_keys
+process_authorized_user_ids() {
+    local line
+    local nline
+    local userIDs
+
+    authorizedUserIDs="$1"
+
+    log debug "processing authorized_user_ids file..."
+
+    if ! meat "$authorizedUserIDs" > /dev/null ; then
+       log debug " no user IDs to process."
+       return
+    fi
+
+    nline=0
+
+    # extract user IDs from authorized_user_ids file
+    IFS=$'\n'
+    for line in $(meat "$authorizedUserIDs") ; do
+       userIDs["$nline"]="$line"
+       nline=$((nline+1))
+    done
+
+    update_authorized_keys "${userIDs[@]}"
+}
diff --git a/src/share/m/gen_subkey b/src/share/m/gen_subkey
new file mode 100644 (file)
index 0000000..cbefaa3
--- /dev/null
@@ -0,0 +1,127 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere gen-subkey subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# generate a subkey with the 'a' usage flags set
+
+gen_subkey(){
+    local keyLength
+    local keyExpire
+    local keyID
+    local gpgOut
+    local userID
+
+    # get options
+    while true ; do
+       case "$1" in
+           -l|--length)
+               keyLength="$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
+
+    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 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")
+
+    # generate the list of commands that will be passed to edit-key
+    editCommands=$(cat <<EOF
+addkey
+7
+S
+E
+A
+Q
+$keyLength
+$keyExpire
+save
+EOF
+)
+
+    log verbose "generating subkey..."
+    fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+    (umask 077 && mkfifo "$fifoDir/pass")
+    echo "$editCommands" | gpg --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"
+
+    rm -rf "$fifoDir"
+    wait
+    log verbose "done."
+}
diff --git a/src/share/m/import_subkey b/src/share/m/import_subkey
new file mode 100644 (file)
index 0000000..aa89958
--- /dev/null
@@ -0,0 +1,54 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere import-subkey subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# import an existing ssh key as a gpg subkey
+
+import_subkey() {
+    local keyFile="~/.ssh/id_rsa"
+    local keyExpire
+    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)
+    (umask 077 && mkfifo "$fifoDir/pass")
+    ssh2openpgp | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+
+    passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
+
+    rm -rf "$fifoDir"
+    wait
+    log verbose "done."
+}
diff --git a/src/share/m/ssh_proxycommand b/src/share/m/ssh_proxycommand
new file mode 100644 (file)
index 0000000..7239c7a
--- /dev/null
@@ -0,0 +1,237 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# monkeysphere-ssh-proxycommand: MonkeySphere ssh ProxyCommand hook
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# This is meant to be run as an ssh ProxyCommand to initiate a
+# monkeysphere known_hosts update before an ssh connection to host is
+# 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() {
+    local sshKeyOffered
+    local userID
+    local type
+    local validity
+    local keyid
+    local uidfpr
+    local usage
+    local sshKeyGPG
+    local tmpkey
+    local sshFingerprint
+    local gpgSigOut
+
+    userID="ssh://${HOSTP}"
+
+    log "-------------------- Monkeysphere warning -------------------"
+    log "Monkeysphere found OpenPGP keys for this hostname, but none had full validity."
+
+    # retrieve the actual ssh key
+    sshKeyOffered=$(ssh-keyscan -t rsa -p "$PORT" "$HOST" 2>/dev/null | awk '{ print $2, $3 }')
+    # FIXME: should we do any checks for failed keyscans, eg. host not
+    # found?
+
+    # get the gpg info for userid
+    gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \
+       --with-fingerprint --with-fingerprint \
+       ="$userID" 2>/dev/null)
+
+    # find all 'pub' and 'sub' lines in the gpg output, which each
+    # represent a retrieved key for the user ID
+    echo "$gpgOut" | cut -d: -f1,2,5,10,12 | \
+    while IFS=: read -r type validity keyid uidfpr usage ; do
+       case $type in
+           'pub'|'sub')
+               # get the ssh key of the gpg key
+               sshKeyGPG=$(gpg2ssh "$keyid")
+
+               # if one of keys found matches the one offered by the
+               # host, then output info
+               if [ "$sshKeyGPG" = "$sshKeyOffered" ] ; then
+                   log "An OpenPGP key matching the ssh key offered by the host was found:"
+                   log
+
+                   # 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") | \
+                       awk '{ print $2 }')
+
+                   # get the sigs for the matching key
+                   gpgSigOut=$(gpg --check-sigs \
+                       --list-options show-uid-validity \
+                       "$keyid")
+
+                   # output the sigs, but only those on the user ID
+                   # we are looking for
+                   echo "$gpgSigOut" | awk '
+{
+if (match($0,"^pub")) {        print; }
+if (match($0,"^uid")) { ok=0; }
+if (match($0,"^uid.*'$userID'$")) { ok=1; print; }
+if (ok) { if (match($0,"^sig")) { print; } }
+}
+' >&2
+                   log
+
+                   # output the other user IDs for reference
+                   if (echo "$gpgSigOut" | grep "^uid" | grep -v -q "$userID") ; then
+                       log "Other user IDs on this key:"
+                       echo "$gpgSigOut" | grep "^uid" | grep -v "$userID" >&2
+                       log
+                   fi
+
+                   # output ssh fingerprint
+                   log "RSA key fingerprint is ${sshFingerprint}."
+
+                   # this whole process is in a "while read"
+                   # subshell.  the only way to get information out
+                   # of the subshell is to change the return code.
+                   # therefore we return 1 here to indicate that a
+                   # matching gpg key was found for the ssh key
+                   # offered by the host
+                   return 1
+               fi
+               ;;
+       esac
+    done
+
+    # if no key match was made (and the "while read" subshell returned
+    # 1) output how many keys were found
+    if (($? != 1)) ; then
+       log "None of the found keys matched the key offered by the host."
+       log "Run the following command for more info about the found keys:"
+       log "gpg --check-sigs --list-options show-uid-validity =${userID}"
+       # FIXME: should we do anything extra here if the retrieved
+       # host key is actually in the known_hosts file and the ssh
+       # connection will succeed?  Should the user be warned?
+       # prompted?
+    fi
+
+    log "-------------------- ssh continues below --------------------"
+}
+
+########################################################################
+
+# export the monkeysphere log level
+export MONKEYSPHERE_LOG_LEVEL
+
+if [ "$1" = '--no-connect' ] ; then
+    NO_CONNECT='true'
+    shift 1
+fi
+
+HOST="$1"
+PORT="$2"
+
+if [ -z "$HOST" ] ; then
+    log "Host not specified."
+    usage
+    exit 255
+fi
+if [ -z "$PORT" ] ; then
+    PORT=22
+fi
+
+# set the host URI
+if [ "$PORT" != '22' ] ; then
+    HOSTP="${HOST}:${PORT}"
+else
+    HOSTP="${HOST}"
+fi
+URI="ssh://${HOSTP}"
+
+# specify keyserver checking.  the behavior of this proxy command is
+# 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.
+
+# if the host is in the gpg keyring...
+if gpg --list-key ="${URI}" 2>&1 >/dev/null ; then
+    # do not check the keyserver
+    CHECK_KEYSERVER="false"
+
+# if the host is NOT in the keyring...
+else
+    # if the host key is found in the known_hosts file...
+    # FIXME: this only works for default known_hosts location
+    hostKey=$(ssh-keygen -F "$HOST" 2>/dev/null)
+
+    if [ "$hostKey" ] ; then
+       # do not check the keyserver
+       # 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"
+
+    # if the host key is not found in the known_hosts file...
+    else
+       # check the 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
+
+# update the known_hosts file for the host
+monkeysphere update-known_hosts "$HOSTP"
+
+# output on depending on the return of the update-known_hosts
+# subcommand, which is (ultimately) the return code of the
+# update_known_hosts function in common
+case $? in
+    0)
+       # acceptable host key found so continue to ssh
+       true
+       ;;
+    1)
+       # no hosts at all found so also continue (drop through to
+       # regular ssh host verification)
+       true
+       ;;
+    2)
+       # at least one *bad* host key (and no good host keys) was
+       # found, so output some usefull information
+       output_no_valid_key
+       ;;
+    *)
+       # anything else drop through
+       true
+       ;;
+esac
+
+# FIXME: what about the case where monkeysphere successfully finds a
+# valid key for the host and adds it to the known_hosts file, but a
+# different non-monkeysphere key for the host already exists in the
+# known_hosts, and it is this non-ms key that is offered by the host?
+# monkeysphere will succeed, and the ssh connection will succeed, and
+# the user will be left with the impression that they are dealing with
+# a OpenPGP/PKI host key when in fact they are not.  should we use
+# ssh-keyscan to compare the keys first?
+
+# exec a netcat passthrough to host for the ssh connection
+if [ -z "$NO_CONNECT" ] ; then
+    if (which nc 2>/dev/null >/dev/null); then
+       exec nc "$HOST" "$PORT"
+    elif (which socat 2>/dev/null >/dev/null); then
+       exec socat STDIO "TCP:$HOST:$PORT"
+    else
+       echo "Neither netcat nor socat found -- could not complete monkeysphere-ssh-proxycommand connection to $HOST:$PORT" >&2
+       exit 255
+    fi
+fi
+
+}
diff --git a/src/share/m/subkey_to_ssh_agent b/src/share/m/subkey_to_ssh_agent
new file mode 100644 (file)
index 0000000..012c95f
--- /dev/null
@@ -0,0 +1,113 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere subkey-to-ssh-agent subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# try to add all authentication subkeys to the agent
+
+subkey_to_ssh_agent() {
+    local sshaddresponse
+    local secretkeys
+    local authsubkeys
+    local workingdir
+    local keysuccess
+    local subkey
+    local publine
+    local kname
+
+    if ! test_gnu_dummy_s2k_extension ; then
+       failure "Your version of GnuTLS does not seem capable of using with gpg's exported subkeys.
+You may want to consider patching or upgrading to GnuTLS 2.6 or later.
+
+For more details, see:
+ http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html"
+    fi
+
+    # if there's no agent running, don't bother:
+    if [ -z "$SSH_AUTH_SOCK" ] || ! which ssh-add >/dev/null ; then
+       failure "No ssh-agent available."
+    fi
+
+    # and if it looks like it's running, but we can't actually talk to
+    # it, bail out:
+    ssh-add -l >/dev/null
+    sshaddresponse="$?"
+    if [ "$sshaddresponse" = "2" ]; then
+       failure "Could not connect to ssh-agent"
+    fi
+    
+    # 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 | \
+       grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }')
+
+    if [ -z "$secretkeys" ]; then
+       failure "You have no secret keys in your keyring!
+You might want to run 'gpg --gen-key'."
+    fi
+    
+    authsubkeys=$(gpg --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)
+
+    if [ -z "$authsubkeys" ]; then
+       failure "no authentication-capable subkeys available.
+You might want to 'monkeysphere gen-subkey'"
+    fi
+
+    workingdir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+    umask 077
+    mkfifo "$workingdir/passphrase"
+    keysuccess=1
+
+    # FIXME: we're currently allowing any other options to get passed
+    # through to ssh-add.  should we limit it to known ones?  For
+    # example: -d or -c and/or -t <lifetime> 
+
+    for subkey in $authsubkeys; do 
+       # choose a label by which this key will be known in the agent:
+       # we are labelling the key by User ID instead of by
+       # 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 /)
+
+       #kname="[monkeysphere] $primaryuid"
+       kname="$primaryuid"
+
+       if [ "$1" = '-d' ]; then
+           # we're removing the subkey:
+           gpg --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" \
+               --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 )&
+
+           passphrase_prompt "Enter passphrase for key $kname: " "$workingdir/passphrase"
+           wait %2
+       fi
+       keysuccess="$?"
+
+       rm -f "$workingdir/$kname"
+    done
+
+    rm -rf "$workingdir"
+
+    # FIXME: sort out the return values: we're just returning the
+    # success or failure of the final authentication subkey in this
+    # case.  What if earlier ones failed?
+    exit "$keysuccess"
+}
diff --git a/src/share/ma/add_certifier b/src/share/ma/add_certifier
new file mode 100644 (file)
index 0000000..0c3c647
--- /dev/null
@@ -0,0 +1,146 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere authentication add-certifier subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# retrieve key from web of trust, import it into the host keyring, and
+# ltsign the key in the host keyring so that it may certify other keys
+
+add_certifier() {
+
+local domain
+local trust
+local depth
+local keyID
+local fingerprint
+local ltsignCommand
+local trustval
+
+# set default values for trust depth and domain
+domain=
+trust=full
+depth=1
+
+# get options
+while true ; do
+    case "$1" in
+       -n|--domain)
+           domain="$2"
+           shift 2
+           ;;
+       -t|--trust)
+           trust="$2"
+           shift 2
+           ;;
+       -d|--depth)
+           depth="$2"
+           shift 2
+           ;;
+       *)
+           if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
+               failure "Unknown option '$1'.
+Type '$PGRM help' for usage."
+           fi
+           break
+           ;;
+    esac
+done
+
+keyID="$1"
+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
+    echo "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 "Expected there to be a single gpg key in the file."
+    fi
+else
+    # get the key from the key server
+    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 a key ID
+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
+
+echo
+echo "key found:"
+gpg_sphere "--fingerprint 0x${fingerprint}!"
+
+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
+
+# export the key to the host keyring
+gpg_sphere "--export 0x${fingerprint}!" | gpg_core --import
+
+if [ "$trust" = marginal ]; then
+    trustval=1
+elif [ "$trust" = full ]; then
+    trustval=2
+else
+    failure "Trust value requested ('$trust') was unclear (only 'marginal' or 'full' are supported)."
+fi
+
+# ltsign command
+# NOTE: *all* user IDs will be ltsigned
+ltsignCommand=$(cat <<EOF
+ltsign
+y
+$trustval
+$depth
+$domain
+y
+save
+EOF
+    )
+
+# ltsign the key
+if echo "$ltsignCommand" | \
+    gpg_core --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
+
+    # update the trustdb for the authentication keyring
+    gpg_sphere "--check-trustdb"
+
+    echo
+    echo "Identity certifier added."
+else
+    failure "Problem adding identify certifier."
+fi
+
+}
diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics
new file mode 100644 (file)
index 0000000..73e93a0
--- /dev/null
@@ -0,0 +1,185 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere authentication diagnostics subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# check on the status and validity of the key and public certificates
+
+diagnostics() {
+
+local seckey
+local keysfound
+local curdate
+local warnwindow
+local warndate
+local create
+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
+seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
+keysfound=$(echo "$seckey" | grep -c ^sec:)
+curdate=$(date +%s)
+# warn when anything is 2 months away from expiration
+warnwindow='2 months'
+warndate=$(advance_date $warnwindow +%s)
+
+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))
+fi
+
+if ! [ -d "$SYSDATADIR" ] ; then
+    echo "! no $SYSDATADIR directory found.  Please create it."
+    problemsfound=$(($problemsfound+1))
+fi
+
+echo "Checking host GPG key..."
+if (( "$keysfound" < 1 )); then
+    echo "! No host key found."
+    echo " - Recommendation: run 'monkeysphere-server gen-key'"
+    problemsfound=$(($problemsfound+1))
+elif (( "$keysfound" > 1 )); then
+    echo "! More than one host key found?"
+    # FIXME: recommend a way to resolve this
+    problemsfound=$(($problemsfound+1))
+else
+    create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
+    expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
+    fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
+    # check for key expiration:
+    if [ "$expire" ]; then
+       if (( "$expire"  < "$curdate" )); then
+           echo "! Host key is expired."
+           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
+           problemsfound=$(($problemsfound+1))
+       elif (( "$expire" < "$warndate" )); then
+           echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
+           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
+           problemsfound=$(($problemsfound+1))
+       fi
+    fi
+
+    # and weirdnesses:
+    if [ "$create" ] && (( "$create" > "$curdate" )); then
+       echo "! Host key was created in the future(?!). Is your clock correct?"
+       echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
+       problemsfound=$(($problemsfound+1))
+    fi
+    
+    # check for UserID expiration:
+    echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
+    while IFS=: read create expire uid ; do
+       # FIXME: should we be doing any checking on the form
+       # of the User ID?  Should we be unmangling it somehow?
+
+       if [ "$create" ] && (( "$create" > "$curdate" )); then
+           echo "! User ID '$uid' was created in the future(?!).  Is your clock correct?"
+           echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
+           problemsfound=$(($problemsfound+1))
+       fi
+       if [ "$expire" ] ; then
+           if (( "$expire" < "$curdate" )); then
+               echo "! User ID '$uid' is expired."
+               # FIXME: recommend a way to resolve this
+               problemsfound=$(($problemsfound+1))
+           elif (( "$expire" < "$warndate" )); then
+               echo "! User ID '$uid' expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)         
+               # FIXME: recommend a way to resolve this
+               problemsfound=$(($problemsfound+1))
+           fi
+       fi
+    done
+           
+# FIXME: verify that the host key is properly published to the
+#   keyservers (do this with the non-privileged user)
+
+# FIXME: check that there are valid, non-expired certifying signatures
+#   attached to the host key after fetching from the public keyserver
+#   (do this with the non-privileged user as well)
+
+# 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
+
+       # 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,
+#    directories housing them, etc (what should those values be?  can
+#    we make them as minimal as possible?)
+
+# FIXME: look to see that the ownertrust rules are set properly on the
+#    authentication keyring
+
+# FIXME: make sure that at least one identity certifier exists
+
+# FIXME: look at the timestamps on the monkeysphere-generated
+# authorized_keys files -- warn if they seem out-of-date.
+
+# FIXME: check for a cronjob that updates monkeysphere-generated
+# authorized_keys?
+
+echo
+echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
+# Ensure that User ID authentication is enabled:
+if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$" "$sshd_config"; then
+    echo "! $sshd_config does not point to monkeysphere authorized keys."
+    echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${SYSDATADIR}/authorized_keys/%u'"
+    problemsfound=$(($problemsfound+1))
+fi
+if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -v "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$") ; then
+    echo "! $sshd_config refers to non-monkeysphere authorized_keys files:"
+    echo "$badauthorizedkeys"
+    echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
+    problemsfound=$(($problemsfound+1))
+fi
+
+if [ "$problemsfound" -gt 0 ]; then
+    echo "When the above $problemsfound issue"$(if [ "$problemsfound" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
+    echo "  monkeysphere-server diagnostics"
+else
+    echo "Everything seems to be in order!"
+fi
+
+}
diff --git a/src/share/ma/list_certifiers b/src/share/ma/list_certifiers
new file mode 100644 (file)
index 0000000..e37485e
--- /dev/null
@@ -0,0 +1,30 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere authentication list-certifiers subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@fifthhorseman.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# list the host certifiers
+
+list_certifiers() {
+
+local keys
+local key
+
+# find trusted keys in authentication keychain
+keys=$(gpg_sphere "--no-options --list-options show-uid-validity --keyring ${GNUPGHOME_AUTHENTICATION}/pubring.gpg --list-keys --with-colons --fingerprint" | \
+    grep ^pub: | cut -d: -f2,5 | egrep '^(u|f):' | cut -d: -f2)
+
+# output keys
+for key in $keys ; do
+    gpg_sphere "--no-options --list-options show-uid-validity --keyring ${GNUPGHOME_AUTHENTICATION}/pubring.gpg --list-key --fingerprint $key"
+done
+
+}
diff --git a/src/share/ma/remove_certifier b/src/share/ma/remove_certifier
new file mode 100644 (file)
index 0000000..560281d
--- /dev/null
@@ -0,0 +1,49 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere authentication remove-certifier subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# delete a certifiers key from the host keyring
+
+remove_certifier() {
+
+local keyID
+local fingerprint
+
+keyID="$1"
+if [ -z "$keyID" ] ; then
+    failure "You must specify the key ID of a key to remove."
+fi
+
+if gpg_sphere "--no-options --list-options show-uid-validity --keyring ${GNUPGHOME_AUTHENTICATION}/pubring.gpg --list-key 0x${keyID}!" ; then
+    read -p "Really remove above listed identity certifier? (y/N) " OK; OK=${OK:-N}
+    if [ "${OK/y/Y}" != 'Y' ] ; then
+       failure "Identity certifier not removed."
+    fi
+else
+    failure
+fi
+
+# delete the requested key
+if gpg_sphere "--delete-key --batch --yes 0x${keyID}!" ; then
+    # delete key from host keyring as well
+    gpg_core --delete-key --batch --yes "0x${keyID}!"
+
+    # update the trustdb for the authentication keyring
+    gpg_sphere "--check-trustdb"
+
+    echo
+    echo "Identity certifier removed."
+else
+    failure "Problem removing identity certifier."
+fi
+
+}
diff --git a/src/share/ma/update_users b/src/share/ma/update_users
new file mode 100644 (file)
index 0000000..73685f6
--- /dev/null
@@ -0,0 +1,157 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere authentication update-users subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+update_users() {
+
+local unames
+local uname
+local authorizedKeysDir
+local authorizedUserIDs
+
+if [ "$1" ] ; then
+    # get users from command line
+    unames="$@"
+else        
+    # or just look at all users if none specified
+    unames=$(getent passwd | cut -d: -f1)
+fi
+
+RETURN=0
+
+# set mode
+MODE="authorized_keys"
+
+# set gnupg home
+GNUPGHOME="$GNUPGHOME_SPHERE"
+
+# the authorized_keys directory
+authorizedKeysDir="${SYSDATADIR}/authentication/authorized_keys"
+
+# check to see if the gpg trust database has been initialized
+if [ ! -s "${GNUPGHOME}/trustdb.gpg" ] ; then
+    failure "GNUPG trust database uninitialized.  Please see MONKEYSPHERE-SERVER(8)."
+fi
+
+# make sure the authorized_keys directory exists
+mkdir -p "${authorizedKeysDir}"
+
+# loop over users
+for uname in $unames ; do
+    # check all specified users exist
+    if ! id "$uname" >/dev/null ; then
+       log error "----- unknown user '$uname' -----"
+       continue
+    fi
+
+    log verbose "----- user: $uname -----"
+
+    # make temporary directory
+    TMPLOC=$(mktemp -d ${MATMPDIR}/tmp.XXXXXXXXXX) || failure "Could not create temporary directory!"
+
+    # trap to delete temporary directory on exit
+    trap "rm -rf $TMPLOC" EXIT
+
+    # create temporary authorized_user_ids file
+    TMP_AUTHORIZED_USER_IDS="${TMPLOC}/authorized_user_ids"
+    touch "$TMP_AUTHORIZED_USER_IDS"
+
+     # create temporary authorized_keys file
+    AUTHORIZED_KEYS="${TMPLOC}/authorized_keys"
+    touch "$AUTHORIZED_KEYS"
+
+    # set restrictive permissions on the temporary files
+    # FIXME: is there a better way to do this?
+    chmod 0700 "$TMPLOC"
+    chmod 0600 "$AUTHORIZED_KEYS"
+    chmod 0600 "$TMP_AUTHORIZED_USER_IDS"
+    chown -R "$MONKEYSPHERE_USER" "$TMPLOC"
+
+    # process authorized_user_ids file
+    log debug "checking for authorized_user_ids..."
+    # translating ssh-style path variables
+    authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
+    if [ -s "$authorizedUserIDs" ] ; then
+       # check permissions on the authorized_user_ids file path
+       if check_key_file_permissions "$uname" "$authorizedUserIDs" ; then
+            # copy user authorized_user_ids file to temporary
+            # location
+           cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS"
+
+           # export needed variables
+           export AUTHORIZED_KEYS
+           export TMP_AUTHORIZED_USER_IDS
+
+           # process authorized_user_ids file, as monkeysphere user
+           su_monkeysphere_user \
+               ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS"
+           RETURN="$?"
+       else
+           log debug "not processing authorized_user_ids."
+       fi
+    else
+       log debug "empty or absent authorized_user_ids file."
+    fi
+
+    # add user-controlled authorized_keys file if specified translate
+    # ssh-style path variables
+    rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
+    if [ "$rawAuthorizedKeys" != 'none' ] ; then
+       log debug "checking for raw authorized_keys..."
+       if [ -s "$rawAuthorizedKeys" ] ; then
+           # check permissions on the authorized_keys file path
+           if check_key_file_permissions "$uname" "$rawAuthorizedKeys" ; then
+               log verbose "adding raw authorized_keys file... "
+               cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
+           else
+               log debug "not adding raw authorized_keys file."                
+           fi
+       else
+           log debug "empty or absent authorized_keys file."
+       fi
+    fi
+
+    # move the new authorized_keys file into place
+    if [ -s "$AUTHORIZED_KEYS" ] ; then
+       # openssh appears to check the contents of the authorized_keys
+       # file as the user in question, so the file must be readable
+       # by that user at least.
+
+       # but in general, we don't want the user tampering with this
+       # file directly, so we'll adopt this approach: Own the file by
+       # the monkeysphere-server invoker (usually root, but should be
+       # the same uid that sshd is launched as); change the group of
+       # the file so that members of the user's group can read it.
+
+       # FIXME: is there a better way to do this?
+       chown $(whoami) "$AUTHORIZED_KEYS" && \
+           chgrp $(id -g "$uname") "$AUTHORIZED_KEYS" && \
+           chmod g+r "$AUTHORIZED_KEYS" && \
+           mv -f "$AUTHORIZED_KEYS" "${authorizedKeysDir}/${uname}" || \
+           { 
+           log error "Failed to install authorized_keys for '$uname'!"
+           rm -f "${authorizedKeysDir}/${uname}"
+           # indicate that there has been a failure:
+           RETURN=1
+       }
+    else
+       rm -f "${authorizedKeysDir}/${uname}"
+    fi
+
+    # unset the trap
+    trap - EXIT
+
+    # destroy temporary directory
+    rm -rf "$TMPLOC"
+done
+
+}
diff --git a/src/share/mh/add_hostname b/src/share/mh/add_hostname
new file mode 100644 (file)
index 0000000..10d5f58
--- /dev/null
@@ -0,0 +1,73 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host add-hostname subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# add hostname user ID to server key
+
+add_hostname() {
+
+local userID
+local fingerprint
+local tmpuidMatch
+local line
+local adduidCommand
+
+if [ -z "$1" ] ; then
+    failure "You must specify a hostname to add."
+fi
+
+userID="ssh://${1}"
+
+fingerprint=$(fingerprint_server_key)
+
+# match to only ultimately trusted user IDs
+tmpuidMatch="u:$(echo $userID | gpg_escape)"
+
+# find the index of the requsted user ID
+# NOTE: this is based on circumstantial evidence that the order of
+# this output is the appropriate index
+if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}!" \
+    | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
+    failure "Host userID '$userID' already exists."
+fi
+
+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
+    failure "User ID not added."
+fi
+
+# edit-key script command to add user ID
+adduidCommand=$(cat <<EOF
+adduid
+$userID
+
+
+save
+EOF
+)
+
+# execute edit-key script
+if echo "$adduidCommand" | \
+    gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
+
+    show_key
+
+    echo
+    echo "NOTE: User ID added to key, but key not published."
+    echo "Run '$PGRM publish-key' to publish the new user ID."
+else
+    failure "Problem adding user ID."
+fi
+
+}
diff --git a/src/share/mh/add_revoker b/src/share/mh/add_revoker
new file mode 100644 (file)
index 0000000..f9d0bb6
--- /dev/null
@@ -0,0 +1,21 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host add-revoker subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008, and are all released under the GPL, version 3
+# or later.
+
+# add a revoker to the host key
+
+add_revoker() {
+
+# FIXME: implement!
+failure "not implemented yet!"
+
+}
diff --git a/src/share/mh/diagnostics b/src/share/mh/diagnostics
new file mode 100644 (file)
index 0000000..7e76da6
--- /dev/null
@@ -0,0 +1,185 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host diagnostics subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# check on the status and validity of the key and public certificates
+
+diagnostics() {
+
+local seckey
+local keysfound
+local curdate
+local warnwindow
+local warndate
+local create
+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
+seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
+keysfound=$(echo "$seckey" | grep -c ^sec:)
+curdate=$(date +%s)
+# warn when anything is 2 months away from expiration
+warnwindow='2 months'
+warndate=$(advance_date $warnwindow +%s)
+
+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))
+fi
+
+if ! [ -d "$SYSDATADIR" ] ; then
+    echo "! no $SYSDATADIR directory found.  Please create it."
+    problemsfound=$(($problemsfound+1))
+fi
+
+echo "Checking host GPG key..."
+if (( "$keysfound" < 1 )); then
+    echo "! No host key found."
+    echo " - Recommendation: run 'monkeysphere-server gen-key'"
+    problemsfound=$(($problemsfound+1))
+elif (( "$keysfound" > 1 )); then
+    echo "! More than one host key found?"
+    # FIXME: recommend a way to resolve this
+    problemsfound=$(($problemsfound+1))
+else
+    create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
+    expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
+    fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
+    # check for key expiration:
+    if [ "$expire" ]; then
+       if (( "$expire"  < "$curdate" )); then
+           echo "! Host key is expired."
+           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
+           problemsfound=$(($problemsfound+1))
+       elif (( "$expire" < "$warndate" )); then
+           echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
+           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
+           problemsfound=$(($problemsfound+1))
+       fi
+    fi
+
+    # and weirdnesses:
+    if [ "$create" ] && (( "$create" > "$curdate" )); then
+       echo "! Host key was created in the future(?!). Is your clock correct?"
+       echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
+       problemsfound=$(($problemsfound+1))
+    fi
+    
+    # check for UserID expiration:
+    echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
+    while IFS=: read create expire uid ; do
+       # FIXME: should we be doing any checking on the form
+       # of the User ID?  Should we be unmangling it somehow?
+
+       if [ "$create" ] && (( "$create" > "$curdate" )); then
+           echo "! User ID '$uid' was created in the future(?!).  Is your clock correct?"
+           echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
+           problemsfound=$(($problemsfound+1))
+       fi
+       if [ "$expire" ] ; then
+           if (( "$expire" < "$curdate" )); then
+               echo "! User ID '$uid' is expired."
+               # FIXME: recommend a way to resolve this
+               problemsfound=$(($problemsfound+1))
+           elif (( "$expire" < "$warndate" )); then
+               echo "! User ID '$uid' expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)         
+               # FIXME: recommend a way to resolve this
+               problemsfound=$(($problemsfound+1))
+           fi
+       fi
+    done
+           
+# FIXME: verify that the host key is properly published to the
+#   keyservers (do this with the non-privileged user)
+
+# FIXME: check that there are valid, non-expired certifying signatures
+#   attached to the host key after fetching from the public keyserver
+#   (do this with the non-privileged user as well)
+
+# 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
+
+       # 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,
+#    directories housing them, etc (what should those values be?  can
+#    we make them as minimal as possible?)
+
+# FIXME: look to see that the ownertrust rules are set properly on the
+#    authentication keyring
+
+# FIXME: make sure that at least one identity certifier exists
+
+# FIXME: look at the timestamps on the monkeysphere-generated
+# authorized_keys files -- warn if they seem out-of-date.
+
+# FIXME: check for a cronjob that updates monkeysphere-generated
+# authorized_keys?
+
+echo
+echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
+# Ensure that User ID authentication is enabled:
+if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$" "$sshd_config"; then
+    echo "! $sshd_config does not point to monkeysphere authorized keys."
+    echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${SYSDATADIR}/authorized_keys/%u'"
+    problemsfound=$(($problemsfound+1))
+fi
+if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -v "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$") ; then
+    echo "! $sshd_config refers to non-monkeysphere authorized_keys files:"
+    echo "$badauthorizedkeys"
+    echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
+    problemsfound=$(($problemsfound+1))
+fi
+
+if [ "$problemsfound" -gt 0 ]; then
+    echo "When the above $problemsfound issue"$(if [ "$problemsfound" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
+    echo "  monkeysphere-server diagnostics"
+else
+    echo "Everything seems to be in order!"
+fi
+
+}
diff --git a/src/share/mh/extend_key b/src/share/mh/extend_key
new file mode 100644 (file)
index 0000000..ccbaf0e
--- /dev/null
@@ -0,0 +1,34 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host extend-key subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# extend the lifetime of a host key:
+
+extend_key() {
+
+local fpr=$(fingerprint_server_key)
+local extendTo="$1"
+
+# get the new expiration date
+extendTo=$(get_gpg_expiration "$extendTo")
+
+gpg_host --quiet --command-fd 0 --edit-key "$fpr" <<EOF 
+expire
+$extendTo
+save
+EOF
+
+echo
+echo "NOTE: Host key expiration date adjusted, but not yet published."
+echo "Run '$PGRM publish-key' to publish the new expiration date."
+
+}
diff --git a/src/share/mh/gen_key b/src/share/mh/gen_key
new file mode 100644 (file)
index 0000000..aad213a
--- /dev/null
@@ -0,0 +1,107 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host gen-key subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+gen_key() {
+
+local keyType="RSA"
+local keyLength="2048"
+local keyUsage="auth"
+local keyExpire
+local hostName=$(hostname -f)
+local userID
+local keyParameters
+local fingerprint
+
+# check for presense of secret key
+# FIXME: is this the proper test to be doing here?
+fingerprint_server_key >/dev/null \
+       && failure "An OpenPGP host key already exists."
+
+# get options
+while true ; do
+       case "$1" in
+           -l|--length)
+               keyLength="$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
+               hostName="$1"
+               shift;
+               break
+               ;;
+       esac
+done
+
+userID="ssh://${hostName}"
+
+# prompt about key expiration if not specified
+keyExpire=$(get_gpg_expiration "$keyExpire")
+
+# set key parameters
+keyParameters=\
+"Key-Type: $keyType
+Key-Length: $keyLength
+Key-Usage: $keyUsage
+Name-Real: $userID
+Expire-Date: $keyExpire"
+
+echo "The following key parameters will be used for the host private key:"
+echo "$keyParameters"
+
+read -p "Generate key? (Y/n) " OK; OK=${OK:=Y}
+if [ ${OK/y/Y} != 'Y' ] ; then
+       failure "aborting."
+fi
+
+# add commit command
+# must include blank line!
+keyParameters=\
+"${keyParameters}
+
+%commit
+%echo done"
+
+log verbose "generating host key..."
+echo "$keyParameters" | gpg_host --batch --gen-key
+
+# find the key fingerprint of the newly generated key
+fingerprint=$(fingerprint_server_key)
+
+# export host ownertrust to authentication keyring
+log verbose "setting ultimate owner trust for host key..."
+echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
+
+# translate the private key to ssh format, and export to a file
+# for sshs usage.
+# NOTE: assumes that the primary key is the proper key to use
+(umask 077 && \
+       gpg_host --export-secret-key "$fingerprint" | \
+       openpgp2ssh "$fingerprint" > "${SYSDATADIR}/ssh_host_rsa_key")
+log info "SSH host private key output to file: ${SYSDATADIR}/ssh_host_rsa_key"
+ssh-keygen -y -f "${SYSDATADIR}/ssh_host_rsa_key" > "${SYSDATADIR}/ssh_host_rsa_key.pub"
+log info "SSH host public key output to file: ${SYSDATADIR}/ssh_host_rsa_key.pub"
+gpg_authentication "--export-options export-minimal --armor --export 0x${fingerprint}\!" > "${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
+log info "SSH host public key in OpenPGP form: ${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
+
+# show info about new key
+show_key
+
+}
diff --git a/src/share/mh/import_key b/src/share/mh/import_key
new file mode 100644 (file)
index 0000000..386e02d
--- /dev/null
@@ -0,0 +1,89 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host import-key subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009 and are all released under the GPL,
+# version 3 or later.
+
+import_key() {
+
+local hostName=$(hostname -f)
+local keyFile="/etc/ssh/ssh_host_rsa_key"
+local keyExpire
+local userID
+
+# check for presense of secret key
+# FIXME: is this the proper test to be doing here?
+fingerprint_server_key >/dev/null \
+       && failure "An OpenPGP host key already exists."
+
+# 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
+               hostName="$1"
+               shift
+               ;;
+               break
+               ;;
+       esac
+done
+
+if [ ! -f "$keyFile" ] ; then
+       failure "SSH secret key file '$keyFile' not found."
+fi
+
+userID="ssh://${hostName}"
+
+# prompt about key expiration if not specified
+keyExpire=$(get_gpg_expiration "$keyExpire")
+
+echo "The following key parameters will be used for the host private key:"
+echo "Import: $keyFile"
+echo "Name-Real: $userID"
+echo "Expire-Date: $keyExpire"
+
+read -p "Import key? (Y/n) " OK; OK=${OK:=Y}
+if [ ${OK/y/Y} != 'Y' ] ; then
+       failure "aborting."
+fi
+
+log verbose "importing ssh key..."
+# translate ssh key to a private key
+(umask 077 && \
+       pem2openpgp "$userID" "$keyExpire" < "$sshKey" | gpg_host --import)
+
+# find the key fingerprint of the newly converted key
+fingerprint=$(fingerprint_server_key)
+
+# export host ownertrust to authentication keyring
+log verbose "setting ultimate owner trust for host key..."
+echo "${fingerprint}:6:" | gpg_host "--import-ownertrust"
+echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
+
+# export public key to file
+gpg_authentication "--export-options export-minimal --armor --export 0x${fingerprint}\!" > "${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
+log info "SSH host public key in OpenPGP form: ${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
+
+# show info about new key
+show_key
+
+}
diff --git a/src/share/mh/publish_key b/src/share/mh/publish_key
new file mode 100644 (file)
index 0000000..b7ab01d
--- /dev/null
@@ -0,0 +1,31 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host publish-key subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL, version 3
+# or later.
+
+# publish server key to keyserver
+
+publish_key() {
+
+read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
+if [ ${OK/y/Y} != 'Y' ] ; then
+    failure "key not published."
+fi
+
+# find the key fingerprint
+fingerprint=$(fingerprint_server_key)
+
+# publish host key
+# FIXME: need to define how to do this
+#gpg_authentication "--keyserver $KEYSERVER --send-keys '0x${fingerprint}!'"
+echo "not published!!!"
+
+}
diff --git a/src/share/mh/revoke_hostname b/src/share/mh/revoke_hostname
new file mode 100644 (file)
index 0000000..b519cf6
--- /dev/null
@@ -0,0 +1,91 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host revoke-hostname subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# revoke hostname user ID from host key
+
+revoke_hostname() {
+
+local userID
+local fingerprint
+local tmpuidMatch
+local line
+local uidIndex
+local message
+local revuidCommand
+
+if [ -z "$1" ] ; then
+    failure "You must specify a hostname to revoke."
+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 "Please see the following bug report for more information:"
+echo "http://web.monkeysphere.info/bugs/revoke-hostname-revoking-wrong-userid/"
+read -p "Are you sure you would like to proceed? (y/N) " OK; OK=${OK:=N}
+if [ ${OK/y/Y} != 'Y' ] ; then
+    failure "aborting."
+fi
+
+userID="ssh://${1}"
+
+fingerprint=$(fingerprint_server_key)
+
+# match to only ultimately trusted user IDs
+tmpuidMatch="u:$(echo $userID | gpg_escape)"
+
+# find the index of the requsted user ID
+# NOTE: this is based on circumstantial evidence that the order of
+# this output is the appropriate index
+if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}!" \
+    | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
+    uidIndex=${line%%:*}
+else
+    failure "No non-revoked user ID '$userID' is found."
+fi
+
+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
+    failure "User ID not revoked."
+fi
+
+message="Hostname removed by monkeysphere-server $DATE"
+
+# edit-key script command to revoke user ID
+revuidCommand=$(cat <<EOF
+$uidIndex
+revuid
+y
+4
+$message
+
+y
+save
+EOF
+    )  
+
+# execute edit-key script
+if echo "$revuidCommand" | \
+    gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
+
+    show_key
+
+    echo
+    echo "NOTE: User ID revoked, but revocation not published."
+    echo "Run '$PGRM publish-key' to publish the revocation."
+else
+    failure "Problem revoking user ID."
+fi
+
+}
diff --git a/src/share/mh/revoke_key b/src/share/mh/revoke_key
new file mode 100644 (file)
index 0000000..cccdc22
--- /dev/null
@@ -0,0 +1,21 @@
+# -*-shell-script-*-
+# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
+
+# Monkeysphere host revoke-key subcommand
+#
+# The monkeysphere scripts are written by:
+# Jameson Rollins <jrollins@finestructure.net>
+# Jamie McClelland <jm@mayfirst.org>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# They are Copyright 2008-2009, and are all released under the GPL,
+# version 3 or later.
+
+# revoke host key
+
+revoke_key() {
+
+# FIXME: implement!
+failure "not implemented yet!"
+
+}
diff --git a/src/subcommands/m/gen_subkey b/src/subcommands/m/gen_subkey
deleted file mode 100644 (file)
index cbefaa3..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere gen-subkey subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# generate a subkey with the 'a' usage flags set
-
-gen_subkey(){
-    local keyLength
-    local keyExpire
-    local keyID
-    local gpgOut
-    local userID
-
-    # get options
-    while true ; do
-       case "$1" in
-           -l|--length)
-               keyLength="$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
-
-    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 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")
-
-    # generate the list of commands that will be passed to edit-key
-    editCommands=$(cat <<EOF
-addkey
-7
-S
-E
-A
-Q
-$keyLength
-$keyExpire
-save
-EOF
-)
-
-    log verbose "generating subkey..."
-    fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
-    (umask 077 && mkfifo "$fifoDir/pass")
-    echo "$editCommands" | gpg --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"
-
-    rm -rf "$fifoDir"
-    wait
-    log verbose "done."
-}
diff --git a/src/subcommands/m/import_subkey b/src/subcommands/m/import_subkey
deleted file mode 100644 (file)
index aa89958..0000000
+++ /dev/null
@@ -1,54 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere import-subkey subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# import an existing ssh key as a gpg subkey
-
-import_subkey() {
-    local keyFile="~/.ssh/id_rsa"
-    local keyExpire
-    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)
-    (umask 077 && mkfifo "$fifoDir/pass")
-    ssh2openpgp | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
-
-    passphrase_prompt  "Please enter your passphrase for $keyID: " "$fifoDir/pass"
-
-    rm -rf "$fifoDir"
-    wait
-    log verbose "done."
-}
diff --git a/src/subcommands/m/ssh_proxycommand b/src/subcommands/m/ssh_proxycommand
deleted file mode 100644 (file)
index 7239c7a..0000000
+++ /dev/null
@@ -1,237 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# monkeysphere-ssh-proxycommand: MonkeySphere ssh ProxyCommand hook
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# This is meant to be run as an ssh ProxyCommand to initiate a
-# monkeysphere known_hosts update before an ssh connection to host is
-# 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() {
-    local sshKeyOffered
-    local userID
-    local type
-    local validity
-    local keyid
-    local uidfpr
-    local usage
-    local sshKeyGPG
-    local tmpkey
-    local sshFingerprint
-    local gpgSigOut
-
-    userID="ssh://${HOSTP}"
-
-    log "-------------------- Monkeysphere warning -------------------"
-    log "Monkeysphere found OpenPGP keys for this hostname, but none had full validity."
-
-    # retrieve the actual ssh key
-    sshKeyOffered=$(ssh-keyscan -t rsa -p "$PORT" "$HOST" 2>/dev/null | awk '{ print $2, $3 }')
-    # FIXME: should we do any checks for failed keyscans, eg. host not
-    # found?
-
-    # get the gpg info for userid
-    gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \
-       --with-fingerprint --with-fingerprint \
-       ="$userID" 2>/dev/null)
-
-    # find all 'pub' and 'sub' lines in the gpg output, which each
-    # represent a retrieved key for the user ID
-    echo "$gpgOut" | cut -d: -f1,2,5,10,12 | \
-    while IFS=: read -r type validity keyid uidfpr usage ; do
-       case $type in
-           'pub'|'sub')
-               # get the ssh key of the gpg key
-               sshKeyGPG=$(gpg2ssh "$keyid")
-
-               # if one of keys found matches the one offered by the
-               # host, then output info
-               if [ "$sshKeyGPG" = "$sshKeyOffered" ] ; then
-                   log "An OpenPGP key matching the ssh key offered by the host was found:"
-                   log
-
-                   # 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") | \
-                       awk '{ print $2 }')
-
-                   # get the sigs for the matching key
-                   gpgSigOut=$(gpg --check-sigs \
-                       --list-options show-uid-validity \
-                       "$keyid")
-
-                   # output the sigs, but only those on the user ID
-                   # we are looking for
-                   echo "$gpgSigOut" | awk '
-{
-if (match($0,"^pub")) {        print; }
-if (match($0,"^uid")) { ok=0; }
-if (match($0,"^uid.*'$userID'$")) { ok=1; print; }
-if (ok) { if (match($0,"^sig")) { print; } }
-}
-' >&2
-                   log
-
-                   # output the other user IDs for reference
-                   if (echo "$gpgSigOut" | grep "^uid" | grep -v -q "$userID") ; then
-                       log "Other user IDs on this key:"
-                       echo "$gpgSigOut" | grep "^uid" | grep -v "$userID" >&2
-                       log
-                   fi
-
-                   # output ssh fingerprint
-                   log "RSA key fingerprint is ${sshFingerprint}."
-
-                   # this whole process is in a "while read"
-                   # subshell.  the only way to get information out
-                   # of the subshell is to change the return code.
-                   # therefore we return 1 here to indicate that a
-                   # matching gpg key was found for the ssh key
-                   # offered by the host
-                   return 1
-               fi
-               ;;
-       esac
-    done
-
-    # if no key match was made (and the "while read" subshell returned
-    # 1) output how many keys were found
-    if (($? != 1)) ; then
-       log "None of the found keys matched the key offered by the host."
-       log "Run the following command for more info about the found keys:"
-       log "gpg --check-sigs --list-options show-uid-validity =${userID}"
-       # FIXME: should we do anything extra here if the retrieved
-       # host key is actually in the known_hosts file and the ssh
-       # connection will succeed?  Should the user be warned?
-       # prompted?
-    fi
-
-    log "-------------------- ssh continues below --------------------"
-}
-
-########################################################################
-
-# export the monkeysphere log level
-export MONKEYSPHERE_LOG_LEVEL
-
-if [ "$1" = '--no-connect' ] ; then
-    NO_CONNECT='true'
-    shift 1
-fi
-
-HOST="$1"
-PORT="$2"
-
-if [ -z "$HOST" ] ; then
-    log "Host not specified."
-    usage
-    exit 255
-fi
-if [ -z "$PORT" ] ; then
-    PORT=22
-fi
-
-# set the host URI
-if [ "$PORT" != '22' ] ; then
-    HOSTP="${HOST}:${PORT}"
-else
-    HOSTP="${HOST}"
-fi
-URI="ssh://${HOSTP}"
-
-# specify keyserver checking.  the behavior of this proxy command is
-# 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.
-
-# if the host is in the gpg keyring...
-if gpg --list-key ="${URI}" 2>&1 >/dev/null ; then
-    # do not check the keyserver
-    CHECK_KEYSERVER="false"
-
-# if the host is NOT in the keyring...
-else
-    # if the host key is found in the known_hosts file...
-    # FIXME: this only works for default known_hosts location
-    hostKey=$(ssh-keygen -F "$HOST" 2>/dev/null)
-
-    if [ "$hostKey" ] ; then
-       # do not check the keyserver
-       # 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"
-
-    # if the host key is not found in the known_hosts file...
-    else
-       # check the 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
-
-# update the known_hosts file for the host
-monkeysphere update-known_hosts "$HOSTP"
-
-# output on depending on the return of the update-known_hosts
-# subcommand, which is (ultimately) the return code of the
-# update_known_hosts function in common
-case $? in
-    0)
-       # acceptable host key found so continue to ssh
-       true
-       ;;
-    1)
-       # no hosts at all found so also continue (drop through to
-       # regular ssh host verification)
-       true
-       ;;
-    2)
-       # at least one *bad* host key (and no good host keys) was
-       # found, so output some usefull information
-       output_no_valid_key
-       ;;
-    *)
-       # anything else drop through
-       true
-       ;;
-esac
-
-# FIXME: what about the case where monkeysphere successfully finds a
-# valid key for the host and adds it to the known_hosts file, but a
-# different non-monkeysphere key for the host already exists in the
-# known_hosts, and it is this non-ms key that is offered by the host?
-# monkeysphere will succeed, and the ssh connection will succeed, and
-# the user will be left with the impression that they are dealing with
-# a OpenPGP/PKI host key when in fact they are not.  should we use
-# ssh-keyscan to compare the keys first?
-
-# exec a netcat passthrough to host for the ssh connection
-if [ -z "$NO_CONNECT" ] ; then
-    if (which nc 2>/dev/null >/dev/null); then
-       exec nc "$HOST" "$PORT"
-    elif (which socat 2>/dev/null >/dev/null); then
-       exec socat STDIO "TCP:$HOST:$PORT"
-    else
-       echo "Neither netcat nor socat found -- could not complete monkeysphere-ssh-proxycommand connection to $HOST:$PORT" >&2
-       exit 255
-    fi
-fi
-
-}
diff --git a/src/subcommands/m/subkey_to_ssh_agent b/src/subcommands/m/subkey_to_ssh_agent
deleted file mode 100644 (file)
index 012c95f..0000000
+++ /dev/null
@@ -1,113 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere subkey-to-ssh-agent subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# try to add all authentication subkeys to the agent
-
-subkey_to_ssh_agent() {
-    local sshaddresponse
-    local secretkeys
-    local authsubkeys
-    local workingdir
-    local keysuccess
-    local subkey
-    local publine
-    local kname
-
-    if ! test_gnu_dummy_s2k_extension ; then
-       failure "Your version of GnuTLS does not seem capable of using with gpg's exported subkeys.
-You may want to consider patching or upgrading to GnuTLS 2.6 or later.
-
-For more details, see:
- http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html"
-    fi
-
-    # if there's no agent running, don't bother:
-    if [ -z "$SSH_AUTH_SOCK" ] || ! which ssh-add >/dev/null ; then
-       failure "No ssh-agent available."
-    fi
-
-    # and if it looks like it's running, but we can't actually talk to
-    # it, bail out:
-    ssh-add -l >/dev/null
-    sshaddresponse="$?"
-    if [ "$sshaddresponse" = "2" ]; then
-       failure "Could not connect to ssh-agent"
-    fi
-    
-    # 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 | \
-       grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }')
-
-    if [ -z "$secretkeys" ]; then
-       failure "You have no secret keys in your keyring!
-You might want to run 'gpg --gen-key'."
-    fi
-    
-    authsubkeys=$(gpg --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)
-
-    if [ -z "$authsubkeys" ]; then
-       failure "no authentication-capable subkeys available.
-You might want to 'monkeysphere gen-subkey'"
-    fi
-
-    workingdir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
-    umask 077
-    mkfifo "$workingdir/passphrase"
-    keysuccess=1
-
-    # FIXME: we're currently allowing any other options to get passed
-    # through to ssh-add.  should we limit it to known ones?  For
-    # example: -d or -c and/or -t <lifetime> 
-
-    for subkey in $authsubkeys; do 
-       # choose a label by which this key will be known in the agent:
-       # we are labelling the key by User ID instead of by
-       # 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 /)
-
-       #kname="[monkeysphere] $primaryuid"
-       kname="$primaryuid"
-
-       if [ "$1" = '-d' ]; then
-           # we're removing the subkey:
-           gpg --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" \
-               --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 )&
-
-           passphrase_prompt "Enter passphrase for key $kname: " "$workingdir/passphrase"
-           wait %2
-       fi
-       keysuccess="$?"
-
-       rm -f "$workingdir/$kname"
-    done
-
-    rm -rf "$workingdir"
-
-    # FIXME: sort out the return values: we're just returning the
-    # success or failure of the final authentication subkey in this
-    # case.  What if earlier ones failed?
-    exit "$keysuccess"
-}
diff --git a/src/subcommands/ma/add_certifier b/src/subcommands/ma/add_certifier
deleted file mode 100644 (file)
index 0c3c647..0000000
+++ /dev/null
@@ -1,146 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere authentication add-certifier subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# retrieve key from web of trust, import it into the host keyring, and
-# ltsign the key in the host keyring so that it may certify other keys
-
-add_certifier() {
-
-local domain
-local trust
-local depth
-local keyID
-local fingerprint
-local ltsignCommand
-local trustval
-
-# set default values for trust depth and domain
-domain=
-trust=full
-depth=1
-
-# get options
-while true ; do
-    case "$1" in
-       -n|--domain)
-           domain="$2"
-           shift 2
-           ;;
-       -t|--trust)
-           trust="$2"
-           shift 2
-           ;;
-       -d|--depth)
-           depth="$2"
-           shift 2
-           ;;
-       *)
-           if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
-               failure "Unknown option '$1'.
-Type '$PGRM help' for usage."
-           fi
-           break
-           ;;
-    esac
-done
-
-keyID="$1"
-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
-    echo "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 "Expected there to be a single gpg key in the file."
-    fi
-else
-    # get the key from the key server
-    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 a key ID
-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
-
-echo
-echo "key found:"
-gpg_sphere "--fingerprint 0x${fingerprint}!"
-
-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
-
-# export the key to the host keyring
-gpg_sphere "--export 0x${fingerprint}!" | gpg_core --import
-
-if [ "$trust" = marginal ]; then
-    trustval=1
-elif [ "$trust" = full ]; then
-    trustval=2
-else
-    failure "Trust value requested ('$trust') was unclear (only 'marginal' or 'full' are supported)."
-fi
-
-# ltsign command
-# NOTE: *all* user IDs will be ltsigned
-ltsignCommand=$(cat <<EOF
-ltsign
-y
-$trustval
-$depth
-$domain
-y
-save
-EOF
-    )
-
-# ltsign the key
-if echo "$ltsignCommand" | \
-    gpg_core --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
-
-    # update the trustdb for the authentication keyring
-    gpg_sphere "--check-trustdb"
-
-    echo
-    echo "Identity certifier added."
-else
-    failure "Problem adding identify certifier."
-fi
-
-}
diff --git a/src/subcommands/ma/diagnostics b/src/subcommands/ma/diagnostics
deleted file mode 100644 (file)
index 73e93a0..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere authentication diagnostics subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# check on the status and validity of the key and public certificates
-
-diagnostics() {
-
-local seckey
-local keysfound
-local curdate
-local warnwindow
-local warndate
-local create
-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
-seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
-keysfound=$(echo "$seckey" | grep -c ^sec:)
-curdate=$(date +%s)
-# warn when anything is 2 months away from expiration
-warnwindow='2 months'
-warndate=$(advance_date $warnwindow +%s)
-
-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))
-fi
-
-if ! [ -d "$SYSDATADIR" ] ; then
-    echo "! no $SYSDATADIR directory found.  Please create it."
-    problemsfound=$(($problemsfound+1))
-fi
-
-echo "Checking host GPG key..."
-if (( "$keysfound" < 1 )); then
-    echo "! No host key found."
-    echo " - Recommendation: run 'monkeysphere-server gen-key'"
-    problemsfound=$(($problemsfound+1))
-elif (( "$keysfound" > 1 )); then
-    echo "! More than one host key found?"
-    # FIXME: recommend a way to resolve this
-    problemsfound=$(($problemsfound+1))
-else
-    create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
-    expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
-    fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
-    # check for key expiration:
-    if [ "$expire" ]; then
-       if (( "$expire"  < "$curdate" )); then
-           echo "! Host key is expired."
-           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
-           problemsfound=$(($problemsfound+1))
-       elif (( "$expire" < "$warndate" )); then
-           echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
-           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
-           problemsfound=$(($problemsfound+1))
-       fi
-    fi
-
-    # and weirdnesses:
-    if [ "$create" ] && (( "$create" > "$curdate" )); then
-       echo "! Host key was created in the future(?!). Is your clock correct?"
-       echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
-       problemsfound=$(($problemsfound+1))
-    fi
-    
-    # check for UserID expiration:
-    echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
-    while IFS=: read create expire uid ; do
-       # FIXME: should we be doing any checking on the form
-       # of the User ID?  Should we be unmangling it somehow?
-
-       if [ "$create" ] && (( "$create" > "$curdate" )); then
-           echo "! User ID '$uid' was created in the future(?!).  Is your clock correct?"
-           echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
-           problemsfound=$(($problemsfound+1))
-       fi
-       if [ "$expire" ] ; then
-           if (( "$expire" < "$curdate" )); then
-               echo "! User ID '$uid' is expired."
-               # FIXME: recommend a way to resolve this
-               problemsfound=$(($problemsfound+1))
-           elif (( "$expire" < "$warndate" )); then
-               echo "! User ID '$uid' expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)         
-               # FIXME: recommend a way to resolve this
-               problemsfound=$(($problemsfound+1))
-           fi
-       fi
-    done
-           
-# FIXME: verify that the host key is properly published to the
-#   keyservers (do this with the non-privileged user)
-
-# FIXME: check that there are valid, non-expired certifying signatures
-#   attached to the host key after fetching from the public keyserver
-#   (do this with the non-privileged user as well)
-
-# 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
-
-       # 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,
-#    directories housing them, etc (what should those values be?  can
-#    we make them as minimal as possible?)
-
-# FIXME: look to see that the ownertrust rules are set properly on the
-#    authentication keyring
-
-# FIXME: make sure that at least one identity certifier exists
-
-# FIXME: look at the timestamps on the monkeysphere-generated
-# authorized_keys files -- warn if they seem out-of-date.
-
-# FIXME: check for a cronjob that updates monkeysphere-generated
-# authorized_keys?
-
-echo
-echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
-# Ensure that User ID authentication is enabled:
-if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$" "$sshd_config"; then
-    echo "! $sshd_config does not point to monkeysphere authorized keys."
-    echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${SYSDATADIR}/authorized_keys/%u'"
-    problemsfound=$(($problemsfound+1))
-fi
-if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -v "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$") ; then
-    echo "! $sshd_config refers to non-monkeysphere authorized_keys files:"
-    echo "$badauthorizedkeys"
-    echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
-    problemsfound=$(($problemsfound+1))
-fi
-
-if [ "$problemsfound" -gt 0 ]; then
-    echo "When the above $problemsfound issue"$(if [ "$problemsfound" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
-    echo "  monkeysphere-server diagnostics"
-else
-    echo "Everything seems to be in order!"
-fi
-
-}
diff --git a/src/subcommands/ma/list_certifiers b/src/subcommands/ma/list_certifiers
deleted file mode 100644 (file)
index e37485e..0000000
+++ /dev/null
@@ -1,30 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere authentication list-certifiers subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@fifthhorseman.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# list the host certifiers
-
-list_certifiers() {
-
-local keys
-local key
-
-# find trusted keys in authentication keychain
-keys=$(gpg_sphere "--no-options --list-options show-uid-validity --keyring ${GNUPGHOME_AUTHENTICATION}/pubring.gpg --list-keys --with-colons --fingerprint" | \
-    grep ^pub: | cut -d: -f2,5 | egrep '^(u|f):' | cut -d: -f2)
-
-# output keys
-for key in $keys ; do
-    gpg_sphere "--no-options --list-options show-uid-validity --keyring ${GNUPGHOME_AUTHENTICATION}/pubring.gpg --list-key --fingerprint $key"
-done
-
-}
diff --git a/src/subcommands/ma/remove_certifier b/src/subcommands/ma/remove_certifier
deleted file mode 100644 (file)
index 560281d..0000000
+++ /dev/null
@@ -1,49 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere authentication remove-certifier subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# delete a certifiers key from the host keyring
-
-remove_certifier() {
-
-local keyID
-local fingerprint
-
-keyID="$1"
-if [ -z "$keyID" ] ; then
-    failure "You must specify the key ID of a key to remove."
-fi
-
-if gpg_sphere "--no-options --list-options show-uid-validity --keyring ${GNUPGHOME_AUTHENTICATION}/pubring.gpg --list-key 0x${keyID}!" ; then
-    read -p "Really remove above listed identity certifier? (y/N) " OK; OK=${OK:-N}
-    if [ "${OK/y/Y}" != 'Y' ] ; then
-       failure "Identity certifier not removed."
-    fi
-else
-    failure
-fi
-
-# delete the requested key
-if gpg_sphere "--delete-key --batch --yes 0x${keyID}!" ; then
-    # delete key from host keyring as well
-    gpg_core --delete-key --batch --yes "0x${keyID}!"
-
-    # update the trustdb for the authentication keyring
-    gpg_sphere "--check-trustdb"
-
-    echo
-    echo "Identity certifier removed."
-else
-    failure "Problem removing identity certifier."
-fi
-
-}
diff --git a/src/subcommands/ma/update_users b/src/subcommands/ma/update_users
deleted file mode 100644 (file)
index 73685f6..0000000
+++ /dev/null
@@ -1,157 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere authentication update-users subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-update_users() {
-
-local unames
-local uname
-local authorizedKeysDir
-local authorizedUserIDs
-
-if [ "$1" ] ; then
-    # get users from command line
-    unames="$@"
-else        
-    # or just look at all users if none specified
-    unames=$(getent passwd | cut -d: -f1)
-fi
-
-RETURN=0
-
-# set mode
-MODE="authorized_keys"
-
-# set gnupg home
-GNUPGHOME="$GNUPGHOME_SPHERE"
-
-# the authorized_keys directory
-authorizedKeysDir="${SYSDATADIR}/authentication/authorized_keys"
-
-# check to see if the gpg trust database has been initialized
-if [ ! -s "${GNUPGHOME}/trustdb.gpg" ] ; then
-    failure "GNUPG trust database uninitialized.  Please see MONKEYSPHERE-SERVER(8)."
-fi
-
-# make sure the authorized_keys directory exists
-mkdir -p "${authorizedKeysDir}"
-
-# loop over users
-for uname in $unames ; do
-    # check all specified users exist
-    if ! id "$uname" >/dev/null ; then
-       log error "----- unknown user '$uname' -----"
-       continue
-    fi
-
-    log verbose "----- user: $uname -----"
-
-    # make temporary directory
-    TMPLOC=$(mktemp -d ${MATMPDIR}/tmp.XXXXXXXXXX) || failure "Could not create temporary directory!"
-
-    # trap to delete temporary directory on exit
-    trap "rm -rf $TMPLOC" EXIT
-
-    # create temporary authorized_user_ids file
-    TMP_AUTHORIZED_USER_IDS="${TMPLOC}/authorized_user_ids"
-    touch "$TMP_AUTHORIZED_USER_IDS"
-
-     # create temporary authorized_keys file
-    AUTHORIZED_KEYS="${TMPLOC}/authorized_keys"
-    touch "$AUTHORIZED_KEYS"
-
-    # set restrictive permissions on the temporary files
-    # FIXME: is there a better way to do this?
-    chmod 0700 "$TMPLOC"
-    chmod 0600 "$AUTHORIZED_KEYS"
-    chmod 0600 "$TMP_AUTHORIZED_USER_IDS"
-    chown -R "$MONKEYSPHERE_USER" "$TMPLOC"
-
-    # process authorized_user_ids file
-    log debug "checking for authorized_user_ids..."
-    # translating ssh-style path variables
-    authorizedUserIDs=$(translate_ssh_variables "$uname" "$AUTHORIZED_USER_IDS")
-    if [ -s "$authorizedUserIDs" ] ; then
-       # check permissions on the authorized_user_ids file path
-       if check_key_file_permissions "$uname" "$authorizedUserIDs" ; then
-            # copy user authorized_user_ids file to temporary
-            # location
-           cat "$authorizedUserIDs" > "$TMP_AUTHORIZED_USER_IDS"
-
-           # export needed variables
-           export AUTHORIZED_KEYS
-           export TMP_AUTHORIZED_USER_IDS
-
-           # process authorized_user_ids file, as monkeysphere user
-           su_monkeysphere_user \
-               ". ${SYSSHAREDIR}/common; process_authorized_user_ids $TMP_AUTHORIZED_USER_IDS"
-           RETURN="$?"
-       else
-           log debug "not processing authorized_user_ids."
-       fi
-    else
-       log debug "empty or absent authorized_user_ids file."
-    fi
-
-    # add user-controlled authorized_keys file if specified translate
-    # ssh-style path variables
-    rawAuthorizedKeys=$(translate_ssh_variables "$uname" "$RAW_AUTHORIZED_KEYS")
-    if [ "$rawAuthorizedKeys" != 'none' ] ; then
-       log debug "checking for raw authorized_keys..."
-       if [ -s "$rawAuthorizedKeys" ] ; then
-           # check permissions on the authorized_keys file path
-           if check_key_file_permissions "$uname" "$rawAuthorizedKeys" ; then
-               log verbose "adding raw authorized_keys file... "
-               cat "$rawAuthorizedKeys" >> "$AUTHORIZED_KEYS"
-           else
-               log debug "not adding raw authorized_keys file."                
-           fi
-       else
-           log debug "empty or absent authorized_keys file."
-       fi
-    fi
-
-    # move the new authorized_keys file into place
-    if [ -s "$AUTHORIZED_KEYS" ] ; then
-       # openssh appears to check the contents of the authorized_keys
-       # file as the user in question, so the file must be readable
-       # by that user at least.
-
-       # but in general, we don't want the user tampering with this
-       # file directly, so we'll adopt this approach: Own the file by
-       # the monkeysphere-server invoker (usually root, but should be
-       # the same uid that sshd is launched as); change the group of
-       # the file so that members of the user's group can read it.
-
-       # FIXME: is there a better way to do this?
-       chown $(whoami) "$AUTHORIZED_KEYS" && \
-           chgrp $(id -g "$uname") "$AUTHORIZED_KEYS" && \
-           chmod g+r "$AUTHORIZED_KEYS" && \
-           mv -f "$AUTHORIZED_KEYS" "${authorizedKeysDir}/${uname}" || \
-           { 
-           log error "Failed to install authorized_keys for '$uname'!"
-           rm -f "${authorizedKeysDir}/${uname}"
-           # indicate that there has been a failure:
-           RETURN=1
-       }
-    else
-       rm -f "${authorizedKeysDir}/${uname}"
-    fi
-
-    # unset the trap
-    trap - EXIT
-
-    # destroy temporary directory
-    rm -rf "$TMPLOC"
-done
-
-}
diff --git a/src/subcommands/mh/add_hostname b/src/subcommands/mh/add_hostname
deleted file mode 100644 (file)
index 10d5f58..0000000
+++ /dev/null
@@ -1,73 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host add-hostname subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# add hostname user ID to server key
-
-add_hostname() {
-
-local userID
-local fingerprint
-local tmpuidMatch
-local line
-local adduidCommand
-
-if [ -z "$1" ] ; then
-    failure "You must specify a hostname to add."
-fi
-
-userID="ssh://${1}"
-
-fingerprint=$(fingerprint_server_key)
-
-# match to only ultimately trusted user IDs
-tmpuidMatch="u:$(echo $userID | gpg_escape)"
-
-# find the index of the requsted user ID
-# NOTE: this is based on circumstantial evidence that the order of
-# this output is the appropriate index
-if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}!" \
-    | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
-    failure "Host userID '$userID' already exists."
-fi
-
-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
-    failure "User ID not added."
-fi
-
-# edit-key script command to add user ID
-adduidCommand=$(cat <<EOF
-adduid
-$userID
-
-
-save
-EOF
-)
-
-# execute edit-key script
-if echo "$adduidCommand" | \
-    gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
-
-    show_key
-
-    echo
-    echo "NOTE: User ID added to key, but key not published."
-    echo "Run '$PGRM publish-key' to publish the new user ID."
-else
-    failure "Problem adding user ID."
-fi
-
-}
diff --git a/src/subcommands/mh/add_revoker b/src/subcommands/mh/add_revoker
deleted file mode 100644 (file)
index f9d0bb6..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host add-revoker subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008, and are all released under the GPL, version 3
-# or later.
-
-# add a revoker to the host key
-
-add_revoker() {
-
-# FIXME: implement!
-failure "not implemented yet!"
-
-}
diff --git a/src/subcommands/mh/diagnostics b/src/subcommands/mh/diagnostics
deleted file mode 100644 (file)
index 7e76da6..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host diagnostics subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# check on the status and validity of the key and public certificates
-
-diagnostics() {
-
-local seckey
-local keysfound
-local curdate
-local warnwindow
-local warndate
-local create
-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
-seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
-keysfound=$(echo "$seckey" | grep -c ^sec:)
-curdate=$(date +%s)
-# warn when anything is 2 months away from expiration
-warnwindow='2 months'
-warndate=$(advance_date $warnwindow +%s)
-
-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))
-fi
-
-if ! [ -d "$SYSDATADIR" ] ; then
-    echo "! no $SYSDATADIR directory found.  Please create it."
-    problemsfound=$(($problemsfound+1))
-fi
-
-echo "Checking host GPG key..."
-if (( "$keysfound" < 1 )); then
-    echo "! No host key found."
-    echo " - Recommendation: run 'monkeysphere-server gen-key'"
-    problemsfound=$(($problemsfound+1))
-elif (( "$keysfound" > 1 )); then
-    echo "! More than one host key found?"
-    # FIXME: recommend a way to resolve this
-    problemsfound=$(($problemsfound+1))
-else
-    create=$(echo "$seckey" | grep ^sec: | cut -f6 -d:)
-    expire=$(echo "$seckey" | grep ^sec: | cut -f7 -d:)
-    fingerprint=$(echo "$seckey" | grep ^fpr: | head -n1 | cut -f10 -d:)
-    # check for key expiration:
-    if [ "$expire" ]; then
-       if (( "$expire"  < "$curdate" )); then
-           echo "! Host key is expired."
-           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
-           problemsfound=$(($problemsfound+1))
-       elif (( "$expire" < "$warndate" )); then
-           echo "! Host key expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)
-           echo " - Recommendation: extend lifetime of key with 'monkeysphere-server extend-key'"
-           problemsfound=$(($problemsfound+1))
-       fi
-    fi
-
-    # and weirdnesses:
-    if [ "$create" ] && (( "$create" > "$curdate" )); then
-       echo "! Host key was created in the future(?!). Is your clock correct?"
-       echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
-       problemsfound=$(($problemsfound+1))
-    fi
-    
-    # check for UserID expiration:
-    echo "$seckey" | grep ^uid: | cut -d: -f6,7,10 | \
-    while IFS=: read create expire uid ; do
-       # FIXME: should we be doing any checking on the form
-       # of the User ID?  Should we be unmangling it somehow?
-
-       if [ "$create" ] && (( "$create" > "$curdate" )); then
-           echo "! User ID '$uid' was created in the future(?!).  Is your clock correct?"
-           echo " - Recommendation: Check clock ($(date +%F_%T)); use NTP?"
-           problemsfound=$(($problemsfound+1))
-       fi
-       if [ "$expire" ] ; then
-           if (( "$expire" < "$curdate" )); then
-               echo "! User ID '$uid' is expired."
-               # FIXME: recommend a way to resolve this
-               problemsfound=$(($problemsfound+1))
-           elif (( "$expire" < "$warndate" )); then
-               echo "! User ID '$uid' expires in less than $warnwindow:" $(advance_date $(( $expire - $curdate )) seconds +%F)         
-               # FIXME: recommend a way to resolve this
-               problemsfound=$(($problemsfound+1))
-           fi
-       fi
-    done
-           
-# FIXME: verify that the host key is properly published to the
-#   keyservers (do this with the non-privileged user)
-
-# FIXME: check that there are valid, non-expired certifying signatures
-#   attached to the host key after fetching from the public keyserver
-#   (do this with the non-privileged user as well)
-
-# 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
-
-       # 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,
-#    directories housing them, etc (what should those values be?  can
-#    we make them as minimal as possible?)
-
-# FIXME: look to see that the ownertrust rules are set properly on the
-#    authentication keyring
-
-# FIXME: make sure that at least one identity certifier exists
-
-# FIXME: look at the timestamps on the monkeysphere-generated
-# authorized_keys files -- warn if they seem out-of-date.
-
-# FIXME: check for a cronjob that updates monkeysphere-generated
-# authorized_keys?
-
-echo
-echo "Checking for MonkeySphere-enabled public-key authentication for users ..."
-# Ensure that User ID authentication is enabled:
-if ! grep -q "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$" "$sshd_config"; then
-    echo "! $sshd_config does not point to monkeysphere authorized keys."
-    echo " - Recommendation: add a line to $sshd_config: 'AuthorizedKeysFile ${SYSDATADIR}/authorized_keys/%u'"
-    problemsfound=$(($problemsfound+1))
-fi
-if badauthorizedkeys=$(grep -i '^AuthorizedKeysFile' "$sshd_config" | grep -v "^AuthorizedKeysFile[[:space:]]\+${SYSDATADIR}/authorized_keys/%u$") ; then
-    echo "! $sshd_config refers to non-monkeysphere authorized_keys files:"
-    echo "$badauthorizedkeys"
-    echo " - Recommendation: remove the above AuthorizedKeysFile lines from $sshd_config"
-    problemsfound=$(($problemsfound+1))
-fi
-
-if [ "$problemsfound" -gt 0 ]; then
-    echo "When the above $problemsfound issue"$(if [ "$problemsfound" -eq 1 ] ; then echo " is" ; else echo "s are" ; fi)" resolved, please re-run:"
-    echo "  monkeysphere-server diagnostics"
-else
-    echo "Everything seems to be in order!"
-fi
-
-}
diff --git a/src/subcommands/mh/extend_key b/src/subcommands/mh/extend_key
deleted file mode 100644 (file)
index ccbaf0e..0000000
+++ /dev/null
@@ -1,34 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host extend-key subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# extend the lifetime of a host key:
-
-extend_key() {
-
-local fpr=$(fingerprint_server_key)
-local extendTo="$1"
-
-# get the new expiration date
-extendTo=$(get_gpg_expiration "$extendTo")
-
-gpg_host --quiet --command-fd 0 --edit-key "$fpr" <<EOF 
-expire
-$extendTo
-save
-EOF
-
-echo
-echo "NOTE: Host key expiration date adjusted, but not yet published."
-echo "Run '$PGRM publish-key' to publish the new expiration date."
-
-}
diff --git a/src/subcommands/mh/gen_key b/src/subcommands/mh/gen_key
deleted file mode 100644 (file)
index aad213a..0000000
+++ /dev/null
@@ -1,107 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host gen-key subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-gen_key() {
-
-local keyType="RSA"
-local keyLength="2048"
-local keyUsage="auth"
-local keyExpire
-local hostName=$(hostname -f)
-local userID
-local keyParameters
-local fingerprint
-
-# check for presense of secret key
-# FIXME: is this the proper test to be doing here?
-fingerprint_server_key >/dev/null \
-       && failure "An OpenPGP host key already exists."
-
-# get options
-while true ; do
-       case "$1" in
-           -l|--length)
-               keyLength="$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
-               hostName="$1"
-               shift;
-               break
-               ;;
-       esac
-done
-
-userID="ssh://${hostName}"
-
-# prompt about key expiration if not specified
-keyExpire=$(get_gpg_expiration "$keyExpire")
-
-# set key parameters
-keyParameters=\
-"Key-Type: $keyType
-Key-Length: $keyLength
-Key-Usage: $keyUsage
-Name-Real: $userID
-Expire-Date: $keyExpire"
-
-echo "The following key parameters will be used for the host private key:"
-echo "$keyParameters"
-
-read -p "Generate key? (Y/n) " OK; OK=${OK:=Y}
-if [ ${OK/y/Y} != 'Y' ] ; then
-       failure "aborting."
-fi
-
-# add commit command
-# must include blank line!
-keyParameters=\
-"${keyParameters}
-
-%commit
-%echo done"
-
-log verbose "generating host key..."
-echo "$keyParameters" | gpg_host --batch --gen-key
-
-# find the key fingerprint of the newly generated key
-fingerprint=$(fingerprint_server_key)
-
-# export host ownertrust to authentication keyring
-log verbose "setting ultimate owner trust for host key..."
-echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
-
-# translate the private key to ssh format, and export to a file
-# for sshs usage.
-# NOTE: assumes that the primary key is the proper key to use
-(umask 077 && \
-       gpg_host --export-secret-key "$fingerprint" | \
-       openpgp2ssh "$fingerprint" > "${SYSDATADIR}/ssh_host_rsa_key")
-log info "SSH host private key output to file: ${SYSDATADIR}/ssh_host_rsa_key"
-ssh-keygen -y -f "${SYSDATADIR}/ssh_host_rsa_key" > "${SYSDATADIR}/ssh_host_rsa_key.pub"
-log info "SSH host public key output to file: ${SYSDATADIR}/ssh_host_rsa_key.pub"
-gpg_authentication "--export-options export-minimal --armor --export 0x${fingerprint}\!" > "${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
-log info "SSH host public key in OpenPGP form: ${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
-
-# show info about new key
-show_key
-
-}
diff --git a/src/subcommands/mh/import_key b/src/subcommands/mh/import_key
deleted file mode 100644 (file)
index 386e02d..0000000
+++ /dev/null
@@ -1,89 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host import-key subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009 and are all released under the GPL,
-# version 3 or later.
-
-import_key() {
-
-local hostName=$(hostname -f)
-local keyFile="/etc/ssh/ssh_host_rsa_key"
-local keyExpire
-local userID
-
-# check for presense of secret key
-# FIXME: is this the proper test to be doing here?
-fingerprint_server_key >/dev/null \
-       && failure "An OpenPGP host key already exists."
-
-# 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
-               hostName="$1"
-               shift
-               ;;
-               break
-               ;;
-       esac
-done
-
-if [ ! -f "$keyFile" ] ; then
-       failure "SSH secret key file '$keyFile' not found."
-fi
-
-userID="ssh://${hostName}"
-
-# prompt about key expiration if not specified
-keyExpire=$(get_gpg_expiration "$keyExpire")
-
-echo "The following key parameters will be used for the host private key:"
-echo "Import: $keyFile"
-echo "Name-Real: $userID"
-echo "Expire-Date: $keyExpire"
-
-read -p "Import key? (Y/n) " OK; OK=${OK:=Y}
-if [ ${OK/y/Y} != 'Y' ] ; then
-       failure "aborting."
-fi
-
-log verbose "importing ssh key..."
-# translate ssh key to a private key
-(umask 077 && \
-       pem2openpgp "$userID" "$keyExpire" < "$sshKey" | gpg_host --import)
-
-# find the key fingerprint of the newly converted key
-fingerprint=$(fingerprint_server_key)
-
-# export host ownertrust to authentication keyring
-log verbose "setting ultimate owner trust for host key..."
-echo "${fingerprint}:6:" | gpg_host "--import-ownertrust"
-echo "${fingerprint}:6:" | gpg_authentication "--import-ownertrust"
-
-# export public key to file
-gpg_authentication "--export-options export-minimal --armor --export 0x${fingerprint}\!" > "${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
-log info "SSH host public key in OpenPGP form: ${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
-
-# show info about new key
-show_key
-
-}
diff --git a/src/subcommands/mh/publish_key b/src/subcommands/mh/publish_key
deleted file mode 100644 (file)
index b7ab01d..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host publish-key subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL, version 3
-# or later.
-
-# publish server key to keyserver
-
-publish_key() {
-
-read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
-if [ ${OK/y/Y} != 'Y' ] ; then
-    failure "key not published."
-fi
-
-# find the key fingerprint
-fingerprint=$(fingerprint_server_key)
-
-# publish host key
-# FIXME: need to define how to do this
-#gpg_authentication "--keyserver $KEYSERVER --send-keys '0x${fingerprint}!'"
-echo "not published!!!"
-
-}
diff --git a/src/subcommands/mh/revoke_hostname b/src/subcommands/mh/revoke_hostname
deleted file mode 100644 (file)
index b519cf6..0000000
+++ /dev/null
@@ -1,91 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host revoke-hostname subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# revoke hostname user ID from host key
-
-revoke_hostname() {
-
-local userID
-local fingerprint
-local tmpuidMatch
-local line
-local uidIndex
-local message
-local revuidCommand
-
-if [ -z "$1" ] ; then
-    failure "You must specify a hostname to revoke."
-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 "Please see the following bug report for more information:"
-echo "http://web.monkeysphere.info/bugs/revoke-hostname-revoking-wrong-userid/"
-read -p "Are you sure you would like to proceed? (y/N) " OK; OK=${OK:=N}
-if [ ${OK/y/Y} != 'Y' ] ; then
-    failure "aborting."
-fi
-
-userID="ssh://${1}"
-
-fingerprint=$(fingerprint_server_key)
-
-# match to only ultimately trusted user IDs
-tmpuidMatch="u:$(echo $userID | gpg_escape)"
-
-# find the index of the requsted user ID
-# NOTE: this is based on circumstantial evidence that the order of
-# this output is the appropriate index
-if line=$(gpg_host --list-keys --with-colons --fixed-list-mode "0x${fingerprint}!" \
-    | egrep '^(uid|uat):' | cut -f2,10 -d: | grep -n -x -F "$tmpuidMatch") ; then
-    uidIndex=${line%%:*}
-else
-    failure "No non-revoked user ID '$userID' is found."
-fi
-
-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
-    failure "User ID not revoked."
-fi
-
-message="Hostname removed by monkeysphere-server $DATE"
-
-# edit-key script command to revoke user ID
-revuidCommand=$(cat <<EOF
-$uidIndex
-revuid
-y
-4
-$message
-
-y
-save
-EOF
-    )  
-
-# execute edit-key script
-if echo "$revuidCommand" | \
-    gpg_host --quiet --command-fd 0 --edit-key "0x${fingerprint}!" ; then
-
-    show_key
-
-    echo
-    echo "NOTE: User ID revoked, but revocation not published."
-    echo "Run '$PGRM publish-key' to publish the revocation."
-else
-    failure "Problem revoking user ID."
-fi
-
-}
diff --git a/src/subcommands/mh/revoke_key b/src/subcommands/mh/revoke_key
deleted file mode 100644 (file)
index cccdc22..0000000
+++ /dev/null
@@ -1,21 +0,0 @@
-# -*-shell-script-*-
-# This should be sourced by bash (though we welcome changes to make it POSIX sh compliant)
-
-# Monkeysphere host revoke-key subcommand
-#
-# The monkeysphere scripts are written by:
-# Jameson Rollins <jrollins@finestructure.net>
-# Jamie McClelland <jm@mayfirst.org>
-# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
-#
-# They are Copyright 2008-2009, and are all released under the GPL,
-# version 3 or later.
-
-# revoke host key
-
-revoke_key() {
-
-# FIXME: implement!
-failure "not implemented yet!"
-
-}