From dd002c89fc4dccabc16d488a15a40cc88383605f Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 16 Nov 2008 03:17:36 -0500 Subject: added some useful output to the ssh-proxycommand for "marginal" cases where keys are found for host but do not have full validity. this uses ssh-keyscan to pull the key for the host in question, check this key against the keys against those found via gpg, and output some useful information about the one that matches. --- src/monkeysphere-ssh-proxycommand | 98 ++++++++++++++++++++++++++++++++++++++- 1 file changed, 96 insertions(+), 2 deletions(-) (limited to 'src/monkeysphere-ssh-proxycommand') diff --git a/src/monkeysphere-ssh-proxycommand b/src/monkeysphere-ssh-proxycommand index 6276092..b039844 100755 --- a/src/monkeysphere-ssh-proxycommand +++ b/src/monkeysphere-ssh-proxycommand @@ -13,14 +13,84 @@ # established. Can be added to ~/.ssh/config as follows: # ProxyCommand monkeysphere-ssh-proxycommand %h %p +######################################################################## +PGRM=$(basename $0) + +SYSSHAREDIR=${MONKEYSPHERE_SYSSHAREDIR:-"/usr/share/monkeysphere"} +export SYSSHAREDIR +. "${SYSSHAREDIR}/common" || exit 1 + +######################################################################## +# FUNCTIONS ######################################################################## usage() { -cat <&2 + cat <&2 usage: ssh -o ProxyCommand="$(basename $0) %h %p" ... EOF } +log() { + echo "$@" >&2 +} + +output_no_valid_key() { + local sshKeyOffered + local userID + local type + local validity + local keyid + local uidfpr + local usage + local sshKeyGPG + local sshFingerprint + + log "OpenPGP keys with*out* full validity found for this host:" + log + + # retrieve the actual ssh key + sshKeyOffered=$(ssh-keyscan -t rsa -p "$PORT" "$HOST" 2>/dev/null | awk '{ print $2, $3 }') + + userID="ssh://${HOSTP}" + + # 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) + + # 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 + 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 + + # get the fingerprint of the ssh key + tmpkey=$(mktemp ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX) + echo "$sshKeyGPG" > "$tmpkey" + sshFingerprint=$(ssh-keygen -l -f "$tmpkey" | awk '{ print $2 }') + rm -rf "$tmpkey" + + # output gpg info + gpg --check-sigs \ + --list-options show-uid-validity \ + "$keyid" >&2 + + # output ssh fingerprint + log "RSA key fingerprint is ${sshFingerprint}." + log "Falling through to standard ssh host checking." + log + fi + ;; + esac + done +} + ######################################################################## # export the monkeysphere log level @@ -35,7 +105,7 @@ HOST="$1" PORT="$2" if [ -z "$HOST" ] ; then - echo "Host not specified." >&2 + log "Host not specified." usage exit 255 fi @@ -88,6 +158,30 @@ 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 + # exec a netcat passthrough to host for the ssh connection if [ -z "$NO_CONNECT" ] ; then if (which nc 2>/dev/null >/dev/null); then -- cgit v1.2.3 From d91a9e05ef6c351f40d931d2f7d19e3a3979279c Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 16 Nov 2008 17:26:14 -0500 Subject: add some more informative debug output to key processing. --- src/common | 6 +++++- src/monkeysphere-ssh-proxycommand | 14 +++++++++----- 2 files changed, 14 insertions(+), 6 deletions(-) (limited to 'src/monkeysphere-ssh-proxycommand') diff --git a/src/common b/src/common index efee9bd..51b0470 100644 --- a/src/common +++ b/src/common @@ -639,7 +639,7 @@ process_user_id() { ;; 'uid') # user ids if [ "$lastKey" != pub ] ; then - log verbose " - got a user ID after a sub key?! user IDs should only follow primary keys!" + 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 @@ -652,6 +652,8 @@ process_user_id() { if [ "$validity" = 'u' -o "$validity" = 'f' ] ; then # mark user ID acceptable uidOK=true + else + log debug " - unacceptable user ID validity ($validity)." fi else continue @@ -693,10 +695,12 @@ process_user_id() { # 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 diff --git a/src/monkeysphere-ssh-proxycommand b/src/monkeysphere-ssh-proxycommand index b039844..aeea30d 100755 --- a/src/monkeysphere-ssh-proxycommand +++ b/src/monkeysphere-ssh-proxycommand @@ -45,20 +45,24 @@ output_no_valid_key() { local sshKeyGPG local sshFingerprint - log "OpenPGP keys with*out* full validity found for this host:" + userID="ssh://${HOSTP}" + + log "Monkeysphere found only OpenPGP keys for this host with*out* full validity." + log "host: $userID" log # 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? - userID="ssh://${HOSTP}" - - # output gpg info for (exact) userid and store + # output gpg info for userid and store gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \ --with-fingerprint --with-fingerprint \ ="$userID" 2>/dev/null) - # loop over all lines in the gpg output and process. + # 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 -- cgit v1.2.3 From f7dfcead0281c9f6dd26908f76282efc843a7e52 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Mon, 17 Nov 2008 01:14:20 -0500 Subject: More work on the marginal case output for the ssh-proxycommand. For a key matching that offered by the host, now outputs just the information (including sigs) of the relevant user ID. There is some other useful output for other cases as well. I also added a couple of FIXMEs for some other cases that I think we should think about and maybe tweak behavior for. --- src/monkeysphere-ssh-proxycommand | 74 +++++++++++++++++++++++++++++++++------ 1 file changed, 63 insertions(+), 11 deletions(-) (limited to 'src/monkeysphere-ssh-proxycommand') diff --git a/src/monkeysphere-ssh-proxycommand b/src/monkeysphere-ssh-proxycommand index aeea30d..b3dc562 100755 --- a/src/monkeysphere-ssh-proxycommand +++ b/src/monkeysphere-ssh-proxycommand @@ -43,20 +43,21 @@ output_no_valid_key() { local uidfpr local usage local sshKeyGPG + local tmpkey local sshFingerprint + local gpgSigOut userID="ssh://${HOSTP}" - log "Monkeysphere found only OpenPGP keys for this host with*out* full validity." - log "host: $userID" - log + 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 + # FIXME: should we do any checks for failed keyscans, eg. host not # found? - # output gpg info for userid and store + # get the gpg info for userid gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \ --with-fingerprint --with-fingerprint \ ="$userID" 2>/dev/null) @@ -73,26 +74,68 @@ output_no_valid_key() { # 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 # get the fingerprint of the ssh key tmpkey=$(mktemp ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX) echo "$sshKeyGPG" > "$tmpkey" - sshFingerprint=$(ssh-keygen -l -f "$tmpkey" | awk '{ print $2 }') + sshFingerprint=$(ssh-keygen -l -f "$tmpkey" | \ + awk '{ print $2 }') rm -rf "$tmpkey" - # output gpg info - gpg --check-sigs \ + # get the sigs for the matching key + gpgSigOut=$(gpg --check-sigs \ --list-options show-uid-validity \ - "$keyid" >&2 + "$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}." - log "Falling through to standard ssh host checking." - log + + # 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 --------------------" } ######################################################################## @@ -186,6 +229,15 @@ case $? in ;; 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 -- cgit v1.2.3