diff --git a/src/nwconn.c b/src/nwconn.c index 56c5f34..93cf99b 100644 --- a/src/nwconn.c +++ b/src/nwconn.c @@ -43,6 +43,7 @@ #include "nwqconn.h" #include "namspace.h" #include "nwshare.h" +#include "nwdbm.h" #include "nwconn.h" #include "trustee.h" @@ -77,6 +78,77 @@ static char *prog_title; static int req_printed=0; + +static int scan_volume_user_disk_restrictions(uint8 volnr, uint32 sequence, + uint8 *response) +{ + struct XDATA { + uint8 entries; + struct { + uint8 id[4]; + uint8 restriction[4]; + } entry[12]; + } *xdata = (struct XDATA *)response; + int result = nw_get_volume_name(volnr, NULL, 0); + + if (result < 0) + return result; + + xdata->entries = 0; + +#if QUOTA_SUPPORT + { + NETOBJ obj; + uint32 last_obj_id = MAX_U32; + uint32 restricted_index = 0; + uint8 wild[] = "*"; + int scan_result; + + memset(&obj, 0, sizeof(obj)); + obj.type = 1; /* user */ + xstrcpy(obj.name, wild); + + scan_result = scan_for_obj(&obj, last_obj_id, 1); + while (!scan_result && xdata->entries < 12) { + uint8 more_segments = 0; + uint8 property_flags = 0; + char unix_user[128]; + uint32 restriction = 0x40000000; + uint32 inuse = 0; + + memset(unix_user, 0, sizeof(unix_user)); + if (!nw_get_prop_val_by_obj_id(obj.id, 1, + (uint8 *)"UNIX_USER", 9, + (uint8 *)unix_user, &more_segments, &property_flags)) { + struct passwd *pw; + + unix_user[sizeof(unix_user)-1] = '\0'; + pw = getpwnam(unix_user); + + if (pw && !nw_get_vol_restrictions(volnr, pw->pw_uid, + &restriction, &inuse) && + restriction < 0x40000000) { + if (restricted_index >= sequence) { + U32_TO_BE32(obj.id, xdata->entry[xdata->entries].id); + U32_TO_BE32(restriction, xdata->entry[xdata->entries].restriction); + xdata->entries++; + } + restricted_index++; + } + } + + last_obj_id = obj.id; + memset(&obj, 0, sizeof(obj)); + obj.type = 1; + xstrcpy(obj.name, wild); + scan_result = scan_for_obj(&obj, last_obj_id, 1); + } + } +#endif + + return 1 + (8 * xdata->entries); +} + static int trustee_v3_to_ncp22_rights(int rights) { int ncp22 = 0; @@ -1215,21 +1287,32 @@ static int handle_ncp_serv(void) } break; - case 0x20 : { /* scan volume user disk restrictions */ + case 0x20 : { /* Scan Volume's User Disk Restrictions */ + /* + * NCP 0x2222/22/32 Scan Volume's User Disk Restrictions. + * + * WebSDK / headers: + * Request: Volume Number, Sequence. Sequence starts at + * zero and is incremented by the number of entries returned + * by previous calls. + * Reply: Number Of Entries followed by up to twelve + * Object ID / Restriction pairs. Restrictions are reported + * in 4K blocks. + * + * The Rust nwserver and lwared implementations both return + * an empty list after validating the volume. MARS-NWE keeps + * that SDK-compatible unrestricted result for non-quota + * builds, and fills entries from the existing Linux quota + * backend when QUOTA_SUPPORT is enabled and a restricted + * bindery user maps to a Unix uid. + */ uint8 volnr = *(p+1); - /* uint32 sequence = GET_BE32(p+2); */ - struct XDATA { - uint8 entries; /* 0x0 */ - /*--- per entry (max.entries = 12) ----*/ - uint8 id[4]; - uint8 restriction[4]; - } *xdata = (struct XDATA*) responsedata; - int result = nw_get_volume_name(volnr, NULL, 0); - if (result > -1) { - xdata->entries = 0x0; - data_len = (8 * xdata->entries) + 1; - } else completition = (uint8) (-result); - } + uint32 sequence = GET_BE32(p+2); + int result = scan_volume_user_disk_restrictions( + volnr, sequence, responsedata); + if (result > -1) data_len = result; + else completition = (uint8) (-result); + } break; case 0x21 : { /* change Vol restrictions for Obj */