From 789c0a9e6d2c0cc790d9b792b00228fd815d940f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jakobus=20Sch=C3=BCrz?= Date: Wed, 9 Aug 2023 16:24:51 +0200 Subject: [PATCH] new startagent. old renamed to startagent.old --- bin/sshstartagent | 312 --------------------- bin/startagent | 673 +++++++++++++++++++++------------------------ bin/startagent.old | 449 ++++++++++++++++++++++++++++++ 3 files changed, 761 insertions(+), 673 deletions(-) delete mode 100755 bin/sshstartagent create mode 100755 bin/startagent.old diff --git a/bin/sshstartagent b/bin/sshstartagent deleted file mode 100755 index 278f6c3..0000000 --- a/bin/sshstartagent +++ /dev/null @@ -1,312 +0,0 @@ -#!/bin/bash - -FILELOGLEVEL=DEBUG -DEFAULT_SOCKET_REMOTE=~/.ssh/ssh_from_remote_auth_sock -. $(dirname $0)/../logging -# loggerfactory -LANG=C - -usage(){ - cat << EOF - - Usage: $(basename $0) [[-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 -} - -create_filenamebase() { - printf "%s" "${ssh_identity}-$(hostname)" -} - -create_agentfilename() { - printf "%s" "${SSH_AGENTS_DIR}/agent-$(create_filenamebase)" -} - -create_socketfilename() { - printf "%s" "${SSH_AGENT_SOCKETS_DIR}/socket-$(create_filenamebase)" -} - -ssh_runinagent() { - - local SSH_AUTH_SOCK - local SSH_AGENT_PID - local PKCS11_MODULE - local agentfile - local command - local agentfile=${1} - shift - local sshcommand=${@} - - logdebug "agentfile: ${agentfile}" - logtrace "run command »$sshcommand« in agent $agentfile" - if [ -e "$agentfile" ]; then - #/bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE; eval $(<$agentfile) >/dev/null 2>&1; echo SSH_AUTH_SOCK ${SSH_AUTH_SOCK:-not set} >&2; $sshcommand" - #unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE - . $agentfile >&2 - logdebug "SSH_AUTH_SOCK: ${SSH_AUTH_SOCK:-not set}" - logdebug "SSH_AGENT_PID: ${SSH_AGENT_PID:-not set}" - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" - $sshcommand - ret=$? - else - logwarning "agentfile not existent" - ret=99 - fi - - return $ret - -} - -set_and_load_identity_config() { - - # check if idendity directory an file config exists in it. - # if it exist, source it - ssh_identity="${1}" - ssh_identity_dir="${SSH_IDENTITIES_DIR}/${ssh_identity}" - loginfo "ssh-identity: ${ssh_identity_dir}" - if [ -d ${ssh_identity_dir} ]; then - loginfo "Directory identity-dir ${ssh_identity_dir} exists. Use it" - else - logwarning "Directory identity-dir ${ssh_identity_dir} does not exist. Use default-config" - ssh_identity=default - ssh_identity_dir="${SSH_IDENTITIES_DIR}/${ssh_identity}" - fi - - if [ -e "${ssh_identity_dir}/config" ]; then - logdebug "source ${ssh_identity_dir}/config" - unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE SSH_AGENT_ALLOW_FROM_REMOTE SSH_ADD_OPTION - . "${ssh_identity_dir}/config" - fi - -} - -start_or_restart_local_agent() { - if [ -e "${ssh_agentfile}" ] - then - logdebug "agentfile ${ssh_agentfile} exists" - eval $(<$ssh_agentfile) >/dev/null 2>&1 - logdebug "SSH_AUTH_SOCK: ${SSH_AUTH_SOCK:-not set}" - logdebug "SSH_AGENT_PID: ${SSH_AGENT_PID:-not set}" - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" - for i in $(pgrep -f ${SSH_AUTH_SOCK}) - do - logdebug "$(stat ${SSH_AUTH_SOCK})" - logdebug "found pid: $i" - logdebug "is SSH_AGENT_PID set?" [ -n "${SSH_AGENT_PID:+x}" ] - logdebug "is $SSH_AGENT_PID same as found pid $i:" [ $i -eq ${SSH_AGENT_PID} ] - ${REMOTE_UNUSED_AGENTS:-false} && { [ -n "${SSH_AGENT_PID:+x}" ] && [ $i -eq ${SSH_AGENT_PID} ] || { logwarning "kill unused ssh-agent with pid $i"; kill $i; }; } - done - if [ -e ${ssh_socketfile} ] - then - case $(pgrep -f ${SSH_AUTH_SOCK}|wc -l) in - 0) - logdebug "no ssh-agents for file ${ssh_socketfile}" - ret=3 - ;; - 1) - logdebug "one running agent for file ${ssh_socketfile}. Use it" - msg="$(ssh_runinagent $ssh_agentfile "ssh-add -v -l 2>&1")" - ret=$? - logdebug "SSH_AUTH_SOCK: $SSH_AUTH_SOCK" - ;; - *) - logdebug "more than one ssh-agents for file ${ssh_socketfile}" - return 3 - ;; - esac - else - logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" - msg="$(ssh_runinagent $ssh_agentfile "ssh-add -v -l 2>&1")" - ret=$? - fi - logdebug "ret: $ret" - #msg="$(ssh-add -l 2>&1)" - logtrace "Output from check for running agent: $msg" - case $ret in - 0) - logdebug "agent is running" - ;; - 1) - logdebug "agent is running, but:" - logwarning "$msg" - ;; - 2|3|99) - logdebug "former agent is not running -> start it" - logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" - logdebug "remove agentfile: $( rm -v -f "$ssh_agentfile" )" - #logdebug "$(ssh-agent -k)" - logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" - logtrace "$(ssh-agent -a $ssh_socketfile ${SSH_AGENT_OPTIONS} > $ssh_agentfile )" - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" - sed '/^PKCS11_MODULE/d' ${ssh_agentfile} - [ -n "${PKCS11_MODULE:+x}" ] && logdebug "add PKCS11_MODULE to ${ssh_agentfile}" - [ -n "${PKCS11_MODULE:+x}" ] && echo "PKCS11_MODULE=$PKCS11_MODULE; export PKCS11_MODULE" >> ${ssh_agentfile} - logdebug "agent started" - ;; - 4) - logdebug "this is strange" - ;; - esac - else - logdebug "ssh_agentfile ${ssh_agentfile} does not exist" - logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" - logdebug "remove agentfile: $( rm -v -f "$ssh_agentfile" )" - logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" - logtrace "$(ssh-agent -a $ssh_socketfile ${SSH_AGENT_OPTIONS} > $ssh_agentfile )" - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" - sed '/^PKCS11_MODULE/d' ${ssh_agentfile} - [ -n "${PKCS11_MODULE:+x}" ] && logdebug "add PKCS11_MODULE to ${ssh_agentfile}" - [ -n "${PKCS11_MODULE:+x}" ] && echo "PKCS11_MODULE=$PKCS11_MODULE; export PKCS11_MODULE" >> ${ssh_agentfile} - logdebug "agent started" - fi - -} - - -check_and_link_socket() { - - if ${SSH_AGENT_ALLOW_FROM_REMOTE:-false} - then - logdebug "Remote agent allowed." - if [ -e ${DEFAULT_SOCKET_REMOTE} ] - then - logdebug "Link remote socket to ${ssh_socketfile}" - ln -f -s $(readlink -f ${DEFAULT_SOCKET_REMOTE}) ${ssh_socketfile} - [ -e ~/.ssh/p11m ] && . ~/.ssh/p11m - logdebug "Write new agentfile ${ssh_agentfile}" - cat << EOF > ${ssh_agentfile} -SSH_AUTH_SOCK=$ssh_socketfile; export SSH_AUTH_SOCK; -${P11M:+PKCS11_MODULE=${P11M}; export PKCS11_MODULE} -EOF - else - logdebug "Use local agent" - start_or_restart_local_agent - fi - else - logdebug "Only local agent allowed" - if [ -e ${ssh_agentfile} -a $(grep SSH_AUTH_SOCK ${ssh_agentfile}|echo $?) ] - then - logdebug "agentfile exists" - else - logdebug "agentfile is missing -> kill all ssh-agents for socket" - pkill -f ${ssh_socketfile} - fi - if [ -L ${ssh_socketfile} ] - then - logdebug "${ssh_socketfile} is symlinked to $(readlink -f ${ssh_socketfile}). Remove it" - rm ${ssh_socketfile} - else - if [ -e ${ssh_socketfile} -a $(pgrep -f ${ssh_socketfile} >/dev/null 2>&2; echo $?) ] - then - logdebug "Socket and agent for ${ssh_socketfile} are up and a running agent exist. Use it" - else - logdebug "No agent for socket ${ssh_socketfile} or socket does not exist, remove both if possible" - rm -f ${ssh_socketfile} - pkill -f ${ssh_socketfile} - fi - - fi - start_or_restart_local_agent - fi - -} - -load_or_reload_identities() { - - logdebug "Now load all identities for $ssh_identitiy from $ssh_identity_dir" - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" - -} - -################################################## -SCRIPTENTRY - -createonly=false -tokenonly=false -readd=false -keyonly=false -remove=false -while :; do - case $1 in - -c|--create-only) - createonly=true - shift - ;; - -h|--info) - usage - exit 0 - ;; - -*) - echo "Unknown urgument: »$1«" >&2 - exit 1 - ;; - *) - #ssh_identity=${1-${SSH_DEFAULT_IDENTITY}} - ssh_identity=${1} - break - ;; - esac -done -[ -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; } -logtrace " SSH_AGENTS_DIR: $SSH_AGENTS_DIR" -logtrace "SSH_AGENT_SOCKETS_DIR: $SSH_AGENT_SOCKETS_DIR" -logtrace " SSH_IDENTITIES_DIR: $SSH_IDENTITIES_DIR" -[ -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" - - -set_and_load_identity_config ${1} -loginfo " SSH_ADD_OPTIONS=${SSH_ADD_OPTIONS:-not set}" -loginfo "SSH_AGENT_ALLOW_FROM_REMOTE=${SSH_AGENT_ALLOW_FROM_REMOTE:-false}" -loginfo " PKCS11_MODULE=${PKCS11_MODULE:-not set}" -loginfo " P11M=${P11M:-not set}" -loginfo " SSH_AUTH_SOCK=${SSH_AUTH_SOCK:-not set}" -loginfo " SSH_AUTH_SOCK_REMOTE=${SSH_AUTH_SOCK_REMOTE:-not set}" - -ssh_agentfile=$(create_agentfilename) -ssh_socketfile=$(create_socketfilename) -logdebug "AGENT: ${ssh_agentfile}" -logdebug "SOCKET: ${ssh_socketfile}" - -[ -e $ssh_agentfile ] && eval $(<$ssh_agentfile) >&2 -check_and_link_socket -load_or_reload_identities -$createonly && printf "%s" "${ssh_agentfile}" -logdebug "cat ${ssh_agentfile} -$(cat ${ssh_agentfile})" - - -SCRIPTEXIT -loginfo "return with $res" -exit $res diff --git a/bin/startagent b/bin/startagent index 1f9e230..b33df85 100755 --- a/bin/startagent +++ b/bin/startagent @@ -1,6 +1,7 @@ #!/bin/bash FILELOGLEVEL=DEBUG +DEFAULT_SOCKET_REMOTE=~/.ssh/ssh_from_remote_auth_sock . $(dirname $0)/../logging # loggerfactory LANG=C @@ -38,67 +39,297 @@ usage(){ EOF - } -check_token(){ - if [ -e ~/.ssh/ssh_from_remote_auth_sock ] - then - logdebug "~/.ssh/ssh_from_remote_auth_sock is link" - . ~/.ssh/p11m - local agentfile="${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" - cat << EOF > $agentfile -SSH_AUTH_SOCK=~/.ssh/ssh_from_remote_auth_sock; export SSH_AUTH_SOCK -PKCS11_MODULE=${P11M}; export PKCS11_MODULE -EOF - # echo $agentfile - loginfo "$(cat $agentfile)" - return 0 +create_filenamebase() { + printf "%s" "${ssh_identity}-$(hostname)" +} + +create_agentfilename() { + printf "%s" "${SSH_AGENTS_DIR}/agent-$(create_filenamebase)" +} + +create_socketfilename() { + printf "%s" "${SSH_AGENT_SOCKETS_DIR}/socket-$(create_filenamebase)" +} + +ssh_runinagent() { + + local SSH_AUTH_SOCK + local SSH_AGENT_PID + local PKCS11_MODULE + local agentfile + local command + local agentfile=${1} + shift + local sshcommand=${@} + + logdebug "agentfile: ${agentfile}" + logtrace "run command »$sshcommand« in agent $agentfile" + if [ -e "$agentfile" ]; then + #/bin/sh -c "unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE; eval $(<$agentfile) >/dev/null 2>&1; echo SSH_AUTH_SOCK ${SSH_AUTH_SOCK:-not set} >&2; $sshcommand" + #unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE + . $agentfile >&2 + logdebug "SSH_AUTH_SOCK: ${SSH_AUTH_SOCK:-not set}" + logdebug "SSH_AGENT_PID: ${SSH_AGENT_PID:-not set}" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + $sshcommand + ret=$? else - logdebug "~/.ssh/ssh_from_remote_auth_sock is broken" - return 1 + logwarning "agentfile not existent" + ret=99 fi + + return $ret + } -# loginfo "a P11M: ${P11M}" -# loginfo "a PKCS11_MODULE: ${PKCS11_MODULE}" -# -# [ -n "${P11M:+x}" ] && export PKCS11_MODULE=${P11M} -# loginfo "b P11M: ${P11M}" -# loginfo "b PKCS11_MODULE: ${PKCS11_MODULE}" -# # it's the same as "token" in functions.sh -# # defined here also, to work also in environments, where functions.sh couldn't be sourced -# [ -z "${PKCS11_MODULE:+x}" ] && { PKCS11_MODULE=$P11M; export PKCS11_MODULE; } -# -# loginfo "c P11M: ${P11M}" -# loginfo "c PKCS11_MODULE: ${PKCS11_MODULE}" -# # If DISPLAY is set, ssh-add calls ssh-askpass, and if its in remote-terminal, it wont work -# # So remember and unset DISPLAY, and set it at the end again, if it was set before -# [ $DISPLAY ] && local DISPLAY_ORIG=$DISPLAY -# [ $DISPLAY ] && logtrace "unset DISPLAY: $DISPLAY" -# [ $DISPLAY ] && unset DISPLAY -# -# # Write public keys of all in agent stored keys to a temporary file -# local tmppubkey="$(mktemp -p ${XDG_RUNTIME_DIR} pubkey.XXXXXX.pub)" -# logtrace "tmppubkey: $tmppubkey" -# logdebug "C" -# tmpIFS="${IFS}" -# IFS=$'\n' -# for tmppk in $(ssh-add -L) -# do -# printf "%s" "$tmppk" |tee "${tmppubkey}" || return $? -# #echo "${tmppk}" > $tmppubkey || return $? -# #ssh-add -L > $tmppubkey || return $? -# # Check if public-keys in tmppubkey are working. They are not working, if you removed and add back hardware-token. -# loginfo "$(ssh-add -T ${tmppubkey}|| { ssh-add -e $PKCS11_MODULE; ssh-add -s $PKCS11_MODULE; } )" -# logdebug "$(ssh-add -l )" -# done -# logdebug "$(rm "${tmppubkey}")" -# IFS=$tmpIFS -# unset tmpIFS -# [ $DISPLAY_ORIG ] && logtrace "reset DISPLAY=$DISPLAY_ORIG" -# [ $DISPLAY_ORIG ] && export DISPLAY=$DISPLAY_ORIG -# -#} + +set_and_load_identity_config() { + + # check if idendity directory an file config exists in it. + # if it exist, source it + #ssh_identity="${1}" + ssh_identity_dir="${SSH_IDENTITIES_DIR}/${ssh_identity}" + loginfo "ssh-identity: ${ssh_identity}" + loginfo "ssh-identity_dir: ${ssh_identity_dir}" + if [ -d ${ssh_identity_dir} ]; then + loginfo "Directory identity-dir ${ssh_identity_dir} exists. Use it" + else + logwarning "Directory identity-dir ${ssh_identity_dir} does not exist. Use default-config" + ssh_identity=default + ssh_identity_dir="${SSH_IDENTITIES_DIR}/${ssh_identity}" + fi + + if [ -e "${ssh_identity_dir}/config" ]; then + logdebug "source ${ssh_identity_dir}/config" + unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE SSH_AGENT_ALLOW_FROM_REMOTE SSH_ADD_OPTION + . "${ssh_identity_dir}/config" + fi + +} + +start_or_restart_local_agent() { + if [ -e "${ssh_agentfile}" ] + then + logdebug "agentfile ${ssh_agentfile} exists" + eval $(<$ssh_agentfile) >/dev/null 2>&1 + logdebug "SSH_AUTH_SOCK: ${SSH_AUTH_SOCK:-not set}" + logdebug "SSH_AGENT_PID: ${SSH_AGENT_PID:-not set}" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + for i in $(pgrep -f ${SSH_AUTH_SOCK}) + do + logdebug "$(stat ${SSH_AUTH_SOCK})" + logdebug "found pid: $i" + logdebug "is SSH_AGENT_PID set?" [ -n "${SSH_AGENT_PID:+x}" ] + logdebug "is $SSH_AGENT_PID same as found pid $i:" [ $i -eq ${SSH_AGENT_PID} ] + ${REMOTE_UNUSED_AGENTS:-false} && { [ -n "${SSH_AGENT_PID:+x}" ] && [ $i -eq ${SSH_AGENT_PID} ] || { logwarning "kill unused ssh-agent with pid $i"; kill $i; }; } + done + if [ -e ${ssh_socketfile} ] + then + case $(pgrep -f ${SSH_AUTH_SOCK}|wc -l) in + 0) + logdebug "no ssh-agents for file ${ssh_socketfile}" + ret=3 + ;; + 1) + logdebug "one running agent for file ${ssh_socketfile}. Use it" + msg="$(ssh_runinagent $ssh_agentfile "ssh-add -v -l 2>&1")" + ret=$? + logdebug "SSH_AUTH_SOCK: $SSH_AUTH_SOCK" + ;; + *) + logdebug "more than one ssh-agents for file ${ssh_socketfile}" + return 3 + ;; + esac + else + logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" + msg="$(ssh_runinagent $ssh_agentfile "ssh-add -v -l 2>&1")" + ret=$? + fi + logdebug "ret: $ret" + #msg="$(ssh-add -l 2>&1)" + logtrace "Output from check for running agent: $msg" + case $ret in + 0) + logdebug "agent is running" + ;; + 1) + logdebug "agent is running, but:" + logwarning "$msg" + ;; + 2|3|99) + logdebug "former agent is not running -> start it" + logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" + logdebug "remove agentfile: $( rm -v -f "$ssh_agentfile" )" + #logdebug "$(ssh-agent -k)" + logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" + logtrace "$(ssh-agent -a $ssh_socketfile ${SSH_AGENT_OPTIONS} > $ssh_agentfile )" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + sed '/^PKCS11_MODULE/d' ${ssh_agentfile} + [ -n "${PKCS11_MODULE:+x}" ] && logdebug "add PKCS11_MODULE to ${ssh_agentfile}" + [ -n "${PKCS11_MODULE:+x}" ] && echo "PKCS11_MODULE=$PKCS11_MODULE; export PKCS11_MODULE" >> ${ssh_agentfile} + logdebug "agent started" + ;; + 4) + logdebug "this is strange" + ;; + esac + else + logdebug "ssh_agentfile ${ssh_agentfile} does not exist" + logdebug "remove socketfile: $( rm -v -f "$ssh_socketfile" )" + logdebug "remove agentfile: $( rm -v -f "$ssh_agentfile" )" + logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" + logtrace "$(ssh-agent -a $ssh_socketfile ${SSH_AGENT_OPTIONS} > $ssh_agentfile )" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + sed '/^PKCS11_MODULE/d' ${ssh_agentfile} + [ -n "${PKCS11_MODULE:+x}" ] && logdebug "add PKCS11_MODULE to ${ssh_agentfile}" + [ -n "${PKCS11_MODULE:+x}" ] && echo "PKCS11_MODULE=$PKCS11_MODULE; export PKCS11_MODULE" >> ${ssh_agentfile} + logdebug "agent started" + fi + +} + + +check_and_link_socket() { + + if ${SSH_AGENT_ALLOW_FROM_REMOTE:-false} + then + logdebug "Remote agent allowed." + if [ -e ${DEFAULT_SOCKET_REMOTE} ] + then + logdebug "Link remote socket to ${ssh_socketfile}" + ln -f -s $(readlink -f ${DEFAULT_SOCKET_REMOTE}) ${ssh_socketfile} + [ -e ~/.ssh/p11m ] && . ~/.ssh/p11m + logdebug "Write new agentfile ${ssh_agentfile}" + cat << EOF > ${ssh_agentfile} +SSH_AUTH_SOCK=$ssh_socketfile; export SSH_AUTH_SOCK; +${P11M:+PKCS11_MODULE=${P11M}; export PKCS11_MODULE} +EOF + else + logdebug "Use local agent" + start_or_restart_local_agent + fi + else + logdebug "Only local agent allowed" + if [ -e ${ssh_agentfile} -a $(grep SSH_AUTH_SOCK ${ssh_agentfile}|echo $?) ] + then + logdebug "agentfile exists" + else + logdebug "agentfile is missing -> kill all ssh-agents for socket" + pkill -f ${ssh_socketfile} + fi + if [ -L ${ssh_socketfile} ] + then + logdebug "${ssh_socketfile} is symlinked to $(readlink -f ${ssh_socketfile}). Remove it" + rm ${ssh_socketfile} + else + if [ -e ${ssh_socketfile} -a $(pgrep -f ${ssh_socketfile} >/dev/null 2>&2; echo $?) ] + then + logdebug "Socket and agent for ${ssh_socketfile} are up and a running agent exist. Use it" + else + logdebug "No agent for socket ${ssh_socketfile} or socket does not exist, remove both if possible" + rm -f ${ssh_socketfile} + pkill -f ${ssh_socketfile} + fi + + fi + start_or_restart_local_agent + fi + +} + +check_pubkeys_and_certs() { + + for pubkey in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_*|grep "pub$\|public$"|grep -v "cert.pub"); do + if $( ls ${pubkey%.pub} 1>/dev/null 2>&1);then + logdebug "pubkey with privkey: ${pubkey} | ${pubkey%.pub}" + else + logdebug "pubkey without privkey: $pubkey" + pubkeysonly+=($pubkey) + fi + if [ -e "${pubkey%.pub}-cert.pub" ]; then + cert_exp_date=$(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}') + [ $(date +%s -d $cert_exp_date) -gt $(date +%s -d NOW) ] \ + || logwarning "CERTIFICATE IS NOT VALID ANYMORE: ${pubkey%.pub}-cert.pub" + [ $(date +%s -d $cert_exp_date) -lt $(date +%s -d "$SSH_CERT_VALIDITY_WARN_SEC") ] \ + && logwarning "CERTIFICATE expires in $(echo "scale=0; ( `date -d $cert_exp_date +%s` - `date -d now +%s`) / (24*3600)" | bc -l) days: ${pubkey%.pub}-cert.pub" + fi + logwarning "$(ssh-add -T ${pubkey})" + done + + +} + +load_or_reload_identities() { + + logdebug " ssh_idendity=${ssh_identity}" + logdebug "Now load all identities for ${ssh_identity} from ${ssh_identity_dir}" + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set}" + local fingerprint + declare -a fingerprints + local pubkeysonly + declare -a pubkeysonly + fingerprints=( $(ssh-add -l|awk '{print $2}') ) + logdebug "fingerprints from loaded keys before action:" + for f in ${fingerprints[@]};do + logdebug "$f" + done + 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" + else + logdebug "key: $key is not loaded -> load it" + logdebug "$(ssh-add ${SSH_ADD_OPTIONS} ${key} 2>&1)" + fi + done + for pubkey in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_*|grep "pub$\|public$"|grep -v "cert.pub"); do + if $( ls ${pubkey%.pub} 1>/dev/null 2>&1);then + logdebug "pubkey with privkey: ${pubkey} | ${pubkey%.pub}" + else + logdebug "pubkey without privkey: $pubkey" + pubkeysonly+=($pubkey) + fi + if [ -e "${pubkey%.pub}-cert.pub" ]; then + cert_exp_date=$(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}') + [ $(date +%s -d $cert_exp_date) -gt $(date +%s -d NOW) ] \ + || logwarning "CERTIFICATE IS NOT VALID ANYMORE: ${pubkey%.pub}-cert.pub" + [ $(date +%s -d $cert_exp_date) -lt $(date +%s -d "$SSH_CERT_VALIDITY_WARN_SEC") ] \ + && logwarning "CERTIFICATE expires in $(echo "scale=0; ( `date -d $cert_exp_date +%s` - `date -d now +%s`) / (24*3600)" | bc -l) days: ${pubkey%.pub}-cert.pub" + fi + done + for pubkey in ${pubkeysonly[@]} + do + logdebug "Pubkey: ${pubkey}" + logdebug " SSH_AUTH_SOCK=${SSH_AUTH_SOCK}" + logwarning "$(ssh-add -T ${pubkey} 2>&1)" + if [ $? -gt 0 ] + then + logdebug "Pubkey ${pubkey} is not usable" + if [ -n "${PKCS11_MODULE:+x}" ] + then + logdebug "PKCS11_MODULE is set ${PKCS11_MODULE:-not set}" + logdebug "$(ssh-add -e $PKCS11_MODULE)" && logdebug "$(ssh-add -s $PKCS11_MODULE)" + else + logdebug "No PKCS11_MODULE defined" + fi + else + logdebug "Pubkey ${pubkey} is usable" + if [ -n "${PKCS11_MODULE:+x}" ] + then + logdebug "PKCS11_MODULE is set ${PKCS11_MODULE:-not set}" + else + logdebug "No PKCS11_MODULE defined" + fi + fi + done + + +} + +################################################## +SCRIPTENTRY createonly=false tokenonly=false @@ -111,22 +342,6 @@ while :; do 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 @@ -142,276 +357,6 @@ while :; do ;; esac done - -agent_start_or_restart () { - - logtrace "agent_start_or_restart" - # If DISPLAY is set, ssh-add calls ssh-askpass, and if its in remote-terminal, it wont work - # So remember and unset DISPLAY, and set it at the end again, if it was set before - [ $DISPLAY ] && local DISPLAY_ORIG=$DISPLAY - [ $DISPLAY ] && logtrace "unset DISPLAY: $DISPLAY" - [ $DISPLAY ] && unset DISPLAY - - 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 for ${ssh_identity}: $agentfile" - logtrace "agentsocket for ${ssh_identity}: $agentsocket" - if (! $keyonly && ! $tokenonly ) && $remove ; then - logdebug "delete keys and tokens in this ssh-agent" - 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 "Output from check for running: $msg" - case $ret in - 0) - logdebug "agent is running" - ;; - 1) - logdebug "agent is running, but:" - logwarning "$msg" - ;; - 2) - logdebug "former agent is not running -> start it" - logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" - [ -e $agentsocket ] && { logdebug -n "remove socketfile: $( rm -v "$agentsocket" )"; } - [ -e $agentfile ] && { logdebug -n "remove agentfile: $( rm -v "$agentfile" )"; } - 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 $SSH_AGENT_OPTIONS \> $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)" - loginfo agentfile: $agentfile - printf "%s" "$agentfile" - ret=0 - else - logwarning "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)" - printf "%s" "$agentfile" - ret=0 - else - logwarning "no identity given -> exit" - ret=1 - fi - fi - - [ $DISPLAY_ORIG ] && logtrace "reset DISPLAY=$DISPLAY_ORIG" - [ $DISPLAY_ORIG ] && export DISPLAY=$DISPLAY_ORIG - return $ret - -} - -agent_load_identity_keys () { - - logtrace "agent_load_identity_keys" - # If DISPLAY is set, ssh-add calls ssh-askpass, and if its in remote-terminal, it wont work - # So remember and unset DISPLAY, and set it at the end again, if it was set before - [ $DISPLAY ] && local DISPLAY_ORIG=$DISPLAY - [ $DISPLAY ] && logtrace "unset DISPLAY: $DISPLAY" - [ $DISPLAY ] && unset DISPLAY - - local ssh_identity - local agentfile - local agentsocket - local fingerprints - declare -a fingerprints - local pubkeysonly - declare -a pubkeysonly - 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 - # load keys - 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 - # load tokens - for pubkey in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_*|grep "pub$\|public$"|grep -v "cert.pub"); do - if $( ls ${pubkey%.pub} 1>/dev/null 2>&1);then - logdebug "pubkey with privkey: ${pubkey} | ${pubkey%.pub}" - else - logdebug "pubkey without privkey: $pubkey" - pubkeysonly+=($pubkey) - fi - if [ -e "${pubkey%.pub}-cert.pub" ]; then - #logwarning "${pubkey%.pub}-cert.pub: $(date +%s -d $(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}'))" - #logwarning "now: $(date +%s -d NOW)" - cert_exp_date=$(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}') - #[ $(date +%s -d $(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}')) -gt $(date +%s -d NOW) ] \ - [ $(date +%s -d $cert_exp_date) -gt $(date +%s -d NOW) ] \ - || logwarning "CERTIFICATE IS NOT VALID ANYMORE: ${pubkey%.pub}-cert.pub" - #[ $(date +%s -d $(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}')) -lt $(date +%s -d "$SSH_CERT_VALIDITY_WARN_SEC") ] \ - [ $(date +%s -d $cert_exp_date) -lt $(date +%s -d "$SSH_CERT_VALIDITY_WARN_SEC") ] \ - && logwarning "CERTIFICATE expires in $(echo "scale=0; ( `date -d $cert_exp_date +%s` - `date -d now +%s`) / (24*3600)" | bc -l) days: ${pubkey%.pub}-cert.pub" - fi - done - loginfo "pubkeysonly: ${pubkeysonly[@]} (count: ${#pubkeysonly[*]})" - - - for key in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/*|grep "\.so$"); do - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set} - key: $key" - if [ "$(readlink -f $key)" != "$PKCS11_MODULE" -a "${PKCS11_MODULE:-x}" != "x" ] - then - key="$PKCS11_MODULE" - else - export PKCS11_MODULE=$(readlink -f $key) - fi - logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set} - key: $key" - grep -q "PKCS11_MODULE" "${agentfile}" >/dev/null 2>&1 && { sed -i -e '/PKCS11_MODULE/d' "${agentfile}"; key=$PKCS11_MODULE; } - printf "%s\n" "PKCS11_MODULE=$(readlink -f $key)" | tee -a "${agentfile}" >&2 - - tokenfingerprints=($(ssh-keygen -l -D $key|tr -s ' '|awk '{print $2}')) - - logtrace "fingerprints: ${fingerprints[*]}" - logtrace "tokenfingerprints count: ${#tokenfingerprints[@]}" - if [ ${#tokenfingerprints[@]} -gt 1 ]; then - logerr "Found ${#tokenfingerprints[@]} in $key! Check if only one token is plugged into your computer" - - else - tokenfingerprint=${tokenfingerprints[0]} - logtrace "tokenfingerprint: ${tokenfingerprint}" - if [[ "${fingerprints[@]}" =~ "$tokenfingerprint" ]]; then - logdebug "token: $key ($tokenfingerprint) is loaded" - check_pubkeysonly - if $readd || $remove ; then - $readd && logdebug "re-add token $key" - $remove && logdebug "remove token $key" - logtrace "agentfile1 $agentfile \$SSH_ADD_OPTIONS $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 -v ${SSH_ADD_OPTIONS} -e ${key} 2>&1)" - $remove || logdebug "$(ssh_runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -s ${key} 2>&1)" - fi - fi - done - fi - loginfo "currently loaded keys after action: $(ssh_runinagent $agentfile ssh-add -l|wc -l)" - logdebug "$(ssh_runinagent $agentfile ssh-add -l)" - else - logwarning "ssh-identity $ssh_identity is not configured. Please create $identitydir and add keys" - fi - fi - - [ $DISPLAY_ORIG ] && logtrace "reset DISPLAY=$DISPLAY_ORIG" - [ $DISPLAY_ORIG ] && export DISPLAY=$DISPLAY_ORIG - -} - -function check_pubkeysonly () { - if [ ${#pubkeysonly[*]} -gt 0 ] ; then - for p in ${pubkeysonly[@]}; do - logtrace "pubkeyonly: $p" - logtrace "$(ssh_runinagent $agentfile ssh-add -T ${p} 2>&1)" - ssh_runinagent $agentfile ssh-add -T ${p} 2>&1 || { $remove || readd=true; break; } - done - else - logwarning "obviously there is no pubkey for the token in ${SSH_IDENTITIES_DIR}/${ssh_identity}/" - logwarning "you can add the pubkey with" - logwarning " ssh-add -L > ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_etoken.pub" - logwarning "make sure, only the token is loaded into ssh-agent with" - logwarning " ssh-add -l" - logwarning "only one line should be the output" - fi - logdebug "readd: $readd" -} - -ssh_runinagent () { - - local SSH_AUTH_SOCK - local SSH_AGENT_PID - 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 - logwarning "agentfile not existent" - ret=99 - fi - - return $ret - -} - -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; } @@ -422,27 +367,33 @@ logtrace " SSH_IDENTITIES_DIR: $SSH_IDENTITIES_DIR" [ -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" +logdebug "ssh_idendity: ${ssh_identity}" +unset SSH_AUTH_SOCK SSH_AGENT_PID PKCS11_MODULE SSH_AGENT_ALLOW_FROM_REMOTE + +set_and_load_identity_config ${ssh_identity} +logdebug " SSH_ADD_OPTIONS=${SSH_ADD_OPTIONS:-not set}" +logdebug "SSH_AGENT_ALLOW_FROM_REMOTE=${SSH_AGENT_ALLOW_FROM_REMOTE:-false}" +logdebug " PKCS11_MODULE=${PKCS11_MODULE:-not set}" +logdebug " P11M=${P11M:-not set}" +logdebug " SSH_AUTH_SOCK=${SSH_AUTH_SOCK:-not set}" +logdebug " SSH_AUTH_SOCK_REMOTE=${SSH_AUTH_SOCK_REMOTE:-not set}" +logdebug " ssh_idendity=${ssh_identity}" + +ssh_agentfile=$(create_agentfilename) +ssh_socketfile=$(create_socketfilename) + +[ -e $ssh_agentfile ] && eval $(<$ssh_agentfile) >&2 +check_and_link_socket +logdebug "SSH_AGENT_FILE=${ssh_agentfile}" +logdebug " SSH_AGENT_PID=${SSH_AGENT_PID}" +logdebug " SSH_AUTH_SOCK=${SSH_AUTH_SOCK}" +logdebug " ssh_idendity=${ssh_identity}" +$createonly || load_or_reload_identities +$createonly && printf "%s" "${ssh_agentfile}" +logtrace "cat ${ssh_agentfile} +$(cat ${ssh_agentfile})" -if [[ $SSH_TTY || $X2GO_SESSION ]] ; then - logdebug "Shell running with forwarded ssh-agent. Please add local token manually" - check_token - res=2 -else - logdebug "run with local ssh-agent" - check_token - if [ $? -eq 0 ] - then - loginfo "run with remote agent" - printf "%s" "${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" - #! $createonly && agent_load_identity_keys $ssh_identity - res=1 - else - agent_start_or_restart $ssh_identity - ! $createonly && agent_load_identity_keys $ssh_identity - res=0 - fi -fi SCRIPTEXIT loginfo "return with $res" diff --git a/bin/startagent.old b/bin/startagent.old new file mode 100755 index 0000000..1f9e230 --- /dev/null +++ b/bin/startagent.old @@ -0,0 +1,449 @@ +#!/bin/bash + +FILELOGLEVEL=DEBUG +. $(dirname $0)/../logging +# loggerfactory +LANG=C + +usage(){ + cat << EOF + + Usage: $(basename $0) [[-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 + +} + +check_token(){ + if [ -e ~/.ssh/ssh_from_remote_auth_sock ] + then + logdebug "~/.ssh/ssh_from_remote_auth_sock is link" + . ~/.ssh/p11m + local agentfile="${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" + cat << EOF > $agentfile +SSH_AUTH_SOCK=~/.ssh/ssh_from_remote_auth_sock; export SSH_AUTH_SOCK +PKCS11_MODULE=${P11M}; export PKCS11_MODULE +EOF + # echo $agentfile + loginfo "$(cat $agentfile)" + return 0 + else + logdebug "~/.ssh/ssh_from_remote_auth_sock is broken" + return 1 + fi +} +# loginfo "a P11M: ${P11M}" +# loginfo "a PKCS11_MODULE: ${PKCS11_MODULE}" +# +# [ -n "${P11M:+x}" ] && export PKCS11_MODULE=${P11M} +# loginfo "b P11M: ${P11M}" +# loginfo "b PKCS11_MODULE: ${PKCS11_MODULE}" +# # it's the same as "token" in functions.sh +# # defined here also, to work also in environments, where functions.sh couldn't be sourced +# [ -z "${PKCS11_MODULE:+x}" ] && { PKCS11_MODULE=$P11M; export PKCS11_MODULE; } +# +# loginfo "c P11M: ${P11M}" +# loginfo "c PKCS11_MODULE: ${PKCS11_MODULE}" +# # If DISPLAY is set, ssh-add calls ssh-askpass, and if its in remote-terminal, it wont work +# # So remember and unset DISPLAY, and set it at the end again, if it was set before +# [ $DISPLAY ] && local DISPLAY_ORIG=$DISPLAY +# [ $DISPLAY ] && logtrace "unset DISPLAY: $DISPLAY" +# [ $DISPLAY ] && unset DISPLAY +# +# # Write public keys of all in agent stored keys to a temporary file +# local tmppubkey="$(mktemp -p ${XDG_RUNTIME_DIR} pubkey.XXXXXX.pub)" +# logtrace "tmppubkey: $tmppubkey" +# logdebug "C" +# tmpIFS="${IFS}" +# IFS=$'\n' +# for tmppk in $(ssh-add -L) +# do +# printf "%s" "$tmppk" |tee "${tmppubkey}" || return $? +# #echo "${tmppk}" > $tmppubkey || return $? +# #ssh-add -L > $tmppubkey || return $? +# # Check if public-keys in tmppubkey are working. They are not working, if you removed and add back hardware-token. +# loginfo "$(ssh-add -T ${tmppubkey}|| { ssh-add -e $PKCS11_MODULE; ssh-add -s $PKCS11_MODULE; } )" +# logdebug "$(ssh-add -l )" +# done +# logdebug "$(rm "${tmppubkey}")" +# IFS=$tmpIFS +# unset tmpIFS +# [ $DISPLAY_ORIG ] && logtrace "reset DISPLAY=$DISPLAY_ORIG" +# [ $DISPLAY_ORIG ] && export DISPLAY=$DISPLAY_ORIG +# +#} + +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«" >&2 + exit 1 + ;; + *) + #ssh_identity=${1-${SSH_DEFAULT_IDENTITY}} + ssh_identity=${1} + break + ;; + esac +done + +agent_start_or_restart () { + + logtrace "agent_start_or_restart" + # If DISPLAY is set, ssh-add calls ssh-askpass, and if its in remote-terminal, it wont work + # So remember and unset DISPLAY, and set it at the end again, if it was set before + [ $DISPLAY ] && local DISPLAY_ORIG=$DISPLAY + [ $DISPLAY ] && logtrace "unset DISPLAY: $DISPLAY" + [ $DISPLAY ] && unset DISPLAY + + 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 for ${ssh_identity}: $agentfile" + logtrace "agentsocket for ${ssh_identity}: $agentsocket" + if (! $keyonly && ! $tokenonly ) && $remove ; then + logdebug "delete keys and tokens in this ssh-agent" + 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 "Output from check for running: $msg" + case $ret in + 0) + logdebug "agent is running" + ;; + 1) + logdebug "agent is running, but:" + logwarning "$msg" + ;; + 2) + logdebug "former agent is not running -> start it" + logdebug "SSH_AGENT_OPTIONS: $SSH_AGENT_OPTIONS" + [ -e $agentsocket ] && { logdebug -n "remove socketfile: $( rm -v "$agentsocket" )"; } + [ -e $agentfile ] && { logdebug -n "remove agentfile: $( rm -v "$agentfile" )"; } + 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 $SSH_AGENT_OPTIONS \> $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)" + loginfo agentfile: $agentfile + printf "%s" "$agentfile" + ret=0 + else + logwarning "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)" + printf "%s" "$agentfile" + ret=0 + else + logwarning "no identity given -> exit" + ret=1 + fi + fi + + [ $DISPLAY_ORIG ] && logtrace "reset DISPLAY=$DISPLAY_ORIG" + [ $DISPLAY_ORIG ] && export DISPLAY=$DISPLAY_ORIG + return $ret + +} + +agent_load_identity_keys () { + + logtrace "agent_load_identity_keys" + # If DISPLAY is set, ssh-add calls ssh-askpass, and if its in remote-terminal, it wont work + # So remember and unset DISPLAY, and set it at the end again, if it was set before + [ $DISPLAY ] && local DISPLAY_ORIG=$DISPLAY + [ $DISPLAY ] && logtrace "unset DISPLAY: $DISPLAY" + [ $DISPLAY ] && unset DISPLAY + + local ssh_identity + local agentfile + local agentsocket + local fingerprints + declare -a fingerprints + local pubkeysonly + declare -a pubkeysonly + 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 + # load keys + 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 + # load tokens + for pubkey in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_*|grep "pub$\|public$"|grep -v "cert.pub"); do + if $( ls ${pubkey%.pub} 1>/dev/null 2>&1);then + logdebug "pubkey with privkey: ${pubkey} | ${pubkey%.pub}" + else + logdebug "pubkey without privkey: $pubkey" + pubkeysonly+=($pubkey) + fi + if [ -e "${pubkey%.pub}-cert.pub" ]; then + #logwarning "${pubkey%.pub}-cert.pub: $(date +%s -d $(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}'))" + #logwarning "now: $(date +%s -d NOW)" + cert_exp_date=$(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}') + #[ $(date +%s -d $(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}')) -gt $(date +%s -d NOW) ] \ + [ $(date +%s -d $cert_exp_date) -gt $(date +%s -d NOW) ] \ + || logwarning "CERTIFICATE IS NOT VALID ANYMORE: ${pubkey%.pub}-cert.pub" + #[ $(date +%s -d $(ssh-keygen -L -f "${pubkey%.pub}-cert.pub"|awk '$1 == "Valid:"{print $5}')) -lt $(date +%s -d "$SSH_CERT_VALIDITY_WARN_SEC") ] \ + [ $(date +%s -d $cert_exp_date) -lt $(date +%s -d "$SSH_CERT_VALIDITY_WARN_SEC") ] \ + && logwarning "CERTIFICATE expires in $(echo "scale=0; ( `date -d $cert_exp_date +%s` - `date -d now +%s`) / (24*3600)" | bc -l) days: ${pubkey%.pub}-cert.pub" + fi + done + loginfo "pubkeysonly: ${pubkeysonly[@]} (count: ${#pubkeysonly[*]})" + + + for key in $(ls ${SSH_IDENTITIES_DIR}/${ssh_identity}/*|grep "\.so$"); do + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set} - key: $key" + if [ "$(readlink -f $key)" != "$PKCS11_MODULE" -a "${PKCS11_MODULE:-x}" != "x" ] + then + key="$PKCS11_MODULE" + else + export PKCS11_MODULE=$(readlink -f $key) + fi + logdebug "PKCS11_MODULE: ${PKCS11_MODULE:-not set} - key: $key" + grep -q "PKCS11_MODULE" "${agentfile}" >/dev/null 2>&1 && { sed -i -e '/PKCS11_MODULE/d' "${agentfile}"; key=$PKCS11_MODULE; } + printf "%s\n" "PKCS11_MODULE=$(readlink -f $key)" | tee -a "${agentfile}" >&2 + + tokenfingerprints=($(ssh-keygen -l -D $key|tr -s ' '|awk '{print $2}')) + + logtrace "fingerprints: ${fingerprints[*]}" + logtrace "tokenfingerprints count: ${#tokenfingerprints[@]}" + if [ ${#tokenfingerprints[@]} -gt 1 ]; then + logerr "Found ${#tokenfingerprints[@]} in $key! Check if only one token is plugged into your computer" + + else + tokenfingerprint=${tokenfingerprints[0]} + logtrace "tokenfingerprint: ${tokenfingerprint}" + if [[ "${fingerprints[@]}" =~ "$tokenfingerprint" ]]; then + logdebug "token: $key ($tokenfingerprint) is loaded" + check_pubkeysonly + if $readd || $remove ; then + $readd && logdebug "re-add token $key" + $remove && logdebug "remove token $key" + logtrace "agentfile1 $agentfile \$SSH_ADD_OPTIONS $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 -v ${SSH_ADD_OPTIONS} -e ${key} 2>&1)" + $remove || logdebug "$(ssh_runinagent $agentfile ssh-add ${SSH_ADD_OPTIONS} -s ${key} 2>&1)" + fi + fi + done + fi + loginfo "currently loaded keys after action: $(ssh_runinagent $agentfile ssh-add -l|wc -l)" + logdebug "$(ssh_runinagent $agentfile ssh-add -l)" + else + logwarning "ssh-identity $ssh_identity is not configured. Please create $identitydir and add keys" + fi + fi + + [ $DISPLAY_ORIG ] && logtrace "reset DISPLAY=$DISPLAY_ORIG" + [ $DISPLAY_ORIG ] && export DISPLAY=$DISPLAY_ORIG + +} + +function check_pubkeysonly () { + if [ ${#pubkeysonly[*]} -gt 0 ] ; then + for p in ${pubkeysonly[@]}; do + logtrace "pubkeyonly: $p" + logtrace "$(ssh_runinagent $agentfile ssh-add -T ${p} 2>&1)" + ssh_runinagent $agentfile ssh-add -T ${p} 2>&1 || { $remove || readd=true; break; } + done + else + logwarning "obviously there is no pubkey for the token in ${SSH_IDENTITIES_DIR}/${ssh_identity}/" + logwarning "you can add the pubkey with" + logwarning " ssh-add -L > ${SSH_IDENTITIES_DIR}/${ssh_identity}/id_etoken.pub" + logwarning "make sure, only the token is loaded into ssh-agent with" + logwarning " ssh-add -l" + logwarning "only one line should be the output" + fi + logdebug "readd: $readd" +} + +ssh_runinagent () { + + local SSH_AUTH_SOCK + local SSH_AGENT_PID + 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 + logwarning "agentfile not existent" + ret=99 + fi + + return $ret + +} + +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; } +logtrace " SSH_AGENTS_DIR: $SSH_AGENTS_DIR" +logtrace "SSH_AGENT_SOCKETS_DIR: $SSH_AGENT_SOCKETS_DIR" +logtrace " SSH_IDENTITIES_DIR: $SSH_IDENTITIES_DIR" +[ -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" + + +if [[ $SSH_TTY || $X2GO_SESSION ]] ; then + logdebug "Shell running with forwarded ssh-agent. Please add local token manually" + check_token + res=2 +else + logdebug "run with local ssh-agent" + check_token + if [ $? -eq 0 ] + then + loginfo "run with remote agent" + printf "%s" "${SSH_AGENTS_DIR}/agent-${ssh_identity}-$(hostname)" + #! $createonly && agent_load_identity_keys $ssh_identity + res=1 + else + agent_start_or_restart $ssh_identity + ! $createonly && agent_load_identity_keys $ssh_identity + res=0 + fi +fi + +SCRIPTEXIT +loginfo "return with $res" +exit $res