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