Add more functionality to issuer alt name and subject alt name. New options
to include email addresses from DN and copy details from issuer certificate.
Include examples in openssl.cnf, update Win32 ordinals.
diff --git a/apps/ca.c b/apps/ca.c
index 08f4146..76bbcbc 100644
--- a/apps/ca.c
+++ b/apps/ca.c
@@ -695,6 +695,7 @@
 				BIO_printf(bio_err,
 				 "Error Loading extension section %s\n",
 								 extensions);
+				ret = 1;
 				goto err;
 			}
 		}
diff --git a/apps/openssl.cnf b/apps/openssl.cnf
index fbf0a1b..7dee643 100644
--- a/apps/openssl.cnf
+++ b/apps/openssl.cnf
@@ -132,6 +132,13 @@
 subjectKeyIdentifier=hash
 authorityKeyIdentifier=keyid,issuer:always
 
+# Import the email address.
+
+subjectAltName=email:copy
+
+# Copy subject details
+
+issuerAltName=issuer:copy
 
 #nsCaRevocationUrl		= http://www.domain.dom/ca-crl.pem
 #nsBaseUrl
@@ -163,6 +170,11 @@
 # Some might want this also
 #nsCertType = sslCA, emailCA
 
+# Include email address in subject alt name: another PKIX recommendation
+subjectAltName=email:copy
+# Copy issuer details
+issuerAltName=issuer:copy
+
 # RAW DER hex encoding of an extension: beware experts only!
 # 1.2.3.5=RAW:02:03
 # You can even override a supported extension:
diff --git a/crypto/asn1/asn1.h b/crypto/asn1/asn1.h
index 0f74f40..9901d6b 100644
--- a/crypto/asn1/asn1.h
+++ b/crypto/asn1/asn1.h
@@ -328,6 +328,8 @@
 #define ASN1_IA5STRING_new()	(ASN1_IA5STRING *)\
 		ASN1_STRING_type_new(V_ASN1_IA5STRING)
 #define ASN1_IA5STRING_free(a)	ASN1_STRING_free((ASN1_STRING *)a)
+#define ASN1_IA5STRING_dup(a)	\
+			(ASN1_IA5STRING *)ASN1_STRING_dup((ASN1_STRING *)a)
 #define M_i2d_ASN1_IA5STRING(a,pp) \
 		i2d_ASN1_bytes((ASN1_STRING *)a,pp,V_ASN1_IA5STRING,\
 			V_ASN1_UNIVERSAL)
diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c
index 0e8211b..76f1b63 100644
--- a/crypto/x509v3/v3_alt.c
+++ b/crypto/x509v3/v3_alt.c
@@ -65,6 +65,18 @@
 #include <conf.h>
 #include "x509v3.h"
 
+#ifndef NOPROTO
+STACK *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK *nval);
+STACK *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK *nval);
+static int copy_email(X509V3_CTX *ctx, STACK *gens);
+static int copy_issuer(X509V3_CTX *ctx, STACK *gens);
+#else
+STACK *v2i_issuer_alt();
+STACK *v2i_subject_alt();
+static int copy_email();
+static int copy_issuer();
+#endif
+
 X509V3_EXT_METHOD v3_alt[] = {
 { NID_subject_alt_name, 0,
 (X509V3_EXT_NEW)GENERAL_NAMES_new,
@@ -73,7 +85,7 @@
 i2d_GENERAL_NAMES,
 NULL, NULL,
 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-(X509V3_EXT_V2I)v2i_GENERAL_NAMES,
+(X509V3_EXT_V2I)v2i_subject_alt,
 NULL, NULL},
 { NID_issuer_alt_name, 0,
 (X509V3_EXT_NEW)GENERAL_NAMES_new,
@@ -82,7 +94,7 @@
 i2d_GENERAL_NAMES,
 NULL, NULL,
 (X509V3_EXT_I2V)i2v_GENERAL_NAMES,
-(X509V3_EXT_V2I)v2i_GENERAL_NAMES,
+(X509V3_EXT_V2I)v2i_issuer_alt,
 NULL, NULL},
 EXT_END
 };
