Mailing-List: contact cygwin-help AT cygwin DOT com; run by ezmlm List-Subscribe: List-Archive: List-Post: List-Help: , Sender: cygwin-owner AT cygwin DOT com Mail-Followup-To: cygwin AT cygwin DOT com Delivered-To: mailing list cygwin AT cygwin DOT com Date: Thu, 1 Aug 2002 19:00:17 +0600 From: =?koi8-r?B?4s/SydMg883J0s7P1w==?= Reply-To: =?koi8-r?B?4s/SydMg883J0s7P1w==?= Organization: Eastwind X-Priority: 3 (Normal) Message-ID: <18033324390.20020801190017@eastwind.ru> To: cygwin AT cygwin DOT com Subject: HOWTO run ssh-agent as an NT/2K service MIME-Version: 1.0 Content-Type: text/plain; charset=koi8-r Content-Transfer-Encoding: 8bit Hello There is a problem when running ssh-agent from a shell prompt: when you logout from that shell the console window won't close until one kills the agent. The only solution that comes in mind is running ssh-agent as a service (on Windows NT/2K platforms). I've found two discussions on cygwin mailing list dedicated to this subject here http://www.cygwin.com/ml/cygwin-patches/2001-q1/msg00184.html and here http://www.cygwin.com/ml/cygwin/2002-05/msg01305.html, but in the end I came with my own solution. Read on... Starting an ssh-agent as a service is pretty easy: cygrunsrv -I "ssh-agent-$USER" -d "CYGWIN ssh-agent for $USER" \ -p /usr/bin/ssh-agent -a "$S_OR_C_FLAG -d" \ -t manual -1 ~/.ssh-agent -o -u $USER assuming the following requirements are met: 1) CYGWIN envronment variable contains ntsec option for valid socket permissions 2) A USER has "Log on as service" privilege 3) if cygrunsrv is run from startup script, a user, probably needs administrative privileges to be able to install/start a service. However, it is possible for a system administrator to install as many instances of ssh-agent services as needed and configure them to start automatically (see the "-t" option of cygrunsrv) during system boot, thus not requiring additional priviliges for users other then "Log on as service" (this is in theory, I have not tried this configuration). Now, when we started an ssh-agent service the next problem is how to carry the information about a socket, agent listens to, to applications. We need to set SSH_AUTH_SOCK environment variable somehow. The easy but not reliable way: SSH_AUTH_SOCK=`find /tmp/ssh-* -type s -user $USER -perm 600 | tail -n 1`; export SSH_AUTH_SOCK The reliable way to set SSH_AUTH_SOCK is only via ssh-agent output, and this requires trivial patching of openssh sources. The problem is that ssh-agent output to stdout is buffered, thus "-1 ~/.ssh-agent" option of cygrunsrv makes empty file. Inserting call to fflush(stdout) to the right place of ssh-agent.c (line 1070 for openssh-3.4p1, before goto statement) does the trick. The rest is pure shell scripting. here is the patch -8<----------------8<--------------8<-- diff -u openssh-3.4p1/ssh-agent.c openssh-3.4p1-patched/ssh-agent.c --- openssh-3.4p1/ssh-agent.c 2002-06-26 05:19:13.000000000 +0600 +++ openssh-3.4p1-patched/ssh-agent.c 2002-07-31 14:09:16.000000000 +0600 @@ -1067,6 +1067,7 @@ printf(format, SSH_AUTHSOCKET_ENV_NAME, socket_name, SSH_AUTHSOCKET_ENV_NAME); printf("echo Agent pid %ld;\n", (long)parent_pid); + fflush(stdout); goto skip; } pid = fork(); -8<----------------8<--------------8<-- and the script I source from .bash_profile it lacks one important feature - locking, to prevent simultanious execution when several concurent consoles are starting any ideas on how to implement it will be appreciated -8<----------------8<--------------8<-- # start ssh-agent as a service and load private keys unset SSH_AUTH_SOCK unset SSH_AGENT_PID SSH_AGENT=/usr/bin/ssh-agent SSH_AGENT_OPT="-s -d" SSH_AGENT_FILE="$HOME/.ssh-agent-$HOSTNAME" SSH_ADD=/usr/bin/ssh-add SSH_ADD_OPT="" SSH_IDENTITIES="" # Check for initial state: # 1. there is only one instance of ssh-agent for the user # 2. SSH_AGENT_FILE exists and the last string containing SSH_AUTH_SOCK # matches running ssh-agent # 3. the soket exists, its path matches ssh-agent's PID, and permissions are correct # # If any condition fails, reset to correct state: # 1. kill all instances of ssh-agent # 2. delete SSH_AGENT_FILE # 3. start ssh-agent service and create new SSH_AGENT_FILE # # When correct initial state is achived, set and export SSH_AUTH_SOCK # and SSH_AGENT_PID variables, add keys ensure_ssh_agent_started() { if [ `ps x | grep 'ssh-agent$' | wc -l` -ne 1 -o ! -f "$SSH_AGENT_FILE" ] ; then for pid in `ps x | awk '/ssh-agent$/ { print $1 }'` ; do kill $pid done rm -f "$SSH_AGENT_FILE" fi if [ `ps x | grep 'ssh-agent$' | wc -l` -eq 0 ] ; then echo Installing service ssh-agent-$USER... # this command will ask you for a user password # it is required to install the service that runs on # behalf of a user cygrunsrv -I "ssh-agent-$USER" -d "CYGWIN ssh-agent for $USER" \ -p "$SSH_AGENT" -a "$SSH_AGENT_OPT" -t manual -u "$USER" \ -o -1 "$SSH_AGENT_FILE" echo Starting service ssh-agent-$USER... if ! cygrunsrv -S "ssh-agent-$USER" ; then echo Failed to start ssh-agent-$USER service return 1 else SSH_AGENT_STARTED=1 fi fi return 0 } validate_ssh_agent_and_load_keys() { SSH_AGENT_PID=`ps x | awk '/ssh-agent$/ { print $1 }'` eval `grep '^SSH_AUTH_SOCK' "$SSH_AGENT_FILE" 2>/dev/null | tail -n 1` if test -n "$SSH_AGENT_PID" -a -n "$SSH_AUTH_SOCK" && expr match "$SSH_AUTH_SOCK" "/tmp/ssh-[A-Za-z]*$SSH_AGENT_PID/agent.$SSH_AGENT_PID" 1>/dev/null && find `dirname $SSH_AUTH_SOCK` -type s -perm 600 -user "$USER" 1>/dev/null 2>/dev/null ; then export SSH_AGENT_PID if [ -n "$SSH_AGENT_STARTED" ] ; then echo Adding keys to the agent $SSH_ADD $SSH_ADD_OPT $SSH_IDENTITIES fi else unset SSH_AUTH_SOCK unset SSH_AGENT_PID fi } ensure_ssh_agent_started && validate_ssh_agent_and_load_keys unset ensure_ssh_agent_started unset validate_ssh_agent_and_load_keys unset SSH_AGENT unset SSH_AGENT_OPT unset SSH_AGENT_FILE unset SSH_ADD unset SSH_ADD_OPT unset SSH_IDENTITIES unset SSH_AGENT_STARTED -8<----------------8<--------------8<-- -- Best regards, Boris -- Unsubscribe info: http://cygwin.com/ml/#unsubscribe-simple Bug reporting: http://cygwin.com/bugs.html Documentation: http://cygwin.com/docs.html FAQ: http://cygwin.com/faq/