File:  [ELWIX - Embedded LightWeight unIX -] / embedaddon / rsync / rsync-ssl
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs - revision graph
Wed Mar 17 00:32:36 2021 UTC (3 years, 3 months ago) by misho
Branches: rsync, MAIN
CVS tags: v3_2_3, HEAD
rsync 3.2.3

    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>