@@ -158,6 +170,157 @@
 	return ret;
 }
 
+STACK *v2i_issuer_alt(method, ctx, nval)
+X509V3_EXT_METHOD *method;
+X509V3_CTX *ctx;
+STACK *nval;
+{
+	STACK *gens = NULL;
+	CONF_VALUE *cnf;
+	int i;
+	if(!(gens = sk_new(NULL))) {
+		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	for(i = 0; i < sk_num(nval); i++) {
+		cnf = (CONF_VALUE *)sk_value(nval, i);
+		if(!name_cmp(cnf->name, "issuer") && cnf->value &&
+						!strcmp(cnf->value, "copy")) {
+			if(!copy_issuer(ctx, gens)) goto err;
+		} else {
+			GENERAL_NAME *gen;
+			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+								 goto err; 
+			sk_push(gens, (char *)gen);
+		}
+	}
+	return gens;
+	err:
+	sk_pop_free(gens, GENERAL_NAME_free);
+	return NULL;
+}
+
+/* Append subject altname of issuer to issuer alt name of subject */
+
+static int copy_issuer(ctx, gens)
+X509V3_CTX *ctx;
+STACK *gens;
+{
+	STACK *ialt;
+	char *gen;
+	X509_EXTENSION *ext;
+	int i;
+	if(ctx && (ctx->flags == CTX_TEST)) return 1;
+	if(!ctx || !ctx->issuer_cert) {
+		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS);
+		goto err;
+	}
+        i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
+	if(i < 0) return 1;
+        if(!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
+                        !(ialt = (STACK *) X509V3_EXT_d2i(ext)) ) {
+		X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR);
+		goto err;
+	}
+
+	for(i = 0; i < sk_num(ialt); i++) {
+		gen = sk_value(ialt, i);
+		if(!sk_push(gens, gen)) {
+			X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+	}
+	sk_free(ialt);
+
+	return 1;
+		
+	err:
+	return 0;
+	
+}
+
+STACK *v2i_subject_alt(method, ctx, nval)
+X509V3_EXT_METHOD *method;
+X509V3_CTX *ctx;
+STACK *nval;
+{
+	STACK *gens = NULL;
+	CONF_VALUE *cnf;
+	int i;
+	if(!(gens = sk_new(NULL))) {
+		X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE);
+		return NULL;
+	}
+	for(i = 0; i < sk_num(nval); i++) {
+		cnf = (CONF_VALUE *)sk_value(nval, i);
+		if(!name_cmp(cnf->name, "email") && cnf->value &&
+						!strcmp(cnf->value, "copy")) {
+			if(!copy_email(ctx, gens)) goto err;
+		} else {
+			GENERAL_NAME *gen;
+			if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
+								 goto err; 
+			sk_push(gens, (char *)gen);
+		}
+	}
+	return gens;
+	err:
+	sk_pop_free(gens, GENERAL_NAME_free);
+	return NULL;
+}
+
+/* Copy any email addresses in a certificate or request to 
+ * GENERAL_NAMES
+ */
+
+static int copy_email(ctx, gens)
+X509V3_CTX *ctx;
+STACK *gens;
+{
+	X509_NAME *nm;
+	ASN1_IA5STRING *email = NULL;
+	X509_NAME_ENTRY *ne;
+	GENERAL_NAME *gen = NULL;
+	int i;
+	if(ctx->flags == CTX_TEST) return 1;
+	if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
+		X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS);
+		goto err;
+	}
+	/* Find the subject name */
+	if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert);
+	else nm = X509_REQ_get_subject_name(ctx->subject_req);
+
+	/* Now add any email address(es) to STACK */
+	i = -1;
+	while((i = X509_NAME_get_index_by_NID(nm,
+					 NID_pkcs9_emailAddress, i)) > 0) {
+		ne = X509_NAME_get_entry(nm, i);
+		email = ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne));
+		if(!email || !(gen = GENERAL_NAME_new())) {
+			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		gen->d.ia5 = email;
+		email = NULL;
+		gen->type = GEN_EMAIL;
+		if(!sk_push(gens, (char *)gen)) {
+			X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE);
+			goto err;
+		}
+		gen = NULL;
+	}
+
+	
+	return 1;
+		
+	err:
+	GENERAL_NAME_free(gen);
+	ASN1_IA5STRING_free(email);
+	return 0;
+	
+}
+
 STACK *v2i_GENERAL_NAMES(method, ctx, nval)
 X509V3_EXT_METHOD *method;
 X509V3_CTX *ctx;
