| Index: openssl/apps/apps.c
 | 
| ===================================================================
 | 
| --- openssl/apps/apps.c	(revision 105093)
 | 
| +++ openssl/apps/apps.c	(working copy)
 | 
| @@ -109,12 +109,21 @@
 | 
|   *
 | 
|   */
 | 
|  
 | 
| +#ifndef _POSIX_C_SOURCE
 | 
| +#define _POSIX_C_SOURCE 2	/* On VMS, you need to define this to get
 | 
| +				   the declaration of fileno().  The value
 | 
| +				   2 is to make sure no function defined
 | 
| +				   in POSIX-2 is left undefined. */
 | 
| +#endif
 | 
|  #include <stdio.h>
 | 
|  #include <stdlib.h>
 | 
|  #include <string.h>
 | 
| +#if !defined(OPENSSL_SYSNAME_WIN32) && !defined(NETWARE_CLIB)
 | 
| +#include <strings.h>
 | 
| +#endif
 | 
|  #include <sys/types.h>
 | 
| -#include <sys/stat.h>
 | 
|  #include <ctype.h>
 | 
| +#include <errno.h>
 | 
|  #include <assert.h>
 | 
|  #include <openssl/err.h>
 | 
|  #include <openssl/x509.h>
 | 
| @@ -138,6 +147,11 @@
 | 
|  #include "apps.h"
 | 
|  #undef NON_MAIN
 | 
|  
 | 
| +#ifdef _WIN32
 | 
| +static int WIN32_rename(const char *from, const char *to);
 | 
| +#define rename(from,to) WIN32_rename((from),(to))
 | 
| +#endif
 | 
| +
 | 
|  typedef struct {
 | 
|  	const char *name;
 | 
|  	unsigned long flag;
 | 
| @@ -166,18 +180,23 @@
 | 
|  	static char *buf=NULL;
 | 
|  	static char **arg=NULL;
 | 
|  	char *p;
 | 
| -	struct stat stbuf;
 | 
|  
 | 
| -	if (stat(file,&stbuf) < 0) return(0);
 | 
| -
 | 
|  	fp=fopen(file,"r");
 | 
|  	if (fp == NULL)
 | 
|  		return(0);
 | 
|  
 | 
| +	if (fseek(fp,0,SEEK_END)==0)
 | 
| +		len=ftell(fp), rewind(fp);
 | 
| +	else	len=-1;
 | 
| +	if (len<=0)
 | 
| +		{
 | 
| +		fclose(fp);
 | 
| +		return(0);
 | 
| +		}
 | 
| +
 | 
|  	*argc=0;
 | 
|  	*argv=NULL;
 | 
|  
 | 
| -	len=(unsigned int)stbuf.st_size;
 | 
|  	if (buf != NULL) OPENSSL_free(buf);
 | 
|  	buf=(char *)OPENSSL_malloc(len+1);
 | 
|  	if (buf == NULL) return(0);
 | 
| @@ -238,22 +257,31 @@
 | 
|  
 | 
|  int str2fmt(char *s)
 | 
|  	{
 | 
| +	if (s == NULL)
 | 
| +		return FORMAT_UNDEF;
 | 
|  	if 	((*s == 'D') || (*s == 'd'))
 | 
|  		return(FORMAT_ASN1);
 | 
|  	else if ((*s == 'T') || (*s == 't'))
 | 
|  		return(FORMAT_TEXT);
 | 
| -	else if ((*s == 'P') || (*s == 'p'))
 | 
| -		return(FORMAT_PEM);
 | 
| -	else if ((*s == 'N') || (*s == 'n'))
 | 
| -		return(FORMAT_NETSCAPE);
 | 
| -	else if ((*s == 'S') || (*s == 's'))
 | 
| -		return(FORMAT_SMIME);
 | 
| +  	else if ((*s == 'N') || (*s == 'n'))
 | 
| +  		return(FORMAT_NETSCAPE);
 | 
| +  	else if ((*s == 'S') || (*s == 's'))
 | 
| +  		return(FORMAT_SMIME);
 | 
| + 	else if ((*s == 'M') || (*s == 'm'))
 | 
| + 		return(FORMAT_MSBLOB);
 | 
|  	else if ((*s == '1')
 | 
|  		|| (strcmp(s,"PKCS12") == 0) || (strcmp(s,"pkcs12") == 0)
 | 
|  		|| (strcmp(s,"P12") == 0) || (strcmp(s,"p12") == 0))
 | 
|  		return(FORMAT_PKCS12);
 | 
|  	else if ((*s == 'E') || (*s == 'e'))
 | 
|  		return(FORMAT_ENGINE);
 | 
| +	else if ((*s == 'P') || (*s == 'p'))
 | 
| + 		{
 | 
| + 		if (s[1] == 'V' || s[1] == 'v')
 | 
| + 			return FORMAT_PVK;
 | 
| + 		else
 | 
| +  			return(FORMAT_PEM);
 | 
| + 		}
 | 
|  	else
 | 
|  		return(FORMAT_UNDEF);
 | 
|  	}
 | 
| @@ -351,13 +379,12 @@
 | 
|  
 | 
|  int chopup_args(ARGS *arg, char *buf, int *argc, char **argv[])
 | 
|  	{
 | 
| -	int num,len,i;
 | 
| +	int num,i;
 | 
|  	char *p;
 | 
|  
 | 
|  	*argc=0;
 | 
|  	*argv=NULL;
 | 
|  
 | 
| -	len=strlen(buf);
 | 
|  	i=0;
 | 
|  	if (arg->count == 0)
 | 
|  		{
 | 
| @@ -639,6 +666,15 @@
 | 
|  				BIO_printf(err, "Can't open file %s\n", arg + 5);
 | 
|  				return NULL;
 | 
|  			}
 | 
| +#if !defined(_WIN32)
 | 
| +		/*
 | 
| +		 * Under _WIN32, which covers even Win64 and CE, file
 | 
| +		 * descriptors referenced by BIO_s_fd are not inherited
 | 
| +		 * by child process and therefore below is not an option.
 | 
| +		 * It could have been an option if bss_fd.c was operating
 | 
| +		 * on real Windows descriptors, such as those obtained
 | 
| +		 * with CreateFile.
 | 
| +		 */
 | 
|  		} else if(!strncmp(arg, "fd:", 3)) {
 | 
|  			BIO *btmp;
 | 
|  			i = atoi(arg + 3);
 | 
| @@ -650,6 +686,7 @@
 | 
|  			/* Can't do BIO_gets on an fd BIO so add a buffering BIO */
 | 
|  			btmp = BIO_new(BIO_f_buffer());
 | 
|  			pwdbio = BIO_push(btmp, pwdbio);
 | 
| +#endif
 | 
|  		} else if(!strcmp(arg, "stdin")) {
 | 
|  			pwdbio = BIO_new_fp(stdin, BIO_NOCLOSE);
 | 
|  			if(!pwdbio) {
 | 
| @@ -749,8 +786,6 @@
 | 
|  X509 *load_cert(BIO *err, const char *file, int format,
 | 
|  	const char *pass, ENGINE *e, const char *cert_descrip)
 | 
|  	{
 | 
| -	ASN1_HEADER *ah=NULL;
 | 
| -	BUF_MEM *buf=NULL;
 | 
|  	X509 *x=NULL;
 | 
|  	BIO *cert;
 | 
|  
 | 
| @@ -762,7 +797,11 @@
 | 
|  
 | 
|  	if (file == NULL)
 | 
|  		{
 | 
| +#ifdef _IONBF
 | 
| +# ifndef OPENSSL_NO_SETVBUF_IONBF
 | 
|  		setvbuf(stdin, NULL, _IONBF, 0);
 | 
| +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
 | 
| +#endif
 | 
|  		BIO_set_fp(cert,stdin,BIO_NOCLOSE);
 | 
|  		}
 | 
|  	else
 | 
| @@ -780,46 +819,21 @@
 | 
|  		x=d2i_X509_bio(cert,NULL);
 | 
|  	else if (format == FORMAT_NETSCAPE)
 | 
|  		{
 | 
| -		const unsigned char *p,*op;
 | 
| -		int size=0,i;
 | 
| -
 | 
| -		/* We sort of have to do it this way because it is sort of nice
 | 
| -		 * to read the header first and check it, then
 | 
| -		 * try to read the certificate */
 | 
| -		buf=BUF_MEM_new();
 | 
| -		for (;;)
 | 
| -			{
 | 
| -			if ((buf == NULL) || (!BUF_MEM_grow(buf,size+1024*10)))
 | 
| +		NETSCAPE_X509 *nx;
 | 
| +		nx=ASN1_item_d2i_bio(ASN1_ITEM_rptr(NETSCAPE_X509),cert,NULL);
 | 
| +		if (nx == NULL)
 | 
|  				goto end;
 | 
| -			i=BIO_read(cert,&(buf->data[size]),1024*10);
 | 
| -			size+=i;
 | 
| -			if (i == 0) break;
 | 
| -			if (i < 0)
 | 
| -				{
 | 
| -				perror("reading certificate");
 | 
| -				goto end;
 | 
| -				}
 | 
| -			}
 | 
| -		p=(unsigned char *)buf->data;
 | 
| -		op=p;
 | 
|  
 | 
| -		/* First load the header */
 | 
| -		if ((ah=d2i_ASN1_HEADER(NULL,&p,(long)size)) == NULL)
 | 
| -			goto end;
 | 
| -		if ((ah->header == NULL) || (ah->header->data == NULL) ||
 | 
| -			(strncmp(NETSCAPE_CERT_HDR,(char *)ah->header->data,
 | 
| -			ah->header->length) != 0))
 | 
| +		if ((strncmp(NETSCAPE_CERT_HDR,(char *)nx->header->data,
 | 
| +			nx->header->length) != 0))
 | 
|  			{
 | 
| +			NETSCAPE_X509_free(nx);
 | 
|  			BIO_printf(err,"Error reading header on certificate\n");
 | 
|  			goto end;
 | 
|  			}
 | 
| -		/* header is ok, so now read the object */
 | 
| -		p=op;
 | 
| -		ah->meth=X509_asn1_meth();
 | 
| -		if ((ah=d2i_ASN1_HEADER(&ah,&p,(long)size)) == NULL)
 | 
| -			goto end;
 | 
| -		x=(X509 *)ah->data;
 | 
| -		ah->data=NULL;
 | 
| +		x=nx->cert;
 | 
| +		nx->cert = NULL;
 | 
| +		NETSCAPE_X509_free(nx);
 | 
|  		}
 | 
|  	else if (format == FORMAT_PEM)
 | 
|  		x=PEM_read_bio_X509_AUX(cert,NULL,
 | 
| @@ -841,9 +855,7 @@
 | 
|  		BIO_printf(err,"unable to load certificate\n");
 | 
|  		ERR_print_errors(err);
 | 
|  		}
 | 
| -	if (ah != NULL) ASN1_HEADER_free(ah);
 | 
|  	if (cert != NULL) BIO_free(cert);
 | 
| -	if (buf != NULL) BUF_MEM_free(buf);
 | 
|  	return(x);
 | 
|  	}
 | 
|  
 | 
| @@ -888,7 +900,11 @@
 | 
|  		}
 | 
|  	if (file == NULL && maybe_stdin)
 | 
|  		{
 | 
| +#ifdef _IONBF
 | 
| +# ifndef OPENSSL_NO_SETVBUF_IONBF
 | 
|  		setvbuf(stdin, NULL, _IONBF, 0);
 | 
| +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
 | 
| +#endif
 | 
|  		BIO_set_fp(key,stdin,BIO_NOCLOSE);
 | 
|  		}
 | 
|  	else
 | 
| @@ -919,6 +935,13 @@
 | 
|  				&pkey, NULL, NULL))
 | 
