a64ff97ada0624c487bbbef90efe124450c65f4f
[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 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, const char *file, int line);
116 void solaris_locking_callback(int mode, int type, const char *file, int line);
117 void win32_locking_callback(int mode, int type, const char *file, int line);
118 void pthreads_locking_callback(int mode, int type, const char *file, int line);
119 void netware_locking_callback(int mode, int type, const char *file, int line);
120 void beos_locking_callback(int mode, int type, const char *file, int line);
121
122 void irix_thread_id(CRYPTO_THREADID *tid);
123 void solaris_thread_id(CRYPTO_THREADID *tid);
124 void pthreads_thread_id(CRYPTO_THREADID *tid);
125 void netware_thread_id(CRYPTO_THREADID *tid);
126 void beos_thread_id(CRYPTO_THREADID *tid);
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     CRYPTO_THREADID thread_id;
359
360     ctx[0] = (char *)ssl_ctx[0];
361     ctx[1] = (char *)ssl_ctx[1];
362
363     if (reconnect) {
364         ctx[2] = (char *)SSL_new(ssl_ctx[0]);
365         ctx[3] = (char *)SSL_new(ssl_ctx[1]);
366     } else {
367         ctx[2] = NULL;
368         ctx[3] = NULL;
369     }
370
371     CRYPTO_THREADID_current(&thread_id);
372     BIO_printf(bio_stdout, "started thread %lu\n",
373                CRYPTO_THREADID_hash(&thread_id));
374     for (i = 0; i < number_of_loops; i++) {
375 /*-     BIO_printf(bio_err,"%4d %2d ctx->ref (%3d,%3d)\n",
376                    CRYPTO_THREADID_hash(&thread_id),i,
377                    ssl_ctx[0]->references,
378                    ssl_ctx[1]->references); */
379 /*      pthread_delay_np(&tm); */
380
381         ret = doit(ctx);
382         if (ret != 0) {
383             BIO_printf(bio_stdout, "error[%d] %lu - %d\n",
384                        i, CRYPTO_THREADID_hash(&thread_id), ret);
385             return (ret);
386         }
387     }
388     BIO_printf(bio_stdout, "DONE %lu\n", CRYPTO_THREADID_hash(&thread_id));
389     if (reconnect) {
390         SSL_free((SSL *)ctx[2]);
391         SSL_free((SSL *)ctx[3]);
392     }
393 #ifdef OPENSSL_SYS_NETWARE
394     MPKSemaphoreSignal(ThreadSem);
395 #endif
396     return (0);
397 }
398
399 int doit(char *ctx[4])
400 {
401     SSL_CTX *s_ctx, *c_ctx;
402     static char cbuf[200], sbuf[200];
403     SSL *c_ssl = NULL;
404     SSL *s_ssl = NULL;
405     BIO *c_to_s = NULL;
406     BIO *s_to_c = NULL;
407     BIO *c_bio = NULL;
408     BIO *s_bio = NULL;
409     int c_r, c_w, s_r, s_w;
410     int c_want, s_want;
411     int i;
412     int done = 0;
413     int c_write, s_write;
414     int do_server = 0, do_client = 0;
415
416     s_ctx = (SSL_CTX *)ctx[0];
417     c_ctx = (SSL_CTX *)ctx[1];
418
419     if (ctx[2] != NULL)
420         s_ssl = (SSL *)ctx[2];
421     else
422         s_ssl = SSL_new(s_ctx);
423
424     if (ctx[3] != NULL)
425         c_ssl = (SSL *)ctx[3];
426     else
427         c_ssl = SSL_new(c_ctx);
428
429     if ((s_ssl == NULL) || (c_ssl == NULL))
430         goto err;
431
432     c_to_s = BIO_new(BIO_s_mem());
433     s_to_c = BIO_new(BIO_s_mem());
434     if ((s_to_c == NULL) || (c_to_s == NULL))
435         goto err;
436
437     c_bio = BIO_new(BIO_f_ssl());
438     s_bio = BIO_new(BIO_f_ssl());
439     if ((c_bio == NULL) || (s_bio == NULL))
440         goto err;
441
442     SSL_set_connect_state(c_ssl);
443     SSL_set_bio(c_ssl, s_to_c, c_to_s);
444     BIO_set_ssl(c_bio, c_ssl, (ctx[2] == NULL) ? BIO_CLOSE : BIO_NOCLOSE);
445
446     SSL_set_accept_state(s_ssl);
447     SSL_set_bio(s_ssl, c_to_s, s_to_c);
448     BIO_set_ssl(s_bio, s_ssl, (ctx[3] == NULL) ? BIO_CLOSE : BIO_NOCLOSE);
449
450     c_r = 0;
451     s_r = 1;
452     c_w = 1;
453     s_w = 0;
454     c_want = W_WRITE;
455     s_want = 0;
456     c_write = 1, s_write = 0;
457
458     /* We can always do writes */
459     for (;;) {
460         do_server = 0;
461         do_client = 0;
462
463         i = (int)BIO_pending(s_bio);
464         if ((i && s_r) || s_w)
465             do_server = 1;
466
467         i = (int)BIO_pending(c_bio);
468         if ((i && c_r) || c_w)
469             do_client = 1;
470
471         if (do_server && verbose) {
472             if (SSL_in_init(s_ssl))
473                 printf("server waiting in SSL_accept - %s\n",
474                        SSL_state_string_long(s_ssl));
475             else if (s_write)
476                 printf("server:SSL_write()\n");
477             else
478                 printf("server:SSL_read()\n");
479         }
480
481         if (do_client && verbose) {
482             if (SSL_in_init(c_ssl))
483                 printf("client waiting in SSL_connect - %s\n",
484                        SSL_state_string_long(c_ssl));
485             else if (c_write)
486                 printf("client:SSL_write()\n");
487             else
488                 printf("client:SSL_read()\n");
489         }
490
491         if (!do_client && !do_server) {
492             fprintf(stdout, "ERROR IN STARTUP\n");
493             break;
494         }
495         if (do_client && !(done & C_DONE)) {
496             if (c_write) {
497                 i = BIO_write(c_bio, "hello from client\n", 18);
498                 if (i < 0) {
499                     c_r = 0;
500                     c_w = 0;
501                     if (BIO_should_retry(c_bio)) {
502                         if (BIO_should_read(c_bio))
503                             c_r = 1;
504                         if (BIO_should_write(c_bio))
505                             c_w = 1;
506                     } else {
507                         fprintf(stderr, "ERROR in CLIENT\n");
508                         ERR_print_errors_fp(stderr);
509                         return (1);
510                     }
511                 } else if (i == 0) {
512                     fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
513                     return (1);
514                 } else {
515                     /* ok */
516                     c_write = 0;
517                 }
518             } else {
519                 i = BIO_read(c_bio, cbuf, 100);
520                 if (i < 0) {
521                     c_r = 0;
522                     c_w = 0;
523                     if (BIO_should_retry(c_bio)) {
524                         if (BIO_should_read(c_bio))
525                             c_r = 1;
526                         if (BIO_should_write(c_bio))
527                             c_w = 1;
528                     } else {
529                         fprintf(stderr, "ERROR in CLIENT\n");
530                         ERR_print_errors_fp(stderr);
531                         return (1);
532                     }
533                 } else if (i == 0) {
534                     fprintf(stderr, "SSL CLIENT STARTUP FAILED\n");
535                     return (1);
536                 } else {
537                     done |= C_DONE;
538 #ifdef undef
539                     fprintf(stdout, "CLIENT:from server:");
540                     fwrite(cbuf, 1, i, stdout);
541                     fflush(stdout);
542 #endif
543                 }
544             }
545         }
546
547         if (do_server && !(done & S_DONE)) {
548             if (!s_write) {
549                 i = BIO_read(s_bio, sbuf, 100);
550                 if (i < 0) {
551                     s_r = 0;
552                     s_w = 0;
553                     if (BIO_should_retry(s_bio)) {
554                         if (BIO_should_read(s_bio))
555                             s_r = 1;
556                         if (BIO_should_write(s_bio))
557                             s_w = 1;
558                     } else {
559                         fprintf(stderr, "ERROR in SERVER\n");
560                         ERR_print_errors_fp(stderr);
561                         return (1);
562                     }
563                 } else if (i == 0) {
564                     fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
565                     return (1);
566                 } else {
567                     s_write = 1;
568                     s_w = 1;
569 #ifdef undef
570                     fprintf(stdout, "SERVER:from client:");
571                     fwrite(sbuf, 1, i, stdout);
572                     fflush(stdout);
573 #endif
574                 }
575             } else {
576                 i = BIO_write(s_bio, "hello from server\n", 18);
577                 if (i < 0) {
578                     s_r = 0;
579                     s_w = 0;
580                     if (BIO_should_retry(s_bio)) {
581                         if (BIO_should_read(s_bio))
582                             s_r = 1;
583                         if (BIO_should_write(s_bio))
584                             s_w = 1;
585                     } else {
586                         fprintf(stderr, "ERROR in SERVER\n");
587                         ERR_print_errors_fp(stderr);
588                         return (1);
589                     }
590                 } else if (i == 0) {
591                     fprintf(stderr, "SSL SERVER STARTUP FAILED\n");
592                     return (1);
593                 } else {
594                     s_write = 0;
595                     s_r = 1;
596                     done |= S_DONE;
597                 }
598             }
599         }
600
601         if ((done & S_DONE) && (done & C_DONE))
602             break;
603 #if defined(OPENSSL_SYS_NETWARE)
604         ThreadSwitchWithDelay();
605 #endif
606     }
607
608     SSL_set_shutdown(c_ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
609     SSL_set_shutdown(s_ssl, SSL_SENT_SHUTDOWN | SSL_RECEIVED_SHUTDOWN);
610
611 #ifdef undef
612     fprintf(stdout, "DONE\n");
613 #endif
614  err:
615     /*
616      * We have to set the BIO's to NULL otherwise they will be free()ed
617      * twice.  Once when th s_ssl is SSL_free()ed and again when c_ssl is
618      * SSL_free()ed. This is a hack required because s_ssl and c_ssl are
619      * sharing the same BIO structure and SSL_set_bio() and SSL_free()
620      * automatically BIO_free non NULL entries. You should not normally do
621      * this or be required to do this
622      */
623
624     if (s_ssl != NULL) {
625         s_ssl->rbio = NULL;
626         s_ssl->wbio = NULL;
627     }
628     if (c_ssl != NULL) {
629         c_ssl->rbio = NULL;
630         c_ssl->wbio = NULL;
631     }
632
633     /* The SSL's are optionally freed in the following calls */
634     if (c_to_s != NULL)
635         BIO_free(c_to_s);
636     if (s_to_c != NULL)
637         BIO_free(s_to_c);
638
639     if (c_bio != NULL)
640         BIO_free(c_bio);
641     if (s_bio != NULL)
642         BIO_free(s_bio);
643     return (0);
644 }
645
646 int verify_callback(int ok, X509_STORE_CTX *ctx)
647 {
648     char *s, buf[256];
649
650     if (verbose) {
651         s = X509_NAME_oneline(X509_get_subject_name(ctx->current_cert),
652                               buf, 256);
653         if (s != NULL) {
654             if (ok)
655                 fprintf(stderr, "depth=%d %s\n", ctx->error_depth, buf);
656             else
657                 fprintf(stderr, "depth=%d error=%d %s\n",
658                         ctx->error_depth, ctx->error, buf);
659         }
660     }
661     return (ok);
662 }
663
664 #define THREAD_STACK_SIZE (16*1024)
665
666 #ifdef OPENSSL_SYS_WIN32
667
668 static HANDLE *lock_cs;
669
670 void thread_setup(void)
671 {
672     int i;
673
674     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(HANDLE));
675     for (i = 0; i < CRYPTO_num_locks(); i++) {
676         lock_cs[i] = CreateMutex(NULL, FALSE, NULL);
677     }
678
679     CRYPTO_set_locking_callback((void (*)(int, int, char *, int))
680                                 win32_locking_callback);
681     /* id callback defined */
682 }
683
684 void thread_cleanup(void)
685 {
686     int i;
687
688     CRYPTO_set_locking_callback(NULL);
689     for (i = 0; i < CRYPTO_num_locks(); i++)
690         CloseHandle(lock_cs[i]);
691     OPENSSL_free(lock_cs);
692 }
693
694 void win32_locking_callback(int mode, int type, const char *file, int line)
695 {
696     if (mode & CRYPTO_LOCK) {
697         WaitForSingleObject(lock_cs[type], INFINITE);
698     } else {
699         ReleaseMutex(lock_cs[type]);
700     }
701 }
702
703 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
704 {
705     double ret;
706     SSL_CTX *ssl_ctx[2];
707     DWORD thread_id[MAX_THREAD_NUMBER];
708     HANDLE thread_handle[MAX_THREAD_NUMBER];
709     int i;
710     SYSTEMTIME start, end;
711
712     ssl_ctx[0] = s_ctx;
713     ssl_ctx[1] = c_ctx;
714
715     GetSystemTime(&start);
716     for (i = 0; i < thread_number; i++) {
717         thread_handle[i] = CreateThread(NULL,
718                                         THREAD_STACK_SIZE,
719                                         (LPTHREAD_START_ROUTINE) ndoit,
720                                         (void *)ssl_ctx, 0L, &(thread_id[i]));
721     }
722
723     printf("reaping\n");
724     for (i = 0; i < thread_number; i += 50) {
725         int j;
726
727         j = (thread_number < (i + 50)) ? (thread_number - i) : 50;
728
729         if (WaitForMultipleObjects(j,
730                                    (CONST HANDLE *) & (thread_handle[i]),
731                                    TRUE, INFINITE)
732             == WAIT_FAILED) {
733             fprintf(stderr, "WaitForMultipleObjects failed:%d\n",
734                     GetLastError());
735             exit(1);
736         }
737     }
738     GetSystemTime(&end);
739
740     if (start.wDayOfWeek > end.wDayOfWeek)
741         end.wDayOfWeek += 7;
742     ret = (end.wDayOfWeek - start.wDayOfWeek) * 24;
743
744     ret = (ret + end.wHour - start.wHour) * 60;
745     ret = (ret + end.wMinute - start.wMinute) * 60;
746     ret = (ret + end.wSecond - start.wSecond);
747     ret += (end.wMilliseconds - start.wMilliseconds) / 1000.0;
748
749     printf("win32 threads done - %.3f seconds\n", ret);
750 }
751
752 #endif                          /* OPENSSL_SYS_WIN32 */
753
754 #ifdef SOLARIS
755
756 static mutex_t *lock_cs;
757 /*
758  * static rwlock_t *lock_cs;
759  */
760 static long *lock_count;
761
762 void thread_setup(void)
763 {
764     int i;
765
766     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(mutex_t));
767     lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
768     for (i = 0; i < CRYPTO_num_locks(); i++) {
769         lock_count[i] = 0;
770         /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
771         mutex_init(&(lock_cs[i]), USYNC_THREAD, NULL);
772     }
773
774     CRYPTO_set_id_callback(solaris_thread_id);
775     CRYPTO_set_locking_callback(solaris_locking_callback);
776 }
777
778 void thread_cleanup(void)
779 {
780     int i;
781
782     CRYPTO_set_locking_callback(NULL);
783
784     fprintf(stderr, "cleanup\n");
785
786     for (i = 0; i < CRYPTO_num_locks(); i++) {
787         /* rwlock_destroy(&(lock_cs[i])); */
788         mutex_destroy(&(lock_cs[i]));
789         fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
790     }
791     OPENSSL_free(lock_cs);
792     OPENSSL_free(lock_count);
793
794     fprintf(stderr, "done cleanup\n");
795
796 }
797
798 void solaris_locking_callback(int mode, int type, const char *file, int line)
799 {
800 # ifdef undef
801     fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
802             CRYPTO_thread_id(),
803             (mode & CRYPTO_LOCK) ? "l" : "u",
804             (type & CRYPTO_READ) ? "r" : "w", file, line);
805 # endif
806
807     /*-
808     if (CRYPTO_LOCK_SSL_CERT == type)
809     fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
810             CRYPTO_thread_id(),
811             mode,file,line);
812     */
813     if (mode & CRYPTO_LOCK) {
814         /*-
815         if (mode & CRYPTO_READ)
816                 rw_rdlock(&(lock_cs[type]));
817         else
818                 rw_wrlock(&(lock_cs[type])); */
819
820         mutex_lock(&(lock_cs[type]));
821         lock_count[type]++;
822     } else {
823 /*      rw_unlock(&(lock_cs[type]));  */
824         mutex_unlock(&(lock_cs[type]));
825     }
826 }
827
828 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
829 {
830     SSL_CTX *ssl_ctx[2];
831     thread_t thread_ctx[MAX_THREAD_NUMBER];
832     int i;
833
834     ssl_ctx[0] = s_ctx;
835     ssl_ctx[1] = c_ctx;
836
837     thr_setconcurrency(thread_number);
838     for (i = 0; i < thread_number; i++) {
839         thr_create(NULL, THREAD_STACK_SIZE,
840                    (void *(*)())ndoit, (void *)ssl_ctx, 0L, &(thread_ctx[i]));
841     }
842
843     printf("reaping\n");
844     for (i = 0; i < thread_number; i++) {
845         thr_join(thread_ctx[i], NULL, NULL);
846     }
847
848     printf("solaris threads done (%d,%d)\n",
849            s_ctx->references, c_ctx->references);
850 }
851
852 void solaris_thread_id(CRYPTO_THREADID *tid)
853 {
854     CRYPTO_THREADID_set_numeric((unsigned long)thr_self());
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(irix_thread_id);
884     CRYPTO_set_locking_callback(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, const 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     CRYPTO_THREADID_set_numeric((unsigned long)getpid());
939 }
940 #endif                          /* IRIX */
941
942 #ifdef PTHREADS
943
944 static pthread_mutex_t *lock_cs;
945 static long *lock_count;
946
947 void thread_setup(void)
948 {
949     int i;
950
951     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(pthread_mutex_t));
952     lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
953     for (i = 0; i < CRYPTO_num_locks(); i++) {
954         lock_count[i] = 0;
955         pthread_mutex_init(&(lock_cs[i]), NULL);
956     }
957
958     CRYPTO_THREADID_set_callback(pthreads_thread_id);
959     CRYPTO_set_locking_callback(pthreads_locking_callback);
960 }
961
962 void thread_cleanup(void)
963 {
964     int i;
965
966     CRYPTO_set_locking_callback(NULL);
967     fprintf(stderr, "cleanup\n");
968     for (i = 0; i < CRYPTO_num_locks(); i++) {
969         pthread_mutex_destroy(&(lock_cs[i]));
970         fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
971     }
972     OPENSSL_free(lock_cs);
973     OPENSSL_free(lock_count);
974
975     fprintf(stderr, "done cleanup\n");
976 }
977
978 void pthreads_locking_callback(int mode, int type, const char *file, int line)
979 {
980 # ifdef undef
981     fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
982             CRYPTO_thread_id(),
983             (mode & CRYPTO_LOCK) ? "l" : "u",
984             (type & CRYPTO_READ) ? "r" : "w", file, line);
985 # endif
986 /*-
987     if (CRYPTO_LOCK_SSL_CERT == type)
988             fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
989             CRYPTO_thread_id(),
990             mode,file,line);
991 */
992     if (mode & CRYPTO_LOCK) {
993         pthread_mutex_lock(&(lock_cs[type]));
994         lock_count[type]++;
995     } else {
996         pthread_mutex_unlock(&(lock_cs[type]));
997     }
998 }
999
1000 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1001 {
1002     SSL_CTX *ssl_ctx[2];
1003     pthread_t thread_ctx[MAX_THREAD_NUMBER];
1004     int i;
1005
1006     ssl_ctx[0] = s_ctx;
1007     ssl_ctx[1] = c_ctx;
1008
1009     /*
1010      * thr_setconcurrency(thread_number);
1011      */
1012     for (i = 0; i < thread_number; i++) {
1013         pthread_create(&(thread_ctx[i]), NULL,
1014                        (void *(*)())ndoit, (void *)ssl_ctx);
1015     }
1016
1017     printf("reaping\n");
1018     for (i = 0; i < thread_number; i++) {
1019         pthread_join(thread_ctx[i], NULL);
1020     }
1021
1022     printf("pthreads threads done (%d,%d)\n",
1023            s_ctx->references, c_ctx->references);
1024 }
1025
1026 void pthreads_thread_id(CRYPTO_THREADID *tid)
1027 {
1028     CRYPTO_THREADID_set_numeric(tid, (unsigned long)pthread_self());
1029 }
1030
1031 #endif                          /* PTHREADS */
1032
1033 #ifdef OPENSSL_SYS_NETWARE
1034
1035 void thread_setup(void)
1036 {
1037     int i;
1038
1039     lock_cs = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(MPKMutex));
1040     lock_count = OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1041     for (i = 0; i < CRYPTO_num_locks(); i++) {
1042         lock_count[i] = 0;
1043         lock_cs[i] = MPKMutexAlloc("OpenSSL mutex");
1044     }
1045
1046     ThreadSem = MPKSemaphoreAlloc("OpenSSL mttest semaphore", 0);
1047
1048     CRYPTO_set_id_callback(netware_thread_id);
1049     CRYPTO_set_locking_callback(netware_locking_callback);
1050 }
1051
1052 void thread_cleanup(void)
1053 {
1054     int i;
1055
1056     CRYPTO_set_locking_callback(NULL);
1057
1058     fprintf(stdout, "thread_cleanup\n");
1059
1060     for (i = 0; i < CRYPTO_num_locks(); i++) {
1061         MPKMutexFree(lock_cs[i]);
1062         fprintf(stdout, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
1063     }
1064     OPENSSL_free(lock_cs);
1065     OPENSSL_free(lock_count);
1066
1067     MPKSemaphoreFree(ThreadSem);
1068
1069     fprintf(stdout, "done cleanup\n");
1070 }
1071
1072 void netware_locking_callback(int mode, int type, const char *file, int line)
1073 {
1074     if (mode & CRYPTO_LOCK) {
1075         MPKMutexLock(lock_cs[type]);
1076         lock_count[type]++;
1077     } else
1078         MPKMutexUnlock(lock_cs[type]);
1079 }
1080
1081 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1082 {
1083     SSL_CTX *ssl_ctx[2];
1084     int i;
1085     ssl_ctx[0] = s_ctx;
1086     ssl_ctx[1] = c_ctx;
1087
1088     for (i = 0; i < thread_number; i++) {
1089         BeginThread((void (*)(void *))ndoit, NULL, THREAD_STACK_SIZE,
1090                     (void *)ssl_ctx);
1091         ThreadSwitchWithDelay();
1092     }
1093
1094     printf("reaping\n");
1095
1096     /* loop until all threads have signaled the semaphore */
1097     for (i = 0; i < thread_number; i++) {
1098         MPKSemaphoreWait(ThreadSem);
1099     }
1100     printf("netware threads done (%d,%d)\n",
1101            s_ctx->references, c_ctx->references);
1102 }
1103
1104 unsigned long netware_thread_id(void)
1105 {
1106     CRYPTO_THREADID_set_numeric((unsigned long)GetThreadID());
1107 }
1108 #endif                          /* NETWARE */
1109
1110 #ifdef BEOS_THREADS
1111
1112 # include <Locker.h>
1113
1114 static BLocker **lock_cs;
1115 static long *lock_count;
1116
1117 void thread_setup(void)
1118 {
1119     int i;
1120
1121     lock_cs =
1122         (BLocker **) OPENSSL_malloc(CRYPTO_num_locks() * sizeof(BLocker *));
1123     lock_count = (long *)OPENSSL_malloc(CRYPTO_num_locks() * sizeof(long));
1124     for (i = 0; i < CRYPTO_num_locks(); i++) {
1125         lock_count[i] = 0;
1126         lock_cs[i] = new BLocker(CRYPTO_get_lock_name(i));
1127     }
1128
1129     CRYPTO_set_id_callback((unsigned long (*)())beos_thread_id);
1130     CRYPTO_set_locking_callback(beos_locking_callback);
1131 }
1132
1133 void thread_cleanup(void)
1134 {
1135     int i;
1136
1137     CRYPTO_set_locking_callback(NULL);
1138     fprintf(stderr, "cleanup\n");
1139     for (i = 0; i < CRYPTO_num_locks(); i++) {
1140         delete lock_cs[i];
1141         fprintf(stderr, "%8ld:%s\n", lock_count[i], CRYPTO_get_lock_name(i));
1142     }
1143     OPENSSL_free(lock_cs);
1144     OPENSSL_free(lock_count);
1145
1146     fprintf(stderr, "done cleanup\n");
1147 }
1148
1149 void beos_locking_callback(int mode, int type, const char *file, int line)
1150 {
1151 # if 0
1152     fprintf(stderr, "thread=%4d mode=%s lock=%s %s:%d\n",
1153             CRYPTO_thread_id(),
1154             (mode & CRYPTO_LOCK) ? "l" : "u",
1155             (type & CRYPTO_READ) ? "r" : "w", file, line);
1156 # endif
1157     if (mode & CRYPTO_LOCK) {
1158         lock_cs[type]->Lock();
1159         lock_count[type]++;
1160     } else {
1161         lock_cs[type]->Unlock();
1162     }
1163 }
1164
1165 void do_threads(SSL_CTX *s_ctx, SSL_CTX *c_ctx)
1166 {
1167     SSL_CTX *ssl_ctx[2];
1168     thread_id thread_ctx[MAX_THREAD_NUMBER];
1169     int i;
1170
1171     ssl_ctx[0] = s_ctx;
1172     ssl_ctx[1] = c_ctx;
1173
1174     for (i = 0; i < thread_number; i++) {
1175         thread_ctx[i] = spawn_thread((thread_func) ndoit,
1176                                      NULL, B_NORMAL_PRIORITY,
1177                                      (void *)ssl_ctx);
1178         resume_thread(thread_ctx[i]);
1179     }
1180
1181     printf("waiting...\n");
1182     for (i = 0; i < thread_number; i++) {
1183         status_t result;
1184         wait_for_thread(thread_ctx[i], &result);
1185     }
1186
1187     printf("beos threads done (%d,%d)\n",
1188            s_ctx->references, c_ctx->references);
1189 }
1190
1191 unsigned long beos_thread_id(void)
1192 {
1193     unsigned long ret;
1194
1195     ret = (unsigned long)find_thread(NULL);
1196     return (ret);
1197 }
1198
1199 #endif                          /* BEOS_THREADS */