v3_alt.c revision 59191
1/* v3_alt.c */ 2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL 3 * project 1999. 4 */ 5/* ==================================================================== 6 * Copyright (c) 1999 The OpenSSL Project. All rights reserved. 7 * 8 * Redistribution and use in source and binary forms, with or without 9 * modification, are permitted provided that the following conditions 10 * are met: 11 * 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in 17 * the documentation and/or other materials provided with the 18 * distribution. 19 * 20 * 3. All advertising materials mentioning features or use of this 21 * software must display the following acknowledgment: 22 * "This product includes software developed by the OpenSSL Project 23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)" 24 * 25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to 26 * endorse or promote products derived from this software without 27 * prior written permission. For written permission, please contact 28 * licensing@OpenSSL.org. 29 * 30 * 5. Products derived from this software may not be called "OpenSSL" 31 * nor may "OpenSSL" appear in their names without prior written 32 * permission of the OpenSSL Project. 33 * 34 * 6. Redistributions of any form whatsoever must retain the following 35 * acknowledgment: 36 * "This product includes software developed by the OpenSSL Project 37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)" 38 * 39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY 40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR 43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, 44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED 50 * OF THE POSSIBILITY OF SUCH DAMAGE. 51 * ==================================================================== 52 * 53 * This product includes cryptographic software written by Eric Young 54 * (eay@cryptsoft.com). This product includes software written by Tim 55 * Hudson (tjh@cryptsoft.com). 56 * 57 */ 58 59#include <stdio.h> 60#include "cryptlib.h" 61#include <openssl/conf.h> 62#include <openssl/x509v3.h> 63 64static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 65static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval); 66static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens); 67static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens); 68X509V3_EXT_METHOD v3_alt[] = { 69{ NID_subject_alt_name, 0, 70(X509V3_EXT_NEW)GENERAL_NAMES_new, 71(X509V3_EXT_FREE)GENERAL_NAMES_free, 72(X509V3_EXT_D2I)d2i_GENERAL_NAMES, 73(X509V3_EXT_I2D)i2d_GENERAL_NAMES, 74NULL, NULL, 75(X509V3_EXT_I2V)i2v_GENERAL_NAMES, 76(X509V3_EXT_V2I)v2i_subject_alt, 77NULL, NULL, NULL}, 78{ NID_issuer_alt_name, 0, 79(X509V3_EXT_NEW)GENERAL_NAMES_new, 80(X509V3_EXT_FREE)GENERAL_NAMES_free, 81(X509V3_EXT_D2I)d2i_GENERAL_NAMES, 82(X509V3_EXT_I2D)i2d_GENERAL_NAMES, 83NULL, NULL, 84(X509V3_EXT_I2V)i2v_GENERAL_NAMES, 85(X509V3_EXT_V2I)v2i_issuer_alt, 86NULL, NULL, NULL}, 87}; 88 89STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method, 90 STACK_OF(GENERAL_NAME) *gens, STACK_OF(CONF_VALUE) *ret) 91{ 92 int i; 93 GENERAL_NAME *gen; 94 for(i = 0; i < sk_GENERAL_NAME_num(gens); i++) { 95 gen = sk_GENERAL_NAME_value(gens, i); 96 ret = i2v_GENERAL_NAME(method, gen, ret); 97 } 98 if(!ret) return sk_CONF_VALUE_new_null(); 99 return ret; 100} 101 102STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method, 103 GENERAL_NAME *gen, STACK_OF(CONF_VALUE) *ret) 104{ 105 char oline[256]; 106 unsigned char *p; 107 switch (gen->type) 108 { 109 case GEN_OTHERNAME: 110 X509V3_add_value("othername","<unsupported>", &ret); 111 break; 112 113 case GEN_X400: 114 X509V3_add_value("X400Name","<unsupported>", &ret); 115 break; 116 117 case GEN_EDIPARTY: 118 X509V3_add_value("EdiPartyName","<unsupported>", &ret); 119 break; 120 121 case GEN_EMAIL: 122 X509V3_add_value_uchar("email",gen->d.ia5->data, &ret); 123 break; 124 125 case GEN_DNS: 126 X509V3_add_value_uchar("DNS",gen->d.ia5->data, &ret); 127 break; 128 129 case GEN_URI: 130 X509V3_add_value_uchar("URI",gen->d.ia5->data, &ret); 131 break; 132 133 case GEN_DIRNAME: 134 X509_NAME_oneline(gen->d.dirn, oline, 256); 135 X509V3_add_value("DirName",oline, &ret); 136 break; 137 138 case GEN_IPADD: 139 p = gen->d.ip->data; 140 /* BUG: doesn't support IPV6 */ 141 if(gen->d.ip->length != 4) { 142 X509V3_add_value("IP Address","<invalid>", &ret); 143 break; 144 } 145 sprintf(oline, "%d.%d.%d.%d", p[0], p[1], p[2], p[3]); 146 X509V3_add_value("IP Address",oline, &ret); 147 break; 148 149 case GEN_RID: 150 i2t_ASN1_OBJECT(oline, 256, gen->d.rid); 151 X509V3_add_value("Registered ID",oline, &ret); 152 break; 153 } 154 return ret; 155} 156 157static STACK_OF(GENERAL_NAME) *v2i_issuer_alt(X509V3_EXT_METHOD *method, 158 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 159{ 160 STACK_OF(GENERAL_NAME) *gens = NULL; 161 CONF_VALUE *cnf; 162 int i; 163 if(!(gens = sk_GENERAL_NAME_new(NULL))) { 164 X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); 165 return NULL; 166 } 167 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 168 cnf = sk_CONF_VALUE_value(nval, i); 169 if(!name_cmp(cnf->name, "issuer") && cnf->value && 170 !strcmp(cnf->value, "copy")) { 171 if(!copy_issuer(ctx, gens)) goto err; 172 } else { 173 GENERAL_NAME *gen; 174 if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 175 goto err; 176 sk_GENERAL_NAME_push(gens, gen); 177 } 178 } 179 return gens; 180 err: 181 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 182 return NULL; 183} 184 185/* Append subject altname of issuer to issuer alt name of subject */ 186 187static int copy_issuer(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) 188{ 189 STACK_OF(GENERAL_NAME) *ialt; 190 GENERAL_NAME *gen; 191 X509_EXTENSION *ext; 192 int i; 193 if(ctx && (ctx->flags == CTX_TEST)) return 1; 194 if(!ctx || !ctx->issuer_cert) { 195 X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_NO_ISSUER_DETAILS); 196 goto err; 197 } 198 i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1); 199 if(i < 0) return 1; 200 if(!(ext = X509_get_ext(ctx->issuer_cert, i)) || 201 !(ialt = X509V3_EXT_d2i(ext)) ) { 202 X509V3err(X509V3_F_COPY_ISSUER,X509V3_R_ISSUER_DECODE_ERROR); 203 goto err; 204 } 205 206 for(i = 0; i < sk_GENERAL_NAME_num(ialt); i++) { 207 gen = sk_GENERAL_NAME_value(ialt, i); 208 if(!sk_GENERAL_NAME_push(gens, gen)) { 209 X509V3err(X509V3_F_COPY_ISSUER,ERR_R_MALLOC_FAILURE); 210 goto err; 211 } 212 } 213 sk_GENERAL_NAME_free(ialt); 214 215 return 1; 216 217 err: 218 return 0; 219 220} 221 222static STACK_OF(GENERAL_NAME) *v2i_subject_alt(X509V3_EXT_METHOD *method, 223 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 224{ 225 STACK_OF(GENERAL_NAME) *gens = NULL; 226 CONF_VALUE *cnf; 227 int i; 228 if(!(gens = sk_GENERAL_NAME_new(NULL))) { 229 X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); 230 return NULL; 231 } 232 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 233 cnf = sk_CONF_VALUE_value(nval, i); 234 if(!name_cmp(cnf->name, "email") && cnf->value && 235 !strcmp(cnf->value, "copy")) { 236 if(!copy_email(ctx, gens)) goto err; 237 } else { 238 GENERAL_NAME *gen; 239 if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) 240 goto err; 241 sk_GENERAL_NAME_push(gens, gen); 242 } 243 } 244 return gens; 245 err: 246 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 247 return NULL; 248} 249 250/* Copy any email addresses in a certificate or request to 251 * GENERAL_NAMES 252 */ 253 254static int copy_email(X509V3_CTX *ctx, STACK_OF(GENERAL_NAME) *gens) 255{ 256 X509_NAME *nm; 257 ASN1_IA5STRING *email = NULL; 258 X509_NAME_ENTRY *ne; 259 GENERAL_NAME *gen = NULL; 260 int i; 261 if(ctx->flags == CTX_TEST) return 1; 262 if(!ctx || (!ctx->subject_cert && !ctx->subject_req)) { 263 X509V3err(X509V3_F_COPY_EMAIL,X509V3_R_NO_SUBJECT_DETAILS); 264 goto err; 265 } 266 /* Find the subject name */ 267 if(ctx->subject_cert) nm = X509_get_subject_name(ctx->subject_cert); 268 else nm = X509_REQ_get_subject_name(ctx->subject_req); 269 270 /* Now add any email address(es) to STACK */ 271 i = -1; 272 while((i = X509_NAME_get_index_by_NID(nm, 273 NID_pkcs9_emailAddress, i)) > 0) { 274 ne = X509_NAME_get_entry(nm, i); 275 email = M_ASN1_IA5STRING_dup(X509_NAME_ENTRY_get_data(ne)); 276 if(!email || !(gen = GENERAL_NAME_new())) { 277 X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); 278 goto err; 279 } 280 gen->d.ia5 = email; 281 email = NULL; 282 gen->type = GEN_EMAIL; 283 if(!sk_GENERAL_NAME_push(gens, gen)) { 284 X509V3err(X509V3_F_COPY_EMAIL,ERR_R_MALLOC_FAILURE); 285 goto err; 286 } 287 gen = NULL; 288 } 289 290 291 return 1; 292 293 err: 294 GENERAL_NAME_free(gen); 295 M_ASN1_IA5STRING_free(email); 296 return 0; 297 298} 299 300STACK_OF(GENERAL_NAME) *v2i_GENERAL_NAMES(X509V3_EXT_METHOD *method, 301 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval) 302{ 303 GENERAL_NAME *gen; 304 STACK_OF(GENERAL_NAME) *gens = NULL; 305 CONF_VALUE *cnf; 306 int i; 307 if(!(gens = sk_GENERAL_NAME_new(NULL))) { 308 X509V3err(X509V3_F_V2I_GENERAL_NAMES,ERR_R_MALLOC_FAILURE); 309 return NULL; 310 } 311 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) { 312 cnf = sk_CONF_VALUE_value(nval, i); 313 if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) goto err; 314 sk_GENERAL_NAME_push(gens, gen); 315 } 316 return gens; 317 err: 318 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free); 319 return NULL; 320} 321 322GENERAL_NAME *v2i_GENERAL_NAME(X509V3_EXT_METHOD *method, X509V3_CTX *ctx, 323 CONF_VALUE *cnf) 324{ 325char is_string = 0; 326int type; 327GENERAL_NAME *gen = NULL; 328 329char *name, *value; 330 331name = cnf->name; 332value = cnf->value; 333 334if(!value) { 335 X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_MISSING_VALUE); 336 return NULL; 337} 338 339if(!(gen = GENERAL_NAME_new())) { 340 X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); 341 return NULL; 342} 343 344if(!name_cmp(name, "email")) { 345 is_string = 1; 346 type = GEN_EMAIL; 347} else if(!name_cmp(name, "URI")) { 348 is_string = 1; 349 type = GEN_URI; 350} else if(!name_cmp(name, "DNS")) { 351 is_string = 1; 352 type = GEN_DNS; 353} else if(!name_cmp(name, "RID")) { 354 ASN1_OBJECT *obj; 355 if(!(obj = OBJ_txt2obj(value,0))) { 356 X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_OBJECT); 357 ERR_add_error_data(2, "value=", value); 358 goto err; 359 } 360 gen->d.rid = obj; 361 type = GEN_RID; 362} else if(!name_cmp(name, "IP")) { 363 int i1,i2,i3,i4; 364 unsigned char ip[4]; 365 if((sscanf(value, "%d.%d.%d.%d",&i1,&i2,&i3,&i4) != 4) || 366 (i1 < 0) || (i1 > 255) || (i2 < 0) || (i2 > 255) || 367 (i3 < 0) || (i3 > 255) || (i4 < 0) || (i4 > 255) ) { 368 X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_BAD_IP_ADDRESS); 369 ERR_add_error_data(2, "value=", value); 370 goto err; 371 } 372 ip[0] = i1; ip[1] = i2 ; ip[2] = i3 ; ip[3] = i4; 373 if(!(gen->d.ip = M_ASN1_OCTET_STRING_new()) || 374 !ASN1_STRING_set(gen->d.ip, ip, 4)) { 375 X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); 376 goto err; 377 } 378 type = GEN_IPADD; 379} else { 380 X509V3err(X509V3_F_V2I_GENERAL_NAME,X509V3_R_UNSUPPORTED_OPTION); 381 ERR_add_error_data(2, "name=", name); 382 goto err; 383} 384 385if(is_string) { 386 if(!(gen->d.ia5 = M_ASN1_IA5STRING_new()) || 387 !ASN1_STRING_set(gen->d.ia5, (unsigned char*)value, 388 strlen(value))) { 389 X509V3err(X509V3_F_V2I_GENERAL_NAME,ERR_R_MALLOC_FAILURE); 390 goto err; 391 } 392} 393 394gen->type = type; 395 396return gen; 397 398err: 399GENERAL_NAME_free(gen); 400return NULL; 401} 402