diff options
-rw-r--r-- | ChangeLog | 4 | ||||
-rw-r--r-- | contrib/ssh-copy-id | 309 | ||||
-rw-r--r-- | contrib/ssh-copy-id.1 | 251 |
3 files changed, 459 insertions, 105 deletions
@@ -1,3 +1,7 @@ | |||
1 | 20120322 | ||
2 | - (djm) [contrib/ssh-copy-id contrib/ssh-copy-id.1] Updated to Phil | ||
3 | Hands' greatly revised version. | ||
4 | |||
1 | 20120318 | 5 | 20120318 |
2 | - (djm) [configure.ac log.c scp.c sshconnect2.c openbsd-compat/vis.c] | 6 | - (djm) [configure.ac log.c scp.c sshconnect2.c openbsd-compat/vis.c] |
3 | [openbsd-compat/vis.h] FreeBSD's strnvis isn't compatible with OpenBSD's | 7 | [openbsd-compat/vis.h] FreeBSD's strnvis isn't compatible with OpenBSD's |
diff --git a/contrib/ssh-copy-id b/contrib/ssh-copy-id index 9451aceec..af18a1929 100644 --- a/contrib/ssh-copy-id +++ b/contrib/ssh-copy-id | |||
@@ -1,54 +1,293 @@ | |||
1 | #!/bin/sh | 1 | #!/bin/sh |
2 | 2 | ||
3 | # Shell script to install your public key on a remote machine | 3 | # Copyright (c) 1999-2013 Philip Hands <phil@hands.com> |
4 | # Takes the remote machine name as an argument. | 4 | # 2013 Martin Kletzander <mkletzan@redhat.com> |
5 | # Obviously, the remote machine must accept password authentication, | 5 | # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es> |
6 | # or one of the other keys in your ssh-agent, for this to work. | 6 | # 2010 Eric Moret <eric.moret@gmail.com> |
7 | 7 | # 2009 Xr <xr@i-jeuxvideo.com> | |
8 | ID_FILE="${HOME}/.ssh/id_rsa.pub" | 8 | # 2007 Justin Pryzby <justinpryzby@users.sourceforge.net> |
9 | 9 | # 2004 Reini Urban <rurban@x-ray.at> | |
10 | if [ "-i" = "$1" ]; then | 10 | # 2003 Colin Watson <cjwatson@debian.org> |
11 | shift | 11 | # All rights reserved. |
12 | # check if we have 2 parameters left, if so the first is the new ID file | 12 | # |
13 | if [ -n "$2" ]; then | 13 | # Redistribution and use in source and binary forms, with or without |
14 | if expr "$1" : ".*\.pub" > /dev/null ; then | 14 | # modification, are permitted provided that the following conditions |
15 | ID_FILE="$1" | 15 | # are met: |
16 | else | 16 | # 1. Redistributions of source code must retain the above copyright |
17 | ID_FILE="$1.pub" | 17 | # notice, this list of conditions and the following disclaimer. |
18 | fi | 18 | # 2. Redistributions in binary form must reproduce the above copyright |
19 | shift # and this should leave $1 as the target name | 19 | # notice, this list of conditions and the following disclaimer in the |
20 | # documentation and/or other materials provided with the distribution. | ||
21 | # | ||
22 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | ||
23 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | ||
24 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | ||
25 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | ||
26 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | ||
27 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | ||
28 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | ||
29 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | ||
30 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | ||
31 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | ||
32 | |||
33 | # Shell script to install your public key(s) on a remote machine | ||
34 | # See the ssh-copy-id(1) man page for details | ||
35 | |||
36 | # check that we have something mildly sane as our shell, or try to find something better | ||
37 | if false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0" | ||
38 | then | ||
39 | SANE_SH=${SANE_SH:-/usr/bin/ksh} | ||
40 | if printf 'true ^ false\n' | "$SANE_SH" | ||
41 | then | ||
42 | printf "'%s' seems viable.\n" "$SANE_SH" | ||
43 | exec "$SANE_SH" "$0" "$@" | ||
44 | else | ||
45 | cat <<-EOF | ||
46 | oh dear. | ||
47 | |||
48 | If you have a more recent shell available, that supports \$(...) etc. | ||
49 | please try setting the environment variable SANE_SH to the path of that | ||
50 | shell, and then retry running this script. If that works, please report | ||
51 | a bug describing your setup, and the shell you used to make it work. | ||
52 | |||
53 | EOF | ||
54 | printf "%s: ERROR: Less dimwitted shell required.\n" "$0" | ||
55 | exit 1 | ||
20 | fi | 56 | fi |
21 | else | 57 | fi |
22 | if [ x$SSH_AUTH_SOCK != x ] && ssh-add -L >/dev/null 2>&1; then | 58 | |
23 | GET_ID="$GET_ID ssh-add -L" | 59 | DEFAULT_PUB_ID_FILE=$(ls -t ${HOME}/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1) |
60 | |||
61 | usage () { | ||
62 | printf 'Usage: %s [-h|-?|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2 | ||
63 | exit 1 | ||
64 | } | ||
65 | |||
66 | # escape any single quotes in an argument | ||
67 | quote() { | ||
68 | printf "%s\n" "$1" | sed -e "s/'/'\\\\''/g" | ||
69 | } | ||
70 | |||
71 | use_id_file() { | ||
72 | local L_ID_FILE="$1" | ||
73 | |||
74 | if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then | ||
75 | PUB_ID_FILE="$L_ID_FILE" | ||
76 | else | ||
77 | PUB_ID_FILE="$L_ID_FILE.pub" | ||
24 | fi | 78 | fi |
79 | |||
80 | PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub) | ||
81 | |||
82 | # check that the files are readable | ||
83 | for f in $PUB_ID_FILE $PRIV_ID_FILE ; do | ||
84 | ErrMSG=$( { : < $f ; } 2>&1 ) || { | ||
85 | printf "\n%s: ERROR: failed to open ID file '%s': %s\n\n" "$0" "$f" "$(printf "%s\n" "$ErrMSG" | sed -e 's/.*: *//')" | ||
86 | exit 1 | ||
87 | } | ||
88 | done | ||
89 | GET_ID="cat \"$PUB_ID_FILE\"" | ||
90 | } | ||
91 | |||
92 | if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then | ||
93 | GET_ID="ssh-add -L" | ||
25 | fi | 94 | fi |
26 | 95 | ||
27 | if [ -z "`eval $GET_ID`" ] && [ -r "${ID_FILE}" ] ; then | 96 | while test "$#" -gt 0 |
28 | GET_ID="cat \"${ID_FILE}\"" | 97 | do |
98 | [ "${SEEN_OPT_I}" ] && expr "$1" : "[-]i" >/dev/null && { | ||
99 | printf "\n%s: ERROR: -i option must not be specified more than once\n\n" "$0" | ||
100 | usage | ||
101 | } | ||
102 | |||
103 | OPT= OPTARG= | ||
104 | # implement something like getopt to avoid Solaris pain | ||
105 | case "$1" in | ||
106 | -i?*|-o?*|-p?*) | ||
107 | OPT="$(printf -- "$1"|cut -c1-2)" | ||
108 | OPTARG="$(printf -- "$1"|cut -c3-)" | ||
109 | shift | ||
110 | ;; | ||
111 | -o|-p) | ||
112 | OPT="$1" | ||
113 | OPTARG="$2" | ||
114 | shift 2 | ||
115 | ;; | ||
116 | -i) | ||
117 | OPT="$1" | ||
118 | test "$#" -le 2 || expr "$2" : "[-]" >/dev/null || { | ||
119 | OPTARG="$2" | ||
120 | shift | ||
121 | } | ||
122 | shift | ||
123 | ;; | ||
124 | -n|-h|-\?) | ||
125 | OPT="$1" | ||
126 | OPTARG= | ||
127 | shift | ||
128 | ;; | ||
129 | --) | ||
130 | shift | ||
131 | while test "$#" -gt 0 | ||
132 | do | ||
133 | SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'" | ||
134 | shift | ||
135 | done | ||
136 | break | ||
137 | ;; | ||
138 | -*) | ||
139 | printf "\n%s: ERROR: invalid option (%s)\n\n" "$0" "$1" | ||
140 | usage | ||
141 | ;; | ||
142 | *) | ||
143 | SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'" | ||
144 | shift | ||
145 | continue | ||
146 | ;; | ||
147 | esac | ||
148 | |||
149 | case "$OPT" in | ||
150 | -i) | ||
151 | SEEN_OPT_I="yes" | ||
152 | use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}" | ||
153 | ;; | ||
154 | -o|-p) | ||
155 | SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }$OPT '$(quote "$OPTARG")'" | ||
156 | ;; | ||
157 | -n) | ||
158 | DRY_RUN=1 | ||
159 | ;; | ||
160 | -h|-\?) | ||
161 | usage | ||
162 | ;; | ||
163 | esac | ||
164 | done | ||
165 | |||
166 | eval set -- "$SAVEARGS" | ||
167 | |||
168 | if [ $# != 1 ] ; then | ||
169 | printf '%s: ERROR: Too many arguments. Expecting a target hostname, got: %s\n\n' "$0" "$SAVEARGS" >&2 | ||
170 | usage | ||
29 | fi | 171 | fi |
30 | 172 | ||
31 | if [ -z "`eval $GET_ID`" ]; then | 173 | # drop trailing colon |
32 | echo "$0: ERROR: No identities found" >&2 | 174 | USER_HOST=$(printf "%s\n" "$1" | sed 's/:$//') |
33 | exit 1 | 175 | # tack the hostname onto SSH_OPTS |
176 | SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }'$(quote "$USER_HOST")'" | ||
177 | # and populate "$@" for later use (only way to get proper quoting of options) | ||
178 | eval set -- "$SSH_OPTS" | ||
179 | |||
180 | if [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then | ||
181 | use_id_file "$PUB_ID_FILE" | ||
34 | fi | 182 | fi |
35 | 183 | ||
36 | if [ "$#" -lt 1 ] || [ "$1" = "-h" ] || [ "$1" = "--help" ]; then | 184 | if [ -z "$(eval $GET_ID)" ] ; then |
37 | echo "Usage: $0 [-i [identity_file]] [user@]machine" >&2 | 185 | printf '%s: ERROR: No identities found\n' "$0" >&2 |
38 | exit 1 | 186 | exit 1 |
39 | fi | 187 | fi |
40 | 188 | ||
41 | # strip any trailing colon | 189 | # populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...) |
42 | host=`echo $1 | sed 's/:$//'` | 190 | # and has the side effect of setting $NEW_IDS |
191 | populate_new_ids() { | ||
192 | local L_SUCCESS="$1" | ||
43 | 193 | ||
44 | { eval "$GET_ID" ; } | ssh $host "umask 077; test -d ~/.ssh || mkdir ~/.ssh ; cat >> ~/.ssh/authorized_keys" || exit 1 | 194 | # repopulate "$@" inside this function |
195 | eval set -- "$SSH_OPTS" | ||
45 | 196 | ||
46 | cat <<EOF | 197 | umask 0177 |
47 | Now try logging into the machine, with "ssh '$host'", and check in: | 198 | local L_TMP_ID_FILE=$(mktemp ~/.ssh/ssh-copy-id_id.XXXXXXXXXX) |
199 | trap "rm -f $L_TMP_ID_FILE*" EXIT TERM INT QUIT | ||
200 | printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2 | ||
201 | NEW_IDS=$( | ||
202 | eval $GET_ID | { | ||
203 | while read ID ; do | ||
204 | printf '%s\n' "$ID" > $L_TMP_ID_FILE | ||
48 | 205 | ||
49 | ~/.ssh/authorized_keys | 206 | # the next line assumes $PRIV_ID_FILE only set if using a single id file - this |
207 | # assumption will break if we implement the possibility of multiple -i options. | ||
208 | # The point being that if file based, ssh needs the private key, which it cannot | ||
209 | # find if only given the contents of the .pub file in an unrelated tmpfile | ||
210 | ssh -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ | ||
211 | -o PreferredAuthentications=publickey \ | ||
212 | -o IdentitiesOnly=yes "$@" exit 2>$L_TMP_ID_FILE.stderr </dev/null | ||
213 | if [ "$?" = "$L_SUCCESS" ] ; then | ||
214 | : > $L_TMP_ID_FILE | ||
215 | else | ||
216 | grep 'Permission denied' $L_TMP_ID_FILE.stderr >/dev/null || { | ||
217 | sed -e 's/^/ERROR: /' <$L_TMP_ID_FILE.stderr >$L_TMP_ID_FILE | ||
218 | cat >/dev/null #consume the other keys, causing loop to end | ||
219 | } | ||
220 | fi | ||
221 | |||
222 | cat $L_TMP_ID_FILE | ||
223 | done | ||
224 | } | ||
225 | ) | ||
226 | rm -f $L_TMP_ID_FILE* && trap - EXIT TERM INT QUIT | ||
227 | |||
228 | if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then | ||
229 | printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2 | ||
230 | exit 1 | ||
231 | fi | ||
232 | if [ -z "$NEW_IDS" ] ; then | ||
233 | printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n\n' "$0" >&2 | ||
234 | exit 0 | ||
235 | fi | ||
236 | printf '%s: INFO: %d key(s) remain to be installed -- if you are prompted now it is to install the new keys\n' "$0" "$(printf '%s\n' "$NEW_IDS" | wc -l)" >&2 | ||
237 | } | ||
50 | 238 | ||
51 | to make sure we haven't added extra keys that you weren't expecting. | 239 | REMOTE_VERSION=$(ssh -v -o PreferredAuthentications=',' "$@" 2>&1 | |
240 | sed -ne 's/.*remote software version //p') | ||
52 | 241 | ||
53 | EOF | 242 | case "$REMOTE_VERSION" in |
243 | NetScreen*) | ||
244 | populate_new_ids 1 | ||
245 | for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do | ||
246 | KEY_NO=$(($KEY_NO + 1)) | ||
247 | printf "%s\n" "$KEY" | grep ssh-dss >/dev/null || { | ||
248 | printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2 | ||
249 | continue | ||
250 | } | ||
251 | [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | ssh -T "$@" >/dev/null 2>&1 | ||
252 | if [ $? = 255 ] ; then | ||
253 | printf '%s: ERROR: installation of key #%d failed (please report a bug describing what caused this, so that we can make this message useful)\n' "$0" "$KEY_NO" >&2 | ||
254 | else | ||
255 | ADDED=$(($ADDED + 1)) | ||
256 | fi | ||
257 | done | ||
258 | if [ -z "$ADDED" ] ; then | ||
259 | exit 1 | ||
260 | fi | ||
261 | ;; | ||
262 | *) | ||
263 | # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect | ||
264 | populate_new_ids 0 | ||
265 | [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | ssh "$@" " | ||
266 | umask 077 ; | ||
267 | mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ; | ||
268 | if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi" \ | ||
269 | || exit 1 | ||
270 | ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) | ||
271 | ;; | ||
272 | esac | ||
273 | |||
274 | if [ "$DRY_RUN" ] ; then | ||
275 | cat <<-EOF | ||
276 | =-=-=-=-=-=-=-= | ||
277 | Would have added the following key(s): | ||
278 | |||
279 | $NEW_IDS | ||
280 | =-=-=-=-=-=-=-= | ||
281 | EOF | ||
282 | else | ||
283 | cat <<-EOF | ||
284 | |||
285 | Number of key(s) added: $ADDED | ||
286 | |||
287 | Now try logging into the machine, with: "ssh $SSH_OPTS" | ||
288 | and check to make sure that only the key(s) you wanted were added. | ||
289 | |||
290 | EOF | ||
291 | fi | ||
54 | 292 | ||
293 | # =-=-=-= | ||
diff --git a/contrib/ssh-copy-id.1 b/contrib/ssh-copy-id.1 index cb15ab24d..67a59e492 100644 --- a/contrib/ssh-copy-id.1 +++ b/contrib/ssh-copy-id.1 | |||
@@ -1,75 +1,186 @@ | |||
1 | .ig \" -*- nroff -*- | 1 | .ig \" -*- nroff -*- |
2 | Copyright (c) 1999 Philip Hands Computing <http://www.hands.com/> | 2 | Copyright (c) 1999-2013 hands.com Ltd. <http://hands.com/> |
3 | 3 | ||
4 | Permission is granted to make and distribute verbatim copies of | 4 | Redistribution and use in source and binary forms, with or without |
5 | this manual provided the copyright notice and this permission notice | 5 | modification, are permitted provided that the following conditions |
6 | are preserved on all copies. | 6 | are met: |
7 | 1. Redistributions of source code must retain the above copyright | ||
8 | notice, this list of conditions and the following disclaimer. | ||
9 | 2. Redistributions in binary form must reproduce the above copyright | ||
10 | notice, this list of conditions and the following disclaimer in the | ||
11 | documentation and/or other materials provided with the distribution. | ||
7 | 12 | ||
8 | Permission is granted to copy and distribute modified versions of this | 13 | THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
9 | manual under the conditions for verbatim copying, provided that the | 14 | IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
10 | entire resulting derived work is distributed under the terms of a | 15 | OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
11 | permission notice identical to this one. | 16 | IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
12 | 17 | INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | |
13 | Permission is granted to copy and distribute translations of this | 18 | NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
14 | manual into another language, under the above conditions for modified | 19 | DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
15 | versions, except that this permission notice may be included in | 20 | THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
16 | translations approved by the Free Software Foundation instead of in | 21 | (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
17 | the original English. | 22 | THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
18 | .. | 23 | .. |
19 | .TH SSH-COPY-ID 1 "14 November 1999" "OpenSSH" | 24 | .Dd $Mdocdate: June 17 2010 $ |
20 | .SH NAME | 25 | .Dt SSH-COPY-ID 1 |
21 | ssh-copy-id \- install your public key in a remote machine's authorized_keys | 26 | .Os |
22 | .SH SYNOPSIS | 27 | .Sh NAME |
23 | .B ssh-copy-id [-i [identity_file]] | 28 | .Nm ssh-copy-id |
24 | .I "[user@]machine" | 29 | .Nd use locally available keys to authorise logins on a remote machine |
30 | .Sh SYNOPSIS | ||
31 | .Nm | ||
32 | .Op Fl n | ||
33 | .Op Fl i Op Ar identity_file | ||
34 | .Op Fl p Ar port | ||
35 | .Op Fl o Ar ssh_option | ||
36 | .Op Ar user Ns @ Ns | ||
37 | .Ar hostname | ||
38 | .Nm | ||
39 | .Fl h | Fl ? | ||
25 | .br | 40 | .br |
26 | .SH DESCRIPTION | 41 | .Sh DESCRIPTION |
27 | .BR ssh-copy-id | 42 | .Nm |
28 | is a script that uses ssh to log into a remote machine and | 43 | is a script that uses |
29 | append the indicated identity file to that machine's | 44 | .Xr ssh 1 |
30 | .B ~/.ssh/authorized_keys | 45 | to log into a remote machine (presumably using a login password, |
31 | file. | 46 | so password authentication should be enabled, unless you've done some |
32 | .PP | 47 | clever use of multiple identities). It assembles a list of one or more |
33 | If the | 48 | fingerprints (as described below) and tries to log in with each key, to |
34 | .B -i | 49 | see if any of them are already installed (of course, if you are not using |
35 | option is given then the identity file (defaults to | 50 | .Xr ssh-agent 1 |
36 | .BR ~/.ssh/id_rsa.pub ) | 51 | this may result in you being repeatedly prompted for pass-phrases). |
37 | is used, regardless of whether there are any keys in your | 52 | It then assembles a list of those that failed to log in, and using ssh, |
38 | .BR ssh-agent . | 53 | enables logins with those keys on the remote server. By default it adds |
39 | Otherwise, if this: | 54 | the keys by appending them to the remote user's |
40 | .PP | 55 | .Pa ~/.ssh/authorized_keys |
41 | .B " ssh-add -L" | 56 | (creating the file, and directory, if necessary). It is also capable |
42 | .PP | 57 | of detecting if the remote system is a NetScreen, and using its |
43 | provides any output, it uses that in preference to the identity file. | 58 | .Ql set ssh pka-dsa key ... |
44 | .PP | 59 | command instead. |
45 | If the | 60 | .Pp |
46 | .B -i | 61 | The options are as follows: |
47 | option is used, or the | 62 | .Bl -tag -width Ds |
48 | .B ssh-add | 63 | .It Fl i Ar identity_file |
49 | produced no output, then it uses the contents of the identity | 64 | Use only the key(s) contained in |
50 | file. Once it has one or more fingerprints (by whatever means) it | 65 | .Ar identity_file |
51 | uses ssh to append them to | 66 | (rather than looking for identities via |
52 | .B ~/.ssh/authorized_keys | 67 | .Xr ssh-add 1 |
53 | on the remote machine (creating the file, and directory, if necessary.) | 68 | or in the |
54 | 69 | .Ic default_ID_file ) . | |
55 | .SH NOTES | 70 | If the filename does not end in |
56 | This program does not modify the permissions of any | 71 | .Pa .pub |
57 | pre-existing files or directories. Therefore, if the remote | 72 | this is added. If the filename is omitted, the |
58 | .B sshd | 73 | .Ic default_ID_file |
59 | has | 74 | is used. |
60 | .B StrictModes | 75 | .Pp |
61 | set in its | 76 | Note that this can be used to ensure that the keys copied have the |
62 | configuration, then the user's home, | 77 | comment one prefers and/or extra options applied, by ensuring that the |
63 | .B ~/.ssh | 78 | key file has these set as preferred before the copy is attempted. |
64 | folder, and | 79 | .It Fl n |
65 | .B ~/.ssh/authorized_keys | 80 | do a dry-run. Instead of installing keys on the remote system simply |
66 | file may need to have group writability disabled manually, e.g. via | 81 | prints the key(s) that would have been installed. |
67 | 82 | .It Fl h , Fl ? | |
68 | .B " chmod go-w ~ ~/.ssh ~/.ssh/authorized_keys" | 83 | Print Usage summary |
69 | 84 | .It Fl p Ar port , Fl o Ar ssh_option | |
70 | on the remote machine. | 85 | These two options are simply passed through untouched, along with their |
71 | 86 | argument, to allow one to set the port or other | |
72 | .SH "SEE ALSO" | 87 | .Xr ssh 1 |
73 | .BR ssh (1), | 88 | options, respectively. |
74 | .BR ssh-agent (1), | 89 | .Pp |
75 | .BR sshd (8) | 90 | Rather than specifying these as command line options, it is often better to use (per-host) settings in |
91 | .Xr ssh 1 Ns 's | ||
92 | configuration file: | ||
93 | .Xr ssh_config 5 . | ||
94 | .El | ||
95 | .Pp | ||
96 | Default behaviour without | ||
97 | .Fl i , | ||
98 | is to check if | ||
99 | .Ql ssh-add -L | ||
100 | provides any output, and if so those keys are used. Note that this results in | ||
101 | the comment on the key being the filename that was given to | ||
102 | .Xr ssh-add 1 | ||
103 | when the key was loaded into your | ||
104 | .Xr ssh-agent 1 | ||
105 | rather than the comment contained in that file, which is a bit of a shame. | ||
106 | Otherwise, if | ||
107 | .Xr ssh-add 1 | ||
108 | provides no keys contents of the | ||
109 | .Ic default_ID_file | ||
110 | will be used. | ||
111 | .Pp | ||
112 | The | ||
113 | .Ic default_ID_file | ||
114 | is the most recent file that matches: | ||
115 | .Pa ~/.ssh/id*.pub , | ||
116 | (excluding those that match | ||
117 | .Pa ~/.ssh/*-cert.pub ) | ||
118 | so if you create a key that is not the one you want | ||
119 | .Nm | ||
120 | to use, just use | ||
121 | .Xr touch 1 | ||
122 | on your preferred key's | ||
123 | .Pa .pub | ||
124 | file to reinstate it as the most recent. | ||
125 | .Pp | ||
126 | .Sh EXAMPLES | ||
127 | If you have already installed keys from one system on a lot of remote | ||
128 | hosts, and you then create a new key, on a new client machine, say, | ||
129 | it can be difficult to keep track of which systems on which you've | ||
130 | installed the new key. One way of dealing with this is to load both | ||
131 | the new key and old key(s) into your | ||
132 | .Xr ssh-agent 1 . | ||
133 | Load the new key first, without the | ||
134 | .Fl c | ||
135 | option, then load one or more old keys into the agent, possibly by | ||
136 | ssh-ing to the client machine that has that old key, using the | ||
137 | .Fl A | ||
138 | option to allow agent forwarding: | ||
139 | .Pp | ||
140 | .D1 user@newclient$ ssh-add | ||
141 | .D1 user@newclient$ ssh -A old.client | ||
142 | .D1 user@oldl$ ssh-add -c | ||
143 | .D1 No ... prompt for pass-phrase ... | ||
144 | .D1 user@old$ logoff | ||
145 | .D1 user@newclient$ ssh someserver | ||
146 | .Pp | ||
147 | now, if the new key is installed on the server, you'll be allowed in | ||
148 | unprompted, whereas if you only have the old key(s) enabled, you'll be | ||
149 | asked for confirmation, which is your cue to log back out and run | ||
150 | .Pp | ||
151 | .D1 user@newclient$ ssh-copy-id -i someserver | ||
152 | .Pp | ||
153 | The reason you might want to specify the -i option in this case is to | ||
154 | ensure that the comment on the installed key is the one from the | ||
155 | .Pa .pub | ||
156 | file, rather than just the filename that was loaded into you agent. | ||
157 | It also ensures that only the id you intended is installed, rather than | ||
158 | all the keys that you have in your | ||
159 | .Xr ssh-agent 1 . | ||
160 | Of course, you can specify another id, or use the contents of the | ||
161 | .Xr ssh-agent 1 | ||
162 | as you prefer. | ||
163 | .Pp | ||
164 | Having mentioned | ||
165 | .Xr ssh-add 1 Ns 's | ||
166 | .Fl c | ||
167 | option, you might consider using this whenever using agent forwarding | ||
168 | to avoid your key being hijacked, but it is much better to instead use | ||
169 | .Xr ssh 1 Ns 's | ||
170 | .Ar ProxyCommand | ||
171 | and | ||
172 | .Fl W | ||
173 | option, | ||
174 | to bounce through remote servers while always doing direct end-to-end | ||
175 | authentication. This way the middle hop(s) don't get access to your | ||
176 | .Xr ssh-agent 1 . | ||
177 | A web search for | ||
178 | .Ql ssh proxycommand nc | ||
179 | should prove enlightening (N.B. the modern approach is to use the | ||
180 | .Fl W | ||
181 | option, rather than | ||
182 | .Xr nc 1 ) . | ||
183 | .Sh "SEE ALSO" | ||
184 | .Xr ssh 1 , | ||
185 | .Xr ssh-agent 1 , | ||
186 | .Xr sshd 8 | ||