3 # This script uses openssl, gnutls, or stunnel to secure an rsync daemon connection.
5 # By default this script takes rsync args and hands them off to the actual
6 # rsync command with an --rsh option that makes it open an SSL connection to an
7 # rsync daemon. See the rsync-ssl manpage for usage details and env variables.
9 # When the first arg is --HELPER, we are being used by rsync as an --rsh helper
10 # script, and the args are (note the trailing dot):
12 # rsync-ssl --HELPER HOSTNAME rsync --server --daemon .
14 # --HELPER is not a user-facing option, so it is not documented in the manpage.
16 # The first SSL setup was based on: http://dozzie.jarowit.net/trac/wiki/RsyncSSL
17 # Note that an stunnel connection requires at least version 4.x of stunnel.
19 function rsync_ssl_run
{
24 echo "You must use rsync-ssl with a daemon-style hostname." 1>&2
29 exec rsync
--rsh="$0 --HELPER" "${@}"
32 function rsync_ssl_helper
{
33 if [[ -z "$RSYNC_SSL_TYPE" ]]; then
34 found
=`path_search openssl stunnel4 stunnel` ||
exit 1
35 if [[ "$found" == */openssl
]]; then
36 RSYNC_SSL_TYPE
=openssl
37 RSYNC_SSL_OPENSSL
="$found"
38 elif [[ "$found" == */gnutls-cli
]]; then
40 RSYNC_SSL_GNUTLS
="$found"
42 RSYNC_SSL_TYPE
=stunnel
43 RSYNC_SSL_STUNNEL
="$found"
47 case "$RSYNC_SSL_TYPE" in
49 if [[ -z "$RSYNC_SSL_OPENSSL" ]]; then
50 RSYNC_SSL_OPENSSL
=`path_search openssl` ||
exit 1
55 if [[ -z "$RSYNC_SSL_GNUTLS" ]]; then
56 RSYNC_SSL_GNUTLS
=`path_search gnutls-cli` ||
exit 1
61 if [[ -z "$RSYNC_SSL_STUNNEL" ]]; then
62 RSYNC_SSL_STUNNEL
=`path_search stunnel4 stunnel` ||
exit 1
67 echo "The RSYNC_SSL_TYPE specifies an unknown type: $RSYNC_SSL_TYPE" 1>&2
72 if [[ -z "$RSYNC_SSL_CERT" ]]; then
76 certopt
="-cert$optsep$RSYNC_SSL_CERT"
77 gnutls_cert_opt
="--x509certfile=$RSYNC_SSL_CERT"
80 if [[ -z "$RSYNC_SSL_KEY" ]]; then
84 keyopt
="-key$optsep$RSYNC_SSL_KEY"
85 gnutls_key_opt
="--x509keyfile=$RSYNC_SSL_KEY"
88 if [[ -z ${RSYNC_SSL_CA_CERT+x} ]]; then
89 # RSYNC_SSL_CA_CERT unset - default CA set AND verify:
91 caopt
="-verify_return_error -verify 4"
95 # Since there is no way of using the default CA certificate collection,
96 # we cannot do any verification. Thus, stunnel should really only be
97 # used if nothing else is available.
100 elif [[ "$RSYNC_SSL_CA_CERT" == "" ]]; then
101 # RSYNC_SSL_CA_CERT set but empty -do NO verifications:
105 gnutls_opts
="--insecure"
108 verify
="verifyChain = no"
110 # RSYNC_SSL_CA_CERT set - use CA AND verify:
112 caopt
="-CAfile $RSYNC_SSL_CA_CERT -verify_return_error -verify 4"
114 gnutls_opts
="--x509cafile=$RSYNC_SSL_CA_CERT"
116 cafile
="CAfile = $RSYNC_SSL_CA_CERT"
117 verify
="verifyChain = yes"
120 port
="${RSYNC_PORT:-0}"
121 if [[ "$port" == 0 ]]; then
122 port
="${RSYNC_SSL_PORT:-874}"
125 # If the user specified USER@HOSTNAME::module, then rsync passes us
126 # the -l USER option too, so we must be prepared to ignore it.
127 if [[ "$1" == "-l" ]]; then
134 if [[ -z "$hostname" ||
"$1" != rsync ||
"$2" != --server ||
"$3" != --daemon ]]; then
135 echo "Usage: rsync-ssl --HELPER HOSTNAME rsync --server --daemon ." 1>&2
139 if [[ $RSYNC_SSL_TYPE == openssl
]]; then
140 exec $RSYNC_SSL_OPENSSL s_client
$caopt $certopt $keyopt -quiet -verify_quiet -servername $hostname -verify_hostname $hostname -connect $hostname:$port
141 elif [[ $RSYNC_SSL_TYPE == gnutls
]]; then
142 exec $RSYNC_SSL_GNUTLS --logfile=/dev
/null
$gnutls_cert_opt $gnutls_key_opt $gnutls_opts $hostname:$port
144 # devzero@web.de came up with this no-tmpfile calling syntax:
145 exec $RSYNC_SSL_STUNNEL -fd 10 11<&0 <<EOF 10<&0 0<&11 11<&-
148 connect = $hostname:$port
158 function path_search
{
161 for prog
in "${@}"; do
163 [[ -z "$dir" ]] && dir
=.
164 if [[ -f "$dir/$prog" && -x "$dir/$prog" ]]; then
173 echo "Failed to find on your path: $*" 1>&2
174 echo "See the rsync-ssl manpage for configuration assistance." 1>&2
178 if [[ "$#" == 0 ]]; then
179 echo "Usage: rsync-ssl [--type=SSL_TYPE] RSYNC_ARG [...]" 1>&2
180 echo "The SSL_TYPE can be openssl or stunnel"
184 if [[ "$1" = --help ||
"$1" = -h ]]; then
188 if [[ "$1" == --HELPER ]]; then
190 rsync_ssl_helper
"${@}"
193 if [[ "$1" == --type=* ]]; then
194 export RSYNC_SSL_TYPE
="${1/--type=/}"