]> git.ipfire.org Git - thirdparty/rsync.git/blame - rsync-ssl
More tweaks for Actions.
[thirdparty/rsync.git] / rsync-ssl
CommitLineData
27e88dec 1#!/usr/bin/env bash
de78dd68 2
6273153c 3# This script uses openssl, gnutls, or stunnel to secure an rsync daemon connection.
2a87d78f 4
de78dd68
WD
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.
8
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):
11#
12# rsync-ssl --HELPER HOSTNAME rsync --server --daemon .
13#
14# --HELPER is not a user-facing option, so it is not documented in the manpage.
15
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.
18
19function rsync_ssl_run {
20 case "$*" in
21 *rsync://*) ;;
22 *::*) ;;
23 *)
24 echo "You must use rsync-ssl with a daemon-style hostname." 1>&2
25 exit 1
26 ;;
27 esac
28
29 exec rsync --rsh="$0 --HELPER" "${@}"
30}
31
32function rsync_ssl_helper {
33 if [[ -z "$RSYNC_SSL_TYPE" ]]; then
628dcceb 34 found=`path_search openssl stunnel4 stunnel` || exit 1
de78dd68
WD
35 if [[ "$found" == */openssl ]]; then
36 RSYNC_SSL_TYPE=openssl
37 RSYNC_SSL_OPENSSL="$found"
6273153c
WD
38 elif [[ "$found" == */gnutls-cli ]]; then
39 RSYNC_SSL_TYPE=gnutls
40 RSYNC_SSL_GNUTLS="$found"
de78dd68
WD
41 else
42 RSYNC_SSL_TYPE=stunnel
43 RSYNC_SSL_STUNNEL="$found"
44 fi
45 fi
46
47 case "$RSYNC_SSL_TYPE" in
48 openssl)
49 if [[ -z "$RSYNC_SSL_OPENSSL" ]]; then
50 RSYNC_SSL_OPENSSL=`path_search openssl` || exit 1
51 fi
52 optsep=' '
53 ;;
6273153c
WD
54 gnutls)
55 if [[ -z "$RSYNC_SSL_GNUTLS" ]]; then
56 RSYNC_SSL_GNUTLS=`path_search gnutls-cli` || exit 1
57 fi
58 optsep=' '
59 ;;
de78dd68
WD
60 stunnel)
61 if [[ -z "$RSYNC_SSL_STUNNEL" ]]; then
62 RSYNC_SSL_STUNNEL=`path_search stunnel4 stunnel` || exit 1
63 fi
64 optsep=' = '
65 ;;
66 *)
67 echo "The RSYNC_SSL_TYPE specifies an unknown type: $RSYNC_SSL_TYPE" 1>&2
68 exit 1
69 ;;
70 esac
71
72 if [[ -z "$RSYNC_SSL_CERT" ]]; then
73 certopt=""
6273153c 74 gnutls_cert_opt=""
de78dd68 75 else
592c6bc3 76 certopt="-cert$optsep$RSYNC_SSL_CERT"
33379302
F
77 gnutls_cert_opt="--x509certfile=$RSYNC_SSL_CERT"
78 fi
79
80 if [[ -z "$RSYNC_SSL_KEY" ]]; then
81 keyopt=""
82 gnutls_key_opt=""
83 else
84 keyopt="-key$optsep$RSYNC_SSL_KEY"
85 gnutls_key_opt="--x509keyfile=$RSYNC_SSL_KEY"
de78dd68
WD
86 fi
87
88 if [[ -z ${RSYNC_SSL_CA_CERT+x} ]]; then
89 # RSYNC_SSL_CA_CERT unset - default CA set AND verify:
90 # openssl:
91 caopt="-verify_return_error -verify 4"
6273153c
WD
92 # gnutls:
93 gnutls_opts=""
de78dd68 94 # stunnel:
628dcceb
WD
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.
de78dd68 98 cafile=""
00ec415a 99 verify=""
de78dd68
WD
100 elif [[ "$RSYNC_SSL_CA_CERT" == "" ]]; then
101 # RSYNC_SSL_CA_CERT set but empty -do NO verifications:
102 # openssl:
103 caopt="-verify 1"
6273153c
WD
104 # gnutls:
105 gnutls_opts="--insecure"
de78dd68
WD
106 # stunnel:
107 cafile=""
00ec415a 108 verify="verifyChain = no"
de78dd68
WD
109 else
110 # RSYNC_SSL_CA_CERT set - use CA AND verify:
111 # openssl:
112 caopt="-CAfile $RSYNC_SSL_CA_CERT -verify_return_error -verify 4"
6273153c
WD
113 # gnutls:
114 gnutls_opts="--x509cafile=$RSYNC_SSL_CA_CERT"
de78dd68
WD
115 # stunnel:
116 cafile="CAfile = $RSYNC_SSL_CA_CERT"
00ec415a 117 verify="verifyChain = yes"
de78dd68
WD
118 fi
119
120 port="${RSYNC_PORT:-0}"
121 if [[ "$port" == 0 ]]; then
122 port="${RSYNC_SSL_PORT:-874}"
123 fi
124
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
128 shift 2
129 fi
130
131 hostname="$1"
2a87d78f 132 shift
2a87d78f 133
de78dd68
WD
134 if [[ -z "$hostname" || "$1" != rsync || "$2" != --server || "$3" != --daemon ]]; then
135 echo "Usage: rsync-ssl --HELPER HOSTNAME rsync --server --daemon ." 1>&2
136 exit 1
137 fi
138
139 if [[ $RSYNC_SSL_TYPE == openssl ]]; then
33379302 140 exec $RSYNC_SSL_OPENSSL s_client $caopt $certopt $keyopt -quiet -verify_quiet -servername $hostname -verify_hostname $hostname -connect $hostname:$port
6273153c 141 elif [[ $RSYNC_SSL_TYPE == gnutls ]]; then
33379302 142 exec $RSYNC_SSL_GNUTLS --logfile=/dev/null $gnutls_cert_opt $gnutls_key_opt $gnutls_opts $hostname:$port
de78dd68
WD
143 else
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<&-
146foreground = yes
147debug = crit
148connect = $hostname:$port
149client = yes
150TIMEOUTclose = 0
00ec415a 151$verify
de78dd68
WD
152$certopt
153$cafile
154EOF
155 fi
156}
157
158function path_search {
159 IFS_SAVE="$IFS"
160 IFS=:
161 for prog in "${@}"; do
162 for dir in $PATH; do
163 [[ -z "$dir" ]] && dir=.
164 if [[ -f "$dir/$prog" && -x "$dir/$prog" ]]; then
165 echo "$dir/$prog"
166 IFS="$IFS_SAVE"
167 return 0
168 fi
169 done
170 done
171
172 IFS="$IFS_SAVE"
173 echo "Failed to find on your path: $*" 1>&2
174 echo "See the rsync-ssl manpage for configuration assistance." 1>&2
175 return 1
176}
177
178if [[ "$#" == 0 ]]; then
00ec415a 179 echo "Usage: rsync-ssl [--type=SSL_TYPE] RSYNC_ARG [...]" 1>&2
628dcceb 180 echo "The SSL_TYPE can be openssl or stunnel"
70d4a945 181 exit 1
de78dd68
WD
182fi
183
184if [[ "$1" = --help || "$1" = -h ]]; then
185 exec rsync --help
186fi
2a87d78f 187
de78dd68
WD
188if [[ "$1" == --HELPER ]]; then
189 shift
190 rsync_ssl_helper "${@}"
191fi
192
193if [[ "$1" == --type=* ]]; then
194 export RSYNC_SSL_TYPE="${1/--type=/}"
195 shift
196fi
6e962ac5 197
de78dd68 198rsync_ssl_run "${@}"