|  			goto end;
 | 
|  		}
 | 
| +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA) && !defined (OPENSSL_NO_RC4)
 | 
| +	else if (format == FORMAT_MSBLOB)
 | 
| +		pkey = b2i_PrivateKey_bio(key);
 | 
| +	else if (format == FORMAT_PVK)
 | 
| +		pkey = b2i_PVK_bio(key, (pem_password_cb *)password_callback,
 | 
| +								&cb_data);
 | 
| +#endif
 | 
|  	else
 | 
|  		{
 | 
|  		BIO_printf(err,"bad input format specified for key file\n");
 | 
| @@ -968,7 +991,11 @@
 | 
|  		}
 | 
|  	if (file == NULL && maybe_stdin)
 | 
|  		{
 | 
| +#ifdef _IONBF
 | 
| +# ifndef OPENSSL_NO_SETVBUF_IONBF
 | 
|  		setvbuf(stdin, NULL, _IONBF, 0);
 | 
| +# endif /* ndef OPENSSL_NO_SETVBUF_IONBF */
 | 
| +#endif
 | 
|  		BIO_set_fp(key,stdin,BIO_NOCLOSE);
 | 
|  		}
 | 
|  	else
 | 
| @@ -983,6 +1010,37 @@
 | 
|  		{
 | 
|  		pkey=d2i_PUBKEY_bio(key, NULL);
 | 
|  		}
 | 
| +#ifndef OPENSSL_NO_RSA
 | 
| +	else if (format == FORMAT_ASN1RSA)
 | 
| +		{
 | 
| +		RSA *rsa;
 | 
| +		rsa = d2i_RSAPublicKey_bio(key, NULL);
 | 
| +		if (rsa)
 | 
| +			{
 | 
| +			pkey = EVP_PKEY_new();
 | 
| +			if (pkey)
 | 
| +				EVP_PKEY_set1_RSA(pkey, rsa);
 | 
| +			RSA_free(rsa);
 | 
| +			}
 | 
| +		else
 | 
| +			pkey = NULL;
 | 
| +		}
 | 
| +	else if (format == FORMAT_PEMRSA)
 | 
| +		{
 | 
| +		RSA *rsa;
 | 
| +		rsa = PEM_read_bio_RSAPublicKey(key, NULL, 
 | 
| +			(pem_password_cb *)password_callback, &cb_data);
 | 
| +		if (rsa)
 | 
| +			{
 | 
| +			pkey = EVP_PKEY_new();
 | 
| +			if (pkey)
 | 
| +				EVP_PKEY_set1_RSA(pkey, rsa);
 | 
| +			RSA_free(rsa);
 | 
| +			}
 | 
| +		else
 | 
| +			pkey = NULL;
 | 
| +		}
 | 
| +#endif
 | 
|  	else if (format == FORMAT_PEM)
 | 
