Import of old SSLeay release: SSLeay 0.9.0b
diff --git a/apps/s_server.c b/apps/s_server.c
index d1e406c..5012ef2 100644
--- a/apps/s_server.c
+++ b/apps/s_server.c
@@ -1,5 +1,5 @@
 /* apps/s_server.c */
-/* Copyright (C) 1995-1997 Eric Young (eay@cryptsoft.com)
+/* Copyright (C) 1995-1998 Eric Young (eay@cryptsoft.com)
  * All rights reserved.
  *
  * This package is an SSL implementation written
@@ -61,7 +61,7 @@
 #include <string.h>
 #include <sys/types.h>
 #include <sys/stat.h>
-#ifdef WIN16
+#ifdef NO_STDIO
 #define APPS_WIN16
 #endif
 #include "lhash.h"
@@ -82,8 +82,11 @@
 static void sv_usage(void);
 static int init_ssl_connection(SSL *s);
 static void print_stats(BIO *bp,SSL_CTX *ctx);
+#ifndef NO_DH
 static DH *load_dh_param(void );
 static DH *get_dh512(void);
+#endif
+/* static void s_server_init(void);*/
 #else
 static RSA MS_CALLBACK *tmp_rsa_cb();
 static int sv_body();
@@ -92,15 +95,19 @@
 static void sv_usage();
 static int init_ssl_connection();
 static void print_stats();
+#ifndef NO_DH
 static DH *load_dh_param();
 static DH *get_dh512();
 #endif
+/* static void s_server_init(); */
+#endif
 
 
 #ifndef S_ISDIR
 #define S_ISDIR(a)	(((a) & _S_IFMT) == _S_IFDIR)
 #endif
 
