Skip to content

Commit 5e42db6

Browse files
committed
sftp: check the request ID on every client reply
SFTP_CheckReqId() matches each reply header against the outstanding request ID, advances the ID once on a match, and sets WS_SFTP_BAD_REQ_ID on a mismatch. Every client response handler calls it before acting on the reply, including the STATUS-only ones. - DoName and GetHandle set WS_SFTP_BAD_REQ_TYPE on an unexpected reply type and free their state - SetSTAT, Close, Remove and RMDIR now check the reply ID - correct the WS_SFTP_BAD_REQ_TYPE comment in error.h - test each request against a matched, misnumbered and mistyped reply Issue: F-10547, F-13909, F-10566
1 parent 4b05c4e commit 5e42db6

3 files changed

Lines changed: 226 additions & 63 deletions

File tree

‎src/wolfsftp.c‎

Lines changed: 65 additions & 61 deletions
Original file line numberDiff line numberDiff line change
@@ -375,7 +375,6 @@ enum WS_SFTP_GET_HANDLE_STATE_ID {
375375
STATE_GET_HANDLE_INIT,
376376
STATE_GET_HANDLE_GET_HEADER,
377377
STATE_GET_HANDLE_DO_STATUS,
378-
STATE_GET_HANDLE_CHECK_REQ_ID,
379378
STATE_GET_HANDLE_READ,
380379
STATE_GET_HANDLE_CLEANUP
381380
};
@@ -6969,9 +6968,27 @@ int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz)
69696968
}
69706969

69716970

6971+
/* Check that a response answers the outstanding request. A match advances
6972+
* the request ID for the next request; a mismatch sets WS_SFTP_BAD_REQ_ID.
6973+
*
6974+
* returns WS_SUCCESS on a match
6975+
*/
6976+
static int SFTP_CheckReqId(WOLFSSH* ssh, word32 reqId)
6977+
{
6978+
if (reqId != ssh->reqId) {
6979+
WLOG(WS_LOG_SFTP, "Unexpected request ID %u, expected %u",
6980+
reqId, ssh->reqId);
6981+
ssh->error = WS_SFTP_BAD_REQ_ID;
6982+
return WS_FATAL_ERROR;
6983+
}
6984+
ssh->reqId++;
6985+
return WS_SUCCESS;
6986+
}
6987+
6988+
69726989
/* process a status packet
69736990
*
6974-
* assuming that request ID has already been read
6991+
* assuming that request ID has already been read and checked
69756992
*
69766993
* structure of status packet is as follows
69776994
* {
@@ -7361,24 +7378,22 @@ static WS_SFTPNAME* wolfSSH_SFTP_DoName(WOLFSSH* ssh)
73617378
return NULL;
73627379
}
73637380

7364-
if (reqId != ssh->reqId) {
7365-
WLOG(WS_LOG_SFTP, "unexpected ID");
7381+
if (SFTP_CheckReqId(ssh, reqId) != WS_SUCCESS) {
7382+
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
73667383
return NULL;
73677384
}
73687385

7369-
if (type != WOLFSSH_FTP_NAME) {
7370-
WLOG(WS_LOG_SFTP, "Unexpected packet type %d", type);
7371-
/* check for status msg */
7372-
if (type == WOLFSSH_FTP_STATUS) {
7373-
state->state = SFTP_NAME_DO_STATUS;
7374-
}
7375-
else {
7376-
return NULL;
7377-
}
7386+
if (type == WOLFSSH_FTP_NAME) {
7387+
state->state = SFTP_NAME_GET_PACKET;
7388+
}
7389+
else if (type == WOLFSSH_FTP_STATUS) {
7390+
state->state = SFTP_NAME_DO_STATUS;
73787391
}
73797392
else {
7380-
ssh->reqId += 1;
7381-
state->state = SFTP_NAME_GET_PACKET;
7393+
WLOG(WS_LOG_SFTP, "Unexpected packet type %d", type);
7394+
ssh->error = WS_SFTP_BAD_REQ_TYPE;
7395+
wolfSSH_SFTP_ClearState(ssh, STATE_ID_NAME);
7396+
return NULL;
73827397
}
73837398

73847399
if (wolfSSH_SFTP_buffer_create(ssh, &state->buffer, maxSz) !=
@@ -7597,6 +7612,12 @@ static int wolfSSH_SFTP_GetHandle(WOLFSSH* ssh, byte* handle, word32* handleSz)
75977612
}
75987613
}
75997614

