Sisyphus repository
Last update: 1 october 2023 | SRPMs: 18631 | Visits: 37771515
en ru br
ALT Linux repos
S:2.5.4-alt4

Group :: Archiving/Backup
RPM: burp

 Main   Changelog   Spec   Patches   Sources   Download   Gear   Bugs and FR  Repocop 

Patch: burp-2.3.16-alt3.patch
Download


 .gear/burp.init                 | 102 +++++++++++++++++++++++++++++++
 .gear/burp.service              |  10 +++
 .gear/burp.spec                 | 131 ++++++++++++++++++++++++++++++++++++++++
 .gear/rules                     |   3 +
 .gear/tags/list                 |   1 +
 .gear/test-burp.sh              |  71 ++++++++++++++++++++++
 .gear/test-client.conf          |  23 +++++++
 .gear/test-server.conf          |  33 ++++++++++
 .gear/upstream/remotes          |   3 +
 Makefile.am                     |   6 +-
 android/burp_ca                 |   1 -
 configs/certs/CA/CA.cnf.in      |   1 -
 configs/certs/CA/burp_ca.bat.in |   1 -
 configs/certs/CA/burp_ca.in     |   3 -
 configs/client/burp.conf.in     |   9 ++-
 configure.ac                    |  14 +++++
 manpages/burp.8.in              |   3 +
 src/conf.c                      |   2 +
 src/conf.h                      |   3 +
 src/handy.c                     |  77 +++++++++++++++++------
 src/handy.h                     |  12 +++-
 src/prog.c                      |  10 ++-
 src/server/child.c              |   2 +-
 utest/test_conf.c               |   1 +
 24 files changed, 492 insertions(+), 30 deletions(-)
