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>