|  		{
 | 
|  		pkey=PEM_read_bio_PUBKEY(key,NULL,
 | 
| @@ -992,6 +1050,10 @@
 | 
|  	else if (format == FORMAT_NETSCAPE || format == FORMAT_IISSGC)
 | 
|  		pkey = load_netscape_key(err, key, file, key_descrip, format);
 | 
|  #endif
 | 
| +#if !defined(OPENSSL_NO_RSA) && !defined(OPENSSL_NO_DSA)
 | 
| +	else if (format == FORMAT_MSBLOB)
 | 
| +		pkey = b2i_PublicKey_bio(key);
 | 
| +#endif
 | 
|  	else
 | 
|  		{
 | 
|  		BIO_printf(err,"bad input format specified for key file\n");
 | 
| @@ -1050,77 +1112,121 @@
 | 
|  	}
 | 
|  #endif /* ndef OPENSSL_NO_RC4 */
 | 
|  
 | 
| -STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
 | 
| -	const char *pass, ENGINE *e, const char *cert_descrip)
 | 
| +static int load_certs_crls(BIO *err, const char *file, int format,
 | 
| +	const char *pass, ENGINE *e, const char *desc,
 | 
| +	STACK_OF(X509) **pcerts, STACK_OF(X509_CRL) **pcrls)
 | 
|  	{
 | 
| -	BIO *certs;
 | 
|  	int i;
 | 
| -	STACK_OF(X509) *othercerts = NULL;
 | 
| -	STACK_OF(X509_INFO) *allcerts = NULL;
 | 
| +	BIO *bio;
 | 
| +	STACK_OF(X509_INFO) *xis = NULL;
 | 
|  	X509_INFO *xi;
 | 
|  	PW_CB_DATA cb_data;
 | 
| +	int rv = 0;
 | 
|  
 | 
|  	cb_data.password = pass;
 | 
|  	cb_data.prompt_info = file;
 | 
|  
 | 
| -	if((certs = BIO_new(BIO_s_file())) == NULL)
 | 
| +	if (format != FORMAT_PEM)
 | 
|  		{
 | 
| -		ERR_print_errors(err);
 | 
| -		goto end;
 | 
| +		BIO_printf(err,"bad input format specified for %s\n", desc);
 | 
| +		return 0;
 | 
|  		}
 | 
|  
 | 
|  	if (file == NULL)
 | 
| -		BIO_set_fp(certs,stdin,BIO_NOCLOSE);
 | 
| +		bio = BIO_new_fp(stdin,BIO_NOCLOSE);
 | 
|  	else
 | 
| +		bio = BIO_new_file(file, "r");
 | 
| +
 | 
| +	if (bio == NULL)
 | 
|  		{
 | 
| -		if (BIO_read_filename(certs,file) <= 0)
 | 
| -			{
 | 
| -			BIO_printf(err, "Error opening %s %s\n",
 | 
| -				cert_descrip, file);
 | 
| -			ERR_print_errors(err);
 | 
| +		BIO_printf(err, "Error opening %s %s\n",
 | 
| +				desc, file ? file : "stdin");
 | 
| +		ERR_print_errors(err);
 | 
| +		return 0;
 | 
| +		}
 | 
| +
 | 
| +	xis = PEM_X509_INFO_read_bio(bio, NULL,
 | 
| +				(pem_password_cb *)password_callback, &cb_data);
 | 
| +
 | 
| +	BIO_free(bio);
 | 
| +
 | 
| +	if (pcerts)
 | 
| +		{
 | 
| +		*pcerts = sk_X509_new_null();
 | 
| +		if (!*pcerts)
 | 
|  			goto end;
 | 
| -			}
 | 
|  		}
 | 
|  
 | 
| -	if      (format == FORMAT_PEM)
 | 
| +	if (pcrls)
 | 
|  		{
 | 
| -		othercerts = sk_X509_new_null();
 | 
| -		if(!othercerts)
 | 
| +		*pcrls = sk_X509_CRL_new_null();
 | 
| +		if (!*pcrls)
 | 
| +			goto end;
 | 
| +		}
 | 
| +
 | 
| +	for(i = 0; i < sk_X509_INFO_num(xis); i++)
 | 
| +		{
 | 
| +		xi = sk_X509_INFO_value (xis, i);
 | 
| +		if (xi->x509 && pcerts)
 | 
|  			{
 | 
| -			sk_X509_free(othercerts);
 | 
| -			othercerts = NULL;
 | 
| -			goto end;
 | 
| +			if (!sk_X509_push(*pcerts, xi->x509))
 | 
| +				goto end;
 | 
| +			xi->x509 = NULL;
 | 
|  			}
 | 
| -		allcerts = PEM_X509_INFO_read_bio(certs, NULL,
 | 
| -				(pem_password_cb *)password_callback, &cb_data);
 | 
| -		for(i = 0; i < sk_X509_INFO_num(allcerts); i++)
 | 
| +		if (xi->crl && pcrls)
 | 
|  			{
 | 
| -			xi = sk_X509_INFO_value (allcerts, i);
 | 
| -			if (xi->x509)
 | 
| -				{
 | 
| -				sk_X509_push(othercerts, xi->x509);
 | 
| -				xi->x509 = NULL;
 | 
| -				}
 | 
| +			if (!sk_X509_CRL_push(*pcrls, xi->crl))
 | 
| +				goto end;
 | 
| +			xi->crl = NULL;
 | 
|  			}
 | 
| -		goto end;
 | 
|  		}
 | 
| -	else	{
 | 
| -		BIO_printf(err,"bad input format specified for %s\n",
 | 
| -			cert_descrip);
 | 
| -		goto end;
 | 
| -		}
 | 
| -end:
 | 
| -	if (othercerts == NULL)
 | 
| +
 | 
| +	if (pcerts && sk_X509_num(*pcerts) > 0)
 | 
| +		rv = 1;
 | 
| +
 | 
| +	if (pcrls && sk_X509_CRL_num(*pcrls) > 0)
 | 
| +		rv = 1;
 | 
| +
 | 
| +	end:
 | 
| +
 | 
| +	if (xis)
 | 
| +		sk_X509_INFO_pop_free(xis, X509_INFO_free);
 | 
| +
 | 
| +	if (rv == 0)
 | 
|  		{
 | 
| -		BIO_printf(err,"unable to load certificates\n");
 | 
| +		if (pcerts)
 | 
| +			{
 | 
| +			sk_X509_pop_free(*pcerts, X509_free);
 | 
| +			*pcerts = NULL;
 | 
| +			}
 | 
| +		if (pcrls)
 | 
| +			{
 | 
| +			sk_X509_CRL_pop_free(*pcrls, X509_CRL_free);
 | 
| +			*pcrls = NULL;
 | 
| +			}
 | 
| +		BIO_printf(err,"unable to load %s\n",
 | 
| +				pcerts ? "certificates" : "CRLs");
 | 
|  		ERR_print_errors(err);
 | 
|  		}
 | 
| -	if (allcerts) sk_X509_INFO_pop_free(allcerts, X509_INFO_free);
 | 
| -	if (certs != NULL) BIO_free(certs);
 | 
| -	return(othercerts);
 | 
| +	return rv;
 | 
|  	}
 | 
|  
 | 
| +STACK_OF(X509) *load_certs(BIO *err, const char *file, int format,
 | 
| +	const char *pass, ENGINE *e, const char *desc)
 | 
| +	{
 | 
| +	STACK_OF(X509) *certs;
 | 
| +	load_certs_crls(err, file, format, pass, e, desc, &certs, NULL);
 | 
| +	return certs;
 | 
| +	}	
 | 
|  
 | 
| +STACK_OF(X509_CRL) *load_crls(BIO *err, const char *file, int format,
 | 
| +	const char *pass, ENGINE *e, const char *desc)
 | 
| +	{
 | 
| +	STACK_OF(X509_CRL) *crls;
 | 
| +	load_certs_crls(err, file, format, pass, e, desc, NULL, &crls);
 | 
| +	return crls;
 | 
| +	}	
 | 
| +
 | 
|  #define X509V3_EXT_UNKNOWN_MASK		(0xfL << 16)
 | 
|  /* Return error for unknown extensions */
 | 
|  #define X509V3_EXT_DEFAULT		0
 | 
| @@ -1406,6 +1512,10 @@
 | 
|  
 | 
|  int load_config(BIO *err, CONF *cnf)
 | 
|  	{
 | 
| +	static int load_config_called = 0;
 | 
| +	if (load_config_called)
 | 
| +		return 1;
 | 
| +	load_config_called = 1;
 | 
|  	if (!cnf)
 | 
|  		cnf = config;
 | 
|  	if (!cnf)
 | 
| @@ -1439,7 +1549,7 @@
 | 
|  	return p;
 | 
|  	}
 | 
|  
 | 
| -static unsigned long index_serial_hash(const char **a)
 | 
| +static unsigned long index_serial_hash(const OPENSSL_CSTRING *a)
 | 
|  	{
 | 
|  	const char *n;
 | 
|  
 | 
| @@ -1448,7 +1558,7 @@
 | 
|  	return(lh_strhash(n));
 | 
|  	}
 | 
|  
 | 
| -static int index_serial_cmp(const char **a, const char **b)
 | 
| +static int index_serial_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
 | 
|  	{
 | 
|  	const char *aa,*bb;
 | 
|  
 | 
| @@ -1460,17 +1570,16 @@
 | 
|  static int index_name_qual(char **a)
 | 
|  	{ return(a[0][0] == 'V'); }
 | 
|  
 | 
| -static unsigned long index_name_hash(const char **a)
 | 
| +static unsigned long index_name_hash(const OPENSSL_CSTRING *a)
 | 
|  	{ return(lh_strhash(a[DB_name])); }
 | 
|  
 | 
| -int index_name_cmp(const char **a, const char **b)
 | 
| -	{ return(strcmp(a[DB_name],
 | 
| -	     b[DB_name])); }
 | 
| +int index_name_cmp(const OPENSSL_CSTRING *a, const OPENSSL_CSTRING *b)
 | 
| +	{ return(strcmp(a[DB_name], b[DB_name])); }
 | 
|  
 | 
| -static IMPLEMENT_LHASH_HASH_FN(index_serial_hash,const char **)
 | 
| -static IMPLEMENT_LHASH_COMP_FN(index_serial_cmp,const char **)
 | 
| -static IMPLEMENT_LHASH_HASH_FN(index_name_hash,const char **)
 | 
| -static IMPLEMENT_LHASH_COMP_FN(index_name_cmp,const char **)
 | 
| +static IMPLEMENT_LHASH_HASH_FN(index_serial, OPENSSL_CSTRING)
 | 
| +static IMPLEMENT_LHASH_COMP_FN(index_serial, OPENSSL_CSTRING)
 | 
| +static IMPLEMENT_LHASH_HASH_FN(index_name, OPENSSL_CSTRING)
 | 
| +static IMPLEMENT_LHASH_COMP_FN(index_name, OPENSSL_CSTRING)
 | 
|  
 | 
|  #undef BSIZE
 | 
|  #define BSIZE 256
 | 
| @@ -1598,7 +1707,6 @@
 | 
|  	{
 | 
|  	char buf[5][BSIZE];
 | 
|  	int i,j;
 | 
| -	struct stat sb;
 | 
|  
 | 
|  	i = strlen(serialfile) + strlen(old_suffix);
 | 
|  	j = strlen(serialfile) + strlen(new_suffix);
 | 
| @@ -1623,30 +1731,21 @@
 | 
|  	j = BIO_snprintf(buf[1], sizeof buf[1], "%s-%s",
 | 
|  		serialfile, old_suffix);
 | 
|  #endif
 | 
| -	if (stat(serialfile,&sb) < 0)
 | 
| -		{
 | 
| -		if (errno != ENOENT 
 | 
| +#ifdef RL_DEBUG
 | 
| +	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
| +		serialfile, buf[1]);
 | 
| +#endif
 | 
| +	if (rename(serialfile,buf[1]) < 0 && errno != ENOENT
 | 
|  #ifdef ENOTDIR
 | 
|  			&& errno != ENOTDIR
 | 
|  #endif
 | 
| -		   )
 | 
| -			goto err;
 | 
| -		}
 | 
| -	else
 | 
| -		{
 | 
| -#ifdef RL_DEBUG
 | 
| -		BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
| -			serialfile, buf[1]);
 | 
| -#endif
 | 
| -		if (rename(serialfile,buf[1]) < 0)
 | 
| -			{
 | 
| +	   )		{
 | 
|  			BIO_printf(bio_err,
 | 
|  				"unable to rename %s to %s\n",
 | 
|  				serialfile, buf[1]);
 | 
|  			perror("reason");
 | 
|  			goto err;
 | 
|  			}
 | 
| -		}
 | 
|  #ifdef RL_DEBUG
 | 
|  	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
|  		buf[0],serialfile);
 | 
| @@ -1713,10 +1812,7 @@
 | 
|  		goto err;
 | 
|  		}
 | 
