ssh

Dependents:   OS

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_ */