Unchecked malloc fixes
[openssl.git] / crypto / threads / mttest.c
1 /* crypto/threads/mttest.c */
2 /* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
3  * All rights reserved.
4  *
5  * This package is an SSL implementation written
6  * by Eric Young (eay@cryptsoft.com).
7  * The implementation was written so as to conform with Netscapes SSL.
8  *
9  * This library is free for commercial and non-commercial use as long as
10  * the following conditions are aheared to.  The following conditions
11  * apply to all code found in this distribution, be it the RC4, RSA,
12  * lhash, DES, etc., code; not just the SSL code.  The SSL documentation
13  * included with this distribution is covered by the same copyright terms
14  * except that the holder is Tim Hudson (tjh@cryptsoft.com).
15  *
16  * Copyright remains Eric Young's, and as such any Copyright notices in
17  * the code are not to be removed.
18  * If this package is used in a product, Eric Young should be given attribution
19  * as the author of the parts of the library used.
20  * This can be in the form of a textual message at program startup or
21  * in documentation (online or textual) provided with the package.
22  *
23  * Redistribution and use in source and binary forms, with or without
24  * modification, are permitted provided that the following conditions
25  * are met:
26  * 1. Redistributions of source code must retain the copyright
27  *    notice, this list of conditions and the following disclaimer.
28  * 2. Redistributions in binary form must reproduce the above copyright
29  *    notice, this list of conditions and the following disclaimer in the
30  *    documentation and/or other materials provided with the distribution.
31  * 3. All advertising materials mentioning features or use of this software
32  *    must display the following acknowledgement:
33  *    "This product includes cryptographic software written by
34  *     Eric Young (eay@cryptsoft.com)"
35  *    The word 'cryptographic' can be left out if the rouines from the library
36  *    being used are not cryptographic related :-).
37  * 4. If you include any Windows specific code (or a derivative thereof) from
38  *    the apps directory (application code) you must include an acknowledgement:
39  *    "This product includes software written by Tim Hudson (tjh@cryptsoft.com)"
40  *
41  * THIS SOFTWARE IS PROVIDED BY ERIC YOUNG ``AS IS'' AND
42  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
43  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
44  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
45  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
46  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
47  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
48  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
49  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
50  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
51  * SUCH DAMAGE.
52  *
53  * The licence and distribution terms for any publically available version or
54  * derivative of this code cannot be changed.  i.e. this code cannot simply be
55  * copied and put under another distribution licence
56  * [including the GNU Public Licence.]
57  */
58
59 #include <stdio.h>
60 #include <stdlib.h>
61 #include <string.h>
62 #include <errno.h>
63 #ifdef LINUX
64 # include <typedefs.h>
65 #endif
66 #ifdef OPENSSL_SYS_WIN32
67 # include <windows.h>
68 #endif
69 #ifdef SOLARIS
70 # include <synch.h>
71 # include <thread.h>
72 #endif
73 #ifdef IRIX
74 # include <ulocks.h>
75 # include <sys/prctl.h>
76 #endif
77 #ifdef PTHREADS
78 # include <pthread.h>
79 #endif
80 #ifdef OPENSSL_SYS_NETWARE
81 # if !defined __int64
82 #  define __int64 long long
83 # endif
84 # include <nwmpk.h>
85 #endif
86 #include <openssl/lhash.h>
87 #include <openssl/crypto.h>
88 #include <openssl/buffer.h>
89 #include "../../e_os.h"
90 #include <openssl/x509.h>
91 #include <openssl/ssl.h>
92 #include <openssl/err.h>
93 #include <openssl/rand.h>
94
95 #ifdef OPENSSL_NO_FP_API
96 # define APPS_WIN16
97 # include "../buffer/bss_file.c"
98 #endif
99
100 #ifdef OPENSSL_SYS_NETWARE
101 # define TEST_SERVER_CERT "/openssl/apps/server.pem"
102 # define TEST_CLIENT_CERT "/openssl/apps/client.pem"
103 #else
104 # define TEST_SERVER_CERT "../../apps/server.pem"
105 # define TEST_CLIENT_CERT "../../apps/client.pem"
106 #endif
107
108 #define MAX_THREAD_NUMBER       100
109
110 int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *xs);
111 void thread_setup(void);
112 void thread_cleanup(void);
113 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx);
114
115 void irix_locking_callback(int mode, int type, char *file, int line);
116 void solaris_locking_callback(int mode, int type, char *file, int line);
117 void win32_locking_callback(int mode, int type, char *file, int line);
118 void pthreads_locking_callback(int mode, int type, char *file, int line);
119 void netware_locking_callback(int mode, int type, char *file, int line);
120 void beos_locking_callback(int mode, int type, const char *file, int line);
121
122 unsigned long irix_thread_id(void);
123 unsigned long solaris_thread_id(void);
124 unsigned long pthreads_thread_id(void);
125 unsigned long netware_thread_id(void);
126 unsigned long beos_thread_id(void);
127
128 #if defined(OPENSSL_SYS_NETWARE)
129 static MPKMutex *lock_cs;
130 static MPKSema ThreadSem;
131 static long *lock_count;
132 #endif
133
134 BIO *bio_err = NULL;
135 BIO *bio_stdout = NULL;
136
137 static char *cipher = NULL;
138 int verbose = 0;
139 #ifdef FIONBIO
140 static int s_nbio = 0;
141 #endif
142
143 int thread_number = 10;
144 int number_of_loops = 10;
145 int reconnect = 0;
146 int cache_stats = 0;
147
148 static const char rnd_seed[] =
149     "string to make the random number generator think it has entropy";
150
151 int doit(char *ctx[4]);
152 static void print_stats(FILE *fp, SSL_CTX *ctx)
153 {
154     fprintf(fp, "%4ld items in the session cache\n",
155             SSL_CTX_sess_number(ctx));
156     fprintf(fp, "%4d client connects (SSL_connect())\n",
157             SSL_CTX_sess_connect(ctx));
158     fprintf(fp, "%4d client connects that finished\n",
159             SSL_CTX_sess_connect_good(ctx));
160     fprintf(fp, "%4d server connects (SSL_accept())\n",
161             SSL_CTX_sess_accept(ctx));
162     fprintf(fp, "%4d server connects that finished\n",
163             SSL_CTX_sess_accept_good(ctx));
164     fprintf(fp, "%4d session cache hits\n", SSL_CTX_sess_hits(ctx));
165     fprintf(fp, "%4d session cache misses\n", SSL_CTX_sess_misses(ctx));
166     fprintf(fp, "%4d session cache timeouts\n", SSL_CTX_sess_timeouts(ctx));
167 }
168
169 static void sv_usage(void)
170 {
171     fprintf(stderr, "usage: ssltest [args ...]\n");
172     fprintf(stderr, "\n");
173     fprintf(stderr, " -server_auth  - check server certificate\n");
174     fprintf(stderr, " -client_auth  - do client authentication\n");
175     fprintf(stderr, " -v            - more output\n");
176     fprintf(stderr, " -CApath arg   - PEM format directory of CA's\n");
177     fprintf(stderr, " -CAfile arg   - PEM format file of CA's\n");
178     fprintf(stderr, " -threads arg  - number of threads\n");
179     fprintf(stderr, " -loops arg    - number of 'connections', per thread\n");
180     fprintf(stderr, " -reconnect    - reuse session-id's\n");
181     fprintf(stderr, " -stats        - server session-id cache stats\n");
182     fprintf(stderr, " -cert arg     - server certificate/key\n");
183     fprintf(stderr, " -ccert arg    - client certificate/key\n");
184     fprintf(stderr, " -ssl3         - just SSLv3n\n");
185 }
186
187 int main(int argc, char *argv[])
188 {
189     char *CApath = NULL, *CAfile = NULL;
190     int badop = 0;
191     int ret = 1;
192     int client_auth = 0;
193     int server_auth = 0;
194     SSL_CTX *s_ctx = NULL;
195     SSL_CTX *c_ctx = NULL;
196     char *scert = TEST_SERVER_CERT;
197     char *ccert = TEST_CLIENT_CERT;
198     SSL_METHOD *ssl_method = SSLv23_method();
199
200     RAND_seed(rnd_seed, sizeof rnd_seed);
201
202     if (bio_err == NULL)
203         bio_err = BIO_new_fp(stderr, BIO_NOCLOSE);
204     if (bio_stdout == NULL)
205         bio_stdout = BIO_new_fp(stdout, BIO_NOCLOSE);
206     argc--;
207     argv++;
208
209     while (argc >= 1) {
210         if (strcmp(*argv, "-server_auth") == 0)
211             server_auth = 1;
212         else if (strcmp(*argv, "-client_auth") == 0)
213             client_auth = 1;
214         else if (strcmp(*argv, "-reconnect") == 0)
215             reconnect = 1;
216         else if (strcmp(*argv, "-stats") == 0)
217             cache_stats = 1;
218         else if (strcmp(*argv, "-ssl3") == 0)
219             ssl_method = SSLv3_method();
220         else if (strcmp(*argv, "-ssl2") == 0)
221             ssl_method = SSLv2_method();
222         else if (strcmp(*argv, "-CApath") == 0) {
223             if (--argc < 1)
224                 goto bad;
225             CApath = *(++argv);
226         } else if (strcmp(*argv, "-CAfile") == 0) {
227             if (--argc < 1)
228                 goto bad;
229             CAfile = *(++argv);
230         } else if (strcmp(*argv, "-cert") == 0) {
231             if (--argc < 1)
232                 goto bad;
233             scert = *(++argv);
234         } else if (strcmp(*argv, "-ccert") == 0) {
235             if (--argc < 1)
236                 goto bad;
237             ccert = *(++argv);
238         } else if (strcmp(*argv, "-threads") == 0) {
239             if (--argc < 1)
240                 goto bad;
241             thread_number = atoi(*(++argv));
242             if (thread_number == 0)
243                 thread_number = 1;
244             if (thread_number > MAX_THREAD_NUMBER)
245                 thread_number = MAX_THREAD_NUMBER;
246         } else if (strcmp(*argv, "-loops") == 0) {
247             if (--argc < 1)
248                 goto bad;
249             number_of_loops = atoi(*(++argv));
250             if (number_of_loops == 0)
251                 number_of_loops = 1;
252         } else {
253             fprintf(stderr, "unknown option %s\n", *argv);
254             badop = 1;
255             break;
256         }
257         argc--;
258         argv++;
259     }
260     if (badop) {
261  bad:
262         sv_usage();
263         goto end;
264     }
265
266     if (cipher == NULL && OPENSSL_issetugid() == 0)
267         cipher = getenv("SSL_CIPHER");
268
269     SSL_load_error_strings();
270     OpenSSL_add_ssl_algorithms();
271
272     c_ctx = SSL_CTX_new(ssl_method);
273     s_ctx = SSL_CTX_new(ssl_method);
274     if ((c_ctx == NULL) || (s_ctx == NULL)) {
275         ERR_print_errors(bio_err);
276         goto end;
277     }
278
279     SSL_CTX_set_session_cache_mode(s_ctx,
280                                    SSL_SESS_CACHE_NO_AUTO_CLEAR |
281                                    SSL_SESS_CACHE_SERVER);
282     SSL_CTX_set_session_cache_mode(c_ctx,
283                                    SSL_SESS_CACHE_NO_AUTO_CLEAR |
284                                    SSL_SESS_CACHE_SERVER);
285
286     if (!SSL_CTX_use_certificate_file(s_ctx, scert, SSL_FILETYPE_PEM)) {
287         ERR_print_errors(bio_err);
288     } else
289         if (!SSL_CTX_use_RSAPrivateKey_file(s_ctx, scert, SSL_FILETYPE_PEM)) {
290         ERR_print_errors(bio_err);
291         goto end;
292     }
293
294     if (client_auth) {
295         SSL_CTX_use_certificate_file(c_ctx, ccert, SSL_FILETYPE_PEM);
296         SSL_CTX_use_RSAPrivateKey_file(c_ctx, ccert, SSL_FILETYPE_PEM);
297     }
298
299     if ((!SSL_CTX_load_verify_locations(s_ctx, CAfile, CApath)) ||
300         (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
301         (!SSL_CTX_load_verify_locations(c_ctx, CAfile, CApath)) ||
302         (!SSL_CTX_set_default_verify_paths(c_ctx))) {
303         fprintf(stderr, "SSL_load_verify_locations\n");
304         ERR_print_errors(bio_err);
305         goto end;
306     }
307
308     if (client_auth) {
309         fprintf(stderr, "client authentication\n");
310         SSL_CTX_set_verify(s_ctx,
311                            SSL_VERIFY_PEER | SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
312                            verify_callback);
313     }
314     if (server_auth) {
315         fprintf(stderr, "server authentication\n");
316         SSL_CTX_set_verify(c_ctx, SSL_VERIFY_PEER, verify_callback);
317     }
318
319     thread_setup();
320     do_threads(s_ctx, c_ctx);
321     thread_cleanup();
322  end:
323
324     if (c_ctx != NULL) {
325         fprintf(stderr, "Client SSL_CTX stats then free it\n");
326         print_stats(stderr, c_ctx);
327         SSL_CTX_free(c_ctx);
328     }
329     if (s_ctx != NULL) {
330         fprintf(stderr, "Server SSL_CTX stats then free it\n");
331         print_stats(stderr, s_ctx);
332         if (cache_stats) {
333             fprintf(stderr, "-----\n");
334             lh_stats(SSL_CTX_sessions(s_ctx), stderr);
335             fprintf(stderr, "-----\n");
336     /*-     lh_node_stats(SSL_CTX_sessions(s_ctx),stderr);
337             fprintf(stderr,"-----\n"); */
338             lh_node_usage_stats(SSL_CTX_sessions(s_ctx), stderr);
339             fprintf(stderr, "-----\n");
340         }
341         SSL_CTX_free(s_ctx);
342         fprintf(stderr, "done free\n");
343     }
344     exit(ret);
345     return (0);
346 }
347
348 #define W_READ  1
349 #define W_WRITE 2
350 #define C_DONE  1
351 #define S_DONE  2
352
353 int ndoit(SSL_CTX *ssl_ctx[2])
354 {
355     int i;
356     int ret;
357     char *ctx[4];
358
359     ctx[0] = (char *)ssl_ctx[0];
360     ctx[1] = (char *)ssl_ctx[1];
361
362     if (reconnect) {
363         ctx[2] = (char *)SSL_new(ssl_ctx[0]);
364         ctx[3] = (char *)SSL_new(ssl_ctx[1]);
365     } else {
366         ctx[2] = NULL;
367         ctx[3] = NULL;
368     }
369
370     fprintf(stdout, "started thread %lu\n", CRYPTO_thread_id());
371     for (i = 0; i < number_of_loops; i++) {
372 /*-     fprintf(stderr,"%4d %2d ctx->ref (%3d,%3d)\n",
373             CRYPTO_thread_id(),i,
374             ssl_ctx[0]->references,
375             ssl_ctx[1]->references); */
376 /*      pthread_delay_np(&tm); */
377
378         ret = doit(ctx);
379         if (ret != 0) {
380             fprintf(stdout, "error[%d] %lu - %d\n",
381                     i, CRYPTO_thread_id(), ret);
382             return (ret);
383         }
384     }
385     fprintf(stdout, "DONE %lu\n", CRYPTO_thread_id());
386     if (reconnect) {
387         SSL_free((SSL *)ctx[2]);
388         SSL_free((SSL *)ctx[3]);
389     }
390 #ifdef OPENSSL_SYS_NETWARE
391     MPKSemaphoreSignal(ThreadSem);
392 #endif
393     return (0);
394 }
395
396 int doit(char *ctx[4])
397 {
398     SSL_CTX *s_ctx, *c_ctx;
399     static char cbuf[200], sbuf[200];
400     SSL *c_ssl = NULL;
401     SSL *s_ssl = NULL;
402     BIO *c_to_s = NULL;
403     BIO *s_to_c = NULL;
404     BIO *c_bio = NULL;
405     BIO *s_bio = NULL;
406     int c_r, c_w, s_r, s_w;
407     int c_want, s_want;
408     int i;
409     int done = 0;
410     int c_write, s_write;
411     int do_server = 0, do_client = 0;
412
413     s_ctx = (SSL_CTX *)ctx[0];
414     c_ctx = (SSL_CTX *)ctx[1];
415
416     if (ctx[2] != NULL)
417         s_ssl = (SSL *)ctx[2];
418     else
419         s_ssl = SSL_new(s_ctx);
420
421     if (ctx[3] != NULL)
422         c_ssl = (SSL *)ctx[3];
423     else
424         c_ssl = SSL_new(c_ctx);
425
426     if ((s_ssl == NULL) || (c_ssl == NULL))
427         goto err;
428
429     c_to_s = BIO_new(BIO_s_mem());
430     s_to_c = BIO_new(BIO_s_mem());
431     if ((s_to_c == NULL) || (c_to_s == NULL))
432         goto err;
433
434     c_bio = BIO_new(BIO_f_ssl());
435     s_bio = BIO_new(BIO_f_ssl());
436     if ((c_bio == NULL) || (s_bio == NULL))
437         goto err;
438
439     SSL_set_connect_state(c_ssl);
440     SSL_set_bio(c_ssl, s_to_c, c_to_s);
441     BIO_set_ssl(c_bio, c_ssl, (ctx[2] == NULL) ? BIO_CLOSE : BIO_NOCLOSE);
442
443     SSL_set_accept_state(s_ssl);
444     SSL_set_bio(s_ssl, c_to_s, s_to_c);
445     BIO_set_ssl(s_bio, s_ssl, (ctx[3] == NULL) ? BIO_CLOSE : BIO_NOCLOSE);
446
447     c_r = 0;
448     s_r = 1;
449     c_w = 1;
450     s_w = 0;
451     c_want = W_WRITE;
452     s_want = 0;
453     c_write = 1, s_write = 0;
454
455     /* We can always do writes */
456     for (;;) {
457         do_server = 0;
458         do_client = 0;
459
460         i = (int)BIO_pending(s_bio);
461         if ((i && s_r) || s_w)
462             do_server = 1;
463
464         i = (int)BIO_pending(c_bio);
465         if ((i && c_r) || c_w)
466             do_client = 1;
467
468         if (do_server && verbose) {
469             if (SSL_in_init(s_ssl))
470                 printf("server waiting in SSL_accept - %s\n",
471                        SSL_state_string_long(s_ssl));
472             else if (s_write)
473                 printf("server:SSL_write()\n");
474             else
475                 printf("server:SSL_read()\n");
476         }
477
478         if (do_client && verbose) {
479             if (SSL_in_init(c_ssl))
480                 printf("client waiting in SSL_connect - %s\n",
481                        SSL_state_string_long(c_ssl));
482             else if (c_write)
483                 printf("client:SSL_write()\n");
484             else
485                 printf("client:SSL_read()\n");
486         }
487
488         if (!do_client && !do_server) {
489             fprintf(stdout, "ERROR IN STARTUP\n");
490             break;
491         }
492         if (do_client && !(done & C_DONE)) {
493             if (c_write) {
494                 i = BIO_write(c_bio, "hello from client\n", 18);
495                 if (i < 0) {
496                     c_r = 0;
497                     c_w = 0;
498                     if (BIO_should_retry(c_bio)) {
499                         if (BIO_should_read(c_bio))
500                             c_r = 1;
501                         if (BIO_should_write(c_bio))
502                             c_w = 1;
503                     } else {
504                         fprintf(stderr, "ERROR in CLIENT\n");
505                         ERR_print_errors_fp(stderr);
506                         return (1);
507                     }
508                 } else if (i == 0) {
509                     fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
510                     return (1);
511                 } else {
512                     /* ok */
513                     c_write = 0;
514                 }
515             } else {
516                 i = BIO_read(c_bio, cbuf, 100);
517                 if (i < 0) {
518                     c_r = 0;
519                     c_w = 0;
520                     if (BIO_should_retry(c_bio)) {
521                         if (BIO_should_read(c_bio))
522                             c_r = 1;
523                         if (BIO_should_write(c_bio))
524                             c_w = 1;
525                     } else {
526                         fprintf(stderr, "ERROR in CLIENT\n");
527                         ERR_print_errors_fp(stderr);
528                         return (1);
529                     }
530                 } else if (i == 0) {
531                     fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
532                     return (1);
533                 } else {
534                     done |= C_DONE;
535 #ifdef undef
536                     fprintf(stdout, "CLIENT:from server:");
537                     fwrite(cbuf, 1, i, stdout);
538                     fflush(stdout);
539 #endif
540                 }
541             }
542         }
543
544         if (do_server && !(done & S_DONE)) {
545             if (!s_write) {
546                 i = BIO_read(s_bio, sbuf, 100);
547                 if (i < 0) {
548                     s_r = 0;
549                     s_w = 0;
550                     if (BIO_should_retry(s_bio)) {
551                         if (BIO_should_read(s_bio))
552                             s_r = 1;
553                         if (BIO_should_write(s_bio))
554                             s_w = 1;
555                     } else {
556                         fprintf(stderr, "ERROR in SERVER\n");
557                         ERR_print_errors_fp(stderr);
558                         return (1);
559                     }
560                 } else if (i == 0) {
561                     fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
562                     return (1);
563                 } else {
564                     s_write = 1;
565                     s_w = 1;
566 #ifdef undef
567                     fprintf(stdout, "SERVER:from client:");
568                     fwrite(sbuf, 1, i, stdout);
569                     fflush(stdout);
570 #endif
571                 }
572             } else {
573                 i = BIO_write(s_bio, "hello from server\n", 18);
574                 if (i < 0) {
575                     s_r = 0;
576                     s_w = 0;
577                     if (BIO_should_retry(s_bio)) {
578                         if (BIO_should_read(s_bio))
579                             s_r = 1;
580                         if (BIO_should_write(s_bio))
581                             s_w = 1;
582                     } else {
583                         fprintf(stderr, "ERROR in SERVER\n");
584                         ERR_print_errors_fp(stderr);
585                         return (1);
586                     }
587                 } else if (i == 0) {
588                     fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
589                     return (1);
590                 } else {
591                     s_write = 0;
592                     s_r = 1;
593                     done |= S_DONE;
594                 }
595             }
596         }
597
598         if ((done & S_DONE) && (done & C_DONE))
599             break;
600 #if defined(OPENSSL_SYS_NETWARE)
601         ThreadSwitchWithDelay();
602 #endif
603     }
604
605     SSL_set_shutdown(c_ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
606     SSL_set_shutdown(s_ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
607
608 #ifdef undef
609     fprintf(stdout, "DONE\n");
610 #endif
611  err:
612     /*
613      * We have to set the BIO's to NULL otherwise they will be free()ed
614      * twice.  Once when th s_ssl is SSL_free()ed and again when c_ssl is
615      * SSL_free()ed. This is a hack required because s_ssl and c_ssl are
616      * sharing the same BIO structure and SSL_set_bio() and SSL_free()
617      * automatically BIO_free non NULL entries. You should not normally do
618      * this or be required to do this
619      */
620
621     if (s_ssl != NULL) {
622         s_ssl->rbio = NULL;
623         s_ssl->wbio = NULL;
624     }
625     if (c_ssl != NULL) {
626         c_ssl->rbio = NULL;
627         c_ssl->wbio = NULL;
628     }
629
630     /* The SSL's are optionally freed in the following calls */
631     if (c_to_s != NULL)
632         BIO_free(c_to_s);
633     if (s_to_c != NULL)
634         BIO_free(s_to_c);
635
636     if (c_bio != NULL)
637         BIO_free(c_bio);
638     if (s_bio != NULL)
639         BIO_free(s_bio);
640     return (0);
641 }
642
643 int MS_CALLBACK verify_callback(int ok, X509_STORE_CTX *ctx)
644 {
645     char *s, buf[256];
646
647     if (verbose) {
648         s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
649                               buf, 256);
650         if (s != NULL) {
651             if (ok)
652                 fprintf(stderr, "depth=%d %s\n", ctx->error_depth, buf);
653             else
654                 fprintf(stderr, "depth=%d error=%d %s\n",
655                         ctx->error_depth, ctx->error, buf);
656         }
657     }
658     return (ok);
659 }
660
661 #define THREAD_STACK_SIZE (16*1024)
662
663 #ifdef OPENSSL_SYS_WIN32
664
665 static HANDLE *lock_cs;
666
667 void thread_setup(void)
668 {
669     int i;
670
671     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
672     for (i = 0; i < CRYPTO_num_locks(); i++) {
673         lock_cs[i] = CreateMutex(NULL, FALSE, NULL);
674     }
675
676     CRYPTO_set_locking_callback((void (*)(int, int, char *, int))
677                                 win32_locking_callback);
678     /* id callback defined */
679 }
680
681 void thread_cleanup(void)
682 {
683     int i;
684
685     CRYPTO_set_locking_callback(NULL);
686     for (i = 0; i < CRYPTO_num_locks(); i++)
687         CloseHandle(lock_cs[i]);
688     OPENSSL_free(lock_cs);
689 }
690
691 void win32_locking_callback(int mode, int type, char *file, int line)
692 {
693     if (mode & CRYPTO_LOCK) {
694         WaitForSingleObject(lock_cs[type], INFINITE);
695     } else {
696         ReleaseMutex(lock_cs[type]);
697     }
698 }
699
700 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
701 {
702     double ret;
703     SSL_CTX *ssl_ctx[2];
704     DWORD thread_id[MAX_THREAD_NUMBER];
705     HANDLE thread_handle[MAX_THREAD_NUMBER];
706     int i;
707     SYSTEMTIME start, end;
708
709     ssl_ctx[0] = s_ctx;
710     ssl_ctx[1] = c_ctx;
711
712     GetSystemTime(&start);
713     for (i = 0; i < thread_number; i++) {
714         thread_handle[i] = CreateThread(NULL,
715                                         THREAD_STACK_SIZE,
716                                         (LPTHREAD_START_ROUTINE) ndoit,
717                                         (void *)ssl_ctx, 0L, &(thread_id[i]));
718     }
719
720     printf("reaping\n");
721     for (i = 0; i < thread_number; i += 50) {
722         int j;
723
724         j = (thread_number < (i + 50)) ? (thread_number - i) : 50;
725
726         if (WaitForMultipleObjects(j,
727                                    (CONST HANDLE *) & (thread_handle[i]),
728                                    TRUE, INFINITE)
729             == WAIT_FAILED) {
730             fprintf(stderr, "WaitForMultipleObjects failed:%d\n",
731                     GetLastError());
732             exit(1);
733         }
734     }
735     GetSystemTime(&end);
736
737     if (start.wDayOfWeek > end.wDayOfWeek)
738         end.wDayOfWeek += 7;
739     ret = (end.wDayOfWeek - start.wDayOfWeek) * 24;
740
741     ret = (ret + end.wHour - start.wHour) * 60;
742     ret = (ret + end.wMinute - start.wMinute) * 60;
743     ret = (ret + end.wSecond - start.wSecond);
744     ret += (end.wMilliseconds - start.wMilliseconds) / 1000.0;
745
746     printf("win32 threads done - %.3f seconds\n", ret);
747 }
748
749 #endif                          /* OPENSSL_SYS_WIN32 */
750
751 #ifdef SOLARIS
752
753 static mutex_t *lock_cs;
754 /*
755  * static rwlock_t *lock_cs;
756  */
757 static long *lock_count;
758
759 void thread_setup(void)
760 {
761     int i;
762
763     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
764     lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
765     for (i = 0; i < CRYPTO_num_locks(); i++) {
766         lock_count[i] = 0;
767         /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
768         mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
769     }
770
771     CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
772     CRYPTO_set_locking_callback((void (*)())solaris_locking_callback);
773 }
774
775 void thread_cleanup(void)
776 {
777     int i;
778
779     CRYPTO_set_locking_callback(NULL);
780
781     fprintf(stderr, "cleanup\n");
782
783     for (i = 0; i < CRYPTO_num_locks(); i++) {
784         /* rwlock_destroy(&(lock_cs[i])); */
785         mutex_destroy(&(lock_cs[i]));
786         fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
787     }
788     OPENSSL_free(lock_cs);
789     OPENSSL_free(lock_count);
790
791     fprintf(stderr, "done cleanup\n");
792
793 }
794
795 void solaris_locking_callback(int mode, int type, char *file, int line)
796 {
797 # ifdef undef
798     fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
799             CRYPTO_thread_id(),
800             (mode & CRYPTO_LOCK) ? "l" : "u",
801             (type & CRYPTO_READ) ? "r" : "w", file, line);
802 # endif
803
804     /*-
805     if (CRYPTO_LOCK_SSL_CERT == type)
806     fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
807             CRYPTO_thread_id(),
808             mode,file,line);
809     */
810     if (mode & CRYPTO_LOCK) {
811         /*-
812         if (mode & CRYPTO_READ)
813                 rw_rdlock(&(lock_cs[type]));
814         else
815                 rw_wrlock(&(lock_cs[type])); */
816
817         mutex_lock(&(lock_cs[type]));
818         lock_count[type]++;
819     } else {
820 /*      rw_unlock(&(lock_cs[type]));  */
821         mutex_unlock(&(lock_cs[type]));
822     }
823 }
824
825 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
826 {
827     SSL_CTX *ssl_ctx[2];
828     thread_t thread_ctx[MAX_THREAD_NUMBER];
829     int i;
830
831     ssl_ctx[0] = s_ctx;
832     ssl_ctx[1] = c_ctx;
833
834     thr_setconcurrency(thread_number);
835     for (i = 0; i < thread_number; i++) {
836         thr_create(NULL, THREAD_STACK_SIZE,
837                    (void *(*)())ndoit, (void *)ssl_ctx, 0L, &(thread_ctx[i]));
838     }
839
840     printf("reaping\n");
841     for (i = 0; i < thread_number; i++) {
842         thr_join(thread_ctx[i], NULL, NULL);
843     }
844
845     printf("solaris threads done (%d,%d)\n",
846            s_ctx->references, c_ctx->references);
847 }
848
849 unsigned long solaris_thread_id(void)
850 {
851     unsigned long ret;
852
853     ret = (unsigned long)thr_self();
854     return (ret);
855 }
856 #endif                          /* SOLARIS */
857
858 #ifdef IRIX
859
860 static usptr_t *arena;
861 static usema_t **lock_cs;
862
863 void thread_setup(void)
864 {
865     int i;
866     char filename[20];
867
868     strcpy(filename, "/tmp/mttest.XXXXXX");
869     mktemp(filename);
870
871     usconfig(CONF_STHREADIOOFF);
872     usconfig(CONF_STHREADMALLOCOFF);
873     usconfig(CONF_INITUSERS, 100);
874     usconfig(CONF_LOCKTYPE, US_DEBUGPLUS);
875     arena = usinit(filename);
876     unlink(filename);
877
878     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(usema_t *));
879     for (i = 0; i < CRYPTO_num_locks(); i++) {
880         lock_cs[i] = usnewsema(arena, 1);
881     }
882
883     CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id);
884     CRYPTO_set_locking_callback((void (*)())irix_locking_callback);
885 }
886
887 void thread_cleanup(void)
888 {
889     int i;
890
891     CRYPTO_set_locking_callback(NULL);
892     for (i = 0; i < CRYPTO_num_locks(); i++) {
893         char buf[10];
894
895         sprintf(buf, "%2d:", i);
896         usdumpsema(lock_cs[i], stdout, buf);
897         usfreesema(lock_cs[i], arena);
898     }
899     OPENSSL_free(lock_cs);
900 }
901
902 void irix_locking_callback(int mode, int type, char *file, int line)
903 {
904     if (mode & CRYPTO_LOCK) {
905         printf("lock %d\n", type);
906         uspsema(lock_cs[type]);
907     } else {
908         printf("unlock %d\n", type);
909         usvsema(lock_cs[type]);
910     }
911 }
912
913 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
914 {
915     SSL_CTX *ssl_ctx[2];
916     int thread_ctx[MAX_THREAD_NUMBER];
917     int i;
918
919     ssl_ctx[0] = s_ctx;
920     ssl_ctx[1] = c_ctx;
921
922     for (i = 0; i < thread_number; i++) {
923         thread_ctx[i] = sproc((void (*)())ndoit,
924                               PR_SADDR | PR_SFDS, (void *)ssl_ctx);
925     }
926
927     printf("reaping\n");
928     for (i = 0; i < thread_number; i++) {
929         wait(NULL);
930     }
931
932     printf("irix threads done (%d,%d)\n",
933            s_ctx->references, c_ctx->references);
934 }
935
936 unsigned long irix_thread_id(void)
937 {
938     unsigned long ret;
939
940     ret = (unsigned long)getpid();
941     return (ret);
942 }
943 #endif                          /* IRIX */
944
945 #ifdef PTHREADS
946
947 static pthread_mutex_t *lock_cs;
948 static long *lock_count;
949
950 void thread_setup(void)
951 {
952     int i;
953
954     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
955     lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
956     for (i = 0; i < CRYPTO_num_locks(); i++) {
957         lock_count[i] = 0;
958         pthread_mutex_init(&(lock_cs[i]), NULL);
959     }
960
961     CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
962     CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
963 }
964
965 void thread_cleanup(void)
966 {
967     int i;
968
969     CRYPTO_set_locking_callback(NULL);
970     fprintf(stderr, "cleanup\n");
971     for (i = 0; i < CRYPTO_num_locks(); i++) {
972         pthread_mutex_destroy(&(lock_cs[i]));
973         fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
974     }
975     OPENSSL_free(lock_cs);
976     OPENSSL_free(lock_count);
977
978     fprintf(stderr, "done cleanup\n");
979 }
980
981 void pthreads_locking_callback(int mode, int type, char *file, int line)
982 {
983 # ifdef undef
984     fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
985             CRYPTO_thread_id(),
986             (mode & CRYPTO_LOCK) ? "l" : "u",
987             (type & CRYPTO_READ) ? "r" : "w", file, line);
988 # endif
989 /*-
990     if (CRYPTO_LOCK_SSL_CERT == type)
991             fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
992             CRYPTO_thread_id(),
993             mode,file,line);
994 */
995     if (mode & CRYPTO_LOCK) {
996         pthread_mutex_lock(&(lock_cs[type]));
997         lock_count[type]++;
998     } else {
999         pthread_mutex_unlock(&(lock_cs[type]));
1000     }
1001 }
1002
1003 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1004 {
1005     SSL_CTX *ssl_ctx[2];
1006     pthread_t thread_ctx[MAX_THREAD_NUMBER];
1007     int i;
1008
1009     ssl_ctx[0] = s_ctx;
1010     ssl_ctx[1] = c_ctx;
1011
1012     /*
1013      * thr_setconcurrency(thread_number);
1014      */
1015     for (i = 0; i < thread_number; i++) {
1016         pthread_create(&(thread_ctx[i]), NULL,
1017                        (void *(*)())ndoit, (void *)ssl_ctx);
1018     }
1019
1020     printf("reaping\n");
1021     for (i = 0; i < thread_number; i++) {
1022         pthread_join(thread_ctx[i], NULL);
1023     }
1024
1025     printf("pthreads threads done (%d,%d)\n",
1026            s_ctx->references, c_ctx->references);
1027 }
1028
1029 unsigned long pthreads_thread_id(void)
1030 {
1031     unsigned long ret;
1032
1033     ret = (unsigned long)pthread_self();
1034     return (ret);
1035 }
1036
1037 #endif                          /* PTHREADS */
1038
1039 #ifdef OPENSSL_SYS_NETWARE
1040
1041 void thread_setup(void)
1042 {
1043     int i;
1044
1045     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(MPKMutex));
1046     lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1047     for (i = 0; i < CRYPTO_num_locks(); i++) {
1048         lock_count[i] = 0;
1049         lock_cs[i] = MPKMutexAlloc("OpenSSL mutex");
1050     }
1051
1052     ThreadSem = MPKSemaphoreAlloc("OpenSSL mttest semaphore", 0);
1053
1054     CRYPTO_set_id_callback((unsigned long (*)())netware_thread_id);
1055     CRYPTO_set_locking_callback((void (*)())netware_locking_callback);
1056 }
1057
1058 void thread_cleanup(void)
1059 {
1060     int i;
1061
1062     CRYPTO_set_locking_callback(NULL);
1063
1064     fprintf(stdout, "thread_cleanup\n");
1065
1066     for (i = 0; i < CRYPTO_num_locks(); i++) {
1067         MPKMutexFree(lock_cs[i]);
1068         fprintf(stdout, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
1069     }
1070     OPENSSL_free(lock_cs);
1071     OPENSSL_free(lock_count);
1072
1073     MPKSemaphoreFree(ThreadSem);
1074
1075     fprintf(stdout, "done cleanup\n");
1076 }
1077
1078 void netware_locking_callback(int mode, int type, char *file, int line)
1079 {
1080     if (mode & CRYPTO_LOCK) {
1081         MPKMutexLock(lock_cs[type]);
1082         lock_count[type]++;
1083     } else
1084         MPKMutexUnlock(lock_cs[type]);
1085 }
1086
1087 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1088 {
1089     SSL_CTX *ssl_ctx[2];
1090     int i;
1091     ssl_ctx[0] = s_ctx;
1092     ssl_ctx[1] = c_ctx;
1093
1094     for (i = 0; i < thread_number; i++) {
1095         BeginThread((void (*)(void *))ndoit, NULL, THREAD_STACK_SIZE,
1096                     (void *)ssl_ctx);
1097         ThreadSwitchWithDelay();
1098     }
1099
1100     printf("reaping\n");
1101
1102     /* loop until all threads have signaled the semaphore */
1103     for (i = 0; i < thread_number; i++) {
1104         MPKSemaphoreWait(ThreadSem);
1105     }
1106     printf("netware threads done (%d,%d)\n",
1107            s_ctx->references, c_ctx->references);
1108 }
1109
1110 unsigned long netware_thread_id(void)
1111 {
1112     unsigned long ret;
1113
1114     ret = (unsigned long)GetThreadID();
1115     return (ret);
1116 }
1117 #endif                          /* NETWARE */
1118
1119 #ifdef BEOS_THREADS
1120
1121 # include <Locker.h>
1122
1123 static BLocker **lock_cs;
1124 static long *lock_count;
1125
1126 void thread_setup(void)
1127 {
1128     int i;
1129
1130     lock_cs =
1131         (BLocker **) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(BLocker *));
1132     lock_count = (long *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1133     for (i = 0; i < CRYPTO_num_locks(); i++) {
1134         lock_count[i] = 0;
1135         lock_cs[i] = new BLocker(CRYPTO_get_lock_name(i));
1136     }
1137
1138     CRYPTO_set_id_callback((unsigned long (*)())beos_thread_id);
1139     CRYPTO_set_locking_callback(beos_locking_callback);
1140 }
1141
1142 void thread_cleanup(void)
1143 {
1144     int i;
1145
1146     CRYPTO_set_locking_callback(NULL);
1147     fprintf(stderr, "cleanup\n");
1148     for (i = 0; i < CRYPTO_num_locks(); i++) {
1149         delete lock_cs[i];
1150         fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
1151     }
1152     OPENSSL_free(lock_cs);
1153     OPENSSL_free(lock_count);
1154
1155     fprintf(stderr, "done cleanup\n");
1156 }
1157
1158 void beos_locking_callback(int mode, int type, const char *file, int line)
1159 {
1160 # if 0
1161     fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
1162             CRYPTO_thread_id(),
1163             (mode & CRYPTO_LOCK) ? "l" : "u",
1164             (type & CRYPTO_READ) ? "r" : "w", file, line);
1165 # endif
1166     if (mode & CRYPTO_LOCK) {
1167         lock_cs[type]->Lock();
1168         lock_count[type]++;
1169     } else {
1170         lock_cs[type]->Unlock();
1171     }
1172 }
1173
1174 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1175 {
1176     SSL_CTX *ssl_ctx[2];
1177     thread_id thread_ctx[MAX_THREAD_NUMBER];
1178     int i;
1179
1180     ssl_ctx[0] = s_ctx;
1181     ssl_ctx[1] = c_ctx;
1182
1183     for (i = 0; i < thread_number; i++) {
1184         thread_ctx[i] = spawn_thread((thread_func) ndoit,
1185                                      NULL, B_NORMAL_PRIORITY,
1186                                      (void *)ssl_ctx);
1187         resume_thread(thread_ctx[i]);
1188     }
1189
1190     printf("waiting...\n");
1191     for (i = 0; i < thread_number; i++) {
1192         status_t result;
1193         wait_for_thread(thread_ctx[i], &result);
1194     }
1195
1196     printf("beos threads done (%d,%d)\n",
1197            s_ctx->references, c_ctx->references);
1198 }
1199
1200 unsigned long beos_thread_id(void)
1201 {
1202     unsigned long ret;
1203
1204     ret = (unsigned long)find_thread(NULL);
1205     return (ret);
1206 }
1207
1208 #endif                          /* BEOS_THREADS */