nwconn: gate AFP metadata writes with Modify rights
All checks were successful
Source release / source-package (push) Successful in 54s

AFP Set File Information intentionally stores some Apple-specific metadata in mars_nwe-owned xattrs because FinderInfo and the narrow Invisible/System AFP bits do not have a complete NetWare-side representation yet.  Those xattrs are storage details, however, and should not let the AFP adapter bypass the same NetWare policy that protects ordinary metadata changes.

Add a small Modify-rights gate for AFP-specific metadata writes after the path-backed request has been resolved to a mars_nwe volume and Unix node.  The check uses the existing trustee/effective-rights helper with TRUSTEE_M before writing FinderInfo or AFP-only attribute xattrs.  Archive remains routed through the NetWare FILE_ATTR_A attribute helper, and Modify timestamp remains routed through nw_utime_node(), so their existing mars_nwe policy paths are unchanged.

This keeps the WebSDK/NWAFP Set File Information handler as an Apple-facing adapter over existing mars_nwe access control rather than a parallel metadata writer.  It also documents the convergence rule in TODO.md so later Create, Rename, and Delete work can continue to prefer existing NetWare helpers or thin wrappers over duplicated AFP-local file server logic.

Tests: git diff --check

TODO: add non-SUPERVISOR negative smoke coverage for missing Modify rights once a stable low-privilege test user and trustee setup are available.
This commit is contained in:
OpenAI
2026-05-30 14:56:54 +00:00
committed by Mario Fetka
parent e899704677
commit dacfc0f7a1
3 changed files with 53 additions and 3 deletions

19
TODO.md
View File

@@ -406,9 +406,9 @@ Refactor/wrapper follow-up:
reusing existing mars_nwe volume, namespace, and directory-handle helpers.
- Route all AFP writes through existing mars_nwe policy checks before changing
metadata. Archive and Modify timestamp already do this through NetWare
helpers; FinderInfo and AFP-only Invisible/System xattr writes still need an
explicit Modify-rights gate using the same trustee/effective-rights policy as
normal NetWare metadata writes.
helpers. FinderInfo and AFP-only Invisible/System xattr writes are now gated
by the same trustee/effective-rights Modify policy before the AFP metadata
xattrs are updated.
- Continue moving AFP-visible NetWare attributes onto the existing NetWare
attribute store. Archive is already mapped to `FILE_ATTR_A`; ReadOnly,
Hidden, System, ExecuteOnly, and Shareable still need either a real mapping
@@ -428,6 +428,19 @@ Refactor/wrapper follow-up:
Entry ID/CNID index or an existing canonical path lookup once the entry-id
backend grows beyond xattr/stat-derived compatibility IDs.
AFP Set File Information metadata-rights convergence:
- AFP FinderInfo writes and AFP-only Invisible/System attribute xattr writes no
longer bypass NetWare policy just because their storage is AFP-specific.
`afp_set_file_information()` now checks the resolved file through the existing
trustee/effective-rights Modify policy before writing `org.mars-nwe.afp.*`
metadata.
- Archive continues to route through the NetWare attribute helper (`FILE_ATTR_A`),
and Modify timestamp continues to route through `nw_utime_node()`. The new
check only covers metadata that has to remain AFP-specific, keeping AFP as an
Apple-facing adapter over mars_nwe policy rather than a parallel file server.
Endpoint order:
- First finish the non-destructive convergence work above.

View File

@@ -1305,6 +1305,20 @@ static int afp_set_netware_archive_attribute(int volume, char *unixname,
return(set_nw_attrib_word(volume, unixname, stb, (int)(nw_attrs & 0xffff)));
}
static int afp_check_metadata_modify_rights(int volume, char *unixname,
struct stat *stb,
const char *call_name,
uint8 *path, int path_len)
{
if (!unixname || !stb) return(-0x9c);
if (tru_eff_rights_exists(volume, (uint8 *)unixname, stb, TRUSTEE_M)) {
XDPRINTF((2,0, "%s rejected: no Modify rights for AFP metadata path='%s'",
call_name, visable_data(path, path_len)));
return(-0x8c); /* no modify rights */
}
return(0);
}
static int afp_set_file_information(uint8 *afp_req, int afp_len,
const char *call_name)
/*
@@ -1333,6 +1347,7 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
int result;
uint16 log_attrs = 0;
time_t log_mtime = (time_t)-1;
int needs_afp_metadata_modify = 0;
if (afp_len < 9) {
XDPRINTF((2,0, "%s rejected: short request len=%d",
@@ -1390,6 +1405,8 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
call_name, requested_attrs, visable_data(afp_req + 9, path_len)));
return(-0x9c);
}
if (requested_bits & AFP_ATTR_XATTR_MASK)
needs_afp_metadata_modify = 1;
data_off += 2;
}
if ((request_mask & AFP_FILE_BITMAP_MODIFY_DATE) && afp_len < data_off + 4) {
@@ -1400,6 +1417,8 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
if (request_mask & AFP_FILE_BITMAP_MODIFY_DATE)
data_off += 4;
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) && data_off & 1) data_off++;
if (request_mask & AFP_FILE_BITMAP_FINDER_INFO)
needs_afp_metadata_modify = 1;
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) &&
afp_len < data_off + NWATALK_FINDER_INFO_LEN) {
XDPRINTF((2,0, "%s rejected: short FinderInfo data len=%d data_off=%d",
@@ -1429,6 +1448,13 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
return(-0x9c);
}
if (needs_afp_metadata_modify) {
result = afp_check_metadata_modify_rights(path_volume, unixname, &stbuff,
call_name, afp_req + 9, path_len);
if (result < 0)
return(result);
}
data_off = 9 + path_len;
if (data_off & 1) data_off++;
if (request_mask & AFP_FILE_BITMAP_ATTRIBUTES) {

View File

@@ -87,6 +87,17 @@ collected separately. Use `--stop-on-failure` for strict bisect-style runs; by
default the script keeps going so one failing endpoint does not hide later AFP
output from the report.
AFP metadata writes and NetWare Modify rights:
FinderInfo and AFP-only attribute metadata are stored in `org.mars-nwe.afp.*`
xattrs, but those writes are still file metadata changes. The Set File
Information handler now resolves the target through the normal mars_nwe path and
checks the existing NetWare Modify trustee policy before updating FinderInfo or
AFP-only Invisible/System metadata. Archive uses the existing NetWare attribute
path, and Modify timestamp uses `nw_utime_node()`, so the smoke suite should
continue to pass for SUPERVISOR while non-supervisor negative coverage can later
exercise the same policy gate.
A verified suite run after the FinderInfo payload-alignment fix completed with
`failures=0` for `SYS:PUBLIC/pmdflts.ini`. The report covered Entry ID by path,
Entry ID from NetWare handle, Get File Information, Scan File Information,