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>