ssh
Diff: wolfssh/test.h
- Revision:
- 0:c4152c628df5
--- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/wolfssh/test.h Mon Nov 25 14:24:05 2019 +0000 @@ -0,0 +1,471 @@ +/* test.h */ + +#pragma once + +#ifndef _WOLFSSH_TEST_H_ +#define _WOLFSSH_TEST_H_ + + +#include <stdio.h> +/*#include <stdlib.h>*/ +#include <ctype.h> +/*#include <wolfssh/error.h>*/ + +#ifdef USE_WINDOWS_API + #include <winsock2.h> + #include <process.h> + #include <assert.h> + #ifdef TEST_IPV6 /* don't require newer SDK for IPV4 */ + #include <ws2tcpip.h> + #include <wspiapi.h> + #endif + #define SOCKET_T SOCKET +#else /* USE_WINDOWS_API */ + #include <unistd.h> + #include <netdb.h> + #include <netinet/in.h> + //#include <netinet/tcp.h> + #include <arpa/inet.h> + #include <sys/ioctl.h> + #include <sys/socket.h> + #include <pthread.h> + #include <fcntl.h> + #ifndef SO_NOSIGPIPE // FIX: ESP32 + #include <signal.h> /* ignore SIGPIPE */ + #endif + #define SOCKET_T int +#endif /* USE_WINDOWS_API */ + + +/* Socket Handling */ +#ifndef WOLFSSH_SOCKET_INVALID +#ifdef USE_WINDOWS_API + #define WOLFSSH_SOCKET_INVALID ((SOCKET_T)INVALID_SOCKET) +#elif defined(WOLFSSH_TIRTOS) + #define WOLFSSH_SOCKET_INVALID ((SOCKET_T)-1) +#else + #define WOLFSSH_SOCKET_INVALID (SOCKET_T)(0) +#endif +#endif /* WOLFSSH_SOCKET_INVALID */ + +#ifndef WOLFSSL_SOCKET_IS_INVALID +#if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS) + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID) +#else + #define WOLFSSL_SOCKET_IS_INVALID(s) ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID) +#endif +#endif /* WOLFSSL_SOCKET_IS_INVALID */ + + +#if defined(__MACH__) || defined(USE_WINDOWS_API) + #ifndef _SOCKLEN_T + typedef int socklen_t; + #endif +#endif + + +#ifdef USE_WINDOWS_API + #define WCLOSESOCKET(s) closesocket(s) + #define WSTARTTCP() do { WSADATA wsd; WSAStartup(0x0002, &wsd); } while(0) +#else + #define WCLOSESOCKET(s) close(s) + #define WSTARTTCP() +#endif + + +#ifdef SINGLE_THREADED + typedef unsigned int THREAD_RETURN; + typedef void* THREAD_TYPE; + #define WOLFSSH_THREAD +#else + #if defined(_POSIX_THREADS) && !defined(__MINGW32__) + typedef void* THREAD_RETURN; + typedef pthread_t THREAD_TYPE; + #define WOLFSSH_THREAD + #define INFINITE -1 + #define WAIT_OBJECT_0 0L + #else + typedef unsigned int THREAD_RETURN; + typedef intptr_t THREAD_TYPE; + #define WOLFSSH_THREAD __stdcall + #endif +#endif + +#ifdef TEST_IPV6 + typedef struct sockaddr_in6 SOCKADDR_IN_T; + #define AF_INET_V AF_INET6 +#else + typedef struct sockaddr_in SOCKADDR_IN_T; + #define AF_INET_V AF_INET +#endif + + +#define serverKeyRsaPemFile "./keys/server-key-rsa.pem" + + +typedef struct tcp_ready { + word16 ready; /* predicate */ + word16 port; + char* srfName; /* server ready file name */ +#if defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_t mutex; + pthread_cond_t cond; +#endif +} tcp_ready; + + +static INLINE void InitTcpReady(tcp_ready* ready) +{ + ready->ready = 0; + ready->port = 0; + ready->srfName = NULL; +#ifdef SINGLE_THREADED +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_init(&ready->mutex, 0); + pthread_cond_init(&ready->cond, 0); +#endif +} + + +static INLINE void FreeTcpReady(tcp_ready* ready) +{ +#ifdef SINGLE_THREADED + (void)ready; +#elif defined(_POSIX_THREADS) && !defined(__MINGW32__) + pthread_mutex_destroy(&ready->mutex); + pthread_cond_destroy(&ready->cond); +#else + (void)ready; +#endif +} + + +typedef struct func_args { + int argc; + char** argv; + int return_code; + tcp_ready* signal; + WS_CallbackUserAuth user_auth; +} func_args; + + +typedef THREAD_RETURN WOLFSSH_THREAD THREAD_FUNC(void*); +void ThreadStart(THREAD_FUNC, void*, THREAD_TYPE*); +void ThreadJoin(THREAD_TYPE); +void ThreadDetach(THREAD_TYPE); +void WaitTcpReady(func_args*); + + +#ifndef TEST_IPV6 + static const char* const wolfSshIp = "127.0.0.1"; +#else /* TEST_IPV6 */ + static const char* const wolfSshIp = "::1"; +#endif /* TEST_IPV6 */ +static const word16 wolfSshPort = 22222; + + +#ifdef __GNUC__ + #define WS_NORETURN __attribute__((noreturn)) +#else + #define WS_NORETURN +#endif + +static INLINE WS_NORETURN void err_sys(const char* msg) +{ + printf("wolfSSH error: %s\n", msg); + +#ifndef __GNUC__ + /* scan-build (which pretends to be gnuc) can get confused and think the + * msg pointer can be null even when hardcoded and then it won't exit, + * making null pointer checks above the err_sys() call useless. + * We could just always exit() but some compilers will complain about no + * possible return, with gcc we know the attribute to handle that with + * WS_NORETURN. */ + if (msg) +#endif + { + exit(EXIT_FAILURE); + } +} + + +#define MY_EX_USAGE 2 + +extern int myoptind; +extern char* myoptarg; + +static INLINE int mygetopt(int argc, char** argv, const char* optstring) +{ + static char* next = NULL; + + char c; + char* cp; + + if (myoptind == 0) + next = NULL; /* we're starting new/over */ + + if (next == NULL || *next == '\0') { + if (myoptind == 0) + myoptind++; + + if (myoptind >= argc || argv[myoptind][0] != '-' || + argv[myoptind][1] == '\0') { + myoptarg = NULL; + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + if (strcmp(argv[myoptind], "--") == 0) { + myoptind++; + myoptarg = NULL; + + if (myoptind < argc) + myoptarg = argv[myoptind]; + + return -1; + } + + next = argv[myoptind]; + next++; /* skip - */ + myoptind++; + } + + c = *next++; + /* The C++ strchr can return a different value */ + cp = (char*)strchr(optstring, c); + + if (cp == NULL || c == ':') + return '?'; + + cp++; + + if (*cp == ':') { + if (*next != '\0') { + myoptarg = next; + next = NULL; + } + else if (myoptind < argc) { + myoptarg = argv[myoptind]; + myoptind++; + } + else + return '?'; + } + + return c; +} + + +#ifdef USE_WINDOWS_API + #pragma warning(push) + #pragma warning(disable:4996) + /* For Windows builds, disable compiler warnings for: + * - 4996: deprecated function */ +#endif + +static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer, + word16 port) +{ + int useLookup = 0; + (void)useLookup; + + memset(addr, 0, sizeof(SOCKADDR_IN_T)); + +#ifndef TEST_IPV6 + /* peer could be in human readable form */ + if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) { + #ifdef CYASSL_MDK_ARM + int err; + struct hostent* entry = gethostbyname(peer, &err); + #else + struct hostent* entry = gethostbyname(peer); + #endif + + if (entry) { + memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0], + entry->h_length); + useLookup = 1; + } + else + err_sys("no entry for host"); + } +#endif + +#ifndef TEST_IPV6 + #if defined(CYASSL_MDK_ARM) + addr->sin_family = PF_INET; + #else + addr->sin_family = AF_INET_V; + #endif + addr->sin_port = htons(port); + if ((size_t)peer == INADDR_ANY) + addr->sin_addr.s_addr = INADDR_ANY; + else { + if (!useLookup) + addr->sin_addr.s_addr = inet_addr(peer); + } +#else + addr->sin6_family = AF_INET_V; + addr->sin6_port = htons(port); + if ((size_t)peer == INADDR_ANY) + addr->sin6_addr = in6addr_any; + else { + #ifdef HAVE_GETADDRINFO + struct addrinfo hints; + struct addrinfo* answer = NULL; + int ret; + char strPort[80]; + + memset(&hints, 0, sizeof(hints)); + + hints.ai_family = AF_INET_V; + hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM; + hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP; + + WSNPRINTF(strPort, sizeof(strPort), "%d", port); + strPort[79] = '\0'; + + ret = getaddrinfo(peer, strPort, &hints, &answer); + if (ret < 0 || answer == NULL) + err_sys("getaddrinfo failed"); + + memcpy(addr, answer->ai_addr, answer->ai_addrlen); + freeaddrinfo(answer); + #else + printf("no ipv6 getaddrinfo, loopback only tests/examples\n"); + addr->sin6_addr = in6addr_loopback; + #endif + } +#endif +} + +#ifdef USE_WINDOWS_API + #pragma warning(pop) +#endif + + +static INLINE void tcp_socket(SOCKET_T* sockFd) +{ + *sockFd = socket(AF_INET_V, SOCK_STREAM, 0); + +#ifdef USE_WINDOWS_API + if (*sockFd == INVALID_SOCKET) + err_sys("socket failed\n"); +#else + if (*sockFd < 0) + err_sys("socket failed\n"); +#endif + +#ifndef USE_WINDOWS_API +#ifdef SO_NOSIGPIPE + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockFd, SOL_SOCKET, SO_NOSIGPIPE, &on, len); + if (res < 0) + err_sys("setsockopt SO_NOSIGPIPE failed\n"); + } +#elif defined(CYASSL_MDK_ARM) + /* nothing to define */ +#else /* no S_NOSIGPIPE */ + // signal(SIGPIPE, SIG_IGN); // FIX: ESP32 +#endif /* S_NOSIGPIPE */ + +#if defined(TCP_NODELAY) + { + int on = 1; + socklen_t len = sizeof(on); + int res = setsockopt(*sockFd, IPPROTO_TCP, TCP_NODELAY, &on, len); + if (res < 0) + err_sys("setsockopt TCP_NODELAY failed\n"); + } +#endif +#endif /* USE_WINDOWS_API */ +} + + +#ifndef XNTOHS + #define XNTOHS(a) ntohs((a)) +#endif + + +static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr) +{ + SOCKADDR_IN_T addr; + + /* don't use INADDR_ANY by default, firewall may block, make user switch + on */ + build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSshIp), *port); + tcp_socket(sockfd); + +#if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\ + && !defined(WOLFSSL_KEIL_TCP_NET) + { + int res, on = 1; + socklen_t len = sizeof(on); + res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len); + if (res < 0) + err_sys("setsockopt SO_REUSEADDR failed\n"); + } +#endif + + + if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) + err_sys("tcp bind failed"); + if (listen(*sockfd, 5) != 0) + err_sys("tcp listen failed"); + #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS) + if (*port == 0) { + socklen_t len = sizeof(addr); + if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) { + #ifndef TEST_IPV6 + *port = XNTOHS(addr.sin_port); + #else + *port = XNTOHS(addr.sin6_port); + #endif + } + } + #endif +} + + +/* Wolf Root Directory Helper */ +/* KEIL-RL File System does not support relative directory */ +#if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS) + /* Maximum depth to search for WolfSSL root */ + #define MAX_WOLF_ROOT_DEPTH 5 + + static INLINE int ChangeToWolfSshRoot(void) + { + #if !defined(NO_FILESYSTEM) + int depth, res; + WFILE* file; + for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) { + if (WFOPEN(&file, serverKeyRsaPemFile, "rb") == 0) { + WFCLOSE(file); + return depth; + } + #ifdef USE_WINDOWS_API + res = SetCurrentDirectoryA("..\\"); + #else + res = chdir("../"); + #endif + if (res < 0) { + printf("chdir to ../ failed!\n"); + break; + } + } + + err_sys("wolfSSH root not found"); + return -1; + #else + return 0; + #endif + } +#endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOL +FSSL_TIRTOS) */ + + +#endif /* _WOLFSSH_TEST_H_ */