add -t option to specify the target path

Allow the default target path (.ssh/authorized_files) to be over-riden

This was inspired by this MR from Panagiotis Cheilaris <philaris@cs.ntua.gr>

 https://gitlab.com/phil_hands/ssh-copy-id/-/merge_requests/8

SSH-Copy-ID-Upstream: a942a0e076874adb6d8b2f0fb76d6c7918190fcd
This commit is contained in:
Philip Hands 2023-05-23 16:46:42 +02:00 committed by Darren Tucker
parent 914f4ad138
commit b79e7b88ed
No known key found for this signature in database
2 changed files with 26 additions and 20 deletions

View File

@ -64,10 +64,11 @@ fi
# shellcheck disable=SC2010 # shellcheck disable=SC2010
DEFAULT_PUB_ID_FILE=$(ls -t "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1) DEFAULT_PUB_ID_FILE=$(ls -t "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1)
SSH="ssh -a -x" SSH="ssh -a -x"
TARGET_PATH=".ssh/authorized_keys"
umask 0177 umask 0177
usage () { usage () {
printf 'Usage: %s [-h|-?|-f|-n|-s|-x] [-i [identity_file]] [-p port] [-F alternative ssh_config file] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2 printf 'Usage: %s [-h|-?|-f|-n|-s|-x] [-i [identity_file]] [-p port] [-F alternative ssh_config file] [-t target_path] [[-o <ssh -o options>] ...] [user@]hostname\n' "$0" >&2
printf '\t-f: force mode -- copy keys without trying to check if they are already installed\n' >&2 printf '\t-f: force mode -- copy keys without trying to check if they are already installed\n' >&2
printf '\t-n: dry run -- no keys are actually copied\n' >&2 printf '\t-n: dry run -- no keys are actually copied\n' >&2
printf '\t-s: use sftp -- use sftp instead of executing remote-commands. Can be useful if the remote only allows sftp\n' >&2 printf '\t-s: use sftp -- use sftp instead of executing remote-commands. Can be useful if the remote only allows sftp\n' >&2
@ -114,7 +115,7 @@ if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then
GET_ID="ssh-add -L" GET_ID="ssh-add -L"
fi fi
while getopts "i:o:p:F:fnsxh?" OPT while getopts "i:o:p:F:t:fnsxh?" OPT
do do
case "$OPT" in case "$OPT" in
i) i)
@ -137,6 +138,9 @@ do
s) s)
SFTP=sftp SFTP=sftp
;; ;;
t)
TARGET_PATH="${OPTARG}"
;;
x) x)
set -x set -x
;; ;;
@ -238,11 +242,8 @@ populate_new_ids() {
} }
# installkey_sh [target_path] # installkey_sh [target_path]
# produce a one-liner to add the keys to remote authorized_keys file # produce a one-liner to add the keys to remote $TARGET_PATH
# optionally takes an alternative path for authorized_keys
installkeys_sh() { installkeys_sh() {
AUTH_KEY_FILE=${1:-.ssh/authorized_keys}
# In setting INSTALLKEYS_SH: # In setting INSTALLKEYS_SH:
# the tr puts it all on one line (to placate tcsh) # the tr puts it all on one line (to placate tcsh)
# (hence the excessive use of semi-colons (;) ) # (hence the excessive use of semi-colons (;) )
@ -255,7 +256,7 @@ installkeys_sh() {
INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF
cd; cd;
umask 077; umask 077;
AUTH_KEY_FILE="${AUTH_KEY_FILE}"; AUTH_KEY_FILE="${TARGET_PATH}";
[ -f /etc/openwrt_release ] && [ "\$LOGNAME" = "root" ] && [ -f /etc/openwrt_release ] && [ "\$LOGNAME" = "root" ] &&
AUTH_KEY_FILE=/etc/dropbear/authorized_keys; AUTH_KEY_FILE=/etc/dropbear/authorized_keys;
AUTH_KEY_DIR=\`dirname "\${AUTH_KEY_FILE}"\`; AUTH_KEY_DIR=\`dirname "\${AUTH_KEY_FILE}"\`;
@ -275,6 +276,8 @@ installkeys_sh() {
#shellcheck disable=SC2120 # the 'eval set' confuses this #shellcheck disable=SC2120 # the 'eval set' confuses this
installkeys_via_sftp() { installkeys_via_sftp() {
AUTH_KEY_FILE=${TARGET_PATH}
AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}")
# repopulate "$@" inside this function # repopulate "$@" inside this function
eval set -- "$SSH_OPTS" eval set -- "$SSH_OPTS"
@ -286,17 +289,17 @@ installkeys_via_sftp() {
#shellcheck disable=SC2064 #shellcheck disable=SC2064
trap "$L_CLEANUP" EXIT TERM INT QUIT trap "$L_CLEANUP" EXIT TERM INT QUIT
sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1 sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1
-get .ssh/authorized_keys $L_KEYS -get "$AUTH_KEY_FILE" "$L_KEYS"
EOF EOF
# add a newline or create file if it's missing, same like above # add a newline or create file if it's missing, same like above
[ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS" [ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS"
# append the keys being piped in here # append the keys being piped in here
cat >> "$L_KEYS" cat >> "$L_KEYS"
sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1 sftp -b - -o "ControlPath=$L_SHARED_CON" "ignored" <<-EOF || return 1
-mkdir .ssh -mkdir "$AUTH_KEY_DIR"
chmod 700 .ssh chmod 700 "$AUTH_KEY_DIR"
put $L_KEYS .ssh/authorized_keys put $L_KEYS "$AUTH_KEY_FILE"
chmod 600 .ssh/authorized_keys chmod 600 "$AUTH_KEY_FILE"
EOF EOF
#shellcheck disable=SC2064 #shellcheck disable=SC2064
eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT
@ -341,7 +344,7 @@ case "$REMOTE_VERSION" in
fi fi
;; ;;
*) *)
# Assuming that the remote host treats ~/.ssh/authorized_keys as one might expect # Assuming that the remote host treats $TARGET_PATH as one might expect
populate_new_ids 0 populate_new_ids 0
if ! [ "$DRY_RUN" ] ; then if ! [ "$DRY_RUN" ] ; then
printf '%s\n' "$NEW_IDS" | \ printf '%s\n' "$NEW_IDS" | \

View File

@ -36,6 +36,7 @@ THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
.Op Fl i Op Ar identity_file .Op Fl i Op Ar identity_file
.Op Fl p Ar port .Op Fl p Ar port
.Op Fl o Ar ssh_option .Op Fl o Ar ssh_option
.Op Fl t Ar target_path
.Op Ar user Ns @ Ns .Op Ar user Ns @ Ns
.Ar hostname .Ar hostname
.Nm .Nm
@ -92,13 +93,8 @@ With this option the user's
.Pa ~/.ssh/authorized_keys .Pa ~/.ssh/authorized_keys
file will be downloaded, modified locally and uploaded with sftp. file will be downloaded, modified locally and uploaded with sftp.
This option is useful if the server has restrictions on commands which can be used on the remote side. This option is useful if the server has restrictions on commands which can be used on the remote side.
.It Fl x .It Fl t Ar target_path
This option is for debugging the the path on the target system where the keys should be added (defaults to ".ssh/authorized_keys")
.Nm
script itself.
It sets the shell's -x flag, so that you can see the commands being run.
.It Fl h , Fl ?
Print Usage summary
.It Fl p Ar port , Fl o Ar ssh_option .It Fl p Ar port , Fl o Ar ssh_option
These two options are simply passed through untouched, along with their These two options are simply passed through untouched, along with their
argument, to allow one to set the port or other argument, to allow one to set the port or other
@ -109,6 +105,13 @@ Rather than specifying these as command line options, it is often better to use
.Xr ssh 1 Ns 's .Xr ssh 1 Ns 's
configuration file: configuration file:
.Xr ssh_config 5 . .Xr ssh_config 5 .
.It Fl x
This option is for debugging the
.Nm
script itself.
It sets the shell's -x flag, so that you can see the commands being run.
.It Fl h , Fl ?
Print Usage summary
.El .El
.Pp .Pp
Default behaviour without Default behaviour without