From 66ebc1ecb856cc912636a2c152a5ee4b3d228bf1 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Tue, 5 Dec 2023 15:07:38 -0800 Subject: [PATCH] SFTP Zero Byte Files 1. When putting a file with SFTP, the client should check that the requested file is a regular file based on its attributes. 2. Add the attributes to check in the permissions. 3. Add server checking for non-regular files and not allowing them to be opened for reading or writing. --- examples/sftpclient/sftpclient.c | 6 ++++ src/wolfsftp.c | 58 ++++++++++++++++++++++++++------ 2 files changed, 53 insertions(+), 11 deletions(-) diff --git a/examples/sftpclient/sftpclient.c b/examples/sftpclient/sftpclient.c index 7a3cb34b5..9e1a7d4d7 100644 --- a/examples/sftpclient/sftpclient.c +++ b/examples/sftpclient/sftpclient.c @@ -634,6 +634,12 @@ static int doCmds(func_args* args) #endif if (ret != WS_SUCCESS) { + if (wolfSSH_get_error(ssh) == WS_SFTP_NOT_FILE_E) { + if (SFTP_FPUTS(args, "Not a regular file\n") < 0) { + err_msg("fputs error"); + return -1; + } + } if (SFTP_FPUTS(args, "Error pushing file\n") < 0) { err_msg("fputs error"); return -1; diff --git a/src/wolfsftp.c b/src/wolfsftp.c index 3a9cf3cb4..63078e4a9 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -1977,6 +1977,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) char* res = NULL; char ier[] = "Internal Failure"; char oer[] = "Open File Error"; + char naf[] = "Not A File"; if (ssh == NULL) { return WS_BAD_ARGUMENT; @@ -2036,20 +2037,40 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) m |= WOLFSSH_O_EXCL; } - /* if file permissions not set then use default */ - if (!(atr.flags & WOLFSSH_FILEATRB_PERM)) { - atr.per = 0644; + { + WS_SFTP_FILEATRB fileAtr = { 0 }; + if (SFTP_GetAttributes(ssh->fs, + dir, &fileAtr, 1, ssh->ctx->heap) == WS_SUCCESS) { + if ((fileAtr.per & FILEATRB_PER_MASK_TYPE) != FILEATRB_PER_FILE) { + WLOG(WS_LOG_SFTP, "Not a file"); + ssh->error = WS_SFTP_NOT_FILE_E; + + res = naf; + if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, + res, "English", NULL, &outSz) != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + ret = WS_FATAL_ERROR; + } + } } - fd = WOPEN(ssh->fs, dir, m, atr.per); - if (fd < 0) { - WLOG(WS_LOG_SFTP, "Error opening file %s", dir); - res = oer; - if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, res, - "English", NULL, &outSz) != WS_SIZE_ONLY) { - return WS_FATAL_ERROR; + if (ret == WS_SUCCESS) { + /* if file permissions not set then use default */ + if (!(atr.flags & WOLFSSH_FILEATRB_PERM)) { + atr.per = 0644; + } + + fd = WOPEN(ssh->fs, dir, m, atr.per); + if (fd < 0) { + WLOG(WS_LOG_SFTP, "Error opening file %s", dir); + res = oer; + if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, res, + "English", NULL, &outSz) != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + ret = WS_BAD_FILE_E; } - ret = WS_BAD_FILE_E; } #ifdef WOLFSSH_STOREHANDLE @@ -8714,6 +8735,21 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume, case STATE_PUT_OPEN_LOCAL: WLOG(WS_LOG_SFTP, "SFTP PUT STATE: OPEN LOCAL"); #ifndef USE_WINDOWS_API + { + WS_SFTP_FILEATRB fileAtr = { 0 }; + if (SFTP_GetAttributes(ssh->fs, + from, &fileAtr, 1, ssh->ctx->heap) + == WS_SUCCESS) { + if ((fileAtr.per & FILEATRB_PER_MASK_TYPE) + != FILEATRB_PER_FILE) { + WLOG(WS_LOG_SFTP, "Not a file"); + ssh->error = WS_SFTP_NOT_FILE_E; + ret = WS_FATAL_ERROR; + state->state = STATE_PUT_CLEANUP; + continue; + } + } + } ret = WFOPEN(ssh->fs, &state->fl, from, "rb"); if (ret != 0) { WLOG(WS_LOG_SFTP, "Unable to open input file");