MySQL 5.6.14 Source Code Document
 All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Friends Macros Groups Pages
test.hpp
1 /*
2  Copyright (c) 2006, 2012, Oracle and/or its affiliates. All rights reserved.
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-1301 USA.
17 */
18 
19 // test.hpp
20 
21 #ifndef yaSSL_TEST_HPP
22 #define yaSSL_TEST_HPP
23 
24 #include "runtime.hpp"
25 #include "openssl/ssl.h" /* openssl compatibility test */
26 #include "error.hpp"
27 #include <stdio.h>
28 #include <stdlib.h>
29 #include <assert.h>
30 
31 //#define NON_BLOCKING // test server and client example (not echos)
32 
33 #ifdef _WIN32
34  #include <winsock2.h>
35  #include <process.h>
36  #ifdef TEST_IPV6 // don't require newer SDK for IPV4
37  #include <ws2tcpip.h>
38  #include <wspiapi.h>
39  #endif
40  #define SOCKET_T unsigned int
41 #else
42  #include <string.h>
43  #include <unistd.h>
44  #include <netinet/in.h>
45  #include <arpa/inet.h>
46  #include <sys/ioctl.h>
47  #include <sys/time.h>
48  #include <sys/types.h>
49  #include <sys/socket.h>
50  #ifdef TEST_IPV6
51  #include <netdb.h>
52  #endif
53  #include <pthread.h>
54 #ifdef NON_BLOCKING
55  #include <fcntl.h>
56 #endif
57  #define SOCKET_T int
58 #endif /* _WIN32 */
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 
115  tcp_ready() : ready_(false)
116  {
117  pthread_mutex_init(&mutex_, 0);
118  pthread_cond_init(&cond_, 0);
119  }
120 
121  ~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  tcp_ready* signal_;
135 
136  func_args(int c = 0, char** v = 0) : argc(c), argv(v) {}
137 
138  void SetSignal(tcp_ready* p) { signal_ = p; }
139 };
140 
141 typedef THREAD_RETURN YASSL_API THREAD_FUNC(void*);
142 
143 void start_thread(THREAD_FUNC, func_args*, THREAD_TYPE*);
144 void join_thread(THREAD_TYPE);
145 
146 // yaSSL
147 const char* const yasslIP = "127.0.0.1";
148 const unsigned short yasslPort = 11111;
149 
150 
151 // client
152 const char* const cert = "../certs/client-cert.pem";
153 const char* const key = "../certs/client-key.pem";
154 
155 const char* const certSuite = "../../certs/client-cert.pem";
156 const char* const keySuite = "../../certs/client-key.pem";
157 
158 const char* const certDebug = "../../../certs/client-cert.pem";
159 const char* const keyDebug = "../../../certs/client-key.pem";
160 
161 
162 // server
163 const char* const svrCert = "../certs/server-cert.pem";
164 const char* const svrKey = "../certs/server-key.pem";
165 
166 const char* const svrCert2 = "../../certs/server-cert.pem";
167 const char* const svrKey2 = "../../certs/server-key.pem";
168 
169 const char* const svrCert3 = "../../../certs/server-cert.pem";
170 const char* const svrKey3 = "../../../certs/server-key.pem";
171 
172 
173 // server dsa
174 const char* const dsaCert = "../certs/dsa-cert.pem";
175 const char* const dsaKey = "../certs/dsa512.der";
176 
177 const char* const dsaCert2 = "../../certs/dsa-cert.pem";
178 const char* const dsaKey2 = "../../certs/dsa512.der";
179 
180 const char* const dsaCert3 = "../../../certs/dsa-cert.pem";
181 const char* const dsaKey3 = "../../../certs/dsa512.der";
182 
183 
184 // CA
185 const char* const caCert = "../certs/ca-cert.pem";
186 const char* const caCert2 = "../../certs/ca-cert.pem";
187 const char* const caCert3 = "../../../certs/ca-cert.pem";
188 
189 
190 using namespace yaSSL;
191 
192 
193 inline void err_sys(const char* msg)
194 {
195  printf("yassl error: %s\n", msg);
196  exit(EXIT_FAILURE);
197 }
198 
199 
200 extern "C" {
201  static int PasswordCallBack(char*, int, int, void*);
202 }
203 
204 
205 static int PasswordCallBack(char* passwd, int sz, int rw, void* userdata)
206 {
207  strncpy(passwd, "yassl123", sz);
208  return 8;
209 }
210 
211 
212 inline void store_ca(SSL_CTX* ctx)
213 {
214  // To allow testing from serveral dirs
215  if (SSL_CTX_load_verify_locations(ctx, caCert, 0) != SSL_SUCCESS)
216  if (SSL_CTX_load_verify_locations(ctx, caCert2, 0) != SSL_SUCCESS)
217  if (SSL_CTX_load_verify_locations(ctx, caCert3, 0) != SSL_SUCCESS)
218  err_sys("failed to use certificate: certs/cacert.pem");
219 
220  // load client CA for server verify
221  if (SSL_CTX_load_verify_locations(ctx, cert, 0) != SSL_SUCCESS)
222  if (SSL_CTX_load_verify_locations(ctx, certSuite, 0) != SSL_SUCCESS)
223  if (SSL_CTX_load_verify_locations(ctx, certDebug,0) != SSL_SUCCESS)
224  err_sys("failed to use certificate: certs/client-cert.pem");
225 }
226 
227 
228 // client
229 inline void set_certs(SSL_CTX* ctx)
230 {
231  store_ca(ctx);
232  SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
233 
234  // To allow testing from serveral dirs
235  if (SSL_CTX_use_certificate_file(ctx, cert, SSL_FILETYPE_PEM)
236  != SSL_SUCCESS)
237  if (SSL_CTX_use_certificate_file(ctx, certSuite, SSL_FILETYPE_PEM)
238  != SSL_SUCCESS)
239  if (SSL_CTX_use_certificate_file(ctx, certDebug, SSL_FILETYPE_PEM)
240  != SSL_SUCCESS)
241  err_sys("failed to use certificate: certs/client-cert.pem");
242 
243  // To allow testing from several dirs
244  if (SSL_CTX_use_PrivateKey_file(ctx, key, SSL_FILETYPE_PEM)
245  != SSL_SUCCESS)
246  if (SSL_CTX_use_PrivateKey_file(ctx, keySuite, SSL_FILETYPE_PEM)
247  != SSL_SUCCESS)
248  if (SSL_CTX_use_PrivateKey_file(ctx,keyDebug,SSL_FILETYPE_PEM)
249  != SSL_SUCCESS)
250  err_sys("failed to use key file: certs/client-key.pem");
251 }
252 
253 
254 // server
255 inline void set_serverCerts(SSL_CTX* ctx)
256 {
257  store_ca(ctx);
258  SSL_CTX_set_default_passwd_cb(ctx, PasswordCallBack);
259 
260  // To allow testing from serveral dirs
261  if (SSL_CTX_use_certificate_file(ctx, svrCert, SSL_FILETYPE_PEM)
262  != SSL_SUCCESS)
263  if (SSL_CTX_use_certificate_file(ctx, svrCert2, SSL_FILETYPE_PEM)
264  != SSL_SUCCESS)
265  if (SSL_CTX_use_certificate_file(ctx, svrCert3, SSL_FILETYPE_PEM)
266  != SSL_SUCCESS)
267  err_sys("failed to use certificate: certs/server-cert.pem");
268 
269  // To allow testing from several dirs
270  if (SSL_CTX_use_PrivateKey_file(ctx, svrKey, SSL_FILETYPE_PEM)
271  != SSL_SUCCESS)
272  if (SSL_CTX_use_PrivateKey_file(ctx, svrKey2, SSL_FILETYPE_PEM)
273  != SSL_SUCCESS)
274  if (SSL_CTX_use_PrivateKey_file(ctx, svrKey3,SSL_FILETYPE_PEM)
275  != SSL_SUCCESS)
276  err_sys("failed to use key file: certs/server-key.pem");
277 }
278 
279 
280 // dsa server
281 inline void set_dsaServerCerts(SSL_CTX* ctx)
282 {
283  store_ca(ctx);
284 
285  // To allow testing from serveral dirs
286  if (SSL_CTX_use_certificate_file(ctx, dsaCert, SSL_FILETYPE_PEM)
287  != SSL_SUCCESS)
288  if (SSL_CTX_use_certificate_file(ctx, dsaCert2, SSL_FILETYPE_PEM)
289  != SSL_SUCCESS)
290  if (SSL_CTX_use_certificate_file(ctx, dsaCert3, SSL_FILETYPE_PEM)
291  != SSL_SUCCESS)
292  err_sys("failed to use certificate: certs/dsa-cert.pem");
293 
294  // To allow testing from several dirs
295  if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey, SSL_FILETYPE_ASN1)
296  != SSL_SUCCESS)
297  if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey2, SSL_FILETYPE_ASN1)
298  != SSL_SUCCESS)
299  if (SSL_CTX_use_PrivateKey_file(ctx, dsaKey3,SSL_FILETYPE_ASN1)
300  != SSL_SUCCESS)
301  err_sys("failed to use key file: certs/dsa512.der");
302 }
303 
304 
305 inline void set_args(int& argc, char**& argv, func_args& args)
306 {
307  argc = args.argc;
308  argv = args.argv;
309  args.return_code = -1; // error state
310 }
311 
312 
313 inline void tcp_set_nonblocking(SOCKET_T& sockfd)
314 {
315 #ifdef NON_BLOCKING
316  #ifdef _WIN32
317  unsigned long blocking = 1;
318  int ret = ioctlsocket(sockfd, FIONBIO, &blocking);
319  #else
320  int flags = fcntl(sockfd, F_GETFL, 0);
321  int ret = fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
322  #endif
323 #endif
324 }
325 
326 
327 inline void tcp_socket(SOCKET_T& sockfd, SOCKADDR_IN_T& addr)
328 {
329  sockfd = socket(AF_INET_V, SOCK_STREAM, 0);
330  memset(&addr, 0, sizeof(addr));
331 
332 #ifdef TEST_IPV6
333  addr.sin6_family = AF_INET_V;
334  addr.sin6_port = htons(yasslPort);
335  addr.sin6_addr = in6addr_loopback;
336 
337  /* // for external testing later
338  addrinfo hints;
339  memset(&hints, 0, sizeof(hints));
340  hints.ai_family = AF_INET_V;
341  hints.ai_socktype = SOCK_STREAM;
342  hints.ai_flags = AI_PASSIVE;
343 
344  getaddrinfo(yasslIP6, yasslPortStr, &hints, info);
345  // then use info connect(sockfd, info->ai_addr, info->ai_addrlen)
346 
347  if (*info == 0)
348  err_sys("getaddrinfo failed");
349  */ // end external testing later
350 #else
351  addr.sin_family = AF_INET_V;
352  addr.sin_port = htons(yasslPort);
353  addr.sin_addr.s_addr = inet_addr(yasslIP);
354 #endif
355 
356 }
357 
358 
359 inline void tcp_close(SOCKET_T& sockfd)
360 {
361 #ifdef _WIN32
362  closesocket(sockfd);
363 #else
364  close(sockfd);
365 #endif
366  sockfd = (SOCKET_T) -1;
367 }
368 
369 
370 inline void tcp_connect(SOCKET_T& sockfd)
371 {
372  SOCKADDR_IN_T addr;
373  tcp_socket(sockfd, addr);
374 
375  if (connect(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) {
376  tcp_close(sockfd);
377  err_sys("tcp connect failed");
378  }
379 }
380 
381 
382 inline void tcp_listen(SOCKET_T& sockfd)
383 {
384  SOCKADDR_IN_T addr;
385  tcp_socket(sockfd, addr);
386 
387 #ifndef _WIN32
388  int on = 1;
389  socklen_t len = sizeof(on);
390  setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &on, len);
391 #endif
392 
393  if (bind(sockfd, (const sockaddr*)&addr, sizeof(addr)) != 0) {
394  tcp_close(sockfd);
395  err_sys("tcp bind failed");
396  }
397  if (listen(sockfd, 3) != 0) {
398  tcp_close(sockfd);
399  err_sys("tcp listen failed");
400  }
401 }
402 
403 
404 
405 inline void tcp_accept(SOCKET_T& sockfd, SOCKET_T& clientfd, func_args& args)
406 {
407  tcp_listen(sockfd);
408 
409  SOCKADDR_IN_T client;
410  socklen_t client_len = sizeof(client);
411 
412 #if defined(_POSIX_THREADS) && defined(NO_MAIN_DRIVER)
413  // signal ready to tcp_accept
414  tcp_ready& ready = *args.signal_;
415  pthread_mutex_lock(&ready.mutex_);
416  ready.ready_ = true;
417  pthread_cond_signal(&ready.cond_);
418  pthread_mutex_unlock(&ready.mutex_);
419 #endif
420 
421  clientfd = accept(sockfd, (sockaddr*)&client, (ACCEPT_THIRD_T)&client_len);
422 
423  if (clientfd == (SOCKET_T) -1) {
424  tcp_close(sockfd);
425  err_sys("tcp accept failed");
426  }
427 
428 #ifdef NON_BLOCKING
429  tcp_set_nonblocking(clientfd);
430 #endif
431 }
432 
433 
434 inline void showPeer(SSL* ssl)
435 {
436  X509* peer = SSL_get_peer_certificate(ssl);
437  if (peer) {
438  char* issuer = X509_NAME_oneline(X509_get_issuer_name(peer), 0, 0);
439  char* subject = X509_NAME_oneline(X509_get_subject_name(peer), 0, 0);
440 
441  printf("peer's cert info:\n issuer : %s\n subject: %s\n", issuer,
442  subject);
443  free(subject);
444  free(issuer);
445  }
446  else
447  printf("peer has no cert!\n");
448 }
449 
450 
451 
452 inline DH* set_tmpDH(SSL_CTX* ctx)
453 {
454  static unsigned char dh1024_p[] =
455  {
456  0xE6, 0x96, 0x9D, 0x3D, 0x49, 0x5B, 0xE3, 0x2C, 0x7C, 0xF1, 0x80, 0xC3,
457  0xBD, 0xD4, 0x79, 0x8E, 0x91, 0xB7, 0x81, 0x82, 0x51, 0xBB, 0x05, 0x5E,
458  0x2A, 0x20, 0x64, 0x90, 0x4A, 0x79, 0xA7, 0x70, 0xFA, 0x15, 0xA2, 0x59,
459  0xCB, 0xD5, 0x23, 0xA6, 0xA6, 0xEF, 0x09, 0xC4, 0x30, 0x48, 0xD5, 0xA2,
460  0x2F, 0x97, 0x1F, 0x3C, 0x20, 0x12, 0x9B, 0x48, 0x00, 0x0E, 0x6E, 0xDD,
461  0x06, 0x1C, 0xBC, 0x05, 0x3E, 0x37, 0x1D, 0x79, 0x4E, 0x53, 0x27, 0xDF,
462  0x61, 0x1E, 0xBB, 0xBE, 0x1B, 0xAC, 0x9B, 0x5C, 0x60, 0x44, 0xCF, 0x02,
463  0x3D, 0x76, 0xE0, 0x5E, 0xEA, 0x9B, 0xAD, 0x99, 0x1B, 0x13, 0xA6, 0x3C,
464  0x97, 0x4E, 0x9E, 0xF1, 0x83, 0x9E, 0xB5, 0xDB, 0x12, 0x51, 0x36, 0xF7,
465  0x26, 0x2E, 0x56, 0xA8, 0x87, 0x15, 0x38, 0xDF, 0xD8, 0x23, 0xC6, 0x50,
466  0x50, 0x85, 0xE2, 0x1F, 0x0D, 0xD5, 0xC8, 0x6B,
467  };
468 
469  static unsigned char dh1024_g[] =
470  {
471  0x02,
472  };
473 
474  DH* dh;
475  if ( (dh = DH_new()) ) {
476  dh->p = BN_bin2bn(dh1024_p, sizeof(dh1024_p), 0);
477  dh->g = BN_bin2bn(dh1024_g, sizeof(dh1024_g), 0);
478  }
479  if (!dh->p || !dh->g) {
480  DH_free(dh);
481  dh = 0;
482  }
483  SSL_CTX_set_tmp_dh(ctx, dh);
484  return dh;
485 }
486 
487 
488 inline int verify_callback(int preverify_ok, X509_STORE_CTX* ctx)
489 {
490  X509* err_cert = X509_STORE_CTX_get_current_cert(ctx);
491  int err = X509_STORE_CTX_get_error(ctx);
492  int depth = X509_STORE_CTX_get_error_depth(ctx);
493 
494  // test allow self signed
495  if (err_cert && depth == 0 && err == TaoCrypt::SIG_OTHER_E)
496  return 1;
497 
498  return 0;
499 }
500 
501 
502 #endif // yaSSL_TEST_HPP
503