From a457abd11de485a211586fa456228e86a4aa4f40 Mon Sep 17 00:00:00 2001 From: John Safranek Date: Fri, 18 Jan 2019 16:53:07 -0800 Subject: [PATCH] 1. Initialize the ret value in RecvSetSTAT(). 2. Delete trailing commas in a couple enums. 3. Add extern "C" C++ guards around wolfsftp.h. 4. In port.c, comment out the pwrite and pread wrappers for Windows builds. 5. Remove the getcwd from RecvRealPath(), but needs a better fix. 6. Leave out several operations that need to be touched later. Emphasis is to get Get and Put running. 7. Open, Close, Read, Write, have a WINCE version using the Win32 API. 8. Remove the include of stdio.h from port.c for Windows builds. 9. Remove and Rename actions return an error for Windows builds. --- src/port.c | 9 +- src/wolfsftp.c | 539 ++++++++++++++++++++++++++++++++++++++++++--- wolfssh/port.h | 3 + wolfssh/ssh.h | 2 +- wolfssh/wolfsftp.h | 11 +- 5 files changed, 528 insertions(+), 36 deletions(-) diff --git a/src/port.c b/src/port.c index 6bae37e2..3564fa53 100644 --- a/src/port.c +++ b/src/port.c @@ -1,4 +1,4 @@ -/* port.c +/* port.c * * Copyright (C) 2014-2016 wolfSSL Inc. * @@ -31,8 +31,11 @@ #include #endif -#include + #include +#ifndef USE_WINDOWS_API + #include +#endif #ifndef NO_FILESYSTEM @@ -79,6 +82,7 @@ int wfopen(WFILE** f, const char* filename, const char* mode) #endif } +#if 0 #if defined(USE_WINDOWS_API) && (defined(WOLFSSH_SFTP) || \ defined(WOLFSSH_SCP)) && !defined(NO_WOLFSSH_SERVER) int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, long ofst) @@ -123,6 +127,7 @@ int wPread(WFD fd, unsigned char* buf, unsigned int sz, long ofst) } #endif /* USE_WINDOWS_API */ +#endif #endif /* !NO_FILESYSTEM */ #ifndef WSTRING_USER diff --git a/src/wolfsftp.c b/src/wolfsftp.c index f8a4e81a..57d6cbfd 100644 --- a/src/wolfsftp.c +++ b/src/wolfsftp.c @@ -638,7 +638,6 @@ static int SFTP_SetAttributes(WOLFSSH* ssh, byte* buf, word32 bufSz, c32toa(atr->per, buf + idx); idx += UINT32_SZ; } - /* check if time attribute present */ if (atr->flags & WOLFSSH_FILEATRB_TIME) { c32toa(atr->atime, buf + idx); idx += UINT32_SZ; @@ -857,6 +856,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, byte* data, r[rSz] = '\0'; /* get working directory in the case of receiving non absolute path */ +#ifndef USE_WINDOWS_API if (r[0] != '/' && r[1] != ':') { char wd[WOLFSSH_MAX_FILENAME]; @@ -884,6 +884,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, byte* data, WSTRNCAT(wd, r, WOLFSSH_MAX_FILENAME); WMEMCPY(r, wd, WOLFSSH_MAX_FILENAME); } +#endif /* USE_WINDOWS_API */ clean_path(r); rSz = (int)WSTRLEN(r); @@ -997,7 +998,7 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh) ret = wolfSSH_SFTP_RecvRealPath(ssh, state->reqId, state->data, state->sz); break; - + #ifndef _WIN32_WCE case WOLFSSH_FTP_RMDIR: ret = wolfSSH_SFTP_RecvRMDIR(ssh, state->reqId, state->data, state->sz); @@ -1017,11 +1018,14 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh) ret = wolfSSH_SFTP_RecvLSTAT(ssh, state->reqId, state->data, state->sz); break; + #endif + #ifndef USE_WINDOWS_API case WOLFSSH_FTP_FSTAT: ret = wolfSSH_SFTP_RecvFSTAT(ssh, state->reqId, state->data, state->sz); break; + #endif case WOLFSSH_FTP_OPEN: ret = wolfSSH_SFTP_RecvOpen(ssh, state->reqId, @@ -1052,11 +1056,12 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh) ret = wolfSSH_SFTP_RecvRename(ssh, state->reqId, state->data, state->sz); break; - + #ifndef _WIN32_WCE case WOLFSSH_FTP_SETSTAT: ret = wolfSSH_SFTP_RecvSetSTAT(ssh, state->reqId, state->data, state->sz); break; + #endif #ifndef NO_WOLFSSH_DIR case WOLFSSH_FTP_OPENDIR: @@ -1225,6 +1230,8 @@ int wolfSSH_SFTP_CreateStatus(WOLFSSH* ssh, word32 status, word32 reqId, } +#ifndef _WIN32_WCE + /* Handles packet to remove a directory * * returns WS_SUCCESS on success @@ -1385,12 +1392,15 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return ret; } +#endif /* _WIN32_WCE */ + /* Handles packet to open a file * * returns WS_SUCCESS on success */ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) +#ifndef USE_WINDOWS_API { WS_SFTP_FILEATRB atr; WFD fd; @@ -1519,6 +1529,136 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) (void)ier; return ret; } +#else /* USE_WINDOWS_API */ +{ + WS_SFTP_FILEATRB atr; + HANDLE fileHandle; + word32 sz; + char* dir; + word32 reason; + word32 idx = 0; + DWORD desiredAccess = 0; + DWORD shareMode = 0; + DWORD creationDisp = 0; + DWORD flagsAndAttrs = 0; + int ret = WS_SUCCESS; + + word32 outSz = sizeof(HANDLE) + UINT32_SZ + WOLFSSH_SFTP_HEADER; + byte* out = NULL; + + char* res = NULL; + char ier[] = "Internal Failure"; + char oer[] = "Open File Error"; + + if (ssh == NULL) { + return WS_BAD_ARGUMENT; + } + + WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_OPEN"); + + if (sizeof(HANDLE) > WOLFSSH_MAX_HANDLE) { + WLOG(WS_LOG_SFTP, "Handle size is too large"); + return WS_FATAL_ERROR; + } + + ato32(data + idx, &sz); idx += UINT32_SZ; + if (sz + idx > maxSz) { + return WS_BUFFER_E; + } + + /* plus one to make sure is null terminated */ + dir = (char*)WMALLOC(sz + 1, ssh->ctx->heap, DYNTYPE_BUFFER); + if (dir == NULL) { + return WS_MEMORY_E; + } + WMEMCPY(dir, data + idx, sz); + dir[sz] = '\0'; + idx += sz; + + /* get reason for opening file */ + ato32(data + idx, &reason); idx += UINT32_SZ; + + +#if 0 + /* @TODO handle attributes */ + SFTP_ParseAtributes_buffer(ssh, &atr, data, &idx, maxSz); +#endif + + WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER); + + if (reason & WOLFSSH_FXF_READ) + desiredAccess |= GENERIC_READ; + if (reason & WOLFSSH_FXF_WRITE) + desiredAccess |= GENERIC_WRITE; + if (reason & WOLFSSH_FXF_APPEND) + desiredAccess |= FILE_APPEND_DATA; + + if (reason & WOLFSSH_FXF_CREAT) + creationDisp |= CREATE_ALWAYS; + if (reason & WOLFSSH_FXF_TRUNC) + creationDisp |= TRUNCATE_EXISTING; + if (reason & WOLFSSH_FXF_EXCL) + creationDisp |= CREATE_NEW; + +#if 0 + /* if file permissions not set then use default */ + if (!(atr.flags & WOLFSSH_FILEATRB_PERM)) { + atr.per = 0644; + } +#endif + atr.per = FILE_ATTRIBUTE_NORMAL; + + clean_path(dir); + fileHandle = CreateFileA(dir, desiredAccess, shareMode, NULL, creationDisp, + atr.per, NULL); + if (fileHandle == INVALID_HANDLE_VALUE) { + 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; + } + +#ifdef WOLFSSH_STOREHANDLE + if (SFTP_AddHandleNode(ssh, + (byte*)&fileHandle, sizeof(HANDLE), dir) != WS_SUCCESS) { + WLOG(WS_LOG_SFTP, "Unable to store handle"); + res = ier; + if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, res, + "English", NULL, &outSz) != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + ret = WS_FATAL_ERROR; + } +#endif + WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER); + + /* create packet */ + out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); + if (out == NULL) { + return WS_MEMORY_E; + } + if (ret == WS_SUCCESS) { + if (SFTP_CreatePacket(ssh, WOLFSSH_FTP_HANDLE, out, outSz, + (byte*)&fileHandle, sizeof(HANDLE)) != WS_SUCCESS) { + return WS_FATAL_ERROR; + } + } + else { + if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_FAILURE, reqId, res, + "English", out, &outSz) != WS_SUCCESS) { + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); + return WS_FATAL_ERROR; + } + } + wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); + + (void)ier; + return ret; +} +#endif /* USE_WINDOWS_API */ #ifndef NO_WOLFSSH_DIR @@ -1536,13 +1676,12 @@ static word64 idCount = 0; /* @TODO add locking for thread safety */ -#ifndef USE_WINDOWS_API - /* Handles packet to open a directory * * returns WS_SUCCESS on success */ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) +#ifndef USE_WINDOWS_API { WDIR ctx; word32 sz; @@ -1636,23 +1775,18 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return ret; } - #else /* USE_WINDOWS_API */ - -/* Handles packet to open a directory - * - * returns WS_SUCCESS on success - */ -int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) { word32 sz; char* dirName; word32 idx = 0; HANDLE findHandle; WIN32_FIND_DATAA findData; + int ret = WS_SUCCESS; - byte* out = NULL; - word32 outSz = 0; + word32 outSz = sizeof(word64) + WOLFSSH_SFTP_HEADER + UINT32_SZ; + byte* out = NULL; + word64 id; if (ssh == NULL) { return WS_BAD_ARGUMENT; @@ -1660,6 +1794,11 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_OPENDIR"); + if (sizeof(HANDLE) > WOLFSSH_MAX_HANDLE) { + WLOG(WS_LOG_SFTP, "Handle size is too large"); + return WS_FATAL_ERROR; + } + /* get directory name */ ato32(data + idx, &sz); idx += UINT32_SZ; @@ -1684,16 +1823,19 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) WLOG(WS_LOG_SFTP, "Error with opening directory"); WFREE(dirName, ssh->ctx->heap, DYNTYPE_BUFFER); - wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_NOFILE, reqId, - "Unable To Open Directory", "English"); - if (findHandle != INVALID_HANDLE_VALUE) - FindClose(findHandle); - return WS_BAD_FILE_E; + if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_NOFILE, reqId, + "Unable To Open Directory", "English", NULL, &outSz) + != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + ret = WS_BAD_FILE_E; } FindClose(findHandle); + (void)reqId; + /* add to directory list @TODO locking for thread safety */ - { + if (ret == WS_SUCCESS) { DIR_HANDLE* cur = (DIR_HANDLE*)WMALLOC(sizeof(DIR_HANDLE), ssh->ctx->heap, DYNTYPE_SFTP); if (cur == NULL) { @@ -1707,20 +1849,31 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) cur->next = dirList; dirList = cur; - outSz = sizeof(word64) + UINT32_SZ + WOLFSSH_SFTP_HEADER; - out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); - if (out == NULL) { - return WS_MEMORY_E; - } - SFTP_CreatePacket(ssh, WOLFSSH_FTP_HANDLE, out, outSz, (byte*)&cur->id, - sizeof(word64)); - wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); } - return WS_SUCCESS; -} + out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); + if (out == NULL) { + return WS_MEMORY_E; + } + + if (ret == WS_SUCCESS) { + SFTP_CreatePacket(ssh, WOLFSSH_FTP_HANDLE, out, outSz, + (byte*)&id, sizeof(word64)); + } + else { + if (wolfSSH_SFTP_CreateStatus(ssh, WOLFSSH_FTP_NOFILE, reqId, + "Unable To Open Directory", "English", out, &outSz) + != WS_SUCCESS) { + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); + return WS_FATAL_ERROR; + } + } + wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); + + return ret; +} +#endif /* USE_WINDOWS_API */ -#endif #ifdef WOLFSSL_NUCLEUS /* For Nucleus port @@ -2223,6 +2376,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz) * returns WS_SUCCESS on success */ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) +#ifndef USE_WINDOWS_API { WFD fd; word32 sz; @@ -2299,6 +2453,86 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return WS_SUCCESS; } +#else /* USE_WINDOWS_API */ +{ + OVERLAPPED offset; + HANDLE fd; + DWORD bytesWritten; + word32 sz; + int ret = WS_SUCCESS; + word32 idx = 0; + + word32 outSz = 0; + byte* out = NULL; + + char suc[] = "Write File Success"; + char err[] = "Write File Error"; + char* res = suc; + byte type = WOLFSSH_FTP_OK; + + if (ssh == NULL) { + return WS_BAD_ARGUMENT; + } + + WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_WRITE"); + + /* get file handle */ + ato32(data + idx, &sz); + idx += UINT32_SZ; + if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { + WLOG(WS_LOG_SFTP, "Error with file handle size"); + res = err; + type = WOLFSSH_FTP_FAILURE; + ret = WS_BAD_FILE_E; + } + + if (ret == WS_SUCCESS) { + WMEMSET((byte*)&fd, 0, sizeof(HANDLE)); + WMEMCPY((byte*)&fd, data + idx, sz); + idx += sz; + + /* get offset into file */ + WMEMSET(&offset, 0, sizeof(OVERLAPPED)); + ato32(data + idx, &sz); + idx += UINT32_SZ; + offset.OffsetHigh = (DWORD)sz; + ato32(data + idx, &sz); + idx += UINT32_SZ; + offset.Offset = (DWORD)sz; + + /* get length to be written */ + ato32(data + idx, &sz); + idx += UINT32_SZ; + + if (WriteFile(fd, data, sz, &bytesWritten, &offset) == 0) { + WLOG(WS_LOG_SFTP, "Error writing to file"); + res = err; + type = WOLFSSH_FTP_FAILURE; + ret = WS_INVALID_STATE_E; + } + else { + ret = WS_SUCCESS; + } + } + + if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL, + &outSz) != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); + if (out == NULL) { + return WS_MEMORY_E; + } + if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", out, + &outSz) != WS_SUCCESS) { + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); + return WS_FATAL_ERROR; + } + wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); + return WS_SUCCESS; +} + +#endif /* USE_WINDOWS_API */ /* Handles packet to read a file @@ -2306,6 +2540,7 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) * returns WS_SUCCESS on success */ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) +#ifndef USE_WINDOWS_API { WFD fd; word32 sz; @@ -2396,6 +2631,113 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } +#else /* USE_WINDOWS_API */ +{ + OVERLAPPED offset; + HANDLE fd; + DWORD bytesRead; + word32 sz; + int ret; + word32 idx = 0; + + byte* out; + word32 outSz; + + char* res = NULL; + char err[] = "Read File Error"; + char eof[] = "Read EOF"; + byte type = WOLFSSH_FTP_FAILURE; + + if (ssh == NULL) { + return WS_BAD_ARGUMENT; + } + + WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_READ"); + + /* get file handle */ + ato32(data + idx, &sz); idx += UINT32_SZ; + if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { + return WS_BUFFER_E; + } + WMEMSET((byte*)&fd, 0, sizeof(HANDLE)); + WMEMCPY((byte*)&fd, data + idx, sz); idx += sz; + + WMEMSET(&offset, 0, sizeof(OVERLAPPED)); + + /* get offset into file */ + ato32(data + idx, &sz); + idx += UINT32_SZ; + offset.OffsetHigh = (DWORD)sz; + ato32(data + idx, &sz); + idx += UINT32_SZ; + offset.Offset = (DWORD)sz; + + /* get length to be read */ + ato32(data + idx, &sz); + + /* read from handle and send data back to client */ + out = (byte*)WMALLOC(sz + WOLFSSH_SFTP_HEADER + UINT32_SZ, + ssh->ctx->heap, DYNTYPE_BUFFER); + if (out == NULL) { + return WS_MEMORY_E; + } + + if (ReadFile(fd, data, sz, &bytesRead, &offset) == 0) { + if (GetLastError() == ERROR_HANDLE_EOF) { + ret = 0; /* return 0 for end of file */ + } + else { + ret = -1; + } + } + else { + ret = (int)bytesRead; + outSz = (word32)ret + WOLFSSH_SFTP_HEADER + UINT32_SZ; + } + + if (ret < 0) { + WLOG(WS_LOG_SFTP, "Error reading from file"); + res = err; + type = WOLFSSH_FTP_FAILURE; + ret = WS_BAD_FILE_E; + } + + /* eof */ + if (ret == 0) { + WLOG(WS_LOG_SFTP, "Error reading from file"); + res = eof; + type = WOLFSSH_FTP_EOF; + ret = WS_SUCCESS; /* end of file is not fatal error */ + } + + if (res != NULL) { + if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL, + &outSz) != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + if (outSz > sz) { + /* need to increase buffer size for holding status packet */ + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); + out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); + if (out == NULL) { + return WS_MEMORY_E; + } + } + if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", out, + &outSz) != WS_SUCCESS) { + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); + return WS_FATAL_ERROR; + } + } + else { + SFTP_CreatePacket(ssh, WOLFSSH_FTP_DATA, out, outSz, NULL, 0); + } + + wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); + return ret; +} + +#endif /* USE_WINDOWS_API */ /* Handles packet to close a file @@ -2403,6 +2745,7 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) * returns WS_SUCCESS on success */ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) +#ifndef USE_WINDOWS_API { WFD fd; word32 sz; @@ -2478,6 +2821,76 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } +#else /* USE_WINDOWS_API */ +{ + HANDLE fd; + word32 sz; + word32 idx = 0; + int ret; + + byte* out = NULL; + word32 outSz = 0; + + char* res = NULL; + char suc[] = "Closed File"; + char err[] = "Close File Error"; + byte type = WOLFSSH_FTP_FAILURE; + + if (ssh == NULL) { + return WS_BAD_ARGUMENT; + } + + WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_CLOSE"); + + /* get file handle */ + ato32(data + idx, &sz); idx += UINT32_SZ; + if (sz + idx > maxSz || sz > WOLFSSH_MAX_HANDLE) { + return WS_BUFFER_E; + } + + if (sz == sizeof(HANDLE)) { + WMEMSET((byte*)&fd, 0, sizeof(HANDLE)); + WMEMCPY((byte*)&fd, data + idx, sz); + CloseHandle(fd); + #ifdef WOLFSSH_STOREHANDLE + if (SFTP_RemoveHandleNode(ssh, data + idx, sz) != WS_SUCCESS) { + WLOG(WS_LOG_SFTP, "Unable to remove handle from list"); + ret = WS_FATAL_ERROR; + } + #endif + } + else { + ret = WS_FATAL_ERROR; + } + + if (ret < 0) { + WLOG(WS_LOG_SFTP, "Error closing file"); + res = err; + ret = WS_BAD_FILE_E; + } + else { + res = suc; + type = WOLFSSH_FTP_OK; + ret = WS_SUCCESS; + } + + if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", NULL, + &outSz) != WS_SIZE_ONLY) { + return WS_FATAL_ERROR; + } + out = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER); + if (out == NULL) { + return WS_MEMORY_E; + } + if (wolfSSH_SFTP_CreateStatus(ssh, type, reqId, res, "English", out, + &outSz) != WS_SUCCESS) { + WFREE(out, ssh->ctx->heap, DYNTYPE_BUFFER); + return WS_FATAL_ERROR; + } + wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); + return ret; +} +#endif /* USE_WINDOWS_API */ @@ -2519,6 +2932,7 @@ int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) name[sz] = '\0'; clean_path(name); +#if 0 if ((ret = WREMOVE(name)) < 0) { WLOG(WS_LOG_SFTP, "Error removing file"); #if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH) @@ -2536,6 +2950,8 @@ int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) else { ret = WS_SUCCESS; } +#endif + ret = WS_BAD_FILE_E; /* Let the client know the results from trying to remove the file */ WFREE(name, ssh->ctx->heap, DYNTYPE_BUFFER); @@ -2618,10 +3034,13 @@ int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) clean_path(old); clean_path(nw); +#if 0 if (ret == WS_SUCCESS && WRENAME(old, nw) < 0) { WLOG(WS_LOG_SFTP, "Error renaming file"); ret = WS_BAD_FILE_E; } +#endif + ret = WS_BAD_FILE_E; /* Let the client know the results from trying to rename the file */ WFREE(old, ssh->ctx->heap, DYNTYPE_BUFFER); @@ -2921,6 +3340,48 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz, NU_Done(&stats); return WS_SUCCESS; } + +#elif defined(USE_WINDOWS_API) + +/* @TODO can be overriden by user for portability + * NOTE: if atr->flags is set to a value of 0 then no attributes are set. + * Fills out a WS_SFTP_FILEATRB structure + * returns WS_SUCCESS on success + */ +int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr, byte link) +{ + BOOL error; + WIN32_FILE_ATTRIBUTE_DATA stats; + + (void)link; + /* @TODO add proper Windows link support */ + /* Note, for windows, we treat WSTAT and WLSTAT the same. */ + error = !GetFileAttributesExA(fileName, GetFileExInfoStandard, &stats); + if (error) + return WS_BAD_FILE_E; + + WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB)); + + atr->flags |= WOLFSSH_FILEATRB_SIZE; + atr->sz = (((word64)stats.nFileSizeHigh << 32) | stats.nFileSizeLow); + +#if 0 + atr->flags |= WOLFSSH_FILEATRB_PERM; + atr->per = (word32)stats.dwFileAttributes; +#endif + +#if 0 + /* @TODO handle the constellation of possible Windows FILETIMEs */ + atr->flags |= WOLFSSH_FILEATRB_TIME; + atr->atime = (word32)stats.ftLastAccessTime; + atr->mtime = (word32)stats.ftLastWriteTime; +#endif + + /* @TODO handle attribute extensions */ + + return WS_SUCCESS; +} + #else /* @TODO can be overriden by user for portability @@ -3009,6 +3470,7 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz, #endif +#ifndef USE_WINDOWS_API /* Handles receiving fstat packet * returns WS_SUCCESS on success */ @@ -3072,8 +3534,11 @@ int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } +#endif +#ifndef _WIN32_WCE + /* Handles receiving stat packet * returns WS_SUCCESS on success */ @@ -3226,7 +3691,10 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) return ret; } +#endif /* _WIN32_WCE */ + +#ifndef USE_WINDOWS_API /* Set the files mode * return WS_SUCCESS on success */ static int SFTP_SetMode(WOLFSSH* ssh, char* name, word32 mode) { @@ -3236,8 +3704,11 @@ static int SFTP_SetMode(WOLFSSH* ssh, char* name, word32 mode) { } return WS_SUCCESS; } +#endif +#ifndef _WIN32_WCE + /* sets a files attributes * returns WS_SUCCESS on success */ static int SFTP_SetFileAttributes(WOLFSSH* ssh, char* name, WS_SFTP_FILEATRB* atr) @@ -3254,10 +3725,12 @@ static int SFTP_SetFileAttributes(WOLFSSH* ssh, char* name, WS_SFTP_FILEATRB* at /* @TODO set group and user id */ } +#ifndef USE_WINDOWS_API /* check if permissions attribute present */ if (atr->flags & WOLFSSH_FILEATRB_PERM) { ret = SFTP_SetMode(ssh, name, atr->per); } +#endif /* check if time attribute present */ if (atr->flags & WOLFSSH_FILEATRB_TIME) { @@ -3282,7 +3755,7 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) { WS_SFTP_FILEATRB atr; char* name = NULL; - int ret; + int ret = WS_SUCCESS; word32 sz; word32 idx = 0; @@ -3349,6 +3822,8 @@ int wolfSSH_SFTP_RecvSetSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz) wolfSSH_SFTP_RecvSetSend(ssh, out, outSz); return ret; } + +#endif /* _WIN32_WCE */ #endif /* !NO_WOLFSSH_SERVER */ diff --git a/wolfssh/port.h b/wolfssh/port.h index fb619b39..01dd3c38 100644 --- a/wolfssh/port.h +++ b/wolfssh/port.h @@ -120,6 +120,9 @@ extern "C" { #define WCHMOD(f,m) wChmod((f),(m)) #else #include + #ifndef _WIN32_WCE + #include + #endif #define WFILE FILE WOLFSSH_API int wfopen(WFILE**, const char*, const char*); diff --git a/wolfssh/ssh.h b/wolfssh/ssh.h index 6143beaf..f3d1b969 100644 --- a/wolfssh/ssh.h +++ b/wolfssh/ssh.h @@ -175,7 +175,7 @@ typedef enum { WOLFSSH_SESSION_UNKNOWN = 0, WOLFSSH_SESSION_SHELL, WOLFSSH_SESSION_EXEC, - WOLFSSH_SESSION_SUBSYSTEM, + WOLFSSH_SESSION_SUBSYSTEM } WS_SessionType; WOLFSSH_API WS_SessionType wolfSSH_GetSessionType(const WOLFSSH*); diff --git a/wolfssh/wolfsftp.h b/wolfssh/wolfsftp.h index 75e7977e..bd198d48 100644 --- a/wolfssh/wolfsftp.h +++ b/wolfssh/wolfsftp.h @@ -28,6 +28,10 @@ #include +#ifdef __cplusplus +extern "C" { +#endif + /* Packet Types */ enum WS_PacketTypes { WOLFSSH_FTP_INIT = 1, @@ -79,7 +83,7 @@ enum WS_SFTPConnectStates { SFTP_BEGIN = 20, SFTP_RECV, SFTP_EXT, - SFTP_DONE, + SFTP_DONE }; @@ -233,3 +237,8 @@ WOLFSSH_LOCAL int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, WOLFSSL_LOCAL int wolfSSH_SFTP_free(WOLFSSH* ssh); WOLFSSL_LOCAL int SFTP_AddHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz, char* name); WOLFSSL_LOCAL int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz); + + +#ifdef __cplusplus +} +#endif