Skip to content

Instantly share code, notes, and snippets.

@michaelherger
Forked from lo48576/rrysnc.sh
Last active June 21, 2024 23:30

Revisions

  1. michaelherger revised this gist Apr 25, 2018. No changes.
  2. michaelherger revised this gist Apr 18, 2018. 1 changed file with 4 additions and 4 deletions.
    8 changes: 4 additions & 4 deletions rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -41,8 +41,8 @@ debug() {
    echo "[$DATETIME][DEBUG] $1" | tr '\n' '\0' | sed -e 's/\0/\n[DEBUG]'"$DATETIME"'/g' >>"$LOGFILE"
    }

    debug ">>>>>>>>>>>>>>>>>>>>>>>>>"
    debug "$SSH_ORIGINAL_COMMAND"
    #debug ">>>>>>>>>>>>>>>>>>>>>>>>>"
    #debug "$SSH_ORIGINAL_COMMAND"

    # Get "only" option.
    # It would be "w" for `-wo` (write only), "r" for `-ro` (read only), or empty string (neither `-ro` nor `-wo`).
    @@ -125,9 +125,9 @@ while [ $# -ge 1 ] ; do
    shift
    done

    debug "$SSH_ORIGINAL_COMMAND"
    #debug "$SSH_ORIGINAL_COMMAND"

    # Arguments are safe!
    # Arguments are safer!
    # Execute rsync.
    exec $SSH_ORIGINAL_COMMAND

  3. michaelherger revised this gist Apr 18, 2018. 1 changed file with 20 additions and 2 deletions.
    22 changes: 20 additions & 2 deletions rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -17,15 +17,16 @@
    # You should have received a copy of the GNU General Public License
    # along with this program. If not, see <http://www.gnu.org/licenses/>.

    # see https://www.samba.org/ftp/unpacked/rsync/support/rrsync for reference
    # bash version: https://gist.github.com/lo48576/d120d139e091f2338d35e1de85f9315f

    # This script is based on `support/rrsync` perl script in rsync-3.1.2.

    USAGE="Use command=\"$0 [-ro|-wo] SUBDIR\"
    in front of lines in ${HOME}/.ssh/authorized_keys"
    LOGFILE="${HOME}/rrsync.log"
    LOGFILE="${HOME}/logs/rrsync.log"
    CMDNAME="$0"


    # Log the given message.
    die() {
    DATETIME="$(LANG=C date '+%F %T')"
    @@ -40,6 +41,8 @@ debug() {
    echo "[$DATETIME][DEBUG] $1" | tr '\n' '\0' | sed -e 's/\0/\n[DEBUG]'"$DATETIME"'/g' >>"$LOGFILE"
    }

    debug ">>>>>>>>>>>>>>>>>>>>>>>>>"
    debug "$SSH_ORIGINAL_COMMAND"

    # Get "only" option.
    # It would be "w" for `-wo` (write only), "r" for `-ro` (read only), or empty string (neither `-ro` nor `-wo`).
    @@ -79,7 +82,9 @@ if ! echo "$SSH_ORIGINAL_COMMAND" | grep -sqE '^rsync\s+--server' ; then
    fi

    # Check whether the rsync server should be sender or receiver.
    AM_SENDER=0
    if echo "$SSH_ORIGINAL_COMMAND" | grep -sqE '^rsync\s+--server\s+--sender\s' ; then
    AM_SENDER=1
    # The local rsync is sender mode, i.e. files should be sent from local to remote.
    if [ "x$ONLY" = "xw" ] ; then
    die "Sending to read-only server not allowed."
    @@ -95,22 +100,35 @@ fi
    set -f
    set -- $SSH_ORIGINAL_COMMAND
    # For each argument:
    CHECK_TYPE=0
    while [ $# -ge 1 ] ; do
    # Collapse continuous slashes in the argument.
    ARG="$(echo "$1" | sed -e 's!///*!/!g')"

    # Ensure the argument has no ".." as path component.
    if echo "$ARG" | grep -sqE '(^(-[a-zA-Z0-9-]+=?)?|/)\.\.(/|$)' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: \`$1\`"
    die "Do not use .. in option argument, anchor the path at the root of your restricted dir."
    fi

    # Ensure the argument has no absolute path.
    if echo "$ARG" | grep -sq '^/' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: \`$1\`"
    die "Do not use absolute path in argument, anchor the path at the root of your restricted dir."
    fi

    # values copied from https://www.samba.org/ftp/unpacked/rsync/support/rrsync -> $short_no_arg less $short_disabled
    if echo "$ARG" | grep -sqE '^-([ACDEHIJKLORSWXbcdgklmnoprtuvxyz]*s[ACDEHIJKLORSWXbcdgklmnoprtuvxyz]*(e\d*\.\w*)?$)'; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: --protect-args / -s"
    die "--protect-args is not allowed as we need to inspect the target path"
    fi
    shift
    done

    debug "$SSH_ORIGINAL_COMMAND"

    # Arguments are safe!
    # Execute rsync.
    exec $SSH_ORIGINAL_COMMAND


  4. らりお (YOSHIOKA Takuma) revised this gist Feb 10, 2018. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@

    USAGE="Use command=\"$0 [-ro|-wo] SUBDIR\"
    in front of lines in ${HOME}/.ssh/authorized_keys"
    LOGFILE="${HOME}/rsync.log"
    LOGFILE="${HOME}/rrsync.log"
    CMDNAME="$0"


  5. らりお (YOSHIOKA Takuma) revised this gist Feb 10, 2018. 1 changed file with 3 additions and 3 deletions.
    6 changes: 3 additions & 3 deletions rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -2,7 +2,7 @@

    # Copyright (C) 2004 Joe Smith <[email protected]>
    # Copyright (C) 2004-2015 Wayne Davison <[email protected]>
    # Copyright (C) 2016-2017 YOSHIOKA Takuma <[email protected]>
    # Copyright (C) 2016-2018 YOSHIOKA Takuma <[email protected]>
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    @@ -100,12 +100,12 @@ while [ $# -ge 1 ] ; do
    ARG="$(echo "$1" | sed -e 's!///*!/!g')"
    # Ensure the argument has no ".." as path component.
    if echo "$ARG" | grep -sqE '(^(-[a-zA-Z0-9-]+=?)?|/)\.\.(/|$)' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: `$1`"
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: \`$1\`"
    die "Do not use .. in option argument, anchor the path at the root of your restricted dir."
    fi
    # Ensure the argument has no absolute path.
    if echo "$ARG" | grep -sq '^/' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: `$1`"
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: \`$1\`"
    die "Do not use absolute path in argument, anchor the path at the root of your restricted dir."
    fi
    shift
  6. らりお (YOSHIOKA Takuma) revised this gist Jul 1, 2017. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -66,7 +66,7 @@ if [ $# -lt 1 ] ; then
    die "No subdirectory specified.\n${USAGE}"
    fi
    ALLOWED_DIR="$1"
    cd "$ALLOWED_DIR"
    cd "$ALLOWED_DIR" || die 'Failed to change current directory'

    # Ensure the rrsync is invoked via sshd.
    if [ -z "$SSH_ORIGINAL_COMMAND" ] ; then
  7. らりお (YOSHIOKA Takuma) revised this gist Jun 27, 2017. 1 changed file with 20 additions and 0 deletions.
    20 changes: 20 additions & 0 deletions rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -1,5 +1,25 @@
    #!/bin/sh

    # Copyright (C) 2004 Joe Smith <[email protected]>
    # Copyright (C) 2004-2015 Wayne Davison <[email protected]>
    # Copyright (C) 2016-2017 YOSHIOKA Takuma <[email protected]>
    #
    # This program is free software: you can redistribute it and/or modify
    # it under the terms of the GNU General Public License as published by
    # the Free Software Foundation, either version 3 of the License, or
    # (at your option) any later version.
    #
    # This program is distributed in the hope that it will be useful,
    # but WITHOUT ANY WARRANTY; without even the implied warranty of
    # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
    # GNU General Public License for more details.
    #
    # You should have received a copy of the GNU General Public License
    # along with this program. If not, see <http://www.gnu.org/licenses/>.


    # This script is based on `support/rrsync` perl script in rsync-3.1.2.

    USAGE="Use command=\"$0 [-ro|-wo] SUBDIR\"
    in front of lines in ${HOME}/.ssh/authorized_keys"
    LOGFILE="${HOME}/rsync.log"
  8. らりお (YOSHIOKA Takuma) revised this gist Nov 17, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -78,7 +78,7 @@ set -- $SSH_ORIGINAL_COMMAND
    while [ $# -ge 1 ] ; do
    # Collapse continuous slashes in the argument.
    ARG="$(echo "$1" | sed -e 's!///*!/!g')"
    # Ensure the argument has no ".." as argument.
    # Ensure the argument has no ".." as path component.
    if echo "$ARG" | grep -sqE '(^(-[a-zA-Z0-9-]+=?)?|/)\.\.(/|$)' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: `$1`"
    die "Do not use .. in option argument, anchor the path at the root of your restricted dir."
  9. らりお (YOSHIOKA Takuma) revised this gist Oct 7, 2016. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -6,7 +6,7 @@ LOGFILE="${HOME}/rsync.log"
    CMDNAME="$0"


    # Die with the given error message.
    # Log the given message.
    die() {
    DATETIME="$(LANG=C date '+%F %T')"
    echo "[$DATETIME] $CMDNAME: $1" >>"$LOGFILE"
  10. らりお (YOSHIOKA Takuma) created this gist Oct 7, 2016.
    96 changes: 96 additions & 0 deletions rrysnc.sh
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,96 @@
    #!/bin/sh

    USAGE="Use command=\"$0 [-ro|-wo] SUBDIR\"
    in front of lines in ${HOME}/.ssh/authorized_keys"
    LOGFILE="${HOME}/rsync.log"
    CMDNAME="$0"


    # Die with the given error message.
    die() {
    DATETIME="$(LANG=C date '+%F %T')"
    echo "[$DATETIME] $CMDNAME: $1" >>"$LOGFILE"
    echo >>"$LOGFILE"
    exit 2
    }

    # Die with the given error message.
    debug() {
    DATETIME="$(LANG=C date '+%F %T')"
    echo "[$DATETIME][DEBUG] $1" | tr '\n' '\0' | sed -e 's/\0/\n[DEBUG]'"$DATETIME"'/g' >>"$LOGFILE"
    }


    # Get "only" option.
    # It would be "w" for `-wo` (write only), "r" for `-ro` (read only), or empty string (neither `-ro` nor `-wo`).
    ONLY=""
    while [ "x$1" = "x-ro" -o "x$1" = "x-wo" ] ; do
    if [ "x$1" = "x-ro" ] ; then
    if [ "x$ONLY" = "xw" ] ; then
    die "the -ro and -wo options conflict."
    fi
    ONLY="r"
    shift
    else
    if [ "x$ONLY" = "xr" ] ; then
    die "the -ro and -wo options conflict."
    fi
    ONLY="w"
    shift
    fi
    done
    # Now "$ONLY" has "r", "w" or "".

    # Ensure the subdirectory is given.
    if [ $# -lt 1 ] ; then
    die "No subdirectory specified.\n${USAGE}"
    fi
    ALLOWED_DIR="$1"
    cd "$ALLOWED_DIR"

    # Ensure the rrsync is invoked via sshd.
    if [ -z "$SSH_ORIGINAL_COMMAND" ] ; then
    die "Not invoked via sshd.\n${USAGE}"
    fi

    # Ensure the rrsync is invoked in server mode via remote rsync.
    if ! echo "$SSH_ORIGINAL_COMMAND" | grep -sqE '^rsync\s+--server' ; then
    die "SSH_ORIGINAL_COMMAND='$SSH_ORIGINAL_COMMAND' is not 'rsync --server' or '--server' is not specified first."
    fi

    # Check whether the rsync server should be sender or receiver.
    if echo "$SSH_ORIGINAL_COMMAND" | grep -sqE '^rsync\s+--server\s+--sender\s' ; then
    # The local rsync is sender mode, i.e. files should be sent from local to remote.
    if [ "x$ONLY" = "xw" ] ; then
    die "Sending to read-only server not allowed."
    fi
    else
    # The local rsync is receiver mode, i.e. files should be sent from remote to local.
    if [ "x$ONLY" = "xr" ] ; then
    die "Reading to write-only server not allowed."
    fi
    fi

    # Command line sanity check.
    set -f
    set -- $SSH_ORIGINAL_COMMAND
    # For each argument:
    while [ $# -ge 1 ] ; do
    # Collapse continuous slashes in the argument.
    ARG="$(echo "$1" | sed -e 's!///*!/!g')"
    # Ensure the argument has no ".." as argument.
    if echo "$ARG" | grep -sqE '(^(-[a-zA-Z0-9-]+=?)?|/)\.\.(/|$)' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: `$1`"
    die "Do not use .. in option argument, anchor the path at the root of your restricted dir."
    fi
    # Ensure the argument has no absolute path.
    if echo "$ARG" | grep -sq '^/' ; then
    debug "command line: ${SSH_ORIGINAL_COMMAND}\ndangerous argument: `$1`"
    die "Do not use absolute path in argument, anchor the path at the root of your restricted dir."
    fi
    shift
    done

    # Arguments are safe!
    # Execute rsync.
    exec $SSH_ORIGINAL_COMMAND