1ce3adf43SDag-Erling Smørgrav#!/bin/sh 2ce3adf43SDag-Erling Smørgrav 3ce3adf43SDag-Erling Smørgrav# Copyright (c) 1999-2013 Philip Hands <phil@hands.com> 4ce3adf43SDag-Erling Smørgrav# 2013 Martin Kletzander <mkletzan@redhat.com> 5ce3adf43SDag-Erling Smørgrav# 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es> 6ce3adf43SDag-Erling Smørgrav# 2010 Eric Moret <eric.moret@gmail.com> 7ce3adf43SDag-Erling Smørgrav# 2009 Xr <xr@i-jeuxvideo.com> 8ce3adf43SDag-Erling Smørgrav# 2007 Justin Pryzby <justinpryzby@users.sourceforge.net> 9ce3adf43SDag-Erling Smørgrav# 2004 Reini Urban <rurban@x-ray.at> 10ce3adf43SDag-Erling Smørgrav# 2003 Colin Watson <cjwatson@debian.org> 11ce3adf43SDag-Erling Smørgrav# All rights reserved. 12ce3adf43SDag-Erling Smørgrav# 13ce3adf43SDag-Erling Smørgrav# Redistribution and use in source and binary forms, with or without 14ce3adf43SDag-Erling Smørgrav# modification, are permitted provided that the following conditions 15ce3adf43SDag-Erling Smørgrav# are met: 16ce3adf43SDag-Erling Smørgrav# 1. Redistributions of source code must retain the above copyright 17ce3adf43SDag-Erling Smørgrav# notice, this list of conditions and the following disclaimer. 18ce3adf43SDag-Erling Smørgrav# 2. Redistributions in binary form must reproduce the above copyright 19ce3adf43SDag-Erling Smørgrav# notice, this list of conditions and the following disclaimer in the 20ce3adf43SDag-Erling Smørgrav# documentation and/or other materials provided with the distribution. 21ce3adf43SDag-Erling Smørgrav# 22ce3adf43SDag-Erling Smørgrav# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 23ce3adf43SDag-Erling Smørgrav# IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 24ce3adf43SDag-Erling Smørgrav# OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 25ce3adf43SDag-Erling Smørgrav# IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 26ce3adf43SDag-Erling Smørgrav# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 27ce3adf43SDag-Erling Smørgrav# NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 28ce3adf43SDag-Erling Smørgrav# DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 29ce3adf43SDag-Erling Smørgrav# THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 30ce3adf43SDag-Erling Smørgrav# (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 31ce3adf43SDag-Erling Smørgrav# THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 32ce3adf43SDag-Erling Smørgrav 33ce3adf43SDag-Erling Smørgrav# Shell script to install your public key(s) on a remote machine 34ce3adf43SDag-Erling Smørgrav# See the ssh-copy-id(1) man page for details 35ce3adf43SDag-Erling Smørgrav 36ce3adf43SDag-Erling Smørgrav# check that we have something mildly sane as our shell, or try to find something better 37ce3adf43SDag-Erling Smørgravif false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0" 38ce3adf43SDag-Erling Smørgravthen 39ce3adf43SDag-Erling Smørgrav SANE_SH=${SANE_SH:-/usr/bin/ksh} 40ce3adf43SDag-Erling Smørgrav if printf 'true ^ false\n' | "$SANE_SH" 41ce3adf43SDag-Erling Smørgrav then 42ce3adf43SDag-Erling Smørgrav printf "'%s' seems viable.\n" "$SANE_SH" 43ce3adf43SDag-Erling Smørgrav exec "$SANE_SH" "$0" "$@" 44ce3adf43SDag-Erling Smørgrav else 45ce3adf43SDag-Erling Smørgrav cat <<-EOF 46ce3adf43SDag-Erling Smørgrav oh dear. 47ce3adf43SDag-Erling Smørgrav 48ce3adf43SDag-Erling Smørgrav If you have a more recent shell available, that supports \$(...) etc. 49ce3adf43SDag-Erling Smørgrav please try setting the environment variable SANE_SH to the path of that 50ce3adf43SDag-Erling Smørgrav shell, and then retry running this script. If that works, please report 51ce3adf43SDag-Erling Smørgrav a bug describing your setup, and the shell you used to make it work. 52ce3adf43SDag-Erling Smørgrav 53ce3adf43SDag-Erling Smørgrav EOF 54ce3adf43SDag-Erling Smørgrav printf "%s: ERROR: Less dimwitted shell required.\n" "$0" 55ce3adf43SDag-Erling Smørgrav exit 1 56ce3adf43SDag-Erling Smørgrav fi 57ce3adf43SDag-Erling Smørgravfi 58ce3adf43SDag-Erling Smørgrav 59acc1a9efSDag-Erling SmørgravDEFAULT_PUB_ID_FILE="$HOME/$(cd "$HOME" ; ls -t .ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)" 60ce3adf43SDag-Erling Smørgrav 61ce3adf43SDag-Erling Smørgravusage () { 62acc1a9efSDag-Erling Smørgrav printf 'Usage: %s [-h|-?|-f|-n] [-i [identity_file]] [-p port] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2 63acc1a9efSDag-Erling Smørgrav printf '\t-f: force mode -- copy keys without trying to check if they are already installed\n' >&2 64acc1a9efSDag-Erling Smørgrav printf '\t-n: dry run -- no keys are actually copied\n' >&2 65acc1a9efSDag-Erling Smørgrav printf '\t-h|-?: print this help\n' >&2 66ce3adf43SDag-Erling Smørgrav exit 1 67ce3adf43SDag-Erling Smørgrav} 68ce3adf43SDag-Erling Smørgrav 69ce3adf43SDag-Erling Smørgrav# escape any single quotes in an argument 70ce3adf43SDag-Erling Smørgravquote() { 71ce3adf43SDag-Erling Smørgrav printf "%s\n" "$1" | sed -e "s/'/'\\\\''/g" 72ce3adf43SDag-Erling Smørgrav} 73ce3adf43SDag-Erling Smørgrav 74ce3adf43SDag-Erling Smørgravuse_id_file() { 75ce3adf43SDag-Erling Smørgrav local L_ID_FILE="$1" 76ce3adf43SDag-Erling Smørgrav 77ce3adf43SDag-Erling Smørgrav if expr "$L_ID_FILE" : ".*\.pub$" >/dev/null ; then 78ce3adf43SDag-Erling Smørgrav PUB_ID_FILE="$L_ID_FILE" 79ce3adf43SDag-Erling Smørgrav else 80ce3adf43SDag-Erling Smørgrav PUB_ID_FILE="$L_ID_FILE.pub" 81ce3adf43SDag-Erling Smørgrav fi 82ce3adf43SDag-Erling Smørgrav 83acc1a9efSDag-Erling Smørgrav [ "$FORCED" ] || PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub) 84ce3adf43SDag-Erling Smørgrav 85ce3adf43SDag-Erling Smørgrav # check that the files are readable 86acc1a9efSDag-Erling Smørgrav for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do 87acc1a9efSDag-Erling Smørgrav ErrMSG=$( { : < "$f" ; } 2>&1 ) || { 88acc1a9efSDag-Erling Smørgrav local L_PRIVMSG="" 89acc1a9efSDag-Erling Smørgrav [ "$f" = "$PRIV_ID_FILE" ] && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)" 90acc1a9efSDag-Erling Smørgrav printf "\n%s: ERROR: failed to open ID file '%s': %s\n" "$0" "$f" "$(printf "%s\n%s\n" "$ErrMSG" "$L_PRIVMSG" | sed -e 's/.*: *//')" 91ce3adf43SDag-Erling Smørgrav exit 1 92ce3adf43SDag-Erling Smørgrav } 93ce3adf43SDag-Erling Smørgrav done 94acc1a9efSDag-Erling Smørgrav printf '%s: INFO: Source of key(s) to be installed: "%s"\n' "$0" "$PUB_ID_FILE" >&2 95ce3adf43SDag-Erling Smørgrav GET_ID="cat \"$PUB_ID_FILE\"" 96ce3adf43SDag-Erling Smørgrav} 97ce3adf43SDag-Erling Smørgrav 98ce3adf43SDag-Erling Smørgravif [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then 99ce3adf43SDag-Erling Smørgrav GET_ID="ssh-add -L" 100ce3adf43SDag-Erling Smørgravfi 101ce3adf43SDag-Erling Smørgrav 102ce3adf43SDag-Erling Smørgravwhile test "$#" -gt 0 103ce3adf43SDag-Erling Smørgravdo 104ce3adf43SDag-Erling Smørgrav [ "${SEEN_OPT_I}" ] && expr "$1" : "[-]i" >/dev/null && { 105ce3adf43SDag-Erling Smørgrav printf "\n%s: ERROR: -i option must not be specified more than once\n\n" "$0" 106ce3adf43SDag-Erling Smørgrav usage 107ce3adf43SDag-Erling Smørgrav } 108ce3adf43SDag-Erling Smørgrav 109ce3adf43SDag-Erling Smørgrav OPT= OPTARG= 110ce3adf43SDag-Erling Smørgrav # implement something like getopt to avoid Solaris pain 111ce3adf43SDag-Erling Smørgrav case "$1" in 112ce3adf43SDag-Erling Smørgrav -i?*|-o?*|-p?*) 113ce3adf43SDag-Erling Smørgrav OPT="$(printf -- "$1"|cut -c1-2)" 114ce3adf43SDag-Erling Smørgrav OPTARG="$(printf -- "$1"|cut -c3-)" 115ce3adf43SDag-Erling Smørgrav shift 116ce3adf43SDag-Erling Smørgrav ;; 117ce3adf43SDag-Erling Smørgrav -o|-p) 118ce3adf43SDag-Erling Smørgrav OPT="$1" 119ce3adf43SDag-Erling Smørgrav OPTARG="$2" 120ce3adf43SDag-Erling Smørgrav shift 2 121ce3adf43SDag-Erling Smørgrav ;; 122ce3adf43SDag-Erling Smørgrav -i) 123ce3adf43SDag-Erling Smørgrav OPT="$1" 124ce3adf43SDag-Erling Smørgrav test "$#" -le 2 || expr "$2" : "[-]" >/dev/null || { 125ce3adf43SDag-Erling Smørgrav OPTARG="$2" 126ce3adf43SDag-Erling Smørgrav shift 127ce3adf43SDag-Erling Smørgrav } 128ce3adf43SDag-Erling Smørgrav shift 129ce3adf43SDag-Erling Smørgrav ;; 130acc1a9efSDag-Erling Smørgrav -f|-n|-h|-\?) 131ce3adf43SDag-Erling Smørgrav OPT="$1" 132ce3adf43SDag-Erling Smørgrav OPTARG= 133ce3adf43SDag-Erling Smørgrav shift 134ce3adf43SDag-Erling Smørgrav ;; 135ce3adf43SDag-Erling Smørgrav --) 136ce3adf43SDag-Erling Smørgrav shift 137ce3adf43SDag-Erling Smørgrav while test "$#" -gt 0 138ce3adf43SDag-Erling Smørgrav do 139ce3adf43SDag-Erling Smørgrav SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'" 140ce3adf43SDag-Erling Smørgrav shift 141ce3adf43SDag-Erling Smørgrav done 142ce3adf43SDag-Erling Smørgrav break 143ce3adf43SDag-Erling Smørgrav ;; 144ce3adf43SDag-Erling Smørgrav -*) 145ce3adf43SDag-Erling Smørgrav printf "\n%s: ERROR: invalid option (%s)\n\n" "$0" "$1" 146ce3adf43SDag-Erling Smørgrav usage 147ce3adf43SDag-Erling Smørgrav ;; 148ce3adf43SDag-Erling Smørgrav *) 149ce3adf43SDag-Erling Smørgrav SAVEARGS="${SAVEARGS:+$SAVEARGS }'$(quote "$1")'" 150ce3adf43SDag-Erling Smørgrav shift 151ce3adf43SDag-Erling Smørgrav continue 152ce3adf43SDag-Erling Smørgrav ;; 153ce3adf43SDag-Erling Smørgrav esac 154ce3adf43SDag-Erling Smørgrav 155ce3adf43SDag-Erling Smørgrav case "$OPT" in 156ce3adf43SDag-Erling Smørgrav -i) 157ce3adf43SDag-Erling Smørgrav SEEN_OPT_I="yes" 158ce3adf43SDag-Erling Smørgrav use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}" 159ce3adf43SDag-Erling Smørgrav ;; 160ce3adf43SDag-Erling Smørgrav -o|-p) 161ce3adf43SDag-Erling Smørgrav SSH_OPTS="${SSH_OPTS:+$SSH_OPTS }$OPT '$(quote "$OPTARG")'" 162ce3adf43SDag-Erling Smørgrav ;; 163acc1a9efSDag-Erling Smørgrav -f) 164acc1a9efSDag-Erling Smørgrav FORCED=1 165acc1a9efSDag-Erling Smørgrav ;; 166ce3adf43SDag-Erling Smørgrav -n) 167ce3adf43SDag-Erling Smørgrav DRY_RUN=1 168ce3adf43SDag-Erling Smørgrav ;; 169ce3adf43SDag-Erling Smørgrav -h|-\?) 170ce3adf43SDag-Erling Smørgrav usage 171ce3adf43SDag-Erling Smørgrav ;; 172ce3adf43SDag-Erling Smørgrav esac 173ce3adf43SDag-Erling Smørgravdone 174ce3adf43SDag-Erling Smørgrav 175ce3adf43SDag-Erling Smørgraveval set -- "$SAVEARGS" 176ce3adf43SDag-Erling Smørgrav 177ce3adf43SDag-Erling Smørgravif [ $# = 0 ] ; then 178ce3adf43SDag-Erling Smørgrav usage 179ce3adf43SDag-Erling Smørgravfi 180ce3adf43SDag-Erling Smørgravif [ $# != 1 ] ; then 181ce3adf43SDag-Erling Smørgrav printf '%s: ERROR: Too many arguments. Expecting a target hostname, got: %s\n\n' "$0" "$SAVEARGS" >&2 182ce3adf43SDag-Erling Smørgrav usage 183ce3adf43SDag-Erling Smørgravfi 184ce3adf43SDag-Erling Smørgrav 185ce3adf43SDag-Erling Smørgrav# drop trailing colon 186ce3adf43SDag-Erling SmørgravUSER_HOST=$(printf "%s\n" "$1" | sed 's/:$//') 187ce3adf43SDag-Erling Smørgrav# tack the hostname onto SSH_OPTS 188ce3adf43SDag-Erling SmørgravSSH_OPTS="${SSH_OPTS:+$SSH_OPTS }'$(quote "$USER_HOST")'" 189ce3adf43SDag-Erling Smørgrav# and populate "$@" for later use (only way to get proper quoting of options) 190ce3adf43SDag-Erling Smørgraveval set -- "$SSH_OPTS" 191ce3adf43SDag-Erling Smørgrav 192ce3adf43SDag-Erling Smørgravif [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then 193ce3adf43SDag-Erling Smørgrav use_id_file "$PUB_ID_FILE" 194ce3adf43SDag-Erling Smørgravfi 195ce3adf43SDag-Erling Smørgrav 196ce3adf43SDag-Erling Smørgravif [ -z "$(eval $GET_ID)" ] ; then 197ce3adf43SDag-Erling Smørgrav printf '%s: ERROR: No identities found\n' "$0" >&2 198ce3adf43SDag-Erling Smørgrav exit 1 199ce3adf43SDag-Erling Smørgravfi 200ce3adf43SDag-Erling Smørgrav 201ce3adf43SDag-Erling Smørgrav# populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...) 202ce3adf43SDag-Erling Smørgrav# and has the side effect of setting $NEW_IDS 203ce3adf43SDag-Erling Smørgravpopulate_new_ids() { 204ce3adf43SDag-Erling Smørgrav local L_SUCCESS="$1" 205ce3adf43SDag-Erling Smørgrav 206acc1a9efSDag-Erling Smørgrav if [ "$FORCED" ] ; then 207acc1a9efSDag-Erling Smørgrav NEW_IDS=$(eval $GET_ID) 208acc1a9efSDag-Erling Smørgrav return 209acc1a9efSDag-Erling Smørgrav fi 210acc1a9efSDag-Erling Smørgrav 211ce3adf43SDag-Erling Smørgrav # repopulate "$@" inside this function 212ce3adf43SDag-Erling Smørgrav eval set -- "$SSH_OPTS" 213ce3adf43SDag-Erling Smørgrav 214ce3adf43SDag-Erling Smørgrav umask 0177 215ce3adf43SDag-Erling Smørgrav local L_TMP_ID_FILE=$(mktemp ~/.ssh/ssh-copy-id_id.XXXXXXXXXX) 216ce3adf43SDag-Erling Smørgrav if test $? -ne 0 || test "x$L_TMP_ID_FILE" = "x" ; then 217acc1a9efSDag-Erling Smørgrav printf '%s: ERROR: mktemp failed\n' "$0" >&2 218ce3adf43SDag-Erling Smørgrav exit 1 219ce3adf43SDag-Erling Smørgrav fi 220acc1a9efSDag-Erling Smørgrav local L_CLEANUP="rm -f \"$L_TMP_ID_FILE\" \"${L_TMP_ID_FILE}.stderr\"" 221acc1a9efSDag-Erling Smørgrav trap "$L_CLEANUP" EXIT TERM INT QUIT 222ce3adf43SDag-Erling Smørgrav printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2 223ce3adf43SDag-Erling Smørgrav NEW_IDS=$( 224ce3adf43SDag-Erling Smørgrav eval $GET_ID | { 225acc1a9efSDag-Erling Smørgrav while read ID || [ "$ID" ] ; do 226acc1a9efSDag-Erling Smørgrav printf '%s\n' "$ID" > "$L_TMP_ID_FILE" 227ce3adf43SDag-Erling Smørgrav 228ce3adf43SDag-Erling Smørgrav # the next line assumes $PRIV_ID_FILE only set if using a single id file - this 229ce3adf43SDag-Erling Smørgrav # assumption will break if we implement the possibility of multiple -i options. 230ce3adf43SDag-Erling Smørgrav # The point being that if file based, ssh needs the private key, which it cannot 231ce3adf43SDag-Erling Smørgrav # find if only given the contents of the .pub file in an unrelated tmpfile 232ce3adf43SDag-Erling Smørgrav ssh -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ 233acc1a9efSDag-Erling Smørgrav -o ControlPath=none \ 234acc1a9efSDag-Erling Smørgrav -o LogLevel=INFO \ 235ce3adf43SDag-Erling Smørgrav -o PreferredAuthentications=publickey \ 236*076ad2f8SDag-Erling Smørgrav -o IdentitiesOnly=yes "$@" exit 2>"$L_TMP_ID_FILE.stderr" </dev/null 237ce3adf43SDag-Erling Smørgrav if [ "$?" = "$L_SUCCESS" ] ; then 238*076ad2f8SDag-Erling Smørgrav : > "$L_TMP_ID_FILE" 239ce3adf43SDag-Erling Smørgrav else 240*076ad2f8SDag-Erling Smørgrav grep 'Permission denied' "$L_TMP_ID_FILE.stderr" >/dev/null || { 241*076ad2f8SDag-Erling Smørgrav sed -e 's/^/ERROR: /' <"$L_TMP_ID_FILE.stderr" >"$L_TMP_ID_FILE" 242ce3adf43SDag-Erling Smørgrav cat >/dev/null #consume the other keys, causing loop to end 243ce3adf43SDag-Erling Smørgrav } 244ce3adf43SDag-Erling Smørgrav fi 245ce3adf43SDag-Erling Smørgrav 246*076ad2f8SDag-Erling Smørgrav cat "$L_TMP_ID_FILE" 247ce3adf43SDag-Erling Smørgrav done 248ce3adf43SDag-Erling Smørgrav } 249ce3adf43SDag-Erling Smørgrav ) 250acc1a9efSDag-Erling Smørgrav eval "$L_CLEANUP" && trap - EXIT TERM INT QUIT 251ce3adf43SDag-Erling Smørgrav 252ce3adf43SDag-Erling Smørgrav if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then 253ce3adf43SDag-Erling Smørgrav printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2 254ce3adf43SDag-Erling Smørgrav exit 1 255ce3adf43SDag-Erling Smørgrav fi 256ce3adf43SDag-Erling Smørgrav if [ -z "$NEW_IDS" ] ; then 257acc1a9efSDag-Erling Smørgrav printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2 258acc1a9efSDag-Erling Smørgrav printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' "$0" >&2 259ce3adf43SDag-Erling Smørgrav exit 0 260ce3adf43SDag-Erling Smørgrav fi 261ce3adf43SDag-Erling Smørgrav 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 262ce3adf43SDag-Erling Smørgrav} 263ce3adf43SDag-Erling Smørgrav 264acc1a9efSDag-Erling SmørgravREMOTE_VERSION=$(ssh -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 | 265ce3adf43SDag-Erling Smørgrav sed -ne 's/.*remote software version //p') 266ce3adf43SDag-Erling Smørgrav 267ce3adf43SDag-Erling Smørgravcase "$REMOTE_VERSION" in 268ce3adf43SDag-Erling Smørgrav NetScreen*) 269ce3adf43SDag-Erling Smørgrav populate_new_ids 1 270ce3adf43SDag-Erling Smørgrav for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do 271ce3adf43SDag-Erling Smørgrav KEY_NO=$(($KEY_NO + 1)) 272ce3adf43SDag-Erling Smørgrav printf "%s\n" "$KEY" | grep ssh-dss >/dev/null || { 273ce3adf43SDag-Erling Smørgrav printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2 274ce3adf43SDag-Erling Smørgrav continue 275ce3adf43SDag-Erling Smørgrav } 276ce3adf43SDag-Erling Smørgrav [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | ssh -T "$@" >/dev/null 2>&1 277ce3adf43SDag-Erling Smørgrav if [ $? = 255 ] ; then 278ce3adf43SDag-Erling Smørgrav 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 279ce3adf43SDag-Erling Smørgrav else 280ce3adf43SDag-Erling Smørgrav ADDED=$(($ADDED + 1)) 281ce3adf43SDag-Erling Smørgrav fi 282ce3adf43SDag-Erling Smørgrav done 283ce3adf43SDag-Erling Smørgrav if [ -z "$ADDED" ] ; then 284ce3adf43SDag-Erling Smørgrav exit 1 285ce3adf43SDag-Erling Smørgrav fi 286ce3adf43SDag-Erling Smørgrav ;; 287ce3adf43SDag-Erling Smørgrav *) 288ce3adf43SDag-Erling Smørgrav # Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect 289ce3adf43SDag-Erling Smørgrav populate_new_ids 0 290acc1a9efSDag-Erling Smørgrav # in ssh below - to defend against quirky remote shells: use 'exec sh -c' to get POSIX; 'cd' to be at $HOME; and all on one line, because tcsh. 291acc1a9efSDag-Erling Smørgrav [ "$DRY_RUN" ] || printf '%s\n' "$NEW_IDS" | \ 292acc1a9efSDag-Erling Smørgrav ssh "$@" "exec sh -c 'cd ; umask 077 ; mkdir -p .ssh && cat >> .ssh/authorized_keys || exit 1 ; if type restorecon >/dev/null 2>&1 ; then restorecon -F .ssh .ssh/authorized_keys ; fi'" \ 293ce3adf43SDag-Erling Smørgrav || exit 1 294ce3adf43SDag-Erling Smørgrav ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) 295ce3adf43SDag-Erling Smørgrav ;; 296ce3adf43SDag-Erling Smørgravesac 297ce3adf43SDag-Erling Smørgrav 298ce3adf43SDag-Erling Smørgravif [ "$DRY_RUN" ] ; then 299ce3adf43SDag-Erling Smørgrav cat <<-EOF 300ce3adf43SDag-Erling Smørgrav =-=-=-=-=-=-=-= 301ce3adf43SDag-Erling Smørgrav Would have added the following key(s): 302ce3adf43SDag-Erling Smørgrav 303ce3adf43SDag-Erling Smørgrav $NEW_IDS 304ce3adf43SDag-Erling Smørgrav =-=-=-=-=-=-=-= 305ce3adf43SDag-Erling Smørgrav EOF 306ce3adf43SDag-Erling Smørgravelse 307ce3adf43SDag-Erling Smørgrav cat <<-EOF 308ce3adf43SDag-Erling Smørgrav 309ce3adf43SDag-Erling Smørgrav Number of key(s) added: $ADDED 310ce3adf43SDag-Erling Smørgrav 311ce3adf43SDag-Erling Smørgrav Now try logging into the machine, with: "ssh $SSH_OPTS" 312ce3adf43SDag-Erling Smørgrav and check to make sure that only the key(s) you wanted were added. 313ce3adf43SDag-Erling Smørgrav 314ce3adf43SDag-Erling Smørgrav EOF 315ce3adf43SDag-Erling Smørgravfi 316ce3adf43SDag-Erling Smørgrav 317ce3adf43SDag-Erling Smørgrav# =-=-=-= 318