diff --git a/.gear/burp.init b/.gear/burp.init
new file mode 100755
index 00000000..e5c41cae
--- /dev/null
+++ b/.gear/burp.init
@@ -0,0 +1,102 @@
+#! /bin/sh
+#
+# burp init file distributed with brup package
+# author: bassu@phi9.com
+#
+# burp-server  Start burp server
+#
+# chkconfig: - 08 92
+# description: Burp backup server
+#
+# processname: burp
+# config: /etc/burp/burp-server.conf
+# pidfile: /var/run/burp.server.pid
+#
+### BEGIN INIT INFO
+# Provides: burp-server
+# Required-Start: $network $syslog $local_fs
+# Required-Stop: $network $syslog $local_fs
+# Default-Start:
+# Default-Stop:
+# Description: Burp backup server daemon
+# Short-Description: Burp backup server
+### END INIT INFO
+
+. /etc/init.d/functions
+
+RETVAL=0
+prog=burp
+burp=${BURP-/usr/sbin/burp}
+pidfile=${PIDFILE-/var/run/burp.server.pid}
+lockfile=${LOCKFILE-/var/lock/subsys/burp}
+conffile=${CONFFILE-/etc/burp/burp-server.conf}
+
+start () {
+	status -p ${pidfile} ${burp} &>/dev/null && { echo "$prog is already running"; exit 1; }
+	echo -n $"Starting $prog: "
+	start_daemon ${burp} -c ${conffile}
+	RETVAL=$?
+	echo
+	[ $RETVAL -eq 0 ] && touch ${lockfile}
+}
+stop () {
+	echo -n $"Stopping $prog: "
+	stop_daemon ${prog}
+	RETVAL=$?
+	echo
+	if [ $RETVAL -eq 0 ] ; then
+		rm -f ${lockfile} ${pidfile}
+	fi
+}
+
+restart () {
+        stop
+        start
+}
+
+reload () {
+	echo -n $"Reloading $prog: "
+	stop_daemon -p ${pidfile} ${prog} -HUP
+	RETVAL=$?
+	echo
+}
+
+case "$1" in
+  start)
+	start
+	;;
+  stop)
+	stop
+	;;
+  status)
+	status -p ${pidfile} ${burp}
+	RETVAL=$?
+	;;
+  restart)
+	restart
+	;;
+  reload)
+	reload
+	;;
+  condstop)
+	if [ -e "$lockfile" ]; then
+		stop
+	fi
+	;;
+  condrestart)
+	if [ -e "$lockfile" ]; then
+		restart
+	fi
+	;;
+  condreload)
+	if [ -e "$lockfile" ]; then
+		reload
+	fi
+	;;
+  *)
+	echo $"Usage: $0 {start|stop|status|restart|reload|condstop|condrestart|condreload}"
+	RETVAL=2
+        ;;
+esac
+
+exit $RETVAL
diff --git a/.gear/burp.service b/.gear/burp.service
new file mode 100644
index 00000000..92ba4989
--- /dev/null
+++ b/.gear/burp.service
@@ -0,0 +1,10 @@
+[Unit]
+Description=Burp backup server
+After=network.target
+
+[Service]
+Type=forking
+ExecStart=/usr/sbin/burp -c /etc/burp/burp-server.conf
+
+[Install]
+WantedBy=multi-user.target
diff --git a/.gear/burp.spec b/.gear/burp.spec
new file mode 100644
index 00000000..d823e174
--- /dev/null
+++ b/.gear/burp.spec
@@ -0,0 +1,131 @@
+Name:		burp
+Version:	2.3.16
+Release:	alt3
+
+Summary:	Burp is a network-based backup and restore program
+License:	AGPL-3.0 and BSD and GPLv2+ and LGPLv2+
+Group:		Archiving/Backup
+Url:		https://burp.grke.org/
+
+# https://github.com/grke/burp.git master
+Source:		%{name}-%{version}.tar
+Patch:		%{name}-%{version}-%{release}.patch
+
+BuildRequires:  libtool
+BuildRequires:  librsync-devel
+BuildRequires:  zlib-devel
+BuildRequires:  openssl-devel
+BuildRequires:  libncurses-devel
+BuildRequires:  libacl-devel
+BuildRequires:  libuthash-devel
+BuildRequires:  libyajl-devel
+BuildRequires:  check libcheck-devel
+BuildRequires:  libcap-devel
+BuildRequires:  openssl
+
+BuildRequires: rpm-macros-intro-conflicts
+%add_findreq_skiplist %_datadir/%name/scripts/*
+
+%description
+Burp is a network backup and restore program, using client and server.
+It uses librsync in order to save network traffic and to save on the
+amount of space that is used by each backup.
+
+%prep
+%setup
+%patch -p1
+
+%build
+%autoreconf
+%configure \
+    --sysconfdir="%_sysconfdir/burp" \
+    --disable-static
+
+%make_build
+
+%install
+%makeinstall_std install-all
+install -D -p -m 0755 .gear/burp.init %{buildroot}%{_initrddir}/burp-server
+install -D -p -m 0644 .gear/burp.service %{buildroot}%{_unitdir}/burp-server.service
+%__subst "s,password,#password,g" %{buildroot}%_sysconfdir/burp/clientconfdir/testclient
+
+%check
+%make_build check
+.gear/test-burp.sh
+
+%files
+%doc %_docdir/%name/
+%{_initrddir}/burp-server
+%{_unitdir}/burp-*.*
+%dir %_datadir/%name/
+%_datadir/%name/scripts/
+%_bindir/vss_strip
+%_sbindir/*
+%_man8dir/*
+%defattr(640,root,_burp,3770)
+%dir %_sysconfdir/burp/
+%dir %_sysconfdir/burp/CA-client/
+%dir %_sysconfdir/burp/clientconfdir/
+%dir %_sysconfdir/burp/clientconfdir/incexc/
+%config(noreplace) %_sysconfdir/burp/*.c*nf
+%config(noreplace) %_sysconfdir/burp/clientconfdir/testclient
+%config(noreplace) %_sysconfdir/burp/clientconfdir/incexc/example
+
+%pre
+/usr/sbin/groupadd -r -f _burp
+/usr/sbin/useradd -r -g _burp -d /var/empty -s /dev/null -n -c "BURP BackUp and Restore Program" _burp >/dev/null 2>&1 ||:
+
+%post
+%post_service burp-server
+
+%preun
+%preun_service burp-server
+
+%changelog
+* Wed Feb 12 2020 Vitaly Chikunov <vt@altlinux.org> 2.3.16-alt3
+- Remove parasite dependencies from optional scripts.
+
+* Fri Dec 06 2019 Vitaly Chikunov <vt@altlinux.org> 2.3.16-alt2
+- Adjust chkconfig runlevels so that server isn't enabled by default
+- Make _burp:_burp user and configs owned by root:_burp
+- Fix setgid if group= is not specified
+- Add small functionality test
+
+* Mon Nov 25 2019 Vitaly Chikunov <vt@altlinux.org> 2.3.16-alt1
+- New version 2.3.16
+- Fix license string
+- Fix compatibility with openssl-1.1.1
+- Implement support of keeping readall capabilities
+
+* Tue Oct 01 2019 Vitaly Chikunov <vt@altlinux.org> 2.3.14-alt1
+- New version 2.3.14
+
+* Wed Apr 03 2019 Vitaly Chikunov <vt@altlinux.org> 2.3.4-alt1
+- New version 2.3.4
+
+* Fri Mar 15 2019 Vitaly Chikunov <vt@altlinux.org> 2.3.2-alt1
+- new version 2.3.2
+
+* Wed Feb 20 2019 Vitaly Chikunov <vt@altlinux.org> 2.3.0-alt1
+- Update to 2.3.0-12-g3d093f25
+
+* Wed Aug 29 2018 Grigory Ustinov <grenka@altlinux.org> 2.2.4-alt1.1
+- NMU: Rebuild with new openssl 1.1.0.
+
+* Wed Jun 06 2018 Vitaly Chikunov <vt@altlinux.org> 2.2.4-alt1
+- Update to version 2.2.4
+
+* Thu Apr 19 2018 Vitaly Chikunov <vt@altlinux.org> 2.1.32-alt2
+- Fix init script
+- Secure permissions for configs that supposed to contain passwords
+
+* Sun Apr 15 2018 Vitaly Chikunov <vt@altlinux.org> 2.1.32-alt1
+- Respec for 2.1.32
+- Install init scripts
+
+* Tue Dec 05 2017 Vitaly Lipatov <lav@altlinux.ru> 2.1.24-alt1
+- new version 2.1.24 (with rpmrb script)
+
+* Wed Aug 10 2016 Vitaly Lipatov <lav@altlinux.ru> 2.0.44-alt1
+- initial build for ALT Linux Sisyphus
+
diff --git a/.gear/rules b/.gear/rules
new file mode 100644
index 00000000..e47cc414
--- /dev/null
+++ b/.gear/rules
@@ -0,0 +1,3 @@
+spec: .gear/burp.spec
+diff: @version@:. .
+tar: @version@:.
diff --git a/.gear/tags/list b/.gear/tags/list
new file mode 100644
index 00000000..2ef2772e
--- /dev/null
+++ b/.gear/tags/list
@@ -0,0 +1 @@
+6fd6314fecfabb294e6b587fda77934f133e4b22 2.3.16
diff --git a/.gear/test-burp.sh b/.gear/test-burp.sh
new file mode 100755
index 00000000..75c0f418
--- /dev/null
+++ b/.gear/test-burp.sh
@@ -0,0 +1,71 @@
+#!/bin/bash -efu
+
+cd $(dirname $0)
+
+buildroot=$(set +f; echo /usr/src/tmp/*-buildroot)
+home=/usr/src/burp
+PATH=$buildroot/usr/sbin:$PATH
+
+echo "==============="
+echo "FUNCTIONAL TEST"
+echo "==============="
+_err() {
+	ERR=$?
+	echo =======
+	echo FAILURE $ERR
+	echo =======
+	exit $ERR
+}
+trap _err ERR
+
+V() {
+	echo "RUN: $*"
+	"$@"
+}
+
+mkdir -p $home/{client,server,bin}
+mkdir -p $home/client/CA-client
+mkdir -p $home/server/clientconfdir
+mkdir -p $home/server/spool
+
+cp $buildroot/usr/sbin/burp_ca $home/bin/
+cp $buildroot/etc/burp/CA.cnf $home/server/
+
+sed -i "s,^etc=.*,etc=$home/server," $home/bin/burp_ca
+sed -i "s,^CA_DIR.*,CA_DIR = $home/server/CA," $home/server/CA.cnf
+grep ^password test-client.conf > $home/server/clientconfdir/testclient
+
+_kill() {
+	trap - EXIT
+	kill $(cat $home/server/burp.server.pid)
+	wait
+}
+# For debugging of this inside of hasher, othervise hasher-priv
+# could hang on exit from hsh-shell
+trap _kill EXIT
+
+V burp -c test-server.conf -g
+V burp -c test-server.conf -F &
+sleep 1 # Allow them time to startup
+
+V burp -c test-client.conf -al
+V burp -c test-client.conf -ab
+
+# Allow some time for server to settle backup
+for i in $(seq 10); do
+	if [ -e $home/server/spool/testclient/current ]; then
+		echo "Backup settled ($i)"
+		break
+	fi
+	sleep $i
+done
+
+V burp -c test-client.conf -ar -d $home -s3 -f
+_kill
+
+# And now
+V diff -r /usr/src/RPM $home/RPM
+
+echo =======
+echo SUCCESS
+echo =======
diff --git a/.gear/test-client.conf b/.gear/test-client.conf
new file mode 100644
index 00000000..1ddea122
--- /dev/null
+++ b/.gear/test-client.conf
@@ -0,0 +1,23 @@
+mode = client
+server = 127.0.0.1:4971
+status_port = 4972
+password = abcdefgh
+cname = testclient
+pidfile = /usr/src/burp/client/burp.client.pid
+syslog = 0
+stdout = 1
+progress_counter = 0
+server_can_restore = 0
+cross_filesystem = /home
+cross_all_filesystems = 0
+ca_burp_ca = /usr/src/burp/bin/burp_ca
+ca_csr_dir = /usr/src/burp/client/CA-client
+ssl_cert_ca = /usr/src/burp/client/ssl_cert_ca.pem
+ssl_cert = /usr/src/burp/client/ssl_cert-client.pem
+ssl_key = /usr/src/burp/client/ssl_cert-client.key
+ssl_peer_cn = burpserver
+include = /usr/src/RPM
+exclude_fs = sysfs
+nobackup = .nobackup
+exclude_comp = bz2
+exclude_comp = gz
diff --git a/.gear/test-server.conf b/.gear/test-server.conf
new file mode 100644
index 00000000..312b3189
--- /dev/null
+++ b/.gear/test-server.conf
@@ -0,0 +1,33 @@
+mode = server
+listen = 0.0.0.0:4971
+max_children = 5
+directory = /usr/src/burp/server/spool
+dedup_group = global
+clientconfdir = /usr/src/burp/server/clientconfdir
+pidfile = /usr/src/burp/server/burp.server.pid
+hardlinked_archive = 0
+working_dir_recovery_method = delete
+umask = 0022
+syslog = 0
+stdout = 1
+client_can_delete = 1
+client_can_diff = 1
+client_can_force_backup = 1
+client_can_list = 1
+client_can_monitor = 1
+client_can_restore = 1
+client_can_verify = 1
+version_warn = 1
+keep = 7
+ca_conf = /usr/src/burp/server/CA.cnf
+ca_name = burpCA
+ca_server_name = burpserver
+ca_burp_ca = /usr/src/burp/bin/burp_ca
+ca_crl_check = 1
+ssl_cert_ca = /usr/src/burp/server/ssl_cert_ca.pem
+ssl_cert = /usr/src/burp/server/ssl_cert-server.pem
+ssl_key = /usr/src/burp/server/ssl_cert-server.key
+ssl_dhfile = /usr/src/burp/server/dhfile.pem
+timer_arg = 20h
+timer_arg = Mon,Tue,Wed,Thu,Fri,00,01,02,03,04,05,19,20,21,22,23
+timer_arg = Sat,Sun,00,01,02,03,04,05,06,07,08,17,18,19,20,21,22,23
diff --git a/.gear/upstream/remotes b/.gear/upstream/remotes
new file mode 100644
index 00000000..cd34b75c
--- /dev/null
+++ b/.gear/upstream/remotes
@@ -0,0 +1,3 @@
+[remote "upstream"]
+	url = git://github.com/grke/burp.git
+	fetch = +refs/heads/*:refs/remotes/upstream/*
diff --git a/Makefile.am b/Makefile.am
index cfb1cc14..050523ca 100755
--- a/Makefile.am
+++ b/Makefile.am
@@ -118,7 +118,8 @@ main_LDADD = \
 	$(NCURSES_LIBS) \
 	$(OPENSSL_LIBS) \
 	$(RSYNC_LIBS) \
-	$(ZLIBS)
+	$(ZLIBS) \
+	$(CAP_LIBS)
 
 main_CPPFLAGS = \
 	$(AM_CPPFLAGS) \
@@ -399,7 +400,8 @@ runner_LDADD = \
 	$(NCURSES_LIBS) \
 	$(RSYNC_LIBS) \
 	$(OPENSSL_LIBS) \
-	$(ZLIBS)
+	$(ZLIBS) \
+	$(CAP_LIBS)
 
 coverage: check
 if WITH_COVERAGE
diff --git a/android/burp_ca b/android/burp_ca
index 026ad468..e57cf43e 100755
--- a/android/burp_ca
+++ b/android/burp_ca
@@ -9,7 +9,6 @@ name="$8"
 echo "generating key ${name}: ${keypath}"
 ${burp_dir}/openssl genrsa -out "${keypath}" 2048
 
-echo 'RANDFILE = /dev/urandom' > "${tmpconf}"
 echo '[ req ]' >> "${tmpconf}"
 echo 'distinguished_name = req_distinguished_name' >> "${tmpconf}"
 echo 'prompt = no' >> "${tmpconf}"
diff --git a/configs/certs/CA/CA.cnf.in b/configs/certs/CA/CA.cnf.in
index 35b85686..073378fe 100644
--- a/configs/certs/CA/CA.cnf.in
+++ b/configs/certs/CA/CA.cnf.in
@@ -1,6 +1,5 @@
 # simple config for burp_ca
 
-RANDFILE                = /dev/urandom
 CA_DIR                  = @sysconfdir@/CA
 
 
diff --git a/configs/certs/CA/burp_ca.bat.in b/configs/certs/CA/burp_ca.bat.in
index 960e108c..2f75955f 100644
--- a/configs/certs/CA/burp_ca.bat.in
+++ b/configs/certs/CA/burp_ca.bat.in
@@ -40,7 +40,6 @@ echo "generating key %name%: %keypath%"
 REM Need to create a config file for openssl in order to make a certicate
 REM signing request. There must be a neater way to do it than one line at a time
 REM and %tmpconf% at the end each time.
-echo RANDFILE = /dev/urandom > "%tmpconf%"
 echo [ req ] >> "%tmpconf%"
 echo distinguished_name = req_distinguished_name >> "%tmpconf%"
 echo prompt = no >> "%tmpconf%"
diff --git a/configs/certs/CA/burp_ca.in b/configs/certs/CA/burp_ca.in
index 3a3c054c..ad4a5b62 100755
--- a/configs/certs/CA/burp_ca.in
+++ b/configs/certs/CA/burp_ca.in
@@ -190,8 +190,6 @@ if [ "$init" = "yes" ]; then
 	umask "$def_umask"
 	TEMP="$(mktemp "/tmp/@name@_ca.tmp.XXXXXXXX" || echo "/tmp/@name@_ca.tmp.$$")"
 	cat <<-EOF > "$TEMP"
-	RANDFILE                = /dev/urandom
-
 	[ req ]
 	distinguished_name      = req_distinguished_name
 	prompt                  = no
@@ -237,7 +235,6 @@ if [ "$request" = "yes" ]; then
         [ -d "$(dirname "$requestpath")" ] || mkdir "$(dirname "$requestpath")"
 	TEMP="$(mktemp "/tmp/@name@_ca.tmp.XXXXXXXX" || echo "/tmp/@name@_ca.tmp.$$")"
 	cat <<-EOF > "$TEMP"
-	RANDFILE                = /dev/urandom
         req_extensions          = v3_req
 
 	[ req ]
diff --git a/configs/client/burp.conf.in b/configs/client/burp.conf.in
index e9472df4..2a5c22a2 100644
--- a/configs/client/burp.conf.in
+++ b/configs/client/burp.conf.in
@@ -52,8 +52,13 @@ server_can_restore = 0
 # . path/to/more/conf
 
 # Run as different user/group.
-# user=graham
-# group=nogroup
+# user=_burp
+# group=_burp
+# Set to 1 to keep 'readall' capability (linux only) when dropping privileges
+# (default is 0, do not keep capability). Readall capability allows process
+# to read all files (even not owned by user) without requiring root privileges.
+# When using readall=1 if user= is not set it's assumed nobody.
+# readall=1
 
 cross_filesystem=/home
 cross_all_filesystems=0
diff --git a/configure.ac b/configure.ac
index 9af8921b..517edfbc 100644
--- a/configure.ac
+++ b/configure.ac
@@ -278,6 +278,19 @@ AC_CHECK_HEADERS([librsync.h],
 
 AC_SUBST([RSYNC_LIBS])
 
+dnl -----------------------------------------------------------
+dnl Check for headers, functions and libraries required to
+dnl support keeping readall capabilities
+dnl -----------------------------------------------------------
+
+AC_CHECK_HEADERS(sys/prctl.h sys/capability.h)
+AC_CHECK_FUNCS(prctl setreuid)
+AC_CHECK_LIB([cap], [cap_set_proc], [CAP_LIBS="-lcap"], [CAP_LIBS=])
+if test x$CAP_LIBS = x-lcap; then
+   have_readall=yes
+   AC_DEFINE(HAVE_LIBCAP, 1, [Define if you have libcap])
+fi
+AC_SUBST([CAP_LIBS])
 
 dnl --------------------------------------------------------------------------
 dnl Check whether librsync has RS_BLAKE2_SIG_MAGIC
@@ -536,6 +549,7 @@ AC_MSG_NOTICE([                   acl: ${have_acl}])
 AC_MSG_NOTICE([                 crypt: ${have_crypt}])
 AC_MSG_NOTICE([                  ipv6: ${enable_ipv6}])
 AC_MSG_NOTICE([               ncurses: ${have_ncurses}])
+AC_MSG_NOTICE([               readall: ${have_readall}])
 AC_MSG_NOTICE([               openssl: ${have_ssl}])
 AC_MSG_NOTICE([                 xattr: ${have_xattr}])
 AC_MSG_NOTICE([                  zlib: ${ac_cv_header_zlib_h}])
diff --git a/manpages/burp.8.in b/manpages/burp.8.in
index ff216e8b..7c1c7664 100644
--- a/manpages/burp.8.in
+++ b/manpages/burp.8.in
@@ -321,6 +321,9 @@ Run as a particular user. This can be overridden by the client configuration fil
 \fBgroup=[groupname]\fR
 Run as a particular group. This can be overridden by the client configuration files in clientconfdir on the server.
 .TP
+\fBreadall=[0|1]\fR
+Keep readall capability when dropping root privileges (default 0). When enabled changes default atime to 1.
+.TP
 \fBumask=[umask]\fR
 Set the file creation umask. Default is 0022.
 .TP
diff --git a/src/conf.c b/src/conf.c
index 64390e7e..f44bddd7 100644
--- a/src/conf.c
+++ b/src/conf.c
@@ -572,6 +572,8 @@ static int reset_conf(struct conf **c, enum conf_opt o)
 	  return sc_cntr(c[o], 0, 0, "");
 	case OPT_VSS_RESTORE:
 	  return sc_int(c[o], VSS_RESTORE_ON, 0, "");
+	case OPT_READALL:
+	  return sc_int(c[o], 0, CONF_FLAG_CC_OVERRIDE, "readall");
 	case OPT_BREAKPOINT:
 	  return sc_int(c[o], 0,
 		CONF_FLAG_CC_OVERRIDE, "breakpoint");
diff --git a/src/conf.h b/src/conf.h
index bb9e5196..f4bfd11e 100644
--- a/src/conf.h
+++ b/src/conf.h
@@ -314,6 +314,9 @@ enum conf_opt
 	// For testing.
 	OPT_BREAKPOINT,
 
+	// readall capability
+	OPT_READALL,
+
 	OPT_MAX
 };
 
diff --git a/src/handy.c b/src/handy.c
index 1db149c5..88cf50a6 100644
--- a/src/handy.c
+++ b/src/handy.c
@@ -336,7 +336,7 @@ void setup_signal(int sig, void handler(int sig))
 }
 
 /* Function based on src/lib/priv.c from bacula. */
