diff --git a/apps/ca.c b/apps/ca.c index 08f4146dcac18509594bb6f453466037533f8137..76bbcbc2c5d7a2a1712272deba6bd65c19df6c3a 100644 --- a/apps/ca.c +++ b/apps/ca.c @@ -695,6 +695,7 @@ bad: 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 fbf0a1ba7f46f1d7377a850d41b582814f06d24f..7dee6432a8df128bf8ed8c63afe896cd7fbf3ea8 100644 --- a/apps/openssl.cnf +++ b/apps/openssl.cnf @@ -132,6 +132,13 @@ nsComment = "OpenSSL Generated Certificate" 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 @@ keyUsage = cRLSign, keyCertSign # 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 0f74f40e65df2b72641e19ee7be18421ce248eef..9901d6bd89937cca0a456a0e424fdd82d492dd3c 100644 --- a/crypto/asn1/asn1.h +++ b/crypto/asn1/asn1.h @@ -328,6 +328,8 @@ typedef struct asn1_header_st #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 0e8211b0075abcf013ffd8975fc08b66a401e049..76f1b633c53a0485d568e3502d3b2af86b14bd2b 100644 --- a/crypto/x509v3/v3_alt.c +++ b/crypto/x509v3/v3_alt.c @@ -65,6 +65,18 @@ #include #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 @@ GENERAL_NAMES_free, 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 @@ GENERAL_NAMES_free, 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 @@ STACK *ret; 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 @@ char *name, *value; 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 a87af95f26d81cfffb6b7501a6716d60bbe8b935..22ad348dee2c0fcf2874e3bf6958b63ed8d8d6d9 100644 --- a/crypto/x509v3/v3_conf.c +++ b/crypto/x509v3/v3_conf.c @@ -85,10 +85,16 @@ char *value; /* Value */ { 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 *value; /* Value */ 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 cee230ec4fae01dc6a40c213f7e8aa054faef3d3..ecf50c75ae0222d42dbec394cda130135c56a0e3 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 @@ static ERR_STRING_DATA X509V3_str_reasons[]= {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 @@ static ERR_STRING_DATA X509V3_str_reasons[]= {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 f3897686805d807f5a59350de3143e053b47bddb..0f1d948829cc79c29772457958fbe5d1bb4b5a8c 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 73ac250b2c2435652f295d2afb325858b09b1de5..b4aeaf68cfb0164dfbb59cc30624ef39fa3e157e 100644 --- a/crypto/x509v3/x509v3.h +++ b/crypto/x509v3/x509v3.h @@ -237,7 +237,6 @@ int i2d_ext_ku(STACK *a, unsigned char **pp); 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 @@ int X509V3_EXT_print_fp(); /* 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 @@ int X509V3_EXT_print_fp(); #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 @@ int X509V3_EXT_print_fp(); #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 ee5da522aeb80b4f09f8065593bcff8d9c61f6a6..54778768bbeba91ee911584a9c76731cb44617f4 100755 --- a/util/libeay.num +++ b/util/libeay.num @@ -1211,3 +1211,6 @@ v2i_GENERAL_NAMES 1236 i2s_ASN1_INTEGER 1237 X509V3_EXT_get_d2i 1238 name_cmp 1239 +str_dup 1240 +i2s_ASN1_ENUMERATED 1241 +i2s_ASN1_ENUMERATED_TABLE 1242