From: Jameson Graef Rollins Date: Tue, 17 Jun 2008 00:00:46 +0000 (-0400) Subject: Merge branch 'master' into no-cache X-Git-Tag: monkeysphere_0.1-1~19^2~4 X-Git-Url: https://codewiz.org/gitweb?a=commitdiff_plain;h=e619b23879fde5703da435141754324dcf7cfa53;hp=deb41134ca527508253244cfa8860a2031034825;p=monkeysphere.git Merge branch 'master' into no-cache Conflicts: src/common src/monkeysphere src/monkeysphere-ssh-proxycommand --- diff --git a/src/common b/src/common index d1554a6..64d28cb 100644 --- a/src/common +++ b/src/common @@ -143,17 +143,18 @@ process_user_id() { local requiredCapability local requiredPubCapability local gpgOut + local userIDHash + local keyCacheDir local line local type local validity local keyid local uidfpr - local capability + local usage local keyOK local pubKeyID local uidOK local keyIDs - local userIDHash local keyID userID="$1" @@ -174,126 +175,121 @@ process_user_id() { fi # output gpg info for (exact) userid and store - gpgOut=$(gpg --fixed-list-mode --list-key --with-colons \ - ="$userID" 2> /dev/null) - - # return 1 if there only "tru" lines are output from gpg - if [ -z "$(echo "$gpgOut" | grep -v '^tru:')" ] ; then - log " key not found in keychain." - return 1 + gpgOut=$(gpg --list-key --fixed-list-mode --with-colon \ + --with-fingerprint --with-fingerprint \ + ="$userID" 2>/dev/null) + + # if the gpg query return code is not 0, return 1 + if [ "$?" -ne 0 ] ; then + log " key not found." + return 1 fi + echo "$gpgOut" + # loop over all lines in the gpg output and process. # need to do it this way (as opposed to "while read...") so that # variables set in loop will be visible outside of loop - for line in $(seq 1 $(echo "$gpgOut" | wc -l)) ; do - - # read the contents of the line - type=$(echo "$gpgOut" | cutline "$line" | cut -d: -f1) - validity=$(echo "$gpgOut" | cutline "$line" | cut -d: -f2) - keyid=$(echo "$gpgOut" | cutline "$line" | cut -d: -f5) - uidfpr=$(echo "$gpgOut" | cutline "$line" | cut -d: -f10) - capability=$(echo "$gpgOut" | cutline "$line" | cut -d: -f12) - + echo "$gpgOut" | cut -d: -f1,2,5,10,12 | \ + while IFS=: read -r type validity keyid uidfpr usage ; do # process based on record type case $type in 'pub') # primary keys # new key, wipe the slate keyOK= - pubKeyID= uidOK= - keyIDs= - - pubKeyID="$keyid" + pubKeyOK= + fingerprint= - # check primary key validity + # if overall key is not valid, skip if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then log " unacceptable primary key validity ($validity)." continue fi - # check capability is not Disabled... - if check_capability "$capability" 'D' ; then + # if overall key is disabled, skip + if check_capability "$usage" 'D' ; then log " key disabled." continue fi - # check overall key capability - # must be Encryption and Authentication - if ! check_capability "$capability" $requiredPubCapability ; then - log " unacceptable primary key capability ($capability)." + # if overall key capability is not ok, skip + if ! check_capability "$usage" $requiredPubCapability ; then + log " unacceptable primary key capability ($usage)." continue fi - # mark if primary key is acceptable + # mark overall key as ok keyOK=true - # add primary key ID to key list if it has required capability - if check_capability "$capability" $requiredCapability ; then - keyIDs[${#keyIDs[*]}]="$keyid" + # mark primary key as ok if capability is ok + if check_capability "$usage" $requiredCapability ; then + pubKeyOK=true fi ;; 'uid') # user ids - # check key ok and we have key fingerprint + # if the overall key is not ok, skip if [ -z "$keyOK" ] ; then continue fi - # check key validity - if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then + # if an acceptable user ID was already found, skip + if [ "$uidOK" ] ; then continue fi - # check the uid matches + # if the user ID does not match, skip if [ "$(unescape "$uidfpr")" != "$userID" ] ; then continue fi + # if the user ID validity is not ok, skip + if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then + continue + fi - # mark if uid acceptable + # mark user ID acceptable uidOK=true + + # output a line for the primary key + # 0 = ok, 1 = bad + if [ "$keyOK" -a "$uidOK" -a "$pubKeyOK" ] ; then + log " acceptable key found" + echo 0 "$fingerprint" + else + echo 1 "$fingerprint" + fi ;; 'sub') # sub keys - # add sub key ID to key list if it has required capability - if check_capability "$capability" $requiredCapability ; then - keyIDs[${#keyIDs[*]}]="$keyid" + # unset acceptability of last key + subKeyOK= + fingerprint= + + # if the overall key is not ok, skip + if [ -z "$keyOK" ] ; then + continue + fi + # if sub key validity is not ok, skip + if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then + continue + fi + # if sub key capability is not ok, skip + if ! check_capability "$usage" $requiredCapability ; then + continue + fi + + # mark sub key as ok + subKeyOK=true + ;; + 'fpr') # key fingerprint + fingerprint="$uidfpr" + + # output a line for the last subkey + # 0 = ok, 1 = bad + if [ "$keyOK" -a "$uidOK" -a "$subKeyOK" ] ; then + log " acceptable key found" + echo 0 "$fingerprint" + else + echo 1 "$fingerprint" fi ;; esac done - - # hash userid for cache file name - userIDHash=$(echo "$userID" | sha1sum | awk '{ print $1 }') - - # make sure the cache directory exists - mkdir -p "$cacheDir" - - # touch/clear key cache file - # (will be left empty if there are noacceptable keys) - > "$cacheDir"/"$userIDHash"."$pubKeyID" - - # for each acceptable key, write an ssh key line to the - # key cache file - if [ "$keyOK" -a "$uidOK" -a "${keyIDs[*]}" ] ; then - for keyID in ${keyIDs[@]} ; do - log " acceptable key/userID found." - - if [ "$MODE" = 'known_hosts' ] ; then - # export the key - gpg2known_hosts "$keyID" "$userID" >> \ - "$cacheDir"/"$userIDHash"."$pubKeyID" - # hash the cache file if specified - if [ "$HASH_KNOWN_HOSTS" = "true" ] ; then - ssh-keygen -H -f "$cacheDir"/"$userIDHash"."$pubKeyID" > /dev/null 2>&1 - rm "$cacheDir"/"$userIDHash"."$pubKeyID".old - fi - elif [ "$MODE" = 'authorized_keys' ] ; then - # export the key - # FIXME: needs to apply extra options for authorized_keys - # lines if specified - gpg2authorized_keys "$keyID" "$userID" >> \ - "$cacheDir"/"$userIDHash"."$pubKeyID" - fi - done - fi - - # echo the path to the key cache file - echo "$cacheDir"/"$userIDHash"."$pubKeyID" } # update the cache for userid, and prompt to add file to @@ -339,16 +335,34 @@ remove_userid() { log "processing userid: '$userID'" + # check if user ID is in the authorized_user_ids file if ! grep -q "^${userID}\$" "$AUTHORIZED_USER_IDS" ; then log "user ID not currently authorized." return 1 fi + # remove user ID from file log -n "removing user ID '$userID'... " grep -v "$userID" "$AUTHORIZED_USER_IDS" | sponge "$AUTHORIZED_USER_IDS" echo "done." } +# remove all keys from specified key cache from known_hosts file +remove_known_hosts_host_keys() { + local keyCachePath + local hosts + local type + local key + local comment + + keyCachePath="$1" + + meat "${keyCachePath}/keys" | \ + while read -r hosts type key comment ; do + grep -v "$key" "$USER_KNOWN_HOSTS" | sponge "$USER_KNOWN_HOSTS" + done +} + # process a host for addition to a known_host file process_host() { local host @@ -360,11 +374,18 @@ process_host() { log "processing host: $host" - keyCachePath=$(process_user_id "ssh://${host}" "$cacheDir") - if [ $? = 0 ] ; then - ssh-keygen -R "$host" -f "$USER_KNOWN_HOSTS" - cat "$keyCachePath" >> "$USER_KNOWN_HOSTS" - fi + userID="ssh://${host}" + process_user_id "ssh://${host}" + exit + process_user_id "ssh://${host}" | \ + while read -r ok key ; do + # remove the old host key line + remove_known_hosts_host_keys "$key" + # if key OK, add new host line + if [ "$ok" -eq '0' ] ; then + known_hosts_line "$host" "$key" >> "$USER_KNOWN_HOSTS" + fi + done } # process known_hosts file @@ -430,17 +451,14 @@ process_authorized_ids() { authorizedIDs="$1" cacheDir="$2" - # clean out keys file and remake keys directory - rm -rf "$cacheDir" - mkdir -p "$cacheDir" - - # loop through all user ids in file - # FIXME: needs to handle authorized_keys options - cat "$authorizedIDs" | meat | \ - while read -r userID ; do - # process the userid - log "processing userid: '$userID'" - process_user_id "$userID" "$cacheDir" > /dev/null + process_user_id "$userID" | \ + while read -r ok key ; do + # remove the old host key line + remove_authorized_keys_user_keys "$key" + # if key OK, add new host line + if [ "$ok" -eq '0' ] ; then + authorized_keys_line "$userID" "$key" >> "$USER_AUTHORIZED_KEYS" + fi done } diff --git a/src/monkeysphere b/src/monkeysphere index 230de06..8e4c4eb 100755 --- a/src/monkeysphere +++ b/src/monkeysphere @@ -148,7 +148,7 @@ case $COMMAND in # those hosts if [ "$1" ] ; then for host ; do - process_host "$host" "$hostKeysCacheDir" + process_host "$host" done # otherwise, if no hosts are specified, process every user @@ -158,7 +158,7 @@ case $COMMAND in failure "known_hosts file '$USER_KNOWN_HOSTS' is empty." fi log "processing known_hosts file..." - process_known_hosts "$hostKeysCacheDir" + process_known_hosts fi ;; @@ -167,7 +167,7 @@ case $COMMAND in failure "you must specify at least one userid." fi for userID ; do - update_userid "$userID" "$userKeysCacheDir" + update_userid "$userID" done log "Run the following to update your monkeysphere authorized_keys file:" log "$PGRM update-authorized_keys" diff --git a/src/monkeysphere-ssh-proxycommand b/src/monkeysphere-ssh-proxycommand index 3887e48..4b90a0d 100755 --- a/src/monkeysphere-ssh-proxycommand +++ b/src/monkeysphere-ssh-proxycommand @@ -44,6 +44,8 @@ hostKey=$(ssh-keygen -F "$HOST") # don't check the keyserver if [ "$hostKey" ] ; then CHECK_KEYSERVER="false" +else + CHECK_KEYSERVER="true" fi export CHECK_KEYSERVER