1 /*
2    Copyright (c) 2006, 2012, Oracle and/or its affiliates.
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; version 2 of the License.
7 
8    This program is distributed in the hope that it will be useful,
9    but WITHOUT ANY WARRANTY; without even the implied warranty of
10    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11    GNU General Public License for more details.
12 
13    You should have received a copy of the GNU General Public License
14    along with this program; see the file COPYING. If not, write to the
15    Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston,
16    MA  02110-1335  USA.
17 */
18 
19 // test.hpp
20 
21 #ifndef yaSSL_TEST_HPP
22 #define yaSSL_TEST_HPP
23 
24 #include "runtime.hpp"
25 #include "error.hpp"
26 #include <stdio.h>
27 #include <stdlib.h>
28 #include <assert.h>
29 
30 //#define NON_BLOCKING  // test server and client example (not echos)
31 
32 #ifdef _WIN32
33     #include <winsock2.h>
34     #include <process.h>
35     #ifdef TEST_IPV6            // don't require newer SDK for IPV4
36 	    #include <ws2tcpip.h>
37         #include <wspiapi.h>
38     #endif
39     #define SOCKET_T unsigned int
40 #else
41     #include <string.h>
42     #include <unistd.h>
43     #include <netinet/in.h>
44     #include <arpa/inet.h>
45     #include <sys/ioctl.h>
46     #include <sys/time.h>
47     #include <sys/types.h>
48     #include <sys/socket.h>
49     #ifdef TEST_IPV6
50         #include <netdb.h>
51     #endif
52     #include <pthread.h>
53 #ifdef NON_BLOCKING
54     #include <fcntl.h>
55 #endif
56     #define SOCKET_T int
57 #endif /* _WIN32 */
58 #include "openssl/ssl.h"   /* openssl compatibility test */
59 
60 
61 #ifdef _MSC_VER
62     // disable conversion warning
63     // 4996 warning to use MS extensions e.g., strcpy_s instead of strncpy
64     #pragma warning(disable:4244 4996)
65 #endif
66 
67 
68 #if !defined(_SOCKLEN_T) && (defined(_WIN32) || defined(__APPLE__))
69     typedef int socklen_t;
70 #endif
71 
72 
73 // Check type of third arg to accept
74 #if defined(__hpux)
75 // HPUX uses int* for third parameter to accept
76     typedef int*       ACCEPT_THIRD_T;
77 #else
78     typedef socklen_t* ACCEPT_THIRD_T;
79 #endif
80 
81 
82 #ifdef TEST_IPV6
83     typedef sockaddr_in6 SOCKADDR_IN_T;
84     #define AF_INET_V    AF_INET6
85 #else
86     typedef sockaddr_in  SOCKADDR_IN_T;
87     #define AF_INET_V    AF_INET
88 #endif
89 
90 
91 // Check if _POSIX_THREADS should be forced
92 #if !defined(_POSIX_THREADS) && defined(__hpux)
93 // HPUX does not define _POSIX_THREADS as it's not _fully_ implemented
94 #define _POSIX_THREADS
95 #endif
96 
97 
98 #ifndef _POSIX_THREADS
99     typedef unsigned int  THREAD_RETURN;
100     typedef HANDLE        THREAD_TYPE;
101     #define YASSL_API __stdcall
102 #else
103     typedef void*         THREAD_RETURN;
104     typedef pthread_t     THREAD_TYPE;
105     #define YASSL_API
106 #endif
107 
108 
109 struct tcp_ready {
110 #ifdef _POSIX_THREADS
111     pthread_mutex_t mutex_;
112     pthread_cond_t  cond_;
113     bool            ready_;   // predicate
114 
tcp_readytcp_ready115     tcp_ready() : ready_(false)
116     {
117         pthread_mutex_init(&mutex_, 0);
118         pthread_cond_init(&cond_, 0);
119     }
120 
~tcp_readytcp_ready121     ~tcp_ready()
122     {
123         pthread_mutex_destroy(&mutex_);
124         pthread_cond_destroy(&cond_);
125     }
126 #endif
127 };
128 
129 
130 struct func_args {
131     int    argc;
132     char** argv;
133     int    return_code;
134     const char* file_ready;
135     tcp_ready* signal_;
136 
func_argsfunc_args137     func_args(int c = 0, char** v = 0) : argc(c), argv(v), file_ready(0) {}
138 
SetSignalfunc_args139     void SetSignal(tcp_ready* p) { signal_ = p; }
140 };
141 
142 typedef THREAD_RETURN YASSL_API THREAD_FUNC(void*);
143 
144 void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*);
145 void join_thread(THREAD_TYPE);
146 
147 // yaSSL
148 const char* const    yasslIP      = "127.0.0.1";
149 const unsigned short yasslPort    =  11111;
150 const unsigned short proxyPort    =  12345;
151 
152 
153 // client
154 const char* const cert = "../certs/client-cert.pem";
155 const char* const key  = "../certs/client-key.pem";
156 
157 const char* const certSuite = "../../certs/client-cert.pem";
158 const char* const keySuite  = "../../certs/client-key.pem";
159 
160 const char* const certDebug = "../../../certs/client-cert.pem";
161 const char* const keyDebug  = "../../../certs/client-key.pem";
162 
163 
164 // server
165 const char* const svrCert = "../certs/server-cert.pem";
166 const char* const svrKey  = "../certs/server-key.pem";
167 
168 const char* const svrCert2 = "../../certs/server-cert.pem";
169 const char* const svrKey2  = "../../certs/server-key.pem";
170 
171 const char* const svrCert3 = "../../../certs/server-cert.pem";
172 const char* const svrKey3  = "../../../certs/server-key.pem";
173 
174 
175 // server dsa
176 const char* const dsaCert = "../certs/dsa-cert.pem";
177 const char* const dsaKey  = "../certs/dsa1024.der";
178 
179 const char* const dsaCert2 = "../../certs/dsa-cert.pem";
180 const char* const dsaKey2  = "../../certs/dsa1024.der";
181 
182 const char* const dsaCert3 = "../../../certs/dsa-cert.pem";
183 const char* const dsaKey3  = "../../../certs/dsa1024.der";
184 
185 
186 // CA
187 const char* const caCert  = "../certs/ca-cert.pem";
188 const char* const caCert2 = "../../certs/ca-cert.pem";
189 const char* const caCert3 = "../../../certs/ca-cert.pem";
190 
191 
192 using namespace yaSSL;
193 
194 
err_sys(const char * msg)195 inline void err_sys(const char* msg)
196 {
197     printf("yassl error: %s\n", msg);
198     exit(EXIT_FAILURE);
199 }
200 
201 
202 extern "C" {
203   static int PasswordCallBack(char*, int, int, void*);
204 }
205 
206 
PasswordCallBack(char * passwd,int sz,int rw,void * userdata)207 static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata)
208 {
209     strncpy(passwd, "yassl123", sz);
210     return 8;
211 }
212 
213 
store_ca(SSL_CTX * ctx)214 inline void store_ca(SSL_CTX* ctx)
215 {
216     // To allow testing from serveral dirs
217     if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS)
218         if (SSL_CTX_load_verify_locations(ctx, caCert2, 0) != SSL_SUCCESS)
219             if (SSL_CTX_load_verify_locations(ctx, caCert3, 0) != SSL_SUCCESS)
220                 err_sys("failed to use certificate: certs/cacert.pem");
221 
222     // load client CA for server verify
223     if (SSL_CTX_load_verify_locations(ctx, cert, 0) != SSL_SUCCESS)
224         if (SSL_CTX_load_verify_locations(ctx, certSuite, 0) != SSL_SUCCESS)
225             if (SSL_CTX_load_verify_locations(ctx, certDebug,0) != SSL_SUCCESS)
226                 err_sys("failed to use certificate: certs/client-cert.pem");
227 
228     // DSA cert
229     if (SSL_CTX_load_verify_locations(ctx, dsaCert, 0) != SSL_SUCCESS)
230         if (SSL_CTX_load_verify_locations(ctx, dsaCert2, 0) != SSL_SUCCESS)
231             if (SSL_CTX_load_verify_locations(ctx, dsaCert3, 0) != SSL_SUCCESS)
232                 err_sys("failed to use certificate: certs/dsa-cert.pem");
233 
234 }
235 
236 
237 // client
set_certs(SSL_CTX * ctx)238 inline void set_certs(SSL_CTX* ctx)
239 {
240     store_ca(ctx);
241     SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
242 
243     // To allow testing from serveral dirs
244     if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)
245         != SSL_SUCCESS)
246         if (SSL_CTX_use_certificate_file(ctx, certSuite, SSL_FILETYPE_PEM)
247             != SSL_SUCCESS)
248             if (SSL_CTX_use_certificate_file(ctx, certDebug, SSL_FILETYPE_PEM)
249                 != SSL_SUCCESS)
250                 err_sys("failed to use certificate: certs/client-cert.pem");
251 
252     // To allow testing from several dirs
253     if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)
254          != SSL_SUCCESS)
255          if (SSL_CTX_use_PrivateKey_file(ctx, keySuite, SSL_FILETYPE_PEM)
256             != SSL_SUCCESS)
257                 if (SSL_CTX_use_PrivateKey_file(ctx,keyDebug,SSL_FILETYPE_PEM)
258                     != SSL_SUCCESS)
259                     err_sys("failed to use key file: certs/client-key.pem");
260 }
261 
262 
263 // server
set_serverCerts(SSL_CTX * ctx)264 inline void set_serverCerts(SSL_CTX* ctx)
265 {
266     store_ca(ctx);
267     SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
268 
269     // To allow testing from serveral dirs
270     if (SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)
271         != SSL_SUCCESS)
272         if (SSL_CTX_use_certificate_file(ctx, svrCert2, SSL_FILETYPE_PEM)
273             != SSL_SUCCESS)
274             if (SSL_CTX_use_certificate_file(ctx, svrCert3, SSL_FILETYPE_PEM)
275                 != SSL_SUCCESS)
276                 err_sys("failed to use certificate: certs/server-cert.pem");
277 
278     // To allow testing from several dirs
279     if (SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)
280          != SSL_SUCCESS)
281          if (SSL_CTX_use_PrivateKey_file(ctx, svrKey2, SSL_FILETYPE_PEM)
282             != SSL_SUCCESS)
283                 if (SSL_CTX_use_PrivateKey_file(ctx, svrKey3,SSL_FILETYPE_PEM)
284                     != SSL_SUCCESS)
285                     err_sys("failed to use key file: certs/server-key.pem");
286 }
287 
288 
289 // dsa server
set_dsaServerCerts(SSL_CTX * ctx)290 inline void set_dsaServerCerts(SSL_CTX* ctx)
291 {
292     store_ca(ctx);
293 
294     // To allow testing from serveral dirs
295     if (SSL_CTX_use_certificate_file(ctx, dsaCert, SSL_FILETYPE_PEM)
296         != SSL_SUCCESS)
297         if (SSL_CTX_use_certificate_file(ctx, dsaCert2, SSL_FILETYPE_PEM)
298             != SSL_SUCCESS)
299             if (SSL_CTX_use_certificate_file(ctx, dsaCert3, SSL_FILETYPE_PEM)
300                 != SSL_SUCCESS)
301                 err_sys("failed to use certificate: certs/dsa-cert.pem");
302 
303     // To allow testing from several dirs
304     if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey, SSL_FILETYPE_ASN1)
305          != SSL_SUCCESS)
306          if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey2, SSL_FILETYPE_ASN1)
307             != SSL_SUCCESS)
308                 if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey3,SSL_FILETYPE_ASN1)
309                     != SSL_SUCCESS)
310                     err_sys("failed to use key file: certs/dsa1024.der");
311 }
312 
313 
set_args(int & argc,char ** & argv,func_args & args)314 inline void set_args(int& argc, char**& argv, func_args& args)
315 {
316     argc = args.argc;
317     argv = args.argv;
318     args.return_code = -1; // error state
319 }
320 
321 
set_file_ready(const char * name,func_args & args)322 inline void set_file_ready(const char* name, func_args& args)
323 {
324     args.file_ready = name;
325 }
326 
327 
tcp_set_nonblocking(SOCKET_T & sockfd)328 inline void tcp_set_nonblocking(SOCKET_T& sockfd)
329 {
330 #ifdef NON_BLOCKING
331     #ifdef _WIN32
332         unsigned long blocking = 1;
333         int ret = ioctlsocket(sockfd, FIONBIO, &blocking);
334     #else
335         int flags = fcntl(sockfd, F_GETFL, 0);
336         int ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
337     #endif
338 #endif
339 }
340 
341 
tcp_socket(SOCKET_T & sockfd,SOCKADDR_IN_T & addr)342 inline void tcp_socket(SOCKET_T& sockfd, SOCKADDR_IN_T& addr)
343 {
344     sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
345     memset(&addr, 0, sizeof(addr));
346 
347 #ifdef TEST_IPV6
348     addr.sin6_family = AF_INET_V;
349     addr.sin6_port = htons(yasslPort);
350     addr.sin6_addr = in6addr_loopback;
351 
352     /* // for external testing later
353     addrinfo hints;
354     memset(&hints, 0, sizeof(hints));
355     hints.ai_family   = AF_INET_V;
356     hints.ai_socktype = SOCK_STREAM;
357     hints.ai_flags    = AI_PASSIVE;
358 
359     getaddrinfo(yasslIP6, yasslPortStr, &hints, info);
360     // then use info connect(sockfd, info->ai_addr, info->ai_addrlen)
361 
362     if (*info == 0)
363         err_sys("getaddrinfo failed");
364         */   // end external testing later
365 #else
366     addr.sin_family = AF_INET_V;
367 #ifdef YASSL_PROXY_PORT
368     addr.sin_port = htons(proxyPort);
369 #else
370     addr.sin_port = htons(yasslPort);
371 #endif
372     addr.sin_addr.s_addr = inet_addr(yasslIP);
373 #endif
374 
375 }
376 
377 
tcp_close(SOCKET_T & sockfd)378 inline void tcp_close(SOCKET_T& sockfd)
379 {
380 #ifdef _WIN32
381     closesocket(sockfd);
382 #else
383     close(sockfd);
384 #endif
385     sockfd = (SOCKET_T) -1;
386 }
387 
388 
tcp_connect(SOCKET_T & sockfd)389 inline void tcp_connect(SOCKET_T& sockfd)
390 {
391     SOCKADDR_IN_T addr;
392     tcp_socket(sockfd, addr);
393 
394     if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) {
395         tcp_close(sockfd);
396         err_sys("tcp connect failed");
397     }
398 }
399 
400 
tcp_listen(SOCKET_T & sockfd)401 inline void tcp_listen(SOCKET_T& sockfd)
402 {
403     SOCKADDR_IN_T addr;
404     tcp_socket(sockfd, addr);
405 
406 #ifndef _WIN32
407     int       on  = 1;
408     socklen_t len = sizeof(on);
409     setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
410 #endif
411 
412     if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) {
413         tcp_close(sockfd);
414         err_sys("tcp bind failed");
415     }
416     if (listen(sockfd, 3) != 0) {
417         tcp_close(sockfd);
418         err_sys("tcp listen failed");
419     }
420 }
421 
422 
create_ready_file(func_args & args)423 inline void create_ready_file(func_args& args)
424 {
425     FILE* f = fopen(args.file_ready, "w+");
426 
427     if (f) {
428         fputs("ready", f);
429         fclose(f);
430     }
431 }
432 
433 
tcp_accept(SOCKET_T & sockfd,SOCKET_T & clientfd,func_args & args)434 inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args)
435 {
436     tcp_listen(sockfd);
437 
438     SOCKADDR_IN_T client;
439     socklen_t client_len = sizeof(client);
440 
441 #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER)
442     // signal ready to tcp_accept
443     tcp_ready& ready = *args.signal_;
444     pthread_mutex_lock(&ready.mutex_);
445     ready.ready_ = true;
446     pthread_cond_signal(&ready.cond_);
447     pthread_mutex_unlock(&ready.mutex_);
448 #endif
449 
450     if (args.file_ready)
451         create_ready_file(args);
452 
453     clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len);
454 
455     if (clientfd == (SOCKET_T) -1) {
456         tcp_close(sockfd);
457         err_sys("tcp accept failed");
458     }
459 
460 #ifdef NON_BLOCKING
461     tcp_set_nonblocking(clientfd);
462 #endif
463 }
464 
465 
showPeer(SSL * ssl)466 inline void showPeer(SSL* ssl)
467 {
468     X509* peer = SSL_get_peer_certificate(ssl);
469     if (peer) {
470         char* issuer  = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0);
471         char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0);
472 
473         X509_NAME_ENTRY* se = NULL;
474         ASN1_STRING*     sd = NULL;
475         char*            subCN = NULL;
476 
477         X509_NAME* sub = X509_get_subject_name(peer);
478         int lastpos = -1;
479         if (sub)
480             lastpos = X509_NAME_get_index_by_NID(sub, NID_commonName, lastpos);
481         if (lastpos >= 0) {
482             se = X509_NAME_get_entry(sub, lastpos);
483             if (se)
484                 sd = X509_NAME_ENTRY_get_data(se);
485             if (sd)
486                 subCN = (char*)ASN1_STRING_data(sd);
487         }
488 
489         printf("peer's cert info:\n issuer : %s\n subject: %s\n"
490                " subject cn: %s\n", issuer, subject, subCN);
491 
492         free(subject);
493         free(issuer);
494 
495     }
496     else
497         printf("peer has no cert!\n");
498 }
499 
500 
501 
set_tmpDH(SSL_CTX * ctx)502 inline DH* set_tmpDH(SSL_CTX* ctx)
503 {
504     static unsigned char dh1024_p[] =
505     {
506         0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
507         0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
508         0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
509         0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
510         0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
511         0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
512         0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
513         0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
514         0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
515         0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
516         0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
517     };
518 
519     static unsigned char dh1024_g[] =
520     {
521       0x02,
522     };
523 
524     DH* dh;
525     if ( (dh = DH_new()) ) {
526         dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0);
527         dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0);
528     }
529     if (!dh->p || !dh->g) {
530         DH_free(dh);
531         dh = 0;
532     }
533     SSL_CTX_set_tmp_dh(ctx, dh);
534     return dh;
535 }
536 
537 
verify_callback(int preverify_ok,X509_STORE_CTX * ctx)538 inline int verify_callback(int preverify_ok, X509_STORE_CTX* ctx)
539 {
540     X509* err_cert = X509_STORE_CTX_get_current_cert(ctx);
541     int   err      = X509_STORE_CTX_get_error(ctx);
542     int   depth    = X509_STORE_CTX_get_error_depth(ctx);
543 
544     // test allow self signed
545     if (err_cert && depth == 0 && err == TaoCrypt::SIG_OTHER_E)
546         return 1;
547 
548     return 0;
549 }
550 
551 
552 #endif // yaSSL_TEST_HPP
553 
554