mirror of https://github.com/wolfSSL/wolfssh.git
commit
0cdb57b92e
|
@ -32,6 +32,10 @@
|
|||
#include <wolfssh/test.h>
|
||||
#include "examples/echoserver/echoserver.h"
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
/* use buffers for keys with server */
|
||||
#define NO_FILESYSTEM
|
||||
#endif
|
||||
|
||||
#ifdef NO_FILESYSTEM
|
||||
#include <wolfssh/certs_test.h>
|
||||
|
@ -206,13 +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;
|
||||
|
@ -585,6 +595,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
char** argv = serverArgs->argv;
|
||||
serverArgs->return_code = 0;
|
||||
|
||||
if (argc > 0) {
|
||||
while ((ch = mygetopt(argc, argv, "?1ep:")) != -1) {
|
||||
switch (ch) {
|
||||
case '?' :
|
||||
|
@ -612,6 +623,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
exit(MY_EX_USAGE);
|
||||
}
|
||||
}
|
||||
}
|
||||
myoptind = 0; /* reset for test cases */
|
||||
|
||||
if (wolfSSH_Init() != WS_SUCCESS) {
|
||||
|
@ -660,13 +672,41 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
buf[bufSz] = 0;
|
||||
LoadPublicKeyBuffer(buf, bufSz, &pwMapList);
|
||||
}
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
{
|
||||
int i;
|
||||
int ret = !NU_SUCCESS;
|
||||
|
||||
/* wait for network and storage device */
|
||||
if (NETBOOT_Wait_For_Network_Up(NU_SUSPEND) != NU_SUCCESS) {
|
||||
fprintf(stderr, "Couldn't find network.\r\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
for(i = 0; i < 15 && ret != NU_SUCCESS; i++)
|
||||
{
|
||||
fprintf(stdout, "Checking for storage device\r\n");
|
||||
|
||||
ret = NU_Storage_Device_Wait(NU_NULL, NU_PLUS_TICKS_PER_SEC);
|
||||
}
|
||||
|
||||
if (ret != NU_SUCCESS) {
|
||||
fprintf(stderr, "Couldn't find storage device.\r\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
tcp_listen(&listenFd, &port, 1);
|
||||
|
||||
do {
|
||||
SOCKET_T clientFd = 0;
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
struct addr_struct clientAddr;
|
||||
#else
|
||||
SOCKADDR_IN_T clientAddr;
|
||||
socklen_t clientAddrSz = sizeof(clientAddr);
|
||||
#endif
|
||||
WOLFSSH* ssh;
|
||||
thread_ctx_t* threadCtx;
|
||||
|
||||
|
@ -688,10 +728,35 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
wolfSSH_SetHighwater(ssh, defaultHighwater);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
{
|
||||
byte ipaddr[MAX_ADDRESS_SIZE];
|
||||
char buf[16];
|
||||
short addrLength;
|
||||
struct sockaddr_struct sock;
|
||||
|
||||
addrLength = sizeof(struct sockaddr_struct);
|
||||
|
||||
/* Get the local IP address for the socket. 0.0.0.0 if ip adder any */
|
||||
if (NU_Get_Sock_Name(listenFd, &sock, &addrLength) != NU_SUCCESS) {
|
||||
fprintf(stderr, "Couldn't find network.\r\n");
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
WMEMCPY(ipaddr, &sock.ip_num, MAX_ADDRESS_SIZE);
|
||||
NU_Inet_NTOP(NU_FAMILY_IP, &ipaddr[0], buf, 16);
|
||||
fprintf(stdout, "Listing on %s:%d\r\n", buf, port);
|
||||
}
|
||||
#endif
|
||||
|
||||
SignalTcpReady(serverArgs, port);
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
clientFd = NU_Accept(listenFd, &clientAddr, 0);
|
||||
#else
|
||||
clientFd = accept(listenFd, (struct sockaddr*)&clientAddr,
|
||||
&clientAddrSz);
|
||||
&clientAddrSz);
|
||||
#endif
|
||||
if (clientFd == -1)
|
||||
err_sys("tcp accept failed");
|
||||
|
||||
|
@ -715,6 +780,7 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifndef NO_MAIN_DRIVER
|
||||
|
||||
int main(int argc, char** argv)
|
||||
|
@ -734,7 +800,9 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
|
||||
wolfSSH_Init();
|
||||
|
||||
#ifndef WOLFSSL_NUCLEUS
|
||||
ChangeToWolfSshRoot();
|
||||
#endif
|
||||
echoserver_test(&args);
|
||||
|
||||
wolfSSH_Cleanup();
|
||||
|
@ -747,3 +815,37 @@ THREAD_RETURN WOLFSSH_THREAD echoserver_test(void* args)
|
|||
char* myoptarg = NULL;
|
||||
|
||||
#endif /* NO_MAIN_DRIVER */
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
|
||||
#define WS_TASK_SIZE 200000
|
||||
#define WS_TASK_PRIORITY 31
|
||||
static NU_TASK serverTask;
|
||||
|
||||
/* expecting void return on main function */
|
||||
static VOID main_nucleus(UNSIGNED argc, VOID* argv)
|
||||
{
|
||||
main((int)argc, (char**)argv);
|
||||
}
|
||||
|
||||
|
||||
/* using port 8080 because it was an open port on QEMU */
|
||||
VOID Application_Initialize (NU_MEMORY_POOL* memPool,
|
||||
NU_MEMORY_POOL* uncachedPool)
|
||||
{
|
||||
void* pt;
|
||||
int ret;
|
||||
|
||||
UNUSED_PARAMETER(uncachedPool);
|
||||
|
||||
ret = NU_Allocate_Memory(memPool, &pt, WS_TASK_SIZE, NU_NO_SUSPEND);
|
||||
if (ret == NU_SUCCESS) {
|
||||
ret = NU_Create_Task(&serverTask, "wolfSSH Server", main_nucleus, 0,
|
||||
NU_NULL, pt, WS_TASK_SIZE, WS_TASK_PRIORITY, 0,
|
||||
NU_PREEMPT, NU_START);
|
||||
if (ret != NU_SUCCESS) {
|
||||
NU_Deallocate_Memory(pt);
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif /* WOLFSSL_NUCLEUS */
|
||||
|
|
|
@ -0,0 +1,195 @@
|
|||
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
|
||||
<?fileVersion 4.0.0?><cproject storage_type_id="org.eclipse.cdt.core.XmlProjectDescriptionStorage">
|
||||
<storageModule moduleId="org.eclipse.cdt.core.settings">
|
||||
<cconfiguration id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug.1214077048">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug.1214077048" moduleId="org.eclipse.cdt.core.settings" name="Debug">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="com.mentor.embedded.toolchains.core.nucleus.FuseErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.debug" cleanCommand="cs-rm -rf" description="" id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug.1214077048" name="Debug" parent="cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug" postbuildStep="${POSTLD} -O binary "${CWD}/${ProjName}.out" "${CWD}/${ProjName}.bin"" postcleanStep="">
|
||||
<folderInfo id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug.1214077048." name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.mentor.nucleus.exe.debug.1208281997" name="Sourcery CodeBench for Nucleus" superClass="cdt.managedbuild.toolchain.gnu.mentor.nucleus.exe.debug">
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.mentor.nucleus.1291172499" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.mentor.nucleus"/>
|
||||
<builder buildPath="${workspace_loc:/CSBENCH}/Debug" id="cdt.managedbuild.builder.gnu.mentor.nucleus.363008008" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CodeSourcery GNU Builder" superClass="cdt.managedbuild.builder.gnu.mentor.nucleus"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.archiver.nucleus.796002859" name="CodeSourcery GNU Archiver" superClass="cdt.managedbuild.tool.gnu.mentor.archiver.nucleus"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.cpp.compiler.nucleus.1301230838" name="CodeSourcery GNU C++ Compiler" superClass="cdt.managedbuild.tool.gnu.mentor.cpp.compiler.nucleus">
|
||||
<option id="mentor.gnu.cpp.compiler.option.optimization.level.166261543" name="Optimization Level" superClass="mentor.gnu.cpp.compiler.option.optimization.level" value="mentor.gnu.cpp.compiler.optimization.level.none" valueType="enumerated"/>
|
||||
<option id="mentor.gnu.cpp.compiler.option.debugging.level.1260284336" name="Debug Level" superClass="mentor.gnu.cpp.compiler.option.debugging.level" value="mentor.gnu.cpp.compiler.debugging.level.max" valueType="enumerated"/>
|
||||
<option id="mentor.gnu.cpp.compiler.option.indexer_include.2129830556" name="Include paths for indexer" superClass="mentor.gnu.cpp.compiler.option.indexer_include" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="${CFG_INCLUDE}"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/./"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/bsp/arch/plat-realview_eb/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/arch/arm/tool-csgnu_arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/tool-csgnu_arm/"/>
|
||||
</option>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.733911603" name="CodeSourcery GNU C Compiler" superClass="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus">
|
||||
<option defaultValue="mentor.gnu.c.optimization.level.none" id="mentor.gnu.c.compiler.option.optimization.level.1781700399" name="Optimization Level" superClass="mentor.gnu.c.compiler.option.optimization.level" valueType="enumerated"/>
|
||||
<option id="mentor.gnu.c.compiler.option.debugging.level.474868803" name="Debug Level" superClass="mentor.gnu.c.compiler.option.debugging.level" value="mentor.gnu.c.debugging.level.max" valueType="enumerated"/>
|
||||
<option id="mentor.gnu.c.compiler.option.indexer_include.335417164" name="Include paths for indexer" superClass="mentor.gnu.c.compiler.option.indexer_include" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="${CFG_INCLUDE}"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/./"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/bsp/arch/plat-realview_eb/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/arch/arm/tool-csgnu_arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/tool-csgnu_arm/"/>
|
||||
</option>
|
||||
<option id="mentor.gnu.c.compiler.option.preprocessor.def.symbols.1534557880" name="Defined symbols (-D)" superClass="mentor.gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="WOLFSSL_USER_SETTINGS"/>
|
||||
</option>
|
||||
<option id="mentor.gnu.c.compiler.option.include.paths.2089432830" name="Include paths (-I)" superClass="mentor.gnu.c.compiler.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="../../../"/>
|
||||
<listOptionValue builtIn="false" value="../../../../wolfssl"/>
|
||||
<listOptionValue builtIn="false" value="../../../../wolfssl/IDE/CSBENCH"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.input.1877603173" superClass="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.c.linker.nucleus.1678700114" name="CodeSourcery GNU C Linker" superClass="cdt.managedbuild.tool.gnu.mentor.c.linker.nucleus">
|
||||
<option id="mentor.gnu.c.link.option.libs.1194482769" name="Libraries (-l)" superClass="mentor.gnu.c.link.option.libs" valueType="libs">
|
||||
<listOptionValue builtIn="false" value="wolfssl"/>
|
||||
</option>
|
||||
<option id="mentor.gnu.c.link.option.paths.1319236070" name="Library search path (-L)" superClass="mentor.gnu.c.link.option.paths" valueType="libPaths">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/wolfcrypt/Debug}""/>
|
||||
</option>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.cpp.linker.nucleus.596240520" name="CodeSourcery GNU C++ Linker" superClass="cdt.managedbuild.tool.gnu.mentor.cpp.linker.nucleus"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.assembler.nucleus.1670834398" name="CodeSourcery GNU Assembler" superClass="cdt.managedbuild.tool.gnu.mentor.assembler.nucleus">
|
||||
<option id="gnu.both.asm.option.debugging.level.1676640171" name="Debug Level" superClass="gnu.both.asm.option.debugging.level" value="gnu.both.asm.debugging.level.max" valueType="enumerated"/>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2026816449" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
<tool id="com.mentor.embedded.toolchains.core.nucleus.exportgen.process.1917586302" name="Nucleus Exports Generator" superClass="com.mentor.embedded.toolchains.core.nucleus.exportgen.process"/>
|
||||
<tool id="com.mentor.embedded.toolchains.core.nucleus.exportgen.application.2124639416" name="Nucleus Exports Generator" superClass="com.mentor.embedded.toolchains.core.nucleus.exportgen.application"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="src/misc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings">
|
||||
<externalSettings containerId="system-project;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"/>
|
||||
</storageModule>
|
||||
</cconfiguration>
|
||||
<cconfiguration id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.release.593147631">
|
||||
<storageModule buildSystemId="org.eclipse.cdt.managedbuilder.core.configurationDataProvider" id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.release.593147631" moduleId="org.eclipse.cdt.core.settings" name="Release">
|
||||
<externalSettings/>
|
||||
<extensions>
|
||||
<extension id="org.eclipse.cdt.core.ELF" point="org.eclipse.cdt.core.BinaryParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GASErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GmakeErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GLDErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="com.mentor.embedded.toolchains.core.nucleus.FuseErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.CWDLocator" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
<extension id="org.eclipse.cdt.core.GCCErrorParser" point="org.eclipse.cdt.core.ErrorParser"/>
|
||||
</extensions>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<configuration artifactName="${ProjName}" buildArtefactType="org.eclipse.cdt.build.core.buildArtefactType.exe" buildProperties="org.eclipse.cdt.build.core.buildArtefactType=org.eclipse.cdt.build.core.buildArtefactType.exe,org.eclipse.cdt.build.core.buildType=org.eclipse.cdt.build.core.buildType.release" cleanCommand="rm -rf" description="" id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.release.593147631" name="Release" parent="cdt.managedbuild.config.gnu.mentor.nucleus.exe.release" postbuildStep="${POSTLD} -O binary "${CWD}/${ProjName}.out" "${CWD}/${ProjName}.bin"" postcleanStep="">
|
||||
<folderInfo id="cdt.managedbuild.config.gnu.mentor.nucleus.exe.release.593147631." name="/" resourcePath="">
|
||||
<toolChain id="cdt.managedbuild.toolchain.gnu.mentor.nucleus.exe.release.4556438" name="Sourcery CodeBench for Nucleus" superClass="cdt.managedbuild.toolchain.gnu.mentor.nucleus.exe.release">
|
||||
<targetPlatform archList="all" binaryParser="org.eclipse.cdt.core.ELF" id="cdt.managedbuild.targetPlatform.gnu.mentor.nucleus.655260117" isAbstract="false" osList="all" superClass="cdt.managedbuild.targetPlatform.gnu.mentor.nucleus"/>
|
||||
<builder buildPath="${workspace_loc:/CSBENCH}/Release" id="cdt.managedbuild.builder.gnu.mentor.nucleus.461742616" keepEnvironmentInBuildfile="false" managedBuildOn="true" name="CodeSourcery GNU Builder" superClass="cdt.managedbuild.builder.gnu.mentor.nucleus"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.archiver.nucleus.114153486" name="CodeSourcery GNU Archiver" superClass="cdt.managedbuild.tool.gnu.mentor.archiver.nucleus"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.cpp.compiler.nucleus.79634184" name="CodeSourcery GNU C++ Compiler" superClass="cdt.managedbuild.tool.gnu.mentor.cpp.compiler.nucleus">
|
||||
<option id="mentor.gnu.cpp.compiler.option.optimization.level.2040515769" name="Optimization Level" superClass="mentor.gnu.cpp.compiler.option.optimization.level" value="mentor.gnu.cpp.compiler.optimization.level.most" valueType="enumerated"/>
|
||||
<option id="mentor.gnu.cpp.compiler.option.debugging.level.1751501356" name="Debug Level" superClass="mentor.gnu.cpp.compiler.option.debugging.level"/>
|
||||
<option id="mentor.gnu.cpp.compiler.option.indexer_include.1343364452" name="Include paths for indexer" superClass="mentor.gnu.cpp.compiler.option.indexer_include" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="${CFG_INCLUDE}"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/./"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/bsp/arch/plat-realview_eb/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/arch/arm/tool-csgnu_arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/tool-csgnu_arm/"/>
|
||||
</option>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.28888809" name="CodeSourcery GNU C Compiler" superClass="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus">
|
||||
<option defaultValue="mentor.gnu.c.optimization.level.most" id="mentor.gnu.c.compiler.option.optimization.level.1932130070" name="Optimization Level" superClass="mentor.gnu.c.compiler.option.optimization.level" valueType="enumerated"/>
|
||||
<option id="mentor.gnu.c.compiler.option.debugging.level.709958810" name="Debug Level" superClass="mentor.gnu.c.compiler.option.debugging.level"/>
|
||||
<option id="mentor.gnu.c.compiler.option.indexer_include.717141201" name="Include paths for indexer" superClass="mentor.gnu.c.compiler.option.indexer_include" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="${CFG_INCLUDE}"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/./"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/bsp/realview_eb_ct926ejs/include/bsp/arch/plat-realview_eb/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/arch/arm/tool-csgnu_arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/"/>
|
||||
<listOptionValue builtIn="false" value="${SYSTEM_HOME}/os/include/arch/arm/tool-csgnu_arm/"/>
|
||||
</option>
|
||||
<option id="mentor.gnu.c.compiler.option.preprocessor.def.symbols.925278548" name="Defined symbols (-D)" superClass="mentor.gnu.c.compiler.option.preprocessor.def.symbols" valueType="definedSymbols">
|
||||
<listOptionValue builtIn="false" value="WOLFSSL_USER_SETTINGS"/>
|
||||
</option>
|
||||
<option id="mentor.gnu.c.compiler.option.include.paths.308993068" name="Include paths (-I)" superClass="mentor.gnu.c.compiler.option.include.paths" valueType="includePath">
|
||||
<listOptionValue builtIn="false" value="../../../"/>
|
||||
<listOptionValue builtIn="false" value="../../../../wolfssl"/>
|
||||
<listOptionValue builtIn="false" value="../../../../wolfssl/IDE/CSBENCH"/>
|
||||
</option>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.input.25852946" superClass="cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.input"/>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.c.linker.nucleus.636842819" name="CodeSourcery GNU C Linker" superClass="cdt.managedbuild.tool.gnu.mentor.c.linker.nucleus">
|
||||
<option id="mentor.gnu.c.link.option.libs.554706755" name="Libraries (-l)" superClass="mentor.gnu.c.link.option.libs" valueType="libs">
|
||||
<listOptionValue builtIn="false" value="wolfssl"/>
|
||||
</option>
|
||||
<option id="mentor.gnu.c.link.option.paths.2121461092" name="Library search path (-L)" superClass="mentor.gnu.c.link.option.paths" valueType="libPaths">
|
||||
<listOptionValue builtIn="false" value=""${workspace_loc:/wolfcrypt/Release}""/>
|
||||
</option>
|
||||
</tool>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.cpp.linker.nucleus.1551851046" name="CodeSourcery GNU C++ Linker" superClass="cdt.managedbuild.tool.gnu.mentor.cpp.linker.nucleus"/>
|
||||
<tool id="cdt.managedbuild.tool.gnu.mentor.assembler.nucleus.2138744001" name="CodeSourcery GNU Assembler" superClass="cdt.managedbuild.tool.gnu.mentor.assembler.nucleus">
|
||||
<option id="gnu.both.asm.option.debugging.level.1046354273" name="Debug Level" superClass="gnu.both.asm.option.debugging.level" value="gnu.both.asm.debugging.level.none" valueType="enumerated"/>
|
||||
<inputType id="cdt.managedbuild.tool.gnu.assembler.input.2099604782" superClass="cdt.managedbuild.tool.gnu.assembler.input"/>
|
||||
</tool>
|
||||
<tool id="com.mentor.embedded.toolchains.core.nucleus.exportgen.process.255113742" name="Nucleus Exports Generator" superClass="com.mentor.embedded.toolchains.core.nucleus.exportgen.process"/>
|
||||
<tool id="com.mentor.embedded.toolchains.core.nucleus.exportgen.application.942752326" name="Nucleus Exports Generator" superClass="com.mentor.embedded.toolchains.core.nucleus.exportgen.application"/>
|
||||
</toolChain>
|
||||
</folderInfo>
|
||||
<sourceEntries>
|
||||
<entry excluding="src/misc.c" flags="VALUE_WORKSPACE_PATH|RESOLVED" kind="sourcePath" name=""/>
|
||||
</sourceEntries>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.externalSettings">
|
||||
<externalSettings containerId="system-project;" factoryId="org.eclipse.cdt.core.cfg.export.settings.sipplier"/>
|
||||
</storageModule>
|
||||
</cconfiguration>
|
||||
</storageModule>
|
||||
<storageModule moduleId="cdtBuildSystem" version="4.0.0">
|
||||
<project id="CSBENCH.cdt.managedbuild.target.gnu.mentor.nucleus.exe.1080439571" name="Executable" projectType="cdt.managedbuild.target.gnu.mentor.nucleus.exe"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="scannerConfiguration">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId=""/>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mentor.nucleus.exe.release.593147631;cdt.managedbuild.config.gnu.mentor.nucleus.exe.release.593147631.;cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.28888809;cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.input.25852946">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.mentor.embedded.toolchains.core.nucleus.GCCManagedMakePerProjectProfileC"/>
|
||||
</scannerConfigBuildInfo>
|
||||
<scannerConfigBuildInfo instanceId="cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug.1214077048;cdt.managedbuild.config.gnu.mentor.nucleus.exe.debug.1214077048.;cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.733911603;cdt.managedbuild.tool.gnu.mentor.c.compiler.nucleus.input.1877603173">
|
||||
<autodiscovery enabled="true" problemReportingEnabled="true" selectedProfileId="com.mentor.embedded.toolchains.core.nucleus.GCCManagedMakePerProjectProfileC"/>
|
||||
</scannerConfigBuildInfo>
|
||||
</storageModule>
|
||||
<storageModule moduleId="org.eclipse.cdt.core.LanguageSettingsProviders"/>
|
||||
<storageModule moduleId="com.mentor.embedded">
|
||||
<project systemProject="system-project" version="2017.02.1"/>
|
||||
</storageModule>
|
||||
<storageModule moduleId="refreshScope" versionNumber="2">
|
||||
<configuration configurationName="Debug">
|
||||
<resource resourceType="PROJECT" workspacePath="/sftp"/>
|
||||
</configuration>
|
||||
<configuration configurationName="Release">
|
||||
<resource resourceType="PROJECT" workspacePath="/sftp"/>
|
||||
</configuration>
|
||||
</storageModule>
|
||||
</cproject>
|
|
@ -0,0 +1,38 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>sftp</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.genmakebuilder</name>
|
||||
<triggers>clean,full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
<buildCommand>
|
||||
<name>org.eclipse.cdt.managedbuilder.core.ScannerConfigBuilder</name>
|
||||
<triggers>full,incremental,</triggers>
|
||||
<arguments>
|
||||
</arguments>
|
||||
</buildCommand>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
<nature>org.eclipse.cdt.core.cnature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.managedBuildNature</nature>
|
||||
<nature>org.eclipse.cdt.managedbuilder.core.ScannerConfigNature</nature>
|
||||
</natures>
|
||||
<linkedResources>
|
||||
<link>
|
||||
<name>echoserver</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-2-PROJECT_LOC../examples/echoserver</locationURI>
|
||||
</link>
|
||||
<link>
|
||||
<name>src</name>
|
||||
<type>2</type>
|
||||
<locationURI>PARENT-2-PROJECT_LOC../src</locationURI>
|
||||
</link>
|
||||
</linkedResources>
|
||||
</projectDescription>
|
|
@ -0,0 +1,13 @@
|
|||
This is to build with Sourcery CodeBench IDE
|
||||
|
||||
It makes the assumption that the root wolfssl and wolfssh directory are in the same folder
|
||||
|
||||
workspace ->
|
||||
->wolfssl
|
||||
->wolfssh
|
||||
|
||||
To build first compile the wolfssl library using the project provided in wolfssl/IDE/CSBENCH
|
||||
|
||||
Next compile the sftp example project provided in wolfssh/ide/CSBENCH
|
||||
|
||||
Note that this is using port 8080 to listen on by default
|
|
@ -0,0 +1,7 @@
|
|||
# vim:ft=automake
|
||||
# included from Top Level Makefile.am
|
||||
# All paths should be given relative to the root
|
||||
|
||||
EXTRA_DIST+= ide/CSBENCH/.cproject
|
||||
EXTRA_DIST+= ide/CSBENCH/.project
|
||||
EXTRA_DIST+= ide/CSBENCH/README
|
|
@ -1,5 +1,6 @@
|
|||
# vim:ft=automake
|
||||
# included from Top Level Makefile.am
|
||||
# All paths should be given relative to the root
|
||||
|
||||
include ide/winvs/include.am
|
||||
# vim:ft=automake
|
||||
# included from Top Level Makefile.am
|
||||
# All paths should be given relative to the root
|
||||
|
||||
include ide/winvs/include.am
|
||||
include ide/CSBENCH/include.am
|
||||
|
|
122
src/internal.c
122
src/internal.c
|
@ -236,6 +236,9 @@ const char* GetErrorString(int err)
|
|||
case WS_SFTP_COMPLETE:
|
||||
return "sftp connection established";
|
||||
|
||||
case WS_NEXT_ERROR:
|
||||
return "Getting next value/state results in error";
|
||||
|
||||
default:
|
||||
return "Unknown error code";
|
||||
}
|
||||
|
@ -4502,7 +4505,7 @@ int DoReceive(WOLFSSH* ssh)
|
|||
return ret;
|
||||
}
|
||||
}
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case PROCESS_PACKET_LENGTH:
|
||||
if (ssh->inputBuffer.idx + UINT32_SZ > ssh->inputBuffer.bufferSz)
|
||||
|
@ -4515,7 +4518,7 @@ int DoReceive(WOLFSSH* ssh)
|
|||
return WS_OVERFLOW_E;
|
||||
|
||||
ssh->processReplyState = PROCESS_PACKET_FINISH;
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case PROCESS_PACKET_FINISH:
|
||||
readSz = ssh->curSz + LENGTH_SZ + peerMacSz;
|
||||
|
@ -4581,7 +4584,7 @@ int DoReceive(WOLFSSH* ssh)
|
|||
}
|
||||
}
|
||||
ssh->processReplyState = PROCESS_PACKET;
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case PROCESS_PACKET:
|
||||
if ( (ret = DoPacket(ssh)) < 0) {
|
||||
|
@ -4604,6 +4607,7 @@ int DoReceive(WOLFSSH* ssh)
|
|||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -7007,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
|
||||
|
|
15
src/io.c
15
src/io.c
|
@ -128,6 +128,10 @@ void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh)
|
|||
#include "tcpip/tcpip.h"
|
||||
#include "sys/errno.h"
|
||||
#include <errno.h>
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#include "nucleus.h"
|
||||
#include "networking/nu_networking.h"
|
||||
#include <errno.h>
|
||||
#else
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
|
@ -208,6 +212,14 @@ void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh)
|
|||
#define SOCKET_ECONNREFUSED SCK_ERROR
|
||||
#define SOCKET_ECONNABORTED SCK_ERROR
|
||||
#endif
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#define SOCKET_EWOULDBLOCK NU_WOULD_BLOCK
|
||||
#define SOCKET_EAGAIN NU_WOULD_BLOCK
|
||||
#define SOCKET_ECONNRESET NU_NOT_CONNECTED
|
||||
#define SOCKET_EINTR NU_NOT_CONNECTED
|
||||
#define SOCKET_EPIPE NU_NOT_CONNECTED
|
||||
#define SOCKET_ECONNREFUSED NU_CONNECTION_REFUSED
|
||||
#define SOCKET_ECONNABORTED NU_NOT_CONNECTED
|
||||
#else
|
||||
#define SOCKET_EWOULDBLOCK EWOULDBLOCK
|
||||
#define SOCKET_EAGAIN EAGAIN
|
||||
|
@ -233,6 +245,9 @@ void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh)
|
|||
TCPIP_TCP_ArrayPut((socket),(uint8_t*)(buf),(sz))
|
||||
#define RECV_FUNCTION(socket,buf,sz,flags) \
|
||||
TCPIP_TCP_ArrayGet((socket),(uint8_t*)(buf),(sz))
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#define SEND_FUNCTION NU_Send
|
||||
#define RECV_FUNCTION NU_Recv
|
||||
#else
|
||||
#define SEND_FUNCTION send
|
||||
#define RECV_FUNCTION recv
|
||||
|
|
|
@ -29,7 +29,13 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_USER_SETTINGS
|
||||
#include <wolfssl/wolfcrypt/settings.h>
|
||||
#else
|
||||
#include <wolfssl/options.h>
|
||||
#endif
|
||||
|
||||
|
||||
#include <wolfssl/wolfcrypt/random.h>
|
||||
#include <wolfssl/wolfcrypt/rsa.h>
|
||||
#include <wolfssh/error.h>
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
30
src/port.c
30
src/port.c
|
@ -40,6 +40,36 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
|
|||
{
|
||||
#ifdef USE_WINDOWS_API
|
||||
return fopen_s(f, filename, mode) != 0;
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
int m = WOLFSSH_O_CREAT;
|
||||
|
||||
if (WSTRSTR(mode, "r") && WSTRSTR(mode, "w")) {
|
||||
m |= WOLFSSH_O_RDWR;
|
||||
}
|
||||
else {
|
||||
if (WSTRSTR(mode, "r")) {
|
||||
m |= WOLFSSH_O_RDONLY;
|
||||
}
|
||||
if (WSTRSTR(mode, "w")) {
|
||||
m |= WOLFSSH_O_WRONLY;
|
||||
}
|
||||
}
|
||||
|
||||
if (filename != NULL && f != NULL) {
|
||||
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 1;
|
||||
}
|
||||
#else
|
||||
if (f != NULL) {
|
||||
*f = fopen(filename, mode);
|
||||
|
|
46
src/ssh.c
46
src/ssh.c
|
@ -270,7 +270,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_SERVER_VERSION_SENT;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_VERSION_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_SERVER_VERSION_SENT:
|
||||
while (ssh->clientState < CLIENT_VERSION_DONE) {
|
||||
|
@ -282,7 +282,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_CLIENT_VERSION_DONE;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "CLIENT_VERSION_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_CLIENT_VERSION_DONE:
|
||||
if ( (ssh->error = SendKexInit(ssh)) < WS_SUCCESS) {
|
||||
|
@ -292,7 +292,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_SERVER_KEXINIT_SENT;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_KEXINIT_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_SERVER_KEXINIT_SENT:
|
||||
while (ssh->isKeying) {
|
||||
|
@ -304,7 +304,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_KEYED;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "KEYED");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_KEYED:
|
||||
while (ssh->clientState < CLIENT_USERAUTH_REQUEST_DONE) {
|
||||
|
@ -316,7 +316,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_CLIENT_USERAUTH_REQUEST_DONE;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "CLIENT_USERAUTH_REQUEST_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_CLIENT_USERAUTH_REQUEST_DONE:
|
||||
if ( (ssh->error = SendServiceAccept(ssh,
|
||||
|
@ -328,7 +328,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
ssh->acceptState = ACCEPT_SERVER_USERAUTH_ACCEPT_SENT;
|
||||
WLOG(WS_LOG_DEBUG, acceptState,
|
||||
"ACCEPT_SERVER_USERAUTH_ACCEPT_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_SERVER_USERAUTH_ACCEPT_SENT:
|
||||
while (ssh->clientState < CLIENT_USERAUTH_DONE) {
|
||||
|
@ -340,7 +340,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_CLIENT_USERAUTH_DONE;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "CLIENT_USERAUTH_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_CLIENT_USERAUTH_DONE:
|
||||
if ( (ssh->error = SendUserAuthSuccess(ssh)) < WS_SUCCESS) {
|
||||
|
@ -350,7 +350,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_SERVER_USERAUTH_SENT;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_USERAUTH_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_SERVER_USERAUTH_SENT:
|
||||
while (ssh->clientState < CLIENT_CHANNEL_OPEN_DONE) {
|
||||
|
@ -362,7 +362,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_CLIENT_CHANNEL_REQUEST_DONE;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "CLIENT_CHANNEL_REQUEST_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_CLIENT_CHANNEL_REQUEST_DONE:
|
||||
if ( (ssh->error = SendChannelOpenConf(ssh)) < WS_SUCCESS) {
|
||||
|
@ -372,7 +372,7 @@ int wolfSSH_accept(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->acceptState = ACCEPT_SERVER_CHANNEL_ACCEPT_SENT;
|
||||
WLOG(WS_LOG_DEBUG, acceptState, "SERVER_CHANNEL_ACCEPT_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case ACCEPT_SERVER_CHANNEL_ACCEPT_SENT:
|
||||
while (ssh->clientState < CLIENT_DONE) {
|
||||
|
@ -440,7 +440,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_CLIENT_VERSION_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "CLIENT_VERSION_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_VERSION_SENT:
|
||||
while (ssh->serverState < SERVER_VERSION_DONE) {
|
||||
|
@ -452,7 +452,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_SERVER_VERSION_DONE;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "SERVER_VERSION_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_SERVER_VERSION_DONE:
|
||||
if ( (ssh->error = SendKexInit(ssh)) < WS_SUCCESS) {
|
||||
|
@ -462,7 +462,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_CLIENT_KEXINIT_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "CLIENT_KEXINIT_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_KEXINIT_SENT:
|
||||
while (ssh->serverState < SERVER_KEXINIT_DONE) {
|
||||
|
@ -474,7 +474,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_SERVER_KEXINIT_DONE;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "SERVER_KEXINIT_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_SERVER_KEXINIT_DONE:
|
||||
if (ssh->handshake->kexId == ID_DH_GEX_SHA256)
|
||||
|
@ -488,7 +488,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_CLIENT_KEXDH_INIT_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "CLIENT_KEXDH_INIT_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_KEXDH_INIT_SENT:
|
||||
while (ssh->isKeying) {
|
||||
|
@ -500,7 +500,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_KEYED;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "KEYED");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_KEYED:
|
||||
if ( (ssh->error = SendServiceRequest(ssh, ID_SERVICE_USERAUTH)) <
|
||||
|
@ -510,7 +510,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_CLIENT_USERAUTH_REQUEST_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "CLIENT_USERAUTH_REQUEST_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_USERAUTH_REQUEST_SENT:
|
||||
while (ssh->serverState < SERVER_USERAUTH_REQUEST_DONE) {
|
||||
|
@ -522,7 +522,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_SERVER_USERAUTH_REQUEST_DONE;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "SERVER_USERAUTH_REQUEST_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_SERVER_USERAUTH_REQUEST_DONE:
|
||||
if ( (ssh->error = SendUserAuthRequest(ssh, ID_NONE)) <
|
||||
|
@ -533,7 +533,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_CLIENT_USERAUTH_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "CLIENT_USERAUTH_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_USERAUTH_SENT:
|
||||
while (ssh->serverState < SERVER_USERAUTH_ACCEPT_DONE) {
|
||||
|
@ -545,7 +545,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
}
|
||||
ssh->connectState = CONNECT_SERVER_USERAUTH_ACCEPT_DONE;
|
||||
WLOG(WS_LOG_DEBUG, connectState, "SERVER_USERAUTH_ACCEPT_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_SERVER_USERAUTH_ACCEPT_DONE:
|
||||
if ( (ssh->error = SendChannelOpenSession(ssh, DEFAULT_WINDOW_SZ,
|
||||
|
@ -557,7 +557,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
ssh->connectState = CONNECT_CLIENT_CHANNEL_OPEN_SESSION_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState,
|
||||
"CLIENT_CHANNEL_OPEN_SESSION_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_CHANNEL_OPEN_SESSION_SENT:
|
||||
while (ssh->serverState < SERVER_CHANNEL_OPEN_DONE) {
|
||||
|
@ -570,7 +570,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
ssh->connectState = CONNECT_SERVER_CHANNEL_OPEN_SESSION_DONE;
|
||||
WLOG(WS_LOG_DEBUG, connectState,
|
||||
"SERVER_CHANNEL_OPEN_SESSION_DONE");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_SERVER_CHANNEL_OPEN_SESSION_DONE:
|
||||
if ( (ssh->error = SendChannelRequest(ssh, ssh->channelName,
|
||||
|
@ -582,7 +582,7 @@ int wolfSSH_connect(WOLFSSH* ssh)
|
|||
ssh->connectState = CONNECT_CLIENT_CHANNEL_REQUEST_SENT;
|
||||
WLOG(WS_LOG_DEBUG, connectState,
|
||||
"CLIENT_CHANNEL_REQUEST_SENT");
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case CONNECT_CLIENT_CHANNEL_REQUEST_SENT:
|
||||
while (ssh->serverState < SERVER_DONE) {
|
||||
|
|
193
src/wolfscp.c
193
src/wolfscp.c
|
@ -31,12 +31,14 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssh/wolfscp.h>
|
||||
|
||||
#ifdef WOLFSSH_SCP
|
||||
|
||||
#include <wolfssh/ssh.h>
|
||||
#include <wolfssh/internal.h>
|
||||
#include <wolfssh/log.h>
|
||||
#include <wolfssh/wolfscp.h>
|
||||
|
||||
|
||||
#ifdef NO_INLINE
|
||||
#include <wolfssh/misc.h>
|
||||
|
@ -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 */
|
||||
|
@ -1155,7 +1160,7 @@ int ReceiveScpMessage(WOLFSSH* ssh)
|
|||
|
||||
switch (buf[0]) {
|
||||
case 'C':
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case 'D':
|
||||
if (buf[0] == 'C') {
|
||||
|
@ -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;
|
||||
|
@ -1255,7 +1263,7 @@ int SendScpConfirmation(WOLFSSH* ssh)
|
|||
|
||||
case WS_SCP_CONTINUE:
|
||||
/* default to ok confirmation */
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
default:
|
||||
msg[0] = SCP_CONFIRM_OK;
|
||||
|
@ -1307,9 +1315,9 @@ int ReceiveScpConfirmation(WOLFSSH* ssh)
|
|||
case SCP_CONFIRM_OK:
|
||||
break;
|
||||
case SCP_CONFIRM_ERR:
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
case SCP_CONFIRM_FATAL:
|
||||
FALL_THROUGH;
|
||||
FALL_THROUGH /* no break */
|
||||
default:
|
||||
WLOG(WS_LOG_ERROR,
|
||||
"scp error: peer sent error confirmation (code: %d)",
|
||||
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
670
src/wolfsftp.c
670
src/wolfsftp.c
|
@ -23,9 +23,11 @@
|
|||
#include <config.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssh/ssh.h>
|
||||
#include <wolfssh/internal.h>
|
||||
#include <wolfssh/wolfsftp.h>
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
|
||||
#include <wolfssh/internal.h>
|
||||
#include <wolfssh/log.h>
|
||||
|
||||
#ifdef NO_INLINE
|
||||
|
@ -41,6 +43,7 @@ static int SFTP_ParseAtributes_buffer(WOLFSSH* ssh, WS_SFTP_FILEATRB* atr,
|
|||
byte* buf, word32 bufSz);
|
||||
static int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr,
|
||||
byte link);
|
||||
static int SFTP_GetAttributes_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr);
|
||||
static WS_SFTPNAME* wolfSSH_SFTPNAME_new(void* heap);
|
||||
|
||||
/* Gets packet header information
|
||||
|
@ -199,7 +202,7 @@ int wolfSSH_SFTP_accept(WOLFSSH* ssh)
|
|||
return WS_FATAL_ERROR;
|
||||
}
|
||||
ssh->connectState = SFTP_RECV;
|
||||
FALL_THROUGH
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case SFTP_RECV:
|
||||
if ((ssh->error = SFTP_ServerSendInit(ssh)) != WS_SUCCESS) {
|
||||
|
@ -305,87 +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;
|
||||
|
||||
/* remove any double '/' chars */
|
||||
for (i = 0; i < sz; i++) {
|
||||
if (path[i] == '/' && path[i+1] == '/') {
|
||||
WMEMMOVE(path + i, path + i + 1, sz - i + 1);
|
||||
sz -= 1;
|
||||
i--;
|
||||
}
|
||||
}
|
||||
|
||||
/* remove any trailing '.' and '/' chars */
|
||||
sz = WSTRLEN(path);
|
||||
do {
|
||||
i = (int)sz - 1;
|
||||
if (i > 0 && path[i] == '.' && path[i-1] == '.') {
|
||||
break;
|
||||
}
|
||||
|
||||
if (path[i] == '.' || path[i] == '/') {
|
||||
path[i] = '\0';
|
||||
|
||||
}
|
||||
sz = WSTRLEN(path);
|
||||
} while ((int)sz - 1 > 0 &&
|
||||
(path[(int)sz - 1] == '.' || path[(int)sz - 1] == '/'));
|
||||
|
||||
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 = 0; i < sz; i++) {
|
||||
if (path[i] == '/') {
|
||||
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] == '/') {
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* returns WS_SUCCESS on success */
|
||||
static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
||||
{
|
||||
|
@ -394,6 +316,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
|||
char r[WOLFSSH_MAX_FILENAME];
|
||||
word32 rSz;
|
||||
word32 idx = 0;
|
||||
word32 i;
|
||||
byte* out;
|
||||
|
||||
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_REALPATH");
|
||||
|
@ -414,7 +337,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
|||
}
|
||||
|
||||
ato32((byte*)dir, &rSz);
|
||||
if (rSz > WOLFSSH_MAX_FILENAME) {
|
||||
if (rSz > WOLFSSH_MAX_FILENAME || (int)(rSz + UINT32_SZ) > maxSz) {
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
|
@ -423,7 +346,7 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
|||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
/* get working directory in the case of receiving non absolute path */
|
||||
if (r[0] != '/') {
|
||||
if (r[0] != '/' && r[1] != ':') {
|
||||
char wd[WOLFSSH_MAX_FILENAME];
|
||||
|
||||
if (WGETCWD(wd, WOLFSSH_MAX_FILENAME) == NULL) {
|
||||
|
@ -436,8 +359,14 @@ static int wolfSSH_SFTP_RecvRealPath(WOLFSSH* ssh, int reqId, int maxSz)
|
|||
WSTRNCAT(wd, r, WOLFSSH_MAX_FILENAME - 1);
|
||||
WMEMCPY(r, wd, WOLFSSH_MAX_FILENAME);
|
||||
}
|
||||
|
||||
clean_path(r);
|
||||
rSz = (int)WSTRLEN(r);
|
||||
|
||||
/* for real path always send '/' chars */
|
||||
for (i = 0; i < rSz; i++) {
|
||||
if (r[i] == WS_DELIM) r[i] = '/';
|
||||
}
|
||||
WLOG(WS_LOG_SFTP, "Real Path Directory = %s", r);
|
||||
|
||||
/* send response */
|
||||
|
@ -514,6 +443,9 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
|
|||
case WOLFSSH_FTP_LSTAT:
|
||||
return wolfSSH_SFTP_RecvLSTAT(ssh, reqId, maxSz);
|
||||
|
||||
case WOLFSSH_FTP_FSTAT:
|
||||
return wolfSSH_SFTP_RecvFSTAT(ssh, reqId, maxSz);
|
||||
|
||||
case WOLFSSH_FTP_OPEN:
|
||||
return wolfSSH_SFTP_RecvOpen(ssh, reqId, maxSz);
|
||||
|
||||
|
@ -544,7 +476,7 @@ int wolfSSH_SFTP_read(WOLFSSH* ssh)
|
|||
/* read rest of data off the wire and send error status to client */
|
||||
{
|
||||
byte* data;
|
||||
WLOG(WS_LOG_SFTP, "Unknown packet type received");
|
||||
WLOG(WS_LOG_SFTP, "Unknown packet type [%d] received", type);
|
||||
data = (byte*)WMALLOC(maxSz, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (data != NULL) {
|
||||
wolfSSH_stream_read(ssh, data, maxSz);
|
||||
|
@ -605,6 +537,11 @@ int wolfSSH_SFTP_SendStatus(WOLFSSH* ssh, word32 status, word32 reqId,
|
|||
c32toa(status, buf + idx); idx += UINT32_SZ;
|
||||
|
||||
sz = (reason != NULL)? (int)WSTRLEN(reason): 0;
|
||||
if (sz + idx + UINT32_SZ > maxSz) {
|
||||
WFREE(buf, ssh->heap, DYNTYPE_BUFFER);
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
c32toa(sz, buf + idx); idx += UINT32_SZ;
|
||||
if (reason != NULL) {
|
||||
WMEMCPY(buf + idx, reason, sz); idx += sz;
|
||||
|
@ -612,6 +549,11 @@ int wolfSSH_SFTP_SendStatus(WOLFSSH* ssh, word32 status, word32 reqId,
|
|||
|
||||
|
||||
sz = (lang != NULL)? (int)WSTRLEN(lang): 0;
|
||||
if (sz + idx + UINT32_SZ > maxSz) {
|
||||
WFREE(buf, ssh->heap, DYNTYPE_BUFFER);
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
c32toa(sz, buf + idx); idx += UINT32_SZ;
|
||||
if (lang != NULL) {
|
||||
WMEMCPY(buf + idx, lang, sz);
|
||||
|
@ -666,6 +608,7 @@ int wolfSSH_SFTP_RecvRMDIR(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WMEMCPY(dir, data + idx, sz);
|
||||
dir[sz] = '\0';
|
||||
|
||||
clean_path(dir);
|
||||
ret = WRMDIR(dir);
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
@ -696,7 +639,7 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
int ret;
|
||||
byte* data;
|
||||
char* dir;
|
||||
word32 mode;
|
||||
word32 mode = 0;
|
||||
word32 idx = 0;
|
||||
|
||||
if (ssh == NULL) {
|
||||
|
@ -730,11 +673,12 @@ int wolfSSH_SFTP_RecvMKDIR(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
if (sz != UINT32_SZ) {
|
||||
WLOG(WS_LOG_SFTP, "Attribute size larger than 4 not yet supported");
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
WLOG(WS_LOG_SFTP, "Skipping over attribute");
|
||||
}
|
||||
ato32(data + idx, &mode);
|
||||
else {
|
||||
ato32(data + idx, &mode);
|
||||
}
|
||||
clean_path(dir);
|
||||
ret = WMKDIR(dir, mode);
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
@ -811,28 +755,28 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
if ((reason & WOLFSSH_FXF_READ) && (reason & WOLFSSH_FXF_WRITE)) {
|
||||
m |= O_RDWR;
|
||||
m |= WOLFSSH_O_RDWR;
|
||||
}
|
||||
else {
|
||||
if (reason & WOLFSSH_FXF_READ) {
|
||||
m |= O_RDONLY;
|
||||
m |= WOLFSSH_O_RDONLY;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_WRITE) {
|
||||
m |= O_WRONLY;
|
||||
m |= WOLFSSH_O_WRONLY;
|
||||
}
|
||||
}
|
||||
|
||||
if (reason & WOLFSSH_FXF_APPEND) {
|
||||
m |= O_APPEND;
|
||||
m |= WOLFSSH_O_APPEND;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_CREAT) {
|
||||
m |= O_CREAT;
|
||||
m |= WOLFSSH_O_CREAT;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_TRUNC) {
|
||||
m |= O_TRUNC;
|
||||
m |= WOLFSSH_O_TRUNC;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_EXCL) {
|
||||
m |= O_EXCL;
|
||||
m |= WOLFSSH_O_EXCL;
|
||||
}
|
||||
|
||||
/* if file permissions not set then use default */
|
||||
|
@ -840,6 +784,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
atr.per = 0644;
|
||||
}
|
||||
|
||||
clean_path(dir);
|
||||
fd = WOPEN(dir, m, atr.per);
|
||||
if (fd < 0) {
|
||||
WLOG(WS_LOG_SFTP, "Error opening file %s", dir);
|
||||
|
@ -849,6 +794,15 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
return WS_BAD_FILE_E;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
if (SFTP_AddHandleNode(ssh, (byte*)&fd, sizeof(WFD), dir) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to store handle");
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_FAILURE, reqId,
|
||||
"Internal Failure", "English");
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
#endif
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
SendPacketType(ssh, WOLFSSH_FTP_HANDLE, (byte*)&fd, sizeof(WFD));
|
||||
|
@ -862,6 +816,7 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
/* hold pointers to directory handles */
|
||||
typedef struct DIR_HANDLE {
|
||||
WDIR dir;
|
||||
byte isEof; /* flag for if read everything */
|
||||
word64 id; /* handle ID */
|
||||
struct DIR_HANDLE* next;
|
||||
} DIR_HANDLE;
|
||||
|
@ -917,10 +872,14 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
/* get directory handle */
|
||||
ctx = WOPENDIR(dir);
|
||||
if (ctx == NULL) {
|
||||
clean_path(dir);
|
||||
if (WOPENDIR(&ctx, dir) != 0) {
|
||||
WLOG(WS_LOG_SFTP, "Error with opening directory");
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_NOFILE, reqId,
|
||||
"Unable To Open Directory", "English");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
WFREE(dir, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
|
@ -933,9 +892,14 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
if (dirList == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
WMEMCPY(&dirList->dir, &ctx, sizeof(WDIR));
|
||||
#else
|
||||
dirList->dir = ctx;
|
||||
dirList->id = idCount++;
|
||||
dirList->next = NULL;
|
||||
#endif
|
||||
dirList->id = idCount++;
|
||||
dirList->isEof = 0;
|
||||
dirList->next = NULL;
|
||||
SendPacketType(ssh, WOLFSSH_FTP_HANDLE, (byte*)&dirList->id,
|
||||
sizeof(word64));
|
||||
}
|
||||
|
@ -945,10 +909,15 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
if (cur == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
WMEMCPY(&cur->dir, &ctx, sizeof(WDIR));
|
||||
#else
|
||||
cur->dir = ctx;
|
||||
cur->id = idCount++;
|
||||
cur->next = dirList;
|
||||
dirList = cur;
|
||||
#endif
|
||||
cur->id = idCount++;
|
||||
cur->isEof = 0;
|
||||
cur->next = dirList;
|
||||
dirList = cur;
|
||||
SendPacketType(ssh, WOLFSSH_FTP_HANDLE, (byte*)&cur->id,
|
||||
sizeof(word64));
|
||||
}
|
||||
|
@ -957,12 +926,54 @@ int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
/* For Nucleus port
|
||||
* helper function that gets file information from reading directory
|
||||
* @TODO allow user to override
|
||||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
||||
{
|
||||
int sz;
|
||||
|
||||
if (dir == NULL || ssh == NULL || out == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
sz = (int)WSTRLEN(dir->sfname);
|
||||
out->fName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (out->fName == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
WMEMCPY(out->fName, dir->sfname, sz);
|
||||
out->fName[sz] = '\0';
|
||||
out->fSz = sz;
|
||||
|
||||
sz = (int)WSTRLEN(dir->lfname);
|
||||
out->lName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (out ->lName == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
WMEMCPY(out->lName, dir->lfname, sz);
|
||||
out->lName[sz] = '\0';
|
||||
out->lSz = sz;
|
||||
|
||||
SFTP_GetAttributes(out->fName, &out->atrb, 0);
|
||||
|
||||
if ((WREADDIR(dir)) == NULL) {
|
||||
return WS_NEXT_ERROR;
|
||||
}
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
/* helper function that gets file information from reading directory
|
||||
* @TODO allow user to override
|
||||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR dir, WS_SFTPNAME* out)
|
||||
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out)
|
||||
{
|
||||
struct dirent* dp;
|
||||
int sz;
|
||||
|
@ -983,6 +994,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR dir, WS_SFTPNAME* out)
|
|||
}
|
||||
out->lName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (out ->lName == NULL) {
|
||||
WFREE(out->fName, out->heap, DYNTYPE_SFTP);
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
|
@ -1000,6 +1012,7 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR dir, WS_SFTPNAME* out)
|
|||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* helper function to create a name packet. out buffer will have the following
|
||||
|
@ -1033,6 +1046,11 @@ static int wolfSSH_SFTP_SendName(WOLFSSH* ssh, WS_SFTPNAME* list, word32 count,
|
|||
c32toa(count, out + idx); idx += UINT32_SZ;
|
||||
|
||||
for (i = 0; i < count && cur != NULL; i++) {
|
||||
if (*outSz - idx < cur->fSz + cur->lSz + UINT32_SZ * 2) {
|
||||
/* not enough space for the buffer */
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
c32toa(cur->fSz, out + idx); idx += UINT32_SZ;
|
||||
WMEMCPY(out + idx, cur->fName, cur->fSz); idx += cur->fSz;
|
||||
c32toa(cur->lSz, out + idx); idx += UINT32_SZ;
|
||||
|
@ -1067,6 +1085,7 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WS_SFTPNAME* name = NULL;
|
||||
WS_SFTPNAME* list = NULL;
|
||||
word32 outSz = 0;
|
||||
DIR_HANDLE* cur = dirList;
|
||||
|
||||
if (ssh == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
@ -1089,19 +1108,16 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WMEMCPY((byte*)&handle, data + idx, sz);
|
||||
|
||||
/* find DIR given handle */
|
||||
{
|
||||
DIR_HANDLE* cur = dirList;
|
||||
while (cur != NULL) {
|
||||
if (cur->id == handle) {
|
||||
dir = cur->dir;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur == NULL) {
|
||||
/* unable to find handle */
|
||||
return WS_FATAL_ERROR;
|
||||
while (cur != NULL) {
|
||||
if (cur->id == handle) {
|
||||
dir = cur->dir;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
if (cur == NULL) {
|
||||
/* unable to find handle */
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
/* this closes the directory before returning */
|
||||
|
@ -1111,8 +1127,8 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
outSz += UINT32_SZ + WOLFSSH_SFTP_HEADER; /* hold header+number of files */
|
||||
do {
|
||||
name = wolfSSH_SFTPNAME_new(ssh->ctx->heap);
|
||||
ret = wolfSSH_SFTPNAME_readdir(ssh, dir, name);
|
||||
if (ret == WS_SUCCESS) {
|
||||
ret = wolfSSH_SFTPNAME_readdir(ssh, &dir, name);
|
||||
if (ret == WS_SUCCESS || ret == WS_NEXT_ERROR) {
|
||||
count++;
|
||||
outSz += name->fSz + name->lSz + (UINT32_SZ * 2);
|
||||
outSz += SFTP_AtributesSz(ssh, &name->atrb);
|
||||
|
@ -1130,12 +1146,18 @@ int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
} while (ret == WS_SUCCESS);
|
||||
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (list == NULL) {
|
||||
if (list == NULL || cur->isEof) {
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_EOF, reqId,
|
||||
"No More Files In Directory", "English");
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
/* if next state would cause an error then set EOF flag for when called
|
||||
* again */
|
||||
if (ret == WS_NEXT_ERROR) {
|
||||
cur->isEof = 1;
|
||||
}
|
||||
|
||||
data = (byte*)WMALLOC(outSz, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
|
@ -1161,7 +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;
|
||||
WDIR dir = NULL;
|
||||
WDIR* dir = NULL;
|
||||
|
||||
if (ssh == NULL || handle == NULL || handleSz != sizeof(word64)) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
@ -1172,7 +1194,7 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
/* find DIR given handle */
|
||||
while (cur != NULL) {
|
||||
if (cur->id == *((word64*)handle)) {
|
||||
dir = cur->dir;
|
||||
dir = &cur->dir;
|
||||
break;
|
||||
}
|
||||
cur = cur->next;
|
||||
|
@ -1188,7 +1210,8 @@ int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
|||
if (cur != NULL) {
|
||||
DIR_HANDLE* pre = dirList;
|
||||
|
||||
WLOG(WS_LOG_SFTP, "Free'ing and closing handle %ld pointer of [%p]", cur->id, cur);
|
||||
WLOG(WS_LOG_SFTP, "Free'ing and closing handle %ld pointer of [%p]",
|
||||
(long)cur->id, cur);
|
||||
/* case where node is at head of list */
|
||||
if (pre == cur) {
|
||||
dirList = cur->next;
|
||||
|
@ -1235,7 +1258,6 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
/* @TODO check for infinite loop */
|
||||
sz = 0;
|
||||
do {
|
||||
ret = wolfSSH_stream_read(ssh, data + sz, maxSz - sz);
|
||||
|
@ -1243,6 +1265,10 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
sz += ret;
|
||||
}
|
||||
} while (sz < maxSz && ret > 0);
|
||||
if (ret < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get file handle */
|
||||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
|
@ -1268,6 +1294,11 @@ int wolfSSH_SFTP_RecvWrite(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
ret = (int)WPWRITE(fd, data + idx, sz, ofst);
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (ret < 0) {
|
||||
#if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH)
|
||||
if (ret == NUF_NOSPC) {
|
||||
WLOG(WS_LOG_SFTP, "Ran out of memory");
|
||||
}
|
||||
#endif
|
||||
WLOG(WS_LOG_SFTP, "Error writing to file");
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_FAILURE, reqId,
|
||||
"Write File Error", "English");
|
||||
|
@ -1303,7 +1334,10 @@ int wolfSSH_SFTP_RecvRead(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
wolfSSH_stream_read(ssh, data, maxSz);
|
||||
if ((ret = wolfSSH_stream_read(ssh, data, maxSz)) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get file handle */
|
||||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
|
@ -1378,7 +1412,10 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
wolfSSH_stream_read(ssh, data, maxSz);
|
||||
if ((ret = wolfSSH_stream_read(ssh, data, maxSz)) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* get file handle */
|
||||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
|
@ -1398,6 +1435,12 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WMEMSET((byte*)&fd, 0, sizeof(WFD));
|
||||
WMEMCPY((byte*)&fd, data + idx, sz);
|
||||
ret = WCLOSE(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;
|
||||
|
@ -1446,9 +1489,6 @@ int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return ret;
|
||||
}
|
||||
else {
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
|
||||
/* get file name */
|
||||
ato32(data + idx, &sz); idx += UINT32_SZ;
|
||||
|
@ -1465,9 +1505,23 @@ int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
name[sz] = '\0';
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
if (WREMOVE(name) < 0) {
|
||||
clean_path(name);
|
||||
if ((ret = WREMOVE(name)) < 0) {
|
||||
WLOG(WS_LOG_SFTP, "Error removing file");
|
||||
ret = WS_FATAL_ERROR;
|
||||
#if defined(WOLFSSL_NUCLEUS) && defined(DEBUG_WOLFSSH)
|
||||
if (ret == NUF_ACCES)
|
||||
WLOG(WS_LOG_SFTP, "access error");
|
||||
if (ret == NUF_BAD_USER)
|
||||
WLOG(WS_LOG_SFTP, "bad user");
|
||||
if (ret == NUF_IO_ERROR)
|
||||
WLOG(WS_LOG_SFTP, "io error");
|
||||
if (ret == NUF_NOFILE)
|
||||
WLOG(WS_LOG_SFTP, "%s file not found", name);
|
||||
#endif
|
||||
ret = WS_BAD_FILE_E;
|
||||
}
|
||||
else {
|
||||
ret = WS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Let the client know the results from trying to remove the file */
|
||||
|
@ -1547,6 +1601,8 @@ int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
}
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
clean_path(old);
|
||||
clean_path(nw);
|
||||
if (ret == WS_SUCCESS && WRENAME(old, nw) < 0) {
|
||||
WLOG(WS_LOG_SFTP, "Error renaming file");
|
||||
ret = WS_BAD_FILE_E;
|
||||
|
@ -1568,6 +1624,233 @@ int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
}
|
||||
|
||||
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
/* some systems do not have a fstat function to allow for attribute lookup given
|
||||
* a file descriptor. In those cases we keep track of an internal list matching
|
||||
* handles to file names */
|
||||
|
||||
typedef struct WS_HANDLE_LIST {
|
||||
byte handle[WOLFSSH_MAX_HANDLE];
|
||||
word32 handleSz;
|
||||
char name[WOLFSSH_MAX_FILENAME];
|
||||
struct WS_HANDLE_LIST* next;
|
||||
struct WS_HANDLE_LIST* prev;
|
||||
} WS_HANDLE_LIST;
|
||||
static WS_HANDLE_LIST* handleList = NULL;
|
||||
|
||||
|
||||
/* get a handle node from the list
|
||||
* returns WS_HANDLE_LIST pointer on success and NULL on failure */
|
||||
static WS_HANDLE_LIST* SFTP_GetHandleNode(byte* handle, word32 handleSz)
|
||||
{
|
||||
WS_HANDLE_LIST* cur = handleList;
|
||||
|
||||
if (handle == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* for Nucleus need to find name from handle */
|
||||
while (cur != NULL) {
|
||||
if(handleSz == cur->handleSz && WMEMCMP(handle, cur->handle, handleSz) == 0) {
|
||||
break; /* found handle */
|
||||
}
|
||||
cur = cur->next;
|
||||
}
|
||||
|
||||
return cur;
|
||||
}
|
||||
|
||||
|
||||
/* add a name and handle to the handle list
|
||||
* return WS_SUCCESS on success */
|
||||
int SFTP_AddHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz, char* name)
|
||||
{
|
||||
WS_HANDLE_LIST* cur;
|
||||
int sz;
|
||||
|
||||
if (handle == NULL || name == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
cur = (WS_HANDLE_LIST*)WMALLOC(sizeof(WS_HANDLE_LIST), ssh->ctx->heap,
|
||||
DYNTYPE_SFTP);
|
||||
if (cur == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
WMEMCPY(cur->handle, handle, handleSz);
|
||||
cur->handleSz = handleSz;
|
||||
|
||||
sz = (int)WSTRLEN(name);
|
||||
if (sz + 1 >= WOLFSSH_MAX_FILENAME) {
|
||||
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
WMEMCPY(cur->name, name, sz);
|
||||
cur->name[sz] = '\0';
|
||||
|
||||
cur->prev = NULL;
|
||||
cur->next = handleList;
|
||||
if (handleList != NULL) {
|
||||
handleList->prev = cur;
|
||||
}
|
||||
handleList = cur;
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* remove a handle node from the list
|
||||
* returns WS_SUCCESS on success */
|
||||
int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz)
|
||||
{
|
||||
WS_HANDLE_LIST* cur;
|
||||
|
||||
if (ssh == NULL || handle == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
cur = SFTP_GetHandleNode(handle, handleSz);
|
||||
if (cur == NULL) {
|
||||
WLOG(WS_LOG_SFTP, "Fatal Error! Trying to remove a handle that was not in the list");
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
if (cur->next != NULL) {
|
||||
cur->next->prev = cur->prev;
|
||||
}
|
||||
|
||||
if (cur->prev != NULL) {
|
||||
cur->prev->next = cur->next;
|
||||
}
|
||||
|
||||
if (cur->next == NULL && cur->prev == NULL) {
|
||||
handleList = NULL;
|
||||
}
|
||||
|
||||
WFREE(cur, ssh->ctx->heap, DYNTYPE_SFTP);
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif /* WOLFSSH_STOREHANDLE */
|
||||
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
/* @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)
|
||||
{
|
||||
DSTAT stats;
|
||||
int sz = (int)WSTRLEN(fileName);
|
||||
int ret;
|
||||
|
||||
if (link) {
|
||||
ret = WLSTAT(fileName, &stats);
|
||||
}
|
||||
else {
|
||||
ret = WSTAT(fileName, &stats);
|
||||
}
|
||||
|
||||
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
if (sz > 2 && fileName[sz - 2] == ':' && ret == NUF_NOFILE) {
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
atr->per |= 0x4000;
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
if (ret != NU_SUCCESS) {
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
|
||||
atr->flags |= WOLFSSH_FILEATRB_SIZE;
|
||||
atr->sz = (word64)stats.fsize;
|
||||
|
||||
/* get additional attributes */
|
||||
{
|
||||
byte atrib = 0;
|
||||
if (NU_Get_Attributes(&atrib, fileName) == NU_SUCCESS) {
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if (atrib & ADIRENT) {
|
||||
atr->per |= 0x4000;
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
if (atrib & ANORMAL) {
|
||||
atr->per |= 0x755;
|
||||
}
|
||||
if (atrib & ARDONLY) {
|
||||
atr->per |= 0x444;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* @TODO handle attribute extensions */
|
||||
|
||||
NU_Done(&stats);
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* @TODO can be overriden by user for portability
|
||||
* Gets attributes based on file descriptor
|
||||
* 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_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
DSTAT stats;
|
||||
WS_HANDLE_LIST* cur;
|
||||
|
||||
if (handle == NULL || atr == NULL) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
cur = SFTP_GetHandleNode(handle, handleSz);
|
||||
if (cur == NULL) {
|
||||
WLOG(WS_LOG_SFTP, "Unknown handle");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
|
||||
if (WSTAT(cur->name, &stats) != NU_SUCCESS) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
|
||||
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
|
||||
atr->flags |= WOLFSSH_FILEATRB_SIZE;
|
||||
atr->sz = (word64)stats.fsize;
|
||||
|
||||
{
|
||||
byte atrib = 0;
|
||||
if (NU_Get_Attributes(&atrib, cur->name) == NU_SUCCESS) {
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if (atrib & ADIRENT) {
|
||||
atr->per |= 0x4000;
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
if (atrib & ANORMAL) {
|
||||
atr->per |= 0x755;
|
||||
}
|
||||
|
||||
if (atrib & ARDONLY) {
|
||||
atr->per |= 0x444;
|
||||
}
|
||||
}
|
||||
}
|
||||
/* @TODO handle attribute extensions */
|
||||
|
||||
NU_Done(&stats);
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#else
|
||||
|
||||
/* @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
|
||||
|
@ -1613,6 +1896,114 @@ int SFTP_GetAttributes(const char* fileName, WS_SFTP_FILEATRB* atr, byte link)
|
|||
}
|
||||
|
||||
|
||||
/* @TODO can be overriden by user for portability
|
||||
* Gets attributes based on file descriptor
|
||||
* 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_Handle(byte* handle, int handleSz, WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
struct stat stats;
|
||||
|
||||
if (handleSz != sizeof(word32)) {
|
||||
WLOG(WS_LOG_SFTP, "Unexpected handle size SFTP_GetAttributes_Handle()");
|
||||
}
|
||||
|
||||
if (fstat(*(int*)handle, &stats) != 0) {
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
|
||||
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
|
||||
atr->flags |= WOLFSSH_FILEATRB_SIZE;
|
||||
atr->sz = (word64)stats.st_size;
|
||||
|
||||
atr->flags |= WOLFSSH_FILEATRB_UIDGID;
|
||||
atr->uid = (word32)stats.st_uid;
|
||||
atr->gid = (word32)stats.st_gid;
|
||||
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
atr->per = (word32)stats.st_mode;
|
||||
|
||||
#if 0
|
||||
/* @TODO porting time from stat structure */
|
||||
atr->flags |= WOLFSSH_FILEATRB_TIME;
|
||||
atr->atime = (word32)stats.st_atimespec.tv_sec;
|
||||
atr->mtime = (word32)stats.st_mtimespec.tv_sec;
|
||||
#endif
|
||||
|
||||
/* @TODO handle attribute extensions */
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
/* Handles receiving fstat packet
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
||||
{
|
||||
WS_SFTP_FILEATRB atr;
|
||||
word32 handleSz;
|
||||
word32 sz;
|
||||
byte* data;
|
||||
byte* handle;
|
||||
word32 idx = 0;
|
||||
|
||||
if (ssh == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_FSTAT");
|
||||
|
||||
data = (byte*)WMALLOC(maxSz, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
wolfSSH_stream_read(ssh, data, maxSz);
|
||||
|
||||
ato32(data + idx, &handleSz); idx += UINT32_SZ;
|
||||
if (handleSz + idx > maxSz) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
handle = data + idx;
|
||||
|
||||
/* try to get file attributes and send back to client */
|
||||
WMEMSET((byte*)&atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
if (SFTP_GetAttributes_Handle(handle, handleSz, &atr) != WS_SUCCESS) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
WLOG(WS_LOG_SFTP, "Unable to get fstat of file/directory");
|
||||
wolfSSH_SFTP_SendStatus(ssh, WOLFSSH_FTP_FAILURE, reqId,
|
||||
"STAT error", "English");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
sz = SFTP_AtributesSz(ssh, &atr);
|
||||
data = (byte*)WMALLOC(sz + WOLFSSH_SFTP_HEADER, ssh->ctx->heap,
|
||||
DYNTYPE_BUFFER);
|
||||
if (data == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
if (SFTP_SetHeader(ssh, reqId, WOLFSSH_FTP_ATTRS, sz, data) != WS_SUCCESS) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
SFTP_SetAtributes(ssh, data + WOLFSSH_SFTP_HEADER, sz, &atr);
|
||||
if (wolfSSH_stream_send(ssh, data, sz + WOLFSSH_SFTP_HEADER) < 0) {
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
/* Handles receiving stat packet
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
|
@ -1654,6 +2045,7 @@ int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
||||
/* try to get file attributes and send back to client */
|
||||
clean_path(name);
|
||||
WMEMSET((byte*)&atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
if (SFTP_GetAttributes(name, &atr, 0) != WS_SUCCESS) {
|
||||
WFREE(name, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
|
@ -1729,6 +2121,7 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WMEMCPY(name, data + idx, sz);
|
||||
name[sz] = '\0';
|
||||
WFREE(data, ssh->ctx->heap, DYNTYPE_BUFFER);
|
||||
clean_path(name);
|
||||
|
||||
/* try to get file attributes and send back to client */
|
||||
WMEMSET((byte*)&atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
|
@ -1868,7 +2261,7 @@ int wolfSSH_SFTP_connect(WOLFSSH* ssh)
|
|||
return WS_FATAL_ERROR;
|
||||
}
|
||||
ssh->connectState = SFTP_RECV;
|
||||
FALL_THROUGH
|
||||
FALL_THROUGH /* no break */
|
||||
|
||||
case SFTP_RECV:
|
||||
if ((ssh->error = SFTP_ClientRecvInit(ssh)) != WS_SUCCESS) {
|
||||
|
@ -3263,7 +3656,11 @@ int wolfSSH_SFTP_SaveOfst(WOLFSSH* ssh, char* frm, char* to, word64 ofst)
|
|||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
/* @TODO sanity check before copy */
|
||||
if (frmSz > WOLFSSH_MAX_FILENAME || toSz > WOLFSSH_MAX_FILENAME) {
|
||||
WLOG(WS_LOG_SFTP, "File name is too large");
|
||||
return WS_BUFFER_E;
|
||||
}
|
||||
|
||||
current = &ssh->sftpOfst[idx];
|
||||
WMEMCPY(current->from, frm, frmSz);
|
||||
current->from[frmSz] = '\0';
|
||||
|
@ -3512,3 +3909,4 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
|||
return ret;
|
||||
}
|
||||
|
||||
#endif /* WOLFSSH_SFTP */
|
||||
|
|
|
@ -93,8 +93,9 @@ enum WS_ErrorCodes {
|
|||
WS_MATCH_MAC_ALGO_E = -53, /* cannot match MAC algo with peer */
|
||||
WS_PERMISSIONS = -54,
|
||||
WS_SFTP_COMPLETE = -55, /* SFTP connection established */
|
||||
WS_NEXT_ERROR = -56, /* Getting next value/state results in error */
|
||||
|
||||
WS_LAST_E = -55 /* Update this to indicate last error */
|
||||
WS_LAST_E = -56 /* Update this to indicate last error */
|
||||
};
|
||||
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
||||
|
|
205
wolfssh/port.h
205
wolfssh/port.h
|
@ -53,6 +53,43 @@ extern "C" {
|
|||
#endif
|
||||
|
||||
#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) ((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*);
|
||||
|
||||
|
@ -64,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) && \
|
||||
|
@ -76,7 +114,7 @@ extern "C" {
|
|||
#define WMKDIR(p,m) mkdir((p),(m))
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
/* setup string handling */
|
||||
#ifndef WSTRING_USER
|
||||
#include <string.h>
|
||||
|
@ -130,8 +168,150 @@ extern "C" {
|
|||
#define WLOCALTIME(c,r) (localtime_r((c),(r))!=NULL)
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSH_SFTP
|
||||
#ifndef NO_WOLFSSH_SERVER
|
||||
#if (defined(WOLFSSH_SFTP) || defined(WOLFSSH_SCP)) && \
|
||||
!defined(NO_WOLFSSH_SERVER)
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
#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 WFD int
|
||||
|
||||
#ifndef WGETCWD
|
||||
static inline char* wGetCwd(char* buf, unsigned int bufSz)
|
||||
{
|
||||
int ret;
|
||||
MNT_LIST_S* list = NU_NULL;
|
||||
|
||||
if (buf == NULL || bufSz < 3) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ret = NU_List_Mount(&list);
|
||||
if (ret != NU_SUCCESS) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
buf[0] = list->mnt_name[0];
|
||||
buf[1] = ':';
|
||||
buf[2] = '\0';
|
||||
|
||||
return buf;
|
||||
}
|
||||
#define WGETCWD(r,rSz) wGetCwd((r),(rSz))
|
||||
#endif
|
||||
|
||||
#ifndef WPWRITE
|
||||
static inline int wPwrite(WFD fd, unsigned char* buf, unsigned int sz, long ofst)
|
||||
{
|
||||
if (ofst > 0) {
|
||||
NU_Seek(fd, ofst, 0);
|
||||
}
|
||||
|
||||
return NU_Write(fd, (const CHAR*)buf, sz);
|
||||
}
|
||||
#define WPWRITE(fd,b,s,o) wPwrite((fd),(b),(s),(o))
|
||||
#endif
|
||||
|
||||
#ifndef WPREAD
|
||||
static inline int wPread(WFD fd, unsigned char* buf, unsigned int sz, long ofst)
|
||||
{
|
||||
if (ofst > 0) {
|
||||
NU_Seek(fd, ofst, 0);
|
||||
}
|
||||
|
||||
return NU_Read(fd, (CHAR*)buf, sz);
|
||||
}
|
||||
#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, const char* dir)
|
||||
{
|
||||
int ret;
|
||||
int idx = WSTRLEN(dir);
|
||||
char tmp[256]; /* default max file name size */
|
||||
|
||||
if (idx < 3) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
memcpy(tmp, dir, idx);
|
||||
if (tmp[idx - 1] == '.') {
|
||||
tmp[idx - 1] = '*';
|
||||
}
|
||||
else {
|
||||
/* if opening a directory then make sure pattern '/' '*' is used */
|
||||
unsigned char atrib = 0;
|
||||
if (NU_Get_Attributes(&atrib, dir) == NU_SUCCESS) {
|
||||
if (atrib & ADIRENT) {
|
||||
if (tmp[idx-1] != WS_DELIM) {
|
||||
if (idx + 2 > sizeof(tmp)) {
|
||||
/* not enough space */
|
||||
return -1;
|
||||
}
|
||||
tmp[idx++] = WS_DELIM;
|
||||
tmp[idx++] = '*';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (tmp[idx - 1] == WS_DELIM) {
|
||||
if (idx + 1 > sizeof(tmp)) {
|
||||
/* not enough space */
|
||||
return -1;
|
||||
}
|
||||
tmp[idx++] = '*';
|
||||
}
|
||||
tmp[idx] = '\0';
|
||||
ret = NU_Get_First(d, tmp);
|
||||
|
||||
/* if back to root directory i.e. A:/ then handle case
|
||||
* where file system has nothing in it. */
|
||||
if (dir[idx - 3] == ':' && ret == NUF_NOFILE) {
|
||||
memset(d, 0, sizeof(WDIR));
|
||||
ret = NU_SUCCESS;
|
||||
}
|
||||
|
||||
if (ret == NU_SUCCESS) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
#define WOPENDIR(c,d) wOpenDir((c),(d))
|
||||
#endif
|
||||
|
||||
#define WCLOSEDIR(d) NU_Done((d))
|
||||
#define WREADDIR(d) (NU_Get_Next((d)) == NU_SUCCESS)?(d):NULL
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
#else
|
||||
#include <unistd.h> /* used for rmdir */
|
||||
#include <sys/stat.h> /* used for mkdir, stat, and lstat */
|
||||
#include <stdio.h> /* used for remove and rename */
|
||||
|
@ -143,9 +323,18 @@ extern "C" {
|
|||
#define WREMOVE(d) remove((d))
|
||||
#define WRENAME(o,n) rename((o),(n))
|
||||
#define WGETCWD(r,rSz) getcwd((r),(rSz))
|
||||
#define WS_DELIM '/'
|
||||
|
||||
#include <fcntl.h> /* used for open, close, pwrite, and pread */
|
||||
#define WFD int
|
||||
#define WOLFSSH_O_RDWR O_RDWR
|
||||
#define WOLFSSH_O_RDONLY O_RDONLY
|
||||
#define WOLFSSH_O_WRONLY O_WRONLY
|
||||
#define WOLFSSH_O_APPEND O_APPEND
|
||||
#define WOLFSSH_O_CREAT O_CREAT
|
||||
#define WOLFSSH_O_TRUNC O_TRUNC
|
||||
#define WOLFSSH_O_EXCL O_EXCL
|
||||
|
||||
#define WOPEN(f,m,p) open((f),(m),(p))
|
||||
#define WCLOSE(fd) close((fd))
|
||||
#define WPWRITE(fd,b,s,o) pwrite((fd),(b),(s),(o))
|
||||
|
@ -154,12 +343,14 @@ extern "C" {
|
|||
#ifndef NO_WOLFSSL_DIR
|
||||
#include <dirent.h> /* used for opendir, readdir, and closedir */
|
||||
#define WDIR DIR*
|
||||
#define WOPENDIR(d) opendir((d))
|
||||
#define WCLOSEDIR(d) closedir((d))
|
||||
#define WREADDIR(d) readdir((d))
|
||||
|
||||
/* returns 0 on success */
|
||||
#define WOPENDIR(c,d) ((*(c) = opendir((d))) == NULL)
|
||||
#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
|
||||
|
|
|
@ -49,6 +49,11 @@ extern "C" {
|
|||
#define USE_WINDOWS_API
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
#ifndef WOLFSSH_STOREHANDLE
|
||||
#define WOLFSSH_STOREHANDLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
|
|
116
wolfssh/test.h
116
wolfssh/test.h
|
@ -33,6 +33,22 @@
|
|||
#endif
|
||||
#define socklen_t int
|
||||
#define NUM_SOCKETS 1
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#include "nucleus.h"
|
||||
#include "networking/nu_networking.h"
|
||||
#define SOCKET_T int
|
||||
#define socklen_t int
|
||||
#define NUM_SOCKETS 1
|
||||
#define INADDR_ANY IP_ADDR_ANY
|
||||
#define AF_INET NU_FAMILY_IP
|
||||
#define SOCK_STREAM NU_TYPE_STREAM
|
||||
|
||||
#define sin_addr id
|
||||
#define s_addr is_ip_addrs
|
||||
|
||||
#define sin_family family
|
||||
#define sin_port port
|
||||
|
||||
#else /* USE_WINDOWS_API */
|
||||
#include <unistd.h>
|
||||
#include <netdb.h>
|
||||
|
@ -88,6 +104,9 @@
|
|||
#define WCLOSESOCKET(s) closesocket((s))
|
||||
#endif
|
||||
#define WSTARTTCP()
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#define WCLOSESOCKET(s) NU_Close_Socket((s))
|
||||
#define WSTARTTCP()
|
||||
#else
|
||||
#define WCLOSESOCKET(s) close(s)
|
||||
#define WSTARTTCP()
|
||||
|
@ -105,6 +124,10 @@
|
|||
#define WOLFSSH_THREAD
|
||||
#define INFINITE -1
|
||||
#define WAIT_OBJECT_0 0L
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
typedef unsigned int THREAD_RETURN;
|
||||
typedef intptr_t THREAD_TYPE;
|
||||
#define WOLFSSH_THREAD
|
||||
#else
|
||||
typedef unsigned int THREAD_RETURN;
|
||||
typedef intptr_t THREAD_TYPE;
|
||||
|
@ -116,7 +139,9 @@
|
|||
typedef struct sockaddr_in6 SOCKADDR_IN_T;
|
||||
#define AF_INET_V AF_INET6
|
||||
#else
|
||||
typedef struct sockaddr_in SOCKADDR_IN_T;
|
||||
#ifndef WOLFSSL_NUCLEUS
|
||||
typedef struct sockaddr_in SOCKADDR_IN_T;
|
||||
#endif
|
||||
#define AF_INET_V AF_INET
|
||||
#endif
|
||||
|
||||
|
@ -179,8 +204,12 @@ void WaitTcpReady(func_args*);
|
|||
#else /* TEST_IPV6 */
|
||||
static const char* const wolfSshIp = "::1";
|
||||
#endif /* TEST_IPV6 */
|
||||
static const word16 wolfSshPort = 22222;
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
/* port 8080 was open with QEMU */
|
||||
static const word16 wolfSshPort = 8080;
|
||||
#else
|
||||
static const word16 wolfSshPort = 22222;
|
||||
#endif
|
||||
|
||||
#ifdef __GNUC__
|
||||
#define WS_NORETURN __attribute__((noreturn))
|
||||
|
@ -283,6 +312,43 @@ static INLINE int mygetopt(int argc, char** argv, const char* optstring)
|
|||
* - 4996: deprecated function */
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
static INLINE void build_addr(struct addr_struct* addr, const char* peer,
|
||||
word16 port)
|
||||
{
|
||||
int useLookup = 0;
|
||||
(void)useLookup;
|
||||
|
||||
memset(addr, 0, sizeof(struct addr_struct));
|
||||
|
||||
#ifndef TEST_IPV6
|
||||
/* peer could be in human readable form */
|
||||
if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) {
|
||||
|
||||
NU_HOSTENT* entry;
|
||||
NU_HOSTENT h;
|
||||
entry = &h;
|
||||
NU_Get_Host_By_Name((char*)peer, entry);
|
||||
|
||||
if (entry) {
|
||||
memcpy(&addr->id.is_ip_addrs, entry->h_addr_list[0],
|
||||
entry->h_length);
|
||||
useLookup = 1;
|
||||
}
|
||||
else
|
||||
err_sys("no entry for host");
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifndef TEST_IPV6
|
||||
addr->family = NU_FAMILY_IP;
|
||||
addr->port = port;
|
||||
|
||||
/* @TODO always setting any ip addr here */
|
||||
PUT32(addr->id.is_ip_addrs, 0, IP_ADDR_ANY);
|
||||
#endif
|
||||
}
|
||||
#else
|
||||
static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
|
||||
word16 port)
|
||||
{
|
||||
|
@ -299,13 +365,23 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
|
|||
struct hostent* entry = gethostbyname(peer, &err);
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
struct hostent* entry = gethostbyname((char*)peer);
|
||||
#else
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
NU_HOSTENT* entry;
|
||||
NU_HOSTENT h;
|
||||
entry = &h;
|
||||
NU_Get_Host_By_Name((char*)peer, entry);
|
||||
#else
|
||||
struct hostent* entry = gethostbyname(peer);
|
||||
#endif
|
||||
|
||||
if (entry) {
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
memcpy(&addr->id.is_ip_addrs, entry->h_addr_list[0],
|
||||
entry->h_length);
|
||||
#else
|
||||
memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0],
|
||||
entry->h_length);
|
||||
#endif
|
||||
useLookup = 1;
|
||||
}
|
||||
else
|
||||
|
@ -321,7 +397,11 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
|
|||
#endif
|
||||
addr->sin_port = htons(port);
|
||||
if ((size_t)peer == INADDR_ANY)
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
PUT32(addr->id.is_ip_addrs, 0, INADDR_ANY);
|
||||
#else
|
||||
addr->sin_addr.s_addr = INADDR_ANY;
|
||||
#endif
|
||||
else {
|
||||
if (!useLookup) {
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
|
@ -367,6 +447,7 @@ static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
|
|||
}
|
||||
#endif
|
||||
}
|
||||
#endif /* WOLFSSL_NUCLEUS */
|
||||
|
||||
#ifdef USE_WINDOWS_API
|
||||
#pragma warning(pop)
|
||||
|
@ -380,6 +461,8 @@ static INLINE void tcp_socket(SOCKET_T* sockFd)
|
|||
*sockFd = 0;
|
||||
#elif defined(MICROCHIP_TCPIP)
|
||||
*sockFd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
*sockFd = NU_Socket(NU_FAMILY_IP, NU_TYPE_STREAM, 0);
|
||||
#else
|
||||
*sockFd = socket(AF_INET_V, SOCK_STREAM, 0);
|
||||
#endif
|
||||
|
@ -405,6 +488,8 @@ static INLINE void tcp_socket(SOCKET_T* sockFd)
|
|||
/* nothing to define */
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY) && !defined(_FULL_SIGNAL_IMPLEMENTATION)
|
||||
/* not full signal implementation */
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
/* nothing to define */
|
||||
#else /* no S_NOSIGPIPE */
|
||||
signal(SIGPIPE, SIG_IGN);
|
||||
#endif /* S_NOSIGPIPE */
|
||||
|
@ -415,6 +500,7 @@ static INLINE void tcp_socket(SOCKET_T* sockFd)
|
|||
if (!TCPIP_TCP_OptionsSet(*sockFd, TCP_OPTION_NODELAY, (void*)1)) {
|
||||
err_sys("setsockopt TCP_NODELAY failed\n");
|
||||
}
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#else
|
||||
int on = 1;
|
||||
socklen_t len = sizeof(on);
|
||||
|
@ -439,15 +525,19 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr)
|
|||
*sockfd = TCPIP_TCP_ServerOpen(IP_ADDRESS_TYPE_IPV4, *port, 0);
|
||||
return;
|
||||
#else
|
||||
SOCKADDR_IN_T addr;
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
struct addr_struct addr;
|
||||
#else
|
||||
SOCKADDR_IN_T addr;
|
||||
#endif
|
||||
/* don't use INADDR_ANY by default, firewall may block, make user switch
|
||||
on */
|
||||
build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSshIp), *port);
|
||||
tcp_socket(sockfd);
|
||||
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
|
||||
&& !defined(WOLFSSL_KEIL_TCP_NET)
|
||||
&& !defined(WOLFSSL_KEIL_TCP_NET)\
|
||||
&& !defined(WOLFSSL_NUCLEUS)
|
||||
{
|
||||
int res;
|
||||
#ifdef MICROCHIP_TCPIP
|
||||
|
@ -462,11 +552,19 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef WOLFSSL_NUCLEUS
|
||||
if (NU_Bind(*sockfd, &addr, sizeof(addr)) <= 0)
|
||||
err_sys("tcp bind failed");
|
||||
if (NU_Listen(*sockfd, NUM_SOCKETS) != NU_SUCCESS)
|
||||
err_sys("tcp listen failed");
|
||||
#else
|
||||
if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
|
||||
err_sys("tcp bind failed");
|
||||
if (listen(*sockfd, NUM_SOCKETS) != 0)
|
||||
err_sys("tcp listen failed");
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS)
|
||||
#endif
|
||||
|
||||
#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) && !defined(WOLFSSL_NUCLEUS)
|
||||
if (*port == 0) {
|
||||
socklen_t len = sizeof(addr);
|
||||
if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
|
||||
|
@ -484,7 +582,7 @@ static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr)
|
|||
/* Wolf Root Directory Helper */
|
||||
/* KEIL-RL File System does not support relative directory */
|
||||
#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) \
|
||||
&& !defined(NO_WOLFSSL_DIR)
|
||||
&& !defined(NO_WOLFSSL_DIR) && !defined(WOLFSSL_NUCLEUS)
|
||||
/* Maximum depth to search for WolfSSL root */
|
||||
#define MAX_WOLF_ROOT_DEPTH 5
|
||||
|
||||
|
|
|
@ -24,6 +24,7 @@
|
|||
#define WOLFSSH_WOLFSCP_H
|
||||
|
||||
#include <wolfssh/settings.h>
|
||||
#include <wolfssh/ssh.h>
|
||||
#include <wolfssh/port.h>
|
||||
|
||||
#ifdef WOLFSSH_SCP
|
||||
|
@ -57,15 +58,20 @@ extern "C" {
|
|||
#include <errno.h>
|
||||
|
||||
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;
|
||||
|
||||
|
|
|
@ -26,6 +26,8 @@
|
|||
#include <wolfssl/options.h>
|
||||
#endif
|
||||
|
||||
#include <wolfssh/ssh.h>
|
||||
|
||||
/* Packet Types */
|
||||
enum WS_PacketTypes {
|
||||
WOLFSSH_FTP_INIT = 1,
|
||||
|
@ -107,6 +109,10 @@ enum {
|
|||
WOLFSSH_FXF_EXCL = 0x00000020
|
||||
};
|
||||
|
||||
#ifndef WS_DRIVE_SIZE
|
||||
#define WS_DRIVE_SIZE 1
|
||||
#endif
|
||||
|
||||
typedef struct WS_SFTP_FILEATRB_EX WS_SFTP_FILEATRB_EX;
|
||||
struct WS_SFTP_FILEATRB_EX {
|
||||
char* type;
|
||||
|
@ -118,7 +124,7 @@ struct WS_SFTP_FILEATRB_EX {
|
|||
|
||||
typedef struct WS_SFTP_FILEATRB {
|
||||
word32 flags;
|
||||
long sz;
|
||||
word64 sz;
|
||||
word32 uid; /* user ID */
|
||||
word32 gid; /* group ID */
|
||||
word32 per; /* permissions */
|
||||
|
@ -209,6 +215,7 @@ WOLFSSH_LOCAL int wolfSSH_SFTP_RecvRemove(WOLFSSH* ssh, int reqId, word32 maxSz)
|
|||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvRename(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvFSTAT(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
|
||||
#ifndef NO_WOLFSSL_DIR
|
||||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvOpenDir(WOLFSSH* ssh, int reqId, word32 maxSz);
|
||||
|
@ -216,3 +223,6 @@ WOLFSSH_LOCAL int wolfSSH_SFTP_RecvReadDir(WOLFSSH* ssh, int reqId, word32 maxSz
|
|||
WOLFSSH_LOCAL int wolfSSH_SFTP_RecvCloseDir(WOLFSSH* ssh, byte* handle,
|
||||
word32 handleSz);
|
||||
#endif /* NO_WOLFSSL_DIR */
|
||||
|
||||
WOLFSSL_LOCAL int SFTP_AddHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz, char* name);
|
||||
WOLFSSL_LOCAL int SFTP_RemoveHandleNode(WOLFSSH* ssh, byte* handle, word32 handleSz);
|
||||
|
|
Loading…
Reference in New Issue