X-Git-Url: https://codewiz.org/gitweb?a=blobdiff_plain;f=src%2Fshare%2Fcommon;h=8e2232d659350558e472bd5f37c365d050317b8d;hb=f3a03d72bc9c01491fc1cfccdbcef353db058548;hp=a21d803b90a83ee34ebe6ceace98ad1e20f7a29a;hpb=adec130f20e374ae0d8f615f45916e27771a0278;p=monkeysphere.git diff --git a/src/share/common b/src/share/common index a21d803..8e2232d 100644 --- a/src/share/common +++ b/src/share/common @@ -13,34 +13,14 @@ # all-caps variables are meant to be user supplied (ie. from config # file) and are considered global -######################################################################## -### COMMON VARIABLES - -# managed directories -SYSCONFIGDIR=${MONKEYSPHERE_SYSCONFIGDIR:-"/etc/monkeysphere"} -export SYSCONFIGDIR - -# monkeysphere version -VERSION=0.23 - -# default log level -LOG_LEVEL="INFO" - -# default keyserver -KEYSERVER="pool.sks-keyservers.net" - -# whether or not to check keyservers by defaul -CHECK_KEYSERVER="true" - -# default monkeysphere user -MONKEYSPHERE_USER="monkeysphere" - -# default about whether or not to prompt -PROMPT="true" - ######################################################################## ### UTILITY FUNCTIONS +# output version info +version() { + cat "${SYSSHAREDIR}/VERSION" +} + # failure function. exits with code 255, unless specified otherwise. failure() { [ "$1" ] && echo "$1" >&2 @@ -96,11 +76,10 @@ log() { fi if [ "$priority" = "$level" -a "$output" = 'true' ] ; then if [ "$1" ] ; then - echo -n "ms: " >&2 - echo "$@" >&2 + echo "$@" else - cat >&2 - fi + cat + fi | sed 's/^/'"${LOG_PREFIX}"'/' >&2 fi done } @@ -168,8 +147,8 @@ lock() { local action="$1" local file="$2" - if ! ( which lockfile-create >/dev/null 2>/dev/null ) ; then - if ! ( which lockfile >/dev/null ); then + if ! ( type lockfile-create &>/dev/null ) ; then + if ! ( type lockfile &>/dev/null ); then failure "Neither lockfile-create nor lockfile are in the path!" fi use_lockfileprogs= @@ -218,7 +197,7 @@ advance_date() { local shortunits # try things the GNU way first - if date -d "$number $longunits" "$format" >/dev/null 2>&1; then + if date -d "$number $longunits" "$format" &>/dev/null; then date -d "$number $longunits" "$format" else # otherwise, convert to (a limited version of) BSD date syntax: @@ -273,7 +252,13 @@ check_capability() { # hash of a file file_hash() { - md5sum "$1" 2> /dev/null + if type md5sum &>/dev/null ; then + md5sum "$1" + elif type md5 &>/dev/null ; then + md5 "$1" + else + failure "Neither md5sum nor md5 are in the path!" + fi } # convert escaped characters in pipeline from gpg output back into @@ -306,7 +291,8 @@ Please specify how long the key should be valid. y = key expires in n years EOF while [ -z "$keyExpire" ] ; do - read -p "Key is valid for? (0) " keyExpire + printf "Key is valid for? (0) " >&2 + read keyExpire if ! test_gpg_expire ${keyExpire:=0} ; then echo "invalid value" >&2 unset keyExpire @@ -324,7 +310,9 @@ passphrase_prompt() { local fifo="$2" local PASS - if [ "$DISPLAY" ] && which "${SSH_ASKPASS:-ssh-askpass}" >/dev/null; then + if [ "$DISPLAY" ] && type "${SSH_ASKPASS:-ssh-askpass}" >/dev/null; then + printf 'Launching "%s"\n' "${SSH_ASKPASS:-ssh-askpass}" | log info + printf '(with prompt "%s")\n' "$prompt" | log debug "${SSH_ASKPASS:-ssh-askpass}" "$prompt" > "$fifo" else read -s -p "$prompt" PASS @@ -334,52 +322,6 @@ passphrase_prompt() { fi } -test_gnu_dummy_s2k_extension() { - -# this block contains a demonstration private key that has had the -# primary key stripped out using the GNU S2K extension known as -# "gnu-dummy" (see /usr/share/doc/gnupg/DETAILS.gz). The subkey is -# present in cleartext, however. - -# openpgp2ssh will be able to deal with this based on whether the -# local copy of GnuTLS contains read_s2k support that can handle it. - -# read up on that here: - -# http://lists.gnu.org/archive/html/gnutls-devel/2008-08/msg00005.html - -echo " ------BEGIN PGP PRIVATE KEY BLOCK----- -Version: GnuPG v1.4.9 (GNU/Linux) - -lQCVBEO3YdABBACRqqEnucag4+vyZny2M67Pai5+5suIRRvY+Ly8Ms5MvgCi3EVV -xT05O/+0ShiRaf+QicCOFrhbU9PZzzU+seEvkeW2UCu4dQfILkmj+HBEIltGnHr3 -G0yegHj5pnqrcezERURf2e17gGFWX91cXB9Cm721FPXczuKraphKwCA9PwARAQAB -/gNlAkdOVQG0OURlbW9uc3RyYXRpb24gS2V5IGZvciBTMksgR05VIGV4dGVuc2lv -biAxMDAxIC0tIGdudS1kdW1teYi8BBMBAgAmBQJDt2HQAhsDBQkB4TOABgsJCAcD -AgQVAggDBBYCAwECHgECF4AACgkQQZUwSa4UDezTOQP/TMQXUVrWzHYZGopoPZ2+ -ZS3qddiznBHsgb7MGYg1KlTiVJSroDUBCHIUJvdQKZV9zrzrFl47D07x6hGyUPHV -aZXvuITW8t1o5MMHkCy3pmJ2KgfDvdUxrBvLfgPMICA4c6zA0mWquee43syEW9NY -g3q61iPlQwD1J1kX1wlimLCdAdgEQ7dh0AEEANAwa63zlQbuy1Meliy8otwiOa+a -mH6pxxUgUNggjyjO5qx+rl25mMjvGIRX4/L1QwIBXJBVi3SgvJW1COZxZqBYqj9U -8HVT07mWKFEDf0rZLeUE2jTm16cF9fcW4DQhW+sfYm+hi2sY3HeMuwlUBK9KHfW2 -+bGeDzVZ4pqfUEudABEBAAEAA/0bemib+wxub9IyVFUp7nPobjQC83qxLSNzrGI/ -RHzgu/5CQi4tfLOnwbcQsLELfker2hYnjsLrT9PURqK4F7udrWEoZ1I1LymOtLG/ -4tNZ7Mnul3wRC2tCn7FKx8sGJwGh/3li8vZ6ALVJAyOia5TZ/buX0+QZzt6+hPKk -7MU1WQIA4bUBjtrsqDwro94DvPj3/jBnMZbXr6WZIItLNeVDUcM8oHL807Am97K1 -ueO/f6v1sGAHG6lVPTmtekqPSTWBfwIA7CGFvEyvSALfB8NUa6jtk27NCiw0csql -kuhCmwXGMVOiryKEfegkIahf2bAd/gnWHPrpWp7bUE20v8YoW22I4wIAhnm5Wr5Q -Sy7EHDUxmJm5TzadFp9gq08qNzHBpXSYXXJ3JuWcL1/awUqp3tE1I6zZ0hZ38Ia6 -SdBMN88idnhDPqPoiKUEGAECAA8FAkO3YdACGyAFCQHhM4AACgkQQZUwSa4UDezm -vQP/ZhK+2ly9oI2z7ZcNC/BJRch0/ybQ3haahII8pXXmOThpZohr/LUgoWgCZdXg -vP6yiszNk2tIs8KphCAw7Lw/qzDC2hEORjWO4f46qk73RAgSqG/GyzI4ltWiDhqn -vnQCFl3+QFSe4zinqykHnLwGPMXv428d/ZjkIc2ju8dRsn4= -=CR5w ------END PGP PRIVATE KEY BLOCK----- -" | openpgp2ssh 4129E89D17C1D591 >/dev/null 2>/dev/null - -} - # remove all lines with specified string from specified file remove_line() { local file @@ -398,7 +340,7 @@ remove_line() { fi # if the string is in the file... - if grep -q -F "$string" "$file" 2> /dev/null ; then + if grep -q -F "$string" "$file" 2>/dev/null ; then tempfile=$(mktemp "${file}.XXXXXXX") || \ failure "Unable to make temp file '${file}.XXXXXXX'" @@ -420,12 +362,15 @@ remove_monkeysphere_lines() { file="$1" - if [ -z "$file" ] ; then + # return error if file does not exist + if [ ! -e "$file" ] ; then return 1 fi - if [ ! -e "$file" ] ; then - return 1 + # just return ok if the file is empty, since there aren't any + # lines to remove + if [ ! -s "$file" ] ; then + return 0 fi tempfile=$(mktemp "${file}.XXXXXXX") || \ @@ -446,7 +391,7 @@ translate_ssh_variables() { path="$2" # get the user's home directory - userHome=$(getent passwd "$uname" | cut -d: -f6) + userHome=$(get_homedir "$uname") # translate '%u' to user name path=${path/\%u/"$uname"} @@ -481,6 +426,12 @@ check_key_file_permissions() { log debug "checking path permission '$path'..." + # rewrite path if it points to a symlink + if [ -h "$path" ] ; then + path=$(readlink -f "$path") + log debug "checking path symlink '$path'..." + fi + # return 255 if cannot stat file if ! stat=$(ls -ld "$path" 2>/dev/null) ; then log error "could not stat path '$path'." @@ -493,24 +444,52 @@ check_key_file_permissions() { # return 1 if path has invalid owner if [ "$owner" != "$uname" -a "$owner" != 'root' ] ; then - log error "improper ownership on path '$path'." + log error "improper ownership on path '$path':" + log error " $owner != ($uname|root)" return 1 fi # return 2 if path has group or other writability if is_write "$gAccess" || is_write "$oAccess" ; then - log error "improper group or other writability on path '$path'." + log error "improper group or other writability on path '$path':" + log error " group: $gAccess, other: $oAccess" return 2 fi # return zero if all clear, or go to next path if [ "$path" = '/' ] ; then + log debug "path ok." return 0 else check_key_file_permissions "$uname" $(dirname "$path") fi } +# return a list of all users on the system +list_users() { + if type getent &>/dev/null ; then + # for linux and FreeBSD systems + getent passwd | cut -d: -f1 + elif type dscl &>/dev/null ; then + # for Darwin systems + dscl localhost -list /Search/Users + else + failure "Neither getent or dscl is in the path! Could not determine list of users." + fi +} + +# return the path to the home directory of a user +get_homedir() { + local uname=${1:-`whoami`} + eval "echo ~${uname}" +} + +# return the primary group of a user +get_primary_group() { + local uname=${1:-`whoami`} + groups "$uname" | sed 's/^..* : //' | awk '{ print $1 }' +} + ### CONVERSION UTILITIES # output the ssh key for a given key ID @@ -519,20 +498,29 @@ gpg2ssh() { keyID="$1" - gpg --export "$keyID" | openpgp2ssh "$keyID" 2> /dev/null + gpg --export "$keyID" | openpgp2ssh "$keyID" 2>/dev/null } # output known_hosts line from ssh key ssh2known_hosts() { local host + local port local key - host="$1" + # FIXME this does not properly deal with IPv6 hosts using the + # standard port (because it's unclear whether their final + # colon-delimited address section is a port number or an address + # string) + host=${1%:*} + port=${1##*:} key="$2" - echo -n "$host " - echo -n "$key" | tr -d '\n' - echo " MonkeySphere${DATE}" + # specify the host and port properly for new ssh known_hosts + # format + if [ "$port" != "$host" ] ; then + host="[${host}]:${port}" + fi + printf "%s %s MonkeySphere%s\n" "$host" "$key" "$DATE" } # output authorized_keys line from ssh key @@ -543,41 +531,43 @@ ssh2authorized_keys() { userID="$1" key="$2" - echo -n "$key" | tr -d '\n' - echo " MonkeySphere${DATE} ${userID}" + printf "%s MonkeySphere%s %s\n" "$key" "$DATE" "$userID" } # convert key from gpg to ssh known_hosts format gpg2known_hosts() { local host local keyID + local key host="$1" keyID="$2" + key=$(gpg2ssh "$keyID") + # NOTE: it seems that ssh-keygen -R removes all comment fields from # all lines in the known_hosts file. why? # NOTE: just in case, the COMMENT can be matched with the # following regexp: # '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$' - echo -n "$host " - gpg2ssh "$keyID" | tr -d '\n' - echo " MonkeySphere${DATE}" + printf "%s %s MonkeySphere%s\n" "$host" "$key" "$DATE" } # convert key from gpg to ssh authorized_keys format gpg2authorized_keys() { local userID local keyID + local key userID="$1" keyID="$2" + key=$(gpg2ssh "$keyID") + # NOTE: just in case, the COMMENT can be matched with the # following regexp: # '^MonkeySphere[[:digit:]]{4}(-[[:digit:]]{2}){2}T[[:digit:]]{2}(:[[:digit:]]{2}){2}$' - gpg2ssh "$keyID" | tr -d '\n' - echo " MonkeySphere${DATE} ${userID}" + printf "%s MonkeySphere%s %s\n" "$key" "$DATE" "$userID" } ### GPG UTILITIES @@ -599,7 +589,7 @@ gpg_fetch_userid() { echo 1,2,3,4,5 | \ gpg --quiet --batch --with-colons \ --command-fd 0 --keyserver "$KEYSERVER" \ - --search ="$userID" > /dev/null 2>&1 + --search ="$userID" &>/dev/null returnCode="$?" return "$returnCode" @@ -732,14 +722,14 @@ process_user_id() { if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then log verbose " * acceptable primary key." if [ -z "$sshKey" ] ; then - log error " ! primary key could not be translated (not RSA or DSA?)." + log error " ! primary key could not be translated (not RSA?)." else echo "0:${sshKey}" fi else log debug " - unacceptable primary key." if [ -z "$sshKey" ] ; then - log debug " ! primary key could not be translated (not RSA or DSA?)." + log debug " ! primary key could not be translated (not RSA?)." else echo "1:${sshKey}" fi @@ -790,14 +780,14 @@ process_user_id() { if [ "$keyOK" -a "$uidOK" -a "$lastKeyOK" ] ; then log verbose " * acceptable sub key." if [ -z "$sshKey" ] ; then - log error " ! sub key could not be translated (not RSA or DSA?)." + log error " ! sub key could not be translated (not RSA?)." else echo "0:${sshKey}" fi else log debug " - unacceptable sub key." if [ -z "$sshKey" ] ; then - log debug " ! sub key could not be translated (not RSA or DSA?)." + log debug " ! sub key could not be translated (not RSA?)." else echo "1:${sshKey}" fi @@ -859,7 +849,7 @@ process_host_known_hosts() { # hash from stdin to stdout tmpfile=$(mktemp ${TMPDIR:-/tmp}/tmp.XXXXXXXXXX) ssh2known_hosts "$host" "$sshKey" > "$tmpfile" - ssh-keygen -H -f "$tmpfile" 2> /dev/null + ssh-keygen -H -f "$tmpfile" 2>/dev/null cat "$tmpfile" >> "$KNOWN_HOSTS" rm -f "$tmpfile" "${tmpfile}.old" else @@ -909,7 +899,7 @@ update_known_hosts() { (umask 0022 && touch "$KNOWN_HOSTS") # check permissions on the known_hosts file path - check_key_file_permissions "$USER" "$KNOWN_HOSTS" || failure + check_key_file_permissions $(whoami) "$KNOWN_HOSTS" || failure # create a lockfile on known_hosts: lock create "$KNOWN_HOSTS" @@ -970,7 +960,8 @@ process_known_hosts() { failure "known_hosts file '$KNOWN_HOSTS' does not exist." fi - log debug "processing known_hosts file..." + log debug "processing known_hosts file:" + log debug " $KNOWN_HOSTS" hosts=$(meat "$KNOWN_HOSTS" | cut -d ' ' -f 1 | grep -v '^|.*$' | tr , ' ' | tr '\n' ' ') @@ -1058,8 +1049,11 @@ update_authorized_keys() { nIDsOK=0 nIDsBAD=0 + log debug "updating authorized_keys file:" + log debug " $AUTHORIZED_KEYS" + # check permissions on the authorized_keys file path - check_key_file_permissions "$USER" "$AUTHORIZED_KEYS" || failure + check_key_file_permissions $(whoami) "$AUTHORIZED_KEYS" || failure # create a lockfile on authorized_keys lock create "$AUTHORIZED_KEYS" @@ -1131,12 +1125,13 @@ process_authorized_user_ids() { failure "authorized_user_ids file '$authorizedUserIDs' does not exist." fi - # check permissions on the authorized_user_ids file path - check_key_file_permissions "$USER" "$authorizedUserIDs" || failure + log debug "processing authorized_user_ids file:" + log debug " $authorizedUserIDs" - log debug "processing authorized_user_ids file..." + # check permissions on the authorized_user_ids file path + check_key_file_permissions $(whoami) "$authorizedUserIDs" || failure - if ! meat "$authorizedUserIDs" > /dev/null ; then + if ! meat "$authorizedUserIDs" >/dev/null ; then log debug " no user IDs to process." return fi