|  	if ((tmpdb = TXT_DB_read(in,DB_NUMBER)) == NULL)
 | 
| -		{
 | 
| -		if (tmpdb != NULL) TXT_DB_free(tmpdb);
 | 
|  		goto err;
 | 
| -		}
 | 
|  
 | 
|  #ifndef OPENSSL_SYS_VMS
 | 
|  	BIO_snprintf(buf[0], sizeof buf[0], "%s.attr", dbfile);
 | 
| @@ -1777,8 +1873,8 @@
 | 
|  int index_index(CA_DB *db)
 | 
|  	{
 | 
|  	if (!TXT_DB_create_index(db->db, DB_serial, NULL,
 | 
| -				LHASH_HASH_FN(index_serial_hash),
 | 
| -				LHASH_COMP_FN(index_serial_cmp)))
 | 
| +				LHASH_HASH_FN(index_serial),
 | 
| +				LHASH_COMP_FN(index_serial)))
 | 
|  		{
 | 
|  		BIO_printf(bio_err,
 | 
|  		  "error creating serial number index:(%ld,%ld,%ld)\n",
 | 
| @@ -1788,8 +1884,8 @@
 | 
|  
 | 
|  	if (db->attributes.unique_subject
 | 
|  		&& !TXT_DB_create_index(db->db, DB_name, index_name_qual,
 | 
| -			LHASH_HASH_FN(index_name_hash),
 | 
| -			LHASH_COMP_FN(index_name_cmp)))
 | 
| +			LHASH_HASH_FN(index_name),
 | 
| +			LHASH_COMP_FN(index_name)))
 | 
