X-Git-Url: https://git.openssl.org/gitweb/?p=openssl.git;a=blobdiff_plain;f=crypto%2Fx509v3%2Fv3_alt.c;h=ea1410dd74e3fa202d1a25f1e58af05e11c66a6c;hp=f7dabc4f2bc542528c356a3f57e0f67adb4729a2;hb=54298141d39600c4a6872f4440f4f843bcf84669;hpb=bb5ea36b962453c4d74dab15ac1897725a02707d diff --git a/crypto/x509v3/v3_alt.c b/crypto/x509v3/v3_alt.c index f7dabc4f2b..ea1410dd74 100644 --- a/crypto/x509v3/v3_alt.c +++ b/crypto/x509v3/v3_alt.c @@ -1,9 +1,9 @@ /* v3_alt.c */ -/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL - * project 1999. +/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL + * project. */ /* ==================================================================== - * Copyright (c) 1999 The OpenSSL Project. All rights reserved. + * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions @@ -63,9 +63,12 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); -static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens); +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); -X509V3_EXT_METHOD v3_alt[] = { +static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); +static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); + +const X509V3_EXT_METHOD v3_alt[] = { { NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0,0,0,0, 0,0, @@ -79,6 +82,12 @@ NULL, NULL, NULL}, (X509V3_EXT_I2V)i2v_GENERAL_NAMES, (X509V3_EXT_V2I)v2i_issuer_alt, NULL, NULL, NULL}, + +{ NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), +0,0,0,0, +0,0, +(X509V3_EXT_I2V)i2v_GENERAL_NAMES, +NULL, NULL, NULL, NULL}, }; STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, @@ -98,7 +107,8 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) { unsigned char *p; - char oline[256]; + char oline[256], htmp[5]; + int i; switch (gen->type) { case GEN_OTHERNAME: @@ -132,12 +142,27 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, case GEN_IPADD: p = gen->d.ip->data; - /* BUG: doesn't support IPV6 */ - if(gen->d.ip->length != 4) { + if(gen->d.ip->length == 4) + BIO_snprintf(oline, sizeof oline, + "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + else if(gen->d.ip->length == 16) + { + oline[0] = 0; + for (i = 0; i < 8; i++) + { + BIO_snprintf(htmp, sizeof htmp, + "%X", p[0] << 8 | p[1]); + p += 2; + strcat(oline, htmp); + if (i != 7) + strcat(oline, ":"); + } + } + else + { X509V3_add_value("IP Address","", &ret); break; - } - sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + } X509V3_add_value("IP Address",oline, &ret); break; @@ -152,6 +177,7 @@ STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) { unsigned char *p; + int i; switch (gen->type) { case GEN_OTHERNAME: @@ -186,12 +212,24 @@ int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) case GEN_IPADD: p = gen->d.ip->data; - /* BUG: doesn't support IPV6 */ - if(gen->d.ip->length != 4) { + if(gen->d.ip->length == 4) + BIO_printf(out, "IP Address:%d.%d.%d.%d", + p[0], p[1], p[2], p[3]); + else if(gen->d.ip->length == 16) + { + BIO_printf(out, "IP Address"); + for (i = 0; i < 8; i++) + { + BIO_printf(out, ":%X", p[0] << 8 | p[1]); + p += 2; + } + BIO_puts(out, "\n"); + } + else + { BIO_printf(out,"IP Address:"); break; - } - BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]); + } break; case GEN_RID: @@ -209,7 +247,7 @@ static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, CONF_VALUE *cnf; int i; if(!(gens = sk_GENERAL_NAME_new_null())) { - X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); + X509V3err(X509V3_F_V2I_ISSUER_ALT,ERR_R_MALLOC_FAILURE); return NULL; } for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { @@ -274,14 +312,17 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, CONF_VALUE *cnf; int i; if(!(gens = sk_GENERAL_NAME_new_null())) { - X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); + X509V3err(X509V3_F_V2I_SUBJECT_ALT,ERR_R_MALLOC_FAILURE); return NULL; } for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { cnf = sk_CONF_VALUE_value(nval, i); if(!name_cmp(cnf->name, "email") && cnf->value && !strcmp(cnf->value, "copy")) { - if(!copy_email(ctx, gens)) goto err; + if(!copy_email(ctx, gens, 0)) goto err; + } else if(!name_cmp(cnf->name, "email") && cnf->value && + !strcmp(cnf->value, "move")) { + if(!copy_email(ctx, gens, 1)) goto err; } else { GENERAL_NAME *gen; if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) @@ -299,14 +340,15 @@ static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, * GENERAL_NAMES */ -static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens) +static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) { 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 != NULL && 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; @@ -318,9 +360,15 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens) /* Now add any email address(es) to STACK */ i = -1; while((i = X509_NAME_get_index_by_NID(nm, - NID_pkcs9_emailAddress, i)) > 0) { + NID_pkcs9_emailAddress, i)) >= 0) { ne = X509_NAME_get_entry(nm, i); email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); + if (move_p) + { + X509_NAME_delete_entry(nm, i); + X509_NAME_ENTRY_free(ne); + i--; + } if(!email || !(gen = GENERAL_NAME_new())) { X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); goto err; @@ -345,8 +393,8 @@ static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens) } -GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, - X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) +GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) { GENERAL_NAME *gen; GENERAL_NAMES *gens = NULL; @@ -367,83 +415,202 @@ GENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, return NULL; } -GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, - CONF_VALUE *cnf) -{ -char is_string = 0; -int type; -GENERAL_NAME *gen = NULL; +GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + CONF_VALUE *cnf) + { + return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); + } -char *name, *value; +GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, X509V3_CTX *ctx, + int gen_type, char *value, int is_nc) + { + char is_string = 0; + GENERAL_NAME *gen = NULL; -name = cnf->name; -value = cnf->value; + if(!value) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,X509V3_R_MISSING_VALUE); + return NULL; + } -if(!value) { - X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE); - return NULL; -} + if (out) + gen = out; + else + { + gen = GENERAL_NAME_new(); + if(gen == NULL) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + return NULL; + } + } -if(!(gen = GENERAL_NAME_new())) { - X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); - return NULL; -} + switch (gen_type) + { + case GEN_URI: + case GEN_EMAIL: + case GEN_DNS: + is_string = 1; + break; + + case GEN_RID: + { + ASN1_OBJECT *obj; + if(!(obj = OBJ_txt2obj(value,0))) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,X509V3_R_BAD_OBJECT); + ERR_add_error_data(2, "value=", value); + goto err; + } + gen->d.rid = obj; + } + break; -if(!name_cmp(name, "email")) { - is_string = 1; - type = GEN_EMAIL; -} else if(!name_cmp(name, "URI")) { - is_string = 1; - type = GEN_URI; -} else if(!name_cmp(name, "DNS")) { - is_string = 1; - type = GEN_DNS; -} else if(!name_cmp(name, "RID")) { - ASN1_OBJECT *obj; - if(!(obj = OBJ_txt2obj(value,0))) { - X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT); - ERR_add_error_data(2, "value=", value); - goto err; - } - gen->d.rid = obj; - type = GEN_RID; -} else if(!name_cmp(name, "IP")) { - int i1,i2,i3,i4; - unsigned char ip[4]; - if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) || - (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) || - (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) { - X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); - ERR_add_error_data(2, "value=", value); - goto err; - } - ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4; - if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) || - !ASN1_STRING_set(gen->d.ip, ip, 4)) { - X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + case GEN_IPADD: + if (is_nc) + gen->d.ip = a2i_IPADDRESS_NC(value); + else + gen->d.ip = a2i_IPADDRESS(value); + if(gen->d.ip == NULL) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); + ERR_add_error_data(2, "value=", value); goto err; - } - type = GEN_IPADD; -} else { - X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION); - ERR_add_error_data(2, "name=", name); - goto err; -} + } + break; + + case GEN_DIRNAME: + if (!do_dirname(gen, value, ctx)) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,X509V3_R_DIRNAME_ERROR); + goto err; + } + break; -if(is_string) { - if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || - !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value, - strlen(value))) { - X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + case GEN_OTHERNAME: + if (!do_othername(gen, value, ctx)) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,X509V3_R_OTHERNAME_ERROR); + goto err; + } + break; + default: + X509V3err(X509V3_F_A2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_TYPE); goto err; + } + + if(is_string) + { + if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || + !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value, + strlen(value))) + { + X509V3err(X509V3_F_A2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); + goto err; + } + } + + gen->type = gen_type; + + return gen; + + err: + if (!out) + GENERAL_NAME_free(gen); + return NULL; } -} -gen->type = type; +GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, + const X509V3_EXT_METHOD *method, + X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc) + { + int type; -return gen; + char *name, *value; -err: -GENERAL_NAME_free(gen); -return NULL; -} + name = cnf->name; + value = cnf->value; + + if(!value) + { + X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE); + return NULL; + } + + if(!name_cmp(name, "email")) + type = GEN_EMAIL; + else if(!name_cmp(name, "URI")) + type = GEN_URI; + else if(!name_cmp(name, "DNS")) + type = GEN_DNS; + else if(!name_cmp(name, "RID")) + type = GEN_RID; + else if(!name_cmp(name, "IP")) + type = GEN_IPADD; + else if(!name_cmp(name, "dirName")) + type = GEN_DIRNAME; + else if(!name_cmp(name, "otherName")) + type = GEN_OTHERNAME; + else + { + X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION); + ERR_add_error_data(2, "name=", name); + return NULL; + } + + return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc); + + } + +static int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) + { + char *objtmp = NULL, *p; + int objlen; + if (!(p = strchr(value, ';'))) + return 0; + if (!(gen->d.otherName = OTHERNAME_new())) + return 0; + /* Free this up because we will overwrite it. + * no need to free type_id because it is static + */ + ASN1_TYPE_free(gen->d.otherName->value); + if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) + return 0; + objlen = p - value; + objtmp = OPENSSL_malloc(objlen + 1); + if (objtmp == NULL) + return 0; + strncpy(objtmp, value, objlen); + objtmp[objlen] = 0; + gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); + OPENSSL_free(objtmp); + if (!gen->d.otherName->type_id) + return 0; + return 1; + } + +static int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) + { + int ret; + STACK_OF(CONF_VALUE) *sk; + X509_NAME *nm; + if (!(nm = X509_NAME_new())) + return 0; + sk = X509V3_get_section(ctx, value); + if (!sk) + { + X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND); + ERR_add_error_data(2, "section=", value); + X509_NAME_free(nm); + return 0; + } + /* FIXME: should allow other character types... */ + ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); + if (!ret) + X509_NAME_free(nm); + gen->d.dirn = nm; + X509V3_section_free(ctx, sk); + + return ret; + }