Merge pull request #790 from JacobBarthelmeh/pic32

microchip example and filesystem port
pull/796/head
David Garske 2025-04-04 10:04:16 -07:00 committed by GitHub
commit d3bd96f210
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
19 changed files with 22844 additions and 31 deletions

3
.gitignore vendored
View File

@ -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

View File

@ -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

View File

@ -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```

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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)

View File

@ -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);

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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

View File

@ -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"

View File

@ -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