|  		{
 | 
|  		BIO_printf(bio_err,"error creating name index:(%ld,%ld,%ld)\n",
 | 
|  			db->db->error,db->db->arg1,db->db->arg2);
 | 
| @@ -1869,7 +1965,6 @@
 | 
|  	{
 | 
|  	char buf[5][BSIZE];
 | 
|  	int i,j;
 | 
| -	struct stat sb;
 | 
|  
 | 
|  	i = strlen(dbfile) + strlen(old_suffix);
 | 
|  	j = strlen(dbfile) + strlen(new_suffix);
 | 
| @@ -1913,30 +2008,21 @@
 | 
|  	j = BIO_snprintf(buf[3], sizeof buf[3], "%s-attr-%s",
 | 
|  		dbfile, old_suffix);
 | 
|  #endif
 | 
| -	if (stat(dbfile,&sb) < 0)
 | 
| -		{
 | 
| -		if (errno != ENOENT 
 | 
| +#ifdef RL_DEBUG
 | 
| +	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
| +		dbfile, buf[1]);
 | 
| +#endif
 | 
| +	if (rename(dbfile,buf[1]) < 0 && errno != ENOENT
 | 
|  #ifdef ENOTDIR
 | 
| -			&& errno != ENOTDIR
 | 
| +		&& errno != ENOTDIR
 | 
|  #endif
 | 
| -		   )
 | 
| -			goto err;
 | 
| -		}
 | 
| -	else
 | 
| -		{
 | 
| -#ifdef RL_DEBUG
 | 
| -		BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
| -			dbfile, buf[1]);
 | 
| -#endif
 | 
| -		if (rename(dbfile,buf[1]) < 0)
 | 
| -			{
 | 
| +	   )		{
 | 
|  			BIO_printf(bio_err,
 | 
|  				"unable to rename %s to %s\n",
 | 
|  				dbfile, buf[1]);
 | 
|  			perror("reason");
 | 
|  			goto err;
 | 
|  			}
 | 
| -		}
 | 
|  #ifdef RL_DEBUG
 | 
|  	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
|  		buf[0],dbfile);
 | 
| @@ -1950,23 +2036,15 @@
 | 
|  		rename(buf[1],dbfile);
 | 
|  		goto err;
 | 
|  		}
 | 
| -	if (stat(buf[4],&sb) < 0)
 | 
| -		{
 | 
| -		if (errno != ENOENT 
 | 
| +#ifdef RL_DEBUG
 | 
| +	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
| +		buf[4],buf[3]);
 | 
| +#endif
 | 
| +	if (rename(buf[4],buf[3]) < 0 && errno != ENOENT
 | 
|  #ifdef ENOTDIR
 | 
| -			&& errno != ENOTDIR
 | 
| +		&& errno != ENOTDIR
 | 
|  #endif
 | 
| -		   )
 | 
| -			goto err;
 | 
| -		}
 | 
| -	else
 | 
| -		{
 | 
| -#ifdef RL_DEBUG
 | 
| -		BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
| -			buf[4],buf[3]);
 | 
| -#endif
 | 
| -		if (rename(buf[4],buf[3]) < 0)
 | 
| -			{
 | 
| +	   )		{
 | 
|  			BIO_printf(bio_err,
 | 
|  				"unable to rename %s to %s\n",
 | 
|  				buf[4], buf[3]);
 | 
| @@ -1975,7 +2053,6 @@
 | 
|  			rename(buf[1],dbfile);
 | 
|  			goto err;
 | 
|  			}
 | 
| -		}
 | 
|  #ifdef RL_DEBUG
 | 
|  	BIO_printf(bio_err, "DEBUG: renaming \"%s\" to \"%s\"\n",
 | 
|  		buf[2],buf[4]);
 | 
| @@ -2170,52 +2247,13 @@
 | 
|  	return NULL;
 | 
|  }
 | 
|  
 | 
| -/* This code MUST COME AFTER anything that uses rename() */
 | 
| -#ifdef OPENSSL_SYS_WIN32
 | 
| -int WIN32_rename(const char *from, const char *to)
 | 
| -	{
 | 
| -#ifndef OPENSSL_SYS_WINCE
 | 
| -	/* Windows rename gives an error if 'to' exists, so delete it
 | 
| -	 * first and ignore file not found errror
 | 
| -	 */
 | 
| -	if((remove(to) != 0) && (errno != ENOENT))
 | 
| -		return -1;
 | 
| -#undef rename
 | 
| -	return rename(from, to);
 | 
| -#else
 | 
| -	/* convert strings to UNICODE */
 | 
| -	{
 | 
| -	BOOL result = FALSE;
 | 
| -	WCHAR* wfrom;
 | 
| -	WCHAR* wto;
 | 
| -	int i;
 | 
| -	wfrom = malloc((strlen(from)+1)*2);
 | 
| -	wto = malloc((strlen(to)+1)*2);
 | 
| -	if (wfrom != NULL && wto != NULL)
 | 
| -		{
 | 
| -		for (i=0; i<(int)strlen(from)+1; i++)
 | 
| -			wfrom[i] = (short)from[i];
 | 
| -		for (i=0; i<(int)strlen(to)+1; i++)
 | 
| -			wto[i] = (short)to[i];
 | 
| -		result = MoveFile(wfrom, wto);
 | 
| -		}
 | 
| -	if (wfrom != NULL)
 | 
| -		free(wfrom);
 | 
| -	if (wto != NULL)
 | 
| -		free(wto);
 | 
| -	return result;
 | 
| -	}
 | 
| -#endif
 | 
| -	}
 | 
| -#endif
 | 
| -
 | 
|  int args_verify(char ***pargs, int *pargc,
 | 
|  			int *badarg, BIO *err, X509_VERIFY_PARAM **pm)
 | 
|  	{
 | 
|  	ASN1_OBJECT *otmp = NULL;
 | 
|  	unsigned long flags = 0;
 | 
|  	int i;
 | 
| -	int purpose = 0;
 | 
| +	int purpose = 0, depth = -1;
 | 
|  	char **oldargs = *pargs;
 | 
|  	char *arg = **pargs, *argn = (*pargs)[1];
 | 
|  	if (!strcmp(arg, "-policy"))
 | 
| @@ -2255,6 +2293,21 @@
 | 
|  			}
 | 
|  		(*pargs)++;
 | 
|  		}
 | 
| +	else if (strcmp(arg,"-verify_depth") == 0)
 | 
| +		{
 | 
| +		if (!argn)
 | 
| +			*badarg = 1;
 | 
| +		else
 | 
| +			{
 | 
| +			depth = atoi(argn);
 | 
| +			if(depth < 0)
 | 
| +				{
 | 
| +				BIO_printf(err, "invalid depth\n");
 | 
| +				*badarg = 1;
 | 
| +				}
 | 
| +			}
 | 
| +		(*pargs)++;
 | 
| +		}
 | 
|  	else if (!strcmp(arg, "-ignore_critical"))
 | 
|  		flags |= X509_V_FLAG_IGNORE_CRITICAL;
 | 
|  	else if (!strcmp(arg, "-issuer_checks"))
 | 
| @@ -2267,8 +2320,16 @@
 | 
|  		flags |= X509_V_FLAG_POLICY_CHECK;
 | 
|  	else if (!strcmp(arg, "-explicit_policy"))
 | 
|  		flags |= X509_V_FLAG_EXPLICIT_POLICY;
 | 
| +	else if (!strcmp(arg, "-inhibit_any"))
 | 
| +		flags |= X509_V_FLAG_INHIBIT_ANY;
 | 
| +	else if (!strcmp(arg, "-inhibit_map"))
 | 
| +		flags |= X509_V_FLAG_INHIBIT_MAP;
 | 
|  	else if (!strcmp(arg, "-x509_strict"))
 | 
|  		flags |= X509_V_FLAG_X509_STRICT;
 | 
