nwconn: require WebSDK AFP set file information layout
All checks were successful
Source release / source-package (push) Successful in 48s
All checks were successful
Source release / source-package (push) Successful in 48s
This commit is contained in:
112
src/nwconn.c
112
src/nwconn.c
@@ -1992,20 +1992,17 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
/*
|
||||
* Conservative AFP Set File Information subset.
|
||||
*
|
||||
* Keep accepting the older mars_nwe smoke payload where the path immediately
|
||||
* follows the request bitmap and only the selected data fields are appended
|
||||
* after the path. In addition, accept the Novell/WebSDK fixed record layout
|
||||
* used by real AFP clients: Attributes/Date/FinderInfo fields live at fixed
|
||||
* offsets and the path is at offset 55 for 0x09 or 61 for 0x10 (including the
|
||||
* AFP subfunction byte). All NetWare semantics still route through existing
|
||||
* mars_nwe helpers; only genuine AFP metadata stays in nwatalk xattrs.
|
||||
* Accept only the Novell/WebSDK fixed record layout used by real AFP clients:
|
||||
* Attributes/Date/FinderInfo fields live at fixed offsets and the path is at
|
||||
* offset 55 for 0x09 or 61 for 0x10 (including the AFP subfunction byte). All
|
||||
* NetWare semantics still route through existing mars_nwe helpers; only genuine
|
||||
* AFP metadata stays in nwatalk xattrs.
|
||||
*/
|
||||
{
|
||||
uint8 volume_number;
|
||||
uint32 request_entry_id;
|
||||
uint16 request_mask;
|
||||
int is_afp20;
|
||||
int use_websdk_layout = 0;
|
||||
int path_len;
|
||||
int path_off;
|
||||
int path_volume;
|
||||
@@ -2023,7 +2020,6 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
uint8 *modify_data = NULL;
|
||||
uint8 *backup_data = NULL;
|
||||
uint8 *finder_data = NULL;
|
||||
int data_off;
|
||||
|
||||
if (afp_len < 9) {
|
||||
XDPRINTF((2,0, "%s rejected: short request len=%d",
|
||||
@@ -2040,94 +2036,31 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
* WebSDK fixed layout, including afp_req[0] subfunction byte:
|
||||
* 0x09: path_len @ 54, path @ 55
|
||||
* 0x10: path_len @ 60, path @ 61, ProDOSInfo @ 54..59
|
||||
* Prefer it only when the documented path-length slot is plausible; older
|
||||
* mars_nwe tests keep using the compact path-at-8 form below.
|
||||
*/
|
||||
{
|
||||
int websdk_path_len_off = is_afp20 ? 60 : 54;
|
||||
int websdk_path_off = websdk_path_len_off + 1;
|
||||
|
||||
if (afp_len > websdk_path_len_off) {
|
||||
int candidate_len = (int)afp_req[websdk_path_len_off];
|
||||
if (candidate_len > 0 && afp_len >= websdk_path_off + candidate_len) {
|
||||
use_websdk_layout = 1;
|
||||
path_len = candidate_len;
|
||||
path_off = websdk_path_off;
|
||||
attribute_data = afp_req + 8;
|
||||
create_data = afp_req + 10;
|
||||
access_data = afp_req + 12;
|
||||
modify_data = afp_req + 14;
|
||||
backup_data = afp_req + 18;
|
||||
finder_data = afp_req + 22;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!use_websdk_layout) {
|
||||
path_len = (int)afp_req[8];
|
||||
path_off = 9;
|
||||
if (path_len < 0 || afp_len < path_off + path_len) {
|
||||
XDPRINTF((2,0, "%s rejected: boundary check len=%d path_len=%d",
|
||||
call_name, afp_len, path_len));
|
||||
if (afp_len <= websdk_path_len_off) {
|
||||
XDPRINTF((2,0, "%s rejected: short WebSDK request len=%d path_len_off=%d",
|
||||
call_name, afp_len, websdk_path_len_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
|
||||
data_off = path_off + path_len;
|
||||
if (data_off & 1) data_off++;
|
||||
if (request_mask & AFP_FILE_BITMAP_ATTRIBUTES) {
|
||||
if (afp_len < data_off + 2) {
|
||||
XDPRINTF((2,0, "%s rejected: short attribute data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
attribute_data = afp_req + data_off;
|
||||
data_off += 2;
|
||||
}
|
||||
if (request_mask & AFP_FILE_BITMAP_ACCESS_DATE) {
|
||||
if (afp_len < data_off + 4) {
|
||||
XDPRINTF((2,0, "%s rejected: short access timestamp data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
access_data = afp_req + data_off;
|
||||
data_off += 4;
|
||||
}
|
||||
if (request_mask & AFP_FILE_BITMAP_CREATE_DATE) {
|
||||
if (afp_len < data_off + 4) {
|
||||
XDPRINTF((2,0, "%s rejected: short create timestamp data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
create_data = afp_req + data_off;
|
||||
data_off += 4;
|
||||
}
|
||||
if (request_mask & AFP_FILE_BITMAP_MODIFY_DATE) {
|
||||
if (afp_len < data_off + 4) {
|
||||
XDPRINTF((2,0, "%s rejected: short modify timestamp data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
modify_data = afp_req + data_off;
|
||||
data_off += 4;
|
||||
}
|
||||
if (request_mask & AFP_FILE_BITMAP_BACKUP_DATE) {
|
||||
if (afp_len < data_off + 4) {
|
||||
XDPRINTF((2,0, "%s rejected: short backup timestamp data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
backup_data = afp_req + data_off;
|
||||
data_off += 4;
|
||||
}
|
||||
if ((request_mask & AFP_FILE_BITMAP_FINDER_INFO) && data_off & 1) data_off++;
|
||||
if (request_mask & AFP_FILE_BITMAP_FINDER_INFO) {
|
||||
if (afp_len < data_off + NWATALK_FINDER_INFO_LEN) {
|
||||
XDPRINTF((2,0, "%s rejected: short FinderInfo data len=%d data_off=%d",
|
||||
call_name, afp_len, data_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
finder_data = afp_req + data_off;
|
||||
path_len = (int)afp_req[websdk_path_len_off];
|
||||
path_off = websdk_path_off;
|
||||
if (path_len < 0 || afp_len < path_off + path_len) {
|
||||
XDPRINTF((2,0, "%s rejected: WebSDK boundary check len=%d path_len=%d path_off=%d",
|
||||
call_name, afp_len, path_len, path_off));
|
||||
return(-0x7e);
|
||||
}
|
||||
|
||||
attribute_data = afp_req + 8;
|
||||
create_data = afp_req + 10;
|
||||
access_data = afp_req + 12;
|
||||
modify_data = afp_req + 14;
|
||||
backup_data = afp_req + 18;
|
||||
finder_data = afp_req + 22;
|
||||
}
|
||||
|
||||
path_data = afp_req + path_off;
|
||||
@@ -2271,10 +2204,9 @@ static int afp_set_file_information(uint8 *afp_req, int afp_len,
|
||||
return(result);
|
||||
}
|
||||
|
||||
XDPRINTF((3,0, "%s: vol=%d request_vol=%d entry=0x%08x mask=0x%04x path='%s' layout=%s%s%s%s%s%s attrs=0x%04x atime=%ld mtime=%ld",
|
||||
XDPRINTF((3,0, "%s: vol=%d request_vol=%d entry=0x%08x mask=0x%04x path='%s' layout=websdk%s%s%s%s%s%s attrs=0x%04x atime=%ld mtime=%ld",
|
||||
call_name, path_volume, (int)volume_number, request_entry_id,
|
||||
request_mask, visable_data(path_data, path_len),
|
||||
use_websdk_layout ? "websdk" : "compact",
|
||||
(request_mask & AFP_FILE_BITMAP_ATTRIBUTES) ? " attributes" : "",
|
||||
(request_mask & AFP_FILE_BITMAP_ACCESS_DATE) ? " access_time" : "",
|
||||
(request_mask & AFP_FILE_BITMAP_CREATE_DATE) ? " create_time" : "",
|
||||
|
||||
@@ -41,7 +41,7 @@
|
||||
static void usage(const char *prog)
|
||||
{
|
||||
fprintf(stderr,
|
||||
"Usage: %s [--afp09|--afp20] [--websdk-layout] [--expect-completion CODE] [--allow-invalid-namespace] [--allow-invalid-path] "
|
||||
"Usage: %s [--afp09|--afp20] [--expect-completion CODE] [--allow-invalid-namespace] [--allow-invalid-path] "
|
||||
"[--volume N] [--entry-id ID] [--type FOUR] [--creator FOUR] "
|
||||
"[--hidden|--clear-hidden|--invisible|--clear-invisible|--system|--clear-system|--archive|--clear-archive] "
|
||||
"[--access-time-epoch SECONDS] [--create-time-epoch SECONDS] [--mtime-epoch SECONDS] [--backup-time-epoch SECONDS] [--finder-info-only|--attributes-only|--access-time-only|--create-time-only|--timestamp-only|--backup-time-only] "
|
||||
@@ -168,7 +168,6 @@ int main(int argc, char **argv)
|
||||
int allow_invalid_namespace = 0;
|
||||
int allow_invalid_path = 0;
|
||||
int expect_completion = -1;
|
||||
int websdk_layout = 0;
|
||||
uint32_t volume_number = 0;
|
||||
uint32_t entry_id = 0;
|
||||
uint8_t finder_info[32];
|
||||
@@ -188,7 +187,6 @@ int main(int argc, char **argv)
|
||||
uint8_t verify_buf[AFP_REPLY_LEN];
|
||||
uint8_t request[1 + 4 + 2 + 1 + 255 + 1 + 2 + 4 + 4 + 4 + 4 + 1 + 32];
|
||||
size_t path_len;
|
||||
size_t afp_data_off;
|
||||
size_t data_off;
|
||||
int i;
|
||||
NWCCODE err;
|
||||
@@ -218,8 +216,6 @@ int main(int argc, char **argv)
|
||||
set_subfunction = AFP_SET_FILE_INFORMATION;
|
||||
} else if (!strcmp(argv[i], "--afp20")) {
|
||||
set_subfunction = AFP20_SET_FILE_INFORMATION;
|
||||
} else if (!strcmp(argv[i], "--websdk-layout")) {
|
||||
websdk_layout = 1;
|
||||
} else if (!strcmp(argv[i], "--expect-completion")) {
|
||||
uint32_t completion;
|
||||
if (++i >= argc || parse_u32(argv[i], &completion) || completion > 255) {
|
||||
@@ -392,12 +388,12 @@ int main(int argc, char **argv)
|
||||
return 2;
|
||||
}
|
||||
|
||||
if (websdk_layout) {
|
||||
{
|
||||
size_t path_len_off;
|
||||
size_t path_off;
|
||||
|
||||
/*
|
||||
* WebSDK/nwafp.h fixed SetInfo layout, in the payload passed to
|
||||
* Novell/WebSDK nwafp.h fixed SetInfo layout, in the payload passed to
|
||||
* NWRequestSimple() without the leading AFP subfunction byte:
|
||||
* 0x09: path_len @ 53, path @ 54
|
||||
* 0x10: ProDOSInfo @ 53..58, path_len @ 59, path @ 60
|
||||
@@ -423,49 +419,6 @@ int main(int argc, char **argv)
|
||||
request[path_len_off] = (uint8_t)path_len;
|
||||
memcpy(request + path_off, path, path_len);
|
||||
data_off = path_off + path_len;
|
||||
} else {
|
||||
request[7] = (uint8_t)path_len;
|
||||
memcpy(request + 8, path, path_len);
|
||||
/*
|
||||
* The server-side AFP request buffer includes the NCP AFP subfunction byte
|
||||
* at offset 0. This smoke helper passes only the subfunction payload to
|
||||
* NWRequestSimple(), so every server offset after the leading function byte
|
||||
* maps to request_offset - 1 here. Align once in AFP/server coordinates,
|
||||
* then subtract one; do not align the payload offset again or FinderInfo-only
|
||||
* requests with an even path length get a leading zero byte persisted.
|
||||
*/
|
||||
afp_data_off = 1 + 8 + path_len;
|
||||
if (afp_data_off & 1)
|
||||
afp_data_off++;
|
||||
data_off = afp_data_off - 1;
|
||||
if (request_mask & AFP_ATTRIBUTES_MASK) {
|
||||
cpu_to_be16(attr_request, request + data_off);
|
||||
data_off += 2;
|
||||
}
|
||||
if (request_mask & AFP_ACCESS_DATE_MASK) {
|
||||
memcpy(request + data_off, access_time, sizeof(access_time));
|
||||
data_off += sizeof(access_time);
|
||||
}
|
||||
if (request_mask & AFP_CREATE_DATE_MASK) {
|
||||
memcpy(request + data_off, create_time, sizeof(create_time));
|
||||
data_off += sizeof(create_time);
|
||||
}
|
||||
if (request_mask & AFP_MODIFY_DATE_MASK) {
|
||||
memcpy(request + data_off, modify_time, sizeof(modify_time));
|
||||
data_off += sizeof(modify_time);
|
||||
}
|
||||
if (request_mask & AFP_BACKUP_DATE_MASK) {
|
||||
memcpy(request + data_off, backup_time, sizeof(backup_time));
|
||||
data_off += sizeof(backup_time);
|
||||
}
|
||||
if ((request_mask & AFP_FINDER_INFO_MASK) &&
|
||||
(request_mask & (AFP_ATTRIBUTES_MASK | AFP_ACCESS_DATE_MASK | AFP_CREATE_DATE_MASK | AFP_MODIFY_DATE_MASK | AFP_BACKUP_DATE_MASK)) &&
|
||||
((data_off + 1) & 1))
|
||||
data_off++;
|
||||
if (request_mask & AFP_FINDER_INFO_MASK) {
|
||||
memcpy(request + data_off, finder_info, sizeof(finder_info));
|
||||
data_off += sizeof(finder_info);
|
||||
}
|
||||
}
|
||||
|
||||
err = NWRequestSimple(conn,
|
||||
@@ -572,8 +525,8 @@ int main(int argc, char **argv)
|
||||
return 1;
|
||||
}
|
||||
|
||||
printf("AFP Set File Info subfunction=0x%02x layout=%s path=%s bitmap=0x%04x attrs=0x%04x create=0x%04x access=0x%04x modify=0x%04x%04x backup=0x%04x%04x finder_type=%.4s finder_creator=%.4s entry_id=0x%08x verified\n",
|
||||
set_subfunction, websdk_layout ? "websdk" : "compact", path, request_mask, be16_to_cpu(verify_buf + 8),
|
||||
printf("AFP Set File Info subfunction=0x%02x layout=websdk path=%s bitmap=0x%04x attrs=0x%04x create=0x%04x access=0x%04x modify=0x%04x%04x backup=0x%04x%04x finder_type=%.4s finder_creator=%.4s entry_id=0x%08x verified\n",
|
||||
set_subfunction, path, request_mask, be16_to_cpu(verify_buf + 8),
|
||||
be16_to_cpu(verify_buf + 20), be16_to_cpu(verify_buf + 22),
|
||||
be16_to_cpu(verify_buf + 24), be16_to_cpu(verify_buf + 26),
|
||||
be16_to_cpu(verify_buf + 28), be16_to_cpu(verify_buf + 30),
|
||||
|
||||
@@ -601,30 +601,6 @@ run_cmd \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--afp09 --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information FinderInfo WebSDK layout" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --websdk-layout --finder-info-only --type '$FINDER_TYPE' --creator '$FINDER_CREATOR' '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--websdk-layout --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information FinderInfo WebSDK legacy" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --afp09 --websdk-layout --finder-info-only --type '$FINDER_TYPE' --creator '$FINDER_CREATOR' '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--afp09 --websdk-layout --finder-info-only --type "$FINDER_TYPE" --creator "$FINDER_CREATOR" "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information Hidden WebSDK layout" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --websdk-layout --attributes-only --hidden '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--websdk-layout --attributes-only --hidden "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information Clear Hidden WebSDK layout" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --websdk-layout --attributes-only --clear-hidden '$NETWARE_PATH'" \
|
||||
"$SCRIPT_DIR/afp_set_file_info_smoke" -S "$SERVER" -U "$USER_NAME" -P "$PASSWORD" \
|
||||
--websdk-layout --attributes-only --clear-hidden "$NETWARE_PATH"
|
||||
|
||||
run_cmd \
|
||||
"AFP Set File Information Hidden" \
|
||||
"./afp_set_file_info_smoke $COMMON_PRINT --attributes-only --hidden '$NETWARE_PATH'" \
|
||||
|
||||
Reference in New Issue
Block a user