feat(p7-super): implement --super/--no-super safe-subset privilege gate (protocol 2.18.0)
Add the receiver-side --super / --no-super tri-state (Config->super_mode) under the safe-subset + clear-refusal privilege model: FastSync never elevates privileges, it only permits super-user attempts that are already confined fd-relative below the authorized receive root. - identity: privilege_super_permitted() gate (OFF=false, ON=true, AUTO follows geteuid()==0); identity_apply_ownership/_link become no-ops when not permitted; --super with no explicit identity policy implies raw numeric-id preservation (explicit usermap/groupmap/chown/numeric-ids still win); warn exactly once when --super is requested by a non-root receiver. - file_receive: gate char/block device-node creation on the gate; FIFO/socket handling is unchanged. - wire: trailing super_mode int after the --iconv spec, validated 0..2 in receive_privilege_options and validate_received_config; PROTOCOL_VERSION 2.17.0 -> 2.18.0; version-sensitive tests and docs updated. - CLI: --super/--no-super parsed explicitly before the generic --no-* branch (malformed --super=x rejected); usage text added. - tests: config wire round-trip + invalid-value rejection, privilege-gate mode unit test, CLI parse test, integration transfer + root-gated ownership suppression/appliance tests. - docs: RSYNC_COMPAT --super row + Wave E note, protocol mentions, README.
This commit is contained in:
@@ -94,14 +94,14 @@ def _seed_protocol_source(source):
|
||||
class TestProtocol:
|
||||
@pytest.mark.ci
|
||||
def test_protocol_current_version_accepted(self, shared_server):
|
||||
"""--protocol=2.17.0 (the current PROTOCOL_VERSION) is accepted and the
|
||||
"""--protocol=2.18.0 (the current PROTOCOL_VERSION) is accepted and the
|
||||
transfer completes normally."""
|
||||
source = os.path.join(TEST_DATA_DIR, "proto_ok_src")
|
||||
dest = os.path.join(TEST_DATA_DIR, "proto_ok_dst")
|
||||
shutil.rmtree(dest, ignore_errors=True)
|
||||
os.makedirs(dest)
|
||||
_seed_protocol_source(source)
|
||||
result, _ = run_client(source, dest, flags=["--protocol=2.17.0"],
|
||||
result, _ = run_client(source, dest, flags=["--protocol=2.18.0"],
|
||||
port=shared_server.port)
|
||||
assert result.returncode == 0, \
|
||||
f"--protocol current run failed: {(result.stderr or result.stdout)[:400]}"
|
||||
@@ -118,7 +118,7 @@ class TestProtocol:
|
||||
shutil.rmtree(dest, ignore_errors=True)
|
||||
os.makedirs(dest)
|
||||
_seed_protocol_source(source)
|
||||
for bad in ("2.15.0", "2.16.0", "216", "31"):
|
||||
for bad in ("2.17.0", "2.15.0", "2.16.0", "216", "31"):
|
||||
result, _ = run_client(source, dest, flags=[f"--protocol={bad}"],
|
||||
port=shared_server.port)
|
||||
assert result.returncode != 0, f"--protocol={bad} should be rejected"
|
||||
|
||||
Reference in New Issue
Block a user