summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rwxr-xr-xsrc/monkeysphere168
-rwxr-xr-xsrc/monkeysphere-authentication49
-rwxr-xr-xsrc/monkeysphere-host79
-rw-r--r--src/share/common110
-rw-r--r--src/share/m/gen_subkey83
-rw-r--r--src/share/m/import_subkey72
-rw-r--r--src/share/m/ssh_proxycommand39
-rw-r--r--src/share/m/subkey_to_ssh_agent15
-rw-r--r--src/share/ma/add_certifier125
-rw-r--r--src/share/ma/diagnostics18
-rw-r--r--src/share/ma/list_certifiers1
-rw-r--r--src/share/ma/remove_certifier2
-rw-r--r--src/share/ma/setup27
-rw-r--r--src/share/ma/update_users2
-rw-r--r--src/share/mh/add_hostname4
-rw-r--r--src/share/mh/add_revoker132
-rw-r--r--src/share/mh/diagnostics37
-rw-r--r--src/share/mh/import_key27
-rw-r--r--src/share/mh/publish_key8
-rw-r--r--src/share/mh/revoke_hostname6
-rw-r--r--src/share/mh/revoke_key28
-rw-r--r--src/share/mh/set_expire2
-rwxr-xr-xsrc/transition_0.22_0.2369
-rwxr-xr-xsrc/transitions/0.23180
-rw-r--r--src/transitions/README.txt16
25 files changed, 791 insertions, 508 deletions
diff --git a/src/monkeysphere b/src/monkeysphere
index da5f406..a65cef6 100755
--- a/src/monkeysphere
+++ b/src/monkeysphere
@@ -45,12 +45,8 @@ Monkeysphere client tool.
subcommands:
update-known_hosts (k) [HOST]... update known_hosts file
update-authorized_keys (a) update authorized_keys file
- import-subkey (i) import existing ssh key as gpg subkey
- --keyfile (-f) FILE key file to import
- --expire (-e) EXPIRE date to expire
gen-subkey (g) [KEYID] generate an authentication subkey
--length (-l) BITS key length in bits (2048)
- --expire (-e) EXPIRE date to expire
ssh-proxycommand monkeysphere ssh ProxyCommand
subkey-to-ssh-agent (s) store authentication subkey in ssh-agent
version (v) show version number
@@ -59,45 +55,128 @@ subcommands:
EOF
}
+# user gpg command to define common options
+gpg_user() {
+ gpg --no-greeting --quiet --no-tty "$@"
+}
+
+# take a secret key ID and check that only zero or one ID is provided,
+# and that it corresponds to only a single secret key ID
+check_gpg_sec_key_id() {
+ local gpgSecOut
+
+ case "$#" in
+ 0)
+ gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
+ ;;
+ 1)
+ gpgSecOut=$(gpg_user --fixed-list-mode --list-secret-keys --with-colons "$keyID" | egrep '^sec:') || failure
+ ;;
+ *)
+ failure "You must specify only a single primary key ID."
+ ;;
+ esac
+
+ # check that only a single secret key was found
+ case $(echo "$gpgSecOut" | grep -c '^sec:') in
+ 0)
+ failure "No secret keys found. Create an OpenPGP key with the following command:
+ gpg --gen-key"
+ ;;
+ 1)
+ echo "$gpgSecOut" | cut -d: -f5
+ ;;
+ *)
+ echo "Multiple primary secret keys found:" | log error
+ echo "$gpgSecOut" | cut -d: -f5 | log error
+ echo "Please specify which primary key to use." | log error
+ failure
+ ;;
+ esac
+}
+
+# check that a valid authentication subkey does not already exist
+check_gpg_authentication_subkey() {
+ local keyID
+ local IFS
+ local line
+ local type
+ local validity
+ local usage
+
+ keyID="$1"
+
+ # check that a valid authentication key does not already exist
+ IFS=$'\n'
+ for line in $(gpg_user --fixed-list-mode --list-keys --with-colons "$keyID") ; do
+ type=$(echo "$line" | cut -d: -f1)
+ validity=$(echo "$line" | cut -d: -f2)
+ usage=$(echo "$line" | cut -d: -f12)
+
+ # look at keys only
+ if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
+ continue
+ fi
+ # check for authentication capability
+ if ! check_capability "$usage" 'a' ; then
+ continue
+ fi
+ # if authentication key is valid, prompt to continue
+ if [ "$validity" = 'u' ] ; then
+ echo "A valid authentication key already exists for primary key '$keyID'."
+ if [ "$PROMPT" = "true" ] ; then
+ read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
+ failure "aborting."
+ fi
+ break
+ else
+ failure "aborting."
+ fi
+ fi
+ done
+}
+
########################################################################
# MAIN
########################################################################
-# unset variables that should be defined only in config file
-unset KEYSERVER
+# set unset default variables
+GNUPGHOME=${GNUPGHOME:="${HOME}/.gnupg"}
+KNOWN_HOSTS="${HOME}/.ssh/known_hosts"
+HASH_KNOWN_HOSTS="true"
+AUTHORIZED_KEYS="${HOME}/.ssh/authorized_keys"
+
+# unset the check keyserver variable, since that needs to have
+# different defaults for the different functions
unset CHECK_KEYSERVER
-unset KNOWN_HOSTS
-unset HASH_KNOWN_HOSTS
-unset AUTHORIZED_KEYS
# load global config
-[ -r "${SYSCONFIGDIR}/monkeysphere.conf" ] && . "${SYSCONFIGDIR}/monkeysphere.conf"
+[ -r "${SYSCONFIGDIR}/monkeysphere.conf" ] \
+ && . "${SYSCONFIGDIR}/monkeysphere.conf"
# set monkeysphere home directory
MONKEYSPHERE_HOME=${MONKEYSPHERE_HOME:="${HOME}/.monkeysphere"}
mkdir -p -m 0700 "$MONKEYSPHERE_HOME"
# load local config
-[ -e ${MONKEYSPHERE_CONFIG:="${MONKEYSPHERE_HOME}/monkeysphere.conf"} ] && . "$MONKEYSPHERE_CONFIG"
-
-# set empty config variables with ones from the environment, or from
-# config file, or with defaults
-LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
-GNUPGHOME=${MONKEYSPHERE_GNUPGHOME:=${GNUPGHOME:="${HOME}/.gnupg"}}
-KEYSERVER=${MONKEYSPHERE_KEYSERVER:="$KEYSERVER"}
-# if keyserver not specified in env or monkeysphere.conf,
-# look in gpg.conf
+[ -e ${MONKEYSPHERE_CONFIG:="${MONKEYSPHERE_HOME}/monkeysphere.conf"} ] \
+ && . "$MONKEYSPHERE_CONFIG"
+
+# set empty config variables with ones from the environment
+GNUPGHOME=${MONKEYSPHERE_GNUPGHOME:=$GNUPGHOME}
+LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=$LOG_LEVEL}
+KEYSERVER=${MONKEYSPHERE_KEYSERVER:=$KEYSERVER}
+# if keyserver not specified in env or conf, then look in gpg.conf
if [ -z "$KEYSERVER" ] ; then
if [ -f "${GNUPGHOME}/gpg.conf" ] ; then
KEYSERVER=$(grep -e "^[[:space:]]*keyserver " "${GNUPGHOME}/gpg.conf" | tail -1 | awk '{ print $2 }')
fi
fi
-# if it's still not specified, use the default
-KEYSERVER=${KEYSERVER:="subkeys.pgp.net"}
-CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=${CHECK_KEYSERVER:="true"}}
-KNOWN_HOSTS=${MONKEYSPHERE_KNOWN_HOSTS:=${KNOWN_HOSTS:="${HOME}/.ssh/known_hosts"}}
-HASH_KNOWN_HOSTS=${MONKEYSPHERE_HASH_KNOWN_HOSTS:=${HASH_KNOWN_HOSTS:="true"}}
-AUTHORIZED_KEYS=${MONKEYSPHERE_AUTHORIZED_KEYS:=${AUTHORIZED_KEYS:="${HOME}/.ssh/authorized_keys"}}
+PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT}
+KNOWN_HOSTS=${MONKEYSPHERE_KNOWN_HOSTS:=$KNOWN_HOSTS}
+HASH_KNOWN_HOSTS=${MONKEYSPHERE_HASH_KNOWN_HOSTS:=$HASH_KNOWN_HOSTS}
+AUTHORIZED_KEYS=${MONKEYSPHERE_AUTHORIZED_KEYS:=$AUTHORIZED_KEYS}
# other variables not in config file
AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:="${MONKEYSPHERE_HOME}/authorized_user_ids"}
@@ -117,49 +196,26 @@ shift
case $COMMAND in
'update-known_hosts'|'update-known-hosts'|'k')
- MODE='known_hosts'
-
- # touch the known_hosts file so that the file permission check
- # below won't fail upon not finding the file
- (umask 0022 && touch "$KNOWN_HOSTS")
-
- # check permissions on the known_hosts file path
- check_key_file_permissions "$USER" "$KNOWN_HOSTS" || failure
+ # whether or not to check keyservers
+ CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=${CHECK_KEYSERVER:="true"}}
- # if hosts are specified on the command line, process just
- # those hosts
+ # if hosts are specified on the command line, process just
+ # those hosts
if [ "$1" ] ; then
update_known_hosts "$@"
RETURN="$?"
- # otherwise, if no hosts are specified, process every host
- # in the user's known_hosts file
+ # otherwise, if no hosts are specified, process every host
+ # in the user's known_hosts file
else
- # exit if the known_hosts file does not exist
- if [ ! -e "$KNOWN_HOSTS" ] ; then
- log error "known_hosts file '$KNOWN_HOSTS' does not exist."
- exit
- fi
-
process_known_hosts
RETURN="$?"
fi
;;
'update-authorized_keys'|'update-authorized-keys'|'a')
- MODE='authorized_keys'
-
- # check permissions on the authorized_user_ids file path
- check_key_file_permissions "$USER" "$AUTHORIZED_USER_IDS" || failure
-
- # check permissions on the authorized_keys file path
- check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure
-
- # exit if the authorized_user_ids file is empty
- if [ ! -e "$AUTHORIZED_USER_IDS" ] ; then
- log error "authorized_user_ids file '$AUTHORIZED_USER_IDS' does not exist."
- exit
- fi
+ # whether or not to check keyservers
+ CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=${CHECK_KEYSERVER:="true"}}
# process authorized_user_ids file
process_authorized_user_ids "$AUTHORIZED_USER_IDS"
diff --git a/src/monkeysphere-authentication b/src/monkeysphere-authentication
index 8a4146f..497470d 100755
--- a/src/monkeysphere-authentication
+++ b/src/monkeysphere-authentication
@@ -56,7 +56,8 @@ Monkeysphere authentication admin tool.
subcommands:
update-users (u) [USER]... update user authorized_keys files
- add-id-certifier (c+) KEYID import and tsign a certification key
+
+ add-id-certifier (c+) [KEYID|FILE] import and tsign a certification key
--domain (-n) DOMAIN limit ID certifications to DOMAIN
--trust (-t) TRUST trust level of certifier (full)
--depth (-d) DEPTH trust depth for certifier (1)
@@ -75,7 +76,7 @@ gpg_core() {
GNUPGHOME="$GNUPGHOME_CORE"
export GNUPGHOME
- gpg "$@"
+ gpg --no-greeting --quiet --no-tty "$@"
}
# function to interact with the gpg sphere keyring
@@ -84,16 +85,16 @@ gpg_core() {
gpg_sphere() {
GNUPGHOME="$GNUPGHOME_SPHERE"
export GNUPGHOME
-
- su_monkeysphere_user "gpg $@"
+
+ su_monkeysphere_user "gpg --no-greeting --quiet --no-tty $@"
}
# output to stdout the core fingerprint from the gpg core secret
# keyring
core_fingerprint() {
log debug "determining core key fingerprint..."
- gpg_core --quiet --list-secret-key \
- --with-colons --fixed-list-mode --with-fingerprint \
+ gpg_core --list-secret-key --with-colons \
+ --fixed-list-mode --with-fingerprint \
| grep ^fpr: | cut -d: -f10
}
@@ -101,37 +102,31 @@ core_fingerprint() {
gpg_core_sphere_sig_transfer() {
log debug "exporting core local sigs to sphere..."
gpg_core --export-options export-local-sigs --export | \
- gpg_sphere "--import-options import-local-sigs --import" \
- 2>&1 | log debug
+ gpg_sphere "--import-options import-local-sigs --import"
}
########################################################################
# MAIN
########################################################################
-# unset variables that should be defined only in config file of in
-# MONKEYSPHERE_ variables
-unset LOG_LEVEL
-unset KEYSERVER
-unset AUTHORIZED_USER_IDS
-unset RAW_AUTHORIZED_KEYS
-unset MONKEYSPHERE_USER
-unset PROMPT
+# set unset default variables
+AUTHORIZED_USER_IDS="%h/.monkeysphere/authorized_user_ids"
+RAW_AUTHORIZED_KEYS="%h/.ssh/authorized_keys"
# load configuration file
-[ -e ${MONKEYSPHERE_AUTHENTICATION_CONFIG:="${SYSCONFIGDIR}/monkeysphere-authentication.conf"} ] && . "$MONKEYSPHERE_AUTHENTICATION_CONFIG"
-
-# set empty config variable with ones from the environment, or with
-# defaults
-LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
-KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
-AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=${AUTHORIZED_USER_IDS:="%h/.monkeysphere/authorized_user_ids"}}
-RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=${RAW_AUTHORIZED_KEYS:="%h/.ssh/authorized_keys"}}
-MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
-PROMPT=${MONKEYSPHERE_PROMPT:=${PROMPT:="true"}}
+[ -e ${MONKEYSPHERE_AUTHENTICATION_CONFIG:="${SYSCONFIGDIR}/monkeysphere-authentication.conf"} ] \
+ && . "$MONKEYSPHERE_AUTHENTICATION_CONFIG"
+
+# set empty config variable with ones from the environment
+LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=$LOG_LEVEL}
+KEYSERVER=${MONKEYSPHERE_KEYSERVER:=$KEYSERVER}
+CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER}
+MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=$MONKEYSPHERE_USER}
+PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT}
+AUTHORIZED_USER_IDS=${MONKEYSPHERE_AUTHORIZED_USER_IDS:=$AUTHORIZED_USER_IDS}
+RAW_AUTHORIZED_KEYS=${MONKEYSPHERE_RAW_AUTHORIZED_KEYS:=$RAW_AUTHORIZED_KEYS}
# other variables
-CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
REQUIRED_USER_KEY_CAPABILITY=${MONKEYSPHERE_REQUIRED_USER_KEY_CAPABILITY:="a"}
GNUPGHOME_CORE=${MONKEYSPHERE_GNUPGHOME_CORE:="${MADATADIR}/core"}
GNUPGHOME_SPHERE=${MONKEYSPHERE_GNUPGHOME_SPHERE:="${MADATADIR}/sphere"}
diff --git a/src/monkeysphere-host b/src/monkeysphere-host
index c7e011b..4c7df88 100755
--- a/src/monkeysphere-host
+++ b/src/monkeysphere-host
@@ -32,10 +32,6 @@ MHSHAREDIR="${SYSSHAREDIR}/mh"
# datadir for host functions
MHDATADIR="${SYSDATADIR}/host"
-# temp directory for temp gnupghome directories for add_revoker
-MHTMPDIR="${MHDATADIR}/tmp"
-export MHTMPDIR
-
# host pub key files
HOST_KEY_FILE="${SYSDATADIR}/ssh_host_rsa_key.pub.gpg"
@@ -58,16 +54,15 @@ usage: $PGRM <subcommand> [options] [args]
Monkeysphere host admin tool.
subcommands:
+ import-key (i) FILE [NAME[:PORT]] import existing ssh key to gpg
show-key (s) output all host key information
- set-expire (e) EXPIRE set host key expiration
+ set-expire (e) [EXPIRE] set host key expiration
add-hostname (n+) NAME[:PORT] add hostname user ID to host key
revoke-hostname (n-) NAME[:PORT] revoke hostname user ID
- add-revoker (o) FINGERPRINT add a revoker to the host key
+ add-revoker (o) [KEYID|FILE] add a revoker to the host key
revoke-key (r) revoke host key
publish-key (p) publish host key to keyserver
- import-key (i) [NAME[:PORT]] import existing ssh key to gpg
-
version (v) show version number
help (h,?) this help
@@ -77,7 +72,7 @@ EOF
# function to interact with the gpg keyring
gpg_host() {
- GNUPGHOME="$GNUPGHOME_HOST" gpg "$@"
+ GNUPGHOME="$GNUPGHOME_HOST" gpg --no-greeting --quiet --no-tty "$@"
}
# command to list the info about the host key, in colon format, to
@@ -90,12 +85,8 @@ gpg_host_list() {
}
# command for edit key scripts, takes scripts on stdin
-# FIXME: should we supress all the edit script spew? or pipe it
-# through log debug?
gpg_host_edit() {
- gpg_host --no-greeting --quiet \
- --command-fd 0 --no-tty --edit-key \
- "0x${HOST_FINGERPRINT}!" "$@" 2>&1 | log debug
+ gpg_host --command-fd 0 --edit-key "0x${HOST_FINGERPRINT}!" "$@"
}
# export the host public key to the monkeysphere gpg pub key file
@@ -119,7 +110,7 @@ load_fingerprint() {
&& rm -rf "$FUBAR") <"$HOST_KEY_FILE" \
| grep '^fpr:' | cut -d: -f10 )
else
- HOST_FINGERPRINT=
+ failure "host key gpg pub file not found."
fi
}
@@ -127,8 +118,7 @@ load_fingerprint() {
# gpg host secret key
load_fingerprint_secret() {
HOST_FINGERPRINT=$( \
- gpg_host --quiet --list-secret-key \
- --with-colons --with-fingerprint \
+ gpg_host --list-secret-key --with-colons --with-fingerprint \
| grep '^fpr:' | cut -d: -f10 )
}
@@ -142,7 +132,7 @@ check_host_key() {
check_host_no_key() {
[ -s "$HOST_KEY_FILE" ] \
|| failure "You don't appear to have a Monkeysphere host key on this server.
-Please run 'monkeysphere-host import-key' first."
+Please run 'monkeysphere-host import-key...' first."
}
# output the index of a user ID on the host key
@@ -174,7 +164,7 @@ show_key() {
local GNUPGHOME
# tmp gpghome dir
- export GNUPGHOME=$(mktemp -d)
+ export GNUPGHOME=$(msmktempdir)
# trap to remove tmp dir if break
trap "rm -rf $GNUPGHOME" EXIT
@@ -182,6 +172,11 @@ show_key() {
# import the host key into the tmp dir
gpg --quiet --import <"$HOST_KEY_FILE"
+ # create the ssh key
+ TMPSSH="$GNUPGHOME"/ssh_host_key_rsa_pub
+ openpgp2ssh <"$HOST_KEY_FILE" 2>/dev/null >"$TMPSSH"
+
+ # get the gpg fingerprint
HOST_FINGERPRINT=$(gpg --quiet --list-keys --with-colons --with-fingerprint \
| grep '^fpr:' | cut -d: -f10 )
@@ -198,9 +193,7 @@ show_key() {
# list the ssh fingerprint
echo -n "ssh fingerprint: "
- ssh-keygen -l -f /dev/stdin \
- <<<$(openpgp2ssh <"$HOST_KEY_FILE" 2>/dev/null) \
- | awk '{ print $1, $2, $4 }'
+ ssh-keygen -l -f "$TMPSSH" | awk '{ print $1, $2, $4 }'
# remove the tmp file
trap - EXIT
@@ -211,38 +204,31 @@ show_key() {
# MAIN
########################################################################
-# unset variables that should be defined only in config file or in
-# MONKEYSPHERE_ variables
-unset LOG_LEVEL
-unset KEYSERVER
-unset MONKEYSPHERE_USER
-unset PROMPT
-
# load configuration file
-[ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] && . "$MONKEYSPHERE_HOST_CONFIG"
+[ -e ${MONKEYSPHERE_HOST_CONFIG:="${SYSCONFIGDIR}/monkeysphere-host.conf"} ] \
+ && . "$MONKEYSPHERE_HOST_CONFIG"
# set empty config variable with ones from the environment, or with
# defaults
-LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=${LOG_LEVEL:="INFO"}}
-KEYSERVER=${MONKEYSPHERE_KEYSERVER:=${KEYSERVER:="pool.sks-keyservers.net"}}
-MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=${MONKEYSPHERE_USER:="monkeysphere"}}
-PROMPT=${MONKEYSPHERE_PROMPT:=${PROMPT:="true"}}
+LOG_LEVEL=${MONKEYSPHERE_LOG_LEVEL:=$LOG_LEVEL}
+KEYSERVER=${MONKEYSPHERE_KEYSERVER:=$KEYSERVER}
+CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER}
+MONKEYSPHERE_USER=${MONKEYSPHERE_MONKEYSPHERE_USER:=$MONKEYSPHERE_USER}
+PROMPT=${MONKEYSPHERE_PROMPT:=$PROMPT}
# other variables
-CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="true"}
GNUPGHOME_HOST=${MONKEYSPHERE_GNUPGHOME_HOST:="${MHDATADIR}"}
# export variables needed in su invocation
export DATE
-export MODE
export LOG_LEVEL
export KEYSERVER
+export CHECK_KEYSERVER
export MONKEYSPHERE_USER
export PROMPT
-export CHECK_KEYSERVER
export GNUPGHOME_HOST
export GNUPGHOME
-export HOST_FINGERPRINT=
+export HOST_FINGERPRINT
# get subcommand
COMMAND="$1"
@@ -250,6 +236,12 @@ COMMAND="$1"
shift
case $COMMAND in
+ 'import-key'|'i')
+ check_host_key
+ source "${MHSHAREDIR}/import_key"
+ import_key "$@"
+ ;;
+
'show-key'|'show'|'s')
check_host_no_key
show_key
@@ -297,18 +289,17 @@ case $COMMAND in
publish_key
;;
- 'import-key'|'i')
- check_host_key
- source "${MHSHAREDIR}/import_key"
- import_key "$@"
- ;;
-
'diagnostics'|'d')
load_fingerprint
source "${MHSHAREDIR}/diagnostics"
diagnostics
;;
+ 'update-gpg-pub-file')
+ load_fingerprint_secret
+ update_gpg_pub_file
+ ;;
+
'version'|'v')
echo "$VERSION"
;;
diff --git a/src/share/common b/src/share/common
index 4120259..653d58b 100644
--- a/src/share/common
+++ b/src/share/common
@@ -8,7 +8,7 @@
# Jamie McClelland <jm@mayfirst.org>
# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
#
-# Copyright 2008, released under the GPL, version 3 or later
+# Copyright 2008-2009, released under the GPL, version 3 or later
# all-caps variables are meant to be user supplied (ie. from config
# file) and are considered global
@@ -21,7 +21,22 @@ SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"}
export SYSCONFIGDIR
# monkeysphere version
-VERSION=__VERSION__
+VERSION=0.23~pre
+
+# default log level
+LOG_LEVEL="INFO"
+
+# default keyserver
+KEYSERVER="pool.sks-keyservers.net"
+
+# whether or not to check keyservers by defaul
+CHECK_KEYSERVER="true"
+
+# default monkeysphere user
+MONKEYSPHERE_USER="monkeysphere"
+
+# default about whether or not to prompt
+PROMPT="true"
########################################################################
### UTILITY FUNCTIONS
@@ -134,6 +149,16 @@ cutline() {
head --line="$1" "$2" | tail -1
}
+# make a temporary directory
+msmktempdir() {
+ mktemp -d ${TMPDIR:-/tmp}/monkeysphere.XXXXXXXXXX
+}
+
+# make a temporary file
+msmktempfile() {
+ mktemp ${TMPDIR:-/tmp}/monkeysphere.XXXXXXXXXX
+}
+
# this is a wrapper for doing lock functions.
#
# it lets us depend on either lockfile-progs (preferred) or procmail's
@@ -271,7 +296,7 @@ get_gpg_expiration() {
keyExpire="$1"
- if [ -z "$keyExpire" ]; then
+ if [ -z "$keyExpire" -a "$PROMPT" = 'true' ]; then
cat >&2 <<EOF
Please specify how long the key should be valid.
0 = key does not expire
@@ -795,6 +820,9 @@ process_host_known_hosts() {
local sshKey
local tmpfile
+ # set the key processing mode
+ export MODE='known_hosts'
+
host="$1"
userID="ssh://${host}"
@@ -874,6 +902,13 @@ update_known_hosts() {
nHostsOK=0
nHostsBAD=0
+ # touch the known_hosts file so that the file permission check
+ # below won't fail upon not finding the file
+ (umask 0022 && touch "$KNOWN_HOSTS")
+
+ # check permissions on the known_hosts file path
+ check_key_file_permissions "$USER" "$KNOWN_HOSTS" || failure
+
# create a lockfile on known_hosts:
lock create "$KNOWN_HOSTS"
# FIXME: we're discarding any pre-existing EXIT trap; is this bad?
@@ -928,6 +963,11 @@ update_known_hosts() {
process_known_hosts() {
local hosts
+ # exit if the known_hosts file does not exist
+ if [ ! -e "$KNOWN_HOSTS" ] ; then
+ failure "known_hosts file '$KNOWN_HOSTS' does not exist."
+ fi
+
log debug "processing known_hosts file..."
hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ')
@@ -951,6 +991,9 @@ process_uid_authorized_keys() {
local ok
local sshKey
+ # set the key processing mode
+ export MODE='authorized_keys'
+
userID="$1"
log verbose "processing: $userID"
@@ -1012,6 +1055,9 @@ update_authorized_keys() {
nIDsOK=0
nIDsBAD=0
+ # check permissions on the authorized_keys file path
+ check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure
+
# create a lockfile on authorized_keys
lock create "$AUTHORIZED_KEYS"
# FIXME: we're discarding any pre-existing EXIT trap; is this bad?
@@ -1077,6 +1123,14 @@ process_authorized_user_ids() {
authorizedUserIDs="$1"
+ # exit if the authorized_user_ids file is empty
+ if [ ! -e "$authorizedUserIDs" ] ; then
+ failure "authorized_user_ids file '$authorizedUserIDs' does not exist."
+ fi
+
+ # check permissions on the authorized_user_ids file path
+ check_key_file_permissions "$USER" "$authorizedUserIDs" || failure
+
log debug "processing authorized_user_ids file..."
if ! meat "$authorizedUserIDs" > /dev/null ; then
@@ -1095,3 +1149,53 @@ process_authorized_user_ids() {
update_authorized_keys "${userIDs[@]}"
}
+
+# takes a gpg key or keys on stdin, and outputs a list of
+# fingerprints, one per line:
+list_primary_fingerprints() {
+ local fake=$(msmktempdir)
+ GNUPGHOME="$fake" gpg --no-tty --quiet --import
+ GNUPGHOME="$fake" gpg --with-colons --fingerprint --list-keys | \
+ awk -F: '/^fpr:/{ print $10 }'
+ rm -rf "$fake"
+}
+
+
+check_cruft_file() {
+ local loc="$1"
+ local version="$2"
+
+ if [ -e "$loc" ] ; then
+ printf "! The file '%s' is no longer used by\n monkeysphere (as of version %s), and can be removed.\n\n" "$loc" "$version" | log info
+ fi
+}
+
+check_upgrade_dir() {
+ local loc="$1"
+ local version="$2"
+
+ if [ -d "$loc" ] ; then
+ printf "The presence of directory '%s' indicates that you have\nnot yet completed a monkeysphere upgrade.\nYou should probably run the following script:\n %s/transitions/%s\n\n" "$loc" "$SYSSHAREDIR" "$version" | log info
+ fi
+}
+
+## look for cruft from old versions of the monkeysphere, and notice if
+## upgrades have not been run:
+report_cruft() {
+ check_upgrade_dir "${SYSCONFIGDIR}/gnupg-host" 0.23
+ check_upgrade_dir "${SYSCONFIGDIR}/gnupg-authentication" 0.23
+
+ check_cruft_file "${SYSCONFIGDIR}/gnupg-authentication.conf" 0.23
+ check_cruft_file "${SYSCONFIGDIR}/gnupg-host.conf" 0.23
+
+ local found=
+ for foo in "${SYSDATADIR}/backup-from-"*"-transition" ; do
+ if [ -d "$foo" ] ; then
+ printf "! %s\n" "$foo" | log info
+ found=true
+ fi
+ done
+ if [ "$found" ] ; then
+ printf "The directories above are backups left over from a monkeysphere transition.\nThey may contain copies of sensitive data (host keys, certifier lists), but\nthey are no longer needed by monkeysphere.\nYou may remove them at any time.\n\n" | log info
+ fi
+}
diff --git a/src/share/m/gen_subkey b/src/share/m/gen_subkey
index cbefaa3..dbd9dd6 100644
--- a/src/share/m/gen_subkey
+++ b/src/share/m/gen_subkey
@@ -15,10 +15,10 @@
gen_subkey(){
local keyLength
- local keyExpire
+ local gpgSecOut
local keyID
- local gpgOut
- local userID
+ local editCommands
+ local fifoDir
# get options
while true ; do
@@ -27,10 +27,6 @@ gen_subkey(){
keyLength="$2"
shift 2
;;
- -e|--expire)
- keyExpire="$2"
- shift 2
- ;;
*)
if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
failure "Unknown option '$1'.
@@ -41,63 +37,11 @@ Type '$PGRM help' for usage."
esac
done
- case "$#" in
- 0)
- gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:')
- ;;
- 1)
- gpgSecOut=$(gpg --quiet --fixed-list-mode --list-secret-keys --with-colons "$1" | egrep '^sec:') || failure
- ;;
- *)
- failure "You must specify only a single primary key ID."
- ;;
- esac
-
- # check that only a single secret key was found
- case $(echo "$gpgSecOut" | grep -c '^sec:') in
- 0)
- failure "No secret keys found. Create an OpenPGP key with the following command:
- gpg --gen-key"
- ;;
- 1)
- keyID=$(echo "$gpgSecOut" | cut -d: -f5)
- ;;
- *)
- echo "Multiple primary secret keys found:"
- echo "$gpgSecOut" | cut -d: -f5
- failure "Please specify which primary key to use."
- ;;
- esac
+ # check that the keyID is unique
+ keyID=$(check_gpg_sec_key_id "$@")
- # check that a valid authentication key does not already exist
- IFS=$'\n'
- for line in $(gpg --quiet --fixed-list-mode --list-keys --with-colons "$keyID") ; do
- type=$(echo "$line" | cut -d: -f1)
- validity=$(echo "$line" | cut -d: -f2)
- usage=$(echo "$line" | cut -d: -f12)
-
- # look at keys only
- if [ "$type" != 'pub' -a "$type" != 'sub' ] ; then
- continue
- fi
- # check for authentication capability
- if ! check_capability "$usage" 'a' ; then
- continue
- fi
- # if authentication key is valid, prompt to continue
- if [ "$validity" = 'u' ] ; then
- echo "A valid authentication key already exists for primary key '$keyID'."
- read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N}
- if [ "${OK/y/Y}" != 'Y' ] ; then
- failure "aborting."
- fi
- break
- fi
- done
-
- # set subkey defaults
- # prompt about key expiration if not specified
- keyExpire=$(get_gpg_expiration "$keyExpire")
+ # check that an authentication subkey does not already exist
+ check_gpg_authentication_subkey "$keyID"
# generate the list of commands that will be passed to edit-key
editCommands=$(cat <<EOF
@@ -108,19 +52,24 @@ E
A
Q
$keyLength
-$keyExpire
+0
save
EOF
)
- log verbose "generating subkey..."
- fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+ # setup the temp fifo dir for retrieving the key password
+ log debug "creating password fifo..."
+ fifoDir=$(msmktempdir)
+ trap "rm -rf $fifoDir" EXIT
(umask 077 && mkfifo "$fifoDir/pass")
- echo "$editCommands" | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
+
+ log verbose "generating subkey..."
+ echo "$editCommands" | gpg_user --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --edit-key "$keyID" &
# FIXME: this needs to fail more gracefully if the passphrase is incorrect
passphrase_prompt "Please enter your passphrase for $keyID: " "$fifoDir/pass"
+ trap - EXIT
rm -rf "$fifoDir"
wait
log verbose "done."
diff --git a/src/share/m/import_subkey b/src/share/m/import_subkey
index aa89958..8d60f26 100644
--- a/src/share/m/import_subkey
+++ b/src/share/m/import_subkey
@@ -13,41 +13,55 @@
# import an existing ssh key as a gpg subkey
+## 2009-02-20 00:49:11-0500: This is not implemented yet, because we
+## don't currently have a good way to manipulate the user's OpenPGP
+## secret key such that we could make a proper subkey binding
+## signature.
+
import_subkey() {
- local keyFile="~/.ssh/id_rsa"
- local keyExpire
+ local sshKeyFile
local keyID
- local gpgOut
- local userID
-
- # get options
- while true ; do
- case "$1" in
- -f|--keyfile)
- keyFile="$2"
- shift 2
- ;;
- -e|--expire)
- keyExpire="$2"
- shift 2
- ;;
- *)
- if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
- failure "Unknown option '$1'.
-Type '$PGRM help' for usage."
- fi
- break
- ;;
- esac
- done
-
- log verbose "importing ssh key..."
- fifoDir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+ local gpgSecOut
+ local fifoDir
+
+ # FIXME: implement!
+ failure "import-subkey is not implemented yet. We welcome patches. Sorry!"
+
+ sshKeyFile="$1"
+ shift
+
+ # check that key file specified
+ if [ -z "$sshKeyFile" ] ; then
+ failure "Must specify ssh key file to import, or specify '-' for stdin."
+ fi
+
+ # check that the keyID is unique
+ keyID=$(check_gpg_sec_key_id "$@")
+
+ # check that an authentication subkey does not already exist
+ check_gpg_authentication_subkey "$keyID"
+
+ # setup the temp fifo dir for retrieving the key password
+ log debug "creating password fifo..."
+ fifoDir=$(msmktempdir)
+ trap "rm -rf $fifoDir" EXIT
(umask 077 && mkfifo "$fifoDir/pass")
- ssh2openpgp | gpg --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+ # import ssh key to as authentication subkey
+ if [ "$sshKeyFile" = '-' ] ; then
+ log verbose "importing ssh key from stdin..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
+ | gpg_user --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+ else
+ log verbose "importing ssh key from file '$sshKeyFile'..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" <"$sshKeyFile" \
+ | gpg_user --passphrase-fd 3 3< "$fifoDir/pass" --expert --command-fd 0 --import &
+ fi
+
+ # get the password if needed
passphrase_prompt "Please enter your passphrase for $keyID: " "$fifoDir/pass"
+ trap - EXIT
rm -rf "$fifoDir"
wait
log verbose "done."
diff --git a/src/share/m/ssh_proxycommand b/src/share/m/ssh_proxycommand
index cd0a1fb..bd09588 100644
--- a/src/share/m/ssh_proxycommand
+++ b/src/share/m/ssh_proxycommand
@@ -15,8 +15,6 @@
# established. Can be added to ~/.ssh/config as follows:
# ProxyCommand monkeysphere ssh-proxycommand %h %p
-ssh_proxycommand() {
-
# "marginal case" ouput in the case that there is not a full
# validation path to the host
output_no_valid_key() {
@@ -45,7 +43,7 @@ EOF
# found?
# get the gpg info for userid
- gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \
+ gpgOut=$(gpg_user --list-key --fixed-list-mode --with-colon \
--with-fingerprint --with-fingerprint \
="$userID" 2>/dev/null)
@@ -66,14 +64,14 @@ An OpenPGP key matching the ssh key offered by the host was found:
EOF
- # do some crazy "Here Strings" redirection to get the key to
- # ssh-keygen, since it doesn't read from stdin cleanly
- sshFingerprint=$(ssh-keygen -l -f /dev/stdin \
- <<<$(echo "$sshKeyGPG") | \
+ sshKeyGPGFile=$(msmktempfile)
+ printf "%s" "$sshKeyGPG" >"$sshKeyGPGFile"
+ sshFingerprint=$(ssh-keygen -l -f "$sshKeyGPGFile" | \
awk '{ print $2 }')
+ rm -f "$sshKeyGPGFile"
# get the sigs for the matching key
- gpgSigOut=$(gpg --check-sigs \
+ gpgSigOut=$(gpg_user --check-sigs \
--list-options show-uid-validity \
"$keyid")
@@ -136,10 +134,9 @@ EOF
EOF
}
-########################################################################
-# export the monkeysphere log level
-export MONKEYSPHERE_LOG_LEVEL
+# the ssh proxycommand function itself
+ssh_proxycommand() {
if [ "$1" = '--no-connect' ] ; then
NO_CONNECT='true'
@@ -170,12 +167,13 @@ URI="ssh://${HOSTP}"
# intentionally different than that of running monkeyesphere normally,
# and keyserver checking is intentionally done under certain
# circumstances. This can be overridden by setting the
-# MONKEYSPHERE_CHECK_KEYSERVER environment variable.
+# MONKEYSPHERE_CHECK_KEYSERVER environment variable, or by setting the
+# CHECK_KEYSERVER variable in the monkeysphere.conf file.
# if the host is in the gpg keyring...
-if gpg --list-key ="${URI}" 2>&1 >/dev/null ; then
+if gpg_user --list-key ="${URI}" 2>&1 >/dev/null ; then
# do not check the keyserver
- CHECK_KEYSERVER="false"
+ CHECK_KEYSERVER=${CHECK_KEYSERVER:="false"}
# if the host is NOT in the keyring...
else
@@ -188,20 +186,21 @@ else
# FIXME: more nuanced checking should be done here to properly
# take into consideration hosts that join monkeysphere by
# converting an existing and known ssh key
- CHECK_KEYSERVER="false"
+ CHECK_KEYSERVER=${CHECK_KEYSERVER:="false"}
# if the host key is not found in the known_hosts file...
else
# check the keyserver
- CHECK_KEYSERVER="true"
+ CHECK_KEYSERVER=${CHECK_KEYSERVER:="true"}
fi
fi
-# set and export the variable for use by monkeysphere
-MONKEYSPHERE_CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:="$CHECK_KEYSERVER"}
-export MONKEYSPHERE_CHECK_KEYSERVER
+
+# finally look in the MONKEYSPHERE_ environment variable for a
+# CHECK_KEYSERVER setting to override all else
+CHECK_KEYSERVER=${MONKEYSPHERE_CHECK_KEYSERVER:=$CHECK_KEYSERVER}
# update the known_hosts file for the host
-monkeysphere update-known_hosts "$HOSTP"
+update_known_hosts "$HOSTP"
# output on depending on the return of the update-known_hosts
# subcommand, which is (ultimately) the return code of the
diff --git a/src/share/m/subkey_to_ssh_agent b/src/share/m/subkey_to_ssh_agent
index 012c95f..818f4f7 100644
--- a/src/share/m/subkey_to_ssh_agent
+++ b/src/share/m/subkey_to_ssh_agent
@@ -46,7 +46,8 @@ For more details, see:
# get list of secret keys (to work around bug
# https://bugs.g10code.com/gnupg/issue945):
- secretkeys=$(gpg --list-secret-keys --with-colons --fixed-list-mode --fingerprint | \
+ secretkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \
+ --fingerprint | \
grep '^fpr:' | cut -f10 -d: | awk '{ print "0x" $1 "!" }')
if [ -z "$secretkeys" ]; then
@@ -54,7 +55,7 @@ For more details, see:
You might want to run 'gpg --gen-key'."
fi
- authsubkeys=$(gpg --list-secret-keys --with-colons --fixed-list-mode \
+ authsubkeys=$(gpg_user --list-secret-keys --with-colons --fixed-list-mode \
--fingerprint --fingerprint $secretkeys | \
cut -f1,5,10,12 -d: | grep -A1 '^ssb:[^:]*::[^:]*a[^:]*$' | \
grep '^fpr::' | cut -f3 -d: | sort -u)
@@ -64,7 +65,8 @@ You might want to run 'gpg --gen-key'."
You might want to 'monkeysphere gen-subkey'"
fi
- workingdir=$(mktemp -d ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX)
+ workingdir=$(msmktempdir)
+ trap "rm -rf $workingdir" EXIT
umask 077
mkfifo "$workingdir/passphrase"
keysuccess=1
@@ -79,19 +81,19 @@ You might want to 'monkeysphere gen-subkey'"
# fingerprint, but filtering out all / characters to make sure
# the filename is legit.
- primaryuid=$(gpg --with-colons --list-key "0x${subkey}!" | grep '^pub:' | cut -f10 -d: | tr -d /)
+ primaryuid=$(gpg_user --with-colons --list-key "0x${subkey}!" | grep '^pub:' | cut -f10 -d: | tr -d /)
#kname="[monkeysphere] $primaryuid"
kname="$primaryuid"
if [ "$1" = '-d' ]; then
# we're removing the subkey:
- gpg --export "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname"
+ gpg_user --export "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname"
(cd "$workingdir" && ssh-add -d "$kname")
else
# we're adding the subkey:
mkfifo "$workingdir/$kname"
- gpg --quiet --passphrase-fd 3 3<"$workingdir/passphrase" \
+ gpg_user --passphrase-fd 3 3<"$workingdir/passphrase" \
--export-options export-reset-subkey-passwd,export-minimal,no-export-attributes \
--export-secret-subkeys "0x${subkey}!" | openpgp2ssh "$subkey" > "$workingdir/$kname" &
(cd "$workingdir" && DISPLAY=nosuchdisplay SSH_ASKPASS=/bin/false ssh-add "$@" "$kname" </dev/null )&
@@ -104,6 +106,7 @@ You might want to 'monkeysphere gen-subkey'"
rm -f "$workingdir/$kname"
done
+ trap - EXIT
rm -rf "$workingdir"
# FIXME: sort out the return values: we're just returning the
diff --git a/src/share/ma/add_certifier b/src/share/ma/add_certifier
index d34f0de..f2cadf2 100644
--- a/src/share/ma/add_certifier
+++ b/src/share/ma/add_certifier
@@ -31,7 +31,6 @@ local domain=
local trust=full
local depth=1
local keyID
-local importinfo
local fingerprint
local ltsignCommand
local trustval
@@ -51,6 +50,9 @@ while true ; do
depth="$2"
shift 2
;;
+ -)
+ break
+ ;;
*)
if [ "$(echo "$1" | cut -c 1)" = '-' ] ; then
failure "Unknown option '$1'.
@@ -62,67 +64,13 @@ Type '$PGRM help' for usage."
done
keyID="$1"
+
+# check that key ID or file is specified
if [ -z "$keyID" ] ; then
failure "You must specify the key ID of a key to add, or specify a file to read the key from."
fi
-if [ -f "$keyID" ] ; then
- log info "Reading key from file '$keyID':"
- importinfo=$(gpg_sphere "--import" < "$keyID" 2>&1) || failure "could not read key from '$keyID'"
- # FIXME: if this is tried when the key database is not
- # up-to-date, i got these errors (using set -x):
-
- # ++ su -m monkeysphere -c '\''gpg --import'\''
- # Warning: using insecure memory!
- # gpg: key D21739E9: public key "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" imported
- # gpg: Total number processed: 1
- # gpg: imported: 1 (RSA: 1)
- # gpg: can'\''t create `/var/monkeysphere/gnupg-host/pubring.gpg.tmp'\'': Permission denied
- # gpg: failed to rebuild keyring cache: Permission denied
- # gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
- # gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
- # gpg: next trustdb check due at 2009-01-10'
- # + failure 'could not read key from '\''/root/dkg.gpg'\'''
- # + echo 'could not read key from '\''/root/dkg.gpg'\'''
-
- keyID=$(echo "$importinfo" | grep '^gpg: key ' | cut -f2 -d: | cut -f3 -d\ )
- if [ -z "$keyID" ] || [ $(echo "$keyID" | wc -l) -ne 1 ] ; then
- failure "There was not exactly one gpg key in the file."
- fi
-else
- # get the key from the key server
- log debug "retrieving key from keyserver..."
- gpg_sphere "--keyserver $KEYSERVER --recv-key '0x${keyID}!'" || failure "Could not receive a key with this ID from the '$KEYSERVER' keyserver."
-fi
-
-export keyID
-
-# get the full fingerprint of new certifier key
-log debug "getting fingerprint of certifier key..."
-fingerprint=$(gpg_sphere "--list-key --with-colons --with-fingerprint 0x${keyID}!" \
- | grep '^fpr:' | grep "$keyID" | cut -d: -f10)
-
-if [ -z "$fingerprint" ] ; then
- failure "Key '$keyID' not found."
-fi
-
-log info "key found:"
-gpg_sphere "--fingerprint 0x${fingerprint}!"
-
-if [ "$PROMPT" = "true" ] ; then
- echo "Are you sure you want to add the above key as a"
- read -p "certifier of users on this system? (y/N) " OK; OK=${OK:-N}
- if [ "${OK/y/Y}" != 'Y' ] ; then
- failure "Identity certifier not added."
- fi
-else
- log debug "adding key without prompting."
-fi
-
-# export the key to the core keyring so that the core can sign the
-# new certifier key
-log debug "exporting retrieved certifier key to core keyring..."
-gpg_sphere "--export 0x${fingerprint}!" | gpg_core --import
+# check the trust value
case "$trust" in
'marginal')
trustval=1
@@ -135,6 +83,64 @@ case "$trust" in
;;
esac
+# if file is specified
+if [ -f "$keyID" -o "$keyID" = '-' ] ; then
+ # load the key from stdin
+ if [ "$keyID" = '-' ] ; then
+ # make a temporary file to hold the key from stdin
+ keyID=$(msmktempfile)
+ trap "rm -f $keyID" EXIT
+ log verbose "reading key from stdin..."
+ cat > "$keyID"
+
+ # load the key from the file
+ elif [ -f "$keyID" ] ; then
+ log verbose "reading key from file '$keyID'..."
+ fi
+
+ # check the key is ok as monkeysphere user before loading
+ log debug "checking keys in file..."
+ fingerprint=$(su_monkeysphere_user \
+ ". ${SYSSHAREDIR}/common; list_primary_fingerprints" < "$keyID")
+
+ if [ $(printf "%s" "$fingerprint" | egrep -c '^[A-F0-9]{40}$') -ne 1 ] ; then
+ failure "There was not exactly one gpg key in the file."
+ fi
+
+ # load the key
+ gpg_sphere "--import" <"$keyID" \
+ || failure "could not read key from '$keyID'"
+
+# else, get the key from the keyserver
+else
+ log verbose "searching keyserver $KEYSERVER for keyID $keyID..."
+ gpg_sphere "--keyserver $KEYSERVER --recv-key '0x${keyID}!'" \
+ || failure "Could not receive a key with this ID from the '$KEYSERVER' keyserver."
+
+ # get the full fingerprint of new certifier key
+ log debug "getting fingerprint of certifier key..."
+ fingerprint=$(gpg_sphere "--list-key --with-colons --with-fingerprint 0x${keyID}!" \
+ | grep '^fpr:' | grep "$keyID" | cut -d: -f10)
+
+ log info "key found:"
+ gpg_sphere "--fingerprint 0x${fingerprint}!"
+
+ if [ "$PROMPT" = "true" ] ; then
+ echo "Are you sure you want to add the above key as a"
+ read -p "certifier of users on this system? (Y/n) " OK; OK=${OK:-Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
+ failure "Identity certifier not added."
+ fi
+ else
+ log debug "adding key without prompting."
+ fi
+fi
+
+# export the key to the core keyring so that the core can sign the
+# new certifier key
+log debug "loading key into core keyring..."
+gpg_sphere "--export 0x${fingerprint}!" | gpg_core --import
+
# edit-key script to ltsign key
# NOTE: *all* user IDs will be ltsigned
ltsignCommand=$(cat <<EOF
@@ -151,8 +157,7 @@ EOF
# core ltsigns the newly imported certifier key
log debug "executing core ltsign script..."
if echo "$ltsignCommand" | \
- gpg_core --quiet --command-fd 0 --no-tty --edit-key "0x${fingerprint}!" \
- 2>&1 | log debug ; then
+ gpg_core --command-fd 0 --edit-key "0x${fingerprint}!" ; then
# transfer the new sigs back to the sphere keyring
gpg_core_sphere_sig_transfer
diff --git a/src/share/ma/diagnostics b/src/share/ma/diagnostics
index 0411080..ce463b2 100644
--- a/src/share/ma/diagnostics
+++ b/src/share/ma/diagnostics
@@ -28,6 +28,8 @@ local badhostkeys
local sshd_config
local problemsfound=0
+report_cruft
+
if ! id monkeysphere >/dev/null ; then
echo "! No monkeysphere user found! Please create a monkeysphere system user with bash as its shell."
problemsfound=$(($problemsfound+1))
@@ -45,7 +47,10 @@ if ! [ -d "$MADATADIR" ] ; then
exit
fi
-# FIXME: what's the correct, cross-platform answer?
+# FIXME: what's the correct, cross-platform way to determine where
+# sshd_config lives?
+sshd_config=/etc/ssh/sshd_config
+
seckey=$(gpg_core --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
keysfound=$(echo "$seckey" | grep -c ^sec:)
curdate=$(date +%s)
@@ -95,7 +100,16 @@ fi
# FIXME: look to see that the ownertrust rules are set properly on the
# sphere keyring
-# FIXME: make sure that at least one identity certifier exists
+# make sure that at least one identity certifier exists
+echo
+echo "Checking for Identity Certifiers..."
+if ! monkeysphere-authentication list-identity-certifiers | egrep -q '^[A-F0-9]{40}:' then
+ echo "! No Identity Certifiers found!"
+ echo " - Recommendation: once you know who should be able to certify identities for
+ connecting users, you should add their key, with:
+ monkeysphere-authentication add-identity-certifier"
+ problemsfound=$(($problemsfound+1))
+fi
# FIXME: look at the timestamps on the monkeysphere-generated
# authorized_keys files -- warn if they seem out-of-date.
diff --git a/src/share/ma/list_certifiers b/src/share/ma/list_certifiers
index a02487d..38a3222 100644
--- a/src/share/ma/list_certifiers
+++ b/src/share/ma/list_certifiers
@@ -86,5 +86,4 @@ gpg_sphere "--fingerprint --with-colons --fixed-list-mode --check-sigs" | \
esac
done
-
}
diff --git a/src/share/ma/remove_certifier b/src/share/ma/remove_certifier
index 10aa67b..a9a1451 100644
--- a/src/share/ma/remove_certifier
+++ b/src/share/ma/remove_certifier
@@ -27,7 +27,7 @@ fi
gpg_core --list-key --fingerprint "0x${keyID}!" || failure
if [ "$PROMPT" = "true" ] ; then
- read -p "Really remove above listed identity certifier? (y/N) " OK; OK=${OK:-N}
+ read -p "Really remove the identity certifier above? (Y/n) " OK; OK=${OK:-Y}
if [ "${OK/y/Y}" != 'Y' ] ; then
failure "Identity certifier not removed."
fi
diff --git a/src/share/ma/setup b/src/share/ma/setup
index a17e4f2..e77afff 100644
--- a/src/share/ma/setup
+++ b/src/share/ma/setup
@@ -13,13 +13,18 @@
setup() {
# make all needed directories
+ log debug "checking authentication directory structure..."
mkdir -p "${MADATADIR}"
+ chmod 0750 "${MADATADIR}"
+ chgrp "$MONKEYSPHERE_USER" "${MADATADIR}"
mkdir -p "${MATMPDIR}"
+ chmod 0750 "${MATMPDIR}"
+ chgrp "$MONKEYSPHERE_USER" "${MATMPDIR}"
mkdir -p "${GNUPGHOME_CORE}"
- chmod 700 "${GNUPGHOME_CORE}"
+ chmod 0700 "${GNUPGHOME_CORE}"
mkdir -p "${GNUPGHOME_SPHERE}"
- chmod 700 "${GNUPGHOME_SPHERE}"
- mkdir -p "${MADATADIR}"/authorized_keys
+ chmod 0700 "${GNUPGHOME_SPHERE}"
+ mkdir -p "${SYSDATADIR}"/authorized_keys
# deliberately replace the config files via truncation
# FIXME: should we be dumping to tmp files and then moving atomically?
@@ -29,7 +34,6 @@ setup() {
# This file is maintained by the Monkeysphere software.
# Edits will be overwritten.
no-greeting
-list-options show-uid-validity
EOF
log debug "writing sphere gpg.conf..."
@@ -43,9 +47,8 @@ EOF
# make sure the monkeysphere user owns everything in the sphere
# gnupghome
- log debuf "fixing sphere gnupg home ownership..."
- chown -R "$MONKEYSPHERE_USER" "${GNUPGHOME_SPHERE}"
- chgrp -R "$MONKEYSPHERE_USER" "${GNUPGHOME_SPHERE}"
+ log debug "fixing sphere gnupg home ownership..."
+ chown "$MONKEYSPHERE_USER:$MONKEYSPHERE_USER" "${GNUPGHOME_SPHERE}" "${GNUPGHOME_SPHERE}"/gpg.conf
# get fingerprint of core key. this should be empty on unconfigured systems.
local CORE_FPR=$(core_fingerprint)
@@ -59,7 +62,7 @@ EOF
log debug "generating monkeysphere authentication trust core key ($CORE_KEYLENGTH bits)..."
PEM2OPENPGP_USAGE_FLAGS=certify \
PEM2OPENPGP_NEWKEY=$CORE_KEYLENGTH pem2openpgp "$CORE_UID" \
- | gpg_core --import 2>&1 | log debug \
+ | gpg_core --import \
|| failure "Could not import new key for Monkeysphere authentication trust core"
# get fingerprint of core key. should definitely not be empty at this point
@@ -75,17 +78,17 @@ EOF
# export the core key to the sphere keyring
log debug "exporting core pub key to sphere keyring..."
- gpg_core --quiet --export | gpg_sphere "--quiet --import"
+ gpg_core --export | gpg_sphere "--import"
# ensure that the authentication sphere checker has absolute ownertrust on the expected key.
log debug "setting ultimate owner trust on core key in gpg_sphere..."
- printf "%s:6:\n" "$CORE_FPR" | gpg_sphere "--quiet --import-ownertrust"
+ printf "%s:6:\n" "$CORE_FPR" | gpg_sphere "--import-ownertrust"
gpg_sphere "--export-ownertrust" 2>&1 | log debug
# check the owner trust
log debug "checking gpg_sphere owner trust set properly..."
local ORIG_TRUST
- if ORIG_TRUST=$(gpg_sphere "--quiet --export-ownertrust" | grep '^[^#]') ; then
+ if ORIG_TRUST=$(gpg_sphere "--export-ownertrust" | grep '^[^#]') ; then
if [ "${CORE_FPR}:6:" != "$ORIG_TRUST" ] ; then
failure "Monkeysphere authentication trust sphere should explicitly trust the core. It does not have proper ownertrust settings."
fi
@@ -98,7 +101,7 @@ EOF
# our preferences are reasonable (i.e. 3 marginal OR 1 fully
# trusted certifications are sufficient to grant full validity.
log debug "checking trust model for authentication ..."
- local TRUST_MODEL=$(gpg_sphere "--quiet --with-colons --fixed-list-mode --list-keys" \
+ local TRUST_MODEL=$(gpg_sphere "--with-colons --fixed-list-mode --list-keys" \
| head -n1 | grep "^tru:" | cut -d: -f3,6,7)
log debug "sphere trust model: $TRUST_MODEL"
if [ "$TRUST_MODEL" != '1:3:1' ] ; then
diff --git a/src/share/ma/update_users b/src/share/ma/update_users
index e9e3cc6..092d108 100644
--- a/src/share/ma/update_users
+++ b/src/share/ma/update_users
@@ -35,7 +35,7 @@ MODE="authorized_keys"
GNUPGHOME="$GNUPGHOME_SPHERE"
# the authorized_keys directory
-authorizedKeysDir="${MADATADIR}/authorized_keys"
+authorizedKeysDir="${SYSDATADIR}/authorized_keys"
# check to see if the gpg trust database has been initialized
if [ ! -s "${GNUPGHOME}/trustdb.gpg" ] ; then
diff --git a/src/share/mh/add_hostname b/src/share/mh/add_hostname
index 70bbec3..0da6a06 100644
--- a/src/share/mh/add_hostname
+++ b/src/share/mh/add_hostname
@@ -34,8 +34,8 @@ find_host_userid > /dev/null && \
if [ "$PROMPT" = "true" ] ; then
echo "The following user ID will be added to the host key:"
echo " $userID"
- read -p "Are you sure you would like to add this user ID? (y/N) " OK; OK=${OK:=N}
- if [ ${OK/y/Y} != 'Y' ] ; then
+ read -p "Are you sure you would like to add this user ID? (Y/n) " OK; OK=${OK:=Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
failure "User ID not added."
fi
else
diff --git a/src/share/mh/add_revoker b/src/share/mh/add_revoker
index b4113df..428b958 100644
--- a/src/share/mh/add_revoker
+++ b/src/share/mh/add_revoker
@@ -15,91 +15,99 @@
add_revoker() {
-local domain=
-local trust=full
-local depth=1
local keyID
-local importinfo
+local tmpDir
local fingerprint
-local ltsignCommand
-local trustval
+local addrevokerCommand
keyID="$1"
+
+# check that key ID or file is specified
if [ -z "$keyID" ] ; then
failure "You must specify the key ID of a revoker key, or specify a file to read the key from."
fi
-if [ -f "$keyID" ] ; then
- log info "Reading key from file '$keyID':"
- importinfo=$(gpg_host --import < "$keyID" 2>&1) || failure "could not read key from '$keyID'"
- # FIXME: if this is tried when the key database is not
- # up-to-date, i got these errors (using set -x):
-
- # ++ su -m monkeysphere -c '\''gpg --import'\''
- # Warning: using insecure memory!
- # gpg: key D21739E9: public key "Daniel Kahn Gillmor <dkg@fifthhorseman.net>" imported
- # gpg: Total number processed: 1
- # gpg: imported: 1 (RSA: 1)
- # gpg: can'\''t create `/var/monkeysphere/gnupg-host/pubring.gpg.tmp'\'': Permission denied
- # gpg: failed to rebuild keyring cache: Permission denied
- # gpg: 3 marginal(s) needed, 1 complete(s) needed, PGP trust model
- # gpg: depth: 0 valid: 1 signed: 0 trust: 0-, 0q, 0n, 0m, 0f, 1u
- # gpg: next trustdb check due at 2009-01-10'
- # + failure 'could not read key from '\''/root/dkg.gpg'\'''
- # + echo 'could not read key from '\''/root/dkg.gpg'\'''
-
- keyID=$(echo "$importinfo" | grep '^gpg: key ' | cut -f2 -d: | cut -f3 -d\ )
- if [ -z "$keyID" ] || [ $(echo "$keyID" | wc -l) -ne 1 ] ; then
+
+# make a temporary directory for storing keys during import, and set
+# the trap to delete it on exit
+tmpDir=$(msmktempdir)
+trap "rm -rf $tmpDir" EXIT
+
+# if file is specified
+if [ -f "$keyID" -o "$keyID" = '-' ] ; then
+ # load the key from stdin
+ if [ "$keyID" = '-' ] ; then
+ # make a temporary file to hold the key from stdin
+ keyID="$tmpDir"/importkey
+ log verbose "reading key from stdin..."
+ cat > "$keyID"
+
+ # load the key from the file
+ elif [ -f "$keyID" ] ; then
+ log verbose "reading key from file '$keyID'..."
+ fi
+
+ # check the key is ok as monkeysphere user before loading
+ log debug "checking keys in file..."
+ fingerprint=$(su_monkeysphere_user \
+ ". ${SYSSHAREDIR}/common; list_primary_fingerprints" < "$keyID")
+
+ if [ $(printf "%s" "$fingerprint" | egrep -c '^[A-F0-9]{40}$') -ne 1 ] ; then
failure "There was not exactly one gpg key in the file."
fi
+
+ # load the key
+ gpg_host --import <"$keyID" \
+ || failure "could not read key from '$keyID'"
+
+# else, get the key from the keyserver
else
- # create a temporary directory for storing the downloaded key
- TMPLOC=$(mktemp -d "${MHTMPDIR}"/tmp.XXXXXXXXXX) || failure "Could not create temporary directory!"
+ # fix permissions and ownership on temporary directory which will
+ # be used by monkeysphere user for storing the downloaded key
+ chmod 0700 "$tmpDir"
+ chown "$MONKEYSPHERE_USER":"$MONKEYSPHERE_USER" "$tmpDir"
# download the key from the keyserver as the monkeysphere user
- su_monkeysphere_user \
- "GNUPGHOME=$TMPLOC gpg --keyserver $KEYSERVER --recv-key 0x${keyID}!"
+ log verbose "searching keyserver $KEYSERVER for keyID $keyID..."
+ su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --quiet --keyserver $KEYSERVER --recv-key 0x${keyID}!" \
+ || failure "Could not receive a key with this ID from the '$KEYSERVER' keyserver."
+
+ # get the full fingerprint of new revoker key
+ log debug "getting fingerprint of revoker key..."
+ fingerprint=$(su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --list-key --with-colons --with-fingerprint 0x${keyID}!" \
+ | grep '^fpr:' | grep "$keyID" | cut -d: -f10)
+
+ log info "key found:"
+ su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --fingerprint 0x${fingerprint}!"
+
+ if [ "$PROMPT" = "true" ] ; then
+ echo "Are you sure you want to add the above key as a"
+ read -p "revoker of the host key? (Y/n) " OK; OK=${OK:-Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
+ failure "revoker not added."
+ fi
+ else
+ log debug "adding revoker without prompting."
+ fi
# export the new key to the host keyring
- su_monkeysphere_user "GNUPGHOME=$TMPLOC gpg --export 0x${keyID}!" \
+ log debug "loading key into host keyring..."
+ su_monkeysphere_user "GNUPGHOME=$tmpDir gpg --quiet --export 0x${fingerprint}!" \
| gpg_host --import
fi
-export keyID
-
-# get the full fingerprint of the revoker key ID
-fingerprint=$(gpg_host --list-key --with-colons --with-fingerprint "0x${keyID}!" \
- | grep '^fpr:' | grep "$keyID" | cut -d: -f10)
-
-if [ -z "$fingerprint" ] ; then
- failure "Key '$keyID' not found."
-fi
-
-log info "key found:"
-gpg_host --fingerprint "0x${fingerprint}!"
-
-if [ "$PROMPT" = "true" ] ; then
- echo "Are you sure you want to add the above key as a"
- read -p "revoker of the host key? (y/N) " OK; OK=${OK:-N}
- if [ "${OK/y/Y}" != 'Y' ] ; then
- failure "revoker not added."
- fi
-else
- log debug "adding revoker without prompting."
-fi
-
# edit-key script to add revoker
addrevokerCommand=$(cat <<EOF
addrevoker
+$fingerprint
+y
+save
EOF
)
-# FIXME: implement!
-failure "not implemented yet!"
-
# core ltsigns the newly imported revoker key
-if echo "$addrevokerCommand" | \
- gpg_core_edit ; then
+log debug "executing add revoker script..."
+if echo "$addrevokerCommand" | gpg_host_edit ; then
update_gpg_pub_file
@@ -108,4 +116,8 @@ else
failure "Problem adding revoker."
fi
+# remove the temporary directory
+trap - EXIT
+rm -rf "$tmpDir"
+
}
diff --git a/src/share/mh/diagnostics b/src/share/mh/diagnostics
index d774723..2f65f89 100644
--- a/src/share/mh/diagnostics
+++ b/src/share/mh/diagnostics
@@ -25,11 +25,10 @@ local expire
local uid
local fingerprint
local badhostkeys
-local sshd_config
local problemsfound=0
-# FIXME: what's the correct, cross-platform answer?
-sshd_config=/etc/ssh/sshd_config
+report_cruft
+
seckey=$(gpg_host --list-secret-keys --fingerprint --with-colons --fixed-list-mode)
keysfound=$(echo "$seckey" | grep -c ^sec:)
curdate=$(date +%s)
@@ -50,7 +49,7 @@ fi
echo "Checking host GPG key..."
if (( "$keysfound" < 1 )); then
echo "! No host key found."
- echo " - Recommendation: run 'monkeysphere-host gen-key' or 'monkeysphere-host import-key'"
+ echo " - Recommendation: run 'monkeysphere-host import-key'"
problemsfound=$(($problemsfound+1))
elif (( "$keysfound" > 1 )); then
echo "! More than one host key found?"
@@ -114,35 +113,9 @@ else
# FIXME: propose adding a revoker to the host key if none exist (do we
# have a way to do that after key generation?)
- # Ensure that the ssh_host_rsa_key file is present and non-empty:
- echo
- echo "Checking host SSH key..."
- if [ ! -s "${SYSDATADIR}/ssh_host_rsa_key" ] ; then
- echo "! The host key as prepared for SSH (${SYSDATADIR}/ssh_host_rsa_key) is missing or empty."
- problemsfound=$(($problemsfound+1))
- else
- if [ $(ls -l "${SYSDATADIR}/ssh_host_rsa_key" | cut -f1 -d\ ) != '-rw-------' ] ; then
- echo "! Permissions seem wrong for ${SYSDATADIR}/ssh_host_rsa_key -- should be 0600."
- problemsfound=$(($problemsfound+1))
- fi
+# FIXME: test (with ssh-keyscan?) that the running ssh
+# daemon is actually offering the monkeysphere host key.
- # propose changes needed for sshd_config (if any)
- if ! grep -q "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$" "$sshd_config"; then
- echo "! $sshd_config does not point to the monkeysphere host key (${SYSDATADIR}/ssh_host_rsa_key)."
- echo " - Recommendation: add a line to $sshd_config: 'HostKey ${SYSDATADIR}/ssh_host_rsa_key'"
- problemsfound=$(($problemsfound+1))
- fi
- if badhostkeys=$(grep -i '^HostKey' "$sshd_config" | grep -v "^HostKey[[:space:]]\+${SYSDATADIR}/ssh_host_rsa_key$") ; then
- echo "! $sshd_config refers to some non-monkeysphere host keys:"
- echo "$badhostkeys"
- echo " - Recommendation: remove the above HostKey lines from $sshd_config"
- problemsfound=$(($problemsfound+1))
- fi
-
- # FIXME: test (with ssh-keyscan?) that the running ssh
- # daemon is actually offering the monkeysphere host key.
-
- fi
fi
# FIXME: look at the ownership/privileges of the various keyrings,
diff --git a/src/share/mh/import_key b/src/share/mh/import_key
index 557bb7f..040b41c 100644
--- a/src/share/mh/import_key
+++ b/src/share/mh/import_key
@@ -13,15 +13,22 @@
import_key() {
+local sshKeyFile
local hostName
local domain
local userID
-hostName="$1"
+sshKeyFile="$1"
+hostName="$2"
+
+# check that key file specified
+if [ -z "$sshKeyFile" ] ; then
+ failure "Must specify ssh key file to import, or specify '-' for stdin."
+fi
# use the default hostname if not specified
if [ -z "$hostName" ] ; then
- hostName=$(hostname -f)
+ hostName=$(hostname -f) || failure "Could not determine hostname."
# test that the domain is not obviously illegitimate
domain=${foo##*.}
case $domain in
@@ -39,14 +46,20 @@ userID="ssh://${hostName}"
# create host home
mkdir -p "${MHDATADIR}"
-mkdir -p "${MHTMPDIR}"
mkdir -p "${GNUPGHOME_HOST}"
chmod 700 "${GNUPGHOME_HOST}"
-log verbose "importing ssh key..."
-# translate ssh key to a private key
-PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
- | gpg_host --import 2>&1 | log debug
+# import ssh key to a private key
+if [ "$sshKeyFile" = '-' ] ; then
+ log verbose "importing ssh key from stdin..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
+ | gpg_host --import
+else
+ log verbose "importing ssh key from file '$sshKeyFile'..."
+ PEM2OPENPGP_USAGE_FLAGS=authenticate pem2openpgp "$userID" \
+ <"$sshKeyFile" \
+ | gpg_host --import
+fi
# load the new host fpr into the fpr variable. this is so we can
# create the gpg pub key file. we have to do this from the secret key
diff --git a/src/share/mh/publish_key b/src/share/mh/publish_key
index b433ad7..b0ffd93 100644
--- a/src/share/mh/publish_key
+++ b/src/share/mh/publish_key
@@ -18,8 +18,8 @@ publish_key() {
local GNUPGHOME
if [ "$PROMPT" = "true" ] ; then
- read -p "Really publish host key to $KEYSERVER? (y/N) " OK; OK=${OK:=N}
- if [ ${OK/y/Y} != 'Y' ] ; then
+ read -p "Really publish host key to $KEYSERVER? (Y/n) " OK; OK=${OK:=Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
failure "key not published."
fi
else
@@ -27,7 +27,9 @@ else
fi
# create a temporary gnupg directory from which to publish the key
-export GNUPGHOME=$(mktemp -d)
+export GNUPGHOME=$(msmktempdir)
+chmod 0700 "$GNUPGHOME"
+chown "$MONKEYSPHERE_USER":"$MONKEYSPHERE_USER" "$GNUPGHOME"
# trap to remove tmp dir if break
trap "rm -rf $GNUPGHOME" EXIT
diff --git a/src/share/mh/revoke_hostname b/src/share/mh/revoke_hostname
index 77f1f0d..71b56ed 100644
--- a/src/share/mh/revoke_hostname
+++ b/src/share/mh/revoke_hostname
@@ -28,7 +28,7 @@ if [ -z "$1" ] ; then
fi
echo "WARNING: There is a known bug in this function."
-echo "This function has been known to occasionally revoke the wrong user ID."
+echo "This function has been known to occasionally revoke the wrong hostname."
echo "Please see the following bug report for more information:"
echo "https://labs.riseup.net/code/issues/show/422"
read -p "Are you sure you would like to proceed? (y/N) " OK; OK=${OK:=N}
@@ -45,8 +45,8 @@ uidIndex=$(find_host_userid) || \
if [ "$PROMPT" = "true" ] ; then
echo "The following host key user ID will be revoked:"
echo " $userID"
- read -p "Are you sure you would like to revoke this user ID? (y/N) " OK; OK=${OK:=N}
- if [ ${OK/y/Y} != 'Y' ] ; then
+ read -p "Are you sure you would like to revoke this user ID? (N/y) " OK; OK=${OK:=Y}
+ if [ "${OK/y/Y}" != 'Y' ] ; then
failure "User ID not revoked."
fi
else
diff --git a/src/share/mh/revoke_key b/src/share/mh/revoke_key
index cccdc22..380236b 100644
--- a/src/share/mh/revoke_key
+++ b/src/share/mh/revoke_key
@@ -15,7 +15,31 @@
revoke_key() {
-# FIXME: implement!
-failure "not implemented yet!"
+# Coming in here, we expect $HOST_FINGERPRINT to be set, and we
+# believe that there is in fact a key.
+ # our current implementation is very simple: we just want to
+ # generate the revocation certificate on stdout. This provides
+ # for the two most likely (but hopefully not common) scenarios:
+
+ # an admin wants a revocation certificate for the host which they
+ # can store securely offline. In this case, the admin can
+ # redirect stdout to a file, or can simply copy/paste or
+ # transcribe from the terminal.
+
+ # Alternately, an admin might want to publish the revocation
+ # certificate immediately. here's a quick way to do this:
+
+
+ # tmp=$(mktemp -d)
+ # export GNUPGHOME="$tmp"
+ # gpg --import < /var/lib/monkeysphere/ssh_host_rsa_key.pub.gpg
+ # monkeysphere-host revoke-key | gpg --import
+ # gpg --keyserver pool.sks-keyservers.net --send $(hostname -f)
+
+
+ # note: we're not using the gpg_host function because we actually
+ # want to use gpg's UI in this case, so we want to omit --no-tty
+
+ GNUPGHOME="$GNUPGHOME_HOST" gpg --no-greeting --quiet --armor --gen-revoke "0x${HOST_FINGERPRINT}!"
}
diff --git a/src/share/mh/set_expire b/src/share/mh/set_expire
index ae7c13a..63e5c55 100644
--- a/src/share/mh/set_expire
+++ b/src/share/mh/set_expire
@@ -22,7 +22,7 @@ local extendTo
extendTo=$(get_gpg_expiration "$1")
if [ "$PROMPT" = "true" ] ; then
- read -p "Are you sure you want to change the expiration on the host key to '$extendTo'? (y/N) " OK; OK=${OK:-N}
+ read -p "Are you sure you want to change the expiration on the host key to '$extendTo'? (Y/n) " OK; OK=${OK:-Y}
if [ "${OK/y/Y}" != 'Y' ] ; then
failure "expiration not set."
fi
diff --git a/src/transition_0.22_0.23 b/src/transition_0.22_0.23
deleted file mode 100755
index 3328e8c..0000000
--- a/src/transition_0.22_0.23
+++ /dev/null
@@ -1,69 +0,0 @@
-#!/bin/bash
-
-# This is a post-install script for monkeysphere, to transition an old
-# (<=0.22) setup to the new (>0.22) setup
-
-SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
-
-MADATADIR="${SYSDATADIR}/authentication"
-MHDATADIR="${SYSDATADIR}/host"
-
-############################################################
-### transfer host setup
-
-if [ -d "$SYSDATADIR"/gnupg-host ] ; then
-
- if [ -s "$SYSDATADIR"/ssh_host_rsa_key ] ; then
-
- # This would be simple, but it would generate a new pgp key,
- #and we don't want that, right?
- #monkeysphere-host expert import_key "$SYSDATADIR"/ssh_host_rsa_key
-
- # create host home
- mkdir -p "${MHDATADIR}"
- mkdir -p "${MHTMPDIR}"
- mkdir -p "${GNUPGHOME_HOST}"
- chmod 700 "${GNUPGHOME_HOST}"
-
- # transfer the host secret key from the old home to the new
- GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --export-secret-keys \
- GNUPGHOME="$MHDATADIR" gpg --import
-
- # make sure the ssh_host_rsa_key.pub and ssh_host_rsa_key.pub.gpg
- # files exist
-
- # anything else?
-
- fi
-
- #rm -rf "$SYSDATADIR"/gnupg-host
-
-fi
-
-############################################################
-### transfer authentication setup
-
-# should we test for something else/better than the existence of this
-# directory to know that we should go through the setup?
-if [ -d "$SYSDATADIR"/gnupg-authentication ] ; then
-
- # run the authentication setup
- monkeysphere-authentication setup
-
- # transfer certifiers
- # FIXME: how?
- # i think we'll need to run something like
- # gpg_core_sphere_sig_transfer after transfering certifiers ltsigs
-
- # do we need to do some sort of transfer of ownertrust?
-
- # move the authorized_keys directory
- mv "$SYSDATADIR"/authorized_keys "$MADATADIR"/
-
- # do we need to transfer anything else? running update-users will
- # regenerate everything else in the sphere keyring, right?
-
- #rm -rf "$SYSDATADIR"/gnupg-authentication
-
-fi
-
diff --git a/src/transitions/0.23 b/src/transitions/0.23
new file mode 100755
index 0000000..f09dfff
--- /dev/null
+++ b/src/transitions/0.23
@@ -0,0 +1,180 @@
+#!/bin/bash
+
+# This is a post-install script for monkeysphere, to transition an old
+# (<0.23) setup to the new (>=0.23) setup.
+
+# You should be able to run this script after any version >= 0.23 is
+# installed. This script should be well-behaved, even if it is run
+# repeatedly.
+
+# Written by
+# Jameson Rollins <jrollins@finestructure.net>
+# Daniel Kahn Gillmor <dkg@fifthhorseman.net>
+#
+# Copyright 2009, released under the GPL, version 3 or later
+
+# NOTE: the reverse operation (downgrading) is not directly supported,
+# and MAY LOCK YOU OUT OF YOUR SYSTEM, depending on how you have
+# configured the monkeysphere!
+
+# any unexpected errors should cause this script to bail:
+set -e
+
+SYSDATADIR=${MONKEYSPHERE_SYSDATADIR:-"/var/lib/monkeysphere"}
+
+MADATADIR="${SYSDATADIR}/authentication"
+MHDATADIR="${SYSDATADIR}/host"
+
+STASHDIR="${SYSDATADIR}/backup-from-0.23-transition"
+
+
+log() {
+ printf "$@" >&2
+}
+
+# FIXME: implement this function better. here, we only care about
+# dots, *and* about reversing the regexification of them.
+gpg_unescape_and_unregex() {
+ sed 's/\\x5c\././g'
+}
+
+
+is_domain_name() {
+ printf "%s" "$1" | egrep -q '^[[:alnum:]][[:alnum:]-.]*[[:alnum:]]$'
+}
+
+# run the authentication setup (this is also the first chance to bail
+# if 0.23 is not fully-installed, because m-a did not exist before
+# 0.23)
+monkeysphere-authentication setup
+
+# before 0.23, the old gnupg-host data directory used to contain the
+# trust core and the system's ssh host key.
+
+if [ -d "$SYSDATADIR"/gnupg-host ] ; then
+
+### transfer identity certifiers, if they don't already exist in the
+### current setup:
+
+ if monkeysphere-authentication list-identity-certifiers | \
+ grep -q '^[A-F0-9]{40}:$' ; then
+ log 'There are already certifiers in the new system!\nNot transferring any certifiers.\n'
+ else
+ # get the old host keygrip (don't know why there would be more
+ # than one, but we'll transfer all tsigs made by any key that
+ # had been given ultimate ownertrust):
+ for authgrip in $(GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-ownertrust | \
+ grep ':6:$' | \
+ sed -r 's/^[A-F0-9]{24}([A-F0-9]{16}):6:$/\1/') ; do
+
+ # we're assuming that old id certifiers were only added by old
+ # versions of m-s c+, which added certifiers by ltsigning
+ # entire keys.
+
+ # so we'll walk the list of tsigs from the old host key, and
+ # add those keys as certifiers to the new system.
+
+ # FIXME: if an admin has run "m-s add-id-certifier $foo"
+ # multiple times for the same $foo, we'll only transfer
+ # one of those certifications (even if later
+ # certifications had different parameters).
+
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --fingerprint --with-colons --fixed-list-mode --check-sigs | \
+ cut -f 1,2,5,8,9,10 -d: | \
+ egrep '^(fpr:::::|sig:!:'"$authgrip"':[[:digit:]]+ [[:digit:]]+:)' | \
+ while IFS=: read -r type validity grip trustparams trustdomain fpr ; do
+ case $type in
+ 'fpr') # this is a new key
+ keyfpr=$fpr
+ ;;
+ 'sig') # deal with all trust signatures, including
+ # regexes if present.
+ if [ "$keyfpr" ] ; then
+ trustdepth=${trustparams%% *}
+ trustlevel=${trustparams##* }
+ if [ "$trustlevel" -ge 120 ] ; then
+ truststring=full
+ elif [ "$trustlevel" -ge 60 ] ; then
+ truststring=marginal
+ else
+ # trust levels below marginal are ignored.
+ continue
+ fi
+
+ finaldomain=
+ if [ "$trustdomain" ] ; then
+ # FIXME: deal with translating
+ # $trustdomain back to a domain.
+ if [ printf "%s" "$trustdomain" | egrep -q '^<\[\^>\]\+\[@\.\][^>]+>\$$' ] ; then
+ dpart=$(printf "%s" "$trustdomain" | sed -r 's/^<\[\^>\]\+\[@\.\]([^>]+)>\$$/\1/' | gpg_unescape_and_unregex)
+ if [ is_domain_name "$dpart" ]; then
+ finaldomain="--domain $dpart"
+ else
+ log "Does not seem to be a domain name (%s), not adding certifier\n" "$dpart"
+ continue
+ fi
+ else
+ log "Does not seem to be a standard gpg domain-based tsig (%s), not adding certifier\n" "$trustdomain"
+ continue
+ fi
+ fi
+
+ CERTKEY=$(mktemp ${TMPDIR:-/tmp}/mstransition.XXXXXXXX)
+ log "Adding identity certifier with fingerprint %s\n" "$keyfpr"
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export "0x$keyfpr" --export-options export-clean >"$CERTKEY"
+ MONKEYSPHERE_PROMPT=false monkeysphere-authentication add-identity-certifier $finaldomain --trust "$truststring" --depth "$trustdepth" "$CERTKEY"
+ rm -f "$CERTKEY"
+ # clear the fingerprint so that we don't
+ # make additional tsigs on it if more uids
+ # are present:
+ keyfpr=
+ fi
+ ;;
+ esac
+ done
+ done
+ fi
+
+### transfer host key information (if present) into the new spot
+
+ if [ -d "${MHDATADIR}" ] ; then
+ log "Not transferring host key info because host directory already exists.\n"
+ else
+ if [ -s "$SYSDATADIR"/ssh_host_rsa_key ] || \
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --with-colons --list-secret-keys | grep -q '^sec:' ; then
+
+ # create host home
+ mkdir -p "${MHDATADIR}"
+ chmod 0700 "${MHDATADIR}"
+
+ log "importing host key from old monkeysphere installation\n"
+ GNUPGHOME="$SYSDATADIR"/gnupg-host gpg --no-permission-warning --export-secret-keys | \
+ GNUPGHOME="$MHDATADIR" gpg --quiet --no-tty --import
+
+ monkeysphere-host update-gpg-pub-file
+ else
+ log "No host key found in old monkeysphere install; not importing any host key.\n"
+ fi
+ fi
+
+
+### get rid of this old stuff, since we've transferred it all:
+
+ mkdir -p "$STASHDIR"
+ chmod 0700 "$STASHDIR"
+ mv "${SYSDATADIR}/gnupg-host" "$STASHDIR"
+fi
+
+
+# There is nothing in the old authentication directory that we should
+# need to keep around, but it is not unreasonable to transfer keys to
+# the new authentication keyring.
+if [ -d "${SYSDATADIR}/gnupg-authentication" ] ; then
+
+ GNUPGHOME="${SYSDATADIR}/gnupg-authentication" gpg --no-permission-warning --export | \
+ monkeysphere-authentication gpg-cmd --import
+
+ mkdir -p "$STASHDIR"
+ chmod 0700 "$STASHDIR"
+ mv "${SYSDATADIR}/gnupg-authentication" "$STASHDIR"
+fi
diff --git a/src/transitions/README.txt b/src/transitions/README.txt
new file mode 100644
index 0000000..7488c74
--- /dev/null
+++ b/src/transitions/README.txt
@@ -0,0 +1,16 @@
+This directory contains transition scripts for major changes to
+monkeysphere infrastructure.
+
+They are expected to be run immediately after upgrading to the named
+version or later.
+
+For example: you upgrade to from version 0.8 to version 0.15, and the
+directory contains 0.6, 0.12 and 0.15, you should run 0.12 followed by
+0.15.
+
+The scripts are supposed to be cleverly-written enough that you can
+run them repeatedly, and they should only make their intended changes
+once. If they do not behave that way, this is a bug. Please report
+it!
+
+ https://labs.riseup.net/code/projects/monkeysphere/