Managing ssh-agent automatically (with cygwin/PuTTY-Support)

1 Apr

When using SSH with public keys it is very annoying to enter the pass phrase everytime you connect to a host. In some cases (I won’t talk about security here, but you should really check waht it means to use an SSH agent) you can use a SSH agent to store your private keys. I’ll show a little script here, wich I include in my .zprofile to reuse a running SSH agent or to start a new one in the case that no agent is running. This allows to share one single instance between all shell sessions.

First we define a little helper function in .zprofile (if you’re using bash instead of zsh, you have to edit .bash_profile instead):

exists() {
    for i in $*; do
        which $i >/dev/null 2>&1 || return 1
    done
    return 0
}

This helps us to identify, which programms are installed.

First we check if ssh-agent is installed on our system (line 1). If this is the case, we check if SSH_AUTH_SOCKET isn’t already set (line 2; this is the case if we are connected via SSH and agent forwarding). If we don’t have an agent, we take a look at .agent.env: if it does not exist (lines 11-12) we can start an agent and save it’s PID in .agent.env to allow other shells to reuse the agent. If the file is already there we check if the referenced agent is still running (line 6). If it is, we reuse it, otherwise we start a new one (line 7-8):

if exists ssh-agent; then
    if [[ -z $SSH_AUTH_SOCK ]]; then
        if [[ -f ~/.agent.env ]]; then
            . ~/.agent.env -s > /dev/null
 
            if ! kill -0 $SSH_AGENT_PID > /dev/null 2>&1; then
                ssh-agent -s > ~/.agent.env
                . ~/.agent.env > /dev/null 2>&1
            fi
        else
            ssh-agent -s > ~/.agent.env
            . ~/.agent.env > /dev/null 2>&1
        fi
    fi
fi

So far, after parsing the .zprofile file, we have a running ssh-agent in every case. We can now execute ssh-add and add our key(s). On Windows, if using cygwin, the chance is high that you’re using pageant as your ssh-agent. pageant is the SSH agent that comes with PuTTY or WinSCP. However, there are some wrappers that allows openssh to authenticate with PuTTY’s pageant. One of these solutions is ssh-pageant. It is easyly installed:

% git clone git://github.com/cuviper/ssh-pageant.git
Cloning into 'ssh-pageant'...
remote: Counting objects: 206, done.
remote: Compressing objects: 100% (189/189), done.
remote: Total 206 (delta 117), reused 23 (delta 9)
Receiving objects: 100% (206/206), 69.59 KiB, done.
Resolving deltas: 100% (117/117), done.
% cd ssh-pageant
% make
cc -O2 -Werror -Wall -Wextra -MMD   -c -o main.o main.c
cc -O2 -Werror -Wall -Wextra -MMD   -c -o winpgntc.o winpgntc.c
cc   main.o winpgntc.o  -o ssh-pageant.exe
% cp ssh-pageant /usr/bin/
%

The startup code looks nearly the same. I’ll show a univeral version here which works on all environments:

if [[ "$OSTYPE" != cygwin ]]; then
    if exists ssh-agent; then
        if [[ -z $SSH_AUTH_SOCK ]]; then
            if [[ -f ~/.agent.env ]]; then
                . ~/.agent.env -s > /dev/null
 
                if ! kill -0 $SSH_AGENT_PID > /dev/null 2>&1; then
                    ssh-agent -s > ~/.agent.env
                    . ~/.agent.env > /dev/null 2>&1
                fi
            else
                ssh-agent -s > ~/.agent.env
                . ~/.agent.env > /dev/null 2>&1
            fi
        fi
    fi
else
    if exists ssh-pageant; then
        if [[ -f ~/.agent.env ]]; then
            . ~/.agent.env -s > /dev/null
 
            if ! kill -0 $SSH_PAGEANT_PID > /dev/null 2>&1; then
                ssh-pageant -s > ~/.agent.env
                . ~/.agent.env > /dev/null 2>&1
            fi
        else
            ssh-pageant -s > ~/.agent.env
            . ~/.agent.env > /dev/null 2>&1
        fi
    fi
fi

On linux, is also possible to kill the agent if the last user logs out:

on_logout() {
    if [ $(users |sed 's/ /\n/'| grep -c $USER) -eq 1 ]; then
        ssh-agent -k >/dev/null 2>&1
    fi
}
     
trap 'on_logout' EXIT

Have more fun using SSH smiley

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert.