wolfssh/tests/api.c

838 lines
26 KiB
C
Raw Normal View History

2017-06-13 11:15:44 -05:00
/* api.c
*
2019-04-08 12:24:08 -05:00
* Copyright (C) 2014-2019 wolfSSL Inc.
2017-06-13 11:15:44 -05:00
*
* 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/>.
*/
#include <stdio.h>
#include <wolfssh/ssh.h>
#include <wolfssh/internal.h>
2018-07-02 13:02:19 -05:00
#ifdef WOLFSSH_SCP
#include <wolfssh/wolfscp.h>
#endif
#ifdef WOLFSSH_SFTP
#define WOLFSSH_TEST_LOCKING
#define WOLFSSH_TEST_THREADING
#define WOLFSSH_TEST_SERVER
#define WOLFSSH_TEST_ECHOSERVER
#include <wolfssh/test.h>
#include "examples/echoserver/echoserver.h"
#endif
/* for echoserver test cases */
int myoptind = 0;
char* myoptarg = NULL;
2017-06-13 11:15:44 -05:00
#define Fail(description, result) do { \
printf("\nERROR - %s line %d failed with:", __FILE__, __LINE__); \
printf("\n expected: "); printf description; \
printf("\n result: "); printf result; printf("\n\n"); \
abort(); \
} while(0)
#define Assert(test, description, result) if (!(test)) Fail(description, result)
#define AssertTrue(x) Assert( (x), ("%s is true", #x), (#x " => FALSE"))
#define AssertFalse(x) Assert(!(x), ("%s is false", #x), (#x " => TRUE"))
#define AssertNotNull(x) Assert( (x), ("%s is not null", #x), (#x " => NULL"))
#define AssertNull(x) do { \
void* _x = (void *) (x); \
\
Assert(!_x, ("%s is null", #x), (#x " => %p", _x)); \
} while(0)
#define AssertInt(x, y, op, er) do { \
int _x = x; \
int _y = y; \
\
Assert(_x op _y, ("%s " #op " %s", #x, #y), ("%d " #er " %d", _x, _y)); \
} while(0)
#define AssertIntEQ(x, y) AssertInt(x, y, ==, !=)
#define AssertIntNE(x, y) AssertInt(x, y, !=, ==)
#define AssertIntGT(x, y) AssertInt(x, y, >, <=)
#define AssertIntLT(x, y) AssertInt(x, y, <, >=)
#define AssertIntGE(x, y) AssertInt(x, y, >=, <)
#define AssertIntLE(x, y) AssertInt(x, y, <=, >)
#define AssertStr(x, y, op, er) do { \
const char* _x = x; \
const char* _y = y; \
int _z = strcmp(_x, _y); \
\
Assert(_z op 0, ("%s " #op " %s", #x, #y), \
("\"%s\" " #er " \"%s\"", _x, _y));\
} while(0)
#define AssertStrEQ(x, y) AssertStr(x, y, ==, !=)
#define AssertStrNE(x, y) AssertStr(x, y, !=, ==)
#define AssertStrGT(x, y) AssertStr(x, y, >, <=)
#define AssertStrLT(x, y) AssertStr(x, y, <, >=)
#define AssertStrGE(x, y) AssertStr(x, y, >=, <)
#define AssertStrLE(x, y) AssertStr(x, y, <=, >)
/* Utility functions */
#define BAD 0xFF
const byte hexDecode[] =
{
0, 1, 2, 3, 4, 5, 6, 7, 8, 9,
BAD, BAD, BAD, BAD, BAD, BAD, BAD,
10, 11, 12, 13, 14, 15, /* upper case A-F */
BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
BAD, BAD, BAD, BAD, BAD, BAD, BAD, BAD,
BAD, BAD, /* G - ` */
10, 11, 12, 13, 14, 15 /* lower case a-f */
}; /* A starts at 0x41 not 0x3A */
static int Base16_Decode(const byte* in, word32 inLen,
byte* out, word32* outLen)
{
word32 inIdx = 0;
word32 outIdx = 0;
if (inLen == 1 && *outLen && in) {
byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
/* sanity check */
if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
return -1;
b = hexDecode[b];
if (b == BAD)
return -1;
out[outIdx++] = b;
*outLen = outIdx;
return 0;
}
if (inLen % 2)
return -1;
if (*outLen < (inLen / 2))
return -1;
while (inLen) {
byte b = in[inIdx++] - 0x30; /* 0 starts at 0x30 */
byte b2 = in[inIdx++] - 0x30;
/* sanity checks */
if (b >= sizeof(hexDecode)/sizeof(hexDecode[0]))
return -1;
if (b2 >= sizeof(hexDecode)/sizeof(hexDecode[0]))
return -1;
b = hexDecode[b];
b2 = hexDecode[b2];
if (b == BAD || b2 == BAD)
return -1;
out[outIdx++] = (byte)((b << 4) | b2);
inLen -= 2;
}
*outLen = outIdx;
return 0;
}
static void FreeBins(byte* b1, byte* b2, byte* b3, byte* b4)
{
if (b1 != NULL) free(b1);
if (b2 != NULL) free(b2);
if (b3 != NULL) free(b3);
if (b4 != NULL) free(b4);
}
/* convert hex string to binary, store size, 0 success (free mem on failure) */
static int ConvertHexToBin(const char* h1, byte** b1, word32* b1Sz,
const char* h2, byte** b2, word32* b2Sz,
const char* h3, byte** b3, word32* b3Sz,
const char* h4, byte** b4, word32* b4Sz)
{
int ret;
/* b1 */
if (h1 && b1 && b1Sz) {
*b1Sz = (word32)strlen(h1) / 2;
*b1 = (byte*)malloc(*b1Sz);
if (*b1 == NULL)
return -1;
ret = Base16_Decode((const byte*)h1, (word32)strlen(h1),
*b1, b1Sz);
if (ret != 0) {
FreeBins(*b1, NULL, NULL, NULL);
return -1;
}
}
/* b2 */
if (h2 && b2 && b2Sz) {
*b2Sz = (word32)strlen(h2) / 2;
*b2 = (byte*)malloc(*b2Sz);
if (*b2 == NULL) {
FreeBins(b1 ? *b1 : NULL, NULL, NULL, NULL);
return -1;
}
ret = Base16_Decode((const byte*)h2, (word32)strlen(h2),
*b2, b2Sz);
if (ret != 0) {
FreeBins(b1 ? *b1 : NULL, *b2, NULL, NULL);
return -1;
}
}
/* b3 */
if (h3 && b3 && b3Sz) {
*b3Sz = (word32)strlen(h3) / 2;
*b3 = (byte*)malloc(*b3Sz);
if (*b3 == NULL) {
FreeBins(b1 ? *b1 : NULL, b2 ? *b2 : NULL, NULL, NULL);
return -1;
}
ret = Base16_Decode((const byte*)h3, (word32)strlen(h3),
*b3, b3Sz);
if (ret != 0) {
FreeBins(b1 ? *b1 : NULL, b2 ? *b2 : NULL, *b3, NULL);
return -1;
}
}
/* b4 */
if (h4 && b4 && b4Sz) {
*b4Sz = (word32)strlen(h4) / 2;
*b4 = (byte*)malloc(*b4Sz);
if (*b4 == NULL) {
FreeBins(b1 ? *b1 : NULL, b2 ? *b2 : NULL, b3 ? *b3 : NULL, NULL);
return -1;
}
ret = Base16_Decode((const byte*)h4, (word32)strlen(h4),
*b4, b4Sz);
if (ret != 0) {
FreeBins(b1 ? *b1 : NULL, b2 ? *b2 : NULL, b3 ? *b3 : NULL, *b4);
return -1;
}
}
return 0;
}
#ifdef WOLFSSH_SFTP
byte userPassword[256];
static int sftpUserAuth(byte authType, WS_UserAuthData* authData, void* ctx)
{
int ret = WOLFSSH_USERAUTH_INVALID_AUTHTYPE;
if (authType == WOLFSSH_USERAUTH_PASSWORD) {
const char* defaultPassword = (const char*)ctx;
word32 passwordSz;
ret = WOLFSSH_USERAUTH_SUCCESS;
if (defaultPassword != NULL) {
passwordSz = (word32)strlen(defaultPassword);
memcpy(userPassword, defaultPassword, passwordSz);
}
else {
printf("Expecting password set for test cases\n");
return ret;
}
if (ret == WOLFSSH_USERAUTH_SUCCESS) {
authData->sf.password.password = userPassword;
authData->sf.password.passwordSz = passwordSz;
}
}
return ret;
}
/* preforms connection to port, sets WOLFSSH_CTX and WOLFSSH on success
* caller needs to free ctx and ssh when done
*/
static void sftp_client_connect(WOLFSSH_CTX** ctx, WOLFSSH** ssh, int port)
{
SOCKET_T sockFd = WOLFSSH_SOCKET_INVALID;
SOCKADDR_IN_T clientAddr;
socklen_t clientAddrSz = sizeof(clientAddr);
int ret;
char* host = (char*)wolfSshIp;
const char* username = "jill";
const char* password = "upthehill";
if (ctx == NULL || ssh == NULL) {
return;
}
*ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL);
if (*ctx == NULL) {
return;
}
wolfSSH_SetUserAuth(*ctx, sftpUserAuth);
*ssh = wolfSSH_new(*ctx);
if (*ssh == NULL) {
wolfSSH_CTX_free(*ctx);
*ctx = NULL;
return;
}
build_addr(&clientAddr, host, port);
tcp_socket(&sockFd);
ret = connect(sockFd, (const struct sockaddr *)&clientAddr, clientAddrSz);
if (ret != 0){
wolfSSH_free(*ssh);
wolfSSH_CTX_free(*ctx);
*ctx = NULL;
*ssh = NULL;
return;
}
wolfSSH_SetUserAuthCtx(*ssh, (void*)password);
ret = wolfSSH_SetUsername(*ssh, username);
if (ret == WS_SUCCESS)
ret = wolfSSH_set_fd(*ssh, (int)sockFd);
if (ret == WS_SUCCESS)
ret = wolfSSH_SFTP_connect(*ssh);
if (ret != WS_SUCCESS){
wolfSSH_free(*ssh);
wolfSSH_CTX_free(*ctx);
*ctx = NULL;
*ssh = NULL;
return;
}
}
#endif /* WOLFSSH_SFTP */
enum WS_TestEndpointTypes {
TEST_GOOD_ENDPOINT_SERVER = WOLFSSH_ENDPOINT_SERVER,
TEST_GOOD_ENDPOINT_CLIENT = WOLFSSH_ENDPOINT_CLIENT,
TEST_BAD_ENDPOINT_NEXT,
TEST_BAD_ENDPOINT_LAST = 255
};
static void test_wolfSSH_CTX_new(void)
{
WOLFSSH_CTX* ctx;
AssertNull(ctx = wolfSSH_CTX_new(TEST_BAD_ENDPOINT_NEXT, NULL));
wolfSSH_CTX_free(ctx);
AssertNull(ctx = wolfSSH_CTX_new(TEST_BAD_ENDPOINT_LAST, NULL));
wolfSSH_CTX_free(ctx);
AssertNotNull(ctx = wolfSSH_CTX_new(TEST_GOOD_ENDPOINT_SERVER, NULL));
wolfSSH_CTX_free(ctx);
AssertNotNull(ctx = wolfSSH_CTX_new(TEST_GOOD_ENDPOINT_CLIENT, NULL));
wolfSSH_CTX_free(ctx);
}
static void test_server_wolfSSH_new(void)
{
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
AssertNull(ssh = wolfSSH_new(NULL));
wolfSSH_free(ssh);
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
}
static void test_client_wolfSSH_new(void)
{
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
AssertNull(ssh = wolfSSH_new(NULL));
wolfSSH_free(ssh);
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
}
static void test_wolfSSH_set_fd(void)
{
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
WS_SOCKET_T fd = 23, check;
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
AssertIntNE(WS_SUCCESS, wolfSSH_set_fd(NULL, fd));
check = wolfSSH_get_fd(NULL);
AssertFalse(WS_SUCCESS == check);
AssertIntEQ(WS_SUCCESS, wolfSSH_set_fd(ssh, fd));
check = wolfSSH_get_fd(ssh);
AssertTrue(fd == check);
AssertTrue(0 != check);
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
}
IDE Support 1. Added Windows Visual Studio build solution. Includes projects for: * wolfSSH static library * echoserver * unit-test * api-test * 32- and 64-bit debug and release builds for all 2. Made necessary tweaks including adding some wrapper functions so the code compiles for both Linux/macOS and Windows. 3. Fixed a bug in the KDF test where the output buffer wasn't updated when SHA-256 was added. 4. Added the fallthrough attribute for GCC7. 5. Replaced all uses of `uint8_t`, `uint16_t`, and `uint32_t` with the wolfCrypt provided `byte`, `word16`, and `word32`. 6. Split the new channel function into new and init. 7. Added some ECC keys for authentication testing. 8. Moved some functions and includes around. 9. Removed the keying state machine and replaced with a flag. 10. Added rekey trigger if the client sends *CTRL-F* to echoserver. 11. Moved the sequence number increase outside `CreateMac()`. Incremented if the packet was successfully created. This way the sequence number is incremented when using AES-GCM. 12. Removed the redundant function `SendText()`. 13. Renamed the `clientId` related functions and data members to `protoId` to keep things role agnostic. 14. Changed all references of `clientKey` and `serverKey` to `keys` and `peerKeys`. 15. Updated `GenerateKeys()` to generate `keys` and `peerKeys` appropriately based on the endpoint side. 16. Added the wolfSSL style _test.h_ file to group shared example functions in one place. 17. Changed the echoserver to be similar to wolfSSL's where the code may be included without the main function in another executable. Note: This commit is a squash of more than a dozen commits. IDE support was added to the client branch, but the client branch is on hold. There were many changes in the client branch that are needed going forward. The code at the head of the client branch was copied over to the IDE branch, and the client code either deleted or removed from the build.
2017-09-12 13:26:54 -05:00
static void test_wolfSSH_SetUsername(void)
{
#ifndef WOLFSSH_NO_CLIENT
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
const char username[] = "johnny";
const char empty[] = "";
AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(NULL, NULL));
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(ssh, username));
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_CLIENT, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(ssh, NULL));
AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(ssh, empty));
wolfSSH_free(ssh);
AssertNotNull(ssh = wolfSSH_new(ctx));
AssertIntEQ(WS_SUCCESS, wolfSSH_SetUsername(ssh, username));
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
#endif /* WOLFSSH_NO_CLIENT */
}
enum WS_TestFormatTypes {
TEST_GOOD_FORMAT_ASN1 = WOLFSSH_FORMAT_ASN1,
TEST_GOOD_FORMAT_PEM = WOLFSSH_FORMAT_PEM,
TEST_GOOD_FORMAT_RAW = WOLFSSH_FORMAT_RAW,
TEST_BAD_FORMAT_NEXT,
TEST_BAD_FORMAT_LAST = 0xFFFF
};
static const char serverKeyEccDer[] =
"307702010104206109990b79d25f285a0f5d15cca15654f92b3987212da77d85"
"7bb87f38c66dd5a00a06082a8648ce3d030107a144034200048113ffa42bb79c"
"45747a834c61f33fad26cf22cda9a3bca561b47ce662d4c2f755439a31fb8011"
"20b5124b24f578d7fd22ef4635f005586b5f63c8da1bc4f569";
static const char serverKeyRsaDer[] =
"308204a30201000282010100da5dad2514761559f340fd3cb86230b36dc0f9ec"
"ec8b831e9e429cca416ad38ae15234e00d13627ed40fae5c4d04f18dfac5ad77"
"aa5a05caeff88dabff8a29094c04c2f519cbed1fb1b429d3c36ca923dfa3a0e5"
"08dead8c71f934886ced3bf06fa50fac59ff6b33f170fb8ca4b345228d9d777a"
"e5295f8414d999eaeace2d51f3e358fa5b020fc9b52abcb25ed3c230bb3cb1c3"
"ef58f35094288bc4654af700d997d96b4d8d95a18a6206b450112283b4ea2ae7"
"d0a820474fff46aec513e1388bf854af3a4d2ff81fd78490d8930506c27d90db"
"e39cd0c4655a03ad00ac5aa2cdda3f89583753bf2b467aac89412b5a2ee876e7"
"5ee32985a363eae686607c2d02030100010281ff0f911e06c6aea45705405ccd"
"3757c8a101f1ffdf23fdce1b20ad1f004c29916b1525071ff1ceaff6daa74386"
"d0f6c94195df01bec62624c392d7e5419db5fbb6edf468f19025398248e8cf12"
"899bf572d93e90f9c2e81cf72628ddd5dbee0d97d65dae005b6a19fa59fbf3f2"
"d2caf4e2c1b5b80ecac76847c234c1043e38f4820159f28a6ef76b5b0abc05a9"
"2737b9f9068054e8701ab432936bf526c786f4580543f9728fec42a03bba3562"
"ccecf4b304a2ebae3c87408efe8fdd14bebd83c9c918ca817c06f9e3992eec29"
"c52756ea1e93c6e80c44ca73684a7fae16251d1225142aec416925c35de6aee4"
"59801dfabd9f3336939d88d688c95b277b0b6102818100de01abfa65d2fad26f"
"fe3f576d757f8ce6bdfe08bdc71334620e87b27a2ca9cdca93d83191812dd668"
"96aa25e3b87ea598a8e8153cc0cedef5ab80b1f5baafac9cc1b34334ae22f718"
"418663a2448e1b419d2d756f0d5b10195d14aa801fee023ef8b6f6ec658e3889"
"0d0b50e41149863982db73e53a0f1322abada0789b942102818100fbcd4c5249"
"3f2c8094914a38ec0f4a7d3a8ebc0490152584fbd368bdefa047fece5bbf1d2a"
"9427fc5170ffc9e9babe2ba05025d3e1a15733cc5cc77d09f6dcfb72943dca59"
"5273e06c450ad9da30df2b33d752184101f0df1b01c1d3b79b26f81c8fffc819"
"fd36d013a57242a3305957b4da2a09e5455a396d70220cba53268d02818100b1"
"3cc270f093c43cf6be1311984882e11961bb0a7d800e3bf6c0c4e2df19032351"
"44410829b2e8c650cf5fdd49f503deee86826a5a0b4fdcbe63022691184ea1ce"
"aff18e88e330f4f5ff71ebdf233e145288ca3f03beb4e1a06e284e8a65735d85"
"aa885f8f90f03f006352926cd1c4520d5e04177d7ca186545a9d0e0cdba02102"
"818100eafe1b9e27b1876cb03a2f9493e9695119971facfa7261c38be92eb523"
"aee7c1cb002089adb4fae4257559a22c3915454da5bec7d0a86be371739cd0fa"
"bda25a20026cf02d1020086fc2b76fbc8b239b04148d0f098c302966e0eaed15"
"4afcc14c96aed5263c042d88483d2c2773f5cd3e80e3febc334f128d29bafd39"
"de63f9028181008b1f47a2904b823b892de96be128e5228783d0de1e0d8ccc84"
"433d238d9d6cbcc4c6da44447920b63eefcf8ac438b0e5da45ac5acc7b62baa9"
"731fba275c82f8ad311edef33772cb47d2cdf7f87f0039db8d2aca4ec1cee215"
"89d63a61ae9da230a585ae38ea4674dc023aace95fa3c6734f73819056c3ce77"
"5f5bba6c42f121";
static void test_wolfSSH_CTX_UsePrivateKey_buffer(void)
{
#ifndef WOLFSSH_NO_SERVER
WOLFSSH_CTX* ctx;
byte* eccKey;
byte* rsaKey;
byte* lastKey;
word32 eccKeySz, rsaKeySz, lastKeySz;
AssertIntEQ(0, ConvertHexToBin(serverKeyEccDer, &eccKey, &eccKeySz,
serverKeyRsaDer, &rsaKey, &rsaKeySz,
NULL, NULL, NULL, NULL, NULL, NULL));
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL));
AssertNull(ctx->privateKey);
AssertIntEQ(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
/* Fail: all NULL/BAD */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(NULL, NULL, 0, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey);
AssertIntEQ(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
/* Fail: ctx set, others NULL/bad */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, NULL, 0, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey);
AssertIntEQ(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
/* Fail: ctx set, key set, others bad */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx,
rsaKey, 0, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey);
AssertIntEQ(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
/* Fail: ctx set, keySz set, others NULL/bad */
AssertIntNE(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, NULL, 1, TEST_BAD_FORMAT_NEXT));
AssertNull(ctx->privateKey);
AssertIntEQ(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
/* Fail: ctx set, key set, keySz set, format invalid */
AssertIntNE(WS_SUCCESS, wolfSSH_CTX_UsePrivateKey_buffer(ctx,
rsaKey, rsaKeySz, TEST_GOOD_FORMAT_PEM));
AssertNull(ctx->privateKey);
AssertIntEQ(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
/* Pass */
AssertIntEQ(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, eccKey, eccKeySz,
TEST_GOOD_FORMAT_ASN1));
AssertNotNull(ctx->privateKey);
AssertIntNE(0, ctx->privateKeySz);
AssertIntEQ(ECC_SECP256R1, ctx->useEcc);
lastKey = ctx->privateKey;
lastKeySz = ctx->privateKeySz;
AssertIntEQ(WS_SUCCESS,
wolfSSH_CTX_UsePrivateKey_buffer(ctx, rsaKey, rsaKeySz,
TEST_GOOD_FORMAT_ASN1));
AssertNotNull(ctx->privateKey);
AssertIntNE(0, ctx->privateKeySz);
AssertIntEQ(0, ctx->useEcc);
AssertIntEQ(0, (lastKey == ctx->privateKey));
AssertIntNE(lastKeySz, ctx->privateKeySz);
wolfSSH_CTX_free(ctx);
FreeBins(eccKey, rsaKey, NULL, NULL);
#endif /* WOLFSSH_NO_SERVER */
}
2018-07-02 13:02:19 -05:00
#ifdef WOLFSSH_SCP
static int my_ScpRecv(WOLFSSH* ssh, int state, const char* basePath,
const char* fileName, int fileMode, word64 mTime, word64 aTime,
word32 totalFileSz, byte* buf, word32 bufSz, word32 fileOffset,
void* ctx)
{
(void)ssh;
printf("calling scp recv cb with state %d\n", state);
printf("\tbase path = %s\n", basePath);
printf("\tfile name = %s\n", fileName);
printf("\tfile mode = %d\n", fileMode);
printf("\tfile size = %d\n", totalFileSz);
printf("\tfile offset = %d\n", fileOffset);
(void)mTime;
(void)aTime;
(void)buf;
(void)bufSz;
(void)ctx;
return WS_SCP_ABORT; /* error out for test function */
}
#endif
static void test_wolfSSH_SCP_CB(void)
{
#ifdef WOLFSSH_SCP
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
int i = 3, j = 4; /* arbitrary value */
const char err[] = "test setting error msg";
AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(NULL, NULL));
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL));
wolfSSH_SetScpRecv(ctx, my_ScpRecv);
AssertNotNull(ssh = wolfSSH_new(ctx));
wolfSSH_SetScpRecvCtx(ssh, (void*)&i);
AssertIntEQ(i, *(int*)wolfSSH_GetScpRecvCtx(ssh));
wolfSSH_SetScpSendCtx(ssh, (void*)&j);
AssertIntEQ(j, *(int*)wolfSSH_GetScpSendCtx(ssh));
AssertIntNE(j, *(int*)wolfSSH_GetScpRecvCtx(ssh));
AssertIntEQ(wolfSSH_SetScpErrorMsg(ssh, err), WS_SUCCESS);
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
#endif /* WOLFSSH_NO_CLIENT */
}
static void test_wolfSSH_SFTP_SendReadPacket(void)
{
#ifdef WOLFSSH_SFTP
func_args ser;
tcp_ready ready;
int argsCount;
const char* args[10];
WOLFSSH_CTX* ctx = NULL;
WOLFSSH* ssh = NULL;
THREAD_TYPE serThread;
WMEMSET(&ser, 0, sizeof(func_args));
argsCount = 0;
args[argsCount++] = ".";
args[argsCount++] = "-1";
#ifndef USE_WINDOWS_API
args[argsCount++] = "-p";
args[argsCount++] = "0";
#endif
ser.argv = (char**)args;
ser.argc = argsCount;
ser.signal = &ready;
InitTcpReady(ser.signal);
ThreadStart(echoserver_test, (void*)&ser, &serThread);
WaitTcpReady(&ser);
sftp_client_connect(&ctx, &ssh, ready.port);
AssertNotNull(ctx);
AssertNotNull(ssh);
{
WS_SFTPNAME* tmp;
WS_SFTPNAME* current;
byte handle[WOLFSSH_MAX_HANDLE];
word32 handleSz = WOLFSSH_MAX_HANDLE;
const char* currentDir = ".";
byte* out = NULL;
int outSz = 18;
const word32 ofst[2] = {0};
current = wolfSSH_SFTP_LS(ssh, (char*)currentDir);
tmp = current;
while (tmp != NULL) {
if (tmp->atrb.sz[0] > 0) {
if (WMEMCMP(tmp->fName , ".", sizeof(".")) != 0 &&
WMEMCMP(tmp->fName, "..", sizeof("..")) != 0)
break;
}
tmp = tmp->next;
}
out = (byte*)malloc(tmp->atrb.sz[0]);
AssertIntEQ(wolfSSH_SFTP_Open(ssh, tmp->fName, WOLFSSH_FXF_READ, NULL,
handle, &handleSz), WS_SUCCESS);
2019-08-20 14:36:35 -05:00
/* read 18 bytes */
if (tmp->atrb.sz[0] >= 18) {
outSz = 18;
AssertIntEQ(wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz, ofst,
out, outSz), outSz);
}
/* partial read */
outSz = tmp->atrb.sz[0] / 2;
AssertIntEQ(wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz, ofst,
out, outSz), outSz);
2019-08-20 14:36:35 -05:00
/* read all */
outSz = tmp->atrb.sz[0];
AssertIntEQ(wolfSSH_SFTP_SendReadPacket(ssh, handle, handleSz, ofst,
out, outSz), outSz);
free(out);
wolfSSH_SFTP_Close(ssh, handle, handleSz);
wolfSSH_SFTPNAME_list_free(current);
}
AssertIntEQ(wolfSSH_shutdown(ssh), WS_SUCCESS);
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
ThreadJoin(serThread);
#endif
}
#ifdef USE_WINDOWS_API
static byte color_test[] = {
0x1B, 0x5B, 0x34, 0x6D, 0x75, 0x6E, 0x64, 0x65,
0x72, 0x6C, 0x69, 0x6E, 0x65, 0x1B, 0x1B, 0x5B,
0x1B, 0x5B, 0x30, 0x6D, 0x0A, 0x1B, 0x5B, 0x33,
0x31, 0x6D, 0x72, 0x65, 0x64, 0x0A, 0x1B, 0x5B,
0x33, 0x32, 0x6D, 0x67, 0x72, 0x65, 0x65, 0x6E,
0x0A, 0x1B, 0x5B, 0x33, 0x33, 0x6D, 0x79, 0x65,
0x6C, 0x6C, 0x6F, 0x77, 0x0A, 0x1B, 0x5B, 0x32,
0x32, 0x6D, 0x69, 0x6E, 0x74, 0x65, 0x6E, 0x73,
0x65, 0x0A, 0x1B, 0x5B, 0x31, 0x6D, 0x62, 0x6F,
0x6C, 0x64, 0x0A, 0x1B, 0x5B, 0x33, 0x34, 0x6D,
0x62, 0x6C, 0x75, 0x65, 0x0A, 0x1B, 0x5B, 0x33,
0x35, 0x6D, 0x6D, 0x61, 0x67, 0x65, 0x6E, 0x74,
0x61, 0x0A, 0x1B, 0x5B, 0x33, 0x36, 0x6D, 0x63,
0x79, 0x61, 0x6E, 0x0A, 0x1B, 0x5B, 0x33, 0x37,
0x6D, 0x77, 0x68, 0x69, 0x74, 0x65, 0x0A, 0x1B,
0x5B, 0x30, 0x6D, 0x6E, 0x6F, 0x72, 0x6D, 0x61,
0x6C, 0x0A, 0x1B, 0x5B, 0x34, 0x30, 0x6D, 0x62,
0x6C, 0x61, 0x63, 0x6B, 0x20, 0x62, 0x67, 0x0A,
0x1B, 0x5B, 0x34, 0x31, 0x6D, 0x72, 0x65, 0x64,
0x20, 0x62, 0x67, 0x0A, 0x1B, 0x5B, 0x34, 0x32,
0x6D, 0x67, 0x72, 0x65, 0x65, 0x6E, 0x20, 0x62,
0x67, 0x0A, 0x1B, 0x5B, 0x34, 0x33, 0x6D, 0x62,
0x72, 0x6F, 0x77, 0x6E, 0x20, 0x62, 0x67, 0x0A,
0x1B, 0x5B, 0x34, 0x34, 0x6D, 0x62, 0x6C, 0x75,
0x65, 0x20, 0x62, 0x67, 0x0A, 0x1B, 0x5B, 0x34,
0x35, 0x6D, 0x6D, 0x61, 0x67, 0x65, 0x6E, 0x74,
0x61, 0x20, 0x62, 0x67, 0x0A, 0x1B, 0x5B, 0x34,
0x36, 0x6D, 0x63, 0x79, 0x61, 0x6E, 0x20, 0x62,
0x67, 0x0A, 0x1B, 0x5B, 0x34, 0x37, 0x6D, 0x77,
0x68, 0x69, 0x74, 0x65, 0x20, 0x62, 0x67, 0x0A,
0x1B, 0x5B, 0x34, 0x39, 0x6D, 0x64, 0x65, 0x66,
0x61, 0x75, 0x6C, 0x74, 0x20, 0x62, 0x67, 0x0A,
};
#endif /* USE_WINDOWS_API */
static void test_wolfSSH_ConvertConsole(void)
{
#ifdef USE_WINDOWS_API
WOLFSSH_CTX* ctx;
WOLFSSH* ssh;
int i = 3, j = 4; /* arbitrary value */
const char err[] = "test setting error msg";
HANDLE stdoutHandle = GetStdHandle(STD_OUTPUT_HANDLE);
AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(NULL, NULL));
AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL));
AssertNotNull(ssh = wolfSSH_new(ctx));
/* parameter tests */
AssertIntEQ(wolfSSH_ConvertConsole(NULL, stdoutHandle, color_test,
sizeof(color_test)), WS_BAD_ARGUMENT);
AssertIntEQ(wolfSSH_ConvertConsole(ssh, stdoutHandle, NULL,
sizeof(color_test)), WS_BAD_ARGUMENT);
AssertIntEQ(wolfSSH_ConvertConsole(ssh, stdoutHandle, color_test, 1),
WS_WANT_READ);
AssertIntEQ(wolfSSH_ConvertConsole(ssh, stdoutHandle, color_test + 1, 1),
WS_WANT_READ);
AssertIntEQ(wolfSSH_ConvertConsole(ssh, stdoutHandle, color_test + 2,
sizeof(color_test) - 2), WS_SUCCESS);
/* bad esc esc command */
AssertIntEQ(wolfSSH_ConvertConsole(ssh, stdoutHandle, color_test, 1),
WS_WANT_READ);
AssertIntEQ(wolfSSH_ConvertConsole(ssh, stdoutHandle, color_test, 1),
WS_SUCCESS); /* should skip over unknown console code */
wolfSSH_free(ssh);
wolfSSH_CTX_free(ctx);
#endif /* USE_WINDOWS_API */
}
2018-07-02 13:02:19 -05:00
static void test_wstrcat(void)
{
#ifndef WSTRING_USER
char dst[5];
WSTRNCPY(dst, "12", sizeof(dst));
AssertNull(wstrncat(dst, "345", sizeof(dst)));
AssertStrEQ(dst, "12");
AssertNotNull(wstrncat(dst, "67", sizeof(dst)));
AssertStrEQ(dst, "1267");
#endif /* WSTRING_USER */
}
int main(void)
2017-06-13 11:15:44 -05:00
{
AssertIntEQ(wolfSSH_Init(), WS_SUCCESS);
test_wstrcat();
test_wolfSSH_CTX_new();
test_server_wolfSSH_new();
test_client_wolfSSH_new();
test_wolfSSH_set_fd();
IDE Support 1. Added Windows Visual Studio build solution. Includes projects for: * wolfSSH static library * echoserver * unit-test * api-test * 32- and 64-bit debug and release builds for all 2. Made necessary tweaks including adding some wrapper functions so the code compiles for both Linux/macOS and Windows. 3. Fixed a bug in the KDF test where the output buffer wasn't updated when SHA-256 was added. 4. Added the fallthrough attribute for GCC7. 5. Replaced all uses of `uint8_t`, `uint16_t`, and `uint32_t` with the wolfCrypt provided `byte`, `word16`, and `word32`. 6. Split the new channel function into new and init. 7. Added some ECC keys for authentication testing. 8. Moved some functions and includes around. 9. Removed the keying state machine and replaced with a flag. 10. Added rekey trigger if the client sends *CTRL-F* to echoserver. 11. Moved the sequence number increase outside `CreateMac()`. Incremented if the packet was successfully created. This way the sequence number is incremented when using AES-GCM. 12. Removed the redundant function `SendText()`. 13. Renamed the `clientId` related functions and data members to `protoId` to keep things role agnostic. 14. Changed all references of `clientKey` and `serverKey` to `keys` and `peerKeys`. 15. Updated `GenerateKeys()` to generate `keys` and `peerKeys` appropriately based on the endpoint side. 16. Added the wolfSSL style _test.h_ file to group shared example functions in one place. 17. Changed the echoserver to be similar to wolfSSL's where the code may be included without the main function in another executable. Note: This commit is a squash of more than a dozen commits. IDE support was added to the client branch, but the client branch is on hold. There were many changes in the client branch that are needed going forward. The code at the head of the client branch was copied over to the IDE branch, and the client code either deleted or removed from the build.
2017-09-12 13:26:54 -05:00
test_wolfSSH_SetUsername();
test_wolfSSH_ConvertConsole();
test_wolfSSH_CTX_UsePrivateKey_buffer();
2018-07-02 13:02:19 -05:00
/* SCP tests */
test_wolfSSH_SCP_CB();
/* SFTP tests */
test_wolfSSH_SFTP_SendReadPacket();
AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS);
2017-06-13 11:15:44 -05:00
return 0;
}