-int chuser_and_or_chgrp(const char *user, const char *group)
+int chuser_and_or_chgrp(const char *user, const char *group, int readall)
 {
 #ifndef HAVE_WIN32
 	struct passwd *passw = NULL;
@@ -345,6 +345,9 @@ int chuser_and_or_chgrp(const char *user, const char *group)
 	uid_t uid;
 	char *username=NULL;
 
+	// Allow setting readall=1 without setting user
+	if(readall && !user)
+		user="nobody";
 	if(!user && !group) return 0;
 
 	if(user)
@@ -377,41 +380,81 @@ int chuser_and_or_chgrp(const char *user, const char *group)
 		{
 			logp("could not find group '%s': %s\n", group,
 				strerror(errno));
-			free_w(&username);
-			return -1;
+			goto err;
 		}
 		gid=grp->gr_gid;
+	} else {
+		// Resolve git to group name for logp()
+		if (!(grp=getgrgid(gid)))
+		{
+			logp("could not find group for gid %d: %s\n", gid,
+				strerror(errno));
+			goto err;
+		}
+		group=grp->gr_name;
+		grp=NULL;
 	}
 	if(gid!=getgid() // do not do it if we already have the same gid.
 	  && initgroups(username, gid))
 	{
 		if(grp)
-			logp("could not initgroups for group '%s', user '%s': %s\n", group, user, strerror(errno));
+			logp("could not initgroups for group '%s', user '%s': %s\n", group, username, strerror(errno));
 		else
-			logp("could not initgroups for user '%s': %s\n", user, strerror(errno));
-		free_w(&username);
-		return -1;
+			logp("could not initgroups for user '%s': %s\n", username, strerror(errno));
+		goto err;
 	}