7615+
if (SFTP_CheckReqId(ssh, handleState->reqId) != WS_SUCCESS) {
7616+
handleState->state = STATE_GET_HANDLE_CLEANUP;
7617+
ret = WS_FATAL_ERROR;
7618+
continue;
7619+
}
7620+
76007621
if (wolfSSH_SFTP_buffer_create(ssh, &handleState->buffer, ret) !=
76017622
WS_SUCCESS) {
76027623
handleState->state = STATE_GET_HANDLE_CLEANUP;
@@ -7605,13 +7626,14 @@ static int wolfSSH_SFTP_GetHandle(WOLFSSH* ssh, byte* handle, word32* handleSz)
76057626
}
76067627

76077628
if (type == WOLFSSH_FTP_HANDLE)
7608-
handleState->state = STATE_GET_HANDLE_CHECK_REQ_ID;
7629+
handleState->state = STATE_GET_HANDLE_READ;
76097630
else if (type == WOLFSSH_FTP_STATUS) {
76107631
handleState->state = STATE_GET_HANDLE_DO_STATUS;
76117632
}
76127633
else {
76137634
WLOG(WS_LOG_SFTP,
76147635
"Unexpected packet type with getting handle");
7636+
ssh->error = WS_SFTP_BAD_REQ_TYPE;
76157637
handleState->state = STATE_GET_HANDLE_CLEANUP;
76167638
ret = WS_FATAL_ERROR;
76177639
}
@@ -7639,21 +7661,6 @@ static int wolfSSH_SFTP_GetHandle(WOLFSSH* ssh, byte* handle, word32* handleSz)
76397661
handleState->state = STATE_GET_HANDLE_CLEANUP;
76407662
continue;
76417663

7642-
case STATE_GET_HANDLE_CHECK_REQ_ID:
7643-
WLOG(WS_LOG_SFTP, "SFTP GET HANDLE STATE: CHECK_REQ_ID");
7644-
/* @TODO packets do not need to be in order, may need
7645-
* mechanism to handle out of order ID's? */
7646-
if (handleState->reqId != ssh->reqId) {
7647-
WLOG(WS_LOG_SFTP, "Unexpected ID");
7648-
ret = WS_FATAL_ERROR;
7649-
handleState->state = STATE_GET_HANDLE_CLEANUP;
7650-
continue;
7651-
}
7652-
ssh->reqId++;
7653-
7654-
handleState->state = STATE_GET_HANDLE_READ;
7655-
FALL_THROUGH;
7656-
76577664
case STATE_GET_HANDLE_READ:
76587665
WLOG(WS_LOG_SFTP, "SFTP GET HANDLE STATE: READ");
76597666
ret = wolfSSH_SFTP_buffer_read(ssh, &handleState->buffer,
@@ -8006,14 +8013,10 @@ static int SFTP_STAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr, byte type)
80068013
FALL_THROUGH;
80078014

80088015
case STATE_LSTAT_CHECK_REQ_ID:
8009-
/* check request ID */
8010-
if (state->reqId != ssh->reqId) {
8011-
WLOG(WS_LOG_SFTP, "Bad request ID received");
8016+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
8017+
wolfSSH_SFTP_ClearState(ssh, STATE_ID_LSTAT);
80128018
return WS_FATAL_ERROR;
80138019
}
8014-
else {
8015-
ssh->reqId++;
8016-
}
80178020
state->state = STATE_LSTAT_PARSE_REPLY;
80188021
FALL_THROUGH;
80198022

@@ -8221,6 +8224,11 @@ int wolfSSH_SFTP_SetSTAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
82218224
return WS_FATAL_ERROR;
82228225
}
82238226

8227+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
8228+
ret = WS_FATAL_ERROR;
8229+
break;
8230+
}
8231+
82248232
if (type != WOLFSSH_FTP_STATUS) {
82258233
WLOG(WS_LOG_SFTP, "Unexpected packet type %d", type);
82268234
ret = WS_FATAL_ERROR;
@@ -8567,17 +8575,12 @@ int wolfSSH_SFTP_SendWritePacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
85678575
continue;
85688576
}
85698577

8570-
/* check request ID */
8571-
if (state->reqId != ssh->reqId) {
8572-
WLOG(WS_LOG_SFTP, "Bad request ID received");
8578+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
85738579
ret = WS_FATAL_ERROR;
8574-
ssh->error = WS_SFTP_BAD_REQ_ID;
85758580
state->state = STATE_SEND_WRITE_CLEANUP;
85768581
continue;
85778582
}
85788583