+#ifndef NO_DH
 static unsigned char dh512_p[]={
 	0xDA,0x58,0x3C,0x16,0xD9,0x85,0x22,0x89,0xD0,0xE4,0xAF,0x75,
 	0x6F,0x4C,0xCA,0x92,0xDD,0x4B,0xE5,0x33,0xB8,0x04,0xFB,0x0F,
@@ -117,15 +124,14 @@
 	{
 	DH *dh=NULL;
 
-#ifndef NO_DH
 	if ((dh=DH_new()) == NULL) return(NULL);
 	dh->p=BN_bin2bn(dh512_p,sizeof(dh512_p),NULL);
 	dh->g=BN_bin2bn(dh512_g,sizeof(dh512_g),NULL);
 	if ((dh->p == NULL) || (dh->g == NULL))
 		return(NULL);
-#endif
 	return(dh);
 	}
+#endif
 
 /* static int load_CA(SSL_CTX *ctx, char *file);*/
 
@@ -142,8 +148,9 @@
 extern int verify_depth;
 
 static char *cipher=NULL;
-int verify=SSL_VERIFY_NONE;
-char *s_cert_file=TEST_CERT,*s_key_file=NULL;
+static int s_server_verify=SSL_VERIFY_NONE;
+static char *s_cert_file=TEST_CERT,*s_key_file=NULL;
+static char *s_dcert_file=NULL,*s_dkey_file=NULL;
 #ifdef FIONBIO
 static int s_nbio=0;
 #endif
@@ -155,11 +162,33 @@
 static int s_debug=0;
 static int s_quiet=0;
 
+#if 0
+static void s_server_init()
+	{
+	cipher=NULL;
+	s_server_verify=SSL_VERIFY_NONE;
+	s_dcert_file=NULL;
+	s_dkey_file=NULL;
+	s_cert_file=TEST_CERT;
+	s_key_file=NULL;
+#ifdef FIONBIO
+	s_nbio=0;
+#endif
+	s_nbio_test=0;
+	ctx=NULL;
+	www=0;
+
+	bio_s_out=NULL;
+	s_debug=0;
+	s_quiet=0;
+	}
+#endif
+
 static void sv_usage()
 	{
 	BIO_printf(bio_err,"usage: s_server [args ...]\n");
 	BIO_printf(bio_err,"\n");
-	BIO_printf(bio_err," -accpet arg   - port to accept on (default is %d\n",PORT);
+	BIO_printf(bio_err," -accept arg   - port to accept on (default is %d\n",PORT);
 	BIO_printf(bio_err," -verify arg   - turn on peer certificate verification\n");
 	BIO_printf(bio_err," -Verify arg   - turn on peer certificate verification, must have a cert.\n");
 	BIO_printf(bio_err," -cert arg     - certificate file to use, PEM format assumed\n");
@@ -180,14 +209,18 @@
 	BIO_printf(bio_err," -no_tmp_rsa   - Do not generate a tmp RSA key\n");
 	BIO_printf(bio_err," -ssl2         - Just talk SSLv2\n");
 	BIO_printf(bio_err," -ssl3         - Just talk SSLv3\n");
+	BIO_printf(bio_err," -tls1         - Just talk TLSv1\n");
+	BIO_printf(bio_err," -no_ssl2      - Just disable SSLv2\n");
+	BIO_printf(bio_err," -no_ssl3      - Just disable SSLv3\n");
+	BIO_printf(bio_err," -no_tls1      - Just disable TLSv1\n");
 	BIO_printf(bio_err," -bugs         - Turn on SSL bug compatability\n");
 	BIO_printf(bio_err," -www          - Respond to a 'GET /' with a status page\n");
 	BIO_printf(bio_err," -WWW          - Returns requested page from to a 'GET <path> HTTP/1.0'\n");
 	}
 
-static int local_argc;
+static int local_argc=0;
 static char **local_argv;
-static int hack;
+static int hack=0;
 
 int MAIN(argc, argv)
 int argc;
@@ -197,10 +230,13 @@
 	char *CApath=NULL,*CAfile=NULL;
 	int badop=0,bugs=0;
 	int ret=1;
+	int off=0;
 	int no_tmp_rsa=0,nocert=0;
 	int state=0;
 	SSL_METHOD *meth=NULL;
+#ifndef NO_DH
 	DH *dh=NULL;
+#endif
 
 #if !defined(NO_SSL2) && !defined(NO_SSL3)
 	meth=SSLv23_server_method();
@@ -240,14 +276,14 @@
 			}
 		else if	(strcmp(*argv,"-verify") == 0)
 			{
-			verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
+			s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE;
 			if (--argc < 1) goto bad;
 			verify_depth=atoi(*(++argv));
 			BIO_printf(bio_err,"verify depth is %d\n",verify_depth);
 			}
 		else if	(strcmp(*argv,"-Verify") == 0)
 			{
-			verify=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
+			s_server_verify=SSL_VERIFY_PEER|SSL_VERIFY_FAIL_IF_NO_PEER_CERT|
 				SSL_VERIFY_CLIENT_ONCE;
 			if (--argc < 1) goto bad;
 			verify_depth=atoi(*(++argv));
@@ -263,6 +299,16 @@
 			if (--argc < 1) goto bad;
 			s_key_file= *(++argv);
 			}
