#!/bin/bash #LANG=C ###type -t logerror >/dev/null || logerror() {echo blubb; } #for f in logerror logwarn loginfo logdebug logtrace ENTRY EXIT SCRIPTENTRY SCRIPTEXIT; do # if LANG=C type -t $f 2> /dev/null| grep -q 'function'; then # : # else # fx=${f//log/} # echo create function for $fx # eval "$f () { \ # local loglevels; \ # declare -a loglevels; \ # loglevels=( \"ERROR\" \"WARN\" \"INFO\" ); \ # if [[ ! \${loglevels[*]} =~ \"\${LOGLEVEL-\${LOGLEVEL_DEFAULT}}\" ]];then \ # output='/dev/null'; \ # else \ # output='>&2'; \ # fi; \ # echo "\$LOGLEVEL output \$output" # echo ${fx^^}: \$@ > \$output; }" # unset fx # fi #done #unset f # #export LOGLEVEL="ERROR" #logwarn blubb #export LOGLEVEL="DEBUG" #logwarn blubb usage(){ cat << EOF Usage: ssh-agent-start-or-restart [[-c]|[--create-only]]|[[-t]|[--token-only]]|[[-k]|[--key-only]]|[[-r]|[-f]|[--readd]|[--force]] [] If started only with , the script looks up in configured identity-path \$SSH_IDENTITIES_DIR (${SSH_IDENTITIES_DIR}) if it can find a directory named after . If no is given, the identity is set to \$SSH_DEFAULT_IDENTITY ($SSH_DEFAULT_IDENTITY) configured via Environment. IF \$SSH_DEFAULT_IDENTITY is also not set, default is the SSH_DEFAULT_IDENTITY The output is the name of the file, where ssh-agent infomations are hold to load it to current shell for further actions. Use "$ eval \$()", if you want to load the SSH_AUTH_SOCK and SSH_AGENT_PID in current shell or shorter "$ loadagent []" -c|--create-only Create or restart only the agent. Do not load any key or token in it. The Output is used for loading the agent in the current shell. (loadagent ) -t|--token-only To add or renew only configured pkcs11-hardware-token configured in ${SSH_IDENTITIES_DIR}/, just use this. -k|--key-only To add or renew only configured keys configured in ${SSH_IDENTITIES_DIR}/, just use this. -r|-f|--readd-token|--force remove all in ${SSH_IDENTITIES_DIR}/ configured keys and tokens and readd them again. Depends on -t an -k Option to select wheter only keys or tokens only. If no -t and -k is given, all keys and token are removed and readded again. Just to be asked for password again, if you plugged off hardware-token and plugged it in again. --rm|--remove remove keys and token instead of adding them. -h|--info Show this info EOF } createonly=false tokenonly=false readd=false keyonly=false remove=false while :; do case $1 in -c|--create-only) createonly=true shift ;; -t|--token-only) tokenonly=true shift ;; -k|--key-only) keyonly=true shift ;; -r|-f|--readd-token|--force) readd=true shift ;; --rm|--remove) remove=true shift ;; -h|--info) usage exit 0 ;; -*) echo "Unknown urgument: »$1«" exit 1 ;; *) #ssh_identity=${1-${SSH_DEFAULT_IDENTITY}} ssh_identity=${1} break ;; esac done SCRIPTENTRY [ -z "${SSH_IDENTITIES_DIR+x}" ] && { SSH_IDENTITIES_DIR="${SSH_IDENTITIES_DEFAULT_DIR-${HOME}/.ssh/identities}"; export SSH_IDENTITIES_DIR; } [ -z "${SSH_AGENTS_DIR+x}" ] && { SSH_AGENTS_DIR=${SSH_AGENTS_DEFAULT_DIR-~/.ssh/agents}; export SSH_AGENTS_DIR; } [ -z "${SSH_AGENT_SOCKETS_DIR+x}" ] && { SSH_AGENT_SOCKETS_DIR=${SSH_AGENT_SOCKETS_DEFAULT_DIR-~/.ssh/agents}; export SSH_AGENT_SOCKETS_DIR; } [ -z "${SSH_AGENT_OPTIONS+x}" ] && { SSH_AGENT_OPTIONS=${SSH_AGENT_DEFAULT_OPTIONS--t 7200 }; export SSH_AGENT_OPTIONS; } logdebug "SSH_AGENTS_DIR: $SSH_AGENTS_DIR" logdebug "SSH_AGENT_SOCKETS_DIR: $SSH_AGENT_SOCKETS_DIR" logdebug "SSH_IDENTITIES_DIR: $SSH_IDENTITIES_DIR" logdebug "ssh-identität: ${ssh_identity}" [ -z "${SSH_AGENTS_DIR-x}" ] || mkdir -vp "$SSH_AGENTS_DIR" [ -z "${SSH_AGENT_SOCKETS_DIR-x}" ] || mkdir -vp "$SSH_AGENT_SOCKETS_DIR" [ -z "${SSH_IDENTITIES_DIR-x}" ] || mkdir -vp "$SSH_IDENTITIES_DIR" agent-start-or-restart () { ENTRY local ssh_identity local agentfile local agentsocket local ret if [ -n "${1+x}" ]; then ssh_identity="${1}" identitydir=${SSH_IDENTITIES_DIR}/${ssh_identity} loginfo "ssh-identität: ${ssh_identity}" >&2 if [ -d ${identitydir} ]; then [ -e "${identitydir}/config" ] && . "${identitydir}/config" agentfile="${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" agentsocket="${SSH_AGENT_SOCKETS_DIR}/socket-${ssh_identity}-$(hostname)" logtrace "agentfile: $agentfile" logtrace "agentsocket: $agentsocket" logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" if (! $keyonly && ! $tokenonly ) && $remove ; then logdebug "delete keys and tokens in ssh-agent $agentsocket" logdebug "$(ssh-runinagent $agentfile ssh-add -D 2>&1)" createonly=true else if [ -e $agentfile ]; then local msg # TODO make in runinagent msg="$(/bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID; . $agentfile >/dev/null 2>&1; ssh-add -l 2>&1")" local ret=$? logtrace "$msg" case $ret in 0) logdebug "agent is running" ;; 1) logdebug "agent is running, but:" logwarn "$msg" ;; 2) logdebug "former agent is not running -> start it" [ -e $agentsocket ] && { logdebug -n "remove socketfile: $( rm -v "$agentsocket" )"; } logtrace "$(ssh-agent -a $agentsocket ${SSH_AGENT_OPTIONS} > $agentfile )" logdebug "agent started" ;; esac else logdebug "agent did not exist -> create it" logtrace "ssh-agent -a $agentsocket \> $agentfile" logtrace "$(ssh-agent -a $agentsocket $SSH_AGENT_OPTIONS > $agentfile )" logdebug "agent started" fi fi logdebug "ssh-agent for identity »$ssh_identity«: $agentfile" $createonly && logtrace "current loaded keys after action: $(ssh-runinagent $agentfile ssh-add -l)" echo $agentfile ret=0 else logwarn "ssh-identity »$ssh_identity« is not configured. Please create $identitydir and add keys" ret=2 fi else if which gnome-keyring-daemon >/dev/null 2>&1; then logdebug "no identity given -> gnome-keyrings ssh-agent" agentfile="${SSH_AGENTS_DIR}/agent-gnome_session-$(hostname)" agentsocket="${SSH_AGENT_SOCKETS_DIR}/socket-gnome-session-$(hostname)" gnome-keyring-daemon -s > $agentfile logdebug "$(cat $agentfile)" logdebug "ssh-agent for identity »$ssh_identity«: $agentfile" # logdebug "currently loaded keys after action: #$(ssh-runinagent $agentfile ssh-add -l)" echo $agentfile ret=0 else logwarn "no identity given -> exit" ret=1 fi fi EXIT return $ret } agent-load-identity-keys () { ENTRY local ssh_identity local agentfile local agentsocket local fingerprints declare -a fingerprints local fingerprint local tokenfingerprint if [ -n "${1+x}" ]; then ssh_identity="${1}" identitydir=${SSH_IDENTITIES_DIR}/${ssh_identity} if [ -d ${identitydir} ]; then [ -e "${identitydir}/config" ] && . "${identitydir}/config" agentfile="${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" agentsocket="${SSH_AGENT_SOCKETS_DIR}/socket-${ssh_identity}-$(hostname)" logdebug "SSH_ADD_OPTIONS: $SSH_ADD_OPTIONS" logtrace "agentfile: $agentfile" logtrace "agentsocket: $agentsocket" logtrace "identitydir: $identitydir" fingerprints=( $(ssh-runinagent $agentfile "ssh-add -l|awk '{print \$2}'") ) logdebug "fingerprints from loaded keys before action:" for f in ${fingerprints[*]};do logdebug "$f" done if ! $tokenonly ; then for key in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_*|grep -v "pub$\|so$\|config$\|public$"); do fingerprint=$(ssh-keygen -l -f $key|awk '{print $2}') if [[ ${fingerprints[*]} =~ "$fingerprint" ]]; then logdebug "key: $(basename $key) (with fp $fingerprint) is loaded" if $readd || $remove ; then $readd && logdebug "re-add key $key" $remove && logdebug "remove key $key" logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -d ${key} 2>&1)" $remove || logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} ${key} 2>&1)" fi else logdebug "key: $key is not loaded -> load it" #logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -d ${key} 2>&1)" $remove || logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} ${key} 2>&1)" fi done fi if ! $keyonly ; then for key in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/*|grep "\.so$"); do tokenfingerprint="$(ssh-keygen -l -D $key|tr -s ' '|awk '{print $2}')" if [[ ${fingerprints[*]} =~ "$tokenfingerprint" ]]; then logdebug "token: $key ($fingerprint) is loaded" if $readd || $remove ; then $readd && logdebug "re-add token $key" $remove && logdebug "remove token $key" logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -e ${key} 2>&1)" $remove || logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -s ${key} 2>&1)" fi else logdebug "token: $key is not loaded -> load it" logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -e ${key} 2>&1)" $remove || logdebug "$(ssh-runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -s ${key} 2>&1)" fi done fi logdebug "currently loaded keys after action: $(ssh-runinagent $agentfile ssh-add -l)" else logwarn "ssh-identity $ssh_identity is not configured. Please create $identitydir and add keys" fi fi EXIT } ssh-runinagent () { ENTRY local agentfile local command local agentfile=${1} shift local sshcommand=${@} logtrace "run command »$sshcommand« in agent $agentfile" if [ -e "$agentfile" ]; then /bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID; . $agentfile >/dev/null 2>/dev/null; $sshcommand" ret=$? else logwarn "agentfile not existent" ret=99 fi EXIT return $ret } agent-start-or-restart $ssh_identity ! $createonly && agent-load-identity-keys $ssh_identity SCRIPTEXIT exit $?