8579-
ssh->reqId++;
8580-
85818584
if (type != WOLFSSH_FTP_STATUS) {
85828585
WLOG(WS_LOG_SFTP, "Unexpected packet type");
85838586
ret = WS_FATAL_ERROR;
@@ -8773,16 +8776,11 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
87738776

87748777
case STATE_SEND_READ_CHECK_REQ_ID:
87758778
WLOG(WS_LOG_SFTP, "SFTP SEND_READ STATE: CHECK_REQ_ID");
8776-
/* check request ID */
8777-
if (state->reqId != ssh->reqId) {
8778-
WLOG(WS_LOG_SFTP, "Bad request ID received");
8779+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
87798780
ret = WS_FATAL_ERROR;
87808781
state->state = STATE_SEND_READ_CLEANUP;
87818782
continue;
87828783
}
8783-
else {
8784-
ssh->reqId++;
8785-
}
87868784

87878785
if (state->type == WOLFSSH_FTP_DATA)
87888786
state->state = STATE_SEND_READ_FTP_DATA;
@@ -9034,15 +9032,10 @@ int wolfSSH_SFTP_MKDIR(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr)
90349032
return WS_FATAL_ERROR;
90359033
}
90369034

9037-
/* check request ID */
9038-
if (state->reqId != ssh->reqId) {
9039-
WLOG(WS_LOG_SFTP, "Bad request ID received");
9035+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
90409036
wolfSSH_SFTP_ClearState(ssh, STATE_ID_MKDIR);
90419037
return WS_FATAL_ERROR;
90429038
}
9043-
else {
9044-
ssh->reqId++;
9045-
}
90469039

90479040
if (wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret) != 0) {
90489041
wolfSSH_SFTP_ClearState(ssh, STATE_ID_MKDIR);
@@ -9202,6 +9195,12 @@ int wolfSSH_SFTP_Close(WOLFSSH* ssh, byte* handle, word32 handleSz)
92029195
continue;
92039196
}
92049197

9198+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
9199+
ret = WS_FATAL_ERROR;
9200+
state->state = STATE_CLOSE_CLEANUP;
9201+
continue;
9202+
}
9203+
92059204
if (wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret) != 0) {
92069205
ret = WS_MEMORY_E;
92079206
state->state = STATE_CLOSE_CLEANUP;
@@ -9590,17 +9589,12 @@ int wolfSSH_SFTP_Rename(WOLFSSH* ssh, const char* old, const char* nw)
95909589
continue;
95919590
}
95929591

9593-
/* check request ID */
9594-
if (state->reqId != ssh->reqId) {
9595-
WLOG(WS_LOG_SFTP, "Bad request ID received");
9592+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
95969593
ret = WS_FATAL_ERROR;
9597-
ssh->error = WS_SFTP_BAD_REQ_ID;
95989594
state->state = STATE_RENAME_CLEANUP;
95999595
continue;
96009596
}
96019597

9602-
ssh->reqId++;
9603-
96049598
if (type != WOLFSSH_FTP_STATUS) {
96059599
WLOG(WS_LOG_SFTP, "Unexpected packet type");
96069600
ret = WS_FATAL_ERROR;
@@ -9739,6 +9733,11 @@ int wolfSSH_SFTP_Remove(WOLFSSH* ssh, char* f)
97399733
return WS_FATAL_ERROR;
97409734
}
97419735

9736+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
9737+
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
9738+
return WS_FATAL_ERROR;
9739+
}
9740+
97429741
if (wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret) != 0) {
97439742
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RM);
97449743
return WS_FATAL_ERROR;
@@ -9828,6 +9827,11 @@ int wolfSSH_SFTP_RMDIR(WOLFSSH* ssh, char* dir)
98289827
}
98299828
return WS_FATAL_ERROR;
98309829
}
9830+
9831+
if (SFTP_CheckReqId(ssh, state->reqId) != WS_SUCCESS) {
9832+
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
9833+
return WS_FATAL_ERROR;
9834+
}
98319835
if (wolfSSH_SFTP_buffer_create(ssh, &state->buffer, ret) != 0) {
98329836
wolfSSH_SFTP_ClearState(ssh, STATE_ID_RMDIR);
98339837
return WS_MEMORY_E;

0 commit comments

Comments
 (0)