mirror of https://github.com/wolfSSL/wolfssh.git
Merge pull request #190 from JacobBarthelmeh/sftp
add test case for wolfSSH_SFTP_SendReadPacketpull/194/head
commit
62335d9a7b
|
@ -5907,21 +5907,23 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
state->idx += UINT32_SZ;
|
state->idx += UINT32_SZ;
|
||||||
|
|
||||||
state->state = STATE_SEND_READ_SEND_REQ;
|
state->state = STATE_SEND_READ_SEND_REQ;
|
||||||
|
|
||||||
FALL_THROUGH;
|
FALL_THROUGH;
|
||||||
|
|
||||||
case STATE_SEND_READ_SEND_REQ:
|
case STATE_SEND_READ_SEND_REQ:
|
||||||
WLOG(WS_LOG_SFTP, "SFTP SEND_READ STATE: SEND_REQ");
|
WLOG(WS_LOG_SFTP, "SFTP SEND_READ STATE: SEND_REQ");
|
||||||
/* send header and type specific data */
|
/* send header and type specific data */
|
||||||
ret = wolfSSH_stream_send(ssh, state->data, state->idx);
|
ret = wolfSSH_stream_send(ssh, state->data, state->idx);
|
||||||
if (ssh->error == WS_WANT_READ || ssh->error == WS_WANT_WRITE) {
|
if (ret < 0) {
|
||||||
|
if (ssh->error != WS_WANT_READ &&
|
||||||
|
ssh->error != WS_WANT_WRITE) {
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
WFREE(state->data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
WFREE(state->data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||||
state->data = NULL;
|
state->data = NULL;
|
||||||
if (ret < 0) {
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
state->state = STATE_SEND_READ_GET_HEADER;
|
state->state = STATE_SEND_READ_GET_HEADER;
|
||||||
FALL_THROUGH;
|
FALL_THROUGH;
|
||||||
|
|
||||||
|
@ -5929,8 +5931,14 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
WLOG(WS_LOG_SFTP, "SFTP SEND_READ STATE: GET_HEADER");
|
WLOG(WS_LOG_SFTP, "SFTP SEND_READ STATE: GET_HEADER");
|
||||||
/* Get response */
|
/* Get response */
|
||||||
if ((ret = SFTP_GetHeader(ssh, &state->reqId, &state->type))
|
if ((ret = SFTP_GetHeader(ssh, &state->reqId, &state->type))
|
||||||
<= 0)
|
<= 0) {
|
||||||
|
if (ssh->error != WS_WANT_READ &&
|
||||||
|
ssh->error != WS_WANT_WRITE) {
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
|
}
|
||||||
|
|
||||||
state->sz = ret;
|
state->sz = ret;
|
||||||
state->state = STATE_SEND_READ_CHECK_REQ_ID;
|
state->state = STATE_SEND_READ_CHECK_REQ_ID;
|
||||||
|
@ -5941,7 +5949,9 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
/* check request ID */
|
/* check request ID */
|
||||||
if (state->reqId != ssh->reqId) {
|
if (state->reqId != ssh->reqId) {
|
||||||
WLOG(WS_LOG_SFTP, "Bad request ID received");
|
WLOG(WS_LOG_SFTP, "Bad request ID received");
|
||||||
return WS_FATAL_ERROR;
|
ret = WS_FATAL_ERROR;
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
ssh->reqId++;
|
ssh->reqId++;
|
||||||
|
@ -5952,7 +5962,8 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
state->state = STATE_SEND_READ_FTP_STATUS;
|
state->state = STATE_SEND_READ_FTP_STATUS;
|
||||||
else {
|
else {
|
||||||
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
WLOG(WS_LOG_SFTP, "Unexpected packet type");
|
||||||
return WS_FATAL_ERROR;
|
ret = WS_FATAL_ERROR;
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
}
|
}
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -5961,12 +5972,19 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
/* get size of string and place it into out buffer */
|
/* get size of string and place it into out buffer */
|
||||||
ret = wolfSSH_stream_read(ssh, szFlat, UINT32_SZ);
|
ret = wolfSSH_stream_read(ssh, szFlat, UINT32_SZ);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
if (ssh->error != WS_WANT_READ &&
|
||||||
|
ssh->error != WS_WANT_WRITE) {
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
ato32(szFlat, &state->sz);
|
ato32(szFlat, &state->sz);
|
||||||
if (state->sz > outSz) {
|
if (state->sz > outSz) {
|
||||||
WLOG(WS_LOG_SFTP, "Server sent more data then expected");
|
WLOG(WS_LOG_SFTP, "Server sent more data then expected");
|
||||||
return WS_FATAL_ERROR;
|
ret = WS_FATAL_ERROR;
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
state->state = STATE_SEND_READ_REMAINDER;
|
state->state = STATE_SEND_READ_REMAINDER;
|
||||||
|
@ -6004,6 +6022,11 @@ int wolfSSH_SFTP_SendReadPacket(WOLFSSH* ssh, byte* handle, word32 handleSz,
|
||||||
ssh->ctx->heap, DYNTYPE_BUFFER);
|
ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||||
ret = wolfSSH_stream_read(ssh, data, state->sz);
|
ret = wolfSSH_stream_read(ssh, data, state->sz);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
|
if (ssh->error != WS_WANT_READ &&
|
||||||
|
ssh->error != WS_WANT_WRITE) {
|
||||||
|
state->state = STATE_SEND_READ_CLEANUP;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
ret = wolfSSH_SFTP_DoStatus(ssh, state->reqId, data,
|
ret = wolfSSH_SFTP_DoStatus(ssh, state->reqId, data,
|
||||||
|
|
197
tests/api.c
197
tests/api.c
|
@ -25,6 +25,21 @@
|
||||||
#ifdef WOLFSSH_SCP
|
#ifdef WOLFSSH_SCP
|
||||||
#include <wolfssh/wolfscp.h>
|
#include <wolfssh/wolfscp.h>
|
||||||
#endif
|
#endif
|
||||||
|
#ifdef WOLFSSH_SFTP
|
||||||
|
#define WOLFSSH_TEST_LOCKING
|
||||||
|
#define WOLFSSH_TEST_THREADING
|
||||||
|
|
||||||
|
#define WOLFSSH_TEST_SERVER
|
||||||
|
#define WOLFSSH_TEST_ECHOSERVER
|
||||||
|
#include <wolfssh/test.h>
|
||||||
|
|
||||||
|
#include "examples/echoserver/echoserver.h"
|
||||||
|
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* for echoserver test cases */
|
||||||
|
int myoptind = 0;
|
||||||
|
char* myoptarg = NULL;
|
||||||
|
|
||||||
|
|
||||||
#define Fail(description, result) do { \
|
#define Fail(description, result) do { \
|
||||||
|
@ -231,6 +246,93 @@ static int ConvertHexToBin(const char* h1, byte** b1, word32* b1Sz,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WOLFSSH_SFTP
|
||||||
|
byte userPassword[256];
|
||||||
|
static int sftpUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
|
||||||
|
{
|
||||||
|
int ret = WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
|
||||||
|
|
||||||
|
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
|
||||||
|
const char* defaultPassword = (const char*)ctx;
|
||||||
|
word32 passwordSz;
|
||||||
|
|
||||||
|
ret = WOLFSSH_USERAUTH_SUCCESS;
|
||||||
|
if (defaultPassword != NULL) {
|
||||||
|
passwordSz = (word32)strlen(defaultPassword);
|
||||||
|
memcpy(userPassword, defaultPassword, passwordSz);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("Expecting password set for test cases\n");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
|
||||||
|
authData->sf.password.password = userPassword;
|
||||||
|
authData->sf.password.passwordSz = passwordSz;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* preforms connection to port, sets WOLFSSH_CTX and WOLFSSH on success
|
||||||
|
* caller needs to free ctx and ssh when done
|
||||||
|
*/
|
||||||
|
static void sftp_client_connect(WOLFSSH_CTX** ctx, WOLFSSH** ssh, int port)
|
||||||
|
{
|
||||||
|
SOCKET_T sockFd = WOLFSSH_SOCKET_INVALID;
|
||||||
|
SOCKADDR_IN_T clientAddr;
|
||||||
|
socklen_t clientAddrSz = sizeof(clientAddr);
|
||||||
|
int ret;
|
||||||
|
char* host = (char*)wolfSshIp;
|
||||||
|
const char* username = "jill";
|
||||||
|
const char* password = "upthehill";
|
||||||
|
|
||||||
|
if (ctx == NULL || ssh == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
*ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
|
||||||
|
if (*ctx == NULL) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wolfSSH_SetUserAuth(*ctx, sftpUserAuth);
|
||||||
|
*ssh = wolfSSH_new(*ctx);
|
||||||
|
if (*ssh == NULL) {
|
||||||
|
wolfSSH_CTX_free(*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
build_addr(&clientAddr, host, port);
|
||||||
|
tcp_socket(&sockFd);
|
||||||
|
ret = connect(sockFd, (const struct sockaddr *)&clientAddr, clientAddrSz);
|
||||||
|
if (ret != 0){
|
||||||
|
wolfSSH_free(*ssh);
|
||||||
|
wolfSSH_CTX_free(*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
*ssh = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
wolfSSH_SetUserAuthCtx(*ssh, (void*)password);
|
||||||
|
ret = wolfSSH_SetUsername(*ssh, username);
|
||||||
|
if (ret == WS_SUCCESS)
|
||||||
|
ret = wolfSSH_set_fd(*ssh, (int)sockFd);
|
||||||
|
|
||||||
|
if (ret == WS_SUCCESS)
|
||||||
|
ret = wolfSSH_SFTP_connect(*ssh);
|
||||||
|
|
||||||
|
if (ret != WS_SUCCESS){
|
||||||
|
wolfSSH_free(*ssh);
|
||||||
|
wolfSSH_CTX_free(*ctx);
|
||||||
|
*ctx = NULL;
|
||||||
|
*ssh = NULL;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSH_SFTP */
|
||||||
|
|
||||||
|
|
||||||
enum WS_TestEndpointTypes {
|
enum WS_TestEndpointTypes {
|
||||||
TEST_GOOD_ENDPOINT_SERVER = WOLFSSH_ENDPOINT_SERVER,
|
TEST_GOOD_ENDPOINT_SERVER = WOLFSSH_ENDPOINT_SERVER,
|
||||||
|
@ -529,6 +631,97 @@ static void test_wolfSSH_SCP_CB(void)
|
||||||
#endif /* WOLFSSH_NO_CLIENT */
|
#endif /* WOLFSSH_NO_CLIENT */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_wolfSSH_SFTP_SendReadPacket(void)
|
||||||
|
{
|
||||||
|
#ifdef WOLFSSH_SFTP
|
||||||
|
func_args ser;
|
||||||
|
tcp_ready ready;
|
||||||
|
int argsCount;
|
||||||
|
|
||||||
|
const char* args[10];
|
||||||
|
WOLFSSH_CTX* ctx = NULL;
|
||||||
|
WOLFSSH* ssh = NULL;
|
||||||
|
|
||||||
|
THREAD_TYPE serThread;
|
||||||
|
|
||||||
|
WMEMSET(&ser, 0, sizeof(func_args));
|
||||||
|
|
||||||
|
argsCount = 0;
|
||||||
|
args[argsCount++] = ".";
|
||||||
|
args[argsCount++] = "-1";
|
||||||
|
#ifndef USE_WINDOWS_API
|
||||||
|
args[argsCount++] = "-p";
|
||||||
|
args[argsCount++] = "0";
|
||||||
|
#endif
|
||||||
|
ser.argv = (char**)args;
|
||||||
|
ser.argc = argsCount;
|
||||||
|
ser.signal = &ready;
|
||||||
|
InitTcpReady(ser.signal);
|
||||||
|
ThreadStart(echoserver_test, (void*)&ser, &serThread);
|
||||||
|
WaitTcpReady(&ser);
|
||||||
|
|
||||||
|
sftp_client_connect(&ctx, &ssh, ready.port);
|
||||||
|
AssertNotNull(ctx);
|
||||||
|
AssertNotNull(ssh);
|
||||||
|
|
||||||
|
{
|
||||||
|
WS_SFTPNAME* tmp;
|
||||||
|
WS_SFTPNAME* current;
|
||||||
|
byte handle[WOLFSSH_MAX_HANDLE];
|
||||||
|
word32 handleSz = WOLFSSH_MAX_HANDLE;
|
||||||
|
const char* currentDir = ".";
|
||||||
|
byte* out = NULL;
|
||||||
|
int outSz = 18;
|
||||||
|
const word32 ofst[2] = {0};
|
||||||
|
|
||||||
|
current = wolfSSH_SFTP_LS(ssh, (char*)currentDir);
|
||||||
|
tmp = current;
|
||||||
|
while (tmp != NULL) {
|
||||||
|
if ((tmp->atrb.sz[0] > 0) &&
|
||||||
|
(tmp->atrb.flags & WOLFSSH_FILEATRB_PERM) &&
|
||||||
|
!(tmp->atrb.per & 0x4000)) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
tmp = tmp->next;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (tmp != NULL) {
|
||||||
|
out = (byte*)malloc(tmp->atrb.sz[0]);
|
||||||
|
AssertIntEQ(wolfSSH_SFTP_Open(ssh, tmp->fName, WOLFSSH_FXF_READ,
|
||||||
|
NULL, handle, &handleSz), WS_SUCCESS);
|
||||||
|
|
||||||
|
/* read 18 bytes */
|
||||||
|
if (tmp->atrb.sz[0] >= 18) {
|
||||||
|
outSz = 18;
|
||||||
|
AssertIntEQ(wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz,
|
||||||
|
ofst, out, outSz), outSz);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* partial read */
|
||||||
|
outSz = tmp->atrb.sz[0] / 2;
|
||||||
|
AssertIntEQ(wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz, ofst,
|
||||||
|
out, outSz), outSz);
|
||||||
|
|
||||||
|
/* read all */
|
||||||
|
outSz = tmp->atrb.sz[0];
|
||||||
|
AssertIntEQ(wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz, ofst,
|
||||||
|
out, outSz), outSz);
|
||||||
|
|
||||||
|
free(out);
|
||||||
|
wolfSSH_SFTP_Close(ssh, handle, handleSz);
|
||||||
|
wolfSSH_SFTPNAME_list_free(current);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
AssertIntEQ(wolfSSH_shutdown(ssh), WS_SUCCESS);
|
||||||
|
wolfSSH_free(ssh);
|
||||||
|
wolfSSH_CTX_free(ctx);
|
||||||
|
ThreadJoin(serThread);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#ifdef USE_WINDOWS_API
|
#ifdef USE_WINDOWS_API
|
||||||
static byte color_test[] = {
|
static byte color_test[] = {
|
||||||
0x1B, 0x5B, 0x34, 0x6D, 0x75, 0x6E, 0x64, 0x65,
|
0x1B, 0x5B, 0x34, 0x6D, 0x75, 0x6E, 0x64, 0x65,
|
||||||
|
@ -636,6 +829,10 @@ int main(void)
|
||||||
/* SCP tests */
|
/* SCP tests */
|
||||||
test_wolfSSH_SCP_CB();
|
test_wolfSSH_SCP_CB();
|
||||||
|
|
||||||
|
/* SFTP tests */
|
||||||
|
test_wolfSSH_SFTP_SendReadPacket();
|
||||||
|
|
||||||
|
|
||||||
AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS);
|
AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -18,7 +18,8 @@ endif
|
||||||
tests_unit_test_LDADD = src/libwolfssh.la
|
tests_unit_test_LDADD = src/libwolfssh.la
|
||||||
tests_unit_test_DEPENDENCIES = src/libwolfssh.la
|
tests_unit_test_DEPENDENCIES = src/libwolfssh.la
|
||||||
|
|
||||||
tests_api_test_SOURCES = tests/api.c
|
tests_api_test_SOURCES = tests/api.c \
|
||||||
|
examples/echoserver/echoserver.c
|
||||||
tests_api_test_CPPFLAGS = -DNO_MAIN_DRIVER
|
tests_api_test_CPPFLAGS = -DNO_MAIN_DRIVER
|
||||||
if BUILD_SCP
|
if BUILD_SCP
|
||||||
tests_api_test_CPPFLAGS += -DWOLFSSH_SCP
|
tests_api_test_CPPFLAGS += -DWOLFSSH_SCP
|
||||||
|
|
|
@ -164,18 +164,3 @@ int TestsuiteTest(int argc, char** argv)
|
||||||
#endif /* !NO_WOLFSSH_SERVER && !NO_WOLFSSH_CLIENT */
|
#endif /* !NO_WOLFSSH_SERVER && !NO_WOLFSSH_CLIENT */
|
||||||
|
|
||||||
|
|
||||||
void WaitTcpReady(func_args* args)
|
|
||||||
{
|
|
||||||
#if defined(_POSIX_THREADS) && !defined(__MINGW32__)
|
|
||||||
pthread_mutex_lock(&args->signal->mutex);
|
|
||||||
|
|
||||||
if (!args->signal->ready)
|
|
||||||
pthread_cond_wait(&args->signal->cond, &args->signal->mutex);
|
|
||||||
args->signal->ready = 0; /* reset */
|
|
||||||
|
|
||||||
pthread_mutex_unlock(&args->signal->mutex);
|
|
||||||
#else
|
|
||||||
(void)args;
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
|
@ -741,7 +741,21 @@ static INLINE void FreeTcpReady(tcp_ready* ready)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void WaitTcpReady(func_args*);
|
static INLINE void WaitTcpReady(func_args* args)
|
||||||
|
{
|
||||||
|
#if defined(_POSIX_THREADS) && !defined(__MINGW32__)
|
||||||
|
pthread_mutex_lock(&args->signal->mutex);
|
||||||
|
|
||||||
|
if (!args->signal->ready)
|
||||||
|
pthread_cond_wait(&args->signal->cond, &args->signal->mutex);
|
||||||
|
args->signal->ready = 0; /* reset */
|
||||||
|
|
||||||
|
pthread_mutex_unlock(&args->signal->mutex);
|
||||||
|
#else
|
||||||
|
(void)args;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
#endif /* WOLFSSH_TEST_LOCKING */
|
#endif /* WOLFSSH_TEST_LOCKING */
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue