/* api.c * * Copyright (C) 2014-2020 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 . */ #include #include #include #ifdef WOLFSSH_SCP #include #endif #ifdef WOLFSSH_SFTP #define WOLFSSH_TEST_LOCKING #define WOLFSSH_TEST_THREADING #define WOLFSSH_TEST_SERVER #define WOLFSSH_TEST_ECHOSERVER #include #include "examples/echoserver/echoserver.h" #endif /* for echoserver test cases */ int myoptind = 0; char* myoptarg = NULL; #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); } static void test_wolfSSH_SetUsername(void) { #ifndef WOLFSSH_NO_CLIENT WOLFSSH_CTX* ctx; WOLFSSH* ssh; const char username[] = "johnny"; const char empty[] = ""; const char* name = NULL; AssertIntNE(WS_SUCCESS, wolfSSH_SetUsername(NULL, NULL)); AssertIntNE(WS_SUCCESS, wolfSSH_SetUsernameRaw(NULL, NULL, 0)); AssertNotNull(ctx = wolfSSH_CTX_new(WOLFSSH_ENDPOINT_SERVER, NULL)); AssertNotNull(ssh = wolfSSH_new(ctx)); AssertIntEQ(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)); AssertIntNE(WS_SUCCESS, wolfSSH_SetUsernameRaw(ssh, NULL, 0)); AssertIntNE(WS_SUCCESS, wolfSSH_SetUsernameRaw(ssh, NULL, 23)); AssertIntNE(WS_SUCCESS, wolfSSH_SetUsernameRaw(ssh, (const byte*)empty, 0)); AssertIntNE(WS_SUCCESS, wolfSSH_SetUsernameRaw(ssh, (const byte*)username, 0)); wolfSSH_free(ssh); AssertNotNull(ssh = wolfSSH_new(ctx)); AssertIntEQ(WS_SUCCESS, wolfSSH_SetUsername(ssh, username)); AssertIntEQ(WS_SUCCESS, wolfSSH_SetUsernameRaw(ssh, (const byte*)username, (word32)strlen(username))); AssertNotNull((name = wolfSSH_GetUsername(ssh))); AssertIntEQ(0, strcmp(username, name)); 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 }; #ifndef WOLFSSH_NO_ECDSA_SHA2_NISTP256 static const char serverKeyEccDer[] = "307702010104206109990b79d25f285a0f5d15cca15654f92b3987212da77d85" "7bb87f38c66dd5a00a06082a8648ce3d030107a144034200048113ffa42bb79c" "45747a834c61f33fad26cf22cda9a3bca561b47ce662d4c2f755439a31fb8011" "20b5124b24f578d7fd22ef4635f005586b5f63c8da1bc4f569"; static const int serverKeyEccCurveId = ECC_SECP256R1; #elif defined(WOLFSSH_NO_ECDSA_SHA2_NISTP384) static const char serverKeyEccDer[] = "3081a402010104303eadd2bbbf05a7be3a3f7c28151289de5bb3644d7011761d" "b56f2a0362fba64f98e64ff986dc4fb8efdb2d6b8da57142a00706052b810400" "22a1640362000438d62be418ff573fd0e020d48876c4e1121dfb2d6ebee4895d" "7724316d46a23105873f2986d5c712803a6f471ab86850eb063e108961349cf8" "b4c6a4cf5e97bd7e51e975e3e9217261506eb9cf3c493d3eb88d467b5f27ebab" "2161c00066febd"; static const int serverKeyEccCurveId = ECC_SECP384R1; #elif defined(WOLFSSH_NO_ECDSA_SHA2_NISTP521) static const char serverKeyEccDer[] = "3081dc0201010442004ca4d86428d9400e7b2df3912eb996c195895043af92e8" "6de70ae4df46f22a291a6bb2748aae82580df6c39f49b3ed82f1789ece1b657d" "45438cff156534354575a00706052b81040023a18189038186000401f8d0a7c3" "c58d841957969f213a94f3da550edf76d8dd171531f35bb069c8bc300d6f6b37" "d18046a9717f2c6f59519c827095b29a6313306218c235769400d0f96d000a19" "3ba346652beb409a9a45c597a3ed932dd5aaae96bf2f317e5a7ac7458b3c6cdb" "aa90c355382cdfcdca7377d92eb20a5e8c74237ca5a345b19e3f1a2290b154"; static const int serverKeyEccCurveId = ECC_SECP521R1; #endif #ifndef WOLFSSH_NO_SSH_RSA_SHA1 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"; #endif static void test_wolfSSH_CTX_UsePrivateKey_buffer(void) { #ifndef WOLFSSH_NO_SERVER WOLFSSH_CTX* ctx; #ifdef HAVE_ECC byte* eccKey; word32 eccKeySz; #endif #ifndef NO_RSA byte* rsaKey; word32 rsaKeySz; #endif byte* lastKey = NULL; word32 lastKeySz = 0; #ifdef HAVE_ECC AssertIntEQ(0, ConvertHexToBin(serverKeyEccDer, &eccKey, &eccKeySz, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); #endif #ifndef NO_RSA AssertIntEQ(0, ConvertHexToBin(serverKeyRsaDer, &rsaKey, &rsaKeySz, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL)); #endif 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, lastKey, 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, lastKey, lastKeySz, TEST_GOOD_FORMAT_PEM)); AssertNull(ctx->privateKey); AssertIntEQ(0, ctx->privateKeySz); AssertIntEQ(0, ctx->useEcc); /* Pass */ #ifdef HAVE_ECC lastKey = ctx->privateKey; lastKeySz = ctx->privateKeySz; AssertIntEQ(WS_SUCCESS, wolfSSH_CTX_UsePrivateKey_buffer(ctx, eccKey, eccKeySz, TEST_GOOD_FORMAT_ASN1)); AssertNotNull(ctx->privateKey); AssertIntNE(0, ctx->privateKeySz); AssertIntEQ(serverKeyEccCurveId, ctx->useEcc); AssertIntEQ(0, (lastKey == ctx->privateKey)); AssertIntNE(lastKeySz, ctx->privateKeySz); #endif #ifndef NO_RSA 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); #endif wolfSSH_CTX_free(ctx); #ifdef HAVE_ECC FreeBins(eccKey, NULL, NULL, NULL); #endif #ifndef NO_RSA FreeBins(rsaKey, NULL, NULL, NULL); #endif #endif /* WOLFSSH_NO_SERVER */ } #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) && (tmp->atrb.flags & WOLFSSH_FILEATRB_PERM) && !(tmp->atrb.per & 0x4000)) { break; } tmp = tmp->next; } if (tmp != NULL) { out = (byte*)malloc(tmp->atrb.sz[0]); AssertIntEQ(wolfSSH_SFTP_Open(ssh, tmp->fName, WOLFSSH_FXF_READ, NULL, handle, &handleSz), WS_SUCCESS); /* 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); /* 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 */ } 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) { AssertIntEQ(wolfSSH_Init(), WS_SUCCESS); test_wstrcat(); test_wolfSSH_CTX_new(); test_server_wolfSSH_new(); test_client_wolfSSH_new(); test_wolfSSH_set_fd(); test_wolfSSH_SetUsername(); test_wolfSSH_ConvertConsole(); test_wolfSSH_CTX_UsePrivateKey_buffer(); /* SCP tests */ test_wolfSSH_SCP_CB(); /* SFTP tests */ test_wolfSSH_SFTP_SendReadPacket(); AssertIntEQ(wolfSSH_Cleanup(), WS_SUCCESS); return 0; }