auth_server() tokenised on commas AND whitespace, ignoring the documented
comma-only form, so an entry containing a space was torn in two: the rule
the administrator wrote never matched, and a rule they never wrote
appeared from its tail. For "@Group Name:deny" that means the deny is
skipped and a later :rw entry can match instead -- an authorization
bypass for a member of the denied group.
conf_strtok() already implements the documented behaviour and the
daemon's gid field already uses it (clientserver.c); this consumer was
missed when that one was fixed.
Reported by Andres Berbescu. Refs #137.
(cherry picked from commit e7986502cb)
Route operator-supplied paths (--partial-dir, --backup-dir, alt/copy/link-dest,
--temp-dir, --files-from, --log-file, config and secrets files) and the sender's
own enumeration through the race-safe resolver and an ownership walk that refuses a
target redirected outside the module root. open_tmpfile() now creates the temp via
the cached held dir fd (do_mkstemp_atfd) so an in-tree dir symlink is followed
safely instead of refused. Adds --insecure-links to opt back into legacy following;
the daemon hard-refuses the client flag (use the "insecure links" module param).
The daemon picks the challenge-response auth digest from the client's
negotiation, or -- for a peer that sends no digest list (any rsync before
3.2.0, including the openrsync that ships with macOS) -- falls back to md5
(protocol >= 30) or md4. The negotiation is unauthenticated, so an on-path
attacker can also rewrite it to force md5/md4 between two modern peers. A
captured (challenge, response) pair is then far cheaper to brute-force
offline against a weak digest, recovering a guessable shared secret.
Add a per-module (or global) "auth digest = NAME" parameter. After the
digest is negotiated, auth_server() refuses the connection (before issuing
the challenge) when the negotiated digest is weaker than NAME, comparing by
position in the strongest-first valid_auth_checksums list. Because the
check is on the resolved digest, it also catches the md5/md4 fallback, so an
old or list-omitting client cannot slip under the floor. A floor naming a
digest this build lacks is fail-closed. Default off, preserving
compatibility with older clients.
Documented in rsyncd.conf(5) and SECURITY.md. The test covers the strong-
client accept, the unknown-floor fail-closed, and -- with a bundled old
static rsync -- the real md5-downgrade refusal (plus a no-floor control).
(cherry picked from commit 1ba7951c; backport drops the SECURITY.md policy
section, which is 3.5.0-specific, and the _test.py, which the stable harness
does not run.)
Route the daemon's operator-supplied path opens through
safe_open_no_attacker_symlinks() / a pinned parent dir so a local attacker
cannot plant a symlink at one and redirect the daemon's privileged
read/write: motd, --early-input, lock and --config paths
(clientserver/connection/params); the --password-file and daemon secrets
file, fstat'ing the opened fd (authenticate); and the pid-file parent dir.
Tests: daemon-config-symlink, early-input-symlink, daemon-secrets-file-symlink,
password-file-symlink, daemon-module-chdir-symlink.
- Size flist checksum data to hold the active size, not the max.
- Add a negotiated hash method to the daemon auth code.
- Use EVP for all openssl digests. This makes it easy to add more
openssl digest methods and avoids deprecation warnings.
- Support a way to re-enable deprecated digests via openssl conf
file and allow a default file to be configured.
- Supply a simple openssl-rsync.cnf file to enable legacy digests.
- All the memory-allocation macros now auto-check for failure and exit
with a failure message that incudes the caller's file and lineno
info. This includes strdup().
- Added the `--max-alloc=SIZE` option to be able to override the memory
allocator's sanity-check limit. It defaults to 1G (as before).
Fixes bugzilla bug 12769.
I replaced git-set-file-times with an improved version that I wrote
recently (in python3). A new script uses it to figure out the
last-modified year for each *.[ch] file and updates its copyright.
It also puts the latest year into the latest-year.h file for the
output of --version.
- Standardized the format of the opening comment, including adding a
brief description of what's in the file for those that lacked it.
- Added some missing copyright lines.
- Some minor whitespace tweaks (in a few of the files).
- Pass the hostname in to auth_server().
- Generate a unique error for each failure type in auth_server() so
that the log-file contains why the authorization failed.
- Don't use sscanf() to parse the client's auth-challenge response.