v3_alt.c revision 167612
155714Skris/* v3_alt.c */ 255714Skris/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3160814Ssimon * project. 455714Skris */ 555714Skris/* ==================================================================== 6160814Ssimon * Copyright (c) 1999-2003 The OpenSSL Project. All rights reserved. 755714Skris * 855714Skris * Redistribution and use in source and binary forms, with or without 955714Skris * modification, are permitted provided that the following conditions 1055714Skris * are met: 1155714Skris * 1255714Skris * 1. Redistributions of source code must retain the above copyright 1355714Skris * notice, this list of conditions and the following disclaimer. 1455714Skris * 1555714Skris * 2. Redistributions in binary form must reproduce the above copyright 1655714Skris * notice, this list of conditions and the following disclaimer in 1755714Skris * the documentation and/or other materials provided with the 1855714Skris * distribution. 1955714Skris * 2055714Skris * 3. All advertising materials mentioning features or use of this 2155714Skris * software must display the following acknowledgment: 2255714Skris * "This product includes software developed by the OpenSSL Project 2355714Skris * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 2455714Skris * 2555714Skris * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 2655714Skris * endorse or promote products derived from this software without 2755714Skris * prior written permission. For written permission, please contact 2855714Skris * licensing@OpenSSL.org. 2955714Skris * 3055714Skris * 5. Products derived from this software may not be called "OpenSSL" 3155714Skris * nor may "OpenSSL" appear in their names without prior written 3255714Skris * permission of the OpenSSL Project. 3355714Skris * 3455714Skris * 6. Redistributions of any form whatsoever must retain the following 3555714Skris * acknowledgment: 3655714Skris * "This product includes software developed by the OpenSSL Project 3755714Skris * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 3855714Skris * 3955714Skris * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 4055714Skris * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 4155714Skris * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 4255714Skris * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 4355714Skris * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 4455714Skris * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 4555714Skris * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 4655714Skris * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 4755714Skris * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 4855714Skris * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 4955714Skris * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 5055714Skris * OF THE POSSIBILITY OF SUCH DAMAGE. 5155714Skris * ==================================================================== 5255714Skris * 5355714Skris * This product includes cryptographic software written by Eric Young 5455714Skris * (eay@cryptsoft.com). This product includes software written by Tim 5555714Skris * Hudson (tjh@cryptsoft.com). 5655714Skris * 5755714Skris */ 5855714Skris 5955714Skris#include <stdio.h> 6055714Skris#include "cryptlib.h" 6155714Skris#include <openssl/conf.h> 6255714Skris#include <openssl/x509v3.h> 6355714Skris 64109998Smarkmstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 65109998Smarkmstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 66109998Smarkmstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p); 67109998Smarkmstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens); 68160814Ssimonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); 69160814Ssimonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx); 70160814Ssimon 71167612Ssimonconst X509V3_EXT_METHOD v3_alt[] = { 72109998Smarkm{ NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 73109998Smarkm0,0,0,0, 74109998Smarkm0,0, 7555714Skris(X509V3_EXT_I2V)i2v_GENERAL_NAMES, 7655714Skris(X509V3_EXT_V2I)v2i_subject_alt, 7755714SkrisNULL, NULL, NULL}, 78109998Smarkm 79109998Smarkm{ NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 80109998Smarkm0,0,0,0, 81109998Smarkm0,0, 8255714Skris(X509V3_EXT_I2V)i2v_GENERAL_NAMES, 8355714Skris(X509V3_EXT_V2I)v2i_issuer_alt, 8455714SkrisNULL, NULL, NULL}, 8555714Skris}; 8655714Skris 8755714SkrisSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, 88109998Smarkm GENERAL_NAMES *gens, STACK_OF(CONF_VALUE) *ret) 8955714Skris{ 9055714Skris int i; 9155714Skris GENERAL_NAME *gen; 9255714Skris for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 9355714Skris gen = sk_GENERAL_NAME_value(gens, i); 9455714Skris ret = i2v_GENERAL_NAME(method, gen, ret); 9555714Skris } 9655714Skris if(!ret) return sk_CONF_VALUE_new_null(); 9755714Skris return ret; 9855714Skris} 9955714Skris 10055714SkrisSTACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, 10155714Skris GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) 10255714Skris{ 103109998Smarkm unsigned char *p; 104160814Ssimon char oline[256], htmp[5]; 105160814Ssimon int i; 10655714Skris switch (gen->type) 10755714Skris { 10855714Skris case GEN_OTHERNAME: 10955714Skris X509V3_add_value("othername","<unsupported>", &ret); 11055714Skris break; 11155714Skris 11255714Skris case GEN_X400: 11355714Skris X509V3_add_value("X400Name","<unsupported>", &ret); 11455714Skris break; 11555714Skris 11655714Skris case GEN_EDIPARTY: 11755714Skris X509V3_add_value("EdiPartyName","<unsupported>", &ret); 11855714Skris break; 11955714Skris 12055714Skris case GEN_EMAIL: 12155714Skris X509V3_add_value_uchar("email",gen->d.ia5->data, &ret); 12255714Skris break; 12355714Skris 12455714Skris case GEN_DNS: 12555714Skris X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret); 12655714Skris break; 12755714Skris 12855714Skris case GEN_URI: 12955714Skris X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret); 13055714Skris break; 13155714Skris 13255714Skris case GEN_DIRNAME: 13355714Skris X509_NAME_oneline(gen->d.dirn, oline, 256); 13455714Skris X509V3_add_value("DirName",oline, &ret); 13555714Skris break; 13655714Skris 13755714Skris case GEN_IPADD: 13855714Skris p = gen->d.ip->data; 139160814Ssimon if(gen->d.ip->length == 4) 140160814Ssimon BIO_snprintf(oline, sizeof oline, 141160814Ssimon "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 142160814Ssimon else if(gen->d.ip->length == 16) 143160814Ssimon { 144160814Ssimon oline[0] = 0; 145160814Ssimon for (i = 0; i < 8; i++) 146160814Ssimon { 147160814Ssimon BIO_snprintf(htmp, sizeof htmp, 148160814Ssimon "%X", p[0] << 8 | p[1]); 149160814Ssimon p += 2; 150160814Ssimon strcat(oline, htmp); 151160814Ssimon if (i != 7) 152160814Ssimon strcat(oline, ":"); 153160814Ssimon } 154160814Ssimon } 155160814Ssimon else 156160814Ssimon { 15755714Skris X509V3_add_value("IP Address","<invalid>", &ret); 15855714Skris break; 159160814Ssimon } 16055714Skris X509V3_add_value("IP Address",oline, &ret); 16155714Skris break; 16255714Skris 16355714Skris case GEN_RID: 16455714Skris i2t_ASN1_OBJECT(oline, 256, gen->d.rid); 16555714Skris X509V3_add_value("Registered ID",oline, &ret); 16655714Skris break; 16755714Skris } 16855714Skris return ret; 16955714Skris} 17055714Skris 171109998Smarkmint GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen) 172109998Smarkm{ 173109998Smarkm unsigned char *p; 174160814Ssimon int i; 175109998Smarkm switch (gen->type) 176109998Smarkm { 177109998Smarkm case GEN_OTHERNAME: 178109998Smarkm BIO_printf(out, "othername:<unsupported>"); 179109998Smarkm break; 180109998Smarkm 181109998Smarkm case GEN_X400: 182109998Smarkm BIO_printf(out, "X400Name:<unsupported>"); 183109998Smarkm break; 184109998Smarkm 185109998Smarkm case GEN_EDIPARTY: 186109998Smarkm /* Maybe fix this: it is supported now */ 187109998Smarkm BIO_printf(out, "EdiPartyName:<unsupported>"); 188109998Smarkm break; 189109998Smarkm 190109998Smarkm case GEN_EMAIL: 191109998Smarkm BIO_printf(out, "email:%s",gen->d.ia5->data); 192109998Smarkm break; 193109998Smarkm 194109998Smarkm case GEN_DNS: 195109998Smarkm BIO_printf(out, "DNS:%s",gen->d.ia5->data); 196109998Smarkm break; 197109998Smarkm 198109998Smarkm case GEN_URI: 199109998Smarkm BIO_printf(out, "URI:%s",gen->d.ia5->data); 200109998Smarkm break; 201109998Smarkm 202109998Smarkm case GEN_DIRNAME: 203109998Smarkm BIO_printf(out, "DirName: "); 204109998Smarkm X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE); 205109998Smarkm break; 206109998Smarkm 207109998Smarkm case GEN_IPADD: 208109998Smarkm p = gen->d.ip->data; 209160814Ssimon if(gen->d.ip->length == 4) 210160814Ssimon BIO_printf(out, "IP Address:%d.%d.%d.%d", 211160814Ssimon p[0], p[1], p[2], p[3]); 212160814Ssimon else if(gen->d.ip->length == 16) 213160814Ssimon { 214160814Ssimon BIO_printf(out, "IP Address"); 215160814Ssimon for (i = 0; i < 8; i++) 216160814Ssimon { 217160814Ssimon BIO_printf(out, ":%X", p[0] << 8 | p[1]); 218160814Ssimon p += 2; 219160814Ssimon } 220160814Ssimon BIO_puts(out, "\n"); 221160814Ssimon } 222160814Ssimon else 223160814Ssimon { 224109998Smarkm BIO_printf(out,"IP Address:<invalid>"); 225109998Smarkm break; 226160814Ssimon } 227109998Smarkm break; 228109998Smarkm 229109998Smarkm case GEN_RID: 230109998Smarkm BIO_printf(out, "Registered ID"); 231109998Smarkm i2a_ASN1_OBJECT(out, gen->d.rid); 232109998Smarkm break; 233109998Smarkm } 234109998Smarkm return 1; 235109998Smarkm} 236109998Smarkm 237109998Smarkmstatic GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method, 23855714Skris X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 23955714Skris{ 240109998Smarkm GENERAL_NAMES *gens = NULL; 24155714Skris CONF_VALUE *cnf; 24255714Skris int i; 24368651Skris if(!(gens = sk_GENERAL_NAME_new_null())) { 244160814Ssimon X509V3err(X509V3_F_V2I_ISSUER_ALT,ERR_R_MALLOC_FAILURE); 24555714Skris return NULL; 24655714Skris } 24755714Skris for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 24855714Skris cnf = sk_CONF_VALUE_value(nval, i); 24955714Skris if(!name_cmp(cnf->name, "issuer") && cnf->value && 25055714Skris !strcmp(cnf->value, "copy")) { 25155714Skris if(!copy_issuer(ctx, gens)) goto err; 25255714Skris } else { 25355714Skris GENERAL_NAME *gen; 25455714Skris if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 25555714Skris goto err; 25655714Skris sk_GENERAL_NAME_push(gens, gen); 25755714Skris } 25855714Skris } 25955714Skris return gens; 26055714Skris err: 26155714Skris sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 26255714Skris return NULL; 26355714Skris} 26455714Skris 26555714Skris/* Append subject altname of issuer to issuer alt name of subject */ 26655714Skris 267109998Smarkmstatic int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens) 26855714Skris{ 269109998Smarkm GENERAL_NAMES *ialt; 27055714Skris GENERAL_NAME *gen; 27155714Skris X509_EXTENSION *ext; 27255714Skris int i; 27355714Skris if(ctx && (ctx->flags == CTX_TEST)) return 1; 27455714Skris if(!ctx || !ctx->issuer_cert) { 27555714Skris X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS); 27655714Skris goto err; 27755714Skris } 27855714Skris i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); 27955714Skris if(i < 0) return 1; 28055714Skris if(!(ext = X509_get_ext(ctx->issuer_cert, i)) || 28155714Skris !(ialt = X509V3_EXT_d2i(ext)) ) { 28255714Skris X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR); 28355714Skris goto err; 28455714Skris } 28555714Skris 28655714Skris for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) { 28755714Skris gen = sk_GENERAL_NAME_value(ialt, i); 28855714Skris if(!sk_GENERAL_NAME_push(gens, gen)) { 28955714Skris X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE); 29055714Skris goto err; 29155714Skris } 29255714Skris } 29355714Skris sk_GENERAL_NAME_free(ialt); 29455714Skris 29555714Skris return 1; 29655714Skris 29755714Skris err: 29855714Skris return 0; 29955714Skris 30055714Skris} 30155714Skris 302109998Smarkmstatic GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method, 30355714Skris X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 30455714Skris{ 305109998Smarkm GENERAL_NAMES *gens = NULL; 30655714Skris CONF_VALUE *cnf; 30755714Skris int i; 30868651Skris if(!(gens = sk_GENERAL_NAME_new_null())) { 309160814Ssimon X509V3err(X509V3_F_V2I_SUBJECT_ALT,ERR_R_MALLOC_FAILURE); 31055714Skris return NULL; 31155714Skris } 31255714Skris for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 31355714Skris cnf = sk_CONF_VALUE_value(nval, i); 31455714Skris if(!name_cmp(cnf->name, "email") && cnf->value && 31555714Skris !strcmp(cnf->value, "copy")) { 316109998Smarkm if(!copy_email(ctx, gens, 0)) goto err; 317109998Smarkm } else if(!name_cmp(cnf->name, "email") && cnf->value && 318109998Smarkm !strcmp(cnf->value, "move")) { 319109998Smarkm if(!copy_email(ctx, gens, 1)) goto err; 32055714Skris } else { 32155714Skris GENERAL_NAME *gen; 32255714Skris if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 32355714Skris goto err; 32455714Skris sk_GENERAL_NAME_push(gens, gen); 32555714Skris } 32655714Skris } 32755714Skris return gens; 32855714Skris err: 32955714Skris sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 33055714Skris return NULL; 33155714Skris} 33255714Skris 33355714Skris/* Copy any email addresses in a certificate or request to 33455714Skris * GENERAL_NAMES 33555714Skris */ 33655714Skris 337109998Smarkmstatic int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) 33855714Skris{ 33955714Skris X509_NAME *nm; 34055714Skris ASN1_IA5STRING *email = NULL; 34155714Skris X509_NAME_ENTRY *ne; 34255714Skris GENERAL_NAME *gen = NULL; 34355714Skris int i; 344160814Ssimon if(ctx != NULL && ctx->flags == CTX_TEST) 345160814Ssimon return 1; 34655714Skris if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) { 34755714Skris X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS); 34855714Skris goto err; 34955714Skris } 35055714Skris /* Find the subject name */ 35155714Skris if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert); 35255714Skris else nm = X509_REQ_get_subject_name(ctx->subject_req); 35355714Skris 35455714Skris /* Now add any email address(es) to STACK */ 35555714Skris i = -1; 35655714Skris while((i = X509_NAME_get_index_by_NID(nm, 35776866Skris NID_pkcs9_emailAddress, i)) >= 0) { 35855714Skris ne = X509_NAME_get_entry(nm, i); 35959191Skris email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); 360109998Smarkm if (move_p) 361109998Smarkm { 362109998Smarkm X509_NAME_delete_entry(nm, i); 363109998Smarkm i--; 364109998Smarkm } 36555714Skris if(!email || !(gen = GENERAL_NAME_new())) { 36655714Skris X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); 36755714Skris goto err; 36855714Skris } 36955714Skris gen->d.ia5 = email; 37055714Skris email = NULL; 37155714Skris gen->type = GEN_EMAIL; 37255714Skris if(!sk_GENERAL_NAME_push(gens, gen)) { 37355714Skris X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); 37455714Skris goto err; 37555714Skris } 37655714Skris gen = NULL; 37755714Skris } 37855714Skris 37955714Skris 38055714Skris return 1; 38155714Skris 38255714Skris err: 38355714Skris GENERAL_NAME_free(gen); 38459191Skris M_ASN1_IA5STRING_free(email); 38555714Skris return 0; 38655714Skris 38755714Skris} 38855714Skris 389109998SmarkmGENERAL_NAMES *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, 39055714Skris X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 39155714Skris{ 39255714Skris GENERAL_NAME *gen; 393109998Smarkm GENERAL_NAMES *gens = NULL; 39455714Skris CONF_VALUE *cnf; 39555714Skris int i; 39668651Skris if(!(gens = sk_GENERAL_NAME_new_null())) { 39755714Skris X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); 39855714Skris return NULL; 39955714Skris } 40055714Skris for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 40155714Skris cnf = sk_CONF_VALUE_value(nval, i); 40255714Skris if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err; 40355714Skris sk_GENERAL_NAME_push(gens, gen); 40455714Skris } 40555714Skris return gens; 40655714Skris err: 40755714Skris sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 40855714Skris return NULL; 40955714Skris} 41055714Skris 41155714SkrisGENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 41255714Skris CONF_VALUE *cnf) 413160814Ssimon { 414160814Ssimon return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0); 415160814Ssimon } 41655714Skris 417160814SsimonGENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out, 418160814Ssimon X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 419160814Ssimon CONF_VALUE *cnf, int is_nc) 420160814Ssimon { 421160814Ssimon char is_string = 0; 422160814Ssimon int type; 423160814Ssimon GENERAL_NAME *gen = NULL; 42455714Skris 425160814Ssimon char *name, *value; 42655714Skris 427160814Ssimon name = cnf->name; 428160814Ssimon value = cnf->value; 42955714Skris 430160814Ssimon if(!value) 431160814Ssimon { 432160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_MISSING_VALUE); 433160814Ssimon return NULL; 434160814Ssimon } 43555714Skris 436160814Ssimon if (out) 437160814Ssimon gen = out; 438160814Ssimon else 439160814Ssimon { 440160814Ssimon gen = GENERAL_NAME_new(); 441160814Ssimon if(gen == NULL) 442160814Ssimon { 443160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE); 444160814Ssimon return NULL; 445160814Ssimon } 446160814Ssimon } 447160814Ssimon 448160814Ssimon if(!name_cmp(name, "email")) 449160814Ssimon { 450160814Ssimon is_string = 1; 451160814Ssimon type = GEN_EMAIL; 452160814Ssimon } 453160814Ssimon else if(!name_cmp(name, "URI")) 454160814Ssimon { 455160814Ssimon is_string = 1; 456160814Ssimon type = GEN_URI; 457160814Ssimon } 458160814Ssimon else if(!name_cmp(name, "DNS")) 459160814Ssimon { 460160814Ssimon is_string = 1; 461160814Ssimon type = GEN_DNS; 462160814Ssimon } 463160814Ssimon else if(!name_cmp(name, "RID")) 464160814Ssimon { 465160814Ssimon ASN1_OBJECT *obj; 466160814Ssimon if(!(obj = OBJ_txt2obj(value,0))) 467160814Ssimon { 468160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_OBJECT); 469160814Ssimon ERR_add_error_data(2, "value=", value); 470160814Ssimon goto err; 471160814Ssimon } 472160814Ssimon gen->d.rid = obj; 473160814Ssimon type = GEN_RID; 474160814Ssimon } 475160814Ssimon else if(!name_cmp(name, "IP")) 476160814Ssimon { 477160814Ssimon if (is_nc) 478160814Ssimon gen->d.ip = a2i_IPADDRESS_NC(value); 479160814Ssimon else 480160814Ssimon gen->d.ip = a2i_IPADDRESS(value); 481160814Ssimon if(gen->d.ip == NULL) 482160814Ssimon { 483160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_BAD_IP_ADDRESS); 484160814Ssimon ERR_add_error_data(2, "value=", value); 485160814Ssimon goto err; 486160814Ssimon } 487160814Ssimon type = GEN_IPADD; 488160814Ssimon } 489160814Ssimon else if(!name_cmp(name, "dirName")) 490160814Ssimon { 491160814Ssimon type = GEN_DIRNAME; 492160814Ssimon if (!do_dirname(gen, value, ctx)) 493160814Ssimon { 494160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_DIRNAME_ERROR); 495160814Ssimon goto err; 496160814Ssimon } 497160814Ssimon } 498160814Ssimon else if(!name_cmp(name, "otherName")) 499160814Ssimon { 500160814Ssimon if (!do_othername(gen, value, ctx)) 501160814Ssimon { 502160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_OTHERNAME_ERROR); 503160814Ssimon goto err; 504160814Ssimon } 505160814Ssimon type = GEN_OTHERNAME; 506160814Ssimon } 507160814Ssimon else 508160814Ssimon { 509160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,X509V3_R_UNSUPPORTED_OPTION); 510160814Ssimon ERR_add_error_data(2, "name=", name); 51155714Skris goto err; 512160814Ssimon } 513160814Ssimon 514160814Ssimon if(is_string) 515160814Ssimon { 516160814Ssimon if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || 517160814Ssimon !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value, 518160814Ssimon strlen(value))) 519160814Ssimon { 520160814Ssimon X509V3err(X509V3_F_V2I_GENERAL_NAME_EX,ERR_R_MALLOC_FAILURE); 52155714Skris goto err; 522160814Ssimon } 523160814Ssimon } 524160814Ssimon 525160814Ssimon gen->type = type; 526160814Ssimon 527160814Ssimon return gen; 528160814Ssimon 529160814Ssimon err: 530160814Ssimon GENERAL_NAME_free(gen); 531160814Ssimon return NULL; 53255714Skris } 53355714Skris 534160814Ssimonstatic int do_othername(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) 535160814Ssimon { 536160814Ssimon char *objtmp = NULL, *p; 537160814Ssimon int objlen; 538160814Ssimon if (!(p = strchr(value, ';'))) 539160814Ssimon return 0; 540160814Ssimon if (!(gen->d.otherName = OTHERNAME_new())) 541160814Ssimon return 0; 542160814Ssimon /* Free this up because we will overwrite it. 543160814Ssimon * no need to free type_id because it is static 544160814Ssimon */ 545160814Ssimon ASN1_TYPE_free(gen->d.otherName->value); 546160814Ssimon if (!(gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx))) 547160814Ssimon return 0; 548160814Ssimon objlen = p - value; 549160814Ssimon objtmp = OPENSSL_malloc(objlen + 1); 550160814Ssimon strncpy(objtmp, value, objlen); 551160814Ssimon objtmp[objlen] = 0; 552160814Ssimon gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0); 553160814Ssimon OPENSSL_free(objtmp); 554160814Ssimon if (!gen->d.otherName->type_id) 555160814Ssimon return 0; 556160814Ssimon return 1; 55755714Skris } 55855714Skris 559160814Ssimonstatic int do_dirname(GENERAL_NAME *gen, char *value, X509V3_CTX *ctx) 560160814Ssimon { 561160814Ssimon int ret; 562160814Ssimon STACK_OF(CONF_VALUE) *sk; 563160814Ssimon X509_NAME *nm; 564160814Ssimon if (!(nm = X509_NAME_new())) 565160814Ssimon return 0; 566160814Ssimon sk = X509V3_get_section(ctx, value); 567160814Ssimon if (!sk) 568160814Ssimon { 569160814Ssimon X509V3err(X509V3_F_DO_DIRNAME,X509V3_R_SECTION_NOT_FOUND); 570160814Ssimon ERR_add_error_data(2, "section=", value); 571160814Ssimon X509_NAME_free(nm); 572160814Ssimon return 0; 573160814Ssimon } 574160814Ssimon /* FIXME: should allow other character types... */ 575160814Ssimon ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC); 576160814Ssimon if (!ret) 577160814Ssimon X509_NAME_free(nm); 578160814Ssimon gen->d.dirn = nm; 579160814Ssimon 580160814Ssimon return ret; 581160814Ssimon } 582