ssh-phraseless-keyscan

12th May 2016 at 2:37pm
Bash CodeSnippets
#!/bin/bash

set -uE -o pipefail
umask 077

print_usage() {
    local rc="${1:-0}"; shift
    local msg="${*:-}"
    if [[ -n "$msg" ]] ; then
        >&2 echo "$msg"
    fi
    >&2 echo "Syntax: ${0##*/} <path>"
    exit $rc
}

abort() {
    local msg="$*"
    >&2 echo "$msg; aborting!"
    exit 1
}

is_secure_permissions() {
    local file="$1"
    local perms="$(stat -c %A "$file")"
    if [[ ! "${perms:4:6}" == "------" ]] ; then
        return 1
    else
        return 0
    fi
}

is_passphraseless() {
    local src_key="$1"
    local sock="$(mktemp -u -t "${0##*/}.XXXXXXXX")"
    local dot_ssh="$(mktemp -d -t "${0##*/}.XXXXXXXX")"
    local test_key="$(mktemp --tmpdir="$dot_ssh" -t "${0##*/}.XXXXXXXX")"
    local rc=1

    trap "rm -rf --one-file-system '$sock' '$dot_ssh'" EXIT INT TERM HUP USR1 USR2
    cat "$src_key" > "$test_key"

    export SSH_AUTH_SOCK="$sock" SSH_AGENT_PID=""
    eval $(ssh-agent -a "$sock" -t 3) >/dev/null
    if [[ -n "$SSH_AGENT_PID" ]] && \
       [[ -n "$SSH_AUTH_SOCK" ]] && [[ -S "$SSH_AUTH_SOCK" ]] ; then
        if echo | ssh-add "$test_key" >/dev/null 2>&1 ; then
            printf "$src_key\t"
            ssh-add -L
            ssh-add -D >/dev/null 2>&1
            if ! ssh-agent -k >/dev/null ; then
                kill -9 $SSH_AGENT_PID
                rm -f "$sock"
            fi
            rc=0
        fi
    else
        rc=2
    fi

    rm -rf --one-file-system "$sock" "$dot_ssh" && \
        trap - EXIT INT TERM HUP USR1 USR2

    return $rc
}

main() {
    if [[ ! $# == 1 ]] ; then
        print_usage 64 "Missing mandatory path argument."
    fi

    local root="$1"
    if [[ ! -e "$root" ]] ; then
        abort "Path $root does not exist"
    elif [[ ! -d "$root" ]] ; then
        abort "Path $root is not a directory"
    fi

    find "$root" -maxdepth 3 -type f -path "*/.ssh/*" -or -name "id_" 2>&1 \
        | grep -v ": Permission denied$" \
        | while read file ; do
        if [[ ! -r "$file" ]] ; then
            >&2 echo "Cannot read $file; skipping."
            continue
        elif egrep -q '^-----BEGIN [A-Z0-9]+ PRIVATE KEY-----' "$file" ; then
            if ! is_secure_permissions "$file" ; then
                >&2 echo "$file $(stat -c %A "$file") permissions are not secure."
            fi
            if is_passphraseless "$file" ; then
                >&2 echo "$file has no passphrase set."
            elif [[ $? == 1 ]] ; then
                >&2 echo "$file is secured."
            else
                >&2 echo "$file could not be tested."
            fi
        fi
    done
}

main "$@"

exit