@@ -196,6 +359,11 @@
 name = cnf->name;
 value = cnf->value;
 
+if(!value) {
+	X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE);
+	return NULL;
+}
+
 if(!(gen = GENERAL_NAME_new())) {
 	X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE);
 	return NULL;
diff --git a/crypto/x509v3/v3_conf.c b/crypto/x509v3/v3_conf.c
index a87af95..22ad348 100644
--- a/crypto/x509v3/v3_conf.c
+++ b/crypto/x509v3/v3_conf.c
@@ -85,10 +85,16 @@
 {
 	int crit;
 	int ext_type;
+	X509_EXTENSION *ret;
 	crit = v3_check_critical(&value);
 	if((ext_type = v3_check_generic(&value))) 
 		return v3_generic_extension(name, value, crit, ext_type);
-	return do_ext_conf(conf, ctx, OBJ_sn2nid(name), crit, value);
+	ret = do_ext_conf(conf, ctx, OBJ_sn2nid(name), crit, value);
+	if(!ret) {
+		X509V3err(X509V3_F_X509V3_EXT_CONF,X509V3_R_ERROR_IN_EXTENSION);
+		ERR_add_error_data(4,"name=", name, ", value=", value);
+	}
+	return ret;
 }
 
 X509_EXTENSION *X509V3_EXT_conf_nid(conf, ctx, ext_nid, value)
@@ -120,9 +126,12 @@
 	char *ext_der, *p;
 	int ext_len;
 	ASN1_OCTET_STRING *ext_oct;
-	if(ext_nid == NID_undef) return NULL;
+	if(ext_nid == NID_undef) {
+		X509V3err(X509V3_F_DO_EXT_CONF,X509V3_R_UNKNOWN_EXTENSION_NAME);
+		return NULL;
+	}
 	if(!(method = X509V3_EXT_get_nid(ext_nid))) {
-		/* Add generic extension support here */
+		X509V3err(X509V3_F_DO_EXT_CONF,X509V3_R_UNKNOWN_EXTENSION);
 		return NULL;
 	}
 	/* Now get internal extension representation based on type */
