#!/usr/local/bin/perl # $Id: ssh-agent-setup,v 1.1.1.1 2000/03/23 17:14:48 tamtoft Exp $ # ssh-agent-setup: # Find a working ssh-agent or else start one. In either case, # emit an environment-setting command string to enable use of # the agent by subsequent processes. # # After starting a new ssh-agent or finding an old one with no # identities, invoke ssh-add to add the current user's identity. # This prompts for a passphrase if one is needed. # # Proper usage is: # # eval `setup-ssh-agent` # foreach $var ('SSH_AUTH_SOCK', 'SSH_AUTHENTICATION_SOCKET') { $SSH_AUTH_SOCK = $ENV{$var}; if (defined($SSH_AUTH_SOCK) && &reuse_agent()) { exit; } } $USER = $ENV{'USER'}; $tmp_ssh_USER = "/tmp/ssh-$USER"; if (opendir SOCKDIR, $tmp_ssh_USER) { foreach $socket (readdir SOCKDIR) { $SSH_AUTH_SOCK = "$tmp_ssh_USER/$socket"; next unless ((-S $SSH_AUTH_SOCK) || (-p $SSH_AUTH_SOCK)); if (&reuse_agent()) { exit; } } } &start_agent(); exit; # Try to contact the agent on the socket in $SSH_AUTH_SOCK. # If successful, and it has identities, emit socket setup # commands in prevailing shell syntax and return true. # If successful, but it has no identities, invoke ssh-add. # If ssh-add succeeds, emit socket setup and return true. # Otherwise (ssh-add failure), abort this process. # Otherwise (agent-contact failure), delete the given socket # and return false. sub reuse_agent { $ENV{'SSH_AUTH_SOCK'} = $ENV{'SSH_AUTHENTICATION_SOCKET'} = $SSH_AUTH_SOCK; $response = `ssh-add -l 2>&1`; if ($?) { if (($? >> 8) == 1) { # agent didn't answer unlink $SSH_AUTH_SOCK; return 0; } die "$response\n", "ssh-add failed (exit status ", $? >> 8, ")\n"; } if (($response eq "The agent has no identities.\n") && (system("ssh-add 1>&2"))) { die "ssh-add failed (exit status ", $? >> 8, ")\n"; } $csh_like = ($ENV{'SHELL'} =~ /csh$/); foreach $var ('SSH_AUTH_SOCK', 'SSH_AUTHENTICATION_SOCKET') { if ($csh_like) { print "setenv $var $SSH_AUTH_SOCK;\n"; } else { print "$var=$SSH_AUTH_SOCK; export $var;\n"; } } 1; # return true } # Invoke ssh-agent and save the shell commands that it emits. # Extract an SSH_AUTH_SOCK (or SSH_AUTHENTICATION_SOCKET) binding # from those commands. # Establish that binding and invoke ssh-add to add the user's # identity to the new agent, possibly asking for a passphrase. # Emit the command strings produced by ssh-agent. sub start_agent { local $setup = `ssh-agent`; if ($?) { die "$0: ssh-agent failed (status $?)\n", $setup; } extract: { foreach $var ('SSH_AUTH_SOCK', 'SSH_AUTHENTICATION_SOCKET') { if ($setup =~ /^(setenv )?$var[ =]([^;]+);/) { $ENV{$var} = $2; last extract; } } die "$0: ssh-agent produced no SSH_AUTH_SOCK binding:\n", $setup; } if (system("ssh-add 1>&2")) { die "ssh-agent wrote:\n", $setup; } else { print $setup; } }