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