ssh-agent.plugin.zsh
3619 bytes
1# Get the filename to store/lookup the environment from
2ssh_env_cache="$HOME/.ssh/environment-$SHORT_HOST"
3
4function _start_agent() {
5 # Check if ssh-agent is already running
6 if [[ -f "$ssh_env_cache" ]]; then
7 . "$ssh_env_cache" > /dev/null
8
9 # Test if $SSH_AUTH_SOCK is visible
10 zmodload zsh/net/socket
11 if [[ -S "$SSH_AUTH_SOCK" ]] && zsocket "$SSH_AUTH_SOCK" 2>/dev/null; then
12 return 0
13 fi
14 fi
15
16 if [[ ! -d "$HOME/.ssh" ]]; then
17 echo "[oh-my-zsh] ssh-agent plugin requires ~/.ssh directory"
18 return 1
19 fi
20
21 # Set a maximum lifetime for identities added to ssh-agent
22 local lifetime
23 zstyle -s :omz:plugins:ssh-agent lifetime lifetime
24
25 # start ssh-agent and setup environment
26 zstyle -t :omz:plugins:ssh-agent quiet || echo >&2 "Starting ssh-agent ..."
27 ssh-agent -s ${lifetime:+-t} ${lifetime} | sed '/^echo/d' >! "$ssh_env_cache"
28 chmod 600 "$ssh_env_cache"
29 . "$ssh_env_cache" > /dev/null
30}
31
32function _add_identities() {
33 local id file line sig lines
34 local -a identities loaded_sigs loaded_ids not_loaded
35 zstyle -a :omz:plugins:ssh-agent identities identities
36
37 # check for .ssh folder presence
38 if [[ ! -d "$HOME/.ssh" ]]; then
39 return
40 fi
41
42 # add default keys if no identities were set up via zstyle
43 # this is to mimic the call to ssh-add with no identities
44 if [[ ${#identities} -eq 0 ]]; then
45 # key list found on `ssh-add` man page's DESCRIPTION section
46 for id in id_rsa id_dsa id_ecdsa id_ed25519 id_ed25519_sk identity; do
47 # check if file exists
48 [[ -f "$HOME/.ssh/$id" ]] && identities+=($id)
49 done
50 fi
51
52 # get list of loaded identities' signatures and filenames
53 if lines=$(ssh-add -l); then
54 for line in ${(f)lines}; do
55 loaded_sigs+=${${(z)line}[2]}
56 loaded_ids+=${${(z)line}[3]}
57 done
58 fi
59
60 # add identities if not already loaded
61 for id in $identities; do
62 # if id is an absolute path, make file equal to id
63 [[ "$id" = /* ]] && file="$id" || file="$HOME/.ssh/$id"
64 # check for filename match, otherwise try for signature match
65 if [[ -f $file && ${loaded_ids[(I)$file]} -le 0 ]]; then
66 sig="$(ssh-keygen -lf "$file" | awk '{print $2}')"
67 [[ ${loaded_sigs[(I)$sig]} -le 0 ]] && not_loaded+=("$file")
68 fi
69 done
70
71 # abort if no identities need to be loaded
72 if [[ ${#not_loaded} -eq 0 ]]; then
73 return
74 fi
75
76 # pass extra arguments to ssh-add
77 local args
78 zstyle -a :omz:plugins:ssh-agent ssh-add-args args
79
80 # if ssh-agent quiet mode, pass -q to ssh-add
81 zstyle -t :omz:plugins:ssh-agent quiet && args=(-q $args)
82
83 # use user specified helper to ask for password (ksshaskpass, etc)
84 local helper
85 zstyle -s :omz:plugins:ssh-agent helper helper
86
87 if [[ -n "$helper" ]]; then
88 if [[ -z "${commands[$helper]}" ]]; then
89 echo >&2 "ssh-agent: the helper '$helper' has not been found."
90 else
91 SSH_ASKPASS="$helper" ssh-add "${args[@]}" ${^not_loaded} < /dev/null
92 return $?
93 fi
94 fi
95
96 ssh-add "${args[@]}" ${^not_loaded}
97}
98
99# Add a nifty symlink for screen/tmux if agent forwarding is enabled
100if zstyle -t :omz:plugins:ssh-agent agent-forwarding \
101 && [[ -n "$SSH_AUTH_SOCK" ]]; then
102 if [[ ! -L "$SSH_AUTH_SOCK" ]]; then
103 if [[ -n "$TERMUX_VERSION" ]]; then
104 ln -sf "$SSH_AUTH_SOCK" "$PREFIX"/tmp/ssh-agent-$USERNAME-screen
105 else
106 ln -sf "$SSH_AUTH_SOCK" /tmp/ssh-agent-$USERNAME-screen
107 fi
108 fi
109else
110 _start_agent
111fi
112
113# Don't add identities if lazy-loading is enabled
114if ! zstyle -t :omz:plugins:ssh-agent lazy; then
115 _add_identities
116fi
117
118unset agent_forwarding ssh_env_cache
119unfunction _start_agent _add_identities