-	free_w(&username);
-	if(grp)
+	if(gid!=getgid() // do not do it if we already have the same gid
+	    && setgid(gid))
 	{
-		if(gid!=getgid() // do not do it if we already have the same gid
-		 && setgid(gid))
+		logp("could not set group '%s': %s\n", group,
+		    strerror(errno));
+		goto err;
+	}
+	if (readall)
+	{
+#ifdef ENABLE_KEEP_READALL_CAPS_SUPPORT
+		cap_t caps;
+		// Make capabilities pass through setreuid
+		if(prctl(PR_SET_KEEPCAPS, 1))
 		{
-			logp("could not set group '%s': %s\n", group,
-				strerror(errno));
-			return -1;
+			logp("prctl(PR_SET_KEEPCAPS) failed: %s\n", strerror(errno));
+			goto err;
 		}
-	}
-	if(uid!=getuid() // do not do it if we already have the same uid
+		if(setreuid(uid, uid))
+		{
+			logp("Could not switch to user=%s (uid=%u): %s\n", username, uid, strerror(errno));
+			goto err;
+		}
+		// `ep' is Effective and Permitted
+		caps=cap_from_text("cap_dac_read_search=ep");
+		if(!caps)
+		{
+			logp("cap_from_text() failed: %s\n", strerror(errno));
+			goto err;
+		}
+		if(cap_set_proc(caps) < 0)
+		{
+			logp("cap_set_proc() failed: %s\n", strerror(errno));
+			goto err;
+		}
+		cap_free(caps);
+		logp("Privileges switched to %s keeping readall capability.\n", username);
+#else
+		logp("Keep readall capabilities is not implemented on this platform yet\n");
+		goto err;
+#endif
+	} else if(uid!=getuid() // do not do it if we already have the same uid
 	  && setuid(uid))
 	{
 		logp("could not set specified user '%s': %s\n", username,
 			strerror(errno));
-		return -1;
+		goto err;
 	}
 #endif
 	return 0;
