X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=src%2Fcommon;h=8d8e5063258910ebb75f7fe032ff3a438648cc84;hb=07cb14cdb80ef060e63ba2713ef70b67db9f5783;hp=d7caefdfd3dd50fddae5d0c0fdd53f5187cb6e8e;hpb=3250fce7979ada7e94782430801f5fb76fecbc90;p=monkeysphere.git diff --git a/src/common b/src/common old mode 100755 new mode 100644 index d7caefd..8d8e506 --- a/src/common +++ b/src/common @@ -1,21 +1,21 @@ # -*-shell-script-*- -# Shared bash functions for the monkeysphere +# Shared sh functions for the monkeysphere # # Written by # Jameson Rollins # # Copyright 2008, released under the GPL, version 3 or later -# all caps variables are meant to be user supplied (ie. from config +# all-caps variables are meant to be user supplied (ie. from config # file) and are considered global ######################################################################## # managed directories ETC="/etc/monkeysphere" export ETC -LIB="/var/lib/monkeysphere" -export LIB +CACHE="/var/cache/monkeysphere" +export CACHE ######################################################################## failure() { @@ -23,14 +23,8 @@ failure() { exit ${2:-'1'} } -# write output to stdout -log() { - echo -n "ms: " - echo "$@" -} - # write output to stderr -loge() { +log() { echo -n "ms: " 1>&2 echo "$@" 1>&2 } @@ -48,7 +42,7 @@ cutline() { # retrieve all keys with given user id from keyserver # FIXME: need to figure out how to retrieve all matching keys # (not just first 5) -gpg_fetch_keys() { +gpg_fetch_userid() { local id id="$1" echo 1,2,3,4,5 | \ @@ -75,6 +69,18 @@ check_capability() { return 0 } +# get the full fingerprint of a key ID +get_key_fingerprint() { + local keyID + + keyID="$1" + + gpg --list-key --with-colons --fixed-list-mode \ + --with-fingerprint "$keyID" | grep "$keyID" | \ + grep '^fpr:' | cut -d: -f10 +} + + # convert escaped characters from gpg output back into original # character # FIXME: undo all escape character translation in with-colons gpg output @@ -98,7 +104,7 @@ gpg2known_hosts() { echo -n "$host " gpg --export "$keyID" | \ openpgp2ssh "$keyID" | tr -d '\n' - echo "MonkeySphere${DATE}" + echo " MonkeySphere${DATE}" } # convert key from gpg to ssh authorized_keys format @@ -109,21 +115,22 @@ gpg2authorized_keys() { keyID="$1" userID="$2" - echo -n "MonkeySphere${DATE}:${userID}" gpg --export "$keyID" | \ - openpgp2ssh "$keyID" + openpgp2ssh "$keyID" | tr -d '\n' + echo " MonkeySphere${DATE}:${userID}" } # userid and key policy checking # the following checks policy on the returned keys # - checks that full key has appropriate valididy (u|f) -# - checks key has specified capability (REQUIRED_KEY_CAPABILITY) +# - checks key has specified capability (REQUIRED_*_KEY_CAPABILITY) # - checks that particular desired user id has appropriate validity # see /usr/share/doc/gnupg/DETAILS.gz # expects global variable: "MODE" process_user_id() { local userID local cacheDir + local requiredCapability local requiredPubCapability local gpgOut local line @@ -142,10 +149,16 @@ process_user_id() { userID="$1" cacheDir="$2" - requiredPubCapability=$(echo "$REQUIRED_KEY_CAPABILITY" | tr "[:lower:]" "[:upper:]") + # set the required key capability based on the mode + if [ "$MODE" = 'known_hosts' ] ; then + requiredCapability="$REQUIRED_HOST_KEY_CAPABILITY" + elif [ "$MODE" = 'authorized_keys' ] ; then + requiredCapability="$REQUIRED_USER_KEY_CAPABILITY" + fi + requiredPubCapability=$(echo "$requiredCapability" | tr "[:lower:]" "[:upper:]") # fetch keys from keyserver, return 1 if none found - gpg_fetch_keys "$userID" || return 1 + gpg_fetch_userid "$userID" || return 1 # output gpg info for (exact) userid and store gpgOut=$(gpg --fixed-list-mode --list-key --with-colons \ @@ -153,7 +166,7 @@ process_user_id() { # return 1 if there only "tru" lines are output from gpg if [ -z "$(echo "$gpgOut" | grep -v '^tru:')" ] ; then - loge " key not found." + log " key not found." return 1 fi @@ -182,18 +195,18 @@ process_user_id() { # check primary key validity if [ "$validity" != 'u' -a "$validity" != 'f' ] ; then - loge " unacceptable primary key validity ($validity)." + log " unacceptable primary key validity ($validity)." continue fi # check capability is not Disabled... if check_capability "$capability" 'D' ; then - loge " key disabled." + log " key disabled." continue fi # check overall key capability # must be Encryption and Authentication if ! check_capability "$capability" $requiredPubCapability ; then - loge " unacceptable primary key capability ($capability)." + log " unacceptable primary key capability ($capability)." continue fi @@ -201,7 +214,7 @@ process_user_id() { keyOK=true # add primary key ID to key list if it has required capability - if check_capability "$capability" $REQUIRED_KEY_CAPABILITY ; then + if check_capability "$capability" $requiredCapability ; then keyIDs[${#keyIDs[*]}]="$keyid" fi ;; @@ -224,7 +237,7 @@ process_user_id() { ;; 'sub') # sub keys # add sub key ID to key list if it has required capability - if check_capability "$capability" $REQUIRED_KEY_CAPABILITY ; then + if check_capability "$capability" $requiredCapability ; then keyIDs[${#keyIDs[*]}]="$keyid" fi ;; @@ -234,6 +247,9 @@ process_user_id() { # 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" @@ -242,7 +258,7 @@ process_user_id() { # key cache file if [ "$keyOK" -a "$uidOK" -a "${keyIDs[*]}" ] ; then for keyID in ${keyIDs[@]} ; do - loge " acceptable key/uid found." + log " acceptable key/uid found." if [ "$MODE" = 'known_hosts' ] ; then # export the key @@ -267,21 +283,69 @@ process_user_id() { echo "$cacheDir"/"$userIDHash"."$pubKeyID" } +# update the cache for userid, and prompt to add file to +# authorized_user_ids file if the userid is found in gpg +# and not already in file. +update_userid() { + local userID + local cacheDir + local keyCache + + userID="$1" + cacheDir="$2" + + log "processing userid: '$userID'" + + keyCachePath=$(process_user_id "$userID" "$cacheDir") + + if [ -z "$keyCachePath" ] ; then + return 1 + fi + if ! grep -q "^${userID}\$" "$AUTHORIZED_USER_IDS" ; then + read -p "user ID not currently authorized. authorize? [Y|n]: " OK; OK=${OK:=Y} + if [ ${OK/y/Y} = 'Y' ] ; then + log -n "adding user ID to authorized_user_ids file... " + echo "$userID" >> "$AUTHORIZED_USER_IDS" + echo "done." + else + log "authorized_user_ids file untouched." + fi + fi +} + +# remove a userid from the authorized_user_ids file +remove_userid() { + local userID + + userID="$1" + + log "processing userid: '$userID'" + + if ! grep -q "^${userID}\$" "$AUTHORIZED_USER_IDS" ; then + log "user ID not currently authorized." + return 1 + fi + + log -n "removing user ID '$userID'... " + grep -v "$userID" "$AUTHORIZED_USER_IDS" | sponge "$AUTHORIZED_USER_IDS" + echo "done." +} + # process a host for addition to a known_host file process_host() { local host local cacheDir - local hostKeyCachePath + local keyCachePath host="$1" cacheDir="$2" log "processing host: '$host'" - hostKeyCachePath=$(process_user_id "ssh://${host}" "$cacheDir") + keyCachePath=$(process_user_id "ssh://${host}" "$cacheDir") if [ $? = 0 ] ; then ssh-keygen -R "$host" -f "$USER_KNOWN_HOSTS" - cat "$hostKeyCachePath" >> "$USER_KNOWN_HOSTS" + cat "$keyCachePath" >> "$USER_KNOWN_HOSTS" fi } @@ -298,11 +362,11 @@ process_known_hosts() { cacheDir="$2" # take all the hosts from the known_hosts file (first field), - # grep out all the hashed hosts (lines starting with '|') + # grep out all the hashed hosts (lines starting with '|')... cut -d ' ' -f 1 "$knownHosts" | \ grep -v '^|.*$' | \ while IFS=, read -r -a hosts ; do - # process each host + # ...and process each host for host in ${hosts[*]} ; do process_host "$host" "$cacheDir" done @@ -312,13 +376,13 @@ process_known_hosts() { # update an authorized_keys file after first processing the # authorized_user_ids file update_authorized_keys() { - local cacheDir local msAuthorizedKeys local userAuthorizedKeys + local cacheDir - cacheDir="$1" - msAuthorizedKeys="$2" - userAuthorizedKeys="$3" + msAuthorizedKeys="$1" + userAuthorizedKeys="$2" + cacheDir="$3" process_authorized_ids "$AUTHORIZED_USER_IDS" "$cacheDir" @@ -337,7 +401,8 @@ update_authorized_keys() { cat "$userAuthorizedKeys" >> "$msAuthorizedKeys" echo "done." fi - log "monkeysphere authorized_keys file generated: $msAuthorizedKeys" + log "monkeysphere authorized_keys file generated:" + log "$msAuthorizedKeys" } # process an authorized_*_ids file @@ -367,7 +432,7 @@ process_authorized_ids() { # EXPERIMENTAL (unused) process userids found in authorized_keys file # go through line-by-line, extract monkeysphere userids from comment # fields, and process each userid -process_userids_from_authorized_keys() { +process_authorized_keys() { local authorizedKeys local cacheDir local userID @@ -398,42 +463,43 @@ process_userids_from_authorized_keys() { done } -# update the cache for userid, and prompt to add file to -# authorized_user_ids file if the userid is found in gpg -# and not already in file. -update_userid() { - local userID - local cacheDir - local userIDKeyCache - - userID="$1" - cacheDir="$2" - - log "processing userid: '$userID'" - userIDKeyCache=$(process_user_id "$userID" "$cacheDir") - if [ -z "$userIDKeyCache" ] ; then - return 1 - fi - if ! grep -q "^${userID}\$" "$AUTHORIZED_USER_IDS" ; then - echo "the following userid is not in the authorized_user_ids file:" - echo " $userID" - read -p "would you like to add? [Y|n]: " OK; OK=${OK:=Y} - if [ ${OK/y/Y} = 'Y' ] ; then - log -n " adding userid to authorized_user_ids file... " - echo "$userID" >> "$AUTHORIZED_USER_IDS" - echo "done." - fi - fi -} - # retrieve key from web of trust, and set owner trust to "full" # if key is found. trust_key() { # get the key from the key server - gpg --keyserver "$KEYSERVER" --recv-key "$keyID" || failure "could not retrieve key '$keyID'" + if ! gpg --keyserver "$KEYSERVER" --recv-key "$keyID" ; then + log "could not retrieve key '$keyID'" + return 1 + fi + + # get key fingerprint + fingerprint=$(get_key_fingerprint "$keyID") + + # attach a "non-exportable" signature to the key + # this is required for the key to have any validity at all + # the 'y's on stdin indicates "yes, i really want to sign" + echo -e 'y\ny' | gpg --lsign-key --command-fd 0 "$fingerprint" + + # import "full" trust for fingerprint into gpg + echo ${fingerprint}:5: | gpg --import-ownertrust + if [ $? = 0 ] ; then + log "owner trust updated." + else + failure "there was a problem changing owner trust." + fi +} + +# publish server key to keyserver +publish_server_key() { + read -p "really publish key to $KEYSERVER? [y|N]: " OK; OK=${OK:=N} + if [ ${OK/y/Y} != 'Y' ] ; then + failure "aborting." + fi - # edit the key to change trust - # FIXME: need to figure out how to automate this, - # in a batch mode or something. - gpg --edit-key "$keyID" + # publish host key + # FIXME: need to figure out better way to identify host key + # dummy command so as not to publish fakes keys during testing + # eventually: + #gpg --send-keys --keyserver "$KEYSERVER" $(hostname -f) + echo "NOT PUBLISHED: gpg --send-keys --keyserver $KEYSERVER $(hostname -f)" }