mirror of https://github.com/wolfSSL/wolfssh.git
scp nucleus port
fix for uninitialised value fix compile time warnings scp only build and handle file size of 0 macro guard on sftp build adjust directory pointer on desktop build close connection still on fail and update derefrence of dir with nucleus ssh only build for nucleuspull/73/head
parent
6d434d0030
commit
522d93add3
|
@ -210,17 +210,19 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret != 0) {
|
|
||||||
fprintf(stderr, "Error [%d] with handling connection.\n", ret);
|
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) {
|
if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) {
|
||||||
fprintf(stderr, "Error with SSH shutdown.\n");
|
fprintf(stderr, "Error with SSH shutdown.\n");
|
||||||
}
|
}
|
||||||
|
|
||||||
WCLOSESOCKET(threadCtx->fd);
|
WCLOSESOCKET(threadCtx->fd);
|
||||||
wolfSSH_free(threadCtx->ssh);
|
wolfSSH_free(threadCtx->ssh);
|
||||||
|
|
||||||
|
if (ret != 0) {
|
||||||
|
fprintf(stderr, "Error [%d] \"%s\" with handling connection.\n", ret,
|
||||||
|
wolfSSH_ErrorToName(ret));
|
||||||
|
exit(EXIT_FAILURE);
|
||||||
|
}
|
||||||
|
|
||||||
free(threadCtx);
|
free(threadCtx);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
|
|
112
src/internal.c
112
src/internal.c
|
@ -7011,6 +7011,118 @@ int SendChannelSuccess(WOLFSSH* ssh, word32 channelId, int success)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#if defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)
|
||||||
|
/* cleans up absolute path */
|
||||||
|
void clean_path(char* path)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
long sz = (long)WSTRLEN(path);
|
||||||
|
byte found;
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
if (path[i] == '/') path[i] = '\\';
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/* remove any ./ patterns */
|
||||||
|
for (i = 1; i < sz - 1; i++) {
|
||||||
|
if (path[i] == '.' && path[i - 1] != '.' && path[i + 1] == WS_DELIM) {
|
||||||
|
WMEMMOVE(path + i, path + i + 1, sz - i - 1);
|
||||||
|
path[sz - 1] = '\0';
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sz = (int)WSTRLEN(path);
|
||||||
|
|
||||||
|
/* remove any double '/' or '\' chars */
|
||||||
|
for (i = 0; i < sz; i++) {
|
||||||
|
if ((path[i] == WS_DELIM && path[i+1] == WS_DELIM)) {
|
||||||
|
WMEMMOVE(path + i, path + i + 1, sz - i + 1);
|
||||||
|
sz -= 1;
|
||||||
|
i--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path != NULL) {
|
||||||
|
/* go through path until no cases are found */
|
||||||
|
do {
|
||||||
|
sz = WSTRLEN(path);
|
||||||
|
int prIdx = 0; /* begin of cut */
|
||||||
|
int enIdx = 0; /* end of cut */
|
||||||
|
|
||||||
|
found = 0;
|
||||||
|
for (i = 1; i < sz; i++) {
|
||||||
|
if (path[i] == WS_DELIM) {
|
||||||
|
int z;
|
||||||
|
|
||||||
|
/* if next two chars are .. then delete */
|
||||||
|
if (path[i+1] == '.' && path[i+2] == '.') {
|
||||||
|
enIdx = i + 3;
|
||||||
|
|
||||||
|
/* start at one char before / and retrace path */
|
||||||
|
for (z = i - 1; z > 0; z--) {
|
||||||
|
if (path[z] == WS_DELIM || path[z] == ':') {
|
||||||
|
prIdx = z;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* cut out .. and previous */
|
||||||
|
WMEMMOVE(path + prIdx, path + enIdx, sz - enIdx);
|
||||||
|
path[sz - (enIdx - prIdx)] = '\0';
|
||||||
|
|
||||||
|
if (enIdx == sz) {
|
||||||
|
path[prIdx] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* case of at / */
|
||||||
|
if (WSTRLEN(path) == 0) {
|
||||||
|
path[0] = '/';
|
||||||
|
path[1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
found = 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} while (found);
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
sz = WSTRLEN(path);
|
||||||
|
if (path[sz - 1] == ':') {
|
||||||
|
path[sz] = WS_DELIM;
|
||||||
|
path[sz + 1] = '\0';
|
||||||
|
}
|
||||||
|
|
||||||
|
/* clean up any multiple drive listed i.e. A:/A: */
|
||||||
|
{
|
||||||
|
int i,j;
|
||||||
|
sz = WSTRLEN(path);
|
||||||
|
for (i = 0, j = 0; i < sz; i++) {
|
||||||
|
if (path[i] == ':') {
|
||||||
|
if (j == 0) j = i;
|
||||||
|
else {
|
||||||
|
/* @TODO only checking once */
|
||||||
|
WMEMMOVE(path, path + i - WS_DRIVE_SIZE,
|
||||||
|
sz - i + WS_DRIVE_SIZE);
|
||||||
|
path[sz - i + WS_DRIVE_SIZE] = '\0';
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
/* remove trailing delimiter */
|
||||||
|
if (sz > 3 && path[sz - 1] == WS_DELIM) {
|
||||||
|
path[sz - 1] = '\0';
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif /* WOLFSSH_SFTP || WOLFSSH_SCP */
|
||||||
|
|
||||||
|
|
||||||
#ifdef DEBUG_WOLFSSH
|
#ifdef DEBUG_WOLFSSH
|
||||||
|
|
||||||
#define LINE_WIDTH 16
|
#define LINE_WIDTH 16
|
||||||
|
|
|
@ -142,7 +142,7 @@ void DefaultLoggingCb(enum wolfSSH_LogLevel level, const char *const msgStr)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSH_NO_TIMESTAMP */
|
#endif /* WOLFSSH_NO_TIMESTAMP */
|
||||||
fprintf(stdout, "%s[%s] %s\n", timeStr, GetLogStr(level), msgStr);
|
fprintf(stdout, "%s[%s] %s\r\n", timeStr, GetLogStr(level), msgStr);
|
||||||
}
|
}
|
||||||
#endif /* WOLFSSH_NO_DEFAULT_LOGGING_CB */
|
#endif /* WOLFSSH_NO_DEFAULT_LOGGING_CB */
|
||||||
|
|
||||||
|
|
28
src/port.c
28
src/port.c
|
@ -42,25 +42,33 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
|
||||||
return fopen_s(f, filename, mode) != 0;
|
return fopen_s(f, filename, mode) != 0;
|
||||||
#elif defined(WOLFSSL_NUCLEUS)
|
#elif defined(WOLFSSL_NUCLEUS)
|
||||||
int m = WOLFSSH_O_CREAT;
|
int m = WOLFSSH_O_CREAT;
|
||||||
if (WSTRSTR(mode, "r")) {
|
|
||||||
m |= WOLFSSH_O_RDONLY;
|
if (WSTRSTR(mode, "r") && WSTRSTR(mode, "w")) {
|
||||||
|
m |= WOLFSSH_O_RDWR;
|
||||||
}
|
}
|
||||||
if (WSTRSTR(mode, "w")) {
|
else {
|
||||||
if (m &= WOLFSSH_O_RDONLY) {
|
if (WSTRSTR(mode, "r")) {
|
||||||
m ^= WOLFSSH_O_RDONLY;
|
m |= WOLFSSH_O_RDONLY;
|
||||||
m |= WOLFSSH_O_RDWR;
|
|
||||||
}
|
}
|
||||||
else {
|
if (WSTRSTR(mode, "w")) {
|
||||||
m |= WOLFSSH_O_WRONLY;
|
m |= WOLFSSH_O_WRONLY;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (filename != NULL && f != NULL) {
|
if (filename != NULL && f != NULL) {
|
||||||
**f = NU_Open(filename, m, 0);
|
if ((**f = WOPEN(filename, m, 0)) < 0) {
|
||||||
return 1;
|
return **f;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* fopen defaults to normal */
|
||||||
|
if (NU_Set_Attributes(filename, 0) != NU_SUCCESS) {
|
||||||
|
WCLOSE(**f);
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
return 0;
|
return 1;
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
if (f != NULL) {
|
if (f != NULL) {
|
||||||
|
|
185
src/wolfscp.c
185
src/wolfscp.c
|
@ -31,12 +31,14 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <wolfssh/wolfscp.h>
|
||||||
|
|
||||||
#ifdef WOLFSSH_SCP
|
#ifdef WOLFSSH_SCP
|
||||||
|
|
||||||
#include <wolfssh/ssh.h>
|
#include <wolfssh/ssh.h>
|
||||||
#include <wolfssh/internal.h>
|
#include <wolfssh/internal.h>
|
||||||
#include <wolfssh/log.h>
|
#include <wolfssh/log.h>
|
||||||
#include <wolfssh/wolfscp.h>
|
|
||||||
|
|
||||||
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
||||||
#include <wolfssh/misc.h>
|
#include <wolfssh/misc.h>
|
||||||
|
@ -71,7 +73,7 @@ int DoScpSink(WOLFSSH* ssh)
|
||||||
|
|
||||||
ssh->scpConfirm = ssh->ctx->scpRecvCb(ssh,
|
ssh->scpConfirm = ssh->ctx->scpRecvCb(ssh,
|
||||||
WOLFSSH_SCP_NEW_REQUEST, ssh->scpBasePath,
|
WOLFSSH_SCP_NEW_REQUEST, ssh->scpBasePath,
|
||||||
NULL, 0, 0, 0, 0, NULL, 0, 0, ssh->scpRecvCtx);
|
NULL, 0, 0, 0, 0, NULL, 0, 0, wolfSSH_GetScpRecvCtx(ssh));
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
case SCP_RECEIVE_MESSAGE:
|
case SCP_RECEIVE_MESSAGE:
|
||||||
|
@ -117,7 +119,7 @@ int DoScpSink(WOLFSSH* ssh)
|
||||||
ssh->scpConfirm = ssh->ctx->scpRecvCb(ssh, ssh->scpFileState,
|
ssh->scpConfirm = ssh->ctx->scpRecvCb(ssh, ssh->scpFileState,
|
||||||
ssh->scpBasePath, ssh->scpFileName, ssh->scpFileMode,
|
ssh->scpBasePath, ssh->scpFileName, ssh->scpFileMode,
|
||||||
ssh->scpMTime, ssh->scpATime, ssh->scpFileSz, NULL, 0,
|
ssh->scpMTime, ssh->scpATime, ssh->scpFileSz, NULL, 0,
|
||||||
0, ssh->scpRecvCtx);
|
0, wolfSSH_GetScpRecvCtx(ssh));
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
@ -160,7 +162,7 @@ int DoScpSink(WOLFSSH* ssh)
|
||||||
ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime,
|
ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime,
|
||||||
ssh->scpATime, ssh->scpFileSz, ssh->scpFileBuffer,
|
ssh->scpATime, ssh->scpFileSz, ssh->scpFileBuffer,
|
||||||
ssh->scpFileBufferSz, ssh->scpFileOffset,
|
ssh->scpFileBufferSz, ssh->scpFileOffset,
|
||||||
ssh->scpRecvCtx);
|
wolfSSH_GetScpRecvCtx(ssh));
|
||||||
|
|
||||||
ssh->scpFileOffset += ssh->scpFileBufferSz;
|
ssh->scpFileOffset += ssh->scpFileBufferSz;
|
||||||
|
|
||||||
|
@ -183,7 +185,7 @@ int DoScpSink(WOLFSSH* ssh)
|
||||||
WOLFSSH_SCP_FILE_DONE, ssh->scpBasePath,
|
WOLFSSH_SCP_FILE_DONE, ssh->scpBasePath,
|
||||||
ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime,
|
ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime,
|
||||||
ssh->scpATime, ssh->scpFileSz, NULL, 0, 0,
|
ssh->scpATime, ssh->scpFileSz, NULL, 0, 0,
|
||||||
ssh->scpRecvCtx);
|
wolfSSH_GetScpRecvCtx(ssh));
|
||||||
|
|
||||||
ssh->scpFileOffset = 0;
|
ssh->scpFileOffset = 0;
|
||||||
ssh->scpATime = 0;
|
ssh->scpATime = 0;
|
||||||
|
@ -375,7 +377,7 @@ int DoScpSource(WOLFSSH* ssh)
|
||||||
|
|
||||||
ssh->scpConfirm = ssh->ctx->scpSendCb(ssh,
|
ssh->scpConfirm = ssh->ctx->scpSendCb(ssh,
|
||||||
WOLFSSH_SCP_NEW_REQUEST, NULL, NULL, 0, NULL, NULL,
|
WOLFSSH_SCP_NEW_REQUEST, NULL, NULL, 0, NULL, NULL,
|
||||||
NULL, 0, NULL, NULL, 0, ssh->scpSendCtx);
|
NULL, 0, NULL, NULL, 0, wolfSSH_GetScpSendCtx(ssh));
|
||||||
|
|
||||||
if (ssh->scpConfirm == WS_SCP_ABORT) {
|
if (ssh->scpConfirm == WS_SCP_ABORT) {
|
||||||
ssh->scpState = SCP_RECEIVE_CONFIRMATION_WITH_RECEIPT;
|
ssh->scpState = SCP_RECEIVE_CONFIRMATION_WITH_RECEIPT;
|
||||||
|
@ -451,7 +453,7 @@ int DoScpSource(WOLFSSH* ssh)
|
||||||
&(ssh->scpATime), &(ssh->scpFileMode),
|
&(ssh->scpATime), &(ssh->scpFileMode),
|
||||||
ssh->scpFileOffset, &(ssh->scpFileSz),
|
ssh->scpFileOffset, &(ssh->scpFileSz),
|
||||||
ssh->scpFileBuffer, ssh->scpFileBufferSz,
|
ssh->scpFileBuffer, ssh->scpFileBufferSz,
|
||||||
ssh->scpSendCtx);
|
wolfSSH_GetScpSendCtx(ssh));
|
||||||
|
|
||||||
if (ssh->scpConfirm == WS_SCP_ENTER_DIR) {
|
if (ssh->scpConfirm == WS_SCP_ENTER_DIR) {
|
||||||
ssh->scpState = SCP_SEND_ENTER_DIRECTORY;
|
ssh->scpState = SCP_SEND_ENTER_DIRECTORY;
|
||||||
|
@ -743,7 +745,7 @@ static int GetScpFileMode(WOLFSSH* ssh, byte* buf, word32 bufSz,
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
word32 idx;
|
word32 idx;
|
||||||
byte modeOctet[SCP_MODE_OCTET_LEN];
|
byte modeOctet[SCP_MODE_OCTET_LEN + 1];
|
||||||
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
|
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
|
||||||
defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
|
defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \
|
||||||
defined(WOLFSSL_PUBLIC_MP)
|
defined(WOLFSSL_PUBLIC_MP)
|
||||||
|
@ -764,7 +766,8 @@ static int GetScpFileMode(WOLFSSH* ssh, byte* buf, word32 bufSz,
|
||||||
return WS_BAD_ARGUMENT;
|
return WS_BAD_ARGUMENT;
|
||||||
idx++;
|
idx++;
|
||||||
|
|
||||||
WMEMCPY(modeOctet, buf + idx, sizeof(modeOctet));
|
WMEMCPY(modeOctet, buf + idx, SCP_MODE_OCTET_LEN);
|
||||||
|
modeOctet[SCP_MODE_OCTET_LEN] = '\0';
|
||||||
idx += SCP_MODE_OCTET_LEN;
|
idx += SCP_MODE_OCTET_LEN;
|
||||||
|
|
||||||
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
|
#if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \
|
||||||
|
@ -1104,6 +1107,7 @@ int ParseScpCommand(WOLFSSH* ssh)
|
||||||
/* skip space */
|
/* skip space */
|
||||||
idx += 2;
|
idx += 2;
|
||||||
ssh->scpBasePath = cmd + idx;
|
ssh->scpBasePath = cmd + idx;
|
||||||
|
clean_path((char*)ssh->scpBasePath);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
|
@ -1113,6 +1117,7 @@ int ParseScpCommand(WOLFSSH* ssh)
|
||||||
/* skip space */
|
/* skip space */
|
||||||
idx += 2;
|
idx += 2;
|
||||||
ssh->scpBasePath = cmd + idx;
|
ssh->scpBasePath = cmd + idx;
|
||||||
|
clean_path((char*)ssh->scpBasePath);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
} /* end switch */
|
} /* end switch */
|
||||||
|
@ -1207,6 +1212,9 @@ int ReceiveScpFile(WOLFSSH* ssh)
|
||||||
|
|
||||||
partSz = min(ssh->scpFileSz - ssh->scpFileOffset, DEFAULT_SCP_BUFFER_SZ);
|
partSz = min(ssh->scpFileSz - ssh->scpFileOffset, DEFAULT_SCP_BUFFER_SZ);
|
||||||
|
|
||||||
|
/* don't even bother reading if read size is 0 */
|
||||||
|
if (partSz == 0) return ret;
|
||||||
|
|
||||||
part = (byte*)WMALLOC(partSz, ssh->ctx->heap, DYNTYPE_BUFFER);
|
part = (byte*)WMALLOC(partSz, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||||
if (part == NULL)
|
if (part == NULL)
|
||||||
ret = WS_MEMORY_E;
|
ret = WS_MEMORY_E;
|
||||||
|
@ -1400,7 +1408,7 @@ static int SetTimestampInfo(const char* fileName, word64 mTime, word64 aTime)
|
||||||
tmp[1].tv_sec = mTime;
|
tmp[1].tv_sec = mTime;
|
||||||
tmp[1].tv_usec = 0;
|
tmp[1].tv_usec = 0;
|
||||||
|
|
||||||
ret = utimes(fileName, tmp);
|
ret = WUTIMES(fileName, tmp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1472,24 +1480,73 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
|
||||||
int ret = WS_SCP_CONTINUE;
|
int ret = WS_SCP_CONTINUE;
|
||||||
word32 bytes;
|
word32 bytes;
|
||||||
|
|
||||||
if (ctx != NULL)
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
char abslut[WOLFSSH_MAX_FILENAME];
|
||||||
|
fp = (WFILE*)&ssh->scpFd; /* uses file descriptor for file operations */
|
||||||
|
abslut[0] = '\0';
|
||||||
|
#endif
|
||||||
|
|
||||||
|
if (ctx != NULL) {
|
||||||
fp = (WFILE*)ctx;
|
fp = (WFILE*)ctx;
|
||||||
|
}
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
|
||||||
case WOLFSSH_SCP_NEW_REQUEST:
|
case WOLFSSH_SCP_NEW_REQUEST:
|
||||||
|
|
||||||
/* cd into requested root path */
|
/* cd into requested root path */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
{
|
||||||
|
DSTAT stat;
|
||||||
|
|
||||||
|
clean_path((char*)basePath);
|
||||||
|
|
||||||
|
/* make sure is directory */
|
||||||
|
if ((ret = NU_Get_First(&stat, basePath)) != NU_SUCCESS) {
|
||||||
|
/* if back to root directory i.e. A:/ then handle case
|
||||||
|
* where file system has nothing in it. */
|
||||||
|
if (basePath[1] == ':' && ret == NUF_NOFILE) {
|
||||||
|
ret = WS_SCP_CONTINUE;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
wolfSSH_SetScpErrorMsg(ssh,
|
||||||
|
"invalid destination directory");
|
||||||
|
ret = WS_SCP_ABORT;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = WS_SCP_CONTINUE;
|
||||||
|
|
||||||
|
/* check to make sure that it is a directory */
|
||||||
|
if ((stat.fattribute & ADIRENT) == 0) {
|
||||||
|
wolfSSH_SetScpErrorMsg(ssh,
|
||||||
|
"invalid destination directory");
|
||||||
|
ret = WS_SCP_ABORT;
|
||||||
|
}
|
||||||
|
NU_Done(&stat);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
if (WCHDIR(basePath) != 0) {
|
if (WCHDIR(basePath) != 0) {
|
||||||
wolfSSH_SetScpErrorMsg(ssh, "invalid destination directory");
|
wolfSSH_SetScpErrorMsg(ssh, "invalid destination directory");
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WOLFSSH_SCP_NEW_FILE:
|
case WOLFSSH_SCP_NEW_FILE:
|
||||||
|
|
||||||
/* open file */
|
/* open file */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
/* use absolute path */
|
||||||
|
WSTRNCAT(abslut, (char*)basePath, WOLFSSH_MAX_FILENAME);
|
||||||
|
WSTRNCAT(abslut, "/", sizeof("/"));
|
||||||
|
WSTRNCAT(abslut, fileName, WSTRLEN(fileName));
|
||||||
|
clean_path(abslut);
|
||||||
|
if (WFOPEN(&fp, abslut, "wb") != 0) {
|
||||||
|
#else
|
||||||
if (WFOPEN(&fp, fileName, "wb") != 0) {
|
if (WFOPEN(&fp, fileName, "wb") != 0) {
|
||||||
|
#endif
|
||||||
wolfSSH_SetScpErrorMsg(ssh, "unable to open file for writing");
|
wolfSSH_SetScpErrorMsg(ssh, "unable to open file for writing");
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
break;
|
break;
|
||||||
|
@ -1505,7 +1562,6 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* read file, or file part */
|
/* read file, or file part */
|
||||||
bytes = (word32)WFWRITE(buf, 1, bufSz, fp);
|
bytes = (word32)WFWRITE(buf, 1, bufSz, fp);
|
||||||
if (bytes != bufSz) {
|
if (bytes != bufSz) {
|
||||||
|
@ -1537,7 +1593,16 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
|
||||||
case WOLFSSH_SCP_NEW_DIR:
|
case WOLFSSH_SCP_NEW_DIR:
|
||||||
|
|
||||||
/* try to create new directory */
|
/* try to create new directory */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
/* get absolute path */
|
||||||
|
WSTRNCAT(abslut, (char*)basePath, WOLFSSH_MAX_FILENAME);
|
||||||
|
WSTRNCAT(abslut, "/", sizeof("/"));
|
||||||
|
WSTRNCAT(abslut, fileName, WSTRLEN(fileName));
|
||||||
|
clean_path(abslut);
|
||||||
|
if (WMKDIR(abslut, fileMode) != 0) {
|
||||||
|
#else
|
||||||
if (WMKDIR(fileName, fileMode) != 0) {
|
if (WMKDIR(fileName, fileMode) != 0) {
|
||||||
|
#endif
|
||||||
if (wolfSSH_LastError() != EEXIST) {
|
if (wolfSSH_LastError() != EEXIST) {
|
||||||
wolfSSH_SetScpErrorMsg(ssh, "error creating directory");
|
wolfSSH_SetScpErrorMsg(ssh, "error creating directory");
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
|
@ -1546,19 +1611,30 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* cd into directory */
|
/* cd into directory */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
WSTRNCAT((char*)basePath, "/", sizeof("/"));
|
||||||
|
WSTRNCAT((char*)basePath, fileName, WOLFSSH_MAX_FILENAME);
|
||||||
|
clean_path((char*)basePath);
|
||||||
|
#else
|
||||||
if (WCHDIR(fileName) != 0) {
|
if (WCHDIR(fileName) != 0) {
|
||||||
wolfSSH_SetScpErrorMsg(ssh, "unable to cd into directory");
|
wolfSSH_SetScpErrorMsg(ssh, "unable to cd into directory");
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WOLFSSH_SCP_END_DIR:
|
case WOLFSSH_SCP_END_DIR:
|
||||||
|
|
||||||
/* cd out of directory */
|
/* cd out of directory */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
WSTRNCAT((char*)basePath, "/..", WOLFSSH_MAX_FILENAME - 1);
|
||||||
|
clean_path((char*)basePath);
|
||||||
|
#else
|
||||||
if (WCHDIR("..") != 0) {
|
if (WCHDIR("..") != 0) {
|
||||||
wolfSSH_SetScpErrorMsg(ssh, "unable to cd out of directory");
|
wolfSSH_SetScpErrorMsg(ssh, "unable to cd out of directory");
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
}
|
}
|
||||||
|
#endif
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
@ -1629,13 +1705,27 @@ static int GetFileStats(ScpSendCtx* ctx, const char* fileName,
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get file stats for times and mode */
|
/* get file stats for times and mode */
|
||||||
if (stat(fileName, &ctx->s) < 0) {
|
if (WSTAT(fileName, &ctx->s) < 0) {
|
||||||
ret = WS_BAD_FILE_E;
|
ret = WS_BAD_FILE_E;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
if (ctx->s.fattribute & ARDONLY) {
|
||||||
|
*fileMode = 0x124; /* octal 444 */
|
||||||
|
}
|
||||||
|
if (ctx->s.fattribute == ANORMAL) { /* ANORMAL = 0 */
|
||||||
|
*fileMode = 0x1B6; /* octal 666 */
|
||||||
|
}
|
||||||
|
if (ctx->s.fattribute == ADIRENT) {
|
||||||
|
*fileMode = 0x1ED; /* octal 755 */
|
||||||
|
}
|
||||||
|
*mTime = ctx->s.fupdate;
|
||||||
|
*aTime = ctx->s.faccdate;
|
||||||
|
#else
|
||||||
*mTime = (word64)ctx->s.st_mtime;
|
*mTime = (word64)ctx->s.st_mtime;
|
||||||
*aTime = (word64)ctx->s.st_atime;
|
*aTime = (word64)ctx->s.st_atime;
|
||||||
*fileMode = ctx->s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
*fileMode = ctx->s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
return ret;
|
return ret;
|
||||||
|
@ -1660,8 +1750,11 @@ static ScpDir* ScpNewDir(const char* path, void* heap)
|
||||||
}
|
}
|
||||||
|
|
||||||
entry->next = NULL;
|
entry->next = NULL;
|
||||||
entry->dir = opendir(path);
|
if (WOPENDIR(&entry->dir, path) != 0
|
||||||
if (entry->dir == NULL) {
|
#ifndef WOLFSSL_NUCLEUS
|
||||||
|
|| entry->dir == NULL
|
||||||
|
#endif
|
||||||
|
) {
|
||||||
WFREE(entry, heap, DYNTYPE_SCPDIR);
|
WFREE(entry, heap, DYNTYPE_SCPDIR);
|
||||||
WLOG(WS_LOG_ERROR, scpError, "opendir failed on directory",
|
WLOG(WS_LOG_ERROR, scpError, "opendir failed on directory",
|
||||||
WS_INVALID_PATH_E);
|
WS_INVALID_PATH_E);
|
||||||
|
@ -1710,7 +1803,7 @@ static int ScpPopDir(ScpSendCtx* ctx, void* heap)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (entry != NULL) {
|
if (entry != NULL) {
|
||||||
closedir(entry->dir);
|
WCLOSEDIR(&entry->dir);
|
||||||
WFREE(entry, heap, DYNTYPE_SCPDIR);
|
WFREE(entry, heap, DYNTYPE_SCPDIR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1742,11 +1835,25 @@ static int FindNextDirEntry(ScpSendCtx* ctx)
|
||||||
return WS_BAD_ARGUMENT;
|
return WS_BAD_ARGUMENT;
|
||||||
|
|
||||||
/* skip self (.) and parent (..) directories */
|
/* skip self (.) and parent (..) directories */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
{
|
||||||
|
WDIR* dr;
|
||||||
|
do {
|
||||||
|
dr = WREADDIR(&ctx->currentDir->dir);
|
||||||
|
} while (dr != NULL &&
|
||||||
|
(WSTRNCMP(ctx->currentDir->dir.lfname, ".", 1) == 0 ||
|
||||||
|
WSTRNCMP(ctx->currentDir->dir.lfname ,"..", 2) == 0));
|
||||||
|
if (dr == NULL) {
|
||||||
|
return WS_NEXT_ERROR;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
do {
|
do {
|
||||||
ctx->entry = readdir(ctx->currentDir->dir);
|
ctx->entry = WREADDIR(&ctx->currentDir->dir);
|
||||||
} while ((ctx->entry != NULL) &&
|
} while ((ctx->entry != NULL) &&
|
||||||
(WSTRNCMP(ctx->entry->d_name, ".", 1) == 0 ||
|
(WSTRNCMP(ctx->entry->d_name, ".", 1) == 0 ||
|
||||||
WSTRNCMP(ctx->entry->d_name ,"..", 2) == 0));
|
WSTRNCMP(ctx->entry->d_name ,"..", 2) == 0));
|
||||||
|
#endif
|
||||||
|
|
||||||
return WS_SUCCESS;
|
return WS_SUCCESS;
|
||||||
}
|
}
|
||||||
|
@ -1760,14 +1867,23 @@ static int ScpDirStackIsEmpty(ScpSendCtx* ctx)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* returns 1 if is directory */
|
||||||
static int ScpFileIsDir(ScpSendCtx* ctx)
|
static int ScpFileIsDir(ScpSendCtx* ctx)
|
||||||
{
|
{
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
return (ctx->s.fattribute & ADIRENT);
|
||||||
|
#else
|
||||||
return S_ISDIR(ctx->s.st_mode);
|
return S_ISDIR(ctx->s.st_mode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
static int ScpFileIsFile(ScpSendCtx* ctx)
|
static int ScpFileIsFile(ScpSendCtx* ctx)
|
||||||
{
|
{
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
return (ctx->s.fattribute != ADIRENT);
|
||||||
|
#else
|
||||||
return S_ISREG(ctx->s.st_mode);
|
return S_ISREG(ctx->s.st_mode);
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Default SCP send callback, called by wolfSSH when an application has called
|
/* Default SCP send callback, called by wolfSSH when an application has called
|
||||||
|
@ -1858,6 +1974,10 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
sendCtx = (ScpSendCtx*)ctx;
|
sendCtx = (ScpSendCtx*)ctx;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
if (sendCtx != NULL) sendCtx->fp = &sendCtx->fd;
|
||||||
|
#endif
|
||||||
|
|
||||||
WMEMSET(filePath, 0, DEFAULT_SCP_FILE_NAME_SZ);
|
WMEMSET(filePath, 0, DEFAULT_SCP_FILE_NAME_SZ);
|
||||||
|
|
||||||
switch (state) {
|
switch (state) {
|
||||||
|
@ -1873,16 +1993,21 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case WOLFSSH_SCP_SINGLE_FILE_REQUEST:
|
case WOLFSSH_SCP_SINGLE_FILE_REQUEST:
|
||||||
|
|
||||||
if ((sendCtx == NULL) || WFOPEN(&(sendCtx->fp), peerRequest,
|
if ((sendCtx == NULL) || WFOPEN(&(sendCtx->fp), peerRequest,
|
||||||
"rb") != 0) {
|
"rb") != 0) {
|
||||||
|
|
||||||
wolfSSH_SetScpErrorMsg(ssh, "unable to open file for reading");
|
wolfSSH_SetScpErrorMsg(ssh, "unable to open file for reading");
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS) {
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
if (sendCtx->fd < 0)
|
||||||
|
ret = WS_SCP_ABORT;
|
||||||
|
#else
|
||||||
if (sendCtx->fp == NULL)
|
if (sendCtx->fp == NULL)
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
if (ret == WS_SUCCESS)
|
if (ret == WS_SUCCESS)
|
||||||
|
@ -1936,10 +2061,14 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = FindNextDirEntry(sendCtx);
|
ret = FindNextDirEntry(sendCtx);
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS || ret == WS_NEXT_ERROR) {
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
if (ret == WS_NEXT_ERROR) {
|
||||||
|
#else
|
||||||
/* reached end of directory */
|
/* reached end of directory */
|
||||||
if (sendCtx->entry == NULL) {
|
if (sendCtx->entry == NULL) {
|
||||||
|
#endif
|
||||||
ret = ScpPopDir(sendCtx, ssh->ctx->heap);
|
ret = ScpPopDir(sendCtx, ssh->ctx->heap);
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS) {
|
||||||
ret = WS_SCP_EXIT_DIR;
|
ret = WS_SCP_EXIT_DIR;
|
||||||
|
@ -1959,8 +2088,11 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
if (ret == WS_SUCCESS) {
|
if (ret == WS_SUCCESS) {
|
||||||
|
|
||||||
dirNameLen = (int)WSTRLEN(sendCtx->dirName);
|
dirNameLen = (int)WSTRLEN(sendCtx->dirName);
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
dNameLen = (int)WSTRLEN(sendCtx->currentDir->dir.lfname);
|
||||||
|
#else
|
||||||
dNameLen = (int)WSTRLEN(sendCtx->entry->d_name);
|
dNameLen = (int)WSTRLEN(sendCtx->entry->d_name);
|
||||||
|
#endif
|
||||||
if ((dirNameLen + 1 + dNameLen) > DEFAULT_SCP_FILE_NAME_SZ) {
|
if ((dirNameLen + 1 + dNameLen) > DEFAULT_SCP_FILE_NAME_SZ) {
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
|
|
||||||
|
@ -1968,11 +2100,19 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
WSTRNCPY(filePath, sendCtx->dirName,
|
WSTRNCPY(filePath, sendCtx->dirName,
|
||||||
DEFAULT_SCP_FILE_NAME_SZ);
|
DEFAULT_SCP_FILE_NAME_SZ);
|
||||||
WSTRNCAT(filePath, "/", 1);
|
WSTRNCAT(filePath, "/", 1);
|
||||||
|
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
WSTRNCAT(filePath, sendCtx->currentDir->dir.lfname,
|
||||||
|
DEFAULT_SCP_FILE_NAME_SZ - 1 - dirNameLen);
|
||||||
|
WSTRNCPY(fileName, sendCtx->currentDir->dir.lfname,
|
||||||
|
DEFAULT_SCP_FILE_NAME_SZ);
|
||||||
|
clean_path(filePath);
|
||||||
|
#else
|
||||||
WSTRNCAT(filePath, sendCtx->entry->d_name,
|
WSTRNCAT(filePath, sendCtx->entry->d_name,
|
||||||
DEFAULT_SCP_FILE_NAME_SZ - 1 - dirNameLen);
|
DEFAULT_SCP_FILE_NAME_SZ - 1 - dirNameLen);
|
||||||
WSTRNCPY(fileName, sendCtx->entry->d_name,
|
WSTRNCPY(fileName, sendCtx->entry->d_name,
|
||||||
DEFAULT_SCP_FILE_NAME_SZ);
|
DEFAULT_SCP_FILE_NAME_SZ);
|
||||||
|
#endif
|
||||||
ret = GetFileStats(sendCtx, filePath, mTime, aTime,
|
ret = GetFileStats(sendCtx, filePath, mTime, aTime,
|
||||||
fileMode);
|
fileMode);
|
||||||
}
|
}
|
||||||
|
@ -2012,6 +2152,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
ret = WS_SCP_ABORT;
|
ret = WS_SCP_ABORT;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2025,7 +2166,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest,
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp);
|
ret = (word32)WFREAD(buf, 1, bufSz, sendCtx->fp);
|
||||||
if ((ret < 0) || (fileOffset + ret == *totalFileSz)) {
|
if ((ret <= 0) || (fileOffset + ret == *totalFileSz)) {
|
||||||
WFCLOSE(sendCtx->fp);
|
WFCLOSE(sendCtx->fp);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
126
src/wolfsftp.c
126
src/wolfsftp.c
|
@ -23,9 +23,11 @@
|
||||||
#include <config.h>
|
#include <config.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#include <wolfssh/ssh.h>
|
|
||||||
#include <wolfssh/internal.h>
|
|
||||||
#include <wolfssh/wolfsftp.h>
|
#include <wolfssh/wolfsftp.h>
|
||||||
|
|
||||||
|
#ifdef WOLFSSH_SFTP
|
||||||
|
|
||||||
|
#include <wolfssh/internal.h>
|
||||||
#include <wolfssh/log.h>
|
#include <wolfssh/log.h>
|
||||||
|
|
||||||
#ifdef NO_INLINE
|
#ifdef NO_INLINE
|
||||||
|
@ -306,115 +308,6 @@ static int SFTP_SetAtributes(WOLFSSH* ssh, byte* buf, word32 bufSz,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* cleans up absolute path */
|
|
||||||
static void clean_path(char* path)
|
|
||||||
{
|
|
||||||
int i;
|
|
||||||
long sz = (long)WSTRLEN(path);
|
|
||||||
byte found;
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_NUCLEUS
|
|
||||||
for (i = 0; i < sz; i++) {
|
|
||||||
if (path[i] == '/') path[i] = '\\';
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
/* remove any ./ patterns */
|
|
||||||
for (i = 1; i < sz - 1; i++) {
|
|
||||||
if (path[i] == '.' && path[i - 1] != '.' && path[i + 1] == WS_DELIM) {
|
|
||||||
WMEMMOVE(path + i, path + i + 1, sz - i - 1);
|
|
||||||
path[sz - 1] = '\0';
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sz = (int)WSTRLEN(path);
|
|
||||||
|
|
||||||
/* remove any double '/' or '\' chars */
|
|
||||||
for (i = 0; i < sz; i++) {
|
|
||||||
if ((path[i] == WS_DELIM && path[i+1] == WS_DELIM)) {
|
|
||||||
WMEMMOVE(path + i, path + i + 1, sz - i + 1);
|
|
||||||
sz -= 1;
|
|
||||||
i--;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (path != NULL) {
|
|
||||||
/* go through path until no cases are found */
|
|
||||||
do {
|
|
||||||
sz = WSTRLEN(path);
|
|
||||||
int prIdx = 0; /* begin of cut */
|
|
||||||
int enIdx = 0; /* end of cut */
|
|
||||||
|
|
||||||
found = 0;
|
|
||||||
for (i = 1; i < sz; i++) {
|
|
||||||
if (path[i] == WS_DELIM) {
|
|
||||||
int z;
|
|
||||||
|
|
||||||
/* if next two chars are .. then delete */
|
|
||||||
if (path[i+1] == '.' && path[i+2] == '.') {
|
|
||||||
enIdx = i + 3;
|
|
||||||
|
|
||||||
/* start at one char before / and retrace path */
|
|
||||||
for (z = i - 1; z > 0; z--) {
|
|
||||||
if (path[z] == WS_DELIM || path[z] == ':') {
|
|
||||||
prIdx = z;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
/* cut out .. and previous */
|
|
||||||
WMEMMOVE(path + prIdx, path + enIdx, sz - enIdx);
|
|
||||||
path[sz - (enIdx - prIdx)] = '\0';
|
|
||||||
|
|
||||||
if (enIdx == sz) {
|
|
||||||
path[prIdx] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* case of at / */
|
|
||||||
if (WSTRLEN(path) == 0) {
|
|
||||||
path[0] = '/';
|
|
||||||
path[1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
found = 1;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} while (found);
|
|
||||||
|
|
||||||
#ifdef WOLFSSL_NUCLEUS
|
|
||||||
sz = WSTRLEN(path);
|
|
||||||
if (path[sz - 1] == ':') {
|
|
||||||
path[sz] = WS_DELIM;
|
|
||||||
path[sz + 1] = '\0';
|
|
||||||
}
|
|
||||||
|
|
||||||
/* clean up any multiple drive listed i.e. A:/A: */
|
|
||||||
{
|
|
||||||
int i,j;
|
|
||||||
sz = WSTRLEN(path);
|
|
||||||
for (i = 0, j = 0; i < sz; i++) {
|
|
||||||
if (path[i] == ':') {
|
|
||||||
if (j == 0) j = i;
|
|
||||||
else {
|
|
||||||
/* @TODO only checking once */
|
|
||||||
WMEMMOVE(path, path + i - WS_DRIVE_SIZE, sz - i + WS_DRIVE_SIZE);
|
|
||||||
path[sz - i + WS_DRIVE_SIZE] = '\0';
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
/* remove trailing delimiter */
|
|
||||||
if (sz > 3 && path[sz - 1] == WS_DELIM) {
|
|
||||||
path[sz - 1] = '\0';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* returns WS_SUCCESS on success */
|
/* returns WS_SUCCESS on success */
|
||||||
static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
||||||
{
|
{
|
||||||
|
@ -1089,7 +982,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
||||||
return WS_BAD_ARGUMENT;
|
return WS_BAD_ARGUMENT;
|
||||||
}
|
}
|
||||||
|
|
||||||
dp = WREADDIR(*dir);
|
dp = WREADDIR(dir);
|
||||||
if (dp == NULL) {
|
if (dp == NULL) {
|
||||||
return WS_FATAL_ERROR;
|
return WS_FATAL_ERROR;
|
||||||
}
|
}
|
||||||
|
@ -1290,11 +1183,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
||||||
int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
||||||
{
|
{
|
||||||
DIR_HANDLE* cur = dirList;
|
DIR_HANDLE* cur = dirList;
|
||||||
#ifdef WOLFSSL_NUCLEUS
|
|
||||||
WDIR* dir = NULL;
|
WDIR* dir = NULL;
|
||||||
#else
|
|
||||||
WDIR dir = NULL;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
if (ssh == NULL || handle == NULL || handleSz != sizeof(word64)) {
|
if (ssh == NULL || handle == NULL || handleSz != sizeof(word64)) {
|
||||||
return WS_BAD_ARGUMENT;
|
return WS_BAD_ARGUMENT;
|
||||||
|
@ -1305,11 +1194,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
||||||
/* find DIR given handle */
|
/* find DIR given handle */
|
||||||
while (cur != NULL) {
|
while (cur != NULL) {
|
||||||
if (cur->id == *((word64*)handle)) {
|
if (cur->id == *((word64*)handle)) {
|
||||||
#ifdef WOLFSSL_NUCLEUS
|
|
||||||
dir = &cur->dir;
|
dir = &cur->dir;
|
||||||
#else
|
|
||||||
dir = cur->dir;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
cur = cur->next;
|
cur = cur->next;
|
||||||
|
@ -4024,3 +3909,4 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#endif /* WOLFSSH_SFTP */
|
||||||
|
|
|
@ -303,6 +303,9 @@ struct WOLFSSH {
|
||||||
word32 scpFileBufferSz; /* size of transfer buffer, octets */
|
word32 scpFileBufferSz; /* size of transfer buffer, octets */
|
||||||
word32 scpFileOffset; /* current offset into file transfer */
|
word32 scpFileOffset; /* current offset into file transfer */
|
||||||
word32 scpBufferedSz; /* bytes buffered to send to peer */
|
word32 scpBufferedSz; /* bytes buffered to send to peer */
|
||||||
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
int scpFd; /* SCP receive callback context handle */
|
||||||
|
#endif
|
||||||
void* scpRecvCtx; /* SCP receive callback context handle */
|
void* scpRecvCtx; /* SCP receive callback context handle */
|
||||||
void* scpSendCtx; /* SCP send callback context handle */
|
void* scpSendCtx; /* SCP send callback context handle */
|
||||||
#if !defined(WOLFSSH_SCP_USER_CALLBACKS) && !defined(NO_FILESYSTEM)
|
#if !defined(WOLFSSH_SCP_USER_CALLBACKS) && !defined(NO_FILESYSTEM)
|
||||||
|
@ -657,6 +660,7 @@ WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH*, int, const char*, char*, word32,
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
WOLFSSH_LOCAL void clean_path(char* path);
|
||||||
WOLFSSH_LOCAL void DumpOctetString(const byte*, word32);
|
WOLFSSH_LOCAL void DumpOctetString(const byte*, word32);
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -54,13 +54,41 @@ extern "C" {
|
||||||
|
|
||||||
#ifndef NO_FILESYSTEM
|
#ifndef NO_FILESYSTEM
|
||||||
#ifdef WOLFSSL_NUCLEUS
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
|
#include "storage/nu_storage.h"
|
||||||
|
|
||||||
#define WFILE int
|
#define WFILE int
|
||||||
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
|
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
|
||||||
|
|
||||||
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m))
|
#define WFOPEN(f,fn,m) wfopen((f),(fn),(m))
|
||||||
#define WFCLOSE(f) NU_Close(*(f))
|
#define WFCLOSE(f) NU_Close(*(f))
|
||||||
#define WFWRITE(b,x,s,f) NU_Write(*(f),(const CHAR*)(b),(s))
|
#define WFWRITE(b,x,s,f) ((s) != 0)? NU_Write(*(f),(const CHAR*)(b),(s)): 0
|
||||||
#define WFREAD(b,x,s,f) NU_Read(*(f),(CHAR*)(b),(s))
|
#define WFREAD(b,x,s,f) NU_Read(*(f),(CHAR*)(b),(s))
|
||||||
|
#define WFSEEK(s,o,w) NU_Seek(*(s),(o),(w))
|
||||||
|
#define WFTELL(s) NU_Seek(*(s), 0, PSEEK_CUR)
|
||||||
|
#define WREWIND(s) NU_Seek(*(s), 0, PSEEK_SET)
|
||||||
|
#define WSEEK_END PSEEK_END
|
||||||
|
|
||||||
|
#define WS_DELIM '\\'
|
||||||
|
#define WOLFSSH_O_RDWR PO_RDWR
|
||||||
|
#define WOLFSSH_O_RDONLY PO_RDONLY
|
||||||
|
#define WOLFSSH_O_WRONLY PO_WRONLY
|
||||||
|
#define WOLFSSH_O_APPEND PO_APPEND
|
||||||
|
#define WOLFSSH_O_CREAT PO_CREAT
|
||||||
|
#define WOLFSSH_O_TRUNC PO_TRUNC
|
||||||
|
#define WOLFSSH_O_EXCL PO_EXCL
|
||||||
|
|
||||||
|
#ifndef WOPEN
|
||||||
|
static inline int wOpen(const char* f, short flag, short mode)
|
||||||
|
{
|
||||||
|
/* @TODO could use PS_IWRITE only or PS_IREAD only? */
|
||||||
|
return NU_Open(f, PO_TEXT | flag, (PS_IWRITE | PS_IREAD));
|
||||||
|
}
|
||||||
|
|
||||||
|
#define WOPEN(f,m,p) wOpen((f),(m),(p))
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define WCLOSE(fd) NU_Close((fd))
|
||||||
|
|
||||||
#else
|
#else
|
||||||
#define WFILE FILE
|
#define WFILE FILE
|
||||||
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
|
WOLFSSH_API int wfopen(WFILE**, const char*, const char*);
|
||||||
|
@ -73,6 +101,7 @@ extern "C" {
|
||||||
#define WFTELL(s) ftell((s))
|
#define WFTELL(s) ftell((s))
|
||||||
#define WREWIND(s) rewind((s))
|
#define WREWIND(s) rewind((s))
|
||||||
#define WSEEK_END SEEK_END
|
#define WSEEK_END SEEK_END
|
||||||
|
#define WUTIMES(f,t) utimes((f),(t))
|
||||||
|
|
||||||
#if (defined(WOLFSSH_SCP) || defined(WOLFSSH_SFTP)) && \
|
#if (defined(WOLFSSH_SCP) || defined(WOLFSSH_SFTP)) && \
|
||||||
!defined(WOLFSSH_SCP_USER_CALLBACKS) && \
|
!defined(WOLFSSH_SCP_USER_CALLBACKS) && \
|
||||||
|
@ -139,17 +168,16 @@ extern "C" {
|
||||||
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
|
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(WOLFSSH_SFTP) && !defined(NO_WOLFSSH_SERVER)
|
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
||||||
|
!defined(NO_WOLFSSH_SERVER)
|
||||||
#ifdef WOLFSSL_NUCLEUS
|
#ifdef WOLFSSL_NUCLEUS
|
||||||
#include "storage/nu_storage.h"
|
|
||||||
|
|
||||||
#define WRMDIR(d) (NU_Remove_Dir((d)) == NU_SUCCESS)?0:1
|
#define WRMDIR(d) (NU_Remove_Dir((d)) == NU_SUCCESS)?0:1
|
||||||
#define WMKDIR(d,m) (NU_Make_Dir((d)) == NU_SUCCESS)?0:1
|
#define WMKDIR(d,m) (NU_Make_Dir((d)) == NU_SUCCESS)?0:1
|
||||||
#define WSTAT(p,b) NU_Get_First((b),(p))
|
#define WSTAT(p,b) NU_Get_First((b),(p))
|
||||||
#define WLSTAT(p,b) NU_Get_First((b),(p))
|
#define WLSTAT(p,b) NU_Get_First((b),(p))
|
||||||
#define WREMOVE(d) NU_Delete((d))
|
#define WREMOVE(d) NU_Delete((d))
|
||||||
#define WRENAME(o,n) NU_Rename((o),(n))
|
#define WRENAME(o,n) NU_Rename((o),(n))
|
||||||
#define WS_DELIM '\\'
|
#define WFD int
|
||||||
|
|
||||||
#ifndef WGETCWD
|
#ifndef WGETCWD
|
||||||
static inline char* wGetCwd(char* buf, unsigned int bufSz)
|
static inline char* wGetCwd(char* buf, unsigned int bufSz)
|
||||||
|
@ -175,28 +203,6 @@ extern "C" {
|
||||||
#define WGETCWD(r,rSz) wGetCwd((r),(rSz))
|
#define WGETCWD(r,rSz) wGetCwd((r),(rSz))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#define WOLFSSH_O_RDWR PO_RDWR
|
|
||||||
#define WOLFSSH_O_RDONLY PO_RDONLY
|
|
||||||
#define WOLFSSH_O_WRONLY PO_WRONLY
|
|
||||||
#define WOLFSSH_O_APPEND PO_APPEND
|
|
||||||
#define WOLFSSH_O_CREAT PO_CREAT
|
|
||||||
#define WOLFSSH_O_TRUNC PO_TRUNC
|
|
||||||
#define WOLFSSH_O_EXCL PO_EXCL
|
|
||||||
|
|
||||||
#define WFD int
|
|
||||||
|
|
||||||
#ifndef WOPEN
|
|
||||||
static inline int wOpen(char* f, short flag, short mode)
|
|
||||||
{
|
|
||||||
/* @TODO could use PS_IWRITE only or PS_IREAD only? */
|
|
||||||
return NU_Open(f, PO_TEXT | flag, (PS_IWRITE | PS_IREAD));
|
|
||||||
}
|
|
||||||
|
|
||||||
#define WOPEN(f,m,p) wOpen((f),(m),(p))
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#define WCLOSE(fd) NU_Close((fd))
|
|
||||||
|
|
||||||
#ifndef WPWRITE
|
#ifndef WPWRITE
|
||||||
static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, long ofst)
|
static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, long ofst)
|
||||||
{
|
{
|
||||||
|
@ -221,11 +227,31 @@ extern "C" {
|
||||||
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o))
|
#define WPREAD(fd,b,s,o) wPread((fd),(b),(s),(o))
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
static inline int wUtimes(const char* f, struct timeval t[2])
|
||||||
|
{
|
||||||
|
DSTAT stat;
|
||||||
|
int ret = -1;
|
||||||
|
|
||||||
|
if (NU_Get_First(&stat, f) == NU_SUCCESS) {
|
||||||
|
ret = NU_Utime(&stat, 0xFFFF, t[0].tv_sec, 0xFFFF, t[1].tv_sec,
|
||||||
|
0xFFFF, 0xFFFF);
|
||||||
|
NU_Done(&stat);
|
||||||
|
if (ret == NU_SUCCESS) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#define WUTIMES(f,t) wUtimes((f), (t))
|
||||||
|
|
||||||
#ifndef NO_WOLFSSL_DIR
|
#ifndef NO_WOLFSSL_DIR
|
||||||
#define WDIR DSTAT
|
#define WDIR DSTAT
|
||||||
|
|
||||||
#ifndef WOPENDIR
|
#ifndef WOPENDIR
|
||||||
static inline int wOpenDir(WDIR* d, char* dir)
|
static inline int wOpenDir(WDIR* d, const char* dir)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
int idx = WSTRLEN(dir);
|
int idx = WSTRLEN(dir);
|
||||||
|
@ -320,11 +346,11 @@ extern "C" {
|
||||||
|
|
||||||
/* returns 0 on success */
|
/* returns 0 on success */
|
||||||
#define WOPENDIR(c,d) ((*(c) = opendir((d))) == NULL)
|
#define WOPENDIR(c,d) ((*(c) = opendir((d))) == NULL)
|
||||||
#define WCLOSEDIR(d) closedir((d))
|
#define WCLOSEDIR(d) closedir(*(d))
|
||||||
#define WREADDIR(d) readdir((d))
|
#define WREADDIR(d) readdir(*(d))
|
||||||
#endif /* NO_WOLFSSL_DIR */
|
#endif /* NO_WOLFSSL_DIR */
|
||||||
#endif
|
#endif
|
||||||
#endif /* WOLFSSH_SFTP */
|
#endif /* WOLFSSH_SFTP or WOLFSSH_SCP */
|
||||||
|
|
||||||
/* setup compiler inlining */
|
/* setup compiler inlining */
|
||||||
#ifndef INLINE
|
#ifndef INLINE
|
||||||
|
|
|
@ -24,6 +24,7 @@
|
||||||
#define WOLFSSH_WOLFSCP_H
|
#define WOLFSSH_WOLFSCP_H
|
||||||
|
|
||||||
#include <wolfssh/settings.h>
|
#include <wolfssh/settings.h>
|
||||||
|
#include <wolfssh/ssh.h>
|
||||||
#include <wolfssh/port.h>
|
#include <wolfssh/port.h>
|
||||||
|
|
||||||
#ifdef WOLFSSH_SCP
|
#ifdef WOLFSSH_SCP
|
||||||
|
@ -57,15 +58,20 @@ extern "C" {
|
||||||
#include <errno.h>
|
#include <errno.h>
|
||||||
|
|
||||||
typedef struct ScpSendCtx {
|
typedef struct ScpSendCtx {
|
||||||
|
#ifndef WOLFSSL_NUCLEUS
|
||||||
struct dirent* entry; /* file entry, from readdir() */
|
struct dirent* entry; /* file entry, from readdir() */
|
||||||
struct ScpDir* currentDir; /* dir being copied, stack */
|
|
||||||
WFILE* fp; /* file pointer */
|
|
||||||
struct stat s; /* stat info from file */
|
struct stat s; /* stat info from file */
|
||||||
|
#else
|
||||||
|
int fd; /* file descriptor, in the case of Nucleus fp points to fd */
|
||||||
|
DSTAT s;
|
||||||
|
#endif
|
||||||
|
WFILE* fp; /* file pointer */
|
||||||
|
struct ScpDir* currentDir; /* dir being copied, stack */
|
||||||
char dirName[DEFAULT_SCP_FILE_NAME_SZ]; /* current dir name */
|
char dirName[DEFAULT_SCP_FILE_NAME_SZ]; /* current dir name */
|
||||||
} ScpSendCtx;
|
} ScpSendCtx;
|
||||||
|
|
||||||
typedef struct ScpDir {
|
typedef struct ScpDir {
|
||||||
DIR* dir; /* dir pointer, from opendir() */
|
WDIR dir; /* dir pointer, from opendir() */
|
||||||
struct ScpDir* next; /* previous directory in stack */
|
struct ScpDir* next; /* previous directory in stack */
|
||||||
} ScpDir;
|
} ScpDir;
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,8 @@
|
||||||
#include <wolfssl/options.h>
|
#include <wolfssl/options.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#include <wolfssh/ssh.h>
|
||||||
|
|
||||||
/* Packet Types */
|
/* Packet Types */
|
||||||
enum WS_PacketTypes {
|
enum WS_PacketTypes {
|
||||||
WOLFSSH_FTP_INIT = 1,
|
WOLFSSH_FTP_INIT = 1,
|
||||||
|
|
Loading…
Reference in New Issue