+		else if	(strcmp(*argv,"-dcert") == 0)
+			{
+			if (--argc < 1) goto bad;
+			s_dcert_file= *(++argv);
+			}
+		else if	(strcmp(*argv,"-dkey") == 0)
+			{
+			if (--argc < 1) goto bad;
+			s_dkey_file= *(++argv);
+			}
 		else if (strcmp(*argv,"-nocert") == 0)
 			{
 			nocert=1;
@@ -309,6 +355,12 @@
 			{ www=1; }
 		else if	(strcmp(*argv,"-WWW") == 0)
 			{ www=2; }
+		else if	(strcmp(*argv,"-no_ssl2") == 0)
+			{ off|=SSL_OP_NO_SSLv2; }
+		else if	(strcmp(*argv,"-no_ssl3") == 0)
+			{ off|=SSL_OP_NO_SSLv3; }
+		else if	(strcmp(*argv,"-no_tls1") == 0)
+			{ off|=SSL_OP_NO_TLSv1; }
 #ifndef NO_SSL2
 		else if	(strcmp(*argv,"-ssl2") == 0)
 			{ meth=SSLv2_server_method(); }
@@ -317,6 +369,10 @@
 		else if	(strcmp(*argv,"-ssl3") == 0)
 			{ meth=SSLv3_server_method(); }
 #endif
+#ifndef NO_TLS1
+		else if	(strcmp(*argv,"-tls1") == 0)
+			{ meth=TLSv1_server_method(); }
+#endif
 		else
 			{
 			BIO_printf(bio_err,"unknown option %s\n",*argv);
@@ -352,6 +408,8 @@
 		{
 		s_cert_file=NULL;
 		s_key_file=NULL;
+		s_dcert_file=NULL;
+		s_dkey_file=NULL;
 		}
 
 	SSL_load_error_strings();
@@ -364,12 +422,16 @@
 		goto end;
 		}
 
+	SSL_CTX_set_quiet_shutdown(ctx,1);
 	if (bugs) SSL_CTX_set_options(ctx,SSL_OP_ALL);
 	if (hack) SSL_CTX_set_options(ctx,SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG);
+	SSL_CTX_set_options(ctx,off);
 	if (hack) SSL_CTX_set_options(ctx,SSL_OP_NON_EXPORT_FIRST);
 
 	if (state) SSL_CTX_set_info_callback(ctx,apps_ssl_info_callback);
 
+	SSL_CTX_sess_set_cache_size(ctx,128);
+
 #if 0
 	if (cipher == NULL) cipher=getenv("SSL_CIPHER");
 #endif
@@ -385,9 +447,9 @@
 	if ((!SSL_CTX_load_verify_locations(ctx,CAfile,CApath)) ||
 		(!SSL_CTX_set_default_verify_paths(ctx)))
 		{
-		BIO_printf(bio_err,"X509_load_verify_locations\n");
+		/* BIO_printf(bio_err,"X509_load_verify_locations\n"); */
 		ERR_print_errors(bio_err);
-		goto end;
+		/* goto end; */
 		}
 
 #ifndef NO_DH
@@ -410,6 +472,11 @@
 	
 	if (!set_cert_stuff(ctx,s_cert_file,s_key_file))
 		goto end;
+	if (s_dcert_file != NULL)
+		{
+		if (!set_cert_stuff(ctx,s_dcert_file,s_dkey_file))
+			goto end;
+		}
 
 #if 1
 	SSL_CTX_set_tmp_rsa_callback(ctx,tmp_rsa_cb);
@@ -435,7 +502,7 @@
 
 	if (cipher != NULL)
 		SSL_CTX_set_cipher_list(ctx,cipher);
-	SSL_CTX_set_verify(ctx,verify,verify_callback);
+	SSL_CTX_set_verify(ctx,s_server_verify,verify_callback);
 
 	SSL_CTX_set_client_CA_list(ctx,SSL_load_client_CA_file(s_cert_file));
 
@@ -464,16 +531,23 @@
 		SSL_CTX_sess_number(ssl_ctx));
 	BIO_printf(bio,"%4d client connects (SSL_connect())\n",
 		SSL_CTX_sess_connect(ssl_ctx));
+	BIO_printf(bio,"%4d client renegotiates (SSL_connect())\n",
+		SSL_CTX_sess_connect_renegotiate(ssl_ctx));
 	BIO_printf(bio,"%4d client connects that finished\n",
 		SSL_CTX_sess_connect_good(ssl_ctx));
 	BIO_printf(bio,"%4d server accepts (SSL_accept())\n",
 		SSL_CTX_sess_accept(ssl_ctx));
+	BIO_printf(bio,"%4d server renegotiates (SSL_accept())\n",
+		SSL_CTX_sess_accept_renegotiate(ssl_ctx));
 	BIO_printf(bio,"%4d server accepts that finished\n",
 		SSL_CTX_sess_accept_good(ssl_ctx));
 	BIO_printf(bio,"%4d session cache hits\n",SSL_CTX_sess_hits(ssl_ctx));
 	BIO_printf(bio,"%4d session cache misses\n",SSL_CTX_sess_misses(ssl_ctx));
 	BIO_printf(bio,"%4d session cache timeouts\n",SSL_CTX_sess_timeouts(ssl_ctx));
 	BIO_printf(bio,"%4d callback cache hits\n",SSL_CTX_sess_cb_hits(ssl_ctx));
