π£ Reyna v4
Path:
/
/
usr
/
bin
Full Path (server): /usr/bin
Create Folder
Create File
Upload File
Create WP Admin
π GET
[E]
[D]
[R]
π Mail
[E]
[D]
[R]
π [
[E]
[D]
[R]
π aclocal
[E]
[D]
[R]
π aclocal-1.16
[E]
[D]
[R]
π addr2line
[E]
[D]
[R]
π agentxtrap
[E]
[D]
[R]
π animate
[E]
[D]
[R]
π ar
[E]
[D]
[R]
π arch
[E]
[D]
[R]
π arpaname
[E]
[D]
[R]
π as
[E]
[D]
[R]
π aspell
[E]
[D]
[R]
π at
[E]
[D]
[R]
π atq
[E]
[D]
[R]
π atrm
[E]
[D]
[R]
π autoconf
[E]
[D]
[R]
π autoheader
[E]
[D]
[R]
π autom4te
[E]
[D]
[R]
π automake
[E]
[D]
[R]
π automake-1.16
[E]
[D]
[R]
π autoreconf
[E]
[D]
[R]
π autoscan
[E]
[D]
[R]
π autoupdate
[E]
[D]
[R]
π awk
[E]
[D]
[R]
π b2sum
[E]
[D]
[R]
π base32
[E]
[D]
[R]
π base64
[E]
[D]
[R]
π basename
[E]
[D]
[R]
π basenc
[E]
[D]
[R]
π bash
[E]
[D]
[R]
π bashbug-64
[E]
[D]
[R]
π batch
[E]
[D]
[R]
π bison
[E]
[D]
[R]
π brotli
[E]
[D]
[R]
π bunzip2
[E]
[D]
[R]
π bzcat
[E]
[D]
[R]
π bzcmp
[E]
[D]
[R]
π bzdiff
[E]
[D]
[R]
π bzgrep
[E]
[D]
[R]
π bzip2
[E]
[D]
[R]
π bzip2recover
[E]
[D]
[R]
π bzless
[E]
[D]
[R]
π bzmore
[E]
[D]
[R]
π c++
[E]
[D]
[R]
π c++filt
[E]
[D]
[R]
π c89
[E]
[D]
[R]
π c99
[E]
[D]
[R]
π cagefs_enter.proxied
[E]
[D]
[R]
π cal
[E]
[D]
[R]
π captoinfo
[E]
[D]
[R]
π cat
[E]
[D]
[R]
π catchsegv
[E]
[D]
[R]
π cc
[E]
[D]
[R]
π chcon
[E]
[D]
[R]
π chgrp
[E]
[D]
[R]
π chmod
[E]
[D]
[R]
π chown
[E]
[D]
[R]
π chrt
[E]
[D]
[R]
π cksum
[E]
[D]
[R]
π cldetect
[E]
[D]
[R]
π clear
[E]
[D]
[R]
π clusterdb
[E]
[D]
[R]
π cmp
[E]
[D]
[R]
π col
[E]
[D]
[R]
π colcrt
[E]
[D]
[R]
π colrm
[E]
[D]
[R]
π column
[E]
[D]
[R]
π comm
[E]
[D]
[R]
π compare
[E]
[D]
[R]
π composite
[E]
[D]
[R]
π conjure
[E]
[D]
[R]
π convert
[E]
[D]
[R]
π cp
[E]
[D]
[R]
π cpan
[E]
[D]
[R]
π cpp
[E]
[D]
[R]
π createdb
[E]
[D]
[R]
π createuser
[E]
[D]
[R]
π crontab
[E]
[D]
[R]
π crontab.cagefs
[E]
[D]
[R]
π csplit
[E]
[D]
[R]
π curl
[E]
[D]
[R]
π cut
[E]
[D]
[R]
π cyrusbdb2current
[E]
[D]
[R]
π date
[E]
[D]
[R]
π dbiprof
[E]
[D]
[R]
π dd
[E]
[D]
[R]
π delv
[E]
[D]
[R]
π df
[E]
[D]
[R]
π diff
[E]
[D]
[R]
π diff3
[E]
[D]
[R]
π dig
[E]
[D]
[R]
π dir
[E]
[D]
[R]
π dircolors
[E]
[D]
[R]
π dirname
[E]
[D]
[R]
π display
[E]
[D]
[R]
π dnstap-read
[E]
[D]
[R]
π dropdb
[E]
[D]
[R]
π dropuser
[E]
[D]
[R]
π du
[E]
[D]
[R]
π echo
[E]
[D]
[R]
π ed
[E]
[D]
[R]
π egrep
[E]
[D]
[R]
π enc2xs
[E]
[D]
[R]
π enchant
[E]
[D]
[R]
π enchant-lsmod
[E]
[D]
[R]
π env
[E]
[D]
[R]
π eps2eps
[E]
[D]
[R]
π eqn
[E]
[D]
[R]
π ex
[E]
[D]
[R]
π expand
[E]
[D]
[R]
π expr
[E]
[D]
[R]
π factor
[E]
[D]
[R]
π false
[E]
[D]
[R]
π fc-cache
[E]
[D]
[R]
π fc-cache-64
[E]
[D]
[R]
π fc-cat
[E]
[D]
[R]
π fc-conflist
[E]
[D]
[R]
π fc-list
[E]
[D]
[R]
π fc-match
[E]
[D]
[R]
π fc-pattern
[E]
[D]
[R]
π fc-query
[E]
[D]
[R]
π fc-scan
[E]
[D]
[R]
π fc-validate
[E]
[D]
[R]
π ffmpeg
[E]
[D]
[R]
π ffplay
[E]
[D]
[R]
π ffprobe
[E]
[D]
[R]
π fgrep
[E]
[D]
[R]
π file
[E]
[D]
[R]
π find
[E]
[D]
[R]
π flex
[E]
[D]
[R]
π flex++
[E]
[D]
[R]
π flock
[E]
[D]
[R]
π fmt
[E]
[D]
[R]
π fold
[E]
[D]
[R]
π free
[E]
[D]
[R]
π freetype-config
[E]
[D]
[R]
π funzip
[E]
[D]
[R]
π g++
[E]
[D]
[R]
π gawk
[E]
[D]
[R]
π gcc
[E]
[D]
[R]
π gcc-ar
[E]
[D]
[R]
π gcc-nm
[E]
[D]
[R]
π gcc-ranlib
[E]
[D]
[R]
π gcov
[E]
[D]
[R]
π gcov-dump
[E]
[D]
[R]
π gcov-tool
[E]
[D]
[R]
π gem
[E]
[D]
[R]
π gencat
[E]
[D]
[R]
π geoiplookup
[E]
[D]
[R]
π geoiplookup6
[E]
[D]
[R]
π geqn
[E]
[D]
[R]
π getconf
[E]
[D]
[R]
π getent
[E]
[D]
[R]
π getopt
[E]
[D]
[R]
π ghostscript
[E]
[D]
[R]
π git
[E]
[D]
[R]
π git-receive-pack
[E]
[D]
[R]
π git-shell
[E]
[D]
[R]
π git-upload-archive
[E]
[D]
[R]
π git-upload-pack
[E]
[D]
[R]
π gm
[E]
[D]
[R]
π gmake
[E]
[D]
[R]
π gneqn
[E]
[D]
[R]
π gnroff
[E]
[D]
[R]
π gpg
[E]
[D]
[R]
π gpg-agent
[E]
[D]
[R]
π gpg-error
[E]
[D]
[R]
π gpgsplit
[E]
[D]
[R]
π gpgv
[E]
[D]
[R]
π gpic
[E]
[D]
[R]
π gprof
[E]
[D]
[R]
π grep
[E]
[D]
[R]
π groff
[E]
[D]
[R]
π grops
[E]
[D]
[R]
π grotty
[E]
[D]
[R]
π groups
[E]
[D]
[R]
π gs
[E]
[D]
[R]
π gsnd
[E]
[D]
[R]
π gsoelim
[E]
[D]
[R]
π gtar
[E]
[D]
[R]
π gtbl
[E]
[D]
[R]
π gtroff
[E]
[D]
[R]
π gunzip
[E]
[D]
[R]
π gzexe
[E]
[D]
[R]
π gzip
[E]
[D]
[R]
π h2ph
[E]
[D]
[R]
π h2xs
[E]
[D]
[R]
π head
[E]
[D]
[R]
π hexdump
[E]
[D]
[R]
π host
[E]
[D]
[R]
π hostid
[E]
[D]
[R]
π hostname
[E]
[D]
[R]
π hunspell
[E]
[D]
[R]
π iconv
[E]
[D]
[R]
π icu-config
[E]
[D]
[R]
π icu-config-64
[E]
[D]
[R]
π icuinfo
[E]
[D]
[R]
π id
[E]
[D]
[R]
π identify
[E]
[D]
[R]
π idn
[E]
[D]
[R]
π ifnames
[E]
[D]
[R]
π import
[E]
[D]
[R]
π infocmp
[E]
[D]
[R]
π infotocap
[E]
[D]
[R]
π install
[E]
[D]
[R]
π instmodsh
[E]
[D]
[R]
π ionice
[E]
[D]
[R]
π ipcrm
[E]
[D]
[R]
π ipcs
[E]
[D]
[R]
π isosize
[E]
[D]
[R]
π ispell
[E]
[D]
[R]
π join
[E]
[D]
[R]
π jq
[E]
[D]
[R]
π kill
[E]
[D]
[R]
π ld
[E]
[D]
[R]
π ld.bfd
[E]
[D]
[R]
π ldd
[E]
[D]
[R]
π less
[E]
[D]
[R]
π lessecho
[E]
[D]
[R]
π lesskey
[E]
[D]
[R]
π lesspipe.sh
[E]
[D]
[R]
π lex
[E]
[D]
[R]
π libnetcfg
[E]
[D]
[R]
π libtool
[E]
[D]
[R]
π libtoolize
[E]
[D]
[R]
π link
[E]
[D]
[R]
π ln
[E]
[D]
[R]
π locale
[E]
[D]
[R]
π localedef
[E]
[D]
[R]
π logger
[E]
[D]
[R]
π login
[E]
[D]
[R]
π logname
[E]
[D]
[R]
π look
[E]
[D]
[R]
π ls
[E]
[D]
[R]
π lto-dump
[E]
[D]
[R]
π m4
[E]
[D]
[R]
π mail
[E]
[D]
[R]
π mailx
[E]
[D]
[R]
π mailx.s-nail
[E]
[D]
[R]
π make
[E]
[D]
[R]
π make-dummy-cert
[E]
[D]
[R]
π mariadb
[E]
[D]
[R]
π mariadb-access
[E]
[D]
[R]
π mariadb-admin
[E]
[D]
[R]
π mariadb-binlog
[E]
[D]
[R]
π mariadb-check
[E]
[D]
[R]
π mariadb-conv
[E]
[D]
[R]
π mariadb-convert-table-format
[E]
[D]
[R]
π mariadb-dump
[E]
[D]
[R]
π mariadb-dumpslow
[E]
[D]
[R]
π mariadb-embedded
[E]
[D]
[R]
π mariadb-find-rows
[E]
[D]
[R]
π mariadb-hotcopy
[E]
[D]
[R]
π mariadb-import
[E]
[D]
[R]
π mariadb-plugin
[E]
[D]
[R]
π mariadb-secure-installation
[E]
[D]
[R]
π mariadb-setpermission
[E]
[D]
[R]
π mariadb-show
[E]
[D]
[R]
π mariadb-slap
[E]
[D]
[R]
π mariadb-tzinfo-to-sql
[E]
[D]
[R]
π mariadb-waitpid
[E]
[D]
[R]
π mcookie
[E]
[D]
[R]
π md5sum
[E]
[D]
[R]
π memcached
[E]
[D]
[R]
π memcached-tool
[E]
[D]
[R]
π mesg
[E]
[D]
[R]
π mkdir
[E]
[D]
[R]
π mkfifo
[E]
[D]
[R]
π mknod
[E]
[D]
[R]
π mktemp
[E]
[D]
[R]
π mogrify
[E]
[D]
[R]
π montage
[E]
[D]
[R]
π more
[E]
[D]
[R]
π msql2mysql
[E]
[D]
[R]
π mv
[E]
[D]
[R]
π my_print_defaults
[E]
[D]
[R]
π mysql
[E]
[D]
[R]
π mysql_config
[E]
[D]
[R]
π mysql_find_rows
[E]
[D]
[R]
π mysql_waitpid
[E]
[D]
[R]
π mysqlaccess
[E]
[D]
[R]
π mysqladmin
[E]
[D]
[R]
π mysqlbinlog
[E]
[D]
[R]
π mysqlcheck
[E]
[D]
[R]
π mysqldump
[E]
[D]
[R]
π mysqlimport
[E]
[D]
[R]
π mysqlshow
[E]
[D]
[R]
π mytop
[E]
[D]
[R]
π nail
[E]
[D]
[R]
π namei
[E]
[D]
[R]
π nano
[E]
[D]
[R]
π neqn
[E]
[D]
[R]
π net-snmp-create-v3-user
[E]
[D]
[R]
π nice
[E]
[D]
[R]
π nl
[E]
[D]
[R]
π nm
[E]
[D]
[R]
π nohup
[E]
[D]
[R]
π nproc
[E]
[D]
[R]
π nroff
[E]
[D]
[R]
π nslookup
[E]
[D]
[R]
π nsupdate
[E]
[D]
[R]
π numfmt
[E]
[D]
[R]
π objcopy
[E]
[D]
[R]
π objdump
[E]
[D]
[R]
π od
[E]
[D]
[R]
π openssl
[E]
[D]
[R]
π pango-list
[E]
[D]
[R]
π pango-segmentation
[E]
[D]
[R]
π pango-view
[E]
[D]
[R]
π passenger
[E]
[D]
[R]
π passwd
[E]
[D]
[R]
π paste
[E]
[D]
[R]
π patch
[E]
[D]
[R]
π pathchk
[E]
[D]
[R]
π pdf2dsc
[E]
[D]
[R]
π pdf2ps
[E]
[D]
[R]
π perl
[E]
[D]
[R]
π perl5.32.1
[E]
[D]
[R]
π perlbug
[E]
[D]
[R]
π perldoc
[E]
[D]
[R]
π perlivp
[E]
[D]
[R]
π perlml
[E]
[D]
[R]
π perlthanks
[E]
[D]
[R]
π pg_dump
[E]
[D]
[R]
π pg_dumpall
[E]
[D]
[R]
π pg_restore
[E]
[D]
[R]
π pgrep
[E]
[D]
[R]
π php
[E]
[D]
[R]
π pic
[E]
[D]
[R]
π piconv
[E]
[D]
[R]
π ping
[E]
[D]
[R]
π pinky
[E]
[D]
[R]
π pkg-config
[E]
[D]
[R]
π pkill
[E]
[D]
[R]
π pl2pm
[E]
[D]
[R]
π pmap
[E]
[D]
[R]
π pod2html
[E]
[D]
[R]
π pod2man
[E]
[D]
[R]
π pod2text
[E]
[D]
[R]
π pod2usage
[E]
[D]
[R]
π podchecker
[E]
[D]
[R]
π post-grohtml
[E]
[D]
[R]
π pr
[E]
[D]
[R]
π pre-grohtml
[E]
[D]
[R]
π precat
[E]
[D]
[R]
π preunzip
[E]
[D]
[R]
π prezip
[E]
[D]
[R]
π prezip-bin
[E]
[D]
[R]
π printenv
[E]
[D]
[R]
π printf
[E]
[D]
[R]
π prove
[E]
[D]
[R]
π ps
[E]
[D]
[R]
π ps2ascii
[E]
[D]
[R]
π ps2epsi
[E]
[D]
[R]
π ps2pdf
[E]
[D]
[R]
π ps2pdf12
[E]
[D]
[R]
π ps2pdf13
[E]
[D]
[R]
π ps2pdf14
[E]
[D]
[R]
π ps2pdfwr
[E]
[D]
[R]
π ps2ps
[E]
[D]
[R]
π ps2ps2
[E]
[D]
[R]
π psql
[E]
[D]
[R]
π ptx
[E]
[D]
[R]
π pwd
[E]
[D]
[R]
π pwdx
[E]
[D]
[R]
π pydoc
[E]
[D]
[R]
π pydoc3
[E]
[D]
[R]
π pydoc3.9
[E]
[D]
[R]
π python
[E]
[D]
[R]
π python3
[E]
[D]
[R]
π python3.9
[E]
[D]
[R]
π qt-faststart
[E]
[D]
[R]
π ranlib
[E]
[D]
[R]
π readelf
[E]
[D]
[R]
π readlink
[E]
[D]
[R]
π realpath
[E]
[D]
[R]
π recode
[E]
[D]
[R]
π red
[E]
[D]
[R]
π redis-benchmark
[E]
[D]
[R]
π redis-check-aof
[E]
[D]
[R]
π redis-check-rdb
[E]
[D]
[R]
π redis-cli
[E]
[D]
[R]
π redis-sentinel
[E]
[D]
[R]
π redis-server
[E]
[D]
[R]
π reindexdb
[E]
[D]
[R]
π rename
[E]
[D]
[R]
π renew-dummy-cert
[E]
[D]
[R]
π renice
[E]
[D]
[R]
π replace
[E]
[D]
[R]
π reset
[E]
[D]
[R]
π rev
[E]
[D]
[R]
π rm
[E]
[D]
[R]
π rmdir
[E]
[D]
[R]
π rnano
[E]
[D]
[R]
π rsync
[E]
[D]
[R]
π rsync-ssl
[E]
[D]
[R]
π ruby
[E]
[D]
[R]
π run-with-aspell
[E]
[D]
[R]
π runcon
[E]
[D]
[R]
π rvi
[E]
[D]
[R]
π rview
[E]
[D]
[R]
π rvim
[E]
[D]
[R]
π s-nail
[E]
[D]
[R]
π scalar
[E]
[D]
[R]
π scl
[E]
[D]
[R]
π scl_enabled
[E]
[D]
[R]
π scl_source
[E]
[D]
[R]
π scp
[E]
[D]
[R]
π screen
[E]
[D]
[R]
π script
[E]
[D]
[R]
π sdiff
[E]
[D]
[R]
π sed
[E]
[D]
[R]
π selectorctl
[E]
[D]
[R]
π seq
[E]
[D]
[R]
π setsid
[E]
[D]
[R]
π setterm
[E]
[D]
[R]
π sftp
[E]
[D]
[R]
π sh
[E]
[D]
[R]
π sha1sum
[E]
[D]
[R]
π sha224sum
[E]
[D]
[R]
π sha256sum
[E]
[D]
[R]
π sha384sum
[E]
[D]
[R]
π sha512sum
[E]
[D]
[R]
π shred
[E]
[D]
[R]
π shuf
[E]
[D]
[R]
π size
[E]
[D]
[R]
π skill
[E]
[D]
[R]
π slabtop
[E]
[D]
[R]
π sleep
[E]
[D]
[R]
π snice
[E]
[D]
[R]
π snmpconf
[E]
[D]
[R]
π soelim
[E]
[D]
[R]
π sort
[E]
[D]
[R]
π spell
[E]
[D]
[R]
π splain
[E]
[D]
[R]
π split
[E]
[D]
[R]
π sprof
[E]
[D]
[R]
π sqlite3
[E]
[D]
[R]
π ssh
[E]
[D]
[R]
π ssh-add
[E]
[D]
[R]
π ssh-agent
[E]
[D]
[R]
π ssh-copy-id
[E]
[D]
[R]
π ssh-keygen
[E]
[D]
[R]
π ssh-keyscan
[E]
[D]
[R]
π sss_ssh_knownhostsproxy
[E]
[D]
[R]
π stat
[E]
[D]
[R]
π stdbuf
[E]
[D]
[R]
π strace
[E]
[D]
[R]
π stream
[E]
[D]
[R]
π strings
[E]
[D]
[R]
π strip
[E]
[D]
[R]
π stty
[E]
[D]
[R]
π sum
[E]
[D]
[R]
π sync
[E]
[D]
[R]
π tabs
[E]
[D]
[R]
π tac
[E]
[D]
[R]
π tail
[E]
[D]
[R]
π tar
[E]
[D]
[R]
π taskset
[E]
[D]
[R]
π tbl
[E]
[D]
[R]
π tclsh
[E]
[D]
[R]
π tclsh8.6
[E]
[D]
[R]
π tee
[E]
[D]
[R]
π test
[E]
[D]
[R]
π tic
[E]
[D]
[R]
π timeout
[E]
[D]
[R]
π tload
[E]
[D]
[R]
π tmpwatch
[E]
[D]
[R]
π toe
[E]
[D]
[R]
π top
[E]
[D]
[R]
π touch
[E]
[D]
[R]
π tput
[E]
[D]
[R]
π tr
[E]
[D]
[R]
π tree
[E]
[D]
[R]
π troff
[E]
[D]
[R]
π true
[E]
[D]
[R]
π truncate
[E]
[D]
[R]
π tset
[E]
[D]
[R]
π tsort
[E]
[D]
[R]
π tty
[E]
[D]
[R]
π tzselect
[E]
[D]
[R]
π uapi
[E]
[D]
[R]
π ul
[E]
[D]
[R]
π uname
[E]
[D]
[R]
π unexpand
[E]
[D]
[R]
π uniq
[E]
[D]
[R]
π unlink
[E]
[D]
[R]
π unzip
[E]
[D]
[R]
π unzipsfx
[E]
[D]
[R]
π uptime
[E]
[D]
[R]
π users
[E]
[D]
[R]
π utmpdump
[E]
[D]
[R]
π vacuumdb
[E]
[D]
[R]
π vdir
[E]
[D]
[R]
π vi
[E]
[D]
[R]
π view
[E]
[D]
[R]
π vim
[E]
[D]
[R]
π vimdiff
[E]
[D]
[R]
π vimtutor
[E]
[D]
[R]
π vmstat
[E]
[D]
[R]
π watch
[E]
[D]
[R]
π wc
[E]
[D]
[R]
π wget
[E]
[D]
[R]
π whereis
[E]
[D]
[R]
π which
[E]
[D]
[R]
π who
[E]
[D]
[R]
π whoami
[E]
[D]
[R]
π word-list-compress
[E]
[D]
[R]
π x86_64-redhat-linux-c++
[E]
[D]
[R]
π x86_64-redhat-linux-g++
[E]
[D]
[R]
π x86_64-redhat-linux-gcc
[E]
[D]
[R]
π x86_64-redhat-linux-gcc-11
[E]
[D]
[R]
π xargs
[E]
[D]
[R]
π xmlcatalog
[E]
[D]
[R]
π xmllint
[E]
[D]
[R]
π xmlwf
[E]
[D]
[R]
π xsltproc
[E]
[D]
[R]
π xsubpp
[E]
[D]
[R]
π xxd
[E]
[D]
[R]
π yes
[E]
[D]
[R]
π zcat
[E]
[D]
[R]
π zcmp
[E]
[D]
[R]
π zdiff
[E]
[D]
[R]
π zegrep
[E]
[D]
[R]
π zfgrep
[E]
[D]
[R]
π zforce
[E]
[D]
[R]
π zgrep
[E]
[D]
[R]
π zip
[E]
[D]
[R]
π zipcloak
[E]
[D]
[R]
π zipgrep
[E]
[D]
[R]
π zipinfo
[E]
[D]
[R]
π zipnote
[E]
[D]
[R]
π zipsplit
[E]
[D]
[R]
π zless
[E]
[D]
[R]
π zmore
[E]
[D]
[R]
π znew
[E]
[D]
[R]
π zsoelim
[E]
[D]
[R]
Editing: ssh-copy-id
#!/usr/bin/sh # Copyright (c) 1999-2024 Philip Hands <phil@hands.com> # 2021 Carlos RodrΓguez Gili <carlos.rodriguez-gili@upc.edu> # 2020 Matthias BlΓΌmel <blaimi@blaimi.de> # 2017 Sebastien Boyron <seb@boyron.eu> # 2013 Martin Kletzander <mkletzan@redhat.com> # 2010 Adeodato =?iso-8859-1?Q?Sim=F3?= <asp16@alu.ua.es> # 2010 Eric Moret <eric.moret@gmail.com> # 2009 Xr <xr@i-jeuxvideo.com> # 2007 Justin Pryzby <justinpryzby@users.sourceforge.net> # 2004 Reini Urban <rurban@x-ray.at> # 2003 Colin Watson <cjwatson@debian.org> # All rights reserved. # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # 1. Redistributions of source code must retain the above copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the above copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. # Shell script to install your public key(s) on a remote machine # See the ssh-copy-id(1) man page for details # shellcheck shell=dash # check that we have something mildly sane as our shell, or try to find something better if false ^ printf "%s: WARNING: ancient shell, hunting for a more modern one... " "$0" then SANE_SH=${SANE_SH:-/usr/bin/ksh} if printf 'true ^ false\n' | "$SANE_SH" then printf "'%s' seems viable.\\n" "$SANE_SH" exec "$SANE_SH" "$0" "$@" else cat <<-EOF oh dear. If you have a more recent shell available, that supports \$(...) etc. please try setting the environment variable SANE_SH to the path of that shell, and then retry running this script. If that works, please report a bug describing your setup, and the shell you used to make it work. EOF printf '%s: ERROR: Less dimwitted shell required.\n' "$0" >&2 exit 1 fi fi # shellcheck disable=SC2010 DEFAULT_PUB_ID_FILE=$(ls -dt "${HOME}"/.ssh/id*.pub 2>/dev/null | grep -v -- '-cert.pub$' | head -n 1) SSH="ssh -a -x" TARGET_PATH=".ssh/authorized_keys" umask 0177 usage () { printf 'Usage: %s [-h|-?|-f|-n|-s|-x] [-i [identity_file]] [-t target_path] [-F ssh_config] [[-o ssh_option] ...] [-p port] [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-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-x: debug -- enables -x in this shell, for debugging\n' >&2 printf '\t-h|-?: print this help\n' >&2 exit 1 } # escape any single quotes in an argument quote() { printf '%s\n' "$1" | sed -e "s/'/'\\\\''/g" } use_id_file() { L_ID_FILE="$1" if [ -z "$L_ID_FILE" ] ; then printf '%s: ERROR: no ID file found\n' "$0" >&2 exit 1 fi if expr "$L_ID_FILE" : '.*\.pub$' >/dev/null ; then PUB_ID_FILE="$L_ID_FILE" else PUB_ID_FILE="$L_ID_FILE.pub" fi [ "$FORCED" ] || PRIV_ID_FILE=$(dirname "$PUB_ID_FILE")/$(basename "$PUB_ID_FILE" .pub) # check that the files are readable for f in "$PUB_ID_FILE" ${PRIV_ID_FILE:+"$PRIV_ID_FILE"} ; do ErrMSG=$( { : < "$f" ; } 2>&1 ) || { L_PRIVMSG="" [ "$f" = "$PRIV_ID_FILE" ] && L_PRIVMSG=" (to install the contents of '$PUB_ID_FILE' anyway, look at the -f option)" 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/.*: *//')" >&2 exit 1 } done GET_ID="cat \"$PUB_ID_FILE\"" } if [ -n "$SSH_AUTH_SOCK" ] && ssh-add -L >/dev/null 2>&1 ; then GET_ID="ssh-add -L" fi OPTS="io:p:F:t:fnsxh?" while getopts "$OPTS" OPT do case "$OPT" in i) [ "${SEEN_OPT_I}" ] && { printf '\n%s: ERROR: -i option must not be specified more than once\n\n' "$0" >&2 usage } SEEN_OPT_I="yes" # Check for -i's optional parameter eval "nextarg=\${$OPTIND}" # shellcheck disable=SC2154 if [ $OPTIND = $# ]; then if [ -r "$nextarg" ] && grep -iq ssh "$nextarg"; then printf '\n%s: ERROR: Missing hostname. Use "-i -- %s" if you really mean to use this as the hostname\n\n' "$0" "$nextarg" >&2 usage fi elif ! expr -- "$nextarg" : "-[$(echo "$OPTS" | tr -d :)-]" >/dev/null ; then # when not at the last arg, and not followed by an option, -i has an argument OPTARG="$nextarg" OPTIND=$((OPTIND + 1)) fi use_id_file "${OPTARG:-$DEFAULT_PUB_ID_FILE}" ;; o|F) OPTS_oF="${OPTS_oF:+$OPTS_oF }-$OPT '$(quote "${OPTARG}")'" ;; f) FORCED=1 ;; n) DRY_RUN=1 ;; p) SSH_PORT=${OPTARG} ;; s) SFTP=sftp ;; t) TARGET_PATH="${OPTARG}" ;; x) SET_X="set -x;" set -x ;; h|\?) usage ;; esac done #shift all args to keep only USER_HOST shift $((OPTIND-1)) if [ $# = 0 ] ; then usage fi if [ $# != 1 ] ; then printf '%s: ERROR: Too many arguments. Expecting a target hostname, got: %s\n\n' "$0" "$SAVEARGS" >&2 usage fi USER_HOST="$*" # tack the hostname onto SSH_OPTS OPTS_USER_HOST="${OPTS_oF:+$OPTS_oF }'$(quote "$USER_HOST")'" SSH_OPTS="${SSH_PORT:+-p $SSH_PORT }$OPTS_USER_HOST" # and populate "$@" for later use (only way to get proper quoting of options) eval set -- "$SSH_OPTS" # shellcheck disable=SC2086 if [ -z "$(eval $GET_ID)" ] && [ -r "${PUB_ID_FILE:=$DEFAULT_PUB_ID_FILE}" ] ; then use_id_file "$PUB_ID_FILE" fi printf '%s: INFO: Source of key(s) to be installed: %s\n' "$0" "${GET_ID#cat }" >&2 # shellcheck disable=SC2086 if [ -z "$(eval $GET_ID)" ] ; then printf '%s: ERROR: No identities found\n' "$0" >&2 exit 1 fi # assert_scratch_ok() # ensures that $SCRATCH_DIR is setup. assert_scratch_ok() { [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ] && [ -w "$SCRATCH_DIR" ] && return 0 printf 'ERROR: Assertion failure: in %s(): scratch_dir was not correctly set up (SCRATCH_DIR = "%s")\n' "$1" "$SCRATCH_DIR" >&2 return 1 } # filter_ids() # tries to log in using the keys piped to it, and filters out any that work filter_ids() { L_SUCCESS="$1" assert_scratch_ok filter_ids || return L_TMP_ID_FILE="$SCRATCH_DIR"/popids_tmp_id L_OUTPUT_FILE="$SCRATCH_DIR"/popids_output # repopulate "$@" inside this function eval set -- "$SSH_OPTS" while read -r ID || [ "$ID" ] ; do printf '%s\n' "$ID" > "$L_TMP_ID_FILE" # the next line assumes $PRIV_ID_FILE only set if using a single id file - this # assumption will break if we implement the possibility of multiple -i options. # The point being that if file based, ssh needs the private key, which it cannot # find if only given the contents of the .pub file in an unrelated tmpfile $SSH -i "${PRIV_ID_FILE:-$L_TMP_ID_FILE}" \ -o ControlPath=none \ -o LogLevel=INFO \ -o PreferredAuthentications=publickey \ -o IdentitiesOnly=yes "$@" exit >"$L_OUTPUT_FILE" 2>&1 </dev/null if [ "$?" = "$L_SUCCESS" ] || { [ "$SFTP" ] && grep 'allows sftp connections only' "$L_OUTPUT_FILE" >/dev/null # this error counts as a success if we're setting up an sftp connection } then : > "$L_TMP_ID_FILE" else grep 'Permission denied' "$L_OUTPUT_FILE" >/dev/null || { sed -e 's/^/ERROR: /' <"$L_OUTPUT_FILE" >"$L_TMP_ID_FILE" cat >/dev/null #consume the other keys, causing loop to end } fi cat "$L_TMP_ID_FILE" done } # populate_new_ids() uses several global variables ($USER_HOST, $SSH_OPTS ...) # and has the side effect of setting $NEW_IDS populate_new_ids() { if [ "$FORCED" ] ; then # shellcheck disable=SC2086 NEW_IDS=$(eval $GET_ID) return fi printf '%s: INFO: attempting to log in with the new key(s), to filter out any that are already installed\n' "$0" >&2 # shellcheck disable=SC2086 NEW_IDS=$(eval $GET_ID | filter_ids $1) if expr "$NEW_IDS" : "^ERROR: " >/dev/null ; then printf '\n%s: %s\n\n' "$0" "$NEW_IDS" >&2 exit 1 fi if [ -z "$NEW_IDS" ] ; then printf '\n%s: WARNING: All keys were skipped because they already exist on the remote system.\n' "$0" >&2 printf '\t\t(if you think this is a mistake, you may want to use -f option)\n\n' >&2 exit 0 fi 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 } # installkey_sh [target_path] # produce a one-liner to add the keys to remote $TARGET_PATH installkeys_sh() { # In setting INSTALLKEYS_SH: # the tr puts it all on one line (to placate tcsh) # (hence the excessive use of semi-colons (;) ) # then in the command: # cd to be at $HOME, just in case; # the -z `tail ...` checks for a trailing newline. The echo adds one if was missing # the cat adds the keys we're getting via STDIN # and if available restorecon is used to restore the SELinux context # OpenWrt has a special case for root only. INSTALLKEYS_SH=$(tr '\t\n' ' ' <<-EOF $SET_X cd; umask 077; AUTH_KEY_FILE="${TARGET_PATH}"; [ -f /etc/openwrt_release ] && [ "\$LOGNAME" = "root" ] && AUTH_KEY_FILE=/etc/dropbear/authorized_keys; AUTH_KEY_DIR=\`dirname "\${AUTH_KEY_FILE}"\`; mkdir -p "\${AUTH_KEY_DIR}" && { [ -z "\`tail -1c "\${AUTH_KEY_FILE}" 2>/dev/null\`" ] || echo >> "\${AUTH_KEY_FILE}" || exit 1; } && cat >> "\${AUTH_KEY_FILE}" || exit 1; if type restorecon >/dev/null 2>&1; then restorecon -F "\${AUTH_KEY_DIR}" "\${AUTH_KEY_FILE}"; fi EOF ) # to defend against quirky remote shells: use 'exec sh -c' to get POSIX; printf "exec sh -c '%s'" "${INSTALLKEYS_SH}" } #shellcheck disable=SC2120 # the 'eval set' confuses this installkeys_via_sftp() { AUTH_KEY_FILE=${TARGET_PATH} AUTH_KEY_DIR=$(dirname "${AUTH_KEY_FILE}") # repopulate "$@" inside this function eval set -- "$SSH_OPTS" assert_scratch_ok installkeys_via_sftp || return 1 L_KEYS="$SCRATCH_DIR"/authorized_keys L_SHARED_CON="$SCRATCH_DIR"/master-conn $SSH -f -N -M -S "$L_SHARED_CON" "$@" L_CLEANUP="$SSH -S '$L_SHARED_CON' -O exit 'ignored' >/dev/null 2>&1 ; $SCRATCH_CLEANUP" #shellcheck disable=SC2064 trap "$L_CLEANUP" EXIT TERM INT QUIT sftp -b - -o "ControlPath='$L_SHARED_CON'" "ignored" <<-EOF || return 1 -get "$AUTH_KEY_FILE" "$L_KEYS" EOF # add a newline or create file if it's missing, same like above [ -z "$(tail -1c "$L_KEYS" 2>/dev/null)" ] || echo >> "$L_KEYS" # append the keys being piped in here cat >> "$L_KEYS" sftp -b - -o "ControlPath='$L_SHARED_CON'" "ignored" <<-EOF || return 1 -mkdir "$AUTH_KEY_DIR" chmod 700 "$AUTH_KEY_DIR" put "$L_KEYS" "$AUTH_KEY_FILE" chmod 600 "$AUTH_KEY_FILE" EOF #shellcheck disable=SC2064 eval "$L_CLEANUP" && trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT } # create a scratch dir for any temporary files needed if SCRATCH_DIR=$(mktemp -d ~/.ssh/ssh-copy-id.XXXXXXXXXX) && [ "$SCRATCH_DIR" ] && [ -d "$SCRATCH_DIR" ] then chmod 0700 "$SCRATCH_DIR" SCRATCH_CLEANUP="rm -rf \"$SCRATCH_DIR\"" #shellcheck disable=SC2064 trap "$SCRATCH_CLEANUP" EXIT TERM INT QUIT else printf '%s: ERROR: failed to create required temporary directory under ~/.ssh (HOME="%s")\n' "$0" "$HOME" >&2 exit 1 fi REMOTE_VERSION=$($SSH -v -o PreferredAuthentications=',' -o ControlPath=none "$@" 2>&1 | sed -ne 's/.*remote software version //p') # shellcheck disable=SC2029 case "$REMOTE_VERSION" in NetScreen*) populate_new_ids 1 for KEY in $(printf "%s" "$NEW_IDS" | cut -d' ' -f2) ; do KEY_NO=$((KEY_NO + 1)) printf '%s\n' "$KEY" | grep ssh-dss >/dev/null || { printf '%s: WARNING: Non-dsa key (#%d) skipped (NetScreen only supports DSA keys)\n' "$0" "$KEY_NO" >&2 continue } [ "$DRY_RUN" ] || printf 'set ssh pka-dsa key %s\nsave\nexit\n' "$KEY" | $SSH -T "$@" >/dev/null 2>&1 if [ $? = 255 ] ; then 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 else ADDED=$((ADDED + 1)) fi done if [ -z "$ADDED" ] ; then exit 1 fi ;; *) # Assuming that the remote host treats $TARGET_PATH as one might expect populate_new_ids 0 if ! [ "$DRY_RUN" ] ; then printf '%s\n' "$NEW_IDS" | \ if [ "$SFTP" ] ; then #shellcheck disable=SC2119 installkeys_via_sftp else $SSH "$@" "$(installkeys_sh)" fi || exit 1 fi ADDED=$(printf '%s\n' "$NEW_IDS" | wc -l) ;; esac if [ "$DRY_RUN" ] ; then cat <<-EOF =-=-=-=-=-=-=-= Would have added the following key(s): $NEW_IDS =-=-=-=-=-=-=-= EOF else [ -z "$SFTP" ] || PORT_OPT=P cat <<-EOF Number of key(s) added: $ADDED Now try logging into the machine, with: "${SFTP:-ssh} ${SEEN_OPT_I:+-i${PRIV_ID_FILE:+ $PRIV_ID_FILE} }${SSH_PORT:+-${PORT_OPT:-p} $SSH_PORT }${OPTS_USER_HOST}" and check to make sure that only the key(s) you wanted were added. EOF fi # =-=-=-=
Save