+err:
+	free_w(&username);
+	return -1;
 }
 
 // Not in dpth.c so that Windows client can see it.
diff --git a/src/handy.h b/src/handy.h
index 2f2f9401..cdf92c3a 100644
--- a/src/handy.h
+++ b/src/handy.h
@@ -9,6 +9,16 @@
 
 #include "bfile.h"
 
+#undef ENABLE_KEEP_READALL_CAPS_SUPPORT
+#if defined(HAVE_SYS_PRCTL_H) && defined(HAVE_SYS_CAPABILITY_H) && \
+	defined(HAVE_PRCTL) && defined(HAVE_SETREUID) && defined(HAVE_LIBCAP)
+# include <sys/prctl.h>
+# include <sys/capability.h>
+# if defined(PR_SET_KEEPCAPS)
+#  define ENABLE_KEEP_READALL_CAPS_SUPPORT
+# endif
+#endif
+
 #define min(a,b) \
    ({ __typeof__ (a) _a = (a); \
        __typeof__ (b) _b = (b); \
@@ -23,7 +33,7 @@ extern int set_peer_env_vars(struct sockaddr_storage *addr);
 extern int set_keepalive(int fd, int value);
 extern int init_client_socket(const char *host, const char *port);
 extern void reuseaddr(int fd);
-extern int chuser_and_or_chgrp(const char *user, const char *group);
+extern int chuser_and_or_chgrp(const char *user, const char *group, int readall);
 extern int dpth_protocol1_is_compressed(int compressed, const char *datapath);
 #ifndef HAVE_WIN32
 extern void setup_signal(int sig, void handler(int sig));
diff --git a/src/prog.c b/src/prog.c
index 16a9e653..218641d4 100644
--- a/src/prog.c
+++ b/src/prog.c
@@ -308,6 +308,7 @@ int real_main(int argc, char *argv[])
 	int test_confs=0;
 	enum burp_mode mode;
 	struct strlist *cli_overrides=NULL;
+	int keep_readall_caps=0;
 
 	log_init(argv[0]);
 #ifndef HAVE_WIN32
@@ -498,6 +499,12 @@ int real_main(int argc, char *argv[])
 			case ACTION_BACKUP:
 			case ACTION_BACKUP_TIMED:
 			case ACTION_TIMER_CHECK:
+#ifdef ENABLE_KEEP_READALL_CAPS_SUPPORT
+				keep_readall_caps=get_int(confs[OPT_READALL]);
+				// readall=1 cannot work with atime=0 (O_NOATIME)
+				if (keep_readall_caps)
+					set_int(confs[OPT_ATIME], 1);
+#endif
 				// Need to get the lock.
 				if(!(lock=get_prog_lock(confs)))
 					goto end;
@@ -509,7 +516,8 @@ int real_main(int argc, char *argv[])
 
 	// Change privileges after having got the lock, for convenience.
 	if(chuser_and_or_chgrp(
-		get_string(confs[OPT_USER]), get_string(confs[OPT_GROUP])))
+		get_string(confs[OPT_USER]), get_string(confs[OPT_GROUP]),
+		keep_readall_caps))
 			return -1;
 
 	set_int(confs[OPT_OVERWRITE], forceoverwrite);
