diff --git a/apps/wolfssh/common.c b/apps/wolfssh/common.c index 2d6e7693d..f5e1883ca 100644 --- a/apps/wolfssh/common.c +++ b/apps/wolfssh/common.c @@ -89,7 +89,7 @@ static int load_der_file(const char* filename, byte** out, word32* outSz) if (ret != 0 || file == WBADFILE) return -1; - if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) { + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { WFCLOSE(NULL, file); return -1; } diff --git a/apps/wolfsshd/wolfsshd.c b/apps/wolfsshd/wolfsshd.c index 19b757240..e87d88da2 100644 --- a/apps/wolfsshd/wolfsshd.c +++ b/apps/wolfsshd/wolfsshd.c @@ -291,7 +291,11 @@ static byte* getBufferFromFile(const char* fileName, word32* bufSz, void* heap, return NULL; } } - WFSEEK(NULL, file, 0, WSEEK_END); + + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + WFCLOSE(NULL, file); + return NULL; + } fileSz = WFTELL(NULL, file); if (fileSz < 0) { WFCLOSE(NULL, file); diff --git a/examples/client/common.c b/examples/client/common.c index b9df3416e..dd174fc7e 100644 --- a/examples/client/common.c +++ b/examples/client/common.c @@ -274,7 +274,7 @@ static int load_der_file(const char* filename, byte** out, word32* outSz, if (ret != 0 || file == WBADFILE) return -1; - if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) { + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { WFCLOSE(NULL, file); return -1; } @@ -799,7 +799,10 @@ static int readKeyBlob(const char* filename, WOLFTPM2_KEYBLOB* key) rc = BUFFER_E; goto exit; } if (fp != WBADFILE) { - WFSEEK(NULL, fp, 0, WSEEK_END); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, fp, 0, WSEEK_END))) { + printf("File seek failed\n"); + rc = BUFFER_E; goto exit; + } fileSz = WFTELL(NULL, fp); WREWIND(NULL, fp); diff --git a/examples/echoserver/echoserver.c b/examples/echoserver/echoserver.c index 876761fc4..93308ae24 100644 --- a/examples/echoserver/echoserver.c +++ b/examples/echoserver/echoserver.c @@ -1730,13 +1730,23 @@ static int load_file(const char* fileName, byte* buf, word32* bufSz) WFILE* file; word32 fileSz; word32 readSz; + long tmpSz; if (fileName == NULL) return 0; if (WFOPEN(NULL, &file, fileName, "rb") != 0) return 0; - WFSEEK(NULL, file, 0, WSEEK_END); - fileSz = (word32)WFTELL(NULL, file); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + WFCLOSE(NULL, file); + return 0; + } + + tmpSz = WFTELL(NULL, file); + if (tmpSz < 0) { + WFCLOSE(NULL, file); + return 0; + } + fileSz = (word32)tmpSz; WREWIND(NULL, file); if (buf == NULL || fileSz > *bufSz) { @@ -2555,8 +2565,17 @@ static char* LoadTpmSshKey(const char* keyFile, const char* username) "Failed to open TPM key file: %s\n", keyFile); return NULL; } - WFSEEK(NULL, file, 0, WSEEK_END); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + fprintf(stderr, "TPM key file seek failed\n"); + WFCLOSE(NULL, file); + return NULL; + } length = WFTELL(NULL, file); + if (length < 0) { + fprintf(stderr, "TPM key file tell failed\n"); + WFCLOSE(NULL, file); + return NULL; + } WREWIND(NULL, file); usernameLen = WSTRLEN(username); diff --git a/examples/tpmcertserver/tpmcertclient.c b/examples/tpmcertserver/tpmcertclient.c index 1ebf76d13..018ca489e 100644 --- a/examples/tpmcertserver/tpmcertclient.c +++ b/examples/tpmcertserver/tpmcertclient.c @@ -72,18 +72,22 @@ static int TpmCcLoadFile(const char* file, byte* buf, word32* bufSz) { int ret = 0; WFILE* f; - word32 fileSz; + word32 fileSz = 0; word32 readSz; if (WFOPEN(NULL, &f, file, "rb") != 0) { ret = -1; } else { - WFSEEK(NULL, f, 0, WSEEK_END); - fileSz = (word32)WFTELL(NULL, f); - WREWIND(NULL, f); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, f, 0, WSEEK_END))) { + ret = -1; + } + else { + fileSz = (word32)WFTELL(NULL, f); + WREWIND(NULL, f); + } - if (fileSz == 0 || fileSz > *bufSz) { + if (ret != 0 || fileSz == 0 || fileSz > *bufSz) { ret = -1; } else { diff --git a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c index 2f4076566..f0557fafa 100644 --- a/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c +++ b/ide/Espressif/ESP-IDF/examples/wolfssh_echoserver/main/echoserver.c @@ -1660,13 +1660,23 @@ static int load_file(const char* fileName, byte* buf, word32* bufSz) WFILE* file; word32 fileSz; word32 readSz; + long tmpSz; if (fileName == NULL) return 0; if (WFOPEN(NULL, &file, fileName, "rb") != 0) return 0; - WFSEEK(NULL, file, 0, WSEEK_END); - fileSz = (word32)WFTELL(NULL, file); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + WFCLOSE(NULL, file); + return 0; + } + + tmpSz = WFTELL(NULL, file); + if (tmpSz < 0) { + WFCLOSE(NULL, file); + return 0; + } + fileSz = (word32)tmpSz; WREWIND(NULL, file); if (buf == NULL || fileSz > *bufSz) { @@ -2173,8 +2183,17 @@ static char* LoadTpmSshKey(const char* keyFile, const char* username) "Failed to open TPM key file: %s\n", keyFile); return NULL; } - WFSEEK(NULL, file, 0, WSEEK_END); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + fprintf(stderr, "TPM key file seek failed\n"); + WFCLOSE(NULL, file); + return NULL; + } length = WFTELL(NULL, file); + if (length < 0) { + fprintf(stderr, "TPM key file tell failed\n"); + WFCLOSE(NULL, file); + return NULL; + } WREWIND(NULL, file); usernameLen = WSTRLEN(username); diff --git a/src/port.c b/src/port.c index 8c1255a64..12660346e 100644 --- a/src/port.c +++ b/src/port.c @@ -129,10 +129,10 @@ int wfopen(WFILE** f, const char* filename, const char* mode) int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, const unsigned int* shortOffset) { - int ret; + int ret = -1; - ret = (int)WFSEEK(NULL, &fd, shortOffset[0], SYS_FS_SEEK_SET); - if (ret != -1) { + if (WFSEEK_SUCCESS(WFSEEK( + NULL, &fd, shortOffset[0], SYS_FS_SEEK_SET))) { ret = (int)WFWRITE(NULL, buf, 1, sz, &fd); } @@ -142,10 +142,10 @@ int wfopen(WFILE** f, const char* filename, const char* mode) int wPread(WFD fd, unsigned char* buf, unsigned int sz, const unsigned int* shortOffset) { - int ret; + int ret = -1; - ret = (int)WFSEEK(NULL, &fd, shortOffset[0], SYS_FS_SEEK_SET); - if (ret != -1) + if (WFSEEK_SUCCESS(WFSEEK( + NULL, &fd, shortOffset[0], SYS_FS_SEEK_SET))) ret = (int)WFREAD(NULL, buf, 1, sz, &fd); return ret; diff --git a/src/ssh.c b/src/ssh.c index 1ca8771b6..c9e69da74 100644 --- a/src/ssh.c +++ b/src/ssh.c @@ -2410,7 +2410,7 @@ int wolfSSH_ReadKey_file(const char* name, if (ret != 0 || file == WBADFILE) return WS_BAD_FILE_E; #endif - if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) { + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { WFCLOSE(NULL, file); return WS_BAD_FILE_E; } diff --git a/src/wolfscp.c b/src/wolfscp.c index f357aa360..b4c759eea 100644 --- a/src/wolfscp.c +++ b/src/wolfscp.c @@ -2686,17 +2686,25 @@ int wsScpRecvCallback(WOLFSSH* ssh, int state, const char* basePath, static int _GetFileSize(void* fs, WFILE* fp, word32* fileSz) { + long tmpSz; + WOLFSSH_UNUSED(fs); if (fp == NULL || fileSz == NULL) return WS_BAD_ARGUMENT; /* get file size */ - WFSEEK(fs, fp, 0, WSEEK_END); - *fileSz = (word32)WFTELL(fs, fp); - WREWIND(fs, fp); + if (WFSEEK_SUCCESS(WFSEEK(fs, fp, 0, WSEEK_END))) { + tmpSz = WFTELL(fs, fp); + if (tmpSz < 0) { + return WS_BAD_FILE_E; + } + *fileSz = (word32)tmpSz; + WREWIND(fs, fp); - return WS_SUCCESS; + return WS_SUCCESS; + } + return WS_BAD_FILE_E; } static int GetFileStats(void *fs, ScpSendCtx* ctx, const char* fileName, @@ -3182,8 +3190,14 @@ static int ScpProcessEntry(WOLFSSH* ssh, char* fileName, word64* mTime, if (ret == WS_SUCCESS) { ret = _GetFileSize(ssh->fs, sendCtx->fp, totalFileSz); - if (ret == WS_SUCCESS) + if (ret != WS_SUCCESS) { + WLOG(WS_LOG_ERROR, "scp: unable to get file size, abort"); + wolfSSH_SetScpErrorMsg(ssh, "unable to get file size"); + ret = WS_SCP_ABORT; + } + else { ret = (word32)WFREAD(ssh->fs, buf, 1, bufSz, sendCtx->fp); + } } /* keep fp open if no errors and transfer will continue */ @@ -3356,8 +3370,13 @@ int wsScpSendCallback(WOLFSSH* ssh, int state, const char* peerRequest, #endif } - if (ret == WS_SUCCESS) + if (ret == WS_SUCCESS) { ret = _GetFileSize(ssh->fs, sendCtx->fp, totalFileSz); + if (ret != WS_SUCCESS) { + WLOG(WS_LOG_ERROR, "scp: unable to get file size, abort"); + wolfSSH_SetScpErrorMsg(ssh, "unable to get file size"); + } + } if (ret == WS_SUCCESS) ret = GetFileStats(ssh->fs, sendCtx, peerRequest, mTime, aTime, fileMode); diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 1ec9d6e56..1e2c1e1bc 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -10053,7 +10053,8 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume, #if SIZEOF_OFF_T == 8 offset = (((word64)state->pOfst[1]) << 32) | offset; #endif - if (WFSEEK(ssh->fs, state->fl, offset, 0) != 0) { + if (!WFSEEK_SUCCESS(WFSEEK( + ssh->fs, state->fl, offset, 0))) { WLOG(WS_LOG_SFTP, "Unable to seek input file"); ssh->error = WS_BAD_FILE_E; ret = WS_FATAL_ERROR; diff --git a/tests/auth.c b/tests/auth.c index 9b0ee74c7..12dba743d 100644 --- a/tests/auth.c +++ b/tests/auth.c @@ -174,13 +174,22 @@ static int load_file(const char* fileName, byte* buf, word32* bufSz) WFILE* file; word32 fileSz; word32 readSz; + long tmpSz; if (fileName == NULL) return 0; if (WFOPEN(NULL, &file, fileName, "rb") != 0) return 0; - WFSEEK(NULL, file, 0, WSEEK_END); - fileSz = (word32)WFTELL(NULL, file); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + WFCLOSE(NULL, file); + return 0; + } + tmpSz = WFTELL(NULL, file); + if (tmpSz < 0) { + WFCLOSE(NULL, file); + return 0; + } + fileSz = (word32)tmpSz; WREWIND(NULL, file); if (buf == NULL || fileSz > *bufSz) { diff --git a/tests/regress.c b/tests/regress.c index ca80a4f59..c66a84a55 100644 --- a/tests/regress.c +++ b/tests/regress.c @@ -472,7 +472,10 @@ static word32 LoadFileBuffer(const char* path, byte* buf, word32 bufSz) if (WFOPEN(NULL, &file, path, "rb") != 0 || file == WBADFILE) { return 0; } - WFSEEK(NULL, file, 0, WSEEK_END); + if (!WFSEEK_SUCCESS(WFSEEK(NULL, file, 0, WSEEK_END))) { + WFCLOSE(NULL, file); + return 0; + } fileSz = WFTELL(NULL, file); WREWIND(NULL, file); diff --git a/wolfssh/port.h b/wolfssh/port.h index 3be71494f..1743e3fdc 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -124,6 +124,7 @@ extern "C" { #define WREWIND(fs,s) NU_Seek(*(s), 0, PSEEK_SET) #define WSEEK_END PSEEK_END #define WBADFILE NULL + #define WFSEEK_SUCCESS(r) ((int)(r) >= 0) #define WS_DELIM '\\' #define WOLFSSH_O_RDWR PO_RDWR @@ -440,6 +441,7 @@ extern "C" { #define WSETTIME(fs,f,a,m) (0) #define WFSETTIME(fs,fd,a,m) (0) #define WCHDIR(fs,b) SYS_FS_DirectryChange((b)) + #define WFSEEK_SUCCESS(r) ((int)(r) >= 0) #else #include @@ -1624,6 +1626,15 @@ extern "C" { #define WOLFSSH_O_NOFOLLOW 0 #endif +/* Catch-all so callers can test a seek result unconditionally. Ports whose + * seek returns the new file position rather than a 0/-1 status define their + * own WFSEEK_SUCCESS() in the port block above; see Nucleus and MPLAB + * Harmony. Any definition must evaluate its argument exactly once, as + * callers pass the WFSEEK() call in directly. */ +#ifndef WFSEEK_SUCCESS + #define WFSEEK_SUCCESS(r) ((r) == 0) +#endif + /* wIsSymlink lives in the always-compiled port.c, but its filesystem * dependencies (WSTAT_T/WLSTAT/S_ISLNK on POSIX, WS_GetFileAttributesExA on * Windows) and its only callers exist solely in the SFTP and SCP code, so