1 /*
2 * Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3 * project.
4 */
5 /* ====================================================================
6 * Copyright (c) 1999-2003 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 #include <stdio.h>
58 #include <string.h>
59
60 #include <openssl/conf.h>
61 #include <openssl/err.h>
62 #include <openssl/mem.h>
63 #include <openssl/obj.h>
64 #include <openssl/x509v3.h>
65
66 #include "../x509/internal.h"
67 #include "internal.h"
68
69
70 static void *v2i_subject_alt(const X509V3_EXT_METHOD *method,
71 const X509V3_CTX *ctx,
72 const STACK_OF(CONF_VALUE) *nval);
73 static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method,
74 const X509V3_CTX *ctx,
75 const STACK_OF(CONF_VALUE) *nval);
76 static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
77 static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens);
78 static int do_othername(GENERAL_NAME *gen, const char *value,
79 const X509V3_CTX *ctx);
80 static int do_dirname(GENERAL_NAME *gen, const char *value,
81 const X509V3_CTX *ctx);
82
STACK_OF(CONF_VALUE)83 static STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES_cb(
84 const X509V3_EXT_METHOD *method, void *ext, STACK_OF(CONF_VALUE) *ret) {
85 return i2v_GENERAL_NAMES(method, ext, ret);
86 }
87
88 const X509V3_EXT_METHOD v3_alt[] = {
89 {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
90 i2v_GENERAL_NAMES_cb, v2i_subject_alt, NULL, NULL, NULL},
91
92 {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
93 i2v_GENERAL_NAMES_cb, v2i_issuer_alt, NULL, NULL, NULL},
94
95 {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES), 0, 0, 0, 0, 0, 0,
96 i2v_GENERAL_NAMES_cb, NULL, NULL, NULL, NULL},
97 };
98
STACK_OF(CONF_VALUE)99 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
100 const GENERAL_NAMES *gens,
101 STACK_OF(CONF_VALUE) *ret) {
102 int ret_was_null = ret == NULL;
103 for (size_t i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
104 const GENERAL_NAME *gen = sk_GENERAL_NAME_value(gens, i);
105 STACK_OF(CONF_VALUE) *tmp = i2v_GENERAL_NAME(method, gen, ret);
106 if (tmp == NULL) {
107 if (ret_was_null) {
108 sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
109 }
110 return NULL;
111 }
112 ret = tmp;
113 }
114 if (!ret) {
115 return sk_CONF_VALUE_new_null();
116 }
117 return ret;
118 }
119
STACK_OF(CONF_VALUE)120 STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(const X509V3_EXT_METHOD *method,
121 const GENERAL_NAME *gen,
122 STACK_OF(CONF_VALUE) *ret) {
123 // Note the error-handling for this function relies on there being at most
124 // one |X509V3_add_value| call. If there were two and the second failed, we
125 // would need to sometimes free the first call's result.
126 unsigned char *p;
127 char oline[256], htmp[5];
128 int i;
129 switch (gen->type) {
130 case GEN_OTHERNAME:
131 if (!X509V3_add_value("othername", "<unsupported>", &ret)) {
132 return NULL;
133 }
134 break;
135
136 case GEN_X400:
137 if (!X509V3_add_value("X400Name", "<unsupported>", &ret)) {
138 return NULL;
139 }
140 break;
141
142 case GEN_EDIPARTY:
143 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret)) {
144 return NULL;
145 }
146 break;
147
148 case GEN_EMAIL:
149 if (!x509V3_add_value_asn1_string("email", gen->d.ia5, &ret)) {
150 return NULL;
151 }
152 break;
153
154 case GEN_DNS:
155 if (!x509V3_add_value_asn1_string("DNS", gen->d.ia5, &ret)) {
156 return NULL;
157 }
158 break;
159
160 case GEN_URI:
161 if (!x509V3_add_value_asn1_string("URI", gen->d.ia5, &ret)) {
162 return NULL;
163 }
164 break;
165
166 case GEN_DIRNAME:
167 if (X509_NAME_oneline(gen->d.dirn, oline, 256) == NULL ||
168 !X509V3_add_value("DirName", oline, &ret)) {
169 return NULL;
170 }
171 break;
172
173 case GEN_IPADD:
174 p = gen->d.ip->data;
175 if (gen->d.ip->length == 4) {
176 snprintf(oline, sizeof(oline), "%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
177 } else if (gen->d.ip->length == 16) {
178 oline[0] = 0;
179 for (i = 0; i < 8; i++) {
180 uint16_t v = ((uint16_t)p[0] << 8) | p[1];
181 snprintf(htmp, sizeof(htmp), "%X", v);
182 p += 2;
183 OPENSSL_strlcat(oline, htmp, sizeof(oline));
184 if (i != 7) {
185 OPENSSL_strlcat(oline, ":", sizeof(oline));
186 }
187 }
188 } else {
189 if (!X509V3_add_value("IP Address", "<invalid>", &ret)) {
190 return NULL;
191 }
192 break;
193 }
194 if (!X509V3_add_value("IP Address", oline, &ret)) {
195 return NULL;
196 }
197 break;
198
199 case GEN_RID:
200 i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
201 if (!X509V3_add_value("Registered ID", oline, &ret)) {
202 return NULL;
203 }
204 break;
205 }
206 return ret;
207 }
208
GENERAL_NAME_print(BIO * out,const GENERAL_NAME * gen)209 int GENERAL_NAME_print(BIO *out, const GENERAL_NAME *gen) {
210 switch (gen->type) {
211 case GEN_OTHERNAME:
212 BIO_printf(out, "othername:<unsupported>");
213 break;
214
215 case GEN_X400:
216 BIO_printf(out, "X400Name:<unsupported>");
217 break;
218
219 case GEN_EDIPARTY:
220 // Maybe fix this: it is supported now
221 BIO_printf(out, "EdiPartyName:<unsupported>");
222 break;
223
224 case GEN_EMAIL:
225 BIO_printf(out, "email:");
226 ASN1_STRING_print(out, gen->d.ia5);
227 break;
228
229 case GEN_DNS:
230 BIO_printf(out, "DNS:");
231 ASN1_STRING_print(out, gen->d.ia5);
232 break;
233
234 case GEN_URI:
235 BIO_printf(out, "URI:");
236 ASN1_STRING_print(out, gen->d.ia5);
237 break;
238
239 case GEN_DIRNAME:
240 BIO_printf(out, "DirName: ");
241 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
242 break;
243
244 case GEN_IPADD: {
245 const unsigned char *p = gen->d.ip->data;
246 if (gen->d.ip->length == 4) {
247 BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
248 } else if (gen->d.ip->length == 16) {
249 BIO_printf(out, "IP Address");
250 for (int i = 0; i < 8; i++) {
251 uint16_t v = ((uint16_t)p[0] << 8) | p[1];
252 BIO_printf(out, ":%X", v);
253 p += 2;
254 }
255 BIO_puts(out, "\n");
256 } else {
257 BIO_printf(out, "IP Address:<invalid>");
258 break;
259 }
260 break;
261 }
262
263 case GEN_RID:
264 BIO_printf(out, "Registered ID");
265 i2a_ASN1_OBJECT(out, gen->d.rid);
266 break;
267 }
268 return 1;
269 }
270
v2i_issuer_alt(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)271 static void *v2i_issuer_alt(const X509V3_EXT_METHOD *method,
272 const X509V3_CTX *ctx,
273 const STACK_OF(CONF_VALUE) *nval) {
274 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
275 if (gens == NULL) {
276 return NULL;
277 }
278 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
279 const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
280 if (x509v3_conf_name_matches(cnf->name, "issuer") && cnf->value &&
281 !strcmp(cnf->value, "copy")) {
282 if (!copy_issuer(ctx, gens)) {
283 goto err;
284 }
285 } else {
286 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
287 if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
288 GENERAL_NAME_free(gen);
289 goto err;
290 }
291 }
292 }
293 return gens;
294 err:
295 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
296 return NULL;
297 }
298
299 // Append subject altname of issuer to issuer alt name of subject
300
copy_issuer(const X509V3_CTX * ctx,GENERAL_NAMES * gens)301 static int copy_issuer(const X509V3_CTX *ctx, GENERAL_NAMES *gens) {
302 if (ctx && (ctx->flags == X509V3_CTX_TEST)) {
303 return 1;
304 }
305 if (!ctx || !ctx->issuer_cert) {
306 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_ISSUER_DETAILS);
307 return 0;
308 }
309 int i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
310 if (i < 0) {
311 return 1;
312 }
313
314 int ret = 0;
315 GENERAL_NAMES *ialt = NULL;
316 X509_EXTENSION *ext;
317 if (!(ext = X509_get_ext(ctx->issuer_cert, i)) ||
318 !(ialt = X509V3_EXT_d2i(ext))) {
319 OPENSSL_PUT_ERROR(X509V3, X509V3_R_ISSUER_DECODE_ERROR);
320 goto err;
321 }
322
323 for (size_t j = 0; j < sk_GENERAL_NAME_num(ialt); j++) {
324 GENERAL_NAME *gen = sk_GENERAL_NAME_value(ialt, j);
325 if (!sk_GENERAL_NAME_push(gens, gen)) {
326 goto err;
327 }
328 // Ownership of |gen| has moved from |ialt| to |gens|.
329 sk_GENERAL_NAME_set(ialt, j, NULL);
330 }
331
332 ret = 1;
333
334 err:
335 GENERAL_NAMES_free(ialt);
336 return ret;
337 }
338
v2i_subject_alt(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)339 static void *v2i_subject_alt(const X509V3_EXT_METHOD *method,
340 const X509V3_CTX *ctx,
341 const STACK_OF(CONF_VALUE) *nval) {
342 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
343 if (gens == NULL) {
344 return NULL;
345 }
346 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
347 const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
348 if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
349 !strcmp(cnf->value, "copy")) {
350 if (!copy_email(ctx, gens, 0)) {
351 goto err;
352 }
353 } else if (x509v3_conf_name_matches(cnf->name, "email") && cnf->value &&
354 !strcmp(cnf->value, "move")) {
355 if (!copy_email(ctx, gens, 1)) {
356 goto err;
357 }
358 } else {
359 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
360 if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
361 GENERAL_NAME_free(gen);
362 goto err;
363 }
364 }
365 }
366 return gens;
367 err:
368 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
369 return NULL;
370 }
371
372 // Copy any email addresses in a certificate or request to GENERAL_NAMES
373
copy_email(const X509V3_CTX * ctx,GENERAL_NAMES * gens,int move_p)374 static int copy_email(const X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p) {
375 X509_NAME *nm;
376 ASN1_IA5STRING *email = NULL;
377 X509_NAME_ENTRY *ne;
378 GENERAL_NAME *gen = NULL;
379 int i;
380 if (ctx != NULL && ctx->flags == X509V3_CTX_TEST) {
381 return 1;
382 }
383 if (!ctx || (!ctx->subject_cert && !ctx->subject_req)) {
384 OPENSSL_PUT_ERROR(X509V3, X509V3_R_NO_SUBJECT_DETAILS);
385 goto err;
386 }
387 // Find the subject name
388 if (ctx->subject_cert) {
389 nm = X509_get_subject_name(ctx->subject_cert);
390 } else {
391 nm = X509_REQ_get_subject_name(ctx->subject_req);
392 }
393
394 // Now add any email address(es) to STACK
395 i = -1;
396 while ((i = X509_NAME_get_index_by_NID(nm, NID_pkcs9_emailAddress, i)) >= 0) {
397 ne = X509_NAME_get_entry(nm, i);
398 email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
399 if (move_p) {
400 X509_NAME_delete_entry(nm, i);
401 X509_NAME_ENTRY_free(ne);
402 i--;
403 }
404 if (!email || !(gen = GENERAL_NAME_new())) {
405 goto err;
406 }
407 gen->d.ia5 = email;
408 email = NULL;
409 gen->type = GEN_EMAIL;
410 if (!sk_GENERAL_NAME_push(gens, gen)) {
411 goto err;
412 }
413 gen = NULL;
414 }
415
416 return 1;
417
418 err:
419 GENERAL_NAME_free(gen);
420 ASN1_IA5STRING_free(email);
421 return 0;
422 }
423
v2i_GENERAL_NAMES(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)424 GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
425 const X509V3_CTX *ctx,
426 const STACK_OF(CONF_VALUE) *nval) {
427 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_null();
428 if (gens == NULL) {
429 return NULL;
430 }
431 for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
432 const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
433 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
434 if (gen == NULL || !sk_GENERAL_NAME_push(gens, gen)) {
435 GENERAL_NAME_free(gen);
436 goto err;
437 }
438 }
439 return gens;
440 err:
441 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
442 return NULL;
443 }
444
v2i_GENERAL_NAME(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const CONF_VALUE * cnf)445 GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
446 const X509V3_CTX *ctx, const CONF_VALUE *cnf) {
447 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
448 }
449
a2i_GENERAL_NAME(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,int gen_type,const char * value,int is_nc)450 GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
451 const X509V3_EXT_METHOD *method,
452 const X509V3_CTX *ctx, int gen_type,
453 const char *value, int is_nc) {
454 if (!value) {
455 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
456 return NULL;
457 }
458
459 GENERAL_NAME *gen = NULL;
460 if (out) {
461 gen = out;
462 } else {
463 gen = GENERAL_NAME_new();
464 if (gen == NULL) {
465 return NULL;
466 }
467 }
468
469 switch (gen_type) {
470 case GEN_URI:
471 case GEN_EMAIL:
472 case GEN_DNS: {
473 ASN1_IA5STRING *str = ASN1_IA5STRING_new();
474 if (str == NULL || !ASN1_STRING_set(str, value, strlen(value))) {
475 ASN1_STRING_free(str);
476 goto err;
477 }
478 gen->type = gen_type;
479 gen->d.ia5 = str;
480 break;
481 }
482
483 case GEN_RID: {
484 ASN1_OBJECT *obj;
485 if (!(obj = OBJ_txt2obj(value, 0))) {
486 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_OBJECT);
487 ERR_add_error_data(2, "value=", value);
488 goto err;
489 }
490 gen->type = GEN_RID;
491 gen->d.rid = obj;
492 break;
493 }
494
495 case GEN_IPADD:
496 gen->type = GEN_IPADD;
497 if (is_nc) {
498 gen->d.ip = a2i_IPADDRESS_NC(value);
499 } else {
500 gen->d.ip = a2i_IPADDRESS(value);
501 }
502 if (gen->d.ip == NULL) {
503 OPENSSL_PUT_ERROR(X509V3, X509V3_R_BAD_IP_ADDRESS);
504 ERR_add_error_data(2, "value=", value);
505 goto err;
506 }
507 break;
508
509 case GEN_DIRNAME:
510 if (!do_dirname(gen, value, ctx)) {
511 OPENSSL_PUT_ERROR(X509V3, X509V3_R_DIRNAME_ERROR);
512 goto err;
513 }
514 break;
515
516 case GEN_OTHERNAME:
517 if (!do_othername(gen, value, ctx)) {
518 OPENSSL_PUT_ERROR(X509V3, X509V3_R_OTHERNAME_ERROR);
519 goto err;
520 }
521 break;
522 default:
523 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_TYPE);
524 goto err;
525 }
526
527 return gen;
528
529 err:
530 if (!out) {
531 GENERAL_NAME_free(gen);
532 }
533 return NULL;
534 }
535
v2i_GENERAL_NAME_ex(GENERAL_NAME * out,const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const CONF_VALUE * cnf,int is_nc)536 GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
537 const X509V3_EXT_METHOD *method,
538 const X509V3_CTX *ctx, const CONF_VALUE *cnf,
539 int is_nc) {
540 const char *name = cnf->name;
541 const char *value = cnf->value;
542 if (!value) {
543 OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
544 return NULL;
545 }
546
547 int type;
548 if (x509v3_conf_name_matches(name, "email")) {
549 type = GEN_EMAIL;
550 } else if (x509v3_conf_name_matches(name, "URI")) {
551 type = GEN_URI;
552 } else if (x509v3_conf_name_matches(name, "DNS")) {
553 type = GEN_DNS;
554 } else if (x509v3_conf_name_matches(name, "RID")) {
555 type = GEN_RID;
556 } else if (x509v3_conf_name_matches(name, "IP")) {
557 type = GEN_IPADD;
558 } else if (x509v3_conf_name_matches(name, "dirName")) {
559 type = GEN_DIRNAME;
560 } else if (x509v3_conf_name_matches(name, "otherName")) {
561 type = GEN_OTHERNAME;
562 } else {
563 OPENSSL_PUT_ERROR(X509V3, X509V3_R_UNSUPPORTED_OPTION);
564 ERR_add_error_data(2, "name=", name);
565 return NULL;
566 }
567
568 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
569 }
570
do_othername(GENERAL_NAME * gen,const char * value,const X509V3_CTX * ctx)571 static int do_othername(GENERAL_NAME *gen, const char *value,
572 const X509V3_CTX *ctx) {
573 const char *semicolon = strchr(value, ';');
574 if (semicolon == NULL) {
575 return 0;
576 }
577
578 OTHERNAME *name = OTHERNAME_new();
579 if (name == NULL) {
580 return 0;
581 }
582
583 char *objtmp = OPENSSL_strndup(value, semicolon - value);
584 if (objtmp == NULL) {
585 goto err;
586 }
587 ASN1_OBJECT_free(name->type_id);
588 name->type_id = OBJ_txt2obj(objtmp, /*dont_search_names=*/0);
589 OPENSSL_free(objtmp);
590 if (name->type_id == NULL) {
591 goto err;
592 }
593
594 ASN1_TYPE_free(name->value);
595 name->value = ASN1_generate_v3(semicolon + 1, ctx);
596 if (name->value == NULL) {
597 goto err;
598 }
599
600 gen->type = GEN_OTHERNAME;
601 gen->d.otherName = name;
602 return 1;
603
604 err:
605 OTHERNAME_free(name);
606 return 0;
607 }
608
do_dirname(GENERAL_NAME * gen,const char * value,const X509V3_CTX * ctx)609 static int do_dirname(GENERAL_NAME *gen, const char *value,
610 const X509V3_CTX *ctx) {
611 int ret = 0;
612 X509_NAME *nm = X509_NAME_new();
613 if (nm == NULL) {
614 goto err;
615 }
616 const STACK_OF(CONF_VALUE) *sk = X509V3_get_section(ctx, value);
617 if (sk == NULL) {
618 OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
619 ERR_add_error_data(2, "section=", value);
620 goto err;
621 }
622 // FIXME: should allow other character types...
623 if (!X509V3_NAME_from_section(nm, sk, MBSTRING_ASC)) {
624 goto err;
625 }
626 gen->type = GEN_DIRNAME;
627 gen->d.dirn = nm;
628 ret = 1;
629
630 err:
631 if (!ret) {
632 X509_NAME_free(nm);
633 }
634 return ret;
635 }
636