diff --git a/src/server/child.c b/src/server/child.c
index 27f2c665..c0977f86 100644
--- a/src/server/child.c
+++ b/src/server/child.c
@@ -194,7 +194,7 @@ int child(struct async *as, int is_status_server,
 	if( (!confs_user  || (cconfs_user && strcmp(confs_user, cconfs_user)))
 	  ||(!confs_group ||(cconfs_group && strcmp(confs_group,cconfs_group))))
 	{
-		if(chuser_and_or_chgrp(cconfs_user, cconfs_group))
+		if(chuser_and_or_chgrp(cconfs_user, cconfs_group, 0))
 		{
 			log_and_send(as->asfd,
 				"chuser_and_or_chgrp failed on server");
diff --git a/utest/test_conf.c b/utest/test_conf.c
index eb0574fc..04f5e9d1 100644
--- a/utest/test_conf.c
+++ b/utest/test_conf.c
@@ -82,6 +82,7 @@ static void check_default(struct conf **c, enum conf_opt o)
 		case OPT_B_SCRIPT_POST_RUN_ON_FAIL:
 		case OPT_R_SCRIPT_POST_RUN_ON_FAIL:
 		case OPT_SEND_CLIENT_CNTR:
+		case OPT_READALL:
 		case OPT_BREAKPOINT:
 		case OPT_SYSLOG:
 		case OPT_PROGRESS_COUNTER:
 
design & coding: Vladimir Lettiev aka crux © 2004-2005, Andrew Avramenko aka liks © 2007-2008
current maintainer: Michael Shigorin