ssh-add.zsh 2.3 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970
  1. # Expected location of the ssh-agent authentication socket
  2. #
  3. # `SSH_AUTH_SOCK` points to the socket through which users interact with
  4. # ssh-agent loaded identities.
  5. #
  6. # Having this socket linked to a predictable place means a given user can expect
  7. # loaded identities to persist
  8. # - in any shell instance
  9. # - in tmux, screen and similar multiplexers
  10. # - through `sudo su` to root (BUT NOT with '-' or plain `su`)
  11. #
  12. # This setup helps to persist ssh agent-forwarding across remotes.
  13. [[ ! -z $SUDO_USER ]] && name=$SUDO_USER || name=$USER
  14. SOCK="/tmp/ssh-agent-$name-tmux"
  15. # Link up an existing socket to the expected location if it is not already.
  16. linksocket() {
  17. if [[ ! -z $SSH_AUTH_SOCK && $SSH_AUTH_SOCK != $SOCK ]]; then
  18. ln -sf $SSH_AUTH_SOCK $SOCK &> /dev/null
  19. fi
  20. export SSH_AUTH_SOCK=$SOCK
  21. }
  22. # Find an ssh-agent at the expected location, or start a new one.
  23. #
  24. # `ssh-add` returning a code of 2 means this user has no usable ssh-agent.
  25. #
  26. # If a new agent is started, remember to link the new socket.
  27. #
  28. # Note: ssh-add return codes:
  29. # 0 = success,
  30. # 1 = specified command fails (e.g., no keys with ssh-add -l)
  31. # 2 = unable to contact the authentication agent
  32. # Try to reach an existing socket.
  33. linksocket
  34. ssh-add -l &> /dev/null
  35. agent_reached=$?
  36. # For `sudo su`: a user cannot access a socket with another user's symlink,
  37. # so try to create a personal symlink to the same socket.
  38. # TODO Find a cleaner, simpler way to decide to create symlinks.
  39. if [[ $agent_reached -eq 2 ]]; then
  40. SOCK2="/tmp/ssh-agent-$USER-tmux"
  41. ln -sf `readlink $SOCK` $SOCK2
  42. export SSH_AUTH_SOCK=$SOCK2
  43. ssh-add -l &> /dev/null
  44. agent_reached=$?
  45. fi
  46. # Nothing worked. If there are any identities available, create a new agent.
  47. #
  48. # Defaults: ~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa ~/.ssh/identity
  49. identities_exist=false
  50. default_files=(~/.ssh/id_rsa ~/.ssh/id_dsa ~/.ssh/id_ecdsa ~/.ssh/identity)
  51. for file in $default_files; do
  52. [[ -f $file ]] && identities_exist=true && break
  53. done
  54. if [[ $identities_exist == true && $agent_reached -eq 2 ]]; then
  55. echo "Starting a new SSH Agent."
  56. eval `ssh-agent` &> /dev/null
  57. linksocket
  58. fi
  59. # Add any identities with the default file names if the agent does not have
  60. # anything.
  61. if [[ $identities_exist == true && `ssh-add -L | grep "^ssh-" | wc -l` -eq 0 ]]; then
  62. ssh-add
  63. fi