| +	else if (!strcmp(arg, "-extended_crl"))
 | 
| +		flags |= X509_V_FLAG_EXTENDED_CRL_SUPPORT;
 | 
| +	else if (!strcmp(arg, "-use_deltas"))
 | 
| +		flags |= X509_V_FLAG_USE_DELTAS;
 | 
|  	else if (!strcmp(arg, "-policy_print"))
 | 
|  		flags |= X509_V_FLAG_NOTIFY_POLICY;
 | 
|  	else if (!strcmp(arg, "-check_ss_sig"))
 | 
| @@ -2298,6 +2359,9 @@
 | 
|  	if (purpose)
 | 
|  		X509_VERIFY_PARAM_set_purpose(*pm, purpose);
 | 
|  
 | 
| +	if (depth >= 0)
 | 
| +		X509_VERIFY_PARAM_set_depth(*pm, depth);
 | 
| +
 | 
|  	end:
 | 
|  
 | 
|  	(*pargs)++;
 | 
| @@ -2309,6 +2373,61 @@
 | 
|  
 | 
|  	}
 | 
|  
 | 
| +/* Read whole contents of a BIO into an allocated memory buffer and
 | 
| + * return it.
 | 
| + */
 | 
| +
 | 
| +int bio_to_mem(unsigned char **out, int maxlen, BIO *in)
 | 
| +	{
 | 
| +	BIO *mem;
 | 
| +	int len, ret;
 | 
| +	unsigned char tbuf[1024];
 | 
| +	mem = BIO_new(BIO_s_mem());
 | 
| +	if (!mem)
 | 
| +		return -1;
 | 
| +	for(;;)
 | 
| +		{
 | 
| +		if ((maxlen != -1) && maxlen < 1024)
 | 
| +			len = maxlen;
 | 
| +		else
 | 
| +			len = 1024;
 | 
| +		len = BIO_read(in, tbuf, len);
 | 
| +		if (len <= 0)
 | 
| +			break;
 | 
| +		if (BIO_write(mem, tbuf, len) != len)
 | 
| +			{
 | 
| +			BIO_free(mem);
 | 
| +			return -1;
 | 
| +			}
 | 
| +		maxlen -= len;
 | 
| +
 | 
| +		if (maxlen == 0)
 | 
| +			break;
 | 
| +		}
 | 
| +	ret = BIO_get_mem_data(mem, (char **)out);
 | 
| +	BIO_set_flags(mem, BIO_FLAGS_MEM_RDONLY);
 | 
| +	BIO_free(mem);
 | 
| +	return ret;
 | 
| +	}
 | 
| +
 | 
| +int pkey_ctrl_string(EVP_PKEY_CTX *ctx, char *value)
 | 
| +	{
 | 
| +	int rv;
 | 
| +	char *stmp, *vtmp = NULL;
 | 
| +	stmp = BUF_strdup(value);
 | 
| +	if (!stmp)
 | 
| +		return -1;
 | 
| +	vtmp = strchr(stmp, ':');
 | 
| +	if (vtmp)
 | 
| +		{
 | 
| +		*vtmp = 0;
 | 
| +		vtmp++;
 | 
| +		}
 | 
| +	rv = EVP_PKEY_CTX_ctrl_str(ctx, stmp, vtmp);
 | 
| +	OPENSSL_free(stmp);
 | 
| +	return rv;
 | 
| +	}
 | 
| +
 | 
|  static void nodes_print(BIO *out, const char *name,
 | 
|  	STACK_OF(X509_POLICY_NODE) *nodes)
 | 
|  	{
 | 
| @@ -2350,7 +2469,7 @@
 | 
|  		BIO_free(out);
 | 
|  	}
 | 
|  
 | 
| -#ifndef OPENSSL_NO_JPAKE
 | 
| +#if !defined(OPENSSL_NO_JPAKE) && !defined(OPENSSL_NO_PSK)
 | 
|  
 | 
|  static JPAKE_CTX *jpake_init(const char *us, const char *them,
 | 
|  							 const char *secret)
 | 
| @@ -2533,17 +2652,14 @@
 | 
|  	jpake_send_step3a(bconn, ctx);
 | 
|  	jpake_receive_step3b(ctx, bconn);
 | 
|  
 | 
| -	/*
 | 
| -	 * The problem is that you must use the derived key in the
 | 
| -	 * session key or you are subject to man-in-the-middle
 | 
| -	 * attacks.
 | 
| -	 */
 | 
| -	BIO_puts(out, "JPAKE authentication succeeded (N.B. This version can"
 | 
| -		 " be MitMed. See the version in HEAD for how to do it"
 | 
| -		 " properly)\n");
 | 
| +	BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
 | 
|  
 | 
| +	psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
 | 
| +
 | 
|  	BIO_pop(bconn);
 | 
|  	BIO_free(bconn);
 | 
| +
 | 
| +	JPAKE_CTX_free(ctx);
 | 
|  	}
 | 
|  
 | 
|  void jpake_server_auth(BIO *out, BIO *conn, const char *secret)
 | 
| @@ -2565,28 +2681,351 @@
 | 
|  	jpake_receive_step3a(ctx, bconn);
 | 
|  	jpake_send_step3b(bconn, ctx);
 | 
|  
 | 
| -	/*
 | 
| -	 * The problem is that you must use the derived key in the
 | 
| -	 * session key or you are subject to man-in-the-middle
 | 
| -	 * attacks.
 | 
| -	 */
 | 
| -	BIO_puts(out, "JPAKE authentication succeeded (N.B. This version can"
 | 
| -		 " be MitMed. See the version in HEAD for how to do it"
 | 
| -		 " properly)\n");
 | 
| +	BIO_puts(out, "JPAKE authentication succeeded, setting PSK\n");
 | 
|  
 | 
| +	psk_key = BN_bn2hex(JPAKE_get_shared_key(ctx));
 | 
| +
 | 
|  	BIO_pop(bconn);
 | 
|  	BIO_free(bconn);
 | 
| +
 | 
| +	JPAKE_CTX_free(ctx);
 | 
|  	}
 | 
|  
 | 
|  #endif
 | 
|  
 | 
| +/*
 | 
| + * Platform-specific sections
 | 
| + */
 | 
| +#if defined(_WIN32)
 | 
| +# ifdef fileno
 | 
| +#  undef fileno
 | 
| +#  define fileno(a) (int)_fileno(a)
 | 
| +# endif
 | 
| +
 | 
| +# include <windows.h>
 | 
| +# include <tchar.h>
 | 
| +
 | 
| +static int WIN32_rename(const char *from, const char *to)
 | 
