mirror of https://github.com/wolfSSL/wolfssh.git
Merge pull request #790 from JacobBarthelmeh/pic32
microchip example and filesystem portpull/796/head
commit
d3bd96f210
|
@ -135,3 +135,6 @@ DLL Release
|
|||
/ide/Espressif/**/dependencies.lock
|
||||
|
||||
|
||||
/ide/mplabx/wolfssh.X/dist/
|
||||
/ide/mplabx/wolfssh.X/.generated_files
|
||||
/ide/mplabx/wolfssh.X/build
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
# All paths should be given relative to the root
|
||||
|
||||
include ide/winvs/include.am
|
||||
include ide/mplabx/include.am
|
||||
include ide/CSBENCH/include.am
|
||||
include ide/MQX/include.am
|
||||
include ide/IAR-EWARM/include.am
|
||||
|
|
|
@ -0,0 +1,54 @@
|
|||
# wolfSSH MPLABX
|
||||
|
||||
This is example project to create a wolfSSH library and example code for adding
|
||||
a wolfSSH echoserver to a MPLABX project.
|
||||
|
||||
Tested on a ATSAMV71Q21B with MPLABX version 6.20.
|
||||
|
||||
### Building wolfSSH library
|
||||
|
||||
The library project is located at ide/mplabx/wolfssh.X
|
||||
|
||||
- First open wolfssh.X with MPLABX IDE then click on "CM" content manager and
|
||||
import the ide/mplabx/wolfssh.X/mcc-manifest-generated-success.yml file.
|
||||
- Click apply.
|
||||
- Next click "MCC" and "generate".
|
||||
- To build from the command line, do the following after the XC32 toolchain has
|
||||
been installed.
|
||||
|
||||
```
|
||||
cd ide/mplabx/wolfssh.X
|
||||
make
|
||||
```
|
||||
|
||||
- To build using the IDE open the project ide/mplabx/wolfssh.X and click build.
|
||||
|
||||
|
||||
This will produce a wolfssh.X.a library in the directory
|
||||
ide/mplabx/wolfssh.X/dist/default/production/wolfssh.X.a
|
||||
|
||||
The application and wolfSSL must be built with the same user_settings.h as the
|
||||
wolfSSH library was built with! Differences in macro's defined for
|
||||
configuration will cause undefined behavior and potential crashes.
|
||||
|
||||
### Building an example app
|
||||
|
||||
1) Adjust the "Preprocessor macros" to include WOLFSSL_USER_SETTINGS and add an
|
||||
include path to ide/mplabx/user_settings.h.
|
||||
2) Remove the generated app.c from Source File
|
||||
3) Link to the wolfssh.X.a library. Properties->Libraries->Add Library/Object
|
||||
File...
|
||||
4) Right click on the project and add existing item. Select ide/mplabx/wolfssh.c
|
||||
5) Increase the heap size to 200,000 by right clicking on the project, selecting
|
||||
"Properties"->"x32-ld"
|
||||
|
||||
Notes:
|
||||
|
||||
For the current project this was tested with the heap and stack set to 200,000
|
||||
each. This was not trimed to see the minumum possible heap and stack usage yet.
|
||||
The TX buffer size used was set to 1024. The example was developed with wolfssh
|
||||
version 1.4.20.
|
||||
|
||||
After building and flashing the board a wolfSSH echoserver will be open on port
|
||||
22 which can be connected to by using the example client bundled with wolfSSH.
|
||||
```./examples/client/client -u jill -P upthehill -h 192.168.1.120 -p 22```
|
|
@ -0,0 +1,12 @@
|
|||
# vim:ft=automake
|
||||
# All paths should be given relative to the root
|
||||
|
||||
EXTRA_DIST+= ide/mplabx/README.md
|
||||
EXTRA_DIST+= ide/mplabx/user_settings.h
|
||||
EXTRA_DIST+= ide/mplabx/wolfssh.c
|
||||
|
||||
EXTRA_DIST+= wolfssh.X/Makefile
|
||||
EXTRA_DIST+= wolfssh.X/mcc-manifest-generated-success.yml
|
||||
EXTRA_DIST+= wolfssh.X/wolfssh.mc3
|
||||
EXTRA_DIST+= wolfssh.X/nbproject/configurations.xml
|
||||
EXTRA_DIST+= wolfssh.X/nbproject/project.xml
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef USER_SETTINGS_H
|
||||
#define USER_SETTINGS_H
|
||||
|
||||
/* include Microchip configuration first and then make additional changes */
|
||||
#include "configuration.h"
|
||||
|
||||
#include <stddef.h>
|
||||
|
||||
/* Turn on filesystem support for SFTP use */
|
||||
#undef NO_FILESYSTEM
|
||||
|
||||
/* wolfSSH configuration macros */
|
||||
#define WOLFSSL_WOLFSSH
|
||||
#ifndef NO_FILESYSTEM
|
||||
#define WOLFSSH_SFTP
|
||||
#endif
|
||||
#define DEFAULT_WINDOW_SZ 16384
|
||||
#define WOLFSSH_NO_HMAC_SHA2_512
|
||||
|
||||
/* do not use dirent with wolfSSL */
|
||||
#define NO_WOLFSSL_DIR
|
||||
|
||||
/* avoid the defualt settings in older wolfssl versions from
|
||||
* wolfssl/wolfcryt/settings.h */
|
||||
#undef MICROCHIP_PIC32
|
||||
|
||||
#undef TFM_TIMING_RESISTANT
|
||||
#define TFM_TIMING_RESISTANT
|
||||
|
||||
#undef ECC_TIMING_RESISTANT
|
||||
#define ECC_TIMING_RESISTANT
|
||||
|
||||
/* In older versions of wolfSSL (5.7.6 and older) the strcasecmp and strncasecmp
|
||||
* were dependent on the macro MICROCHIP_PIC32. Defining them here overrides
|
||||
* that. */
|
||||
#if (__XC32_VERSION >= 1000) && (__XC32_VERSION < 4000)
|
||||
#define XSTRCASECMP(s1,s2) strcasecmp((s1),(s2))
|
||||
#define XSTRNCASECMP(s1,s2,n) strncasecmp((s1),(s2),(n))
|
||||
#else
|
||||
#define XSTRCASECMP(s1,s2) strcmp((s1),(s2))
|
||||
#define XSTRNCASECMP(s1,s2,n) strncmp((s1),(s2),(n))
|
||||
#endif
|
||||
|
||||
/* allow signature wrapper api for wolfSSH use */
|
||||
#undef NO_SIG_WRAPPER
|
||||
|
||||
#endif
|
|
@ -0,0 +1,113 @@
|
|||
#
|
||||
# There exist several targets which are by default empty and which can be
|
||||
# used for execution of your targets. These targets are usually executed
|
||||
# before and after some main targets. They are:
|
||||
#
|
||||
# .build-pre: called before 'build' target
|
||||
# .build-post: called after 'build' target
|
||||
# .clean-pre: called before 'clean' target
|
||||
# .clean-post: called after 'clean' target
|
||||
# .clobber-pre: called before 'clobber' target
|
||||
# .clobber-post: called after 'clobber' target
|
||||
# .all-pre: called before 'all' target
|
||||
# .all-post: called after 'all' target
|
||||
# .help-pre: called before 'help' target
|
||||
# .help-post: called after 'help' target
|
||||
#
|
||||
# Targets beginning with '.' are not intended to be called on their own.
|
||||
#
|
||||
# Main targets can be executed directly, and they are:
|
||||
#
|
||||
# build build a specific configuration
|
||||
# clean remove built files from a configuration
|
||||
# clobber remove all built files
|
||||
# all build all configurations
|
||||
# help print help mesage
|
||||
#
|
||||
# Targets .build-impl, .clean-impl, .clobber-impl, .all-impl, and
|
||||
# .help-impl are implemented in nbproject/makefile-impl.mk.
|
||||
#
|
||||
# Available make variables:
|
||||
#
|
||||
# CND_BASEDIR base directory for relative paths
|
||||
# CND_DISTDIR default top distribution directory (build artifacts)
|
||||
# CND_BUILDDIR default top build directory (object files, ...)
|
||||
# CONF name of current configuration
|
||||
# CND_ARTIFACT_DIR_${CONF} directory of build artifact (current configuration)
|
||||
# CND_ARTIFACT_NAME_${CONF} name of build artifact (current configuration)
|
||||
# CND_ARTIFACT_PATH_${CONF} path to build artifact (current configuration)
|
||||
# CND_PACKAGE_DIR_${CONF} directory of package (current configuration)
|
||||
# CND_PACKAGE_NAME_${CONF} name of package (current configuration)
|
||||
# CND_PACKAGE_PATH_${CONF} path to package (current configuration)
|
||||
#
|
||||
# NOCDDL
|
||||
|
||||
|
||||
# Environment
|
||||
MKDIR=mkdir
|
||||
CP=cp
|
||||
CCADMIN=CCadmin
|
||||
RANLIB=ranlib
|
||||
|
||||
|
||||
# build
|
||||
build: .build-post
|
||||
|
||||
.build-pre:
|
||||
# Add your pre 'build' code here...
|
||||
|
||||
.build-post: .build-impl
|
||||
# Add your post 'build' code here...
|
||||
|
||||
|
||||
# clean
|
||||
clean: .clean-post
|
||||
|
||||
.clean-pre:
|
||||
# Add your pre 'clean' code here...
|
||||
# WARNING: the IDE does not call this target since it takes a long time to
|
||||
# simply run make. Instead, the IDE removes the configuration directories
|
||||
# under build and dist directly without calling make.
|
||||
# This target is left here so people can do a clean when running a clean
|
||||
# outside the IDE.
|
||||
|
||||
.clean-post: .clean-impl
|
||||
# Add your post 'clean' code here...
|
||||
|
||||
|
||||
# clobber
|
||||
clobber: .clobber-post
|
||||
|
||||
.clobber-pre:
|
||||
# Add your pre 'clobber' code here...
|
||||
|
||||
.clobber-post: .clobber-impl
|
||||
# Add your post 'clobber' code here...
|
||||
|
||||
|
||||
# all
|
||||
all: .all-post
|
||||
|
||||
.all-pre:
|
||||
# Add your pre 'all' code here...
|
||||
|
||||
.all-post: .all-impl
|
||||
# Add your post 'all' code here...
|
||||
|
||||
|
||||
# help
|
||||
help: .help-post
|
||||
|
||||
.help-pre:
|
||||
# Add your pre 'help' code here...
|
||||
|
||||
.help-post: .help-impl
|
||||
# Add your post 'help' code here...
|
||||
|
||||
|
||||
|
||||
# include project implementation makefile
|
||||
include nbproject/Makefile-impl.mk
|
||||
|
||||
# include project make variables
|
||||
include nbproject/Makefile-variables.mk
|
|
@ -0,0 +1,29 @@
|
|||
# This file has been autogenerated by MPLAB Code Configurator. Please do not edit this file.
|
||||
|
||||
manifest_file_version: 1.0.0
|
||||
project: wolfssh
|
||||
creation_date: 2025-04-02T16:56:35.669-06:00[America/Denver]
|
||||
operating_system: Mac OS X
|
||||
mcc_mode: IDE
|
||||
mcc_mode_version: v6.20
|
||||
device_name: ATSAMV71Q21B
|
||||
compiler: XC32 4.35
|
||||
mcc_version: 5.5.0
|
||||
mcc_core_version: 5.7.0
|
||||
content_manager_version: 5.0.1
|
||||
is_mcc_offline: false
|
||||
is_using_prerelease_versions: false
|
||||
mcc_content_registries: https://registry.npmjs.org/
|
||||
device_library: {library_class: com.microchip.mcc.harmony.Harmony3Library, name: Harmony
|
||||
V3, version: 1.5.5}
|
||||
packs: {name: SAMV71_DFP, version: 4.12.237}
|
||||
modules:
|
||||
- {name: core, type: HARMONY, version: v3.13.1}
|
||||
- {name: csp, type: HARMONY, version: v3.18.0}
|
||||
- {name: filex, type: HARMONY, version: v6.2.1_rel}
|
||||
- {name: CMSIS_5, type: HARMONY, version: 5.9.0}
|
||||
- {name: littlefs, type: HARMONY, version: v2.10.1}
|
||||
- {name: wolfssl, type: HARMONY, version: v5.4.0}
|
||||
- {name: net, type: HARMONY, version: v3.11.0}
|
||||
- {name: crypto, type: HARMONY, version: v3.8.1}
|
||||
- {name: CMSIS-FreeRTOS, type: HARMONY, version: v10.5.1}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,27 @@
|
|||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project xmlns="http://www.netbeans.org/ns/project/1">
|
||||
<type>com.microchip.mplab.nbide.embedded.makeproject</type>
|
||||
<configuration>
|
||||
<data xmlns="http://www.netbeans.org/ns/make-project/1">
|
||||
<name>wolfssh</name>
|
||||
<creation-uuid>92aa1711-a46a-4125-9aea-fd01c492463b</creation-uuid>
|
||||
<make-project-type>0</make-project-type>
|
||||
<sourceEncoding>ISO-8859-1</sourceEncoding>
|
||||
<make-dep-projects/>
|
||||
<sourceRootList>
|
||||
<sourceRootElem>../../../src</sourceRootElem>
|
||||
<sourceRootElem>..</sourceRootElem>
|
||||
<sourceRootElem>../../../wolfssh</sourceRootElem>
|
||||
</sourceRootList>
|
||||
<confList>
|
||||
<confElem>
|
||||
<name>default</name>
|
||||
<type>3</type>
|
||||
</confElem>
|
||||
</confList>
|
||||
<formatting>
|
||||
<project-formatting-style>false</project-formatting-style>
|
||||
</formatting>
|
||||
</data>
|
||||
</configuration>
|
||||
</project>
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,951 @@
|
|||
/* wolfssh.c
|
||||
*
|
||||
* Copyright (C) 2014-2025 wolfSSL Inc.
|
||||
*
|
||||
* This file is part of wolfSSH.
|
||||
*
|
||||
* wolfSSH is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* wolfSSH is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with wolfSSH. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
/* Uses portions of code from the wolfssh/examples/echoserver.c example */
|
||||
|
||||
#include "app.h"
|
||||
#include "definitions.h"
|
||||
#include "tcpip/tcpip.h"
|
||||
|
||||
#include "system/fs/sys_fs.h"
|
||||
#include "system/fs/sys_fs_media_manager.h"
|
||||
|
||||
#include <wolfssh/ssh.h>
|
||||
#include <wolfssh/wolfsftp.h>
|
||||
#include <wolfssh/test.h>
|
||||
#include <wolfssh/log.h>
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
#define NO_FILESYSTEM
|
||||
#include <wolfssh/certs_test.h>
|
||||
#undef NO_FILESYSTEM
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
|
||||
#include <wolfssl/wolfcrypt/sha256.h>
|
||||
#include <wolfssl/wolfcrypt/coding.h>
|
||||
|
||||
#define SERVER_PORT 22
|
||||
|
||||
typedef enum
|
||||
{
|
||||
APP_SSH_TCPIP_WAIT_INIT,
|
||||
APP_SSH_TCPIP_WAIT_FOR_IP,
|
||||
APP_SSH_CTX_INIT,
|
||||
APP_SSH_MOUNT_FILESYSTEM,
|
||||
APP_SSH_FORMAT_DISK,
|
||||
APP_SSH_FORMAT_CHECK,
|
||||
APP_SSH_USERAUTH_INIT,
|
||||
APP_SSH_LOADKEY,
|
||||
APP_SSH_CREATE_SOCKET,
|
||||
APP_SSH_LISTEN,
|
||||
APP_SSH_CLEANUP,
|
||||
APP_SSH_SFTP_START,
|
||||
APP_SSH_SFTP,
|
||||
APP_SSH_ECHO,
|
||||
APP_SSH_ACCEPT,
|
||||
APP_SSH_ERROR
|
||||
} APP_SSH_STATES;
|
||||
|
||||
|
||||
typedef struct APP_SSH_DATA
|
||||
{
|
||||
APP_SSH_STATES state;
|
||||
TCP_SOCKET socket;
|
||||
} APP_SSH_DATA;
|
||||
|
||||
|
||||
APP_SSH_DATA appData;
|
||||
static WOLFSSH_CTX* ctx;
|
||||
static WOLFSSH* ssh;
|
||||
|
||||
#ifndef EXAMPLE_HIGHWATER_MARK
|
||||
#define EXAMPLE_HIGHWATER_MARK 0x3FFF8000 /* 1GB - 32kB */
|
||||
#endif
|
||||
#ifndef EXAMPLE_BUFFER_SZ
|
||||
#define EXAMPLE_BUFFER_SZ 4096
|
||||
#endif
|
||||
#define SCRATCH_BUFFER_SZ 1200
|
||||
|
||||
static INLINE void c32toa(word32 u32, byte* c)
|
||||
{
|
||||
c[0] = (u32 >> 24) & 0xff;
|
||||
c[1] = (u32 >> 16) & 0xff;
|
||||
c[2] = (u32 >> 8) & 0xff;
|
||||
c[3] = u32 & 0xff;
|
||||
}
|
||||
|
||||
/* Map user names to passwords */
|
||||
/* Use arrays for username and p. The password or public key can
|
||||
* be hashed and the hash stored here. Then I won't need the type. */
|
||||
typedef struct PwMap {
|
||||
byte type;
|
||||
byte username[32];
|
||||
word32 usernameSz;
|
||||
byte p[SHA256_DIGEST_SIZE];
|
||||
struct PwMap* next;
|
||||
} PwMap;
|
||||
|
||||
typedef struct PwMapList {
|
||||
PwMap* head;
|
||||
} PwMapList;
|
||||
PwMapList pwMapList;
|
||||
|
||||
static const char echoserverBanner[] = "wolfSSH Example Echo Server\n";
|
||||
|
||||
|
||||
/* These are example user:password strings. To update for an admin user
|
||||
* a string could be added to the list with something like "admin:admin123\n"
|
||||
*/
|
||||
static const char samplePasswordBuffer[] =
|
||||
"jill:upthehill\n"
|
||||
"jack:fetchapail\n";
|
||||
|
||||
|
||||
/* These are example public key authentication options. */
|
||||
static const char samplePublicKeyEccBuffer[] =
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA"
|
||||
"BBBNkI5JTP6D0lF42tbxX19cE87hztUS6FSDoGvPfiU0CgeNSbI+aFdKIzTP5CQEJSvm25"
|
||||
"qUzgDtH7oyaQROUnNvk= hansel\n"
|
||||
"ecdsa-sha2-nistp256 AAAAE2VjZHNhLXNoYTItbmlzdHAyNTYAAAAIbmlzdHAyNTYAAA"
|
||||
"BBBKAtH8cqaDbtJFjtviLobHBmjCtG56DMkP6A4M2H9zX2/YCg1h9bYS7WHd9UQDwXO1Hh"
|
||||
"IZzRYecXh7SG9P4GhRY= gretel\n";
|
||||
|
||||
|
||||
static const char samplePublicKeyRsaBuffer[] =
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQC9P3ZFowOsONXHD5MwWiCciXytBRZGho"
|
||||
"MNiisWSgUs5HdHcACuHYPi2W6Z1PBFmBWT9odOrGRjoZXJfDDoPi+j8SSfDGsc/hsCmc3G"
|
||||
"p2yEhUZUEkDhtOXyqjns1ickC9Gh4u80aSVtwHRnJZh9xPhSq5tLOhId4eP61s+a5pwjTj"
|
||||
"nEhBaIPUJO2C/M0pFnnbZxKgJlX7t1Doy7h5eXxviymOIvaCZKU+x5OopfzM/wFkey0EPW"
|
||||
"NmzI5y/+pzU5afsdeEWdiQDIQc80H6Pz8fsoFPvYSG+s4/wz0duu7yeeV1Ypoho65Zr+pE"
|
||||
"nIf7dO0B8EblgWt+ud+JI8wrAhfE4x hansel\n"
|
||||
"ssh-rsa AAAAB3NzaC1yc2EAAAADAQABAAABAQCqDwRVTRVk/wjPhoo66+Mztrc31KsxDZ"
|
||||
"+kAV0139PHQ+wsueNpba6jNn5o6mUTEOrxrz0LMsDJOBM7CmG0983kF4gRIihECpQ0rcjO"
|
||||
"P6BSfbVTE9mfIK5IsUiZGd8SoE9kSV2pJ2FvZeBQENoAxEFk0zZL9tchPS+OCUGbK4SDjz"
|
||||
"uNZl/30Mczs73N3MBzi6J1oPo7sFlqzB6ecBjK2Kpjus4Y1rYFphJnUxtKvB0s+hoaadru"
|
||||
"biE57dK6BrH5iZwVLTQKux31uCJLPhiktI3iLbdlGZEctJkTasfVSsUizwVIyRjhVKmbdI"
|
||||
"RGwkU38D043AR1h0mUoGCPIKuqcFMf gretel\n";
|
||||
|
||||
|
||||
static int wsUserAuth(byte authType,
|
||||
WS_UserAuthData* authData,
|
||||
void* ctx)
|
||||
{
|
||||
PwMapList* list;
|
||||
PwMap* map;
|
||||
byte authHash[SHA256_DIGEST_SIZE];
|
||||
|
||||
if (ctx == NULL) {
|
||||
SYS_CONSOLE_MESSAGE("wsUserAuth: ctx not set");
|
||||
return WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
|
||||
if (authType != WOLFSSH_USERAUTH_PASSWORD &&
|
||||
authType != WOLFSSH_USERAUTH_PUBLICKEY) {
|
||||
|
||||
return WOLFSSH_USERAUTH_FAILURE;
|
||||
}
|
||||
|
||||
/* Hash the password or public key with its length. */
|
||||
{
|
||||
wc_Sha256 sha;
|
||||
byte flatSz[4];
|
||||
wc_InitSha256(&sha);
|
||||
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
|
||||
c32toa(authData->sf.password.passwordSz, flatSz);
|
||||
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
|
||||
wc_Sha256Update(&sha,
|
||||
authData->sf.password.password,
|
||||
authData->sf.password.passwordSz);
|
||||
}
|
||||
else if (authType == WOLFSSH_USERAUTH_PUBLICKEY) {
|
||||
c32toa(authData->sf.publicKey.publicKeySz, flatSz);
|
||||
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
|
||||
wc_Sha256Update(&sha,
|
||||
authData->sf.publicKey.publicKey,
|
||||
authData->sf.publicKey.publicKeySz);
|
||||
}
|
||||
wc_Sha256Final(&sha, authHash);
|
||||
}
|
||||
|
||||
list = (PwMapList*)ctx;
|
||||
map = list->head;
|
||||
|
||||
while (map != NULL) {
|
||||
if (authData->usernameSz == map->usernameSz &&
|
||||
memcmp(authData->username, map->username, map->usernameSz) == 0) {
|
||||
|
||||
if (authData->type == map->type) {
|
||||
if (memcmp(map->p, authHash, SHA256_DIGEST_SIZE) == 0) {
|
||||
return WOLFSSH_USERAUTH_SUCCESS;
|
||||
}
|
||||
else {
|
||||
return (authType == WOLFSSH_USERAUTH_PASSWORD ?
|
||||
WOLFSSH_USERAUTH_INVALID_PASSWORD :
|
||||
WOLFSSH_USERAUTH_INVALID_PUBLICKEY);
|
||||
}
|
||||
}
|
||||
else {
|
||||
return WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
|
||||
}
|
||||
}
|
||||
map = map->next;
|
||||
}
|
||||
|
||||
return WOLFSSH_USERAUTH_INVALID_USER;
|
||||
}
|
||||
|
||||
|
||||
static void PwMapListDelete(PwMapList* list)
|
||||
{
|
||||
if (list != NULL) {
|
||||
PwMap* head = list->head;
|
||||
|
||||
while (head != NULL) {
|
||||
PwMap* cur = head;
|
||||
head = head->next;
|
||||
memset(cur, 0, sizeof(PwMap));
|
||||
free(cur);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static PwMap* PwMapNew(PwMapList* list, byte type, const byte* username,
|
||||
word32 usernameSz, const byte* p, word32 pSz)
|
||||
{
|
||||
PwMap* map;
|
||||
|
||||
map = (PwMap*)malloc(sizeof(PwMap));
|
||||
if (map != NULL) {
|
||||
Sha256 sha;
|
||||
byte flatSz[4];
|
||||
|
||||
map->type = type;
|
||||
if (usernameSz >= sizeof(map->username))
|
||||
usernameSz = sizeof(map->username) - 1;
|
||||
memcpy(map->username, username, usernameSz + 1);
|
||||
map->username[usernameSz] = 0;
|
||||
map->usernameSz = usernameSz;
|
||||
|
||||
wc_InitSha256(&sha);
|
||||
c32toa(pSz, flatSz);
|
||||
wc_Sha256Update(&sha, flatSz, sizeof(flatSz));
|
||||
wc_Sha256Update(&sha, p, pSz);
|
||||
wc_Sha256Final(&sha, map->p);
|
||||
|
||||
map->next = list->head;
|
||||
list->head = map;
|
||||
}
|
||||
|
||||
return map;
|
||||
}
|
||||
|
||||
|
||||
static int LoadPublicKeyBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
||||
{
|
||||
char* str = (char*)buf;
|
||||
char* delimiter;
|
||||
byte* publicKey64;
|
||||
word32 publicKey64Sz;
|
||||
byte* username;
|
||||
word32 usernameSz;
|
||||
byte publicKey[300];
|
||||
word32 publicKeySz;
|
||||
|
||||
/* Each line of passwd.txt is in the format
|
||||
* ssh-rsa AAAB3BASE64ENCODEDPUBLICKEYBLOB username\n
|
||||
* This function modifies the passed-in buffer. */
|
||||
if (list == NULL)
|
||||
return -1;
|
||||
|
||||
if (buf == NULL || bufSz == 0)
|
||||
return 0;
|
||||
|
||||
while (*str != 0) {
|
||||
/* Skip the public key type. This example will always be ssh-rsa. */
|
||||
delimiter = strchr(str, ' ');
|
||||
str = delimiter + 1;
|
||||
delimiter = strchr(str, ' ');
|
||||
publicKey64 = (byte*)str;
|
||||
*delimiter = 0;
|
||||
publicKey64Sz = (word32)(delimiter - str);
|
||||
str = delimiter + 1;
|
||||
delimiter = strchr(str, '\n');
|
||||
username = (byte*)str;
|
||||
*delimiter = 0;
|
||||
usernameSz = (word32)(delimiter - str);
|
||||
str = delimiter + 1;
|
||||
publicKeySz = sizeof(publicKey);
|
||||
|
||||
if (Base64_Decode(publicKey64, publicKey64Sz,
|
||||
publicKey, &publicKeySz) != 0) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (PwMapNew(list, WOLFSSH_USERAUTH_PUBLICKEY,
|
||||
username, usernameSz,
|
||||
publicKey, publicKeySz) == NULL ) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int LoadPasswordBuffer(byte* buf, word32 bufSz, PwMapList* list)
|
||||
{
|
||||
char* str = (char*)buf;
|
||||
char* delimiter;
|
||||
char* username;
|
||||
char* password;
|
||||
|
||||
/* Each line of passwd.txt is in the format
|
||||
* username:password\n
|
||||
* This function modifies the passed-in buffer. */
|
||||
|
||||
if (list == NULL)
|
||||
return -1;
|
||||
|
||||
if (buf == NULL || bufSz == 0)
|
||||
return 0;
|
||||
|
||||
while (*str != 0) {
|
||||
delimiter = strchr(str, ':');
|
||||
username = str;
|
||||
*delimiter = 0;
|
||||
password = delimiter + 1;
|
||||
str = strchr(password, '\n');
|
||||
*str = 0;
|
||||
str++;
|
||||
if (PwMapNew(list, WOLFSSH_USERAUTH_PASSWORD,
|
||||
(byte*)username, (word32)strlen(username),
|
||||
(byte*)password, (word32)strlen(password)) == NULL ) {
|
||||
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* returns buffer size on success */
|
||||
static int load_key(byte isEcc, byte* buf, word32 bufSz)
|
||||
{
|
||||
word32 sz = 0;
|
||||
|
||||
if (isEcc) {
|
||||
if (sizeof_ecc_key_der_256 > bufSz) {
|
||||
return 0;
|
||||
}
|
||||
WMEMCPY(buf, ecc_key_der_256, sizeof_ecc_key_der_256);
|
||||
sz = sizeof_ecc_key_der_256;
|
||||
}
|
||||
else {
|
||||
if (sizeof_rsa_key_der_2048 > bufSz) {
|
||||
return 0;
|
||||
}
|
||||
WMEMCPY(buf, (byte*)rsa_key_der_2048, sizeof_rsa_key_der_2048);
|
||||
sz = sizeof_rsa_key_der_2048;
|
||||
}
|
||||
|
||||
return sz;
|
||||
}
|
||||
|
||||
|
||||
static byte find_char(const byte* str, const byte* buf, word32 bufSz)
|
||||
{
|
||||
const byte* cur;
|
||||
|
||||
while (bufSz) {
|
||||
cur = str;
|
||||
while (*cur != '\0') {
|
||||
if (*cur == *buf)
|
||||
return *cur;
|
||||
cur++;
|
||||
}
|
||||
buf++;
|
||||
bufSz--;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#if 0
|
||||
/* redirection of logging message to SYS_CONSOLE_PRINT instead of printf */
|
||||
static void logCb(enum wolfSSH_LogLevel lvl, const char *const msg)
|
||||
{
|
||||
if ( wolfSSH_LogEnabled()
|
||||
#if 1 /* optionally filter out just the SFTP logs */
|
||||
&& lvl == WS_LOG_SFTP
|
||||
#endif
|
||||
) {
|
||||
SYS_CONSOLE_PRINT(msg);
|
||||
SYS_CONSOLE_PRINT("\r\n");
|
||||
SYS_CONSOLE_Flush(SYS_CONSOLE_DEFAULT_INSTANCE);
|
||||
SYS_CONSOLE_Tasks(sysObj.sysConsole0);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
void APP_Initialize ( void )
|
||||
{
|
||||
appData.state = APP_SSH_CTX_INIT;
|
||||
wolfSSH_Init();
|
||||
#if 0
|
||||
/* Used to enable debug messages and set logging callback */
|
||||
SYS_CONSOLE_PRINT("Turning on wolfSSH debugging\n\r");
|
||||
wolfSSH_Debugging_ON();
|
||||
wolfSSH_SetLoggingCb(logCb);
|
||||
#endif
|
||||
}
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
|
||||
#define APP_MOUNT_NAME "/mnt/myDrive1/"
|
||||
#define APP_DEVICE_NAME "/dev/nvma1"
|
||||
#ifdef SYS_FS_LFS_MAX_SS
|
||||
#define APP_FS_TYPE LITTLEFS
|
||||
#elif defined(SYS_FS_FAT_MAX_SS)
|
||||
#define APP_FS_TYPE FAT
|
||||
#else
|
||||
#error untested file system setup
|
||||
#endif
|
||||
|
||||
static void CreateTestFile(void)
|
||||
{
|
||||
SYS_FS_RESULT result;
|
||||
SYS_FS_HANDLE fileHandle;
|
||||
char testData[] = "Test Data";
|
||||
SYS_FS_ERROR fsError;
|
||||
|
||||
/* Try to create and write to a test file */
|
||||
fileHandle = SYS_FS_FileOpen("test.txt", (SYS_FS_FILE_OPEN_WRITE));
|
||||
if (fileHandle == SYS_FS_HANDLE_INVALID) {
|
||||
fsError = SYS_FS_Error();
|
||||
SYS_CONSOLE_PRINT("File open failed! Error: %d\r\n", fsError);
|
||||
return;
|
||||
}
|
||||
|
||||
result = SYS_FS_FileWrite(fileHandle, testData, strlen(testData));
|
||||
if(result == -1) {
|
||||
fsError = SYS_FS_Error();
|
||||
SYS_CONSOLE_PRINT("File write failed! Error: %d\r\n", fsError);
|
||||
SYS_FS_FileClose(fileHandle);
|
||||
return;
|
||||
}
|
||||
|
||||
SYS_FS_FileClose(fileHandle);
|
||||
SYS_CONSOLE_PRINT("\tCreated test.txt file example successful!\r\n");
|
||||
}
|
||||
|
||||
|
||||
static int CheckDriveStatus(void)
|
||||
{
|
||||
char cwdBuf[256];
|
||||
int ret = 0;
|
||||
|
||||
SYS_CONSOLE_PRINT("\r\nChecking drive status:\r\n");
|
||||
|
||||
/* Try to get current drive */
|
||||
memset(cwdBuf, 0, sizeof(cwdBuf));
|
||||
if (SYS_FS_CurrentDriveGet(cwdBuf) == SYS_FS_RES_SUCCESS) {
|
||||
SYS_CONSOLE_PRINT("\tCurrent drive: %s\r\n", cwdBuf);
|
||||
}
|
||||
else {
|
||||
SYS_CONSOLE_PRINT("\tFailed to get current drive: %d\r\n",
|
||||
SYS_FS_Error());
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
/* Try to get current directory */
|
||||
memset(cwdBuf, 0, sizeof(cwdBuf));
|
||||
if (SYS_FS_CurrentWorkingDirectoryGet(cwdBuf, sizeof(cwdBuf)) ==
|
||||
SYS_FS_RES_SUCCESS) {
|
||||
SYS_CONSOLE_PRINT("\tCurrent directory: %s\r\n", cwdBuf);
|
||||
}
|
||||
else {
|
||||
SYS_CONSOLE_PRINT("\tFailed to get current directory: %d\r\n",
|
||||
SYS_FS_Error());
|
||||
ret = -1;
|
||||
}
|
||||
CreateTestFile();
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* returns 0 on success, 1 for try again, and negative value on failure */
|
||||
static int TryMount(void)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
/* Try mounting */
|
||||
if (SYS_FS_Mount(APP_DEVICE_NAME, APP_MOUNT_NAME, APP_FS_TYPE, 0, NULL) ==
|
||||
SYS_FS_RES_SUCCESS) {
|
||||
SYS_CONSOLE_PRINT("Filesystem mounted\r\n");
|
||||
}
|
||||
else {
|
||||
int err = (int)SYS_FS_Error();
|
||||
|
||||
if (err == SYS_FS_ERROR_NOT_READY) {
|
||||
ret = 1;
|
||||
}
|
||||
else {
|
||||
SYS_CONSOLE_PRINT("Mount failed: %d\r\n", err);
|
||||
ret = -1;
|
||||
}
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
|
||||
/* Debugging heap and stack available */
|
||||
#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && \
|
||||
INCLUDE_uxTaskGetStackHighWaterMark == 1
|
||||
static int currentStack = 0;
|
||||
static int savedStack = 0;
|
||||
static int minHeap = 600000;
|
||||
#endif
|
||||
|
||||
void APP_Tasks ( void )
|
||||
{
|
||||
int useEcc = 0, numNetworks = 0, ret, error;
|
||||
unsigned char peek_buf[1];
|
||||
|
||||
switch(appData.state)
|
||||
{
|
||||
case APP_SSH_CTX_INIT:
|
||||
ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL);
|
||||
if (ctx == NULL) {
|
||||
SYS_CONSOLE_PRINT("Couldn't allocate SSH CTX data.\r\n");
|
||||
appData.state = APP_SSH_ERROR;
|
||||
}
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
SYS_CONSOLE_PRINT("Attempting filesystem mount...\r\n");
|
||||
appData.state = APP_SSH_MOUNT_FILESYSTEM;
|
||||
#else
|
||||
appData.state = APP_SSH_USERAUTH_INIT;
|
||||
#endif
|
||||
break;
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
case APP_SSH_MOUNT_FILESYSTEM:
|
||||
ret = TryMount();
|
||||
switch (ret) {
|
||||
case 0:
|
||||
appData.state = APP_SSH_FORMAT_DISK;
|
||||
break;
|
||||
|
||||
case 1: /* try again */
|
||||
break;
|
||||
|
||||
case -1: /* failed */
|
||||
SYS_CONSOLE_PRINT("Mounting file system failed\r\n");
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_SSH_FORMAT_DISK:
|
||||
{
|
||||
SYS_FS_FORMAT_PARAM opt;
|
||||
|
||||
#if defined(SYS_FS_LFS_MAX_SS)
|
||||
/* Work buffer used by FAT FS during Format */
|
||||
uint8_t CACHE_ALIGN work[SYS_FS_LFS_MAX_SS];
|
||||
#elif defined(SYS_FS_FAT_MAX_SS)
|
||||
/* Work buffer used by FAT FS during Format */
|
||||
uint8_t CACHE_ALIGN work[SYS_FS_FAT_MAX_SS];
|
||||
#endif
|
||||
|
||||
opt.fmt = APP_FS_TYPE;
|
||||
opt.au_size = 0;
|
||||
|
||||
#if defined(SYS_FS_LFS_MAX_SS)
|
||||
if (SYS_FS_DriveFormat (APP_MOUNT_NAME, &opt, (void *)work,
|
||||
SYS_FS_LFS_MAX_SS) != SYS_FS_RES_SUCCESS)
|
||||
#elif defined(SYS_FS_FAT_MAX_SS)
|
||||
if (SYS_FS_DriveFormat (APP_MOUNT_NAME, &opt, (void *)work,
|
||||
SYS_FS_FAT_MAX_SS) != SYS_FS_RES_SUCCESS)
|
||||
#endif
|
||||
{
|
||||
|
||||
/* Fatal error with failing to format the file system */
|
||||
SYS_CONSOLE_PRINT("Failed to format file system\r\n");
|
||||
vTaskDelay(500);
|
||||
|
||||
/* continue on to wolfSSH which still could host echo server */
|
||||
appData.state = APP_SSH_USERAUTH_INIT;
|
||||
}
|
||||
else {
|
||||
SYS_CONSOLE_PRINT("Formated file system\r\n");
|
||||
appData.state = APP_SSH_FORMAT_CHECK;
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_SSH_FORMAT_CHECK:
|
||||
if (CheckDriveStatus() == 0) {
|
||||
appData.state = APP_SSH_USERAUTH_INIT;
|
||||
}
|
||||
break;
|
||||
#endif /* !NO_FILESYSTEM */
|
||||
|
||||
case APP_SSH_USERAUTH_INIT:
|
||||
wolfSSH_SetUserAuth(ctx, wsUserAuth);
|
||||
wolfSSH_CTX_SetBanner(ctx, echoserverBanner);
|
||||
appData.state = APP_SSH_LOADKEY;
|
||||
break;
|
||||
|
||||
case APP_SSH_LOADKEY:
|
||||
{
|
||||
const char* bufName;
|
||||
byte buf[SCRATCH_BUFFER_SZ];
|
||||
word32 bufSz;
|
||||
|
||||
bufSz = load_key(useEcc, buf, SCRATCH_BUFFER_SZ);
|
||||
if (bufSz == 0) {
|
||||
SYS_CONSOLE_PRINT("Couldn't load key file.\r\n");
|
||||
appData.state = APP_SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
if (wolfSSH_CTX_UsePrivateKey_buffer(ctx, buf, bufSz,
|
||||
WOLFSSH_FORMAT_ASN1) < 0) {
|
||||
SYS_CONSOLE_PRINT("Couldn't use key buffer.\r\n");
|
||||
appData.state = APP_SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
bufSz = (word32)strlen(samplePasswordBuffer);
|
||||
memcpy(buf, samplePasswordBuffer, bufSz);
|
||||
buf[bufSz] = 0;
|
||||
LoadPasswordBuffer(buf, bufSz, &pwMapList);
|
||||
|
||||
bufName = useEcc ? samplePublicKeyEccBuffer :
|
||||
samplePublicKeyRsaBuffer;
|
||||
bufSz = (word32)strlen(bufName);
|
||||
memcpy(buf, bufName, bufSz);
|
||||
buf[bufSz] = 0;
|
||||
LoadPublicKeyBuffer(buf, bufSz, &pwMapList);
|
||||
}
|
||||
appData.state = APP_SSH_CREATE_SOCKET;
|
||||
break;
|
||||
|
||||
case APP_SSH_CREATE_SOCKET:
|
||||
numNetworks = TCPIP_STACK_NumberOfNetworksGet();
|
||||
if (numNetworks > 0) {
|
||||
int i;
|
||||
TCPIP_NET_HANDLE handle;
|
||||
|
||||
for (i = 0; i < numNetworks; i++) {
|
||||
IPV4_ADDR addr;
|
||||
|
||||
handle = TCPIP_STACK_IndexToNet(i);
|
||||
if (!TCPIP_STACK_NetIsReady(handle)) {
|
||||
return; /* interface not ready yet */
|
||||
}
|
||||
addr.Val = TCPIP_STACK_NetAddress(handle);
|
||||
SYS_CONSOLE_MESSAGE(TCPIP_STACK_NetNameGet(handle));
|
||||
SYS_CONSOLE_MESSAGE(" IP Address: ");
|
||||
SYS_CONSOLE_PRINT("%d.%d.%d.%d \r\n", addr.v[0],
|
||||
addr.v[1], addr.v[2], addr.v[3]);
|
||||
}
|
||||
|
||||
/* Create a socket for listen and accepting connections on */
|
||||
appData.socket = TCPIP_TCP_ServerOpen(IP_ADDRESS_TYPE_IPV4, SERVER_PORT, 0);
|
||||
if (!TCPIP_TCP_OptionsSet(appData.socket, TCP_OPTION_NODELAY, (void*)1)) {
|
||||
SYS_CONSOLE_PRINT("Unable to set no delay with TCP\r\n");
|
||||
appData.state = APP_SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
appData.state = APP_SSH_LISTEN;
|
||||
SYS_CONSOLE_PRINT("Waiting for client on to connect on port [%d]\r\n", SERVER_PORT);
|
||||
}
|
||||
else {
|
||||
SYS_CONSOLE_PRINT("No networks found...\r\n");
|
||||
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_SSH_LISTEN:
|
||||
if (TCPIP_TCP_IsConnected(appData.socket)) {
|
||||
SYS_CONSOLE_PRINT("Creating WOLFSSH struct and doing accept\r\n");
|
||||
ssh = wolfSSH_new(ctx);
|
||||
if (ssh == NULL) {
|
||||
SYS_CONSOLE_PRINT("Couldn't allocate SSH data.\r\n");
|
||||
appData.state = APP_SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
wolfSSH_SetUserAuthCtx(ssh, &pwMapList);
|
||||
wolfSSH_set_fd(ssh, appData.socket);
|
||||
appData.state = APP_SSH_ACCEPT;
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_SSH_ACCEPT:
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = wolfSSH_accept(ssh);
|
||||
if (ret == WS_SUCCESS || ret == WS_SFTP_COMPLETE || ret == WS_SCP_INIT) {
|
||||
SYS_CONSOLE_PRINT("wolfSSH accept success!\r\n");
|
||||
/* determine request type */
|
||||
switch (wolfSSH_GetSessionType(ssh)) {
|
||||
case WOLFSSH_SESSION_SHELL:
|
||||
SYS_CONSOLE_PRINT("Starting ECHO session\r\n");
|
||||
appData.state = APP_SSH_ECHO;
|
||||
break;
|
||||
|
||||
case WOLFSSH_SESSION_SUBSYSTEM:
|
||||
SYS_CONSOLE_PRINT("Starting SFTP session\r\n");
|
||||
appData.state = APP_SSH_SFTP_START;
|
||||
break;
|
||||
|
||||
case WOLFSSH_SESSION_UNKNOWN:
|
||||
case WOLFSSH_SESSION_EXEC:
|
||||
case WOLFSSH_SESSION_TERMINAL:
|
||||
SYS_CONSOLE_PRINT("Unsupported session type requested\r\n");
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else {
|
||||
ret = wolfSSH_get_error(ssh);
|
||||
if (ret != WS_WANT_READ && ret != WS_WANT_WRITE) {
|
||||
/* connection was closed or error happened */
|
||||
SYS_CONSOLE_PRINT("Error [%d] with wolfSSH connection. Closing socket.\r\n", ret);
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
}
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_SSH_SFTP_START:
|
||||
SYS_CONSOLE_PRINT("Setting starting SFTP directory to [%s]\r\n",
|
||||
"/mnt/myDrive1");
|
||||
if (wolfSSH_SFTP_SetDefaultPath(ssh, "/mnt/myDrive1") != WS_SUCCESS) {
|
||||
SYS_CONSOLE_PRINT("Error setting starting directory\r\n");
|
||||
SYS_CONSOLE_PRINT("Error = %d\r\n", wolfSSH_get_error(ssh));
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
}
|
||||
appData.state = APP_SSH_SFTP;
|
||||
break;
|
||||
|
||||
case APP_SSH_SFTP:
|
||||
#if defined(INCLUDE_uxTaskGetStackHighWaterMark) && \
|
||||
INCLUDE_uxTaskGetStackHighWaterMark == 1
|
||||
currentStack = uxTaskGetStackHighWaterMark(NULL);
|
||||
if (savedStack != currentStack) {
|
||||
savedStack = currentStack;
|
||||
SYS_CONSOLE_PRINT("Stack bytes free = %d\r\n", currentStack * 4);
|
||||
}
|
||||
|
||||
if (xPortGetMinimumEverFreeHeapSize() < minHeap) {
|
||||
minHeap = xPortGetMinimumEverFreeHeapSize();
|
||||
SYS_CONSOLE_PRINT("Min heap available water mark = %d bytes\r\n", minHeap);
|
||||
SYS_CONSOLE_PRINT("Total heap free = %d bytes\r\n", xPortGetFreeHeapSize());
|
||||
}
|
||||
#endif
|
||||
if (!TCPIP_TCP_IsConnected(wolfSSH_get_fd(ssh))) {
|
||||
SYS_CONSOLE_PRINT("TCP socket was disconnected\r\n");
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (wolfSSH_SFTP_PendingSend(ssh)) {
|
||||
/* Yes, process the SFTP data. */
|
||||
ret = wolfSSH_SFTP_read(ssh);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
|
||||
error == WS_CHAN_RXD || error == WS_REKEYING ||
|
||||
error == WS_WINDOW_FULL)
|
||||
ret = error;
|
||||
if (error == WS_WANT_WRITE && wolfSSH_SFTP_PendingSend(ssh)) {
|
||||
break; /* no need to spend time attempting to pull data
|
||||
* if there is still pending sends */
|
||||
}
|
||||
if (error == WS_EOF) {
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = wolfSSH_stream_peek(ssh, peek_buf, sizeof(peek_buf));
|
||||
if (ret > 0) {
|
||||
/* Yes, process the SFTP data. */
|
||||
ret = wolfSSH_SFTP_read(ssh);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (ret == WS_MEMORY_E) {
|
||||
SYS_CONSOLE_PRINT("Ran out of memory for malloc\r\n");
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
}
|
||||
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
|
||||
error == WS_CHAN_RXD || error == WS_REKEYING ||
|
||||
error == WS_WINDOW_FULL) {
|
||||
ret = error;
|
||||
}
|
||||
if (error == WS_EOF) {
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
}
|
||||
break;
|
||||
}
|
||||
else if (ret < 0) {
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (error == WS_EOF) {
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
ret = wolfSSH_worker(ssh, NULL);
|
||||
error = wolfSSH_get_error(ssh);
|
||||
if (ret == WS_REKEYING) {
|
||||
SYS_CONSOLE_PRINT("Doing rekeying\r\n");
|
||||
/* In a rekey, keeping turning the crank. */
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == WS_WANT_READ || error == WS_WANT_WRITE ||
|
||||
error == WS_WINDOW_FULL) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (error == WS_EOF) {
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
|
||||
if (ret == WS_FATAL_ERROR && error == 0) {
|
||||
WOLFSSH_CHANNEL* channel =
|
||||
wolfSSH_ChannelNext(ssh, NULL);
|
||||
if (channel && wolfSSH_ChannelGetEof(channel)) {
|
||||
ret = 0;
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (ret != WS_SUCCESS && ret != WS_CHAN_RXD) {
|
||||
/* If not successful and no channel data, leave. */
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
}
|
||||
break;
|
||||
|
||||
/* echo ssh input (example code from wolfssh/echoserver/echoserver.c) */
|
||||
case APP_SSH_ECHO:
|
||||
{
|
||||
byte* buf = NULL;
|
||||
byte* tmpBuf;
|
||||
int bufSz, backlogSz = 0, rxSz, txSz, stop = 0, txSum;
|
||||
|
||||
bufSz = EXAMPLE_BUFFER_SZ + backlogSz;
|
||||
|
||||
tmpBuf = (byte*)realloc(buf, bufSz);
|
||||
if (tmpBuf == NULL)
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
else
|
||||
buf = tmpBuf;
|
||||
|
||||
rxSz = wolfSSH_stream_read(ssh, buf + backlogSz,
|
||||
EXAMPLE_BUFFER_SZ);
|
||||
if (rxSz > 0) {
|
||||
{
|
||||
/* print out HEX value of received data */
|
||||
int i;
|
||||
SYS_CONSOLE_PRINT("wolfSSH server read HEX : \r\n");
|
||||
for (i = 0; i < rxSz; i++) {
|
||||
SYS_CONSOLE_PRINT("%02X", buf[backlogSz + i]);
|
||||
}
|
||||
SYS_CONSOLE_PRINT("\r\n");
|
||||
}
|
||||
backlogSz += rxSz;
|
||||
txSum = 0;
|
||||
txSz = 0;
|
||||
|
||||
while (backlogSz != txSum && txSz >= 0 && !stop) {
|
||||
txSz = wolfSSH_stream_send(ssh,
|
||||
buf + txSum,
|
||||
backlogSz - txSum);
|
||||
|
||||
if (txSz > 0) {
|
||||
byte c;
|
||||
const byte matches[] = { 0x03, 0x05, 0x06, 0x00 };
|
||||
|
||||
c = find_char(matches, buf + txSum, txSz);
|
||||
switch (c) {
|
||||
case 0x03:
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
case 0x06:
|
||||
if (wolfSSH_TriggerKeyExchange(ssh)
|
||||
!= WS_SUCCESS)
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
txSum += txSz;
|
||||
}
|
||||
else if (txSz != WS_REKEYING) {
|
||||
appData.state = APP_SSH_CLEANUP;
|
||||
}
|
||||
}
|
||||
|
||||
if (txSum < backlogSz)
|
||||
memmove(buf, buf + txSum, backlogSz - txSum);
|
||||
backlogSz -= txSum;
|
||||
}
|
||||
free(buf);
|
||||
}
|
||||
break;
|
||||
|
||||
case APP_SSH_CLEANUP:
|
||||
SYS_CONSOLE_PRINT("Closing and cleaning up connection\r\n\r\n");
|
||||
wolfSSH_free(ssh);
|
||||
WCLOSESOCKET(wolfSSH_get_fd(ssh));
|
||||
appData.state = APP_SSH_CREATE_SOCKET;
|
||||
break;
|
||||
|
||||
case APP_SSH_ERROR:
|
||||
{
|
||||
static int set = 0;
|
||||
if (!set) {
|
||||
set = 1;
|
||||
wolfSSH_CTX_free(ctx);
|
||||
PwMapListDelete(&pwMapList);
|
||||
if (wolfSSH_Cleanup() != WS_SUCCESS) {
|
||||
SYS_CONSOLE_PRINT("wolfSSH Cleanup Error.\r\n");
|
||||
}
|
||||
SYS_CONSOLE_PRINT("In error state\r\n");
|
||||
}
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
SYS_CONSOLE_PRINT("Unknown state!\r\n");
|
||||
appData.state = APP_SSH_ERROR;
|
||||
break;
|
||||
}
|
||||
}
|
|
@ -11843,12 +11843,13 @@ static int SignHEcdsa(WOLFSSH* ssh, byte* sig, word32* sigSz,
|
|||
WMEMCPY(sig + idx, s, sSz);
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_SMALL_STACK
|
||||
if (r)
|
||||
WFREE(r, heap, DYNTYPE_BUFFER);
|
||||
if (s)
|
||||
WFREE(s, heap, DYNTYPE_BUFFER);
|
||||
#endif
|
||||
#ifdef WOLFSSH_SMALL_STACK
|
||||
if (r)
|
||||
WFREE(r, heap, DYNTYPE_BUFFER);
|
||||
if (s)
|
||||
WFREE(s, heap, DYNTYPE_BUFFER);
|
||||
WOLFSSH_UNUSED(heap); /* could be unused in error case, resolve warning */
|
||||
#endif
|
||||
|
||||
WLOG(WS_LOG_DEBUG, "Leaving SignHEcdsa(), ret = %d", ret);
|
||||
return ret;
|
||||
|
@ -12348,6 +12349,7 @@ int SendKexDhReply(WOLFSSH* ssh)
|
|||
if (sig_ptr)
|
||||
WFREE(sig_ptr, heap, DYNTYPE_BUFFER);
|
||||
#endif
|
||||
WOLFSSH_UNUSED(heap);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -16828,6 +16830,7 @@ int wolfSSH_CleanPath(WOLFSSH* ssh, char* in)
|
|||
WMEMCPY(in, path, sz);
|
||||
in[sz] = '\0';
|
||||
WFREE(path, heap, DYNTYPE_PATH);
|
||||
WOLFSSH_UNUSED(heap);
|
||||
return (int)sz;
|
||||
}
|
||||
#endif /* WOLFSSH_SFTP || WOLFSSH_SCP */
|
||||
|
@ -16898,6 +16901,9 @@ int wolfSSH_oct2dec(WOLFSSH* ssh, byte* oct, word32 octSz)
|
|||
return ret;
|
||||
}
|
||||
|
||||
#ifndef WOLFSSL_MAX_32BIT
|
||||
#define WOLFSSL_MAX_32BIT INT_MAX
|
||||
#endif
|
||||
|
||||
/* addend1 += addend2 */
|
||||
void AddAssign64(word32* addend1, word32 addend2)
|
||||
|
|
14
src/io.c
14
src/io.c
|
@ -135,7 +135,6 @@ void* wolfSSH_GetIOWriteCtx(WOLFSSH* ssh)
|
|||
static int errno;
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
#include "tcpip/tcpip.h"
|
||||
#include "sys/errno.h"
|
||||
#include <errno.h>
|
||||
#elif defined(WOLFSSL_NUCLEUS)
|
||||
#include "nucleus.h"
|
||||
|
@ -327,6 +326,19 @@ int wsEmbedRecv(WOLFSSH* ssh, void* data, word32 sz, void* ctx)
|
|||
}
|
||||
#endif
|
||||
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
/* check is still connected */
|
||||
if (!TCPIP_TCP_IsConnected(sd))
|
||||
{
|
||||
return WS_CBIO_ERR_CONN_CLOSE;
|
||||
}
|
||||
|
||||
/* check for data ready to be read */
|
||||
if (TCPIP_TCP_GetIsReady(sd) <= 0) {
|
||||
return WS_CBIO_ERR_WANT_READ;
|
||||
}
|
||||
#endif
|
||||
|
||||
recvd = (int)RECV_FUNCTION(sd, buf, sz, ssh->rflags);
|
||||
|
||||
recvd = wsReturnCode(recvd, sd);
|
||||
|
|
67
src/port.c
67
src/port.c
|
@ -47,6 +47,23 @@ Flags:
|
|||
|
||||
#if !defined(NO_FILESYSTEM) && !defined(WOLFSSH_USER_FILESYSTEM) && \
|
||||
!defined(WOLFSSH_ZEPHYR)
|
||||
#if defined(MICROCHIP_MPLAB_HARMONY)
|
||||
int wfopen(WFILE* f, const char* filename, SYS_FS_FILE_OPEN_ATTRIBUTES mode)
|
||||
{
|
||||
if (f != NULL) {
|
||||
*f = SYS_FS_FileOpen(filename, mode);
|
||||
if (*f == WBADFILE) {
|
||||
WLOG(WS_LOG_SFTP, "Failed to open file %s", filename);
|
||||
return 1;
|
||||
}
|
||||
else {
|
||||
WLOG(WS_LOG_SFTP, "Opened file %s", filename);
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
#else
|
||||
int wfopen(WFILE** f, const char* filename, const char* mode)
|
||||
{
|
||||
#ifdef USE_WINDOWS_API
|
||||
|
@ -89,7 +106,7 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
|
|||
return 1;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
/* If either pread() or pwrite() are missing, use the local versions. */
|
||||
#if (defined(USE_OSE_API) || \
|
||||
|
@ -108,6 +125,32 @@ int wfopen(WFILE** f, const char* filename, const char* mode)
|
|||
|
||||
/* This is current inline in the source. */
|
||||
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
int wPwrite(WFD fd, unsigned char* buf, unsigned int sz,
|
||||
const unsigned int* shortOffset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (int)WFSEEK(NULL, &fd, shortOffset[0], SYS_FS_SEEK_SET);
|
||||
if (ret != -1) {
|
||||
ret = (int)WFWRITE(NULL, buf, 1, sz, &fd);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
int wPread(WFD fd, unsigned char* buf, unsigned int sz,
|
||||
const unsigned int* shortOffset)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = (int)WFSEEK(NULL, &fd, shortOffset[0], SYS_FS_SEEK_SET);
|
||||
if (ret != -1)
|
||||
ret = (int)WFREAD(NULL, buf, 1, sz, &fd);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
#elif defined(WOLFSSH_LOCAL_PREAD_PWRITE)
|
||||
|
||||
int wPwrite(WFD fd, unsigned char* buf, unsigned int sz,
|
||||
|
@ -617,6 +660,28 @@ int wPread(WFD fd, unsigned char* buf, unsigned int sz,
|
|||
|
||||
#endif
|
||||
|
||||
#ifndef NO_FILESYSTEM
|
||||
#if defined(MICROCHIP_MPLAB_HARMONY)
|
||||
int wChmod(const char *path, int mode)
|
||||
{
|
||||
SYS_FS_RESULT ret;
|
||||
SYS_FS_FILE_DIR_ATTR attr = 0;
|
||||
|
||||
/* mode is the octal value i.e 666 is 0x1B6 */
|
||||
if ((mode & 0x180) != 0x180) { /* not octal 6XX read only */
|
||||
attr |= SYS_FS_ATTR_RDO;
|
||||
}
|
||||
|
||||
/* toggle the read only attribute */
|
||||
ret = SYS_FS_FileDirectoryModeSet(path, attr, SYS_FS_ATTR_RDO);
|
||||
if (ret != SYS_FS_RES_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Failed to set file/dir mode");
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
#endif /* NO_FILESYSTEM */
|
||||
#ifndef WSTRING_USER
|
||||
|
||||
char* wstrdup(const char* s1, void* heap, int type)
|
||||
|
|
11
src/ssh.c
11
src/ssh.c
|
@ -2031,7 +2031,11 @@ int wolfSSH_ReadKey_file(const char* name,
|
|||
byte** out, word32* outSz, const byte** outType, word32* outTypeSz,
|
||||
byte* isPrivate, void* heap)
|
||||
{
|
||||
|
||||
WFILE* file;
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
WFILE f = WBADFILE;
|
||||
#endif
|
||||
byte* in;
|
||||
word32 inSz;
|
||||
int format;
|
||||
|
@ -2044,8 +2048,15 @@ int wolfSSH_ReadKey_file(const char* name,
|
|||
isPrivate == NULL)
|
||||
return WS_BAD_ARGUMENT;
|
||||
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
file = &f;
|
||||
ret = WFOPEN(NULL, &file, name, WOLFSSH_O_RDONLY);
|
||||
if (ret != 0 || *file == WBADFILE) return WS_BAD_FILE_E;
|
||||
#else
|
||||
ret = WFOPEN(NULL, &file, name, "rb");
|
||||
if (ret != 0 || file == WBADFILE) return WS_BAD_FILE_E;
|
||||
#endif
|
||||
|
||||
if (WFSEEK(NULL, file, 0, WSEEK_END) != 0) {
|
||||
WFCLOSE(NULL, file);
|
||||
return WS_BAD_FILE_E;
|
||||
|
|
241
src/wolfsftp.c
241
src/wolfsftp.c
|
@ -2026,27 +2026,34 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
|||
/* @TODO handle attributes */
|
||||
SFTP_ParseAtributes_buffer(ssh, &atr, data, &idx, maxSz);
|
||||
if ((reason & WOLFSSH_FXF_READ) && (reason & WOLFSSH_FXF_WRITE)) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_RDWR");
|
||||
m |= WOLFSSH_O_RDWR;
|
||||
}
|
||||
else {
|
||||
if (reason & WOLFSSH_FXF_READ) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_RDONLY");
|
||||
m |= WOLFSSH_O_RDONLY;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_WRITE) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_WRONLY");
|
||||
m |= WOLFSSH_O_WRONLY;
|
||||
}
|
||||
}
|
||||
|
||||
if (reason & WOLFSSH_FXF_APPEND) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_APPEND");
|
||||
m |= WOLFSSH_O_APPEND;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_CREAT) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_CREAT");
|
||||
m |= WOLFSSH_O_CREAT;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_TRUNC) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_TRUNC");
|
||||
m |= WOLFSSH_O_TRUNC;
|
||||
}
|
||||
if (reason & WOLFSSH_FXF_EXCL) {
|
||||
WLOG(WS_LOG_SFTP, "Opening file with WOLFSSH_O_EXCL");
|
||||
m |= WOLFSSH_O_EXCL;
|
||||
}
|
||||
|
||||
|
@ -2075,7 +2082,17 @@ int wolfSSH_SFTP_RecvOpen(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
|||
atr.per = 0644;
|
||||
}
|
||||
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
fd = WBADFILE;
|
||||
{
|
||||
WFILE* f = &fd;
|
||||
if (WFOPEN(ssh->fs, &f, dir, m) != WS_SUCCESS) {
|
||||
fd = -1;
|
||||
}
|
||||
}
|
||||
#else
|
||||
fd = WOPEN(ssh->fs, dir, m, atr.per);
|
||||
#endif
|
||||
if (fd < 0) {
|
||||
WLOG(WS_LOG_SFTP, "Error opening file %s", dir);
|
||||
res = oer;
|
||||
|
@ -3117,6 +3134,60 @@ static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
|
|||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
int SFTP_GetAttributesStat(WS_SFTP_FILEATRB* atr, WSTAT_T* stats);
|
||||
|
||||
/* helper function that gets file information from reading directory
|
||||
*
|
||||
* returns WS_SUCCESS on success
|
||||
*/
|
||||
static int wolfSSH_SFTPNAME_readdir(WOLFSSH* ssh, WDIR* dir, WS_SFTPNAME* out,
|
||||
char* dirName)
|
||||
{
|
||||
WSTAT_T stat;
|
||||
int sz;
|
||||
|
||||
if (dir == NULL || ssh == NULL || out == NULL) {
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
|
||||
if (*dir == SYS_FS_HANDLE_INVALID) {
|
||||
WLOG(WS_LOG_SFTP, "READ dir attempted with invalid handle");
|
||||
return WS_BAD_ARGUMENT;
|
||||
}
|
||||
WMEMSET(&stat, 0, sizeof(WSTAT_T));
|
||||
|
||||
/* 0 return and dp.name[0] == 0 means end-of-dir */
|
||||
if (SYS_FS_DirRead(*dir, &stat) != SYS_FS_RES_SUCCESS ||
|
||||
stat.fname[0] == '\0') {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
WLOG(WS_LOG_SFTP, "READ dir got nam %s", stat.fname);
|
||||
|
||||
sz = (int)WSTRLEN(stat.fname);
|
||||
out->fName = (char*)WMALLOC(sz + 1, out->heap, DYNTYPE_SFTP);
|
||||
if (out->fName == NULL) {
|
||||
return WS_MEMORY_E;
|
||||
}
|
||||
|
||||
WMEMCPY(out->fName, stat.fname, sz);
|
||||
out->fName[sz] = '\0';
|
||||
out->fSz = sz;
|
||||
|
||||
if (SFTP_GetAttributesStat(&out->atrb, &stat) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to get attribute values for %s",
|
||||
out->fName);
|
||||
}
|
||||
|
||||
/* Use attributes and fName to create long name */
|
||||
if (SFTP_CreateLongName(out) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_DEBUG, "Error creating long name for %s", out->fName);
|
||||
WFREE(out->fName, out->heap, DYNTYPE_SFTP);
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* helper function that gets file information from reading directory
|
||||
|
@ -3905,7 +3976,12 @@ int wolfSSH_SFTP_RecvClose(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
|||
if (sz == sizeof(WFD)) {
|
||||
WMEMSET((byte*)&fd, 0, sizeof(WFD));
|
||||
WMEMCPY((byte*)&fd, data + idx, sz);
|
||||
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
ret = WFCLOSE(ssh->fs, &fd);
|
||||
#else
|
||||
ret = WCLOSE(ssh->fs, fd);
|
||||
#endif
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
if (SFTP_RemoveHandleNode(ssh, data + idx, sz) != WS_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to remove handle from list");
|
||||
|
@ -4851,7 +4927,71 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
|
|||
|
||||
#elif defined(WOLFSSH_USER_FILESYSTEM)
|
||||
/* User-defined I/O support */
|
||||
#else
|
||||
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
int SFTP_GetAttributesStat(WS_SFTP_FILEATRB* atr, WSTAT_T* stats)
|
||||
{
|
||||
/* file size */
|
||||
atr->flags |= WOLFSSH_FILEATRB_SIZE;
|
||||
atr->sz[0] = (word32)stats->fsize;
|
||||
atr->sz[1] = (word32)(0);
|
||||
|
||||
/* file permissions */
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
if ((stats->fattrib & SYS_FS_ATTR_DIR) & SYS_FS_ATTR_MASK) {
|
||||
atr->per |= 0x41ED; /* 755 with directory */
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x8000;
|
||||
}
|
||||
|
||||
/* check for read only */
|
||||
if ((stats->fattrib & SYS_FS_ATTR_RDO) & SYS_FS_ATTR_MASK) {
|
||||
atr->per |= 0x124; /* octal 444 */
|
||||
}
|
||||
else {
|
||||
atr->per |= 0x1ED; /* octal 755 */
|
||||
}
|
||||
|
||||
/* last modified time */
|
||||
atr->mtime = stats->ftime;
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
|
||||
|
||||
static int SFTP_GetAttributesHelper(WS_SFTP_FILEATRB* atr, const char* fName)
|
||||
{
|
||||
WSTAT_T stats;
|
||||
SYS_FS_RESULT res;
|
||||
char buffer[255];
|
||||
|
||||
WMEMSET(atr, 0, sizeof(WS_SFTP_FILEATRB));
|
||||
WMEMSET(buffer, 0, sizeof(buffer));
|
||||
res = SYS_FS_CurrentDriveGet(buffer);
|
||||
if (res == SYS_FS_RES_SUCCESS) {
|
||||
if (WSTRCMP(fName, buffer) == 0) {
|
||||
atr->flags |= WOLFSSH_FILEATRB_PERM;
|
||||
atr->per |= 0x41ED; /* 755 with directory */
|
||||
atr->per |= 0x1ED; /* octal 755 */
|
||||
|
||||
atr->flags |= WOLFSSH_FILEATRB_SIZE;
|
||||
atr->sz[0] = 0;
|
||||
atr->sz[1] = 0;
|
||||
|
||||
atr->mtime = 30912;
|
||||
WLOG(WS_LOG_SFTP, "Setting mount point as directory");
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
if (WSTAT(ssh->fs, fName, &stats) != 0) {
|
||||
WLOG(WS_LOG_SFTP, "Issue with WSTAT call");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
return SFTP_GetAttributesStat(atr, &stats);
|
||||
}
|
||||
|
||||
|
||||
/* @TODO can be overriden by user for portability
|
||||
* NOTE: if atr->flags is set to a value of 0 then no attributes are set.
|
||||
|
@ -4860,6 +5000,46 @@ int SFTP_GetAttributes_Handle(WOLFSSH* ssh, byte* handle, int handleSz,
|
|||
*/
|
||||
int SFTP_GetAttributes(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr,
|
||||
byte noFollow, void* heap)
|
||||
{
|
||||
WOLFSSH_UNUSED(heap);
|
||||
WOLFSSH_UNUSED(fs);
|
||||
|
||||
return SFTP_GetAttributesHelper(atr, fileName);
|
||||
}
|
||||
|
||||
|
||||
/* @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(WOLFSSH* ssh, byte* handle, int handleSz,
|
||||
WS_SFTP_FILEATRB* atr)
|
||||
{
|
||||
WS_HANDLE_LIST* cur;
|
||||
|
||||
if (handleSz != sizeof(word32)) {
|
||||
WLOG(WS_LOG_SFTP, "Unexpected handle size SFTP_GetAttributes_Handle()");
|
||||
}
|
||||
|
||||
cur = SFTP_GetHandleNode(ssh, handle, handleSz);
|
||||
if (cur == NULL) {
|
||||
WLOG(WS_LOG_SFTP, "Unknown handle");
|
||||
return WS_BAD_FILE_E;
|
||||
}
|
||||
|
||||
return SFTP_GetAttributesHelper(atr, cur->name);
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
/* 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(void* fs, const char* fileName, WS_SFTP_FILEATRB* atr,
|
||||
byte noFollow, void* heap)
|
||||
{
|
||||
WSTAT_T stats;
|
||||
|
||||
|
@ -5129,7 +5309,6 @@ int wolfSSH_SFTP_RecvLSTAT(WOLFSSH* ssh, int reqId, byte* data, word32 maxSz)
|
|||
}
|
||||
|
||||
WLOG(WS_LOG_SFTP, "Receiving WOLFSSH_FTP_LSTAT");
|
||||
|
||||
if (maxSz < UINT32_SZ) {
|
||||
/* not enough for an ato32 call */
|
||||
return WS_BUFFER_E;
|
||||
|
@ -8661,12 +8840,12 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
|
|||
|
||||
case STATE_GET_OPEN_LOCAL:
|
||||
WLOG(WS_LOG_SFTP, "SFTP GET STATE: OPEN LOCAL");
|
||||
#ifndef USE_WINDOWS_API
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
if (state->gOfst[0] > 0 || state->gOfst[1] > 0)
|
||||
ret = WFOPEN(ssh->fs, &state->fl, to, "ab");
|
||||
ret = WFOPEN(ssh->fs, &state->fl, to, WOLFSSH_O_APPEND);
|
||||
else
|
||||
ret = WFOPEN(ssh->fs, &state->fl, to, "wb");
|
||||
#else /* USE_WINDOWS_API */
|
||||
ret = WFOPEN(ssh->fs, &state->fl, to, WOLFSSH_O_WRONLY);
|
||||
#elif defined(USE_WINDOWS_API)
|
||||
{
|
||||
DWORD desiredAccess = GENERIC_WRITE;
|
||||
if (state->gOfst > 0)
|
||||
|
@ -8681,6 +8860,11 @@ int wolfSSH_SFTP_Get(WOLFSSH* ssh, char* from,
|
|||
state->offset.OffsetHigh = state->gOfst[1];
|
||||
state->offset.Offset = state->gOfst[0];
|
||||
}
|
||||
#else
|
||||
if (state->gOfst[0] > 0 || state->gOfst[1] > 0)
|
||||
ret = WFOPEN(ssh->fs, &state->fl, to, "ab");
|
||||
else
|
||||
ret = WFOPEN(ssh->fs, &state->fl, to, "wb");
|
||||
#endif /* USE_WINDOWS_API */
|
||||
if (ret != 0) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to open output file");
|
||||
|
@ -8878,7 +9062,11 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
|||
}
|
||||
}
|
||||
}
|
||||
#if defined(MICROCHIP_MPLAB_HARMONY)
|
||||
ret = WFOPEN(ssh->fs, &state->fl, from, WOLFSSH_O_RDONLY);
|
||||
#else
|
||||
ret = WFOPEN(ssh->fs, &state->fl, from, "rb");
|
||||
#endif
|
||||
if (ret != 0) {
|
||||
WLOG(WS_LOG_SFTP, "Unable to open input file");
|
||||
ssh->error = WS_SFTP_FILE_DNE;
|
||||
|
@ -9021,25 +9209,38 @@ int wolfSSH_SFTP_Put(WOLFSSH* ssh, char* from, char* to, byte resume,
|
|||
}
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
static int SFTP_FreeHandles(WOLFSSH* ssh)
|
||||
{
|
||||
WS_HANDLE_LIST* cur = ssh->handleList;
|
||||
|
||||
/* go through and free handles and make sure files are closed */
|
||||
while (cur != NULL) {
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
WFCLOSE(ssh->fs, ((WFILE*)cur->handle));
|
||||
#else
|
||||
WCLOSE(ssh->fs, *((WFD*)cur->handle));
|
||||
#endif
|
||||
if (SFTP_RemoveHandleNode(ssh, cur->handle, cur->handleSz)
|
||||
!= WS_SUCCESS) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
cur = ssh->handleList;
|
||||
}
|
||||
|
||||
return WS_SUCCESS;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* called when wolfSSH_free() is called
|
||||
* return WS_SUCCESS on success */
|
||||
int wolfSSH_SFTP_free(WOLFSSH* ssh)
|
||||
{
|
||||
int ret = WS_SUCCESS;
|
||||
|
||||
WOLFSSH_UNUSED(ssh);
|
||||
#ifdef WOLFSSH_STOREHANDLE
|
||||
{
|
||||
WS_HANDLE_LIST* cur = ssh->handleList;
|
||||
|
||||
/* go through and free handles and make sure files are closed */
|
||||
while (cur != NULL) {
|
||||
WCLOSE(ssh->fs, *((WFD*)cur->handle));
|
||||
if (SFTP_RemoveHandleNode(ssh, cur->handle, cur->handleSz)
|
||||
!= WS_SUCCESS) {
|
||||
return WS_FATAL_ERROR;
|
||||
}
|
||||
cur = ssh->handleList;
|
||||
}
|
||||
}
|
||||
ret = SFTP_FreeHandles(ssh);
|
||||
#endif
|
||||
|
||||
#ifndef NO_WOLFSSH_DIR
|
||||
|
@ -9066,7 +9267,7 @@ int wolfSSH_SFTP_free(WOLFSSH* ssh)
|
|||
#endif /* NO_WOLFSSH_DIR */
|
||||
|
||||
wolfSSH_SFTP_ClearState(ssh, STATE_ID_ALL);
|
||||
return WS_SUCCESS;
|
||||
return ret;
|
||||
}
|
||||
|
||||
#ifdef WOLFSSH_SHOW_SIZES
|
||||
|
|
|
@ -408,7 +408,7 @@ enum NameIdType {
|
|||
#define MAX_KEY_EXCHANGE 2
|
||||
#define MAX_PUBLIC_KEY 1
|
||||
#define MIN_RSA_SIG_SZ 2
|
||||
#define MAX_HMAC_SZ WC_SHA512_DIGEST_SIZE
|
||||
#define MAX_HMAC_SZ WC_MAX_DIGEST_SIZE
|
||||
#define MIN_BLOCK_SZ 8
|
||||
#define COOKIE_SZ 16
|
||||
#define PAD_LENGTH_SZ 1
|
||||
|
|
109
wolfssh/port.h
109
wolfssh/port.h
|
@ -21,7 +21,7 @@
|
|||
|
||||
/*
|
||||
* The port module wraps standard C library functions with macros to
|
||||
* cover portablility issues when building in environments that rename
|
||||
* cover portability issues when building in environments that rename
|
||||
* those functions. This module also provides local versions of some
|
||||
* standard C library functions that are missing on some platforms.
|
||||
*/
|
||||
|
@ -391,6 +391,42 @@ extern "C" {
|
|||
#define WUTIMES(a,b) (0) /* Not ported yet */
|
||||
#define WCHDIR(fs,b) z_fs_chdir((b))
|
||||
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "system/fs/sys_fs.h"
|
||||
|
||||
#define WFFLUSH(s) SYS_FS_FileSync((s))
|
||||
|
||||
#define WFILE SYS_FS_HANDLE
|
||||
|
||||
#define FLUSH_STD(a)
|
||||
|
||||
WOLFSSH_LOCAL int wfopen(WFILE* f, const char* filename,
|
||||
SYS_FS_FILE_OPEN_ATTRIBUTES mode);
|
||||
WOLFSSH_LOCAL int wChmod(const char *path, int mode);
|
||||
|
||||
#define WFOPEN(fs,f,fn,m) wfopen(*(f),(fn),(m))
|
||||
#define WFCLOSE(fs,f) SYS_FS_FileClose(*(f))
|
||||
#define WFREAD(fs,b,s,a,f) SYS_FS_FileRead(*(f),(b),(s)*(a))
|
||||
#define WFWRITE(fs,b,s,a,f) SYS_FS_FileWrite(*(f),(b),(s)*(a))
|
||||
#define WFSEEK(fs,s,o,w) SYS_FS_FileSeek(*(s),(o),(w))
|
||||
#define WFTELL(fs,s) SYS_FS_FileTell(*(s))
|
||||
#define WREWIND(fs,s) SYS_FS_FileSeek(*(s), 0, SYS_FS_SEEK_SET)
|
||||
#define WSEEK_END SYS_FS_SEEK_END
|
||||
#define WBADFILE SYS_FS_HANDLE_INVALID
|
||||
#define WCHMOD(fs,f,m) wChmod((f),(m))
|
||||
#define WFCHMOD(fs,fd,m) (0)
|
||||
#undef WFGETS
|
||||
#define WFGETS(b,s,f) SYS_FS_FileStringGet((f), (b), (s))
|
||||
#undef WFPUTS
|
||||
#define WFPUTS(b,f) SYS_FS_FileStringPut((f), (b))
|
||||
#define WUTIMES(a,b) (0) /* Not ported yet */
|
||||
#define WSETTIME(fs,f,a,m) (0)
|
||||
#define WFSETTIME(fs,fd,a,m) (0)
|
||||
#define WCHDIR(fs,b) SYS_FS_DirectryChange((b))
|
||||
|
||||
#elif defined(WOLFSSH_USER_FILESYSTEM)
|
||||
/* User-defined I/O support */
|
||||
#else
|
||||
|
@ -418,7 +454,7 @@ extern "C" {
|
|||
#ifdef WOLFSSL_VXWORKS
|
||||
#define WUTIMES(f,t) (WS_SUCCESS)
|
||||
#elif defined(USE_WINDOWS_API)
|
||||
#include <sys/utime.h>
|
||||
#include <sys/utime.h>
|
||||
#else
|
||||
#define WUTIMES(f,t) utimes((f),(t))
|
||||
#endif
|
||||
|
@ -1328,6 +1364,75 @@ extern "C" {
|
|||
#define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
|
||||
#define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
|
||||
|
||||
#elif defined(MICROCHIP_MPLAB_HARMONY)
|
||||
|
||||
#define WDIR SYS_FS_HANDLE
|
||||
#define WSTAT_T SYS_FS_FSTAT
|
||||
|
||||
#define WOPENDIR(fs,h,c,d) wDirOpen((h), (c),(d))
|
||||
#define WCLOSEDIR(fs,d) SYS_FS_DirClose(*(d))
|
||||
#define WMKDIR(fs,p,m) SYS_FS_DirectoryMake((p))
|
||||
#define WRMDIR(fs,d) SYS_FS_FileDirectoryRemove((d))
|
||||
#define WSTAT(fs,p,b) wStat((p), (b))
|
||||
#define WREMOVE(fs,d) SYS_FS_FileDirectoryRemove((d))
|
||||
#define WRENAME(fs,o,n) SYS_FS_FileDirectoryRenameMove((o),(n))
|
||||
#define WS_DELIM '/'
|
||||
|
||||
static inline int wDirOpen(void* heap, WDIR* dir, const char* path)
|
||||
{
|
||||
*dir = SYS_FS_DirOpen(path);
|
||||
if (*dir == SYS_FS_HANDLE_INVALID) {
|
||||
return -1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline int wStat(const char* path, WSTAT_T* stat)
|
||||
{
|
||||
int ret;
|
||||
WMEMSET(stat, 0, sizeof(WSTAT_T));
|
||||
ret = SYS_FS_FileStat(path, stat);
|
||||
|
||||
if (ret != SYS_FS_RES_SUCCESS) {
|
||||
WLOG(WS_LOG_SFTP,
|
||||
"Return from SYS_FS_fileStat [%s] = %d, expecting %d",
|
||||
path, ret, SYS_FS_RES_SUCCESS);
|
||||
WLOG(WS_LOG_SFTP, "SYS error reason = %d", SYS_FS_Error());
|
||||
return -1;
|
||||
}
|
||||
else {
|
||||
return 0;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline char *ff_getcwd(char *r, int rSz)
|
||||
{
|
||||
SYS_FS_RESULT ret;
|
||||
ret = SYS_FS_CurrentWorkingDirectoryGet(r, rSz);
|
||||
if (ret != SYS_FS_RES_SUCCESS) {
|
||||
return r;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
#define WGETCWD(fs,r,rSz) ff_getcwd(r,(rSz))
|
||||
|
||||
#define WOLFSSH_O_RDWR SYS_FS_FILE_OPEN_READ_PLUS
|
||||
#define WOLFSSH_O_RDONLY SYS_FS_FILE_OPEN_READ
|
||||
#define WOLFSSH_O_WRONLY SYS_FS_FILE_OPEN_WRITE_PLUS
|
||||
#define WOLFSSH_O_APPEND SYS_FS_FILE_OPEN_APPEND
|
||||
#define WOLFSSH_O_CREAT SYS_FS_FILE_OPEN_WRITE_PLUS
|
||||
#define WOLFSSH_O_TRUNC 0
|
||||
#define WOLFSSH_O_EXCL 0
|
||||
|
||||
/* Our "file descriptor" wrapper */
|
||||
|
||||
#define WFD SYS_FS_HANDLE
|
||||
int wPwrite(WFD, unsigned char*, unsigned int, const unsigned int*);
|
||||
int wPread(WFD, unsigned char*, unsigned int, const unsigned int*);
|
||||
#define WPWRITE(fs,fd,b,s,o) wPwrite((fd),(b),(s),(o))
|
||||
#define WPREAD(fs,fd,b,s,o) wPread((fd),(b),(s),(o))
|
||||
|
||||
#elif defined(WOLFSSH_USER_FILESYSTEM)
|
||||
/* User-defined I/O support */
|
||||
#include "myFilesystem.h"
|
||||
|
|
|
@ -68,6 +68,12 @@ extern "C" {
|
|||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef MICROCHIP_MPLAB_HARMONY
|
||||
#ifndef WOLFSSH_STOREHANDLE
|
||||
#define WOLFSSH_STOREHANDLE
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifdef FREESCALE_MQX
|
||||
#define NO_STDIO_FILESYSTEM
|
||||
#ifndef WOLFSSH_STOREHANDLE
|
||||
|
|
Loading…
Reference in New Issue