ssh

Dependents:   OS

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers test.h Source File

test.h

00001 /* test.h */
00002 
00003 #pragma once
00004 
00005 #ifndef _WOLFSSH_TEST_H_
00006 #define _WOLFSSH_TEST_H_
00007 
00008 
00009 #include <stdio.h>
00010 /*#include <stdlib.h>*/
00011 #include <ctype.h>
00012 /*#include <wolfssh/error.h>*/
00013 
00014 #ifdef USE_WINDOWS_API
00015     #include <winsock2.h>
00016     #include <process.h>
00017     #include <assert.h>
00018     #ifdef TEST_IPV6            /* don't require newer SDK for IPV4 */
00019         #include <ws2tcpip.h>
00020         #include <wspiapi.h>
00021     #endif
00022     #define SOCKET_T SOCKET
00023 #else /* USE_WINDOWS_API */
00024     #include <unistd.h>
00025     #include <netdb.h>
00026     #include <netinet/in.h>
00027     //#include <netinet/tcp.h>
00028     #include <arpa/inet.h>
00029     #include <sys/ioctl.h>
00030     #include <sys/socket.h>
00031     #include <pthread.h>
00032     #include <fcntl.h>
00033     #ifndef SO_NOSIGPIPE // FIX: ESP32
00034         #include <signal.h>  /* ignore SIGPIPE */
00035     #endif
00036     #define SOCKET_T int
00037 #endif /* USE_WINDOWS_API */
00038 
00039 
00040 /* Socket Handling */
00041 #ifndef WOLFSSH_SOCKET_INVALID
00042 #ifdef USE_WINDOWS_API
00043     #define WOLFSSH_SOCKET_INVALID  ((SOCKET_T)INVALID_SOCKET)
00044 #elif defined(WOLFSSH_TIRTOS)
00045     #define WOLFSSH_SOCKET_INVALID  ((SOCKET_T)-1)
00046 #else
00047     #define WOLFSSH_SOCKET_INVALID  (SOCKET_T)(0)
00048 #endif
00049 #endif /* WOLFSSH_SOCKET_INVALID */
00050 
00051 #ifndef WOLFSSL_SOCKET_IS_INVALID
00052 #if defined(USE_WINDOWS_API) || defined(WOLFSSL_TIRTOS)
00053     #define WOLFSSL_SOCKET_IS_INVALID(s)  ((SOCKET_T)(s) == WOLFSSL_SOCKET_INVALID)
00054 #else
00055     #define WOLFSSL_SOCKET_IS_INVALID(s)  ((SOCKET_T)(s) < WOLFSSL_SOCKET_INVALID)
00056 #endif
00057 #endif /* WOLFSSL_SOCKET_IS_INVALID */
00058 
00059 
00060 #if defined(__MACH__) || defined(USE_WINDOWS_API)
00061     #ifndef _SOCKLEN_T
00062         typedef int socklen_t;
00063     #endif
00064 #endif
00065 
00066 
00067 #ifdef USE_WINDOWS_API
00068     #define WCLOSESOCKET(s) closesocket(s)
00069     #define WSTARTTCP() do { WSADATA wsd; WSAStartup(0x0002, &wsd); } while(0)
00070 #else
00071     #define WCLOSESOCKET(s) close(s)
00072     #define WSTARTTCP()
00073 #endif
00074 
00075 
00076 #ifdef SINGLE_THREADED
00077     typedef unsigned int  THREAD_RETURN;
00078     typedef void*         THREAD_TYPE;
00079     #define WOLFSSH_THREAD
00080 #else
00081     #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
00082         typedef void*         THREAD_RETURN;
00083         typedef pthread_t     THREAD_TYPE;
00084         #define WOLFSSH_THREAD
00085         #define INFINITE -1
00086         #define WAIT_OBJECT_0 0L
00087     #else
00088         typedef unsigned int  THREAD_RETURN;
00089         typedef intptr_t      THREAD_TYPE;
00090         #define WOLFSSH_THREAD __stdcall
00091     #endif
00092 #endif
00093 
00094 #ifdef TEST_IPV6
00095     typedef struct sockaddr_in6 SOCKADDR_IN_T;
00096     #define AF_INET_V AF_INET6
00097 #else
00098     typedef struct sockaddr_in  SOCKADDR_IN_T;
00099     #define AF_INET_V AF_INET
00100 #endif
00101 
00102 
00103 #define serverKeyRsaPemFile "./keys/server-key-rsa.pem"
00104 
00105 
00106 typedef struct tcp_ready {
00107     word16 ready;     /* predicate */
00108     word16 port;
00109     char* srfName;     /* server ready file name */
00110 #if defined(_POSIX_THREADS) && !defined(__MINGW32__)
00111     pthread_mutex_t mutex;
00112     pthread_cond_t  cond;
00113 #endif
00114 } tcp_ready;
00115 
00116 
00117 static INLINE void InitTcpReady(tcp_ready* ready)
00118 {
00119     ready->ready = 0;
00120     ready->port = 0;
00121     ready->srfName = NULL;
00122 #ifdef SINGLE_THREADED
00123 #elif defined(_POSIX_THREADS) && !defined(__MINGW32__)
00124     pthread_mutex_init(&ready->mutex, 0);
00125     pthread_cond_init(&ready->cond, 0);
00126 #endif
00127 }
00128 
00129 
00130 static INLINE void FreeTcpReady(tcp_ready* ready)
00131 {
00132 #ifdef SINGLE_THREADED
00133     (void)ready;
00134 #elif defined(_POSIX_THREADS) && !defined(__MINGW32__)
00135     pthread_mutex_destroy(&ready->mutex);
00136     pthread_cond_destroy(&ready->cond);
00137 #else
00138     (void)ready;
00139 #endif
00140 }
00141 
00142 
00143 typedef struct func_args {
00144     int    argc;
00145     char** argv;
00146     int    return_code;
00147     tcp_ready* signal;
00148     WS_CallbackUserAuth user_auth;
00149 } func_args;
00150 
00151 
00152 typedef THREAD_RETURN WOLFSSH_THREAD THREAD_FUNC(void*);
00153 void ThreadStart(THREAD_FUNC, void*, THREAD_TYPE*);
00154 void ThreadJoin(THREAD_TYPE);
00155 void ThreadDetach(THREAD_TYPE);
00156 void WaitTcpReady(func_args*);
00157 
00158 
00159 #ifndef TEST_IPV6
00160     static const char* const wolfSshIp = "127.0.0.1";
00161 #else /* TEST_IPV6 */
00162     static const char* const wolfSshIp = "::1";
00163 #endif /* TEST_IPV6 */
00164 static const word16 wolfSshPort = 22222;
00165 
00166 
00167 #ifdef __GNUC__
00168     #define WS_NORETURN __attribute__((noreturn))
00169 #else
00170     #define WS_NORETURN
00171 #endif
00172 
00173 static INLINE WS_NORETURN void err_sys(const char* msg)
00174 {
00175     printf("wolfSSH error: %s\n", msg);
00176 
00177 #ifndef __GNUC__
00178     /* scan-build (which pretends to be gnuc) can get confused and think the
00179      * msg pointer can be null even when hardcoded and then it won't exit,
00180      * making null pointer checks above the err_sys() call useless.
00181      * We could just always exit() but some compilers will complain about no
00182      * possible return, with gcc we know the attribute to handle that with
00183      * WS_NORETURN. */
00184     if (msg)
00185 #endif
00186     {
00187         exit(EXIT_FAILURE);
00188     }
00189 }
00190 
00191 
00192 #define MY_EX_USAGE 2
00193 
00194 extern int   myoptind;
00195 extern char* myoptarg;
00196 
00197 static INLINE int mygetopt(int argc, char** argv, const char* optstring)
00198 {
00199     static char* next = NULL;
00200 
00201     char  c;
00202     char* cp;
00203 
00204     if (myoptind == 0)
00205         next = NULL;   /* we're starting new/over */
00206 
00207     if (next == NULL || *next == '\0') {
00208         if (myoptind == 0)
00209             myoptind++;
00210 
00211         if (myoptind >= argc || argv[myoptind][0] != '-' ||
00212                                 argv[myoptind][1] == '\0') {
00213             myoptarg = NULL;
00214             if (myoptind < argc)
00215                 myoptarg = argv[myoptind];
00216 
00217             return -1;
00218         }
00219 
00220         if (strcmp(argv[myoptind], "--") == 0) {
00221             myoptind++;
00222             myoptarg = NULL;
00223 
00224             if (myoptind < argc)
00225                 myoptarg = argv[myoptind];
00226 
00227             return -1;
00228         }
00229 
00230         next = argv[myoptind];
00231         next++;                  /* skip - */
00232         myoptind++;
00233     }
00234 
00235     c  = *next++;
00236     /* The C++ strchr can return a different value */
00237     cp = (char*)strchr(optstring, c);
00238 
00239     if (cp == NULL || c == ':')
00240         return '?';
00241 
00242     cp++;
00243 
00244     if (*cp == ':') {
00245         if (*next != '\0') {
00246             myoptarg = next;
00247             next     = NULL;
00248         }
00249         else if (myoptind < argc) {
00250             myoptarg = argv[myoptind];
00251             myoptind++;
00252         }
00253         else
00254             return '?';
00255     }
00256 
00257     return c;
00258 }
00259 
00260 
00261 #ifdef USE_WINDOWS_API
00262     #pragma warning(push)
00263     #pragma warning(disable:4996)
00264     /* For Windows builds, disable compiler warnings for:
00265     * - 4996: deprecated function */
00266 #endif
00267 
00268 static INLINE void build_addr(SOCKADDR_IN_T* addr, const char* peer,
00269                               word16 port)
00270 {
00271     int useLookup = 0;
00272     (void)useLookup;
00273 
00274     memset(addr, 0, sizeof(SOCKADDR_IN_T));
00275 
00276 #ifndef TEST_IPV6
00277     /* peer could be in human readable form */
00278     if ( ((size_t)peer != INADDR_ANY) && isalpha((int)peer[0])) {
00279         #ifdef CYASSL_MDK_ARM
00280             int err;
00281             struct hostent* entry = gethostbyname(peer, &err);
00282         #else
00283             struct hostent* entry = gethostbyname(peer);
00284         #endif
00285 
00286         if (entry) {
00287             memcpy(&addr->sin_addr.s_addr, entry->h_addr_list[0],
00288                    entry->h_length);
00289             useLookup = 1;
00290         }
00291         else
00292             err_sys("no entry for host");
00293     }
00294 #endif
00295 
00296 #ifndef TEST_IPV6
00297     #if defined(CYASSL_MDK_ARM)
00298         addr->sin_family = PF_INET;
00299     #else
00300         addr->sin_family = AF_INET_V;
00301     #endif
00302     addr->sin_port = htons(port);
00303     if ((size_t)peer == INADDR_ANY)
00304         addr->sin_addr.s_addr = INADDR_ANY;
00305     else {
00306         if (!useLookup)
00307             addr->sin_addr.s_addr = inet_addr(peer);
00308     }
00309 #else
00310     addr->sin6_family = AF_INET_V;
00311     addr->sin6_port = htons(port);
00312     if ((size_t)peer == INADDR_ANY)
00313         addr->sin6_addr = in6addr_any;
00314     else {
00315         #ifdef HAVE_GETADDRINFO
00316             struct addrinfo  hints;
00317             struct addrinfo* answer = NULL;
00318             int    ret;
00319             char   strPort[80];
00320 
00321             memset(&hints, 0, sizeof(hints));
00322 
00323             hints.ai_family   = AF_INET_V;
00324             hints.ai_socktype = udp ? SOCK_DGRAM : SOCK_STREAM;
00325             hints.ai_protocol = udp ? IPPROTO_UDP : IPPROTO_TCP;
00326 
00327             WSNPRINTF(strPort, sizeof(strPort), "%d", port);
00328             strPort[79] = '\0';
00329 
00330             ret = getaddrinfo(peer, strPort, &hints, &answer);
00331             if (ret < 0 || answer == NULL)
00332                 err_sys("getaddrinfo failed");
00333 
00334             memcpy(addr, answer->ai_addr, answer->ai_addrlen);
00335             freeaddrinfo(answer);
00336         #else
00337             printf("no ipv6 getaddrinfo, loopback only tests/examples\n");
00338             addr->sin6_addr = in6addr_loopback;
00339         #endif
00340     }
00341 #endif
00342 }
00343 
00344 #ifdef USE_WINDOWS_API
00345     #pragma warning(pop)
00346 #endif
00347 
00348 
00349 static INLINE void tcp_socket(SOCKET_T* sockFd)
00350 {
00351     *sockFd = socket(AF_INET_V, SOCK_STREAM, 0);
00352 
00353 #ifdef USE_WINDOWS_API
00354     if (*sockFd == INVALID_SOCKET)
00355         err_sys("socket failed\n");
00356 #else
00357     if (*sockFd < 0)
00358         err_sys("socket failed\n");
00359 #endif
00360 
00361 #ifndef USE_WINDOWS_API
00362 #ifdef SO_NOSIGPIPE
00363     {
00364         int       on = 1;
00365         socklen_t len = sizeof(on);
00366         int       res = setsockopt(*sockFd, SOL_SOCKET, SO_NOSIGPIPE, &on, len);
00367         if (res < 0)
00368             err_sys("setsockopt SO_NOSIGPIPE failed\n");
00369     }
00370 #elif defined(CYASSL_MDK_ARM)
00371     /* nothing to define */
00372 #else  /* no S_NOSIGPIPE */
00373     // signal(SIGPIPE, SIG_IGN); // FIX: ESP32
00374 #endif /* S_NOSIGPIPE */
00375 
00376 #if defined(TCP_NODELAY)
00377     {
00378         int       on = 1;
00379         socklen_t len = sizeof(on);
00380         int       res = setsockopt(*sockFd, IPPROTO_TCP, TCP_NODELAY, &on, len);
00381         if (res < 0)
00382             err_sys("setsockopt TCP_NODELAY failed\n");
00383     }
00384 #endif
00385 #endif  /* USE_WINDOWS_API */
00386 }
00387 
00388 
00389 #ifndef XNTOHS
00390     #define XNTOHS(a) ntohs((a))
00391 #endif
00392 
00393 
00394 static INLINE void tcp_listen(SOCKET_T* sockfd, word16* port, int useAnyAddr)
00395 {
00396     SOCKADDR_IN_T addr;
00397 
00398     /* don't use INADDR_ANY by default, firewall may block, make user switch
00399        on */
00400     build_addr(&addr, (useAnyAddr ? INADDR_ANY : wolfSshIp), *port);
00401     tcp_socket(sockfd);
00402 
00403 #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_MDK_ARM)\
00404                               && !defined(WOLFSSL_KEIL_TCP_NET)
00405     {
00406         int       res, on  = 1;
00407         socklen_t len = sizeof(on);
00408         res = setsockopt(*sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
00409         if (res < 0)
00410             err_sys("setsockopt SO_REUSEADDR failed\n");
00411     }
00412 #endif
00413 
00414 
00415     if (bind(*sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0)
00416         err_sys("tcp bind failed");
00417     if (listen(*sockfd, 5) != 0)
00418         err_sys("tcp listen failed");
00419     #if !defined(USE_WINDOWS_API) && !defined(WOLFSSL_TIRTOS)
00420         if (*port == 0) {
00421             socklen_t len = sizeof(addr);
00422             if (getsockname(*sockfd, (struct sockaddr*)&addr, &len) == 0) {
00423                 #ifndef TEST_IPV6
00424                     *port = XNTOHS(addr.sin_port);
00425                 #else
00426                     *port = XNTOHS(addr.sin6_port);
00427                 #endif
00428             }
00429         }
00430     #endif
00431 }
00432 
00433 
00434 /* Wolf Root Directory Helper */
00435 /* KEIL-RL File System does not support relative directory */
00436 #if !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOLFSSL_TIRTOS)
00437     /* Maximum depth to search for WolfSSL root */
00438     #define MAX_WOLF_ROOT_DEPTH 5
00439 
00440     static INLINE int ChangeToWolfSshRoot(void)
00441     {
00442         #if !defined(NO_FILESYSTEM)
00443             int depth, res;
00444             WFILE* file;
00445             for(depth = 0; depth <= MAX_WOLF_ROOT_DEPTH; depth++) {
00446                 if (WFOPEN(&file, serverKeyRsaPemFile, "rb") == 0) {
00447                     WFCLOSE(file);
00448                     return depth;
00449                 }
00450             #ifdef USE_WINDOWS_API
00451                 res = SetCurrentDirectoryA("..\\");
00452             #else
00453                 res = chdir("../");
00454             #endif
00455                 if (res < 0) {
00456                     printf("chdir to ../ failed!\n");
00457                     break;
00458                 }
00459             }
00460 
00461             err_sys("wolfSSH root not found");
00462             return -1;
00463         #else
00464             return 0;
00465         #endif
00466     }
00467 #endif /* !defined(WOLFSSL_MDK_ARM) && !defined(WOLFSSL_KEIL_FS) && !defined(WOL
00468 FSSL_TIRTOS) */
00469 
00470 
00471 #endif /* _WOLFSSH_TEST_H_ */