* Fix problem in count_fields() with old AWK

* Make fingerprinting more robust (incl support for newer key types).
This commit is contained in:
Patrick Van der Veken 2021-01-09 14:20:09 +01:00
parent 7c9f951f62
commit fe836edadf

View File

@ -43,7 +43,7 @@
# or LOCAL_CONFIG_FILE instead # or LOCAL_CONFIG_FILE instead
# define the version (YYYY-MM-DD) # define the version (YYYY-MM-DD)
typeset -r SCRIPT_VERSION="2020-12-30" typeset -r SCRIPT_VERSION="2021-01-09"
# name of the global configuration file (script) # name of the global configuration file (script)
typeset -r GLOBAL_CONFIG_FILE="manage_ssh.conf" typeset -r GLOBAL_CONFIG_FILE="manage_ssh.conf"
# name of the local configuration file (script) # name of the local configuration file (script)
@ -89,6 +89,7 @@ typeset KEY_COUNT=0
typeset KEY_1024_COUNT=0 typeset KEY_1024_COUNT=0
typeset KEY_2048_COUNT=0 typeset KEY_2048_COUNT=0
typeset KEY_4096_COUNT=0 typeset KEY_4096_COUNT=0
typeset KEY_BAD_COUNT=0
typeset KEY_OTHER_COUNT=0 typeset KEY_OTHER_COUNT=0
typeset RESOLVE_ALIAS="" typeset RESOLVE_ALIAS=""
typeset SSH_KEYGEN_OPTS="" typeset SSH_KEYGEN_OPTS=""
@ -530,7 +531,15 @@ typeset CHECK_LINE="$1"
typeset CHECK_DELIM="$2" typeset CHECK_DELIM="$2"
typeset NUM_FIELDS=0 typeset NUM_FIELDS=0
case "${OS_NAME}" in
HP-UX)
# wark around old awk's limit on input of max 3000 bytes
NUM_FIELDS=$(print "${CHECK_LINE}" | tr "${CHECK_DELIM}" '\n' 2>/dev/null | wc -l 2>/dev/null)
;;
*)
NUM_FIELDS=$(print "${CHECK_LINE}" | awk -F "${CHECK_DELIM}" '{ print NF }' 2>/dev/null) NUM_FIELDS=$(print "${CHECK_LINE}" | awk -F "${CHECK_DELIM}" '{ print NF }' 2>/dev/null)
;;
esac
print "${NUM_FIELDS}" print "${NUM_FIELDS}"
@ -1492,6 +1501,7 @@ function update_fingerprints
typeset FINGER_LINE="$1" typeset FINGER_LINE="$1"
typeset FINGER_FIELDS=0 typeset FINGER_FIELDS=0
typeset FINGER_USER="" typeset FINGER_USER=""
typeset FINGER_TYPE=""
typeset FINGERPRINT="" typeset FINGERPRINT=""
typeset FINGER_RC=0 typeset FINGER_RC=0
@ -1500,7 +1510,11 @@ typeset FINGER_RC=0
# line should have 3 fields # line should have 3 fields
FINGER_FIELDS=$(count_fields "${FINGER_LINE}" ",") FINGER_FIELDS=$(count_fields "${FINGER_LINE}" ",")
(( FINGER_FIELDS != 3 )) && die "line '${FINGER_LINE}' has missing or too many field(s) (should be 3))" if (( FINGER_FIELDS != 3 ))
then
warn "line '${FINGER_LINE}' has missing or too many field(s) (should be 3))"
return 1
fi
# create fingerprint # create fingerprint
FINGER_USER=$(print "${FINGER_LINE}" | awk -F, '{print $1}') FINGER_USER=$(print "${FINGER_LINE}" | awk -F, '{print $1}')
@ -1510,20 +1524,33 @@ FINGERPRINT=$(ssh-keygen ${SSH_KEYGEN_OPTS} -l -f "${TMP_FILE}" 2>&1)
FINGER_RC=$? FINGER_RC=$?
if (( FINGER_RC == 0 )) if (( FINGER_RC == 0 ))
then then
case "${OS_NAME}" in case "${FINGERPRINT}" in
HP-UX) *\(RSA\)*)
# shellcheck disable=SC2086 FINGER_TYPE="RSA"
FINGER_ENTRY="$(print ${FINGERPRINT} | awk '{print $1,$2,$4}')" ;;
*\(DSA\)*)
FINGER_TYPE="DSA"
;;
*\(ECDSA\)*)
FINGER_TYPE="ECDSA"
;;
*\(ED25519\)*)
FINGER_TYPE="ED25519"
;; ;;
*) *)
# shellcheck disable=SC2086 FINGER_TYPE="UNKNOWN"
FINGER_ENTRY="$(print ${FINGERPRINT} | awk '{print $1,$2,$5}')"
;; ;;
esac esac
log "${FINGER_USER}->${FINGER_ENTRY}"
print "${FINGER_USER} ${FINGER_ENTRY}" >> "${LOCAL_DIR}/fingerprints" # shellcheck disable=SC2086
FINGER_ENTRY="$(print ${FINGERPRINT} | awk '{print $1,$2}')"
log "${FINGER_USER}->${FINGER_ENTRY} (${FINGER_TYPE})"
print "${FINGER_USER} ${FINGER_ENTRY} (${FINGER_TYPE})" >> "${LOCAL_DIR}/fingerprints"
else else
die "failed to obtain fingerprint for key ${FINGER_LINE} [RC=${FINGER_RC}]" warn "failed to obtain fingerprint for key ${FINGER_LINE} [RC=${FINGER_RC}]"
KEY_BAD_COUNT=$(( KEY_BAD_COUNT + 1 ))
return 1
fi fi
# check bit count # check bit count
case "${FINGERPRINT}" in case "${FINGERPRINT}" in
@ -2010,22 +2037,26 @@ case ${ARG_ACTION} in
# are keys stored in a file or a directory? # are keys stored in a file or a directory?
if [[ -n "${KEYS_DIR}" ]] if [[ -n "${KEYS_DIR}" ]]
then then
cat "${KEYS_DIR}"/* | sort | while read -r LINE cat "${KEYS_DIR}"/* | grep -v -E -e '^#' -e '^$' 2>/dev/null | sort 2>/dev/null |\
while read -r LINE
do do
update_fingerprints "${LINE}" update_fingerprints "${LINE}"
KEY_COUNT=$(( KEY_COUNT + 1 )) KEY_COUNT=$(( KEY_COUNT + 1 ))
done done
else else
grep -v -E -e '^#' -e '^$' "${KEYS_FILE}" 2>/dev/null | sort 2>/dev/null |\
while read -r LINE while read -r LINE
do do
update_fingerprints "${LINE}" update_fingerprints "${LINE}"
done < "${KEYS_FILE}" KEY_COUNT=$(( KEY_COUNT + 1 ))
done
fi fi
log "${KEY_COUNT} public keys discovered with following bits distribution:" log "${KEY_COUNT} public keys discovered with following bits distribution:"
log " 1024 bits: ${KEY_1024_COUNT}" log " 1024 bits: ${KEY_1024_COUNT}"
log " 2048 bits: ${KEY_2048_COUNT}" log " 2048 bits: ${KEY_2048_COUNT}"
log " 4096 bits: ${KEY_4096_COUNT}" log " 4096 bits: ${KEY_4096_COUNT}"
log " others : ${KEY_OTHER_COUNT}" log " others : ${KEY_OTHER_COUNT}"
log " bad : ${KEY_BAD_COUNT}"
log "finished updating public key fingerprints" log "finished updating public key fingerprints"
;; ;;
4) # apply SSH controls locally (root user) 4) # apply SSH controls locally (root user)