<n>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
local fifo="$2"
local PASS
- if [ "$DISPLAY" ] && type "${SSH_ASKPASS:-ssh-askpass}" >/dev/null; then
+ if [ "$DISPLAY" ] && type "${SSH_ASKPASS:-ssh-askpass}" >/dev/null 2>/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"
check_key_file_permissions() {
local uname
local path
- local stat
- local access
- local gAccess
- local oAccess
-
- # function to check that the given permission corresponds to writability
- is_write() {
- [ "$1" = "w" ]
- }
uname="$1"
path="$2"
- log debug "checking path permission '$path'..."
-
- # return 255 if cannot stat file
- if ! stat=$(ls -ld "$path" 2>/dev/null) ; then
- log error "could not stat path '$path'."
- return 255
- fi
-
- owner=$(echo "$stat" | awk '{ print $3 }')
- gAccess=$(echo "$stat" | cut -c6)
- oAccess=$(echo "$stat" | cut -c9)
-
- # return 1 if path has invalid owner
- if [ "$owner" != "$uname" -a "$owner" != 'root' ] ; then
- 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 " group: $gAccess, other: $oAccess"
- return 2
- fi
-
- # return zero if all clear, or go to next path
- if [ "$path" = '/' ] ; then
- log debug "path ok."
+ if [ "$STRICT_MODES" = 'false' ] ; then
+ log debug "skipping path permission check for '$path' because STRICT_MODES is false..."
return 0
- else
- check_key_file_permissions "$uname" $(dirname "$path")
fi
+ log debug "checking path permission '$path'..."
+ "${SYSSHAREDIR}/checkperms" "$uname" "$path"
}
# return a list of all users on the system
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
### GPG UTILITIES
+# script to determine if gpg version is equal to or greater than specified version
+is_gpg_version_greater_equal() {
+ local gpgVersion=$(gpg --version | head -1 | awk '{ print $3 }')
+ local latest=$(printf '%s\n%s\n' "$1" "$gpgVersion" \
+ | tr '.' ' ' | sort -g -k1 -k2 -k3 \
+ | tail -1 | tr ' ' '.')
+ [[ "$gpgVersion" == "$latest" ]]
+}
+
# retrieve all keys with given user id from keyserver
# FIXME: need to figure out how to retrieve all matching keys
# (not just first N (5 in this case))
# 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 requested user ID has appropriate validity
# (see /usr/share/doc/gnupg/DETAILS.gz)
# output is one line for every found key, in the following format:
#
# all log output must go to stderr, as stdout is used to pass the
# flag:sshKey to the calling function.
-#
-# expects global variable: "MODE"
process_user_id() {
local returnCode=0
local userID
userID="$1"
# 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
+ requiredCapability=${REQUIRED_KEY_CAPABILITY:="a"}
requiredPubCapability=$(echo "$requiredCapability" | tr "[:lower:]" "[:upper:]")
# fetch the user ID if necessary/requested
# being processed in the key files over "bad" keys (key flag '1')
}
+# output all valid keys for specified user ID literal
+keys_for_userid() {
+ local userID
+ local noKey=
+ local nKeys
+ local nKeysOK
+ local ok
+ local sshKey
+ local tmpfile
+
+ userID="$1"
+
+ log verbose "processing: $userID"
+
+ nKeys=0
+ nKeysOK=0
+
+ IFS=$'\n'
+ for line in $(process_user_id "${userID}") ; do
+ # note that key was found
+ nKeys=$((nKeys+1))
+
+ ok=$(echo "$line" | cut -d: -f1)
+ sshKey=$(echo "$line" | cut -d: -f2)
+
+ if [ -z "$sshKey" ] ; then
+ continue
+ fi
+
+ # if key OK, output key to stdout
+ if [ "$ok" -eq '0' ] ; then
+ # note that key was found ok
+ nKeysOK=$((nKeysOK+1))
+
+ printf '%s\n' "$sshKey"
+ fi
+ done
+
+ # if at least one key was found...
+ if [ "$nKeys" -gt 0 ] ; then
+ # if ok keys were found, return 0
+ if [ "$nKeysOK" -gt 0 ] ; then
+ return 0
+ # else return 2
+ else
+ return 2
+ fi
+ # if no keys were found, return 1
+ else
+ return 1
+ fi
+}
+
# process a single host in the known_host file
process_host_known_hosts() {
local host
local tmpfile
# set the key processing mode
- export MODE='known_hosts'
+ export REQUIRED_KEY_CAPABILITY="$REQUIRED_HOST_KEY_CAPABILITY"
host="$1"
userID="ssh://${host}"
local nHostsBAD
local fileCheck
local host
+ local newUmask
# the number of hosts specified on command line
nHosts="$#"
# touch the known_hosts file so that the file permission check
# below won't fail upon not finding the file
- (umask 0022 && touch "$KNOWN_HOSTS")
+ if [ ! -f "$KNOWN_HOSTS" ]; then
+ # make sure to create any files or directories with the appropriate write bits turned off:
+ newUmask=$(printf "%04o" $(( 0$(umask) | 0022 )) )
+ [ -d $(dirname "$KNOWN_HOSTS") ] \
+ || (umask "$newUmask" && mkdir -p -m 0700 $(dirname "$KNOWN_HOSTS") ) \
+ || failure "Could not create path to known_hosts file '$KNOWN_HOSTS'"
+ # make sure to create this file with the appropriate bits turned off:
+ (umask "$newUmask" && touch "$KNOWN_HOSTS") \
+ || failure "Unable to create known_hosts file '$KNOWN_HOSTS'"
+ fi
# check permissions on the known_hosts file path
- check_key_file_permissions $(whoami) "$KNOWN_HOSTS" || failure
+ check_key_file_permissions $(whoami) "$KNOWN_HOSTS" \
+ || failure "Bad permissions governing known_hosts file '$KNOWN_HOSTS'"
# create a lockfile on known_hosts:
lock create "$KNOWN_HOSTS"
trap "lock remove $KNOWN_HOSTS" EXIT
# note pre update file checksum
- fileCheck="$(file_hash "$KNOWN_HOSTS")"
+ fileCheck=$(file_hash "$KNOWN_HOSTS")
for host ; do
# process the host
local sshKey
# set the key processing mode
- export MODE='authorized_keys'
+ export REQUIRED_KEY_CAPABILITY="$REQUIRED_USER_KEY_CAPABILITY"
userID="$1"
# fingerprints, one per line:
list_primary_fingerprints() {
local fake=$(msmktempdir)
+ trap "rm -rf $fake" EXIT
GNUPGHOME="$fake" gpg --no-tty --quiet --import
GNUPGHOME="$fake" gpg --with-colons --fingerprint --list-keys | \
awk -F: '/^fpr:/{ print $10 }'
+ trap - EXIT
rm -rf "$fake"
}