Share one ID counter for SFTP handles

- Merge fileIdCount and dirIdCount into a single handleIdCount.
- File and directory handle IDs now share one namespace.
- A close or other handle op cannot match the wrong resource type.
pull/1052/head
John Safranek 2026-06-10 12:02:26 -07:00 committed by Paul Adelsbach
parent dc4df8dfdf
commit 72b8e888d8
2 changed files with 47 additions and 38 deletions

View File

@ -2276,6 +2276,34 @@ int ff_pread(int fd, byte *buffer, int sz)
#endif /* WOLFSSH_FATFS */
#ifndef NO_WOLFSSH_SERVER
/* SFTP handle IDs are an opaque WOLFSSH_HANDLE_ID_SZ byte session value made
* up of two big-endian word32s. */
static void SFTP_HandleIdDecode(const byte* in, word32 id[2])
{
ato32(in, &id[0]);
ato32(in + UINT32_SZ, &id[1]);
}
static void SFTP_HandleIdEncode(const word32 id[2], byte* out)
{
c32toa(id[0], out);
c32toa(id[1], out + UINT32_SZ);
}
/* Take the next session handle ID and advance the shared counter. */
static void SFTP_HandleIdNext(WOLFSSH* ssh, word32 id[2])
{
id[0] = ssh->handleIdCount[0];
id[1] = ssh->handleIdCount[1];
AddAssign64(ssh->handleIdCount, 1);
}
#endif /* !NO_WOLFSSH_SERVER */
/* Handles packet to open a file
*
* returns WS_SUCCESS on success
@ -2442,9 +2470,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
if (ret == WS_SUCCESS) {
/* Generate unique file handle ID and add to tracking list */
id[0] = ssh->fileIdCount[0];
id[1] = ssh->fileIdCount[1];
AddAssign64(ssh->fileIdCount, 1);
SFTP_HandleIdNext(ssh, id);
if ((ret = SFTP_AddFileHandle(ssh, fd, dir, id)) != WS_SUCCESS) {
WLOG(WS_LOG_SFTP, "Unable to store handle");
@ -2469,8 +2495,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
}
if (ret == WS_SUCCESS) {
c32toa(id[0], idFlat);
c32toa(id[1], idFlat + UINT32_SZ);
SFTP_HandleIdEncode(id, idFlat);
if (SFTP_CreatePacket(ssh, WOLFSSH_FTP_HANDLE, out, outSz,
idFlat, sizeof(idFlat)) != WS_SUCCESS) {
ret = WS_FATAL_ERROR;
@ -2626,9 +2651,7 @@ cleanup:
if (ret == WS_SUCCESS) {
/* Generate unique file handle ID and add to tracking list */
id[0] = ssh->fileIdCount[0];
id[1] = ssh->fileIdCount[1];
AddAssign64(ssh->fileIdCount, 1);
SFTP_HandleIdNext(ssh, id);
if (SFTP_AddFileHandle(ssh, fileHandle, dir, id) != WS_SUCCESS) {
WLOG(WS_LOG_SFTP, "Unable to store handle");
@ -2653,8 +2676,7 @@ cleanup:
}
if (ret == WS_SUCCESS) {
c32toa(id[0], idFlat);
c32toa(id[1], idFlat + UINT32_SZ);
SFTP_HandleIdEncode(id, idFlat);
if (SFTP_CreatePacket(ssh, WOLFSSH_FTP_HANDLE, out, outSz,
idFlat, sizeof(idFlat)) != WS_SUCCESS) {
ret = WS_FATAL_ERROR;
@ -2731,7 +2753,6 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 outSz = WOLFSSH_HANDLE_ID_SZ + WOLFSSH_SFTP_HEADER + UINT32_SZ;
byte* out = NULL;
word32 id[2];
byte idFlat[WOLFSSH_HANDLE_ID_SZ];
char per[] = "Permission denied";
@ -2798,11 +2819,8 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
#else
cur->dir = ctx;
#endif
cur->id[0] = id[0] = ssh->dirIdCount[0];
cur->id[1] = id[1] = ssh->dirIdCount[1];
c32toa(id[0], idFlat);
c32toa(id[1], idFlat + UINT32_SZ);
AddAssign64(ssh->dirIdCount, 1);
SFTP_HandleIdNext(ssh, cur->id);
SFTP_HandleIdEncode(cur->id, idFlat);
cur->isEof = 0;
cur->next = ssh->dirList;
ssh->dirList = cur;
@ -2846,7 +2864,6 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 outSz = WOLFSSH_HANDLE_ID_SZ + WOLFSSH_SFTP_HEADER + UINT32_SZ;
byte* out = NULL;
word32 id[2];
byte idFlat[WOLFSSH_HANDLE_ID_SZ];
char name[MAX_PATH];
char clean[WOLFSSH_MAX_FILENAME];
@ -2957,11 +2974,8 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
return WS_MEMORY_E;
}
cur->dir = INVALID_HANDLE_VALUE;
cur->id[0] = id[0] = ssh->dirIdCount[0];
cur->id[1] = id[1] = ssh->dirIdCount[1];
c32toa(id[0], idFlat);
c32toa(id[1], idFlat + UINT32_SZ);
AddAssign64(ssh->dirIdCount, 1);
SFTP_HandleIdNext(ssh, cur->id);
SFTP_HandleIdEncode(cur->id, idFlat);
cur->isEof = 0;
cur->dirName = dirName; /* take over ownership of buffer */
cur->next = ssh->dirList;
@ -3925,8 +3939,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
/* find DIR given handle */
cur = ssh->dirList;
ato32(handle, &h[0]);
ato32(handle + UINT32_SZ, &h[1]);
SFTP_HandleIdDecode(handle, h);
while (cur != NULL) {
if (cur->id[0] == h[0] && cur->id[1] == h[1]) {
break;
@ -4152,8 +4165,7 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 handle[2] = {0, 0};
WS_FILE_LIST* fileEntry = NULL;
ato32(str, &handle[0]);
ato32(str + UINT32_SZ, &handle[1]);
SFTP_HandleIdDecode(str, handle);
fileEntry = SFTP_FindFileHandle(ssh, handle);
if (fileEntry == NULL) {
@ -4274,8 +4286,7 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 handle[2] = {0, 0};
WS_FILE_LIST* fileEntry = NULL;
ato32(str, &handle[0]);
ato32(str + UINT32_SZ, &handle[1]);
SFTP_HandleIdDecode(str, handle);
fileEntry = SFTP_FindFileHandle(ssh, handle);
if (fileEntry == NULL) {
@ -4375,8 +4386,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 handle[2] = {0, 0};
WS_FILE_LIST* fileEntry = NULL;
ato32(str, &handle[0]);
ato32(str + UINT32_SZ, &handle[1]);
SFTP_HandleIdDecode(str, handle);
/* Find the file handle in our tracking list */
fileEntry = SFTP_FindFileHandle(ssh, handle);
@ -4504,8 +4514,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 handle[2] = {0, 0};
WS_FILE_LIST* fileEntry = NULL;
ato32(str, &handle[0]);
ato32(str + UINT32_SZ, &handle[1]);
SFTP_HandleIdDecode(str, handle);
/* Find the file handle in our tracking list */
fileEntry = SFTP_FindFileHandle(ssh, handle);
@ -5696,8 +5705,7 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
WS_FILE_LIST* cur;
word32 handleId[2] = {0, 0};
ato32(handle, &handleId[0]);
ato32(handle + UINT32_SZ, &handleId[1]);
SFTP_HandleIdDecode(handle, handleId);
cur = SFTP_FindFileHandle(ssh, handleId);
if (cur == NULL) {
@ -6176,8 +6184,7 @@ int wolfSSH_SFTP_RecvFSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
word32 handle[2] = {0, 0};
WS_FILE_LIST* fileEntry = NULL;
ato32(str, &handle[0]);
ato32(str + UINT32_SZ, &handle[1]);
SFTP_HandleIdDecode(str, handle);
/* Find the file handle in our tracking list */
fileEntry = SFTP_FindFileHandle(ssh, handle);

View File

@ -927,9 +927,11 @@ struct WOLFSSH {
char* sftpDefaultPath;
#ifndef NO_WOLFSSH_DIR
WS_DIR_LIST* dirList;
word32 dirIdCount[2];
#endif
word32 fileIdCount[2];
/* Shared counter for both file and directory handle IDs. A single
* namespace guarantees IDs are unique across files and directories so a
* close request cannot match the wrong resource type. */
word32 handleIdCount[2];
WS_FILE_LIST* fileList;
struct WS_SFTP_RECV_INIT_STATE* recvInitState;
struct WS_SFTP_RECV_STATE* recvState;