malloc lstat buffer and rework SFTP send packet type

pull/134/head
Jacob Barthelmeh 2019-01-02 11:32:41 -07:00
parent 821b34df23
commit f0ba3a0849
2 changed files with 64 additions and 33 deletions

View File

@ -48,6 +48,7 @@ enum WS_SFTP_STATE_ID {
STATE_ID_CLOSE = 0x10, STATE_ID_CLOSE = 0x10,
STATE_ID_GET_HANDLE = 0x20, STATE_ID_GET_HANDLE = 0x20,
STATE_ID_NAME = 0x40, STATE_ID_NAME = 0x40,
STATE_ID_SEND = 0x80,
}; };
enum WS_SFTP_NAME_STATE_ID { enum WS_SFTP_NAME_STATE_ID {
@ -61,7 +62,7 @@ enum WS_SFTP_REAL_STATE_ID {
SFTP_REAL_GET_PACKET SFTP_REAL_GET_PACKET
}; };
enum WS_SFTP_SEND_STATE { enum WS_SFTP_SEND_STATE_ID {
SFTP_BUILD_PACKET, SFTP_BUILD_PACKET,
SFTP_SEND_PACKET SFTP_SEND_PACKET
}; };
@ -109,6 +110,14 @@ typedef struct WS_SFTP_NAME_STATE {
word32 idx; word32 idx;
} WS_SFTP_NAME_STATE; } WS_SFTP_NAME_STATE;
/* similar to open state, could refactor */
typedef struct WS_SFTP_SEND_STATE {
enum WS_SFTP_SEND_STATE_ID state;
byte* data;
int sz;
word32 idx;
} WS_SFTP_SEND_STATE;
enum WS_SFTP_GET_STATE_ID { enum WS_SFTP_GET_STATE_ID {
STATE_GET_INIT, STATE_GET_INIT,
STATE_GET_LSTAT, STATE_GET_LSTAT,
@ -248,6 +257,14 @@ static void wolfSSH_SFTP_ClearState(WOLFSSH* ssh, enum WS_SFTP_STATE_ID state)
ssh->nameState = NULL; ssh->nameState = NULL;
} }
} }
if (state & STATE_ID_SEND) {
if (ssh->sendState) {
XFREE(ssh->sendState->data, ssh->ctx->heap, DYNTYPE_BUFFER);
XFREE(ssh->sendState, ssh->ctx->heap, DYNTYPE_SFTP_STATE);
ssh->sendState = NULL;
}
}
} }
} }
@ -3034,65 +3051,74 @@ int wolfSSH_SFTP_negotiate(WOLFSSH* ssh)
int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz) int SendPacketType(WOLFSSH* ssh, byte type, byte* buf, word32 bufSz)
{ {
int ret = WS_SUCCESS; int ret = WS_SUCCESS;
word32 idx = 0; WS_SFTP_SEND_STATE* state = NULL;
word32 sent = 0;
byte* data = NULL;
if (ssh == NULL || buf == NULL) { if (ssh == NULL || buf == NULL) {
return WS_BAD_ARGUMENT; return WS_BAD_ARGUMENT;
} }
switch (ssh->sendState) { state = ssh->sendState;
if (state == NULL) {
state = (WS_SFTP_SEND_STATE*)WMALLOC(sizeof(WS_SFTP_SEND_STATE),
ssh->ctx->heap, DYNTYPE_SFTP_STATE);
if (state == NULL) {
ssh->error = WS_MEMORY_E;
return WS_FATAL_ERROR;
}
WMEMSET(state, 0, sizeof(WS_SFTP_SEND_STATE));
ssh->sendState = state;
state->state = SFTP_BUILD_PACKET;
}
switch (state->state) {
case SFTP_BUILD_PACKET: case SFTP_BUILD_PACKET:
if (ssh->sftpState != SFTP_DONE) { if (ssh->sftpState != SFTP_DONE) {
WLOG(WS_LOG_SFTP, "SFTP connection not complete, trying to finish"); WLOG(WS_LOG_SFTP, "SFTP connection not complete");
ret = wolfSSH_SFTP_negotiate(ssh); ret = wolfSSH_SFTP_negotiate(ssh);
} }
if (ret == WS_SUCCESS) { if (ret == WS_SUCCESS) {
data = (byte*)WMALLOC(bufSz + WOLFSSH_SFTP_HEADER + state->sz = bufSz + WOLFSSH_SFTP_HEADER + UINT32_SZ;
UINT32_SZ, NULL, DYNTYPE_BUFFER); state->data = (byte*)WMALLOC(state->sz, ssh->ctx->heap,
if (data == NULL) { DYNTYPE_BUFFER);
ssh->sendState = SFTP_BUILD_PACKET; if (state->data == NULL) {
wolfSSH_SFTP_ClearState(ssh, STATE_ID_SEND);
return WS_MEMORY_E; return WS_MEMORY_E;
} }
if (SFTP_SetHeader(ssh, ssh->reqId, type, bufSz + UINT32_SZ, data) if (SFTP_SetHeader(ssh, ssh->reqId, type, bufSz + UINT32_SZ,
!= WS_SUCCESS) { state->data) != WS_SUCCESS) {
WFREE(data, NULL, DYNTYPE_BUFFER); wolfSSH_SFTP_ClearState(ssh, STATE_ID_SEND);
ssh->sendState = SFTP_BUILD_PACKET;
return WS_FATAL_ERROR; return WS_FATAL_ERROR;
} }
idx = WOLFSSH_SFTP_HEADER; state->idx = WOLFSSH_SFTP_HEADER;
c32toa(bufSz, data + idx); idx += UINT32_SZ; c32toa(bufSz, state->data + state->idx);
WMEMCPY(data + idx, buf, bufSz); idx += bufSz; state->idx += UINT32_SZ;
WMEMCPY(state->data + state->idx, buf, bufSz);
state->idx = 0; /* reset state for sending data */
} }
ssh->sendState = SFTP_SEND_PACKET; state->state = SFTP_SEND_PACKET;
FALL_THROUGH; FALL_THROUGH;
/* no break */ /* no break */
case SFTP_SEND_PACKET: case SFTP_SEND_PACKET:
/* send header and type specific state->data, looping over send
* because channel could have restrictions on how much
/* send header and type specific data, looping over send because * state->data can be sent at one time */
* channel could have restrictions on how much data can be sent at
* one time */
do { do {
ret = wolfSSH_stream_send(ssh, data + sent, idx - sent); ret = wolfSSH_stream_send(ssh, state->data + state->idx,
state->sz - state->idx);
if (ssh->error != WS_WANT_WRITE) if (ssh->error != WS_WANT_WRITE)
wolfSSH_CheckReceivePending(ssh); /* check for adjust window packet */ /* check for adjust window packet */
wolfSSH_CheckReceivePending(ssh);
if (ret > 0) if (ret > 0)
sent += (word32)ret; state->idx += (word32)ret;
} while (ret > 0 && sent < idx); } while (ret > 0 && state->idx < (word32)state->sz);
if (ret > 0) { if (ret > 0) {
ret = WS_SUCCESS; ret = WS_SUCCESS;
} wolfSSH_SFTP_ClearState(ssh, STATE_ID_SEND);
WFREE(data, NULL, DYNTYPE_BUFFER);
if (ssh->error != WS_WANT_WRITE) {
ssh->sendState = SFTP_BUILD_PACKET;
} }
break; break;
@ -3915,6 +3941,11 @@ static int SFTP_STAT(WOLFSSH* ssh, char* dir, WS_SFTP_FILEATRB* atr, byte type)
} }
state->sz = (word32)ret; state->sz = (word32)ret;
state->state = STATE_LSTAT_CHECK_REQ_ID; state->state = STATE_LSTAT_CHECK_REQ_ID;
state->data = (byte*)WMALLOC(state->sz, ssh->ctx->heap,
DYNTYPE_BUFFER);
if (state->data == NULL) {
return WS_FATAL_ERROR;
}
FALL_THROUGH; FALL_THROUGH;
case STATE_LSTAT_CHECK_REQ_ID: case STATE_LSTAT_CHECK_REQ_ID:

View File

@ -387,7 +387,6 @@ struct WOLFSSH {
#ifdef WOLFSSH_SFTP #ifdef WOLFSSH_SFTP
word32 reqId; word32 reqId;
byte sftpState; byte sftpState;
byte sendState;
byte realState; byte realState;
byte sftpInt; byte sftpInt;
byte sftpExtSz; /* size of extension buffer (buffer not currently used) */ byte sftpExtSz; /* size of extension buffer (buffer not currently used) */
@ -395,6 +394,7 @@ struct WOLFSSH {
#ifdef WOLFSSH_STOREHANDLE #ifdef WOLFSSH_STOREHANDLE
WS_HANDLE_LIST* handleList; WS_HANDLE_LIST* handleList;
#endif #endif
struct WS_SFTP_SEND_STATE* sendState;
struct WS_SFTP_NAME_STATE* nameState; struct WS_SFTP_NAME_STATE* nameState;
struct WS_SFTP_GET_STATE* getState; struct WS_SFTP_GET_STATE* getState;
struct WS_SFTP_LSTAT_STATE* lstatState; struct WS_SFTP_LSTAT_STATE* lstatState;