More work on the marginal case output for the ssh-proxycommand. For a
authorJameson Graef Rollins <jrollins@finestructure.net>
Mon, 17 Nov 2008 06:14:20 +0000 (01:14 -0500)
committerJameson Graef Rollins <jrollins@finestructure.net>
Mon, 17 Nov 2008 06:14:20 +0000 (01:14 -0500)
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

index aeea30dcd976dbaef5770e317f41135ef879d7aa..b3dc5625509732be84c6aeee7f9f9926b50611ea 100755 (executable)
@@ -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