| +	{
 | 
| +	TCHAR  *tfrom=NULL,*tto;
 | 
| +	DWORD	err;
 | 
| +	int	ret=0;
 | 
| +
 | 
| +	if (sizeof(TCHAR) == 1)
 | 
| +		{
 | 
| +		tfrom = (TCHAR *)from;
 | 
| +		tto   = (TCHAR *)to;
 | 
| +		}
 | 
| +	else	/* UNICODE path */
 | 
| +		{
 | 
| +		size_t i,flen=strlen(from)+1,tlen=strlen(to)+1;
 | 
| +		tfrom = (TCHAR *)malloc(sizeof(TCHAR)*(flen+tlen));
 | 
| +		if (tfrom==NULL) goto err;
 | 
| +		tto=tfrom+flen;
 | 
| +#if !defined(_WIN32_WCE) || _WIN32_WCE>=101
 | 
| +		if (!MultiByteToWideChar(CP_ACP,0,from,flen,(WCHAR *)tfrom,flen))
 | 
| +#endif
 | 
| +			for (i=0;i<flen;i++)	tfrom[i]=(TCHAR)from[i];
 | 
| +#if !defined(_WIN32_WCE) || _WIN32_WCE>=101
 | 
| +		if (!MultiByteToWideChar(CP_ACP,0,to,  tlen,(WCHAR *)tto,  tlen))
 | 
| +#endif
 | 
| +			for (i=0;i<tlen;i++)	tto[i]  =(TCHAR)to[i];
 | 
| +		}
 | 
| +
 | 
| +	if (MoveFile(tfrom,tto))	goto ok;
 | 
| +	err=GetLastError();
 | 
| +	if (err==ERROR_ALREADY_EXISTS || err==ERROR_FILE_EXISTS)
 | 
| +		{
 | 
| +		if (DeleteFile(tto) && MoveFile(tfrom,tto))
 | 
| +			goto ok;
 | 
| +		err=GetLastError();
 | 
| +		}
 | 
| +	if (err==ERROR_FILE_NOT_FOUND || err==ERROR_PATH_NOT_FOUND)
 | 
| +		errno = ENOENT;
 | 
| +	else if (err==ERROR_ACCESS_DENIED)
 | 
| +		errno = EACCES;
 | 
| +	else
 | 
| +		errno = EINVAL;	/* we could map more codes... */
 | 
| +err:
 | 
| +	ret=-1;
 | 
| +ok:
 | 
| +	if (tfrom!=NULL && tfrom!=(TCHAR *)from)	free(tfrom);
 | 
| +	return ret;
 | 
| +	}
 | 
| +#endif
 | 
| +
 | 
| +/* app_tminterval section */
 | 
| +#if defined(_WIN32)
 | 
| +double app_tminterval(int stop,int usertime)
 | 
| +	{
 | 
| +	FILETIME		now;
 | 
| +	double			ret=0;
 | 
| +	static ULARGE_INTEGER	tmstart;
 | 
| +	static int		warning=1;
 | 
| +#ifdef _WIN32_WINNT
 | 
| +	static HANDLE		proc=NULL;
 | 
| +
 | 
| +	if (proc==NULL)
 | 
| +		{
 | 
| +		if (GetVersion() < 0x80000000)
 | 
| +			proc = OpenProcess(PROCESS_QUERY_INFORMATION,FALSE,
 | 
| +						GetCurrentProcessId());
 | 
| +		if (proc==NULL) proc = (HANDLE)-1;
 | 
| +		}
 | 
| +
 | 
| +	if (usertime && proc!=(HANDLE)-1)
 | 
| +		{
 | 
| +		FILETIME junk;
 | 
| +		GetProcessTimes(proc,&junk,&junk,&junk,&now);
 | 
| +		}
 | 
| +	else
 | 
| +#endif
 | 
| +		{
 | 
| +		SYSTEMTIME systime;
 | 
| +
 | 
| +		if (usertime && warning)
 | 
| +			{
 | 
| +			BIO_printf(bio_err,"To get meaningful results, run "
 | 
| +					   "this program on idle system.\n");
 | 
| +			warning=0;
 | 
| +			}
 | 
| +		GetSystemTime(&systime);
 | 
| +		SystemTimeToFileTime(&systime,&now);
 | 
| +		}
 | 
| +
 | 
| +	if (stop==TM_START)
 | 
| +		{
 | 
| +		tmstart.u.LowPart  = now.dwLowDateTime;
 | 
| +		tmstart.u.HighPart = now.dwHighDateTime;
 | 
| +		}
 | 
| +	else	{
 | 
| +		ULARGE_INTEGER tmstop;
 | 
| +
 | 
| +		tmstop.u.LowPart   = now.dwLowDateTime;
 | 
| +		tmstop.u.HighPart  = now.dwHighDateTime;
 | 
| +
 | 
| +		ret = (__int64)(tmstop.QuadPart - tmstart.QuadPart)*1e-7;
 | 
| +		}
 | 
| +
 | 
| +	return (ret);
 | 
| +	}
 | 
| +
 | 
| +#elif defined(OPENSSL_SYS_NETWARE)
 | 
| +#include <time.h>
 | 
| +
 | 
| +double app_tminterval(int stop,int usertime)
 | 
| +	{
 | 
| +	double		ret=0;
 | 
| +	static clock_t	tmstart;
 | 
| +	static int	warning=1;
 | 
| +
 | 
| +	if (usertime && warning)
 | 
| +		{
 | 
| +		BIO_printf(bio_err,"To get meaningful results, run "
 | 
| +				   "this program on idle system.\n");
 | 
| +		warning=0;
 | 
| +		}
 | 
| +
 | 
| +	if (stop==TM_START)	tmstart = clock();
 | 
| +	else			ret     = (clock()-tmstart)/(double)CLOCKS_PER_SEC;
 | 
| +
 | 
| +	return (ret);
 | 
| +	}
 | 
| +
 | 
| +#elif defined(OPENSSL_SYSTEM_VXWORKS)
 | 
| +#include <time.h>
 | 
| +
 | 
| +double app_tminterval(int stop,int usertime)
 | 
| +	{
 | 
| +	double ret=0;
 | 
| +#ifdef CLOCK_REALTIME
 | 
| +	static struct timespec	tmstart;
 | 
| +	struct timespec		now;
 | 
| +#else
 | 
| +	static unsigned long	tmstart;
 | 
| +	unsigned long		now;
 | 
| +#endif
 | 
| +	static int warning=1;
 | 
| +
 | 
| +	if (usertime && warning)
 | 
| +		{
 | 
| +		BIO_printf(bio_err,"To get meaningful results, run "
 | 
| +				   "this program on idle system.\n");
 | 
| +		warning=0;
 | 
| +		}
 | 
| +
 | 
| +#ifdef CLOCK_REALTIME
 | 
| +	clock_gettime(CLOCK_REALTIME,&now);
 | 
| +	if (stop==TM_START)	tmstart = now;
 | 
| +	else	ret = ( (now.tv_sec+now.tv_nsec*1e-9)
 | 
| +			- (tmstart.tv_sec+tmstart.tv_nsec*1e-9) );
 | 
| +#else
 | 
| +	now = tickGet();
 | 
| +	if (stop==TM_START)	tmstart = now;
 | 
| +	else			ret = (now - tmstart)/(double)sysClkRateGet();
 | 
| +#endif
 | 
| +	return (ret);
 | 
| +	}
 | 
| +
 | 
| +#elif defined(OPENSSL_SYSTEM_VMS)
 | 
| +#include <time.h>
 | 
| +#include <times.h>
 | 
| +
 | 
| +double app_tminterval(int stop,int usertime)
 | 
| +	{
 | 
| +	static clock_t	tmstart;
 | 
| +	double		ret = 0;
 | 
| +	clock_t		now;
 | 
| +#ifdef __TMS
 | 
| +	struct tms	rus;
 | 
| +
 | 
| +	now = times(&rus);
 | 
| +	if (usertime)	now = rus.tms_utime;
 | 
| +#else
 | 
| +	if (usertime)
 | 
| +		now = clock(); /* sum of user and kernel times */
 | 
| +	else	{
 | 
| +		struct timeval tv;
 | 
| +		gettimeofday(&tv,NULL);
 | 
| +		now = (clock_t)(
 | 
| +			(unsigned long long)tv.tv_sec*CLK_TCK +
 | 
| +			(unsigned long long)tv.tv_usec*(1000000/CLK_TCK)
 | 
| +			);
 | 
| +		}
 | 
| +#endif
 | 
| +	if (stop==TM_START)	tmstart = now;
 | 
| +	else			ret = (now - tmstart)/(double)(CLK_TCK);
 | 
| +
 | 
| +	return (ret);
 | 
| +	}
 | 
