fix(p7-privilege): harden copy-as/super gates, own dirs/specials

- fake-super owner replay honors --no-super and an active --copy-as
- copy-as/identity ownership now applied to directories and special nodes
- reject copy_as_set && !use_metadata (receiver + client --no-preserve)
- daemon refuses --copy-as; add server-side --no-super operator veto
- implement identity_copy_as_refused/identity_copy_as_active
- reject copy-as ids that overflow int32; escape spec in log errors
- copy-as chown EPERM/EACCES logged at ERROR (still non-fatal)
- identity_wire_valid copy-as bounds; CLI help and RSYNC_COMPAT docs
- add unit tests and root-gated integration coverage
This commit is contained in:
2026-09-12 12:34:43 +02:00
parent e6a65d0980
commit fdc0f238c9
18 changed files with 500 additions and 34 deletions
+20
View File
@@ -31,9 +31,28 @@ static void test_server_cli_defaults() {
EXPECT_EQ_INT(opts.bind_family, AF_UNSPEC);
EXPECT_FALSE(opts.allow_delete);
EXPECT_FALSE(opts.allow_unauthenticated);
EXPECT_FALSE(opts.no_super);
server_cli_options_free(&opts);
}
/* --no-super is a standalone/SSH operator veto (does not require --daemon):
it forces SUPER_MODE_OFF for every connection and refuses client --copy-as. */
static void test_server_cli_no_super() {
const char* args[] = {"fastsync-server", "--no-super", "--destination-root", "/srv"};
ServerCliOptions opts;
EXPECT_EQ_INT(parse_ok(args, 4, &opts), 0);
EXPECT_TRUE(opts.no_super);
EXPECT_EQ_STR(opts.destination_root, "/srv");
server_cli_options_free(&opts);
const char* args2[] = {"fastsync-server", "--daemon", "--config=/tmp/x.conf", "--no-super"};
ServerCliOptions opts2;
EXPECT_EQ_INT(parse_ok(args2, 4, &opts2), 0);
EXPECT_TRUE(opts2.no_super);
EXPECT_TRUE(opts2.daemon_mode);
server_cli_options_free(&opts2);
}
static void test_server_cli_daemon_flags() {
const char* args[] = {"fastsync-server", "--daemon", "--no-detach", "--allow-unauthenticated"};
ServerCliOptions opts;
@@ -197,5 +216,6 @@ void test_server_cli() {
test_server_cli_invalid();
test_server_cli_password_and_early_input();
test_server_cli_password_requires_daemon();
test_server_cli_no_super();
test_server_cli_help();
}