+	BIO_printf(bio,"%4d cache full overflows (%d allowed)\n",
+		SSL_CTX_sess_cache_full(ssl_ctx),
+		SSL_CTX_sess_get_cache_size(ssl_ctx));
 	}
 
 static int sv_body(hostname, s)
@@ -500,7 +574,8 @@
 
 		if (!s_quiet)
 			BIO_printf(bio_err,"turning on non blocking io\n");
-		socket_ioctl(s,FIONBIO,&sl);
+		if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0)
+			ERR_print_errors(bio_err);
 		}
 #endif
 
@@ -539,7 +614,7 @@
 		if (i <= 0) continue;
 		if (FD_ISSET(fileno(stdin),&readfds))
 			{
-			i=read(fileno(stdin),buf,BUFSIZZ);
+			i=read(fileno(stdin),buf,128/*BUFSIZZ*/);
 			if (!s_quiet)
 				{
 				if ((i <= 0) || (buf[0] == 'Q'))
@@ -558,18 +633,24 @@
 					ret= -11;*/
 					goto err;
 					}
-				if (buf[0] == 'r')
+				if ((buf[0] == 'r') && 
+					((buf[1] == '\n') || (buf[1] == '\r')))
 					{
 					SSL_renegotiate(con);
+					i=SSL_do_handshake(con);
+					printf("SSL_do_handshake -> %d\n",i);
 					i=0; /*13; */
 					continue;
 					strcpy(buf,"server side RE-NEGOTIATE\n");
 					}
-				if (buf[0] == 'R')
+				if ((buf[0] == 'R') &&
+					((buf[1] == '\0') || (buf[1] == '\r')))
 					{
 					SSL_set_verify(con,
 						SSL_VERIFY_PEER|SSL_VERIFY_CLIENT_ONCE,NULL);
 					SSL_renegotiate(con);
+					i=SSL_do_handshake(con);
+					printf("SSL_do_handshake -> %d\n",i);
 					i=0; /* 13; */
 					continue;
 					strcpy(buf,"server side RE-NEGOTIATE asking for client cert\n");
@@ -588,19 +669,27 @@
 			for (;;)
 				{
 				/* should do a select for the write */
-				k=SSL_write(con,&(buf[l]),(unsigned int)i);
-				if (
-#ifdef FIONBIO
-					s_nbio &&
+#ifdef RENEG
+{ static count=0; if (++count == 100) { count=0; SSL_renegotiate(con); } }
 #endif
-					BIO_sock_should_retry(k))
+				k=SSL_write(con,&(buf[l]),(unsigned int)i);
+				switch (SSL_get_error(con,k))
 					{
+				case SSL_ERROR_NONE:
+					break;
+				case SSL_ERROR_WANT_WRITE:
+				case SSL_ERROR_WANT_READ:
+				case SSL_ERROR_WANT_X509_LOOKUP:
 					BIO_printf(bio_s_out,"Write BLOCK\n");
-					continue;
-					}
-				if (k <= 0)
-					{
+					break;
+				case SSL_ERROR_SYSCALL:
+				case SSL_ERROR_SSL:
+					BIO_printf(bio_s_out,"ERROR\n");
 					ERR_print_errors(bio_err);
+					ret=1;
+					goto err;
+					break;
+				case SSL_ERROR_ZERO_RETURN:
 					BIO_printf(bio_s_out,"DONE\n");
 					ret=1;
 					goto err;
@@ -629,25 +718,29 @@
 				}
 			else
 				{
-				i=SSL_read(con,(char *)buf,BUFSIZZ);
-				if ((i <= 0) &&
-#ifdef FIONBIO
-					s_nbio &&
-#endif
-					BIO_sock_should_retry(i))
+				i=SSL_read(con,(char *)buf,128 /*BUFSIZZ */);
+				switch (SSL_get_error(con,i))
 					{
+				case SSL_ERROR_NONE:
+					write(fileno(stdout),buf,
+						(unsigned int)i);
+					break;
+				case SSL_ERROR_WANT_WRITE:
+				case SSL_ERROR_WANT_READ:
+				case SSL_ERROR_WANT_X509_LOOKUP:
 					BIO_printf(bio_s_out,"Read BLOCK\n");
-					}
-				else if (i <= 0)
-					{
+					break;
+				case SSL_ERROR_SYSCALL:
+				case SSL_ERROR_SSL:
+					BIO_printf(bio_s_out,"ERROR\n");
 					ERR_print_errors(bio_err);
+					ret=1;
+					goto err;
+				case SSL_ERROR_ZERO_RETURN:
 					BIO_printf(bio_s_out,"DONE\n");
 					ret=1;
 					goto err;
 					}
-				else
-					write(fileno(stdout),buf,
-						(unsigned int)i);
 				}
 			}
 		}
@@ -685,7 +778,7 @@
 	int i;
 	char *str;
 	X509 *peer;
-	int verify_error;
+	long verify_error;
 	MS_STATIC char buf[BUFSIZ];
 
 	if ((i=SSL_accept(con)) <= 0)
@@ -730,20 +823,20 @@
 	return(1);
 	}
 
