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 */ |