X-Git-Url: https://codewiz.org/gitweb?p=monkeysphere.git;a=blobdiff_plain;f=src%2Fmonkeysphere;h=6db4827c15a5ea8fc9248cf2a4c1e0f9e6cd5d79;hp=46abf6fce659dcc09f7017ac97e2a9c814a85105;hb=e71c7bb4dff26178f714cd0fcdbb3058effa4066;hpb=2b5cd0f910f28a601bcecfe68cdfc1ffd9b1362c diff --git a/src/monkeysphere b/src/monkeysphere index 46abf6f..6db4827 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -1,6 +1,6 @@ #!/usr/bin/env bash -# monkeysphere: MonkeySphere client tool +# monkeysphere: Monkeysphere client tool # # The monkeysphere scripts are written by: # Jameson Rollins @@ -12,21 +12,23 @@ # or later. ######################################################################## +set -e + PGRM=$(basename $0) SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"} export SYSSHAREDIR . "${SYSSHAREDIR}/common" || exit 1 +# sharedir for host functions +MSHAREDIR="${SYSSHAREDIR}/m" + # UTC date in ISO 8601 format if needed DATE=$(date -u '+%FT%T') # unset some environment variables that could screw things up unset GREP_OPTIONS -# default return code -RETURN=0 - # set the file creation mask to be only owner rw umask 077 @@ -42,13 +44,9 @@ 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 ssh proxycommand + ssh-proxycommand monkeysphere ssh ProxyCommand subkey-to-ssh-agent (s) store authentication subkey in ssh-agent version (v) show version number help (h,?) this help @@ -56,82 +54,22 @@ subcommands: EOF } -# 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." +# user gpg command to define common options +gpg_user() { + gpg --no-greeting --quiet --no-tty "$@" } -# 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 +# 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 --quiet --fixed-list-mode --list-secret-keys --with-colons 2>/dev/null | egrep '^sec:') + gpgSecOut=$(gpg_user --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 + 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." @@ -145,18 +83,31 @@ Type '$PGRM help' for usage." gpg --gen-key" ;; 1) - keyID=$(echo "$gpgSecOut" | cut -d: -f5) + echo "$gpgSecOut" | cut -d: -f5 ;; *) echo "Multiple primary secret keys found:" echo "$gpgSecOut" | cut -d: -f5 - failure "Please specify which primary key to use." + echo "Please specify which primary key to use." + 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 --quiet --fixed-list-mode --list-keys --with-colons "$keyID") ; do + 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) @@ -171,185 +122,60 @@ Type '$PGRM help' for usage." 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 + echo "A valid authentication key already exists for primary key '$keyID'." 1>&2 + if [ "$PROMPT" = "true" ] ; then + read -p "Are you sure you would like to generate another one? (y/N) " OK; OK=${OK:N} + if [ "${OK/y/Y}" != 'Y' ] ; then + failure "aborting." + fi + break + else 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 </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 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 - - 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"