Annotation of embedaddon/rsync/rsync-ssl, revision 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>