Annotation of embedaddon/rsync/rsync-ssl, revision 1.1.1.1
1.1 misho 1: #!/usr/bin/env bash
2:
3: # This script uses openssl, gnutls, or stunnel to secure an rsync daemon connection.
4:
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:
19: function 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:
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
39: RSYNC_SSL_TYPE=gnutls
40: RSYNC_SSL_GNUTLS="$found"
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: ;;
54: gnutls)
55: if [[ -z "$RSYNC_SSL_GNUTLS" ]]; then
56: RSYNC_SSL_GNUTLS=`path_search gnutls-cli` || exit 1
57: fi
58: optsep=' '
59: ;;
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=""
74: gnutls_cert_opt=""
75: else
76: certopt="cert$optsep$RSYNC_SSL_CERT"
77: gnutls_cert_opt="--x509keyfile=$RSYNC_SSL_CERT"
78: fi
79:
80: if [[ -z ${RSYNC_SSL_CA_CERT+x} ]]; then
81: # RSYNC_SSL_CA_CERT unset - default CA set AND verify:
82: # openssl:
83: caopt="-verify_return_error -verify 4"
84: # gnutls:
85: gnutls_opts=""
86: # stunnel:
87: # Since there is no way of using the default CA certificate collection,
88: # we cannot do any verification. Thus, stunnel should really only be
89: # used if nothing else is available.
90: cafile=""
91: verify=""
92: elif [[ "$RSYNC_SSL_CA_CERT" == "" ]]; then
93: # RSYNC_SSL_CA_CERT set but empty -do NO verifications:
94: # openssl:
95: caopt="-verify 1"
96: # gnutls:
97: gnutls_opts="--insecure"
98: # stunnel:
99: cafile=""
100: verify="verifyChain = no"
101: else
102: # RSYNC_SSL_CA_CERT set - use CA AND verify:
103: # openssl:
104: caopt="-CAfile $RSYNC_SSL_CA_CERT -verify_return_error -verify 4"
105: # gnutls:
106: gnutls_opts="--x509cafile=$RSYNC_SSL_CA_CERT"
107: # stunnel:
108: cafile="CAfile = $RSYNC_SSL_CA_CERT"
109: verify="verifyChain = yes"
110: fi
111:
112: port="${RSYNC_PORT:-0}"
113: if [[ "$port" == 0 ]]; then
114: port="${RSYNC_SSL_PORT:-874}"
115: fi
116:
117: # If the user specified USER@HOSTNAME::module, then rsync passes us
118: # the -l USER option too, so we must be prepared to ignore it.
119: if [[ "$1" == "-l" ]]; then
120: shift 2
121: fi
122:
123: hostname="$1"
124: shift
125:
126: if [[ -z "$hostname" || "$1" != rsync || "$2" != --server || "$3" != --daemon ]]; then
127: echo "Usage: rsync-ssl --HELPER HOSTNAME rsync --server --daemon ." 1>&2
128: exit 1
129: fi
130:
131: if [[ $RSYNC_SSL_TYPE == openssl ]]; then
132: exec $RSYNC_SSL_OPENSSL s_client $caopt $certopt -quiet -verify_quiet -servername $hostname -connect $hostname:$port
133: elif [[ $RSYNC_SSL_TYPE == gnutls ]]; then
134: exec $RSYNC_SSL_GNUTLS --logfile=/dev/null $gnutls_cert_opt $gnutls_opts $hostname:$port
135: else
136: # devzero@web.de came up with this no-tmpfile calling syntax:
137: exec $RSYNC_SSL_STUNNEL -fd 10 11<&0 <<EOF 10<&0 0<&11 11<&-
138: foreground = yes
139: debug = crit
140: connect = $hostname:$port
141: client = yes
142: TIMEOUTclose = 0
143: $verify
144: $certopt
145: $cafile
146: EOF
147: fi
148: }
149:
150: function path_search {
151: IFS_SAVE="$IFS"
152: IFS=:
153: for prog in "${@}"; do
154: for dir in $PATH; do
155: [[ -z "$dir" ]] && dir=.
156: if [[ -f "$dir/$prog" && -x "$dir/$prog" ]]; then
157: echo "$dir/$prog"
158: IFS="$IFS_SAVE"
159: return 0
160: fi
161: done
162: done
163:
164: IFS="$IFS_SAVE"
165: echo "Failed to find on your path: $*" 1>&2
166: echo "See the rsync-ssl manpage for configuration assistance." 1>&2
167: return 1
168: }
169:
170: if [[ "$#" == 0 ]]; then
171: echo "Usage: rsync-ssl [--type=SSL_TYPE] RSYNC_ARG [...]" 1>&2
172: echo "The SSL_TYPE can be openssl or stunnel"
173: exit 1
174: fi
175:
176: if [[ "$1" = --help || "$1" = -h ]]; then
177: exec rsync --help
178: fi
179:
180: if [[ "$1" == --HELPER ]]; then
181: shift
182: rsync_ssl_helper "${@}"
183: fi
184:
185: if [[ "$1" == --type=* ]]; then
186: export RSYNC_SSL_TYPE="${1/--type=/}"
187: shift
188: fi
189:
190: rsync_ssl_run "${@}"
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>