diff --git a/crypto/x509v3/v3err.c b/crypto/x509v3/v3err.c
index cee230e..ecf50c7 100644
--- a/crypto/x509v3/v3err.c
+++ b/crypto/x509v3/v3err.c
@@ -63,6 +63,9 @@
 #ifndef NO_ERR
 static ERR_STRING_DATA X509V3_str_functs[]=
 	{
+{ERR_PACK(0,X509V3_F_COPY_EMAIL,0),	"COPY_EMAIL"},
+{ERR_PACK(0,X509V3_F_COPY_ISSUER,0),	"COPY_ISSUER"},
+{ERR_PACK(0,X509V3_F_DO_EXT_CONF,0),	"DO_EXT_CONF"},
 {ERR_PACK(0,X509V3_F_HEX_TO_STRING,0),	"hex_to_string"},
 {ERR_PACK(0,X509V3_F_I2S_ASN1_ENUMERATED,0),	"i2s_ASN1_ENUMERATED"},
 {ERR_PACK(0,X509V3_F_I2S_ASN1_INTEGER,0),	"i2s_ASN1_INTEGER"},
@@ -94,6 +97,7 @@
 {X509V3_R_BAD_OBJECT                     ,"bad object"},
 {X509V3_R_BN_DEC2BN_ERROR                ,"bn dec2bn error"},
 {X509V3_R_BN_TO_ASN1_INTEGER_ERROR       ,"bn to asn1 integer error"},
+{X509V3_R_ERROR_IN_EXTENSION             ,"error in extension"},
 {X509V3_R_EXTENSION_NAME_ERROR           ,"extension name error"},
 {X509V3_R_EXTENSION_NOT_FOUND            ,"extension not found"},
 {X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED,"extension setting not supported"},
@@ -106,12 +110,18 @@
 {X509V3_R_INVALID_NULL_NAME              ,"invalid null name"},
 {X509V3_R_INVALID_NULL_VALUE             ,"invalid null value"},
 {X509V3_R_INVALID_OBJECT_IDENTIFIER      ,"invalid object identifier"},
+{X509V3_R_ISSUER_DECODE_ERROR            ,"issuer decode error"},
+{X509V3_R_MISSING_VALUE                  ,"missing value"},
 {X509V3_R_NO_ISSUER_CERTIFICATE          ,"no issuer certificate"},
+{X509V3_R_NO_ISSUER_DETAILS              ,"no issuer details"},
 {X509V3_R_NO_PUBLIC_KEY                  ,"no public key"},
+{X509V3_R_NO_SUBJECT_DETAILS             ,"no subject details"},
 {X509V3_R_ODD_NUMBER_OF_DIGITS           ,"odd number of digits"},
 {X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS   ,"unable to get issuer details"},
 {X509V3_R_UNABLE_TO_GET_ISSUER_KEYID     ,"unable to get issuer keyid"},
 {X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT    ,"unknown bit string argument"},
+{X509V3_R_UNKNOWN_EXTENSION              ,"unknown extension"},
+{X509V3_R_UNKNOWN_EXTENSION_NAME         ,"unknown extension name"},
 {X509V3_R_UNKNOWN_OPTION                 ,"unknown option"},
 {X509V3_R_UNSUPPORTED_OPTION             ,"unsupported option"},
 {0,NULL},
diff --git a/crypto/x509v3/x509v3.err b/crypto/x509v3/x509v3.err
index f389768..0f1d948 100644
--- a/crypto/x509v3/x509v3.err
+++ b/crypto/x509v3/x509v3.err
@@ -1,6 +1,9 @@
 /* Error codes for the X509V3 functions. */
 
 /* Function codes. */
+#define X509V3_F_COPY_EMAIL				 122
+#define X509V3_F_COPY_ISSUER				 123
+#define X509V3_F_DO_EXT_CONF				 124
 #define X509V3_F_HEX_TO_STRING				 111
 #define X509V3_F_I2S_ASN1_ENUMERATED			 121
 #define X509V3_F_I2S_ASN1_INTEGER			 120
@@ -29,6 +32,7 @@
 #define X509V3_R_BAD_OBJECT				 119
 #define X509V3_R_BN_DEC2BN_ERROR			 100
 #define X509V3_R_BN_TO_ASN1_INTEGER_ERROR		 101
+#define X509V3_R_ERROR_IN_EXTENSION			 128
 #define X509V3_R_EXTENSION_NAME_ERROR			 115
 #define X509V3_R_EXTENSION_NOT_FOUND			 102
 #define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED	 103
@@ -41,11 +45,17 @@
 #define X509V3_R_INVALID_NULL_NAME			 108
 #define X509V3_R_INVALID_NULL_VALUE			 109
 #define X509V3_R_INVALID_OBJECT_IDENTIFIER		 110
+#define X509V3_R_ISSUER_DECODE_ERROR			 126
+#define X509V3_R_MISSING_VALUE				 124
 #define X509V3_R_NO_ISSUER_CERTIFICATE			 121
+#define X509V3_R_NO_ISSUER_DETAILS			 127
 #define X509V3_R_NO_PUBLIC_KEY				 114
+#define X509V3_R_NO_SUBJECT_DETAILS			 125
 #define X509V3_R_ODD_NUMBER_OF_DIGITS			 112
 #define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS		 122
 #define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID		 123
 #define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT		 111
+#define X509V3_R_UNKNOWN_EXTENSION			 129
+#define X509V3_R_UNKNOWN_EXTENSION_NAME			 130
 #define X509V3_R_UNKNOWN_OPTION				 120
 #define X509V3_R_UNSUPPORTED_OPTION			 117
diff --git a/crypto/x509v3/x509v3.h b/crypto/x509v3/x509v3.h
index 73ac250..b4aeaf6 100644
--- a/crypto/x509v3/x509v3.h
+++ b/crypto/x509v3/x509v3.h
@@ -237,7 +237,6 @@
 STACK *d2i_ext_ku(STACK **a, unsigned char **pp, long length);
 void ext_ku_free(STACK *a);
 STACK *ext_ku_new(void);
-
 char *str_dup(char *val);
 
 #ifdef HEADER_CONF_H
@@ -349,6 +348,9 @@
 /* Error codes for the X509V3 functions. */
 
 /* Function codes. */
+#define X509V3_F_COPY_EMAIL				 122
+#define X509V3_F_COPY_ISSUER				 123
+#define X509V3_F_DO_EXT_CONF				 124
 #define X509V3_F_HEX_TO_STRING				 111
 #define X509V3_F_I2S_ASN1_ENUMERATED			 121
 #define X509V3_F_I2S_ASN1_INTEGER			 120
@@ -377,6 +379,7 @@
 #define X509V3_R_BAD_OBJECT				 119
 #define X509V3_R_BN_DEC2BN_ERROR			 100
 #define X509V3_R_BN_TO_ASN1_INTEGER_ERROR		 101
+#define X509V3_R_ERROR_IN_EXTENSION			 128
 #define X509V3_R_EXTENSION_NAME_ERROR			 115
 #define X509V3_R_EXTENSION_NOT_FOUND			 102
 #define X509V3_R_EXTENSION_SETTING_NOT_SUPPORTED	 103
@@ -389,12 +392,18 @@
 #define X509V3_R_INVALID_NULL_NAME			 108
 #define X509V3_R_INVALID_NULL_VALUE			 109
 #define X509V3_R_INVALID_OBJECT_IDENTIFIER		 110
+#define X509V3_R_ISSUER_DECODE_ERROR			 126
+#define X509V3_R_MISSING_VALUE				 124
 #define X509V3_R_NO_ISSUER_CERTIFICATE			 121
+#define X509V3_R_NO_ISSUER_DETAILS			 127
 #define X509V3_R_NO_PUBLIC_KEY				 114
+#define X509V3_R_NO_SUBJECT_DETAILS			 125
 #define X509V3_R_ODD_NUMBER_OF_DIGITS			 112
 #define X509V3_R_UNABLE_TO_GET_ISSUER_DETAILS		 122
 #define X509V3_R_UNABLE_TO_GET_ISSUER_KEYID		 123
 #define X509V3_R_UNKNOWN_BIT_STRING_ARGUMENT		 111
+#define X509V3_R_UNKNOWN_EXTENSION			 129
+#define X509V3_R_UNKNOWN_EXTENSION_NAME			 130
 #define X509V3_R_UNKNOWN_OPTION				 120
 #define X509V3_R_UNSUPPORTED_OPTION			 117
  
diff --git a/util/libeay.num b/util/libeay.num
index ee5da52..5477876 100755
--- a/util/libeay.num
+++ b/util/libeay.num
@@ -1211,3 +1211,6 @@
 i2s_ASN1_INTEGER                        1237
 X509V3_EXT_get_d2i                      1238
 name_cmp                                1239
+str_dup                                 1240
+i2s_ASN1_ENUMERATED                     1241
+i2s_ASN1_ENUMERATED_TABLE               1242