From 09a630a57493b1967f031a32602d117be64fdad0 Mon Sep 17 00:00:00 2001 From: Jameson Graef Rollins Date: Sun, 22 Jun 2008 11:43:20 -0400 Subject: Improve trust-key function. --- debian/changelog | 3 ++- man/man8/monkeysphere-server.8 | 8 +++++--- src/common | 44 +++++++++++++++++++++++++++++++++++++++--- src/monkeysphere-server | 15 ++++---------- 4 files changed, 52 insertions(+), 18 deletions(-) diff --git a/debian/changelog b/debian/changelog index cec0988..41af80c 100644 --- a/debian/changelog +++ b/debian/changelog @@ -12,8 +12,9 @@ monkeysphere (0.2-1) UNRELEASED; urgency=low * Better handling of unknown users in server update-users * Add file locking when modifying known_hosts or authorized_keys * Better failure/prompting for gen-subkey + * Add ability to set any owner trust level for keys in server keychain. - -- Jameson Graef Rollins Sat, 21 Jun 2008 16:39:26 -0400 + -- Jameson Graef Rollins Sun, 22 Jun 2008 11:42:42 -0400 monkeysphere (0.1-1) experimental; urgency=low diff --git a/man/man8/monkeysphere-server.8 b/man/man8/monkeysphere-server.8 index 2b5af5e..e821e63 100644 --- a/man/man8/monkeysphere-server.8 +++ b/man/man8/monkeysphere-server.8 @@ -43,9 +43,11 @@ Show the fingerprint for the host's OpenPGP key. `f' may be used in place of Publish the host's gpg key to the keyserver. `p' may be used in place of `publish-key'. .TP -.B trust-keys KEYID... -Mark key specified with key IDs with full owner trust. `t' may be used -in place of `trust-keys'. +.B trust-key KEYID [LEVEL] +Set owner trust for key. If LEVEL is not specified, then the program +will prompt for an owner trust level to set for KEYID. This function +lsigns the key as well so that it will have a known validity. `t' may +be used in place of `trust-key'. .TP .B help Output a brief usage summary. `h' or `?' may be used in place of diff --git a/src/common b/src/common index b220150..4021263 100644 --- a/src/common +++ b/src/common @@ -532,6 +532,16 @@ process_authorized_keys() { # retrieve key from web of trust, and set owner trust to "full" # if key is found. trust_key() { + local keyID + local trustLevel + + keyID="$1" + trustLevel="$2" + + if [ -z "$keyID" ] ; then + failure "You must specify key to trust." + fi + # get the key from the key server if ! gpg --keyserver "$KEYSERVER" --recv-key "$keyID" ; then failure "Could not retrieve key '$keyID'." @@ -540,13 +550,41 @@ trust_key() { # get key fingerprint fingerprint=$(get_key_fingerprint "$keyID") + echo "key found:" + gpg --fingerprint "$fingerprint" + + while [ -z "$trustLevel" ] ; do + cat < Date: Mon, 23 Jun 2008 15:54:59 -0400 Subject: Provide better (ie. more informative) return codes. Required some modifications to a couple of different functions. --- src/common | 212 ++++++++++++++++++++++++++++++++++++++----------------- src/monkeysphere | 12 +++- 2 files changed, 156 insertions(+), 68 deletions(-) diff --git a/src/common b/src/common index 4021263..9dcc5e8 100644 --- a/src/common +++ b/src/common @@ -18,8 +18,6 @@ ETC="/etc/monkeysphere" export ETC CACHE="/var/cache/monkeysphere" export CACHE -ERR=0 -export ERR ######################################################################## ### UTILITY FUNCTIONS @@ -344,9 +342,9 @@ process_user_id() { # 0 = ok, 1 = bad if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then log " * acceptable key found." - echo 0 "$fingerprint" + echo "0:${fingerprint}" else - echo 1 "$fingerprint" + echo "1:${fingerprint}" fi ;; 'sub') # sub keys @@ -379,116 +377,193 @@ process_user_id() { # 0 = ok, 1 = bad if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then log " * acceptable key found." - echo 0 "$fingerprint" + echo "0:${fingerprint}" else - echo 1 "$fingerprint" + echo "1:${fingerprint}" fi ;; esac done } -# process hosts in the known_host file -process_hosts_known_hosts() { +# process a single host in the known_host file +process_host_known_hosts() { local host local userID local ok local keyid local tmpfile + local returnCode + + # default return code is 1, which assumes no key was found + returnCode=1 + + host="$1" + + log "processing host: $host" + + userID="ssh://${host}" + + for line in $(process_user_id "ssh://${host}") ; do + ok=$(echo "$line" | cut -d: -f1) + keyid=$(echo "$line" | cut -d: -f2) + + sshKey=$(gpg2ssh "$keyid") + # remove the old host key line + remove_line "$KNOWN_HOSTS" "$sshKey" + # if key OK, add new host line + if [ "$ok" -eq '0' ] ; then + # hash if specified + if [ "$HASH_KNOWN_HOSTS" = 'true' ] ; then + # FIXME: this is really hackish cause ssh-keygen won't + # hash from stdin to stdout + tmpfile=$(mktemp) + ssh2known_hosts "$host" "$sshKey" > "$tmpfile" + ssh-keygen -H -f "$tmpfile" 2> /dev/null + cat "$tmpfile" >> "$KNOWN_HOSTS" + rm -f "$tmpfile" "${tmpfile}.old" + else + ssh2known_hosts "$host" "$sshKey" >> "$KNOWN_HOSTS" + fi + # set return code to be 0, since a key was found + returnCode=0 + fi + return "$returnCode" + done + + return "$returnCode" +} + +# update the known_hosts file for a set of hosts listed on command +# line +update_known_hosts() { + local host + local returnCode + + # default return code is 0, which assumes a key was found for + # every host. code will be set to 1 if a key is not found for at + # least one host + returnCode=0 # create a lockfile on known_hosts lockfile-create "$KNOWN_HOSTS" for host ; do - log "processing host: $host" - - userID="ssh://${host}" - - process_user_id "ssh://${host}" | \ - while read -r ok keyid ; do - sshKey=$(gpg2ssh "$keyid") - # remove the old host key line - remove_line "$KNOWN_HOSTS" "$sshKey" - # if key OK, add new host line - if [ "$ok" -eq '0' ] ; then - # hash if specified - if [ "$HASH_KNOWN_HOSTS" = 'true' ] ; then - # FIXME: this is really hackish cause ssh-keygen won't - # hash from stdin to stdout - tmpfile=$(mktemp) - ssh2known_hosts "$host" "$sshKey" > "$tmpfile" - ssh-keygen -H -f "$tmpfile" 2> /dev/null - cat "$tmpfile" >> "$KNOWN_HOSTS" - rm -f "$tmpfile" "${tmpfile}.old" - else - ssh2known_hosts "$host" "$sshKey" >> "$KNOWN_HOSTS" - fi - fi - done + # process the host, change return code if host key not found + process_host_known_hosts "$host" || returnCode=1 + # touch the lockfile, for good measure. lockfile-touch --oneshot "$KNOWN_HOSTS" done # remove the lockfile lockfile-remove "$KNOWN_HOSTS" + + return "$returnCode" +} + +# process known_hosts file, going through line-by-line, extract each +# host, and process with the host processing function +process_known_hosts() { + local returnCode + + # default return code is 0, which assumes a key was found for + # every host. code will be set to 1 if a key is not found for at + # least one host + returnCode=0 + + # take all the hosts from the known_hosts file (first field), grep + # out all the hashed hosts (lines starting with '|')... + for line in $(cat "$KNOWN_HOSTS" | meat | cut -d ' ' -f 1 | grep -v '^|.*$') ; do + # break up hosts into separate words + update_known_hosts $(echo "$line" | tr , ' ') || returnCode=1 + done + + return "$returnCode" } # process uids for the authorized_keys file -process_uids_authorized_keys() { +process_uid_authorized_keys() { local userID local ok local keyid + local returnCode + + # default return code is 1, which assumes no key was found + returnCode=1 + + userID="$1" + + log "processing user ID: $userID" + + for line in $(process_user_id "$userID") ; do + ok=$(echo "$line" | cut -d: -f1) + keyid=$(echo "$line" | cut -d: -f2) + + sshKey=$(gpg2ssh "$keyid") + # remove the old host key line + remove_line "$AUTHORIZED_KEYS" "$sshKey" + # if key OK, add new host line + if [ "$ok" -eq '0' ] ; then + ssh2authorized_keys "$userID" "$sshKey" >> "$AUTHORIZED_KEYS" + + # set return code to be 0, since a key was found + returnCode=0 + fi + done + + return "$returnCode" +} + +# update the authorized_keys files from a list of user IDs on command +# line +update_authorized_keys() { + local userID + local returnCode + + # default return code is 0, which assumes a key was found for + # every user ID. code will be set to 1 if a key is not found for + # at least one user ID + returnCode=0 # create a lockfile on authorized_keys lockfile-create "$AUTHORIZED_KEYS" for userID ; do - log "processing user ID: $userID" - - process_user_id "$userID" | \ - while read -r ok keyid ; do - sshKey=$(gpg2ssh "$keyid") - # remove the old host key line - remove_line "$AUTHORIZED_KEYS" "$sshKey" - # if key OK, add new host line - if [ "$ok" -eq '0' ] ; then - ssh2authorized_keys "$userID" "$sshKey" >> "$AUTHORIZED_KEYS" - fi - done + # process the user ID, change return code if key not found for + # user ID + process_uid_authorized_keys "$userID" || returnCode=1 + # touch the lockfile, for good measure. lockfile-touch --oneshot "$AUTHORIZED_KEYS" done # remove the lockfile lockfile-remove "$AUTHORIZED_KEYS" -} - -# process known_hosts file -# go through line-by-line, extract each host, and process with the -# host processing function -process_known_hosts() { - local hosts - local host - # take all the hosts from the known_hosts file (first field), - # grep out all the hashed hosts (lines starting with '|')... - cat "$KNOWN_HOSTS" | meat | \ - cut -d ' ' -f 1 | grep -v '^|.*$' | \ - while IFS=, read -r -a hosts ; do - process_hosts_known_hosts ${hosts[@]} - done + return "$returnCode" } # process an authorized_user_ids file for authorized_keys process_authorized_user_ids() { local userid + local returnCode + + # default return code is 0, and is set to 1 if a key for a user ID + # is not found + returnCode=0 authorizedUserIDs="$1" - cat "$authorizedUserIDs" | meat | \ - while read -r userid ; do - process_uids_authorized_keys "$userid" + # set the IFS to be newline for parsing the authorized_user_ids + # file. can't find it in BASH(1) (found it on the net), but it + # works. + IFS=$'\n' + for userid in $(cat "$authorizedUserIDs" | meat) ; do + update_authorized_keys "$userid" || returnCode=1 done + + return "$returnCode" } # EXPERIMENTAL (unused) process userids found in authorized_keys file @@ -498,6 +573,11 @@ process_authorized_user_ids() { process_authorized_keys() { local authorizedKeys local userID + local returnCode + + # default return code is 0, and is set to 1 if a key for a user + # is not found + returnCode=0 authorizedKeys="$1" @@ -522,8 +602,10 @@ process_authorized_keys() { # process the userid log "processing userid: '$userID'" - process_user_id "$userID" > /dev/null + process_user_id "$userID" > /dev/null || returnCode=1 done + + return "$returnCode" } ################################################## diff --git a/src/monkeysphere b/src/monkeysphere index 9b315e2..1368a80 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -24,6 +24,10 @@ DATE=$(date -u '+%FT%T') # unset some environment variables that could screw things up GREP_OPTIONS= +# default return code +ERR=0 +export ERR + ######################################################################## # FUNCTIONS ######################################################################## @@ -156,7 +160,7 @@ case $COMMAND in # if hosts are specified on the command line, process just # those hosts if [ "$1" ] ; then - process_hosts_known_hosts "$@" + update_known_hosts "$@" || ERR=1 # otherwise, if no hosts are specified, process every host # in the user's known_hosts file @@ -165,7 +169,7 @@ case $COMMAND in failure "known_hosts file '$KNOWN_HOSTS' is empty." fi log "processing known_hosts file..." - process_known_hosts + process_known_hosts || ERR=1 fi log "known_hosts file updated." @@ -181,7 +185,7 @@ case $COMMAND in # process authorized_user_ids file log "processing authorized_user_ids file..." - process_authorized_user_ids "$AUTHORIZED_USER_IDS" + process_authorized_user_ids "$AUTHORIZED_USER_IDS" || ERR=1 log "authorized_keys file updated." ;; @@ -202,3 +206,5 @@ case $COMMAND in Type '$PGRM help' for usage." ;; esac + +exit "$ERR" -- cgit v1.2.3