The branch, master has been updated via e07f8fb8 Add a default single-access lock. via 8cf9dbb7 Change args to maybe-make-man. via 3008e7c2 Include "rrsync" in "all" target when `--with-rrsync` was used. from a2b630c0 Unify md parsing scripts & improve non-man html conversions.
https://git.samba.org/?p=rsync.git;a=shortlog;h=master - Log ----------------------------------------------------------------- commit e07f8fb86329d9370edb47d5c057def16108892e Author: Wayne Davison <wa...@opencoder.net> Date: Mon Dec 27 17:44:32 2021 -0800 Add a default single-access lock. commit 8cf9dbb742ce4c89c649cd4f4a14ed9bd254a075 Author: Wayne Davison <wa...@opencoder.net> Date: Mon Dec 27 17:40:31 2021 -0800 Change args to maybe-make-man. commit 3008e7c2269936672d796d95b85b285fc07adc01 Author: Wayne Davison <wa...@opencoder.net> Date: Mon Dec 27 15:44:51 2021 -0800 Include "rrsync" in "all" target when `--with-rrsync` was used. ----------------------------------------------------------------------- Summary of changes: .github/workflows/build.yml | 6 +++--- Makefile.in | 18 +++++++++--------- NEWS.md | 23 ++++++++++++++--------- configure.ac | 6 +++++- maybe-make-man | 13 ++++--------- packaging/cull_options | 5 ++++- support/lsh | 19 +++++++++---------- support/rrsync | 35 ++++++++++++++++++++++++++++++----- 8 files changed, 78 insertions(+), 47 deletions(-) Changeset truncated at 500 lines: diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml index 4f5cbf23..a44cd2ab 100644 --- a/.github/workflows/build.yml +++ b/.github/workflows/build.yml @@ -24,7 +24,7 @@ jobs: - name: configure run: ./configure --with-rrsync - name: make - run: make all rrsync + run: make - name: install run: sudo make install - name: info @@ -63,7 +63,7 @@ jobs: - name: configure run: CPPFLAGS=-I/usr/local/opt/openssl/include/ LDFLAGS=-L/usr/local/opt/openssl/lib/ ./configure --with-rrsync - name: make - run: make all rrsync + run: make - name: install run: sudo make install - name: info @@ -103,7 +103,7 @@ jobs: - name: configure run: bash -c './configure --with-rrsync' - name: make - run: bash -c 'make all rrsync' + run: bash -c 'make' - name: install run: bash -c 'make install' - name: info diff --git a/Makefile.in b/Makefile.in index 14d95abe..8a16f651 100644 --- a/Makefile.in +++ b/Makefile.in @@ -45,11 +45,11 @@ OBJS1=flist.o rsync.o generator.o receiver.o cleanup.o sender.o exclude.o \ util1.o util2.o main.o checksum.o match.o syscall.o log.o backup.o delete.o OBJS2=options.o io.o compat.o hlink.o token.o uidlist.o socket.o hashtable.o \ usage.o fileio.o batch.o clientname.o chmod.o acls.o xattrs.o -OBJS3=progress.o pipe.o @ASM@ +OBJS3=progress.o pipe.o @ASM@ @SIMD@ DAEMON_OBJ = params.o loadparm.o clientserver.o access.o connection.o authenticate.o popt_OBJS=popt/findme.o popt/popt.o popt/poptconfig.o \ popt/popthelp.o popt/poptparse.o -OBJS=$(OBJS1) $(OBJS2) $(OBJS3) @SIMD@ $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@ +OBJS=$(OBJS1) $(OBJS2) $(OBJS3) $(DAEMON_OBJ) $(LIBOBJ) @BUILD_ZLIB@ @BUILD_POPT@ TLS_OBJ = tls.o syscall.o util2.o t_stub.o lib/compat.o lib/snprintf.o lib/permstring.o lib/sysxattrs.o @BUILD_POPT@ @@ -68,7 +68,7 @@ CHECK_OBJS=tls.o testrun.o getgroups.o getfsdev.o t_stub.o t_unsafe.o trimslash. $(CC) -I. -I$(srcdir) $(CFLAGS) $(CPPFLAGS) -c $< @CC_SHOBJ_FLAG@ @OBJ_RESTORE@ -all: Makefile rsync$(EXEEXT) stunnel-rsyncd.conf @MAKE_MAN@ +all: Makefile rsync$(EXEEXT) stunnel-rsyncd.conf @MAKE_RRSYNC@ @MAKE_MAN@ .PHONY: all .PHONY: install @@ -82,7 +82,7 @@ install: all if test -f rsync-ssl.1; then $(INSTALLMAN) -m 644 rsync-ssl.1 $(DESTDIR)$(mandir)/man1; fi if test -f rsyncd.conf.5; then $(INSTALLMAN) -m 644 rsyncd.conf.5 $(DESTDIR)$(mandir)/man5; fi if test "$(with_rrsync)" = yes; then \ - $(INSTALLCMD) -m 755 $(srcdir)/support/rrsync $(DESTDIR)$(bindir); \ + $(INSTALLCMD) -m 755 rrsync $(DESTDIR)$(bindir); \ if test -f rrsync.1; then $(INSTALLMAN) -m 644 rrsync.1 $(DESTDIR)$(mandir)/man1; fi; \ fi @@ -255,19 +255,19 @@ proto.h-tstamp: $(srcdir)/*.c $(srcdir)/lib/compat.c daemon-parm.h $(AWK) -f $(srcdir)/mkproto.awk $(srcdir)/*.c $(srcdir)/lib/compat.c daemon-parm.h .PHONY: man -man: rsync.1 rsync-ssl.1 rsyncd.conf.5 rrsync.1 +man: rsync.1 rsync-ssl.1 rsyncd.conf.5 @MAKE_RRSYNC_1@ rsync.1: rsync.1.md md-convert version.h Makefile - @$(srcdir)/maybe-make-man $(srcdir) rsync.1.md + @$(srcdir)/maybe-make-man rsync.1.md rsync-ssl.1: rsync-ssl.1.md md-convert version.h Makefile - @$(srcdir)/maybe-make-man $(srcdir) rsync-ssl.1.md + @$(srcdir)/maybe-make-man rsync-ssl.1.md rsyncd.conf.5: rsyncd.conf.5.md md-convert version.h Makefile - @$(srcdir)/maybe-make-man $(srcdir) rsyncd.conf.5.md + @$(srcdir)/maybe-make-man rsyncd.conf.5.md rrsync.1: support/rrsync.1.md md-convert Makefile - @$(srcdir)/maybe-make-man $(srcdir) support/rrsync.1.md + @$(srcdir)/maybe-make-man support/rrsync.1.md .PHONY: clean clean: cleantests diff --git a/NEWS.md b/NEWS.md index b88208c5..735dec1d 100644 --- a/NEWS.md +++ b/NEWS.md @@ -97,15 +97,20 @@ - More ASM optimizations from Shark64. - - Transformed rrsync into a python script with improvements: security has been - beefed up; the known rsync options were updated to include recent additions; - rrsync rejects `-L` (`--copy-links`) by default to make it harder to exploit - any out-of-subdir symlinks; a new rrsync option of `-munge` tells rrsync to - always enable the `--munge-links` rsync option on the server side; a new - rrsync option of `-no-del` disables all `--remove*` and `--delete*` rsync - options on the server side; the log format has been tweaked slightly to add - seconds to the timestamp and output the command executed as a tuple; an - rrsync.1 manpage is now created. + - Transformed rrsync into a python script with improvements: + - Security has been beefed up. + - The known rsync options were updated to include recent additions. + - Make rrsync reject `-L`, `-K`, & `-k` by default to make it harder to + exploit any out-of-subdir symlinks. + - A new rrsync option of `-munge` tells rrsync to always enable rsync's + `--munge-links` option on the server side. + - A new rrsync option of `-no-lock` disables a new single-use locking idiom + that is the default when `-ro` is not used (useful with `-munge`). + - A new rrsync option of `-no-del` disables all `--remove*` and `--delete*` + options on the server side. + - The log format has been tweaked slightly to add seconds to the timestamp + and to output the command executed as a tuple (making the args clearer). + - An rrsync.1 manpage was added. - Work around a glibc bug where lchmod() breaks in a chroot w/o /proc mounted. diff --git a/configure.ac b/configure.ac index b30eeb93..3caf5e39 100644 --- a/configure.ac +++ b/configure.ac @@ -117,7 +117,6 @@ if test x"$enable_md2man" != x"no"; then MAKE_MAN=man else AC_MSG_RESULT(no) - MAKE_MAN='' fi # Specifically, this turns on panic_action handling. @@ -140,6 +139,9 @@ AC_ARG_WITH(rrsync, AS_HELP_STRING([--with-rrsync],[also install the rrsync script and its man page])) if test x"$with_rrsync" != x"yes"; then with_rrsync=no +else + MAKE_RRSYNC='rrsync' + MAKE_RRSYNC_1='rrsync.1' fi AC_SUBST(with_rrsync) @@ -1253,6 +1255,8 @@ AC_SUBST(OBJ_RESTORE) AC_SUBST(CC_SHOBJ_FLAG) AC_SUBST(BUILD_POPT) AC_SUBST(BUILD_ZLIB) +AC_SUBST(MAKE_RRSYNC) +AC_SUBST(MAKE_RRSYNC_1) AC_SUBST(MAKE_MAN) AC_CHECK_FUNCS(_acl __acl _facl __facl) diff --git a/maybe-make-man b/maybe-make-man index 99b8fb89..0dc17305 100755 --- a/maybe-make-man +++ b/maybe-make-man @@ -1,19 +1,14 @@ #!/bin/sh -if [ x"$2" = x ]; then - echo "Usage: $0 SRC_DIR NAME.NUM.md" 1>&2 +if [ $# != 1 ]; then + echo "Usage: $0 NAME.NUM.md" 1>&2 exit 1 fi -srcdir="$1" -inname="$2" +inname="$1" +srcdir=`dirname "$0"` flagfile="$srcdir/.md2man-works" -if [ ! -d "$srcdir" ]; then - echo "The specified SRC_DIR is not a directory: $srcdir" 1>&2 - exit 1 -fi - if [ ! -f "$flagfile" ]; then # We test our smallest manpage just to see if the python setup works. if "$srcdir/md-convert" --test "$srcdir/rsync-ssl.1.md" >/dev/null 2>&1; then diff --git a/packaging/cull_options b/packaging/cull_options index d4e1c626..ca061121 100755 --- a/packaging/cull_options +++ b/packaging/cull_options @@ -86,7 +86,10 @@ def main(): # To disable a short-named option, add its letter to this string: """ - txt += str_assign('short_disabled', 'Ls') + "\n" + txt += str_assign('short_disabled', 's') + "\n" + txt += '# These are also disabled when the restricted dir is not "/":\n' + txt += str_assign('short_disabled_subdir', 'KLk') + "\n" + txt += '# These are all possible short options that we will accept (when not disabled above):\n' txt += str_assign('short_no_arg', ''.join(sorted(short_no_arg)), 'DO NOT REMOVE ANY') txt += str_assign('short_with_num', ''.join(sorted(short_with_num)), 'DO NOT REMOVE ANY') diff --git a/support/lsh b/support/lsh index 40fe3d73..7b3c0656 100755 --- a/support/lsh +++ b/support/lsh @@ -16,10 +16,7 @@ GetOptions( 'no-cd' => \( my $no_chdir ), 'sudo' => \( my $use_sudo ), 'rrsync=s' => \( my $rrsync_dir ), - 'ro' => \( my $rrsync_ro = '' ), - 'wo' => \( my $rrsync_wo = '' ), - 'munge' => \( my $rrsync_munge = '' ), - 'no-del' => \( my $rrsync_no_del = '' ), + 'rropts=s' => \( my $rrsync_opts ), ) or &usage; &usage unless @ARGV > 1; @@ -75,10 +72,12 @@ unless ($no_chdir) { if ($rrsync_dir) { $ENV{SSH_ORIGINAL_COMMAND} = join(' ', @ARGV); push @cmd, 'rrsync'; - push @cmd, '-ro' if $rrsync_ro; - push @cmd, '-wo' if $rrsync_wo; - push @cmd, '-munge' if $rrsync_munge; - push @cmd, '-no-del' if $rrsync_no_del; + if ($rrsync_opts) { + foreach my $opt (split(/[ ,]+/, $rrsync_opts)) { + $opt = "-$opt" unless $opt =~ /^-/; + push @cmd, $opt; + } + } push @cmd, $rrsync_dir; } else { push @cmd, '/bin/sh', '-c', "@ARGV"; @@ -101,8 +100,8 @@ Options: --no-cd Skip the chdir \$HOME (the default with hostname "lh") --sudo Use sudo -H -l USER to become root or the specified USER. --rrsync=DIR Test rrsync restricted copying without using ssh. ---ro Passes -ro to rrsync (when --rrsync is specified). ---wo Passes -wo to rrsync (when --rrsync is specified. +--rropts=STR The string "munge,no-del,no-lock" would pass 3 options to + rrsync (must be combined with --rrsync=DIR). The script also ignores a bunch of single-letter ssh options. EOT diff --git a/support/rrsync b/support/rrsync index 5b43a819..469288b9 100755 --- a/support/rrsync +++ b/support/rrsync @@ -24,8 +24,12 @@ LOGFILE = 'rrsync.log' # NOTE: the file must exist for a line to be appended! ### START of options data produced by the cull_options script. ### # To disable a short-named option, add its letter to this string: -short_disabled = 'Ls' +short_disabled = 's' +# These are also disabled when the restricted dir is not "/": +short_disabled_subdir = 'KLk' + +# These are all possible short options that we will accept (when not disabled above): short_no_arg = 'ACDEHIJKLNORSUWXbcdgklmnopqrstuvxyz' # DO NOT REMOVE ANY short_with_num = '@B' # DO NOT REMOVE ANY @@ -125,7 +129,7 @@ long_opts = { ### END of options data produced by the cull_options script. ### -import os, sys, re, argparse, glob, socket, time +import os, sys, re, argparse, glob, socket, time, subprocess from argparse import RawTextHelpFormatter try: @@ -174,6 +178,10 @@ def main(): if args.ro: long_opts['log-file'] = -1 + if args.dir != '/': + global short_disabled + short_disabled += short_disabled_subdir + short_no_arg_re = short_no_arg short_with_num_re = short_with_num if short_disabled: @@ -268,8 +276,12 @@ def main(): log_fh.close() # NOTE: This assumes that the rsync protocol will not be maliciously hijacked. - os.execlp(RSYNC, *cmd) - die("execlp(", RSYNC, *cmd, ') failed') + if args.no_lock: + os.execlp(RSYNC, *cmd) + die("execlp(", RSYNC, *cmd, ') failed') + child = subprocess.run(cmd) + if child.returncode != 0: + sys.exit(child.returncode) def validated_arg(opt, arg, typ=3, wild=False): @@ -319,6 +331,16 @@ def validated_arg(opt, arg, typ=3, wild=False): return ret if wild else ret[0] +def lock_or_die(dirname): + import fcntl + global lock_handle + lock_handle = os.open(dirname, os.O_RDONLY) + try: + fcntl.flock(lock_handle, fcntl.LOCK_EX | fcntl.LOCK_NB) + except: + die('Another instance of rrsync is already accessing this directory.') + + def die(*msg): print(sys.argv[0], 'error:', *msg, file=sys.stderr) if sys.stdin.isatty(): @@ -336,9 +358,10 @@ if __name__ == '__main__': our_desc = """Use "man rrsync" to learn how to restrict ssh users to using a restricted rsync command.""" arg_parser = OurArgParser(description=our_desc, add_help=False) only_group = arg_parser.add_mutually_exclusive_group() - only_group.add_argument('-ro', action='store_true', help="Allow only reading from the DIR. Implies -no-del.") + only_group.add_argument('-ro', action='store_true', help="Allow only reading from the DIR. Implies -no-del and -no-lock.") only_group.add_argument('-wo', action='store_true', help="Allow only writing to the DIR.") arg_parser.add_argument('-no-del', action='store_true', help="Disable rsync's --delete* and --remove* options.") + arg_parser.add_argument('-no-lock', action='store_true', help="Avoid the single-run (per-user) lock check.") arg_parser.add_argument('-munge', action='store_true', help="Enable rsync's --munge-links on the server side.") arg_parser.add_argument('-help', '-h', action='help', help="Output this help message and exit.") arg_parser.add_argument('dir', metavar='DIR', help="The restricted directory to use.") @@ -348,6 +371,8 @@ if __name__ == '__main__': args.dir_slash_len = len(args.dir) if args.ro: args.no_del = True + elif not args.no_lock: + lock_or_die(args.dir) main() # vim: sw=4 et -- The rsync repository. _______________________________________________ rsync-cvs mailing list rsync-cvs@lists.samba.org https://lists.samba.org/mailman/listinfo/rsync-cvs