| +
 | 
| +#elif defined(_SC_CLK_TCK)	/* by means of unistd.h */
 | 
| +#include <sys/times.h>
 | 
| +
 | 
| +double app_tminterval(int stop,int usertime)
 | 
| +	{
 | 
| +	double		ret = 0;
 | 
| +	struct tms	rus;
 | 
| +	clock_t		now = times(&rus);
 | 
| +	static clock_t	tmstart;
 | 
| +
 | 
| +	if (usertime)		now = rus.tms_utime;
 | 
| +
 | 
| +	if (stop==TM_START)	tmstart = now;
 | 
| +	else
 | 
| +		{
 | 
| +		long int tck = sysconf(_SC_CLK_TCK);
 | 
| +		ret = (now - tmstart)/(double)tck;
 | 
| +		}
 | 
| +
 | 
| +	return (ret);
 | 
| +	}
 | 
| +
 | 
| +#else
 | 
| +#include <sys/time.h>
 | 
| +#include <sys/resource.h>
 | 
| +
 | 
| +double app_tminterval(int stop,int usertime)
 | 
| +	{
 | 
| +	double		ret = 0;
 | 
| +	struct rusage	rus;
 | 
| +	struct timeval	now;
 | 
| +	static struct timeval tmstart;
 | 
| +
 | 
| +	if (usertime)		getrusage(RUSAGE_SELF,&rus), now = rus.ru_utime;
 | 
| +	else			gettimeofday(&now,NULL);
 | 
| +
 | 
| +	if (stop==TM_START)	tmstart = now;
 | 
| +	else			ret = ( (now.tv_sec+now.tv_usec*1e-6)
 | 
| +					- (tmstart.tv_sec+tmstart.tv_usec*1e-6) );
 | 
| +
 | 
| +	return ret;
 | 
| +	}
 | 
| +#endif
 | 
| +
 | 
| +/* app_isdir section */
 | 
| +#ifdef _WIN32
 | 
| +int app_isdir(const char *name)
 | 
| +	{
 | 
| +	HANDLE		hList;
 | 
| +	WIN32_FIND_DATA	FileData;
 | 
| +#if defined(UNICODE) || defined(_UNICODE)
 | 
| +	size_t i, len_0 = strlen(name)+1;
 | 
| +
 | 
| +	if (len_0 > sizeof(FileData.cFileName)/sizeof(FileData.cFileName[0]))
 | 
| +		return -1;
 | 
| +
 | 
| +#if !defined(_WIN32_WCE) || _WIN32_WCE>=101
 | 
| +	if (!MultiByteToWideChar(CP_ACP,0,name,len_0,FileData.cFileName,len_0))
 | 
| +#endif
 | 
| +		for (i=0;i<len_0;i++)
 | 
| +			FileData.cFileName[i] = (WCHAR)name[i];
 | 
| +
 | 
| +	hList = FindFirstFile(FileData.cFileName,&FileData);
 | 
| +#else
 | 
| +	hList = FindFirstFile(name,&FileData);
 | 
| +#endif
 | 
| +	if (hList == INVALID_HANDLE_VALUE)	return -1;
 | 
| +	FindClose(hList);
 | 
| +	return ((FileData.dwFileAttributes&FILE_ATTRIBUTE_DIRECTORY)!=0);
 | 
| +	}
 | 
| +#else
 | 
| +#include <sys/stat.h>
 | 
| +#ifndef S_ISDIR
 | 
| +# if defined(_S_IFMT) && defined(_S_IFDIR)
 | 
| +#  define S_ISDIR(a)   (((a) & _S_IFMT) == _S_IFDIR)
 | 
| +# else 
 | 
| +#  define S_ISDIR(a)   (((a) & S_IFMT) == S_IFDIR)
 | 
| +# endif 
 | 
| +#endif 
 | 
| +
 | 
| +int app_isdir(const char *name)
 | 
| +	{
 | 
| +#if defined(S_ISDIR)
 | 
| +	struct stat st;
 | 
| +
 | 
| +	if (stat(name,&st)==0)	return S_ISDIR(st.st_mode);
 | 
| +	else			return -1;
 | 
| +#else
 | 
| +	return -1;
 | 
| +#endif
 | 
| +	}
 | 
| +#endif
 | 
| +
 | 
| +/* raw_read|write section */
 | 
| +#if defined(_WIN32) && defined(STD_INPUT_HANDLE)
 | 
| +int raw_read_stdin(void *buf,int siz)
 | 
| +	{
 | 
| +	DWORD n;
 | 
| +	if (ReadFile(GetStdHandle(STD_INPUT_HANDLE),buf,siz,&n,NULL))
 | 
| +		return (n);
 | 
| +	else	return (-1);
 | 
| +	}
 | 
| +#else
 | 
| +int raw_read_stdin(void *buf,int siz)
 | 
| +	{	return read(fileno(stdin),buf,siz);	}
 | 
| +#endif
 | 
| +
 | 
| +#if defined(_WIN32) && defined(STD_OUTPUT_HANDLE)
 | 
| +int raw_write_stdout(const void *buf,int siz)
 | 
| +	{
 | 
| +	DWORD n;
 | 
| +	if (WriteFile(GetStdHandle(STD_OUTPUT_HANDLE),buf,siz,&n,NULL))
 | 
| +		return (n);
 | 
| +	else	return (-1);
 | 
| +	}
 | 
| +#else
 | 
| +int raw_write_stdout(const void *buf,int siz)
 | 
| +	{	return write(fileno(stdout),buf,siz);	}
 | 
| +#endif
 | 
| +
 | 
| +#if !defined(OPENSSL_NO_TLSEXT) && !defined(OPENSSL_NO_NEXTPROTONEG)
 | 
|  /* next_protos_parse parses a comma separated list of strings into a string
 | 
|   * in a format suitable for passing to SSL_CTX_set_next_protos_advertised.
 | 
|   *   outlen: (output) set to the length of the resulting buffer on success.
 | 
| - *   err: (maybe NULL) on failure, an error message line is written to this BIO.
 | 
|   *   in: a NUL termianted string like "abc,def,ghi"
 | 
|   *
 | 
| - *   returns: a malloced buffer
 | 
| + *   returns: a malloced buffer or NULL on failure.
 | 
|   */
 | 
|  unsigned char *next_protos_parse(unsigned short *outlen, const char *in)
 | 
|  	{
 | 
| @@ -2595,7 +3034,7 @@
 | 
|  	size_t i, start = 0;
 | 
|  
 | 
|  	len = strlen(in);
 | 
| -	if (len > 65535)
 | 
| +	if (len >= 65535)
 | 
|  		return NULL;
 | 
|  
 | 
|  	out = OPENSSL_malloc(strlen(in) + 1);
 | 
| @@ -2621,3 +3060,4 @@
 | 
|  	*outlen = len + 1;
 | 
|  	return out;
 | 
|  	}
 | 
| +#endif  /* !OPENSSL_NO_TLSEXT && !OPENSSL_NO_NEXTPROTONEG */
 | 
| 
 |