From 522d93add38c92dd36e509b87b31141ef398930a Mon Sep 17 00:00:00 2001 From: Jacob Barthelmeh Date: Wed, 13 Jun 2018 11:22:48 -0600 Subject: [PATCH] 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 nucleus --- examples/echoserver/echoserver.c | 12 +- src/internal.c | 112 +++++++++++++++++++ src/log.c | 2 +- src/port.c | 28 +++-- src/wolfscp.c | 185 +++++++++++++++++++++++++++---- src/wolfsftp.c | 126 +-------------------- wolfssh/internal.h | 4 + wolfssh/port.h | 88 +++++++++------ wolfssh/wolfscp.h | 12 +- wolfssh/wolfsftp.h | 2 + 10 files changed, 379 insertions(+), 192 deletions(-) diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 386dc9a2..7518f816 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -210,17 +210,19 @@ static THREAD_RETURN WOLFSSH_THREAD server_worker(void* vArgs) break; } - if (ret != 0) { - fprintf(stderr, "Error [%d] with handling connection.\n", ret); - exit(EXIT_FAILURE); - } - if (wolfSSH_shutdown(threadCtx->ssh) != WS_SUCCESS) { fprintf(stderr, "Error with SSH shutdown.\n"); } WCLOSESOCKET(threadCtx->fd); 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); return 0; diff --git a/src/internal.c b/src/internal.c index 8e278bc7..0a57a492 100644 --- a/src/internal.c +++ b/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 #define LINE_WIDTH 16 diff --git a/src/log.c b/src/log.c index 13235500..3bc43882 100644 --- a/src/log.c +++ b/src/log.c @@ -142,7 +142,7 @@ void DefaultLoggingCb(enum wolfSSH_LogLevel level, const char *const msgStr) } } #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 */ diff --git a/src/port.c b/src/port.c index 6f9278d4..ee552ab7 100644 --- a/src/port.c +++ b/src/port.c @@ -42,25 +42,33 @@ int wfopen(WFILE** f, const char* filename, const char* mode) return fopen_s(f, filename, mode) != 0; #elif defined(WOLFSSL_NUCLEUS) 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")) { - if (m &= WOLFSSH_O_RDONLY) { - m ^= WOLFSSH_O_RDONLY; - m |= WOLFSSH_O_RDWR; + else { + if (WSTRSTR(mode, "r")) { + m |= WOLFSSH_O_RDONLY; } - else { + if (WSTRSTR(mode, "w")) { m |= WOLFSSH_O_WRONLY; } } if (filename != NULL && f != NULL) { - **f = NU_Open(filename, m, 0); - return 1; + if ((**f = WOPEN(filename, m, 0)) < 0) { + return **f; + } + + /* fopen defaults to normal */ + if (NU_Set_Attributes(filename, 0) != NU_SUCCESS) { + WCLOSE(**f); + return 1; + } + return 0; } else { - return 0; + return 1; } #else if (f != NULL) { diff --git a/src/wolfscp.c b/src/wolfscp.c index bd4edb7b..723a5f8f 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -31,12 +31,14 @@ #include #endif +#include + #ifdef WOLFSSH_SCP #include #include #include -#include + #ifdef NO_INLINE #include @@ -71,7 +73,7 @@ int DoScpSink(WOLFSSH* ssh) ssh->scpConfirm = ssh->ctx->scpRecvCb(ssh, 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; case SCP_RECEIVE_MESSAGE: @@ -117,7 +119,7 @@ int DoScpSink(WOLFSSH* ssh) ssh->scpConfirm = ssh->ctx->scpRecvCb(ssh, ssh->scpFileState, ssh->scpBasePath, ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime, ssh->scpATime, ssh->scpFileSz, NULL, 0, - 0, ssh->scpRecvCtx); + 0, wolfSSH_GetScpRecvCtx(ssh)); continue; @@ -160,7 +162,7 @@ int DoScpSink(WOLFSSH* ssh) ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime, ssh->scpATime, ssh->scpFileSz, ssh->scpFileBuffer, ssh->scpFileBufferSz, ssh->scpFileOffset, - ssh->scpRecvCtx); + wolfSSH_GetScpRecvCtx(ssh)); ssh->scpFileOffset += ssh->scpFileBufferSz; @@ -183,7 +185,7 @@ int DoScpSink(WOLFSSH* ssh) WOLFSSH_SCP_FILE_DONE, ssh->scpBasePath, ssh->scpFileName, ssh->scpFileMode, ssh->scpMTime, ssh->scpATime, ssh->scpFileSz, NULL, 0, 0, - ssh->scpRecvCtx); + wolfSSH_GetScpRecvCtx(ssh)); ssh->scpFileOffset = 0; ssh->scpATime = 0; @@ -375,7 +377,7 @@ int DoScpSource(WOLFSSH* ssh) ssh->scpConfirm = ssh->ctx->scpSendCb(ssh, 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) { ssh->scpState = SCP_RECEIVE_CONFIRMATION_WITH_RECEIPT; @@ -451,7 +453,7 @@ int DoScpSource(WOLFSSH* ssh) &(ssh->scpATime), &(ssh->scpFileMode), ssh->scpFileOffset, &(ssh->scpFileSz), ssh->scpFileBuffer, ssh->scpFileBufferSz, - ssh->scpSendCtx); + wolfSSH_GetScpSendCtx(ssh)); if (ssh->scpConfirm == WS_SCP_ENTER_DIR) { ssh->scpState = SCP_SEND_ENTER_DIRECTORY; @@ -743,7 +745,7 @@ static int GetScpFileMode(WOLFSSH* ssh, byte* buf, word32 bufSz, { int ret; word32 idx; - byte modeOctet[SCP_MODE_OCTET_LEN]; + byte modeOctet[SCP_MODE_OCTET_LEN + 1]; #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ defined(WOLFSSL_DEBUG_MATH) || defined(DEBUG_WOLFSSL) || \ defined(WOLFSSL_PUBLIC_MP) @@ -764,7 +766,8 @@ static int GetScpFileMode(WOLFSSH* ssh, byte* buf, word32 bufSz, return WS_BAD_ARGUMENT; 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; #if defined(WOLFSSL_KEY_GEN) || defined(HAVE_COMP_KEY) || \ @@ -1104,6 +1107,7 @@ int ParseScpCommand(WOLFSSH* ssh) /* skip space */ idx += 2; ssh->scpBasePath = cmd + idx; + clean_path((char*)ssh->scpBasePath); } break; @@ -1113,6 +1117,7 @@ int ParseScpCommand(WOLFSSH* ssh) /* skip space */ idx += 2; ssh->scpBasePath = cmd + idx; + clean_path((char*)ssh->scpBasePath); } break; } /* end switch */ @@ -1207,6 +1212,9 @@ int ReceiveScpFile(WOLFSSH* ssh) 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); if (part == NULL) 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_usec = 0; - ret = utimes(fileName, tmp); + ret = WUTIMES(fileName, tmp); } return ret; @@ -1472,24 +1480,73 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, int ret = WS_SCP_CONTINUE; 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; + } switch (state) { case WOLFSSH_SCP_NEW_REQUEST: /* 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) { wolfSSH_SetScpErrorMsg(ssh, "invalid destination directory"); ret = WS_SCP_ABORT; } + #endif break; case WOLFSSH_SCP_NEW_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) { + #endif wolfSSH_SetScpErrorMsg(ssh, "unable to open file for writing"); ret = WS_SCP_ABORT; break; @@ -1505,7 +1562,6 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, ret = WS_SCP_ABORT; break; } - /* read file, or file part */ bytes = (word32)WFWRITE(buf, 1, bufSz, fp); if (bytes != bufSz) { @@ -1537,7 +1593,16 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, case WOLFSSH_SCP_NEW_DIR: /* 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) { +#endif if (wolfSSH_LastError() != EEXIST) { wolfSSH_SetScpErrorMsg(ssh, "error creating directory"); ret = WS_SCP_ABORT; @@ -1546,19 +1611,30 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, } /* 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) { wolfSSH_SetScpErrorMsg(ssh, "unable to cd into directory"); ret = WS_SCP_ABORT; } + #endif break; case WOLFSSH_SCP_END_DIR: /* cd out of directory */ + #ifdef WOLFSSL_NUCLEUS + WSTRNCAT((char*)basePath, "/..", WOLFSSH_MAX_FILENAME - 1); + clean_path((char*)basePath); + #else if (WCHDIR("..") != 0) { wolfSSH_SetScpErrorMsg(ssh, "unable to cd out of directory"); ret = WS_SCP_ABORT; } + #endif break; default: @@ -1629,13 +1705,27 @@ static int GetFileStats(ScpSendCtx* ctx, const char* fileName, } /* get file stats for times and mode */ - if (stat(fileName, &ctx->s) < 0) { + if (WSTAT(fileName, &ctx->s) < 0) { ret = WS_BAD_FILE_E; } 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; *aTime = (word64)ctx->s.st_atime; *fileMode = ctx->s.st_mode & (S_IRWXU | S_IRWXG | S_IRWXO); + #endif } return ret; @@ -1660,8 +1750,11 @@ static ScpDir* ScpNewDir(const char* path, void* heap) } entry->next = NULL; - entry->dir = opendir(path); - if (entry->dir == NULL) { + if (WOPENDIR(&entry->dir, path) != 0 + #ifndef WOLFSSL_NUCLEUS + || entry->dir == NULL + #endif + ) { WFREE(entry, heap, DYNTYPE_SCPDIR); WLOG(WS_LOG_ERROR, scpError, "opendir failed on directory", WS_INVALID_PATH_E); @@ -1710,7 +1803,7 @@ static int ScpPopDir(ScpSendCtx* ctx, void* heap) } if (entry != NULL) { - closedir(entry->dir); + WCLOSEDIR(&entry->dir); WFREE(entry, heap, DYNTYPE_SCPDIR); } @@ -1742,11 +1835,25 @@ static int FindNextDirEntry(ScpSendCtx* ctx) return WS_BAD_ARGUMENT; /* 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 { - ctx->entry = readdir(ctx->currentDir->dir); + ctx->entry = WREADDIR(&ctx->currentDir->dir); } while ((ctx->entry != NULL) && (WSTRNCMP(ctx->entry->d_name, ".", 1) == 0 || WSTRNCMP(ctx->entry->d_name ,"..", 2) == 0)); +#endif return WS_SUCCESS; } @@ -1760,14 +1867,23 @@ static int ScpDirStackIsEmpty(ScpSendCtx* ctx) return 0; } +/* returns 1 if is directory */ static int ScpFileIsDir(ScpSendCtx* ctx) { +#ifdef WOLFSSL_NUCLEUS + return (ctx->s.fattribute & ADIRENT); +#else return S_ISDIR(ctx->s.st_mode); +#endif } static int ScpFileIsFile(ScpSendCtx* ctx) { +#ifdef WOLFSSL_NUCLEUS + return (ctx->s.fattribute != ADIRENT); +#else return S_ISREG(ctx->s.st_mode); +#endif } /* 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; } +#ifdef WOLFSSL_NUCLEUS + if (sendCtx != NULL) sendCtx->fp = &sendCtx->fd; +#endif + WMEMSET(filePath, 0, DEFAULT_SCP_FILE_NAME_SZ); switch (state) { @@ -1873,16 +1993,21 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, break; case WOLFSSH_SCP_SINGLE_FILE_REQUEST: - if ((sendCtx == NULL) || WFOPEN(&(sendCtx->fp), peerRequest, "rb") != 0) { + wolfSSH_SetScpErrorMsg(ssh, "unable to open file for reading"); ret = WS_SCP_ABORT; } if (ret == WS_SUCCESS) { + #ifdef WOLFSSL_NUCLEUS + if (sendCtx->fd < 0) + ret = WS_SCP_ABORT; + #else if (sendCtx->fp == NULL) ret = WS_SCP_ABORT; + #endif } if (ret == WS_SUCCESS) @@ -1936,10 +2061,14 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, } 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 */ if (sendCtx->entry == NULL) { + #endif ret = ScpPopDir(sendCtx, ssh->ctx->heap); if (ret == WS_SUCCESS) { ret = WS_SCP_EXIT_DIR; @@ -1959,8 +2088,11 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, if (ret == WS_SUCCESS) { dirNameLen = (int)WSTRLEN(sendCtx->dirName); + #ifdef WOLFSSL_NUCLEUS + dNameLen = (int)WSTRLEN(sendCtx->currentDir->dir.lfname); + #else dNameLen = (int)WSTRLEN(sendCtx->entry->d_name); - + #endif if ((dirNameLen + 1 + dNameLen) > DEFAULT_SCP_FILE_NAME_SZ) { ret = WS_SCP_ABORT; @@ -1968,11 +2100,19 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, WSTRNCPY(filePath, sendCtx->dirName, DEFAULT_SCP_FILE_NAME_SZ); 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, DEFAULT_SCP_FILE_NAME_SZ - 1 - dirNameLen); WSTRNCPY(fileName, sendCtx->entry->d_name, DEFAULT_SCP_FILE_NAME_SZ); - + #endif ret = GetFileStats(sendCtx, filePath, mTime, aTime, fileMode); } @@ -2012,6 +2152,7 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, } } else { + 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); - if ((ret < 0) || (fileOffset + ret == *totalFileSz)) { + if ((ret <= 0) || (fileOffset + ret == *totalFileSz)) { WFCLOSE(sendCtx->fp); } diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 63ec9277..8bd7ac72 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -23,9 +23,11 @@ #include #endif -#include -#include #include + +#ifdef WOLFSSH_SFTP + +#include #include #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 */ 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; } - dp = WREADDIR(*dir); + dp = WREADDIR(dir); if (dp == NULL) { 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) { DIR_HANDLE* cur = dirList; -#ifdef WOLFSSL_NUCLEUS WDIR* dir = NULL; -#else - WDIR dir = NULL; -#endif if (ssh == NULL || handle == NULL || handleSz != sizeof(word64)) { return WS_BAD_ARGUMENT; @@ -1305,11 +1194,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz) /* find DIR given handle */ while (cur != NULL) { if (cur->id == *((word64*)handle)) { -#ifdef WOLFSSL_NUCLEUS dir = &cur->dir; -#else - dir = cur->dir; -#endif break; } cur = cur->next; @@ -4024,3 +3909,4 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume, return ret; } +#endif /* WOLFSSH_SFTP */ diff --git a/wolfssh/internal.h b/wolfssh/internal.h index bfeb08de..7a4973a4 100644 --- a/wolfssh/internal.h +++ b/wolfssh/internal.h @@ -303,6 +303,9 @@ struct WOLFSSH { word32 scpFileBufferSz; /* size of transfer buffer, octets */ word32 scpFileOffset; /* current offset into file transfer */ 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* scpSendCtx; /* SCP send callback context handle */ #if !defined(WOLFSSH_SCP_USER_CALLBACKS) && !defined(NO_FILESYSTEM) @@ -657,6 +660,7 @@ WOLFSSH_LOCAL int wsScpSendCallback(WOLFSSH*, int, const char*, char*, word32, #endif +WOLFSSH_LOCAL void clean_path(char* path); WOLFSSH_LOCAL void DumpOctetString(const byte*, word32); diff --git a/wolfssh/port.h b/wolfssh/port.h index 692a9782..7ce0e95e 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -54,13 +54,41 @@ extern "C" { #ifndef NO_FILESYSTEM #ifdef WOLFSSL_NUCLEUS + #include "storage/nu_storage.h" + #define WFILE int WOLFSSH_API int wfopen(WFILE**, const char*, const char*); #define WFOPEN(f,fn,m) wfopen((f),(fn),(m)) #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 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 #define WFILE FILE WOLFSSH_API int wfopen(WFILE**, const char*, const char*); @@ -73,6 +101,7 @@ extern "C" { #define WFTELL(s) ftell((s)) #define WREWIND(s) rewind((s)) #define WSEEK_END SEEK_END + #define WUTIMES(f,t) utimes((f),(t)) #if (defined(WOLFSSH_SCP) || defined(WOLFSSH_SFTP)) && \ !defined(WOLFSSH_SCP_USER_CALLBACKS) && \ @@ -139,17 +168,16 @@ extern "C" { #define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL) #endif -#if defined(WOLFSSH_SFTP) && !defined(NO_WOLFSSH_SERVER) +#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \ + !defined(NO_WOLFSSH_SERVER) #ifdef WOLFSSL_NUCLEUS - #include "storage/nu_storage.h" - #define WRMDIR(d) (NU_Remove_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 WLSTAT(p,b) NU_Get_First((b),(p)) #define WREMOVE(d) NU_Delete((d)) #define WRENAME(o,n) NU_Rename((o),(n)) - #define WS_DELIM '\\' + #define WFD int #ifndef WGETCWD static inline char* wGetCwd(char* buf, unsigned int bufSz) @@ -175,28 +203,6 @@ extern "C" { #define WGETCWD(r,rSz) wGetCwd((r),(rSz)) #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 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)) #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 #define WDIR DSTAT #ifndef WOPENDIR - static inline int wOpenDir(WDIR* d, char* dir) + static inline int wOpenDir(WDIR* d, const char* dir) { int ret; int idx = WSTRLEN(dir); @@ -320,11 +346,11 @@ extern "C" { /* returns 0 on success */ #define WOPENDIR(c,d) ((*(c) = opendir((d))) == NULL) - #define WCLOSEDIR(d) closedir((d)) - #define WREADDIR(d) readdir((d)) + #define WCLOSEDIR(d) closedir(*(d)) + #define WREADDIR(d) readdir(*(d)) #endif /* NO_WOLFSSL_DIR */ #endif -#endif /* WOLFSSH_SFTP */ +#endif /* WOLFSSH_SFTP or WOLFSSH_SCP */ /* setup compiler inlining */ #ifndef INLINE diff --git a/wolfssh/wolfscp.h b/wolfssh/wolfscp.h index dae978cb..1ceb6ee8 100644 --- a/wolfssh/wolfscp.h +++ b/wolfssh/wolfscp.h @@ -24,6 +24,7 @@ #define WOLFSSH_WOLFSCP_H #include +#include #include #ifdef WOLFSSH_SCP @@ -57,15 +58,20 @@ extern "C" { #include typedef struct ScpSendCtx { + #ifndef WOLFSSL_NUCLEUS 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 */ + #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 */ } ScpSendCtx; typedef struct ScpDir { - DIR* dir; /* dir pointer, from opendir() */ + WDIR dir; /* dir pointer, from opendir() */ struct ScpDir* next; /* previous directory in stack */ } ScpDir; diff --git a/wolfssh/wolfsftp.h b/wolfssh/wolfsftp.h index ce4db340..cacf8b70 100644 --- a/wolfssh/wolfsftp.h +++ b/wolfssh/wolfsftp.h @@ -26,6 +26,8 @@ #include #endif +#include + /* Packet Types */ enum WS_PacketTypes { WOLFSSH_FTP_INIT = 1,