+#ifndef NO_DH
 static DH *load_dh_param()
 	{
 	DH *ret=NULL;
 	BIO *bio;
 
-#ifndef NO_DH
 	if ((bio=BIO_new_file(DH_PARAM,"r")) == NULL)
 		goto err;
 	ret=PEM_read_bio_DHparams(bio,NULL,NULL);
 err:
 	if (bio != NULL) BIO_free(bio);
-#endif
 	return(ret);
 	}
+#endif
 
 #if 0
 static int load_CA(ctx,file)
@@ -779,6 +872,7 @@
 	SSL *con;
 	SSL_CIPHER *c;
 	BIO *io,*ssl_bio,*sbio;
+	long total_bytes;
 
 	io=BIO_new(BIO_f_buffer());
 	ssl_bio=BIO_new(BIO_f_ssl());
@@ -787,16 +881,17 @@
 #ifdef FIONBIO	
 	if (s_nbio)
 		{
-		unsigned int long sl=1;
+		unsigned long sl=1;
 
 		if (!s_quiet)
 			BIO_printf(bio_err,"turning on non blocking io\n");
-		socket_ioctl(s,FIONBIO,&sl);
+		if (BIO_socket_ioctl(s,FIONBIO,&sl) < 0)
+			ERR_print_errors(bio_err);
 		}
 #endif
 
 	/* lets make the output buffer a reasonable size */
-	if (!BIO_set_write_buffer_size(io,16*1024)) goto err;
+	if (!BIO_set_write_buffer_size(io,253 /*16*1024*/)) goto err;
 
 	if ((con=(SSL *)SSL_new(ctx)) == NULL) goto err;
 
