Some issues for voting
[openssl.git] / mt / mttest.c
1 /* mt/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 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 #include "lhash.h"
78 #include "crypto.h"
79 #include "buffer.h"
80 #include "../e_os.h"
81 #include "x509.h"
82 #include "ssl.h"
83 #include "err.h"
84
85 #ifdef NO_FP_API
86 #define APPS_WIN16
87 #include "../crypto/buffer/bss_file.c"
88 #endif
89
90 #define TEST_SERVER_CERT "../apps/server.pem"
91 #define TEST_CLIENT_CERT "../apps/client.pem"
92
93 #define MAX_THREAD_NUMBER       100
94
95 #ifndef NOPROTO
96 int MS_CALLBACK verify_callback(int ok, X509 *xs, X509 *xi, int depth,
97         int error,char *arg);
98 void thread_setup(void);
99 void thread_cleanup(void);
100 void do_threads(SSL_CTX *s_ctx,SSL_CTX *c_ctx);
101
102 void irix_locking_callback(int mode,int type,char *file,int line);
103 void solaris_locking_callback(int mode,int type,char *file,int line);
104 void win32_locking_callback(int mode,int type,char *file,int line);
105 void pthreads_locking_callback(int mode,int type,char *file,int line);
106
107 unsigned long irix_thread_id(void );
108 unsigned long solaris_thread_id(void );
109 unsigned long pthreads_thread_id(void );
110
111 #else
112 int MS_CALLBACK verify_callback();
113 void thread_setup();
114 void thread_cleanup();
115 void do_threads();
116
117 void irix_locking_callback();
118 void solaris_locking_callback();
119 void win32_locking_callback();
120 void pthreads_locking_callback();
121
122 unsigned long irix_thread_id();
123 unsigned long solaris_thread_id();
124 unsigned long pthreads_thread_id();
125
126 #endif
127
128 BIO *bio_err=NULL;
129 BIO *bio_stdout=NULL;
130
131 static char *cipher=NULL;
132 int verbose=0;
133 #ifdef FIONBIO
134 static int s_nbio=0;
135 #endif
136
137 int thread_number=10;
138 int number_of_loops=10;
139 int reconnect=0;
140 int cache_stats=0;
141
142 #ifndef  NOPROTO
143 int doit(char *ctx[4]);
144 #else
145 int doit();
146 #endif
147
148 static void print_stats(fp,ctx)
149 FILE *fp;
150 SSL_CTX *ctx;
151 {
152         fprintf(fp,"%4ld items in the session cache\n",
153                 SSL_CTX_sess_number(ctx));
154         fprintf(fp,"%4d client connects (SSL_connect())\n",
155                 SSL_CTX_sess_connect(ctx));
156         fprintf(fp,"%4d client connects that finished\n",
157                 SSL_CTX_sess_connect_good(ctx));
158         fprintf(fp,"%4d server connects (SSL_accept())\n",
159                 SSL_CTX_sess_accept(ctx));
160         fprintf(fp,"%4d server connects that finished\n",
161                 SSL_CTX_sess_accept_good(ctx));
162         fprintf(fp,"%4d session cache hits\n",SSL_CTX_sess_hits(ctx));
163         fprintf(fp,"%4d session cache misses\n",SSL_CTX_sess_misses(ctx));
164         fprintf(fp,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ctx));
165         }
166
167 static void sv_usage()
168         {
169         fprintf(stderr,"usage: ssltest [args ...]\n");
170         fprintf(stderr,"\n");
171         fprintf(stderr," -server_auth  - check server certificate\n");
172         fprintf(stderr," -client_auth  - do client authentication\n");
173         fprintf(stderr," -v            - more output\n");
174         fprintf(stderr," -CApath arg   - PEM format directory of CA's\n");
175         fprintf(stderr," -CAfile arg   - PEM format file of CA's\n");
176         fprintf(stderr," -threads arg  - number of threads\n");
177         fprintf(stderr," -loops arg    - number of 'connections', per thread\n");
178         fprintf(stderr," -reconnect    - reuse session-id's\n");
179         fprintf(stderr," -stats        - server session-id cache stats\n");
180         fprintf(stderr," -cert arg     - server certificate/key\n");
181         fprintf(stderr," -ccert arg    - client certificate/key\n");
182         fprintf(stderr," -ssl3         - just SSLv3n\n");
183         }
184
185 int main(argc, argv)
186 int argc;
187 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         if (bio_err == NULL)
201                 bio_err=BIO_new_fp(stderr,BIO_NOCLOSE);
202         if (bio_stdout == NULL)
203                 bio_stdout=BIO_new_fp(stdout,BIO_NOCLOSE);
204         argc--;
205         argv++;
206
207         while (argc >= 1)
208                 {
209                 if      (strcmp(*argv,"-server_auth") == 0)
210                         server_auth=1;
211                 else if (strcmp(*argv,"-client_auth") == 0)
212                         client_auth=1;
213                 else if (strcmp(*argv,"-reconnect") == 0)
214                         reconnect=1;
215                 else if (strcmp(*argv,"-stats") == 0)
216                         cache_stats=1;
217                 else if (strcmp(*argv,"-ssl3") == 0)
218                         ssl_method=SSLv3_method();
219                 else if (strcmp(*argv,"-ssl2") == 0)
220                         ssl_method=SSLv2_method();
221                 else if (strcmp(*argv,"-CApath") == 0)
222                         {
223                         if (--argc < 1) goto bad;
224                         CApath= *(++argv);
225                         }
226                 else if (strcmp(*argv,"-CAfile") == 0)
227                         {
228                         if (--argc < 1) goto bad;
229                         CAfile= *(++argv);
230                         }
231                 else if (strcmp(*argv,"-cert") == 0)
232                         {
233                         if (--argc < 1) goto bad;
234                         scert= *(++argv);
235                         }
236                 else if (strcmp(*argv,"-ccert") == 0)
237                         {
238                         if (--argc < 1) goto bad;
239                         ccert= *(++argv);
240                         }
241                 else if (strcmp(*argv,"-threads") == 0)
242                         {
243                         if (--argc < 1) goto bad;
244                         thread_number= atoi(*(++argv));
245                         if (thread_number == 0) thread_number=1;
246                         if (thread_number > MAX_THREAD_NUMBER)
247                                 thread_number=MAX_THREAD_NUMBER;
248                         }
249                 else if (strcmp(*argv,"-loops") == 0)
250                         {
251                         if (--argc < 1) goto bad;
252                         number_of_loops= atoi(*(++argv));
253                         if (number_of_loops == 0) number_of_loops=1;
254                         }
255                 else
256                         {
257                         fprintf(stderr,"unknown option %s\n",*argv);
258                         badop=1;
259                         break;
260                         }
261                 argc--;
262                 argv++;
263                 }
264         if (badop)
265                 {
266 bad:
267                 sv_usage();
268                 goto end;
269                 }
270
271         if (cipher == NULL) cipher=getenv("SSL_CIPHER");
272
273         SSL_load_error_strings();
274         SSLeay_add_ssl_algorithms();
275
276         c_ctx=SSL_CTX_new(ssl_method);
277         s_ctx=SSL_CTX_new(ssl_method);
278         if ((c_ctx == NULL) || (s_ctx == NULL))
279                 {
280                 ERR_print_errors(bio_err);
281                 goto end;
282                 }
283
284         SSL_CTX_set_session_cache_mode(s_ctx,
285                 SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_SERVER);
286         SSL_CTX_set_session_cache_mode(c_ctx,
287                 SSL_SESS_CACHE_NO_AUTO_CLEAR|SSL_SESS_CACHE_SERVER);
288
289         SSL_CTX_use_certificate_file(s_ctx,scert,SSL_FILETYPE_PEM);
290         SSL_CTX_use_RSAPrivateKey_file(s_ctx,scert,SSL_FILETYPE_PEM);
291
292         if (client_auth)
293                 {
294                 SSL_CTX_use_certificate_file(c_ctx,ccert,
295                         SSL_FILETYPE_PEM);
296                 SSL_CTX_use_RSAPrivateKey_file(c_ctx,ccert,
297                         SSL_FILETYPE_PEM);
298                 }
299
300         if (    (!SSL_CTX_load_verify_locations(s_ctx,CAfile,CApath)) ||
301                 (!SSL_CTX_set_default_verify_paths(s_ctx)) ||
302                 (!SSL_CTX_load_verify_locations(c_ctx,CAfile,CApath)) ||
303                 (!SSL_CTX_set_default_verify_paths(c_ctx)))
304                 {
305                 fprintf(stderr,"SSL_load_verify_locations\n");
306                 ERR_print_errors(bio_err);
307                 goto end;
308                 }
309
310         if (client_auth)
311                 {
312                 fprintf(stderr,"client authentication\n");
313                 SSL_CTX_set_verify(s_ctx,
314                         SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT,
315                         verify_callback);
316                 }
317         if (server_auth)
318                 {
319                 fprintf(stderr,"server authentication\n");
320                 SSL_CTX_set_verify(c_ctx,SSL_VERIFY_PEER,
321                         verify_callback);
322                 }
323
324         thread_setup();
325         do_threads(s_ctx,c_ctx);
326         thread_cleanup();
327 end:
328         
329         if (c_ctx != NULL) 
330                 {
331                 fprintf(stderr,"Client SSL_CTX stats then free it\n");
332                 print_stats(stderr,c_ctx);
333                 SSL_CTX_free(c_ctx);
334                 }
335         if (s_ctx != NULL)
336                 {
337                 fprintf(stderr,"Server SSL_CTX stats then free it\n");
338                 print_stats(stderr,s_ctx);
339                 if (cache_stats)
340                         {
341                         fprintf(stderr,"-----\n");
342                         lh_stats(SSL_CTX_sessions(s_ctx),stderr);
343                         fprintf(stderr,"-----\n");
344                 /*      lh_node_stats(SSL_CTX_sessions(s_ctx),stderr);
345                         fprintf(stderr,"-----\n"); */
346                         lh_node_usage_stats(SSL_CTX_sessions(s_ctx),stderr);
347                         fprintf(stderr,"-----\n");
348                         }
349                 SSL_CTX_free(s_ctx);
350                 fprintf(stderr,"done free\n");
351                 }
352         exit(ret);
353         return(0);
354         }
355
356 #define W_READ  1
357 #define W_WRITE 2
358 #define C_DONE  1
359 #define S_DONE  2
360
361 int ndoit(ssl_ctx)
362 SSL_CTX *ssl_ctx[2];
363         {
364         int i;
365         int ret;
366         char *ctx[4];
367
368         ctx[0]=(char *)ssl_ctx[0];
369         ctx[1]=(char *)ssl_ctx[1];
370
371         if (reconnect)
372                 {
373                 ctx[2]=(char *)SSL_new(ssl_ctx[0]);
374                 ctx[3]=(char *)SSL_new(ssl_ctx[1]);
375                 }
376         else
377                 {
378                 ctx[2]=NULL;
379                 ctx[3]=NULL;
380                 }
381
382         fprintf(stdout,"started thread %lu\n",CRYPTO_thread_id());
383         for (i=0; i<number_of_loops; i++)
384                 {
385 /*              fprintf(stderr,"%4d %2d ctx->ref (%3d,%3d)\n",
386                         CRYPTO_thread_id(),i,
387                         ssl_ctx[0]->references,
388                         ssl_ctx[1]->references); */
389         /*      pthread_delay_np(&tm);*/
390
391                 ret=doit(ctx);
392                 if (ret != 0)
393                         {
394                         fprintf(stdout,"error[%d] %lu - %d\n",
395                                 i,CRYPTO_thread_id(),ret);
396                         return(ret);
397                         }
398                 }
399         fprintf(stdout,"DONE %lu\n",CRYPTO_thread_id());
400         if (reconnect)
401                 {
402                 SSL_free((SSL *)ctx[2]);
403                 SSL_free((SSL *)ctx[3]);
404                 }
405         return(0);
406         }
407
408 int doit(ctx)
409 char *ctx[4];
410         {
411         SSL_CTX *s_ctx,*c_ctx;
412         static char cbuf[200],sbuf[200];
413         SSL *c_ssl=NULL;
414         SSL *s_ssl=NULL;
415         BIO *c_to_s=NULL;
416         BIO *s_to_c=NULL;
417         BIO *c_bio=NULL;
418         BIO *s_bio=NULL;
419         int c_r,c_w,s_r,s_w;
420         int c_want,s_want;
421         int i;
422         int done=0;
423         int c_write,s_write;
424         int do_server=0,do_client=0;
425
426         s_ctx=(SSL_CTX *)ctx[0];
427         c_ctx=(SSL_CTX *)ctx[1];
428
429         if (ctx[2] != NULL)
430                 s_ssl=(SSL *)ctx[2];
431         else
432                 s_ssl=SSL_new(s_ctx);
433
434         if (ctx[3] != NULL)
435                 c_ssl=(SSL *)ctx[3];
436         else
437                 c_ssl=SSL_new(c_ctx);
438
439         if ((s_ssl == NULL) || (c_ssl == NULL)) goto err;
440
441         c_to_s=BIO_new(BIO_s_mem());
442         s_to_c=BIO_new(BIO_s_mem());
443         if ((s_to_c == NULL) || (c_to_s == NULL)) goto err;
444
445         c_bio=BIO_new(BIO_f_ssl());
446         s_bio=BIO_new(BIO_f_ssl());
447         if ((c_bio == NULL) || (s_bio == NULL)) goto err;
448
449         SSL_set_connect_state(c_ssl);
450         SSL_set_bio(c_ssl,s_to_c,c_to_s);
451         BIO_set_ssl(c_bio,c_ssl,(ctx[2] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
452
453         SSL_set_accept_state(s_ssl);
454         SSL_set_bio(s_ssl,c_to_s,s_to_c);
455         BIO_set_ssl(s_bio,s_ssl,(ctx[3] == NULL)?BIO_CLOSE:BIO_NOCLOSE);
456
457         c_r=0; s_r=1;
458         c_w=1; s_w=0;
459         c_want=W_WRITE;
460         s_want=0;
461         c_write=1,s_write=0;
462
463         /* We can always do writes */
464         for (;;)
465                 {
466                 do_server=0;
467                 do_client=0;
468
469                 i=(int)BIO_pending(s_bio);
470                 if ((i && s_r) || s_w) do_server=1;
471
472                 i=(int)BIO_pending(c_bio);
473                 if ((i && c_r) || c_w) do_client=1;
474
475                 if (do_server && verbose)
476                         {
477                         if (SSL_in_init(s_ssl))
478                                 printf("server waiting in SSL_accept - %s\n",
479                                         SSL_state_string_long(s_ssl));
480                         else if (s_write)
481                                 printf("server:SSL_write()\n");
482                         else 
483                                 printf("server:SSL_read()\n");
484                         }
485
486                 if (do_client && verbose)
487                         {
488                         if (SSL_in_init(c_ssl))
489                                 printf("client waiting in SSL_connect - %s\n",
490                                         SSL_state_string_long(c_ssl));
491                         else if (c_write)
492                                 printf("client:SSL_write()\n");
493                         else
494                                 printf("client:SSL_read()\n");
495                         }
496
497                 if (!do_client && !do_server)
498                         {
499                         fprintf(stdout,"ERROR IN STARTUP\n");
500                         break;
501                         }
502                 if (do_client && !(done & C_DONE))
503                         {
504                         if (c_write)
505                                 {
506                                 i=BIO_write(c_bio,"hello from client\n",18);
507                                 if (i < 0)
508                                         {
509                                         c_r=0;
510                                         c_w=0;
511                                         if (BIO_should_retry(c_bio))
512                                                 {
513                                                 if (BIO_should_read(c_bio))
514                                                         c_r=1;
515                                                 if (BIO_should_write(c_bio))
516                                                         c_w=1;
517                                                 }
518                                         else
519                                                 {
520                                                 fprintf(stderr,"ERROR in CLIENT\n");
521                                                 return(1);
522                                                 }
523                                         }
524                                 else if (i == 0)
525                                         {
526                                         fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
527                                         return(1);
528                                         }
529                                 else
530                                         {
531                                         /* ok */
532                                         c_write=0;
533                                         }
534                                 }
535                         else
536                                 {
537                                 i=BIO_read(c_bio,cbuf,100);
538                                 if (i < 0)
539                                         {
540                                         c_r=0;
541                                         c_w=0;
542                                         if (BIO_should_retry(c_bio))
543                                                 {
544                                                 if (BIO_should_read(c_bio))
545                                                         c_r=1;
546                                                 if (BIO_should_write(c_bio))
547                                                         c_w=1;
548                                                 }
549                                         else
550                                                 {
551                                                 fprintf(stderr,"ERROR in CLIENT\n");
552                                                 return(1);
553                                                 }
554                                         }
555                                 else if (i == 0)
556                                         {
557                                         fprintf(stderr,"SSL CLIENT STARTUP FAILED\n");
558                                         return(1);
559                                         }
560                                 else
561                                         {
562                                         done|=C_DONE;
563 #ifdef undef
564                                         fprintf(stdout,"CLIENT:from server:");
565                                         fwrite(cbuf,1,i,stdout);
566                                         fflush(stdout);
567 #endif
568                                         }
569                                 }
570                         }
571
572                 if (do_server && !(done & S_DONE))
573                         {
574                         if (!s_write)
575                                 {
576                                 i=BIO_read(s_bio,sbuf,100);
577                                 if (i < 0)
578                                         {
579                                         s_r=0;
580                                         s_w=0;
581                                         if (BIO_should_retry(s_bio))
582                                                 {
583                                                 if (BIO_should_read(s_bio))
584                                                         s_r=1;
585                                                 if (BIO_should_write(s_bio))
586                                                         s_w=1;
587                                                 }
588                                         else
589                                                 {
590                                                 fprintf(stderr,"ERROR in SERVER\n");
591                                                 ERR_print_errors_fp(stderr);
592                                                 return(1);
593                                                 }
594                                         }
595                                 else if (i == 0)
596                                         {
597                                         fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
598                                         return(1);
599                                         }
600                                 else
601                                         {
602                                         s_write=1;
603                                         s_w=1;
604 #ifdef undef
605                                         fprintf(stdout,"SERVER:from client:");
606                                         fwrite(sbuf,1,i,stdout);
607                                         fflush(stdout);
608 #endif
609                                         }
610                                 }
611                         else
612                                 {
613                                 i=BIO_write(s_bio,"hello from server\n",18);
614                                 if (i < 0)
615                                         {
616                                         s_r=0;
617                                         s_w=0;
618                                         if (BIO_should_retry(s_bio))
619                                                 {
620                                                 if (BIO_should_read(s_bio))
621                                                         s_r=1;
622                                                 if (BIO_should_write(s_bio))
623                                                         s_w=1;
624                                                 }
625                                         else
626                                                 {
627                                                 fprintf(stderr,"ERROR in SERVER\n");
628                                                 ERR_print_errors_fp(stderr);
629                                                 return(1);
630                                                 }
631                                         }
632                                 else if (i == 0)
633                                         {
634                                         fprintf(stderr,"SSL SERVER STARTUP FAILED\n");
635                                         return(1);
636                                         }
637                                 else
638                                         {
639                                         s_write=0;
640                                         s_r=1;
641                                         done|=S_DONE;
642                                         }
643                                 }
644                         }
645
646                 if ((done & S_DONE) && (done & C_DONE)) break;
647                 }
648
649         SSL_set_shutdown(c_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
650         SSL_set_shutdown(s_ssl,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
651
652 #ifdef undef
653         fprintf(stdout,"DONE\n");
654 #endif
655 err:
656         /* We have to set the BIO's to NULL otherwise they will be
657          * free()ed twice.  Once when th s_ssl is SSL_free()ed and
658          * again when c_ssl is SSL_free()ed.
659          * This is a hack required because s_ssl and c_ssl are sharing the same
660          * BIO structure and SSL_set_bio() and SSL_free() automatically
661          * BIO_free non NULL entries.
662          * You should not normally do this or be required to do this */
663
664         if (s_ssl != NULL)
665                 {
666                 s_ssl->rbio=NULL;
667                 s_ssl->wbio=NULL;
668                 }
669         if (c_ssl != NULL)
670                 {
671                 c_ssl->rbio=NULL;
672                 c_ssl->wbio=NULL;
673                 }
674
675         /* The SSL's are optionally freed in the following calls */
676         if (c_to_s != NULL) BIO_free(c_to_s);
677         if (s_to_c != NULL) BIO_free(s_to_c);
678
679         if (c_bio != NULL) BIO_free(c_bio);
680         if (s_bio != NULL) BIO_free(s_bio);
681         return(0);
682         }
683
684 int MS_CALLBACK verify_callback(ok, xs, xi, depth, error, arg)
685 int ok;
686 X509 *xs;
687 X509 *xi;
688 int depth;
689 int error;
690 char *arg;
691         {
692         char buf[256];
693
694         if (verbose)
695                 {
696                 X509_NAME_oneline(X509_get_subject_name(xs),buf,256);
697                 if (ok)
698                         fprintf(stderr,"depth=%d %s\n",depth,buf);
699                 else
700                         fprintf(stderr,"depth=%d error=%d %s\n",depth,error,buf);
701                 }
702         return(ok);
703         }
704
705 #define THREAD_STACK_SIZE (16*1024)
706
707 #ifdef WIN32
708
709 static PRLOCK lock_cs[CRYPTO_NUM_LOCKS];
710
711 void thread_setup()
712         {
713         int i;
714
715         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
716                 {
717                 lock_cs[i]=CreateMutex(NULL,FALSE,NULL);
718                 }
719
720         CRYPTO_set_locking_callback((void (*)(int,int,char *,int))win32_locking_callback);
721         /* id callback defined */
722         }
723
724 void thread_cleanup()
725         {
726         int i;
727
728         CRYPTO_set_locking_callback(NULL);
729         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
730                 CloseHandle(lock_cs[i]);
731         }
732
733 void win32_locking_callback(mode,type,file,line)
734 int mode;
735 int type;
736 char *file;
737 int line;
738         {
739         if (mode & CRYPTO_LOCK)
740                 {
741                 WaitForSingleObject(lock_cs[type],INFINITE);
742                 }
743         else
744                 {
745                 ReleaseMutex(lock_cs[type]);
746                 }
747         }
748
749 void do_threads(s_ctx,c_ctx)
750 SSL_CTX *s_ctx,*c_ctx;
751         {
752         double ret;
753         SSL_CTX *ssl_ctx[2];
754         DWORD thread_id[MAX_THREAD_NUMBER];
755         HANDLE thread_handle[MAX_THREAD_NUMBER];
756         int i;
757         SYSTEMTIME start,end;
758
759         ssl_ctx[0]=s_ctx;
760         ssl_ctx[1]=c_ctx;
761
762         GetSystemTime(&start);
763         for (i=0; i<thread_number; i++)
764                 {
765                 thread_handle[i]=CreateThread(NULL,
766                         THREAD_STACK_SIZE,
767                         (LPTHREAD_START_ROUTINE)ndoit,
768                         (void *)ssl_ctx,
769                         0L,
770                         &(thread_id[i]));
771                 }
772
773         printf("reaping\n");
774         for (i=0; i<thread_number; i+=50)
775                 {
776                 int j;
777
778                 j=(thread_number < (i+50))?(thread_number-i):50;
779
780                 if (WaitForMultipleObjects(j,
781                         (CONST HANDLE *)&(thread_handle[i]),TRUE,INFINITE)
782                         == WAIT_FAILED)
783                         {
784                         fprintf(stderr,"WaitForMultipleObjects failed:%d\n",GetLastError());
785                         exit(1);
786                         }
787                 }
788         GetSystemTime(&end);
789
790         if (start.wDayOfWeek > end.wDayOfWeek) end.wDayOfWeek+=7;
791         ret=(end.wDayOfWeek-start.wDayOfWeek)*24;
792
793         ret=(ret+end.wHour-start.wHour)*60;
794         ret=(ret+end.wMinute-start.wMinute)*60;
795         ret=(ret+end.wSecond-start.wSecond);
796         ret+=(end.wMilliseconds-start.wMilliseconds)/1000.0;
797
798         printf("win32 threads done - %.3f seconds\n",ret);
799         }
800
801 #endif /* WIN32 */
802
803 #ifdef SOLARIS
804
805 static mutex_t lock_cs[CRYPTO_NUM_LOCKS];
806 /*static rwlock_t lock_cs[CRYPTO_NUM_LOCKS]; */
807 static long lock_count[CRYPTO_NUM_LOCKS];
808
809 void thread_setup()
810         {
811         int i;
812
813         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
814                 {
815                 lock_count[i]=0;
816                 /* rwlock_init(&(lock_cs[i]),USYNC_THREAD,NULL); */
817                 mutex_init(&(lock_cs[i]),USYNC_THREAD,NULL);
818                 }
819
820         CRYPTO_set_id_callback((unsigned long (*)())solaris_thread_id);
821         CRYPTO_set_locking_callback((void (*)())solaris_locking_callback);
822         }
823
824 void thread_cleanup()
825         {
826         int i;
827
828         CRYPTO_set_locking_callback(NULL);
829 fprintf(stderr,"cleanup\n");
830         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
831                 {
832                 /* rwlock_destroy(&(lock_cs[i])); */
833                 mutex_destroy(&(lock_cs[i]));
834                 fprintf(stderr,"%8ld:%s\n",lock_count[i],CRYPTO_get_lock_name(i));
835                 }
836 fprintf(stderr,"done cleanup\n");
837         }
838
839 void solaris_locking_callback(mode,type,file,line)
840 int mode;
841 int type;
842 char *file;
843 int line;
844         {
845 #ifdef undef
846 fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
847         CRYPTO_thread_id(),
848         (mode&CRYPTO_LOCK)?"l":"u",
849         (type&CRYPTO_READ)?"r":"w",file,line);
850 #endif
851
852 /*
853 if (CRYPTO_LOCK_SSL_CERT == type)
854         fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
855                 CRYPTO_thread_id(),
856                 mode,file,line);
857 */
858         if (mode & CRYPTO_LOCK)
859                 {
860         /*      if (mode & CRYPTO_READ)
861                         rw_rdlock(&(lock_cs[type]));
862                 else
863                         rw_wrlock(&(lock_cs[type])); */
864
865                 mutex_lock(&(lock_cs[type]));
866                 lock_count[type]++;
867                 }
868         else
869                 {
870 /*              rw_unlock(&(lock_cs[type]));  */
871                 mutex_unlock(&(lock_cs[type]));
872                 }
873         }
874
875 void do_threads(s_ctx,c_ctx)
876 SSL_CTX *s_ctx,*c_ctx;
877         {
878         SSL_CTX *ssl_ctx[2];
879         thread_t thread_ctx[MAX_THREAD_NUMBER];
880         int i;
881
882         ssl_ctx[0]=s_ctx;
883         ssl_ctx[1]=c_ctx;
884
885         thr_setconcurrency(thread_number);
886         for (i=0; i<thread_number; i++)
887                 {
888                 thr_create(NULL, THREAD_STACK_SIZE,
889                         (void *(*)())ndoit,
890                         (void *)ssl_ctx,
891                         0L,
892                         &(thread_ctx[i]));
893                 }
894
895         printf("reaping\n");
896         for (i=0; i<thread_number; i++)
897                 {
898                 thr_join(thread_ctx[i],NULL,NULL);
899                 }
900
901         printf("solaris threads done (%d,%d)\n",
902                 s_ctx->references,c_ctx->references);
903         }
904
905 unsigned long solaris_thread_id()
906         {
907         unsigned long ret;
908
909         ret=(unsigned long)thr_self();
910         return(ret);
911         }
912 #endif /* SOLARIS */
913
914 #ifdef IRIX
915
916
917 static usptr_t *arena;
918 static usema_t *lock_cs[CRYPTO_NUM_LOCKS];
919
920 void thread_setup()
921         {
922         int i;
923         char filename[20];
924
925         strcpy(filename,"/tmp/mttest.XXXXXX");
926         mktemp(filename);
927
928         usconfig(CONF_STHREADIOOFF);
929         usconfig(CONF_STHREADMALLOCOFF);
930         usconfig(CONF_INITUSERS,100);
931         usconfig(CONF_LOCKTYPE,US_DEBUGPLUS);
932         arena=usinit(filename);
933         unlink(filename);
934
935         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
936                 {
937                 lock_cs[i]=usnewsema(arena,1);
938                 }
939
940         CRYPTO_set_id_callback((unsigned long (*)())irix_thread_id);
941         CRYPTO_set_locking_callback((void (*)())irix_locking_callback);
942         }
943
944 void thread_cleanup()
945         {
946         int i;
947
948         CRYPTO_set_locking_callback(NULL);
949         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
950                 {
951                 char buf[10];
952
953                 sprintf(buf,"%2d:",i);
954                 usdumpsema(lock_cs[i],stdout,buf);
955                 usfreesema(lock_cs[i],arena);
956                 }
957         }
958
959 void irix_locking_callback(mode,type,file,line)
960 int mode;
961 int type;
962 char *file;
963 int line;
964         {
965         if (mode & CRYPTO_LOCK)
966                 {
967                 printf("lock %d\n",type);
968                 uspsema(lock_cs[type]);
969                 }
970         else
971                 {
972                 printf("unlock %d\n",type);
973                 usvsema(lock_cs[type]);
974                 }
975         }
976
977 void do_threads(s_ctx,c_ctx)
978 SSL_CTX *s_ctx,*c_ctx;
979         {
980         SSL_CTX *ssl_ctx[2];
981         int thread_ctx[MAX_THREAD_NUMBER];
982         int i;
983
984         ssl_ctx[0]=s_ctx;
985         ssl_ctx[1]=c_ctx;
986
987         for (i=0; i<thread_number; i++)
988                 {
989                 thread_ctx[i]=sproc((void (*)())ndoit,
990                         PR_SADDR|PR_SFDS,(void *)ssl_ctx);
991                 }
992
993         printf("reaping\n");
994         for (i=0; i<thread_number; i++)
995                 {
996                 wait(NULL);
997                 }
998
999         printf("irix threads done (%d,%d)\n",
1000                 s_ctx->references,c_ctx->references);
1001         }
1002
1003 unsigned long irix_thread_id()
1004         {
1005         unsigned long ret;
1006
1007         ret=(unsigned long)getpid();
1008         return(ret);
1009         }
1010 #endif /* IRIX */
1011
1012 #ifdef PTHREADS
1013
1014 static pthread_mutex_t lock_cs[CRYPTO_NUM_LOCKS];
1015 static long lock_count[CRYPTO_NUM_LOCKS];
1016
1017 void thread_setup()
1018         {
1019         int i;
1020
1021         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
1022                 {
1023                 lock_count[i]=0;
1024                 pthread_mutex_init(&(lock_cs[i]),NULL);
1025                 }
1026
1027         CRYPTO_set_id_callback((unsigned long (*)())pthreads_thread_id);
1028         CRYPTO_set_locking_callback((void (*)())pthreads_locking_callback);
1029         }
1030
1031 void thread_cleanup()
1032         {
1033         int i;
1034
1035         CRYPTO_set_locking_callback(NULL);
1036         fprintf(stderr,"cleanup\n");
1037         for (i=0; i<CRYPTO_NUM_LOCKS; i++)
1038                 {
1039                 pthread_mutex_destroy(&(lock_cs[i]));
1040                 fprintf(stderr,"%8ld:%s\n",lock_count[i],
1041                         CRYPTO_get_lock_name(i));
1042                 }
1043         fprintf(stderr,"done cleanup\n");
1044         }
1045
1046 void pthreads_locking_callback(mode,type,file,line)
1047 int mode;
1048 int type;
1049 char *file;
1050 int line;
1051       {
1052 #ifdef undef
1053         fprintf(stderr,"thread=%4d mode=%s lock=%s %s:%d\n",
1054                 CRYPTO_thread_id(),
1055                 (mode&CRYPTO_LOCK)?"l":"u",
1056                 (type&CRYPTO_READ)?"r":"w",file,line);
1057 #endif
1058 /*
1059         if (CRYPTO_LOCK_SSL_CERT == type)
1060                 fprintf(stderr,"(t,m,f,l) %ld %d %s %d\n",
1061                 CRYPTO_thread_id(),
1062                 mode,file,line);
1063 */
1064         if (mode & CRYPTO_LOCK)
1065                 {
1066                 pthread_mutex_lock(&(lock_cs[type]));
1067                 lock_count[type]++;
1068                 }
1069         else
1070                 {
1071                 pthread_mutex_unlock(&(lock_cs[type]));
1072                 }
1073         }
1074
1075 void do_threads(s_ctx,c_ctx)
1076 SSL_CTX *s_ctx,*c_ctx;
1077         {
1078         SSL_CTX *ssl_ctx[2];
1079         pthread_t thread_ctx[MAX_THREAD_NUMBER];
1080         int i;
1081
1082         ssl_ctx[0]=s_ctx;
1083         ssl_ctx[1]=c_ctx;
1084
1085         /*
1086         thr_setconcurrency(thread_number);
1087         */
1088         for (i=0; i<thread_number; i++)
1089                 {
1090                 pthread_create(&(thread_ctx[i]), NULL,
1091                         (void *(*)())ndoit, (void *)ssl_ctx);
1092                 }
1093
1094         printf("reaping\n");
1095         for (i=0; i<thread_number; i++)
1096                 {
1097                 pthread_join(thread_ctx[i],NULL);
1098                 }
1099
1100         printf("pthreads threads done (%d,%d)\n",
1101         s_ctx->references,c_ctx->references);
1102         }
1103
1104 unsigned long pthreads_thread_id()
1105         {
1106         unsigned long ret;
1107
1108         ret=(unsigned long)pthread_self();
1109         return(ret);
1110         }
1111
1112 #endif /* PTHREADS */
1113
1114
1115