@@ -875,14 +970,15 @@
 
 		/* else we have data */
 		if (	((www == 1) && (strncmp("GET ",buf,4) == 0)) ||
-			((www == 2) && (strncmp("GET stats ",buf,10) == 0)))
+			((www == 2) && (strncmp("GET /stats ",buf,10) == 0)))
 			{
 			char *p;
 			X509 *peer;
 			STACK *sk;
-			static char *space="                ";
+			static char *space="                          ";
 
 			BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/html\r\n\r\n");
+			BIO_puts(io,"<HTML><BODY BGCOLOR=ffffff>\n");
 			BIO_puts(io,"<pre>\n");
 /*			BIO_puts(io,SSLeay_version(SSLEAY_VERSION));*/
 			BIO_puts(io,"\n");
@@ -901,10 +997,10 @@
 			for (i=0; i<j; i++)
 				{
 				c=(SSL_CIPHER *)sk_value(sk,i);
-				BIO_printf(io,"%s:%-25s",
+				BIO_printf(io,"%-11s:%-25s",
 					SSL_CIPHER_get_version(c),
 					SSL_CIPHER_get_name(c));
-				if ((((i+1)%3) == 0) && (i+1 != j))
+				if ((((i+1)%2) == 0) && (i+1 != j))
 					BIO_puts(io,"\n");
 				}
 			BIO_puts(io,"\n");
@@ -917,7 +1013,7 @@
 					{
 					if (*p == ':')
 						{
-						BIO_write(io,space,15-j);
+						BIO_write(io,space,26-j);
 						i++;
 						j=0;
 						BIO_write(io,((i%3)?" ":"\n"),1);
@@ -935,7 +1031,7 @@
 				?"---\nReused, "
 				:"---\nNew, "));
 			c=SSL_get_current_cipher(con);
-			BIO_printf(io,"SSLv%d, Cipher is %s\n",
+			BIO_printf(io,"%s, Cipher is %s\n",
 				SSL_CIPHER_get_version(c),
 				SSL_CIPHER_get_name(c));
 			SSL_SESSION_print(io,SSL_get_session(con));
@@ -951,6 +1047,7 @@
 				}
 			else
 				BIO_puts(io,"no client certificate available\n");
+			BIO_puts(io,"</BODY></HTML>\r\n\r\n");
 			break;
 			}
 		else if ((www == 2) && (strncmp("GET ",buf,4) == 0))
@@ -969,6 +1066,7 @@
 					(strncmp(&(e[-1]),"/../",4) == 0))
 					dot=1;
 				}
+			
 
 			if (*e == '\0')
 				{
@@ -1028,18 +1126,31 @@
 			else
 				BIO_puts(io,"HTTP/1.0 200 ok\r\nContent-type: text/plain\r\n\r\n");
 			/* send the file */
+			total_bytes=0;
 			for (;;)
 				{
 				i=BIO_read(file,buf,1024);
 				if (i <= 0) break;
 
+				total_bytes+=i;
+				fprintf(stderr,"%d\n",i);
+				if (total_bytes > 3*1024)
+					{
+					total_bytes=0;
+					fprintf(stderr,"RENEGOTIATE\n");
+					SSL_renegotiate(con);
+					}
+
 				for (j=0; j<i; )
 					{
+#ifdef RENEG
+{ static count=0; if (++count == 13) { SSL_renegotiate(con); } }
+#endif
 					k=BIO_write(io,&(buf[j]),i-j);
 					if (k <= 0)
 						{
 						if (!BIO_should_retry(io))
-							break;
+							goto write_error;
 						else
 							{
 							BIO_printf(bio_s_out,"rwrite W BLOCK\n");
@@ -1051,6 +1162,7 @@
 						}
 					}
 				}
+write_error:
 			BIO_free(file);
 			break;
 			}
@@ -1068,12 +1180,13 @@
 			break;
 		}
 end:
-#if 0
+#if 1
 	/* make sure we re-use sessions */
 	SSL_set_shutdown(con,SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN);
 #else
 	/* This kills performace */
-	SSL_shutdown(con);
+/*	SSL_shutdown(con); A shutdown gets sent in the
+ *	BIO_free_all(io) procession */
 #endif
 
 err:
@@ -1082,7 +1195,7 @@
 		BIO_printf(bio_s_out,"ACCEPT\n");
 
 	if (io != NULL) BIO_free_all(io);
-/*	if (ssl_bio != NULL) BIO_free(ssl_bio); */
+/*	if (ssl_bio != NULL) BIO_free(ssl_bio);*/
 	return(ret);
 	}
 
@@ -1100,7 +1213,7 @@
 			BIO_flush(bio_err);
 			}
 #ifndef NO_RSA
-		rsa_tmp=RSA_generate_key(512,RSA_F4,NULL);
+		rsa_tmp=RSA_generate_key(512,RSA_F4,NULL,NULL);
 #endif
 		if (!s_quiet)
 			{