VirtualBox

source: vbox/trunk/src/libs/openssl-1.1.1l/crypto/x509v3/v3_alt.c@ 91772

Last change on this file since 91772 was 91772, checked in by vboxsync, 3 years ago

openssl-1.1.1l: Applied and adjusted our OpenSSL changes to 1.1.1l. bugref:10126

File size: 17.3 KB
Line 
1/*
2 * Copyright 1999-2021 The OpenSSL Project Authors. All Rights Reserved.
3 *
4 * Licensed under the OpenSSL license (the "License"). You may not use
5 * this file except in compliance with the License. You can obtain a copy
6 * in the file LICENSE in the source distribution or at
7 * https://www.openssl.org/source/license.html
8 */
9
10#include <stdio.h>
11#include "internal/cryptlib.h"
12#include "crypto/x509.h"
13#include <openssl/conf.h>
14#include <openssl/x509v3.h>
15#include "ext_dat.h"
16
17static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
18 X509V3_CTX *ctx,
19 STACK_OF(CONF_VALUE) *nval);
20static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
21 X509V3_CTX *ctx,
22 STACK_OF(CONF_VALUE) *nval);
23static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p);
24static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens);
25static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
26static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx);
27
28const X509V3_EXT_METHOD v3_alt[3] = {
29 {NID_subject_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
30 0, 0, 0, 0,
31 0, 0,
32 (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
33 (X509V3_EXT_V2I)v2i_subject_alt,
34 NULL, NULL, NULL},
35
36 {NID_issuer_alt_name, 0, ASN1_ITEM_ref(GENERAL_NAMES),
37 0, 0, 0, 0,
38 0, 0,
39 (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
40 (X509V3_EXT_V2I)v2i_issuer_alt,
41 NULL, NULL, NULL},
42
43 {NID_certificate_issuer, 0, ASN1_ITEM_ref(GENERAL_NAMES),
44 0, 0, 0, 0,
45 0, 0,
46 (X509V3_EXT_I2V) i2v_GENERAL_NAMES,
47 NULL, NULL, NULL, NULL},
48};
49
50STACK_OF(CONF_VALUE) *i2v_GENERAL_NAMES(X509V3_EXT_METHOD *method,
51 GENERAL_NAMES *gens,
52 STACK_OF(CONF_VALUE) *ret)
53{
54 int i;
55 GENERAL_NAME *gen;
56 STACK_OF(CONF_VALUE) *tmpret = NULL, *origret = ret;
57
58 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
59 gen = sk_GENERAL_NAME_value(gens, i);
60 /*
61 * i2v_GENERAL_NAME allocates ret if it is NULL. If something goes
62 * wrong we need to free the stack - but only if it was empty when we
63 * originally entered this function.
64 */
65 tmpret = i2v_GENERAL_NAME(method, gen, ret);
66 if (tmpret == NULL) {
67 if (origret == NULL)
68 sk_CONF_VALUE_pop_free(ret, X509V3_conf_free);
69 return NULL;
70 }
71 ret = tmpret;
72 }
73 if (ret == NULL)
74 return sk_CONF_VALUE_new_null();
75 return ret;
76}
77
78STACK_OF(CONF_VALUE) *i2v_GENERAL_NAME(X509V3_EXT_METHOD *method,
79 GENERAL_NAME *gen,
80 STACK_OF(CONF_VALUE) *ret)
81{
82 unsigned char *p;
83 char oline[256], htmp[5];
84 int i;
85
86 switch (gen->type) {
87 case GEN_OTHERNAME:
88 if (!X509V3_add_value("othername", "<unsupported>", &ret))
89 return NULL;
90 break;
91
92 case GEN_X400:
93 if (!X509V3_add_value("X400Name", "<unsupported>", &ret))
94 return NULL;
95 break;
96
97 case GEN_EDIPARTY:
98 if (!X509V3_add_value("EdiPartyName", "<unsupported>", &ret))
99 return NULL;
100 break;
101
102 case GEN_EMAIL:
103 if (!x509v3_add_len_value_uchar("email", gen->d.ia5->data,
104 gen->d.ia5->length, &ret))
105 return NULL;
106 break;
107
108 case GEN_DNS:
109 if (!x509v3_add_len_value_uchar("DNS", gen->d.ia5->data,
110 gen->d.ia5->length, &ret))
111 return NULL;
112 break;
113
114 case GEN_URI:
115 if (!x509v3_add_len_value_uchar("URI", gen->d.ia5->data,
116 gen->d.ia5->length, &ret))
117 return NULL;
118 break;
119
120 case GEN_DIRNAME:
121 if (X509_NAME_oneline(gen->d.dirn, oline, sizeof(oline)) == NULL
122 || !X509V3_add_value("DirName", oline, &ret))
123 return NULL;
124 break;
125
126 case GEN_IPADD:
127 p = gen->d.ip->data;
128 if (gen->d.ip->length == 4)
129 BIO_snprintf(oline, sizeof(oline), "%d.%d.%d.%d",
130 p[0], p[1], p[2], p[3]);
131 else if (gen->d.ip->length == 16) {
132 oline[0] = 0;
133 for (i = 0; i < 8; i++) {
134 BIO_snprintf(htmp, sizeof(htmp), "%X", p[0] << 8 | p[1]);
135 p += 2;
136 strcat(oline, htmp);
137 if (i != 7)
138 strcat(oline, ":");
139 }
140 } else {
141 if (!X509V3_add_value("IP Address", "<invalid>", &ret))
142 return NULL;
143 break;
144 }
145 if (!X509V3_add_value("IP Address", oline, &ret))
146 return NULL;
147 break;
148
149 case GEN_RID:
150 i2t_ASN1_OBJECT(oline, 256, gen->d.rid);
151 if (!X509V3_add_value("Registered ID", oline, &ret))
152 return NULL;
153 break;
154 }
155 return ret;
156}
157
158int GENERAL_NAME_print(BIO *out, GENERAL_NAME *gen)
159{
160 unsigned char *p;
161 int i;
162 switch (gen->type) {
163 case GEN_OTHERNAME:
164 BIO_printf(out, "othername:<unsupported>");
165 break;
166
167 case GEN_X400:
168 BIO_printf(out, "X400Name:<unsupported>");
169 break;
170
171 case GEN_EDIPARTY:
172 /* Maybe fix this: it is supported now */
173 BIO_printf(out, "EdiPartyName:<unsupported>");
174 break;
175
176 case GEN_EMAIL:
177 BIO_printf(out, "email:");
178 ASN1_STRING_print(out, gen->d.ia5);
179 break;
180
181 case GEN_DNS:
182 BIO_printf(out, "DNS:");
183 ASN1_STRING_print(out, gen->d.ia5);
184 break;
185
186 case GEN_URI:
187 BIO_printf(out, "URI:");
188 ASN1_STRING_print(out, gen->d.ia5);
189 break;
190
191 case GEN_DIRNAME:
192 BIO_printf(out, "DirName:");
193 X509_NAME_print_ex(out, gen->d.dirn, 0, XN_FLAG_ONELINE);
194 break;
195
196 case GEN_IPADD:
197 p = gen->d.ip->data;
198 if (gen->d.ip->length == 4)
199 BIO_printf(out, "IP Address:%d.%d.%d.%d", p[0], p[1], p[2], p[3]);
200 else if (gen->d.ip->length == 16) {
201 BIO_printf(out, "IP Address");
202 for (i = 0; i < 8; i++) {
203 BIO_printf(out, ":%X", p[0] << 8 | p[1]);
204 p += 2;
205 }
206 BIO_puts(out, "\n");
207 } else {
208 BIO_printf(out, "IP Address:<invalid>");
209 break;
210 }
211 break;
212
213 case GEN_RID:
214 BIO_printf(out, "Registered ID:");
215 i2a_ASN1_OBJECT(out, gen->d.rid);
216 break;
217 }
218 return 1;
219}
220
221static GENERAL_NAMES *v2i_issuer_alt(X509V3_EXT_METHOD *method,
222 X509V3_CTX *ctx,
223 STACK_OF(CONF_VALUE) *nval)
224{
225 const int num = sk_CONF_VALUE_num(nval);
226 GENERAL_NAMES *gens = sk_GENERAL_NAME_new_reserve(NULL, num);
227 int i;
228
229 if (gens == NULL) {
230 X509V3err(X509V3_F_V2I_ISSUER_ALT, ERR_R_MALLOC_FAILURE);
231 sk_GENERAL_NAME_free(gens);
232 return NULL;
233 }
234 for (i = 0; i < num; i++) {
235 CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
236
237 if (!name_cmp(cnf->name, "issuer")
238 && cnf->value && strcmp(cnf->value, "copy") == 0) {
239 if (!copy_issuer(ctx, gens))
240 goto err;
241 } else {
242 GENERAL_NAME *gen = v2i_GENERAL_NAME(method, ctx, cnf);
243
244 if (gen == NULL)
245 goto err;
246 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
247 }
248 }
249 return gens;
250 err:
251 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
252 return NULL;
253}
254
255/* Append subject altname of issuer to issuer alt name of subject */
256
257static int copy_issuer(X509V3_CTX *ctx, GENERAL_NAMES *gens)
258{
259 GENERAL_NAMES *ialt;
260 GENERAL_NAME *gen;
261 X509_EXTENSION *ext;
262 int i, num;
263
264 if (ctx && (ctx->flags == CTX_TEST))
265 return 1;
266 if (!ctx || !ctx->issuer_cert) {
267 X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_NO_ISSUER_DETAILS);
268 goto err;
269 }
270 i = X509_get_ext_by_NID(ctx->issuer_cert, NID_subject_alt_name, -1);
271 if (i < 0)
272 return 1;
273 if ((ext = X509_get_ext(ctx->issuer_cert, i)) == NULL
274 || (ialt = X509V3_EXT_d2i(ext)) == NULL) {
275 X509V3err(X509V3_F_COPY_ISSUER, X509V3_R_ISSUER_DECODE_ERROR);
276 goto err;
277 }
278
279 num = sk_GENERAL_NAME_num(ialt);
280 if (!sk_GENERAL_NAME_reserve(gens, num)) {
281 X509V3err(X509V3_F_COPY_ISSUER, ERR_R_MALLOC_FAILURE);
282 sk_GENERAL_NAME_free(ialt);
283 goto err;
284 }
285
286 for (i = 0; i < num; i++) {
287 gen = sk_GENERAL_NAME_value(ialt, i);
288 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
289 }
290 sk_GENERAL_NAME_free(ialt);
291
292 return 1;
293
294 err:
295 return 0;
296
297}
298
299static GENERAL_NAMES *v2i_subject_alt(X509V3_EXT_METHOD *method,
300 X509V3_CTX *ctx,
301 STACK_OF(CONF_VALUE) *nval)
302{
303 GENERAL_NAMES *gens;
304 CONF_VALUE *cnf;
305 const int num = sk_CONF_VALUE_num(nval);
306 int i;
307
308 gens = sk_GENERAL_NAME_new_reserve(NULL, num);
309 if (gens == NULL) {
310 X509V3err(X509V3_F_V2I_SUBJECT_ALT, ERR_R_MALLOC_FAILURE);
311 sk_GENERAL_NAME_free(gens);
312 return NULL;
313 }
314
315 for (i = 0; i < num; i++) {
316 cnf = sk_CONF_VALUE_value(nval, i);
317 if (!name_cmp(cnf->name, "email")
318 && cnf->value && strcmp(cnf->value, "copy") == 0) {
319 if (!copy_email(ctx, gens, 0))
320 goto err;
321 } else if (!name_cmp(cnf->name, "email")
322 && cnf->value && strcmp(cnf->value, "move") == 0) {
323 if (!copy_email(ctx, gens, 1))
324 goto err;
325 } else {
326 GENERAL_NAME *gen;
327 if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
328 goto err;
329 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
330 }
331 }
332 return gens;
333 err:
334 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
335 return NULL;
336}
337
338/*
339 * Copy any email addresses in a certificate or request to GENERAL_NAMES
340 */
341
342static int copy_email(X509V3_CTX *ctx, GENERAL_NAMES *gens, int move_p)
343{
344 X509_NAME *nm;
345 ASN1_IA5STRING *email = NULL;
346 X509_NAME_ENTRY *ne;
347 GENERAL_NAME *gen = NULL;
348 int i = -1;
349
350 if (ctx != NULL && ctx->flags == CTX_TEST)
351 return 1;
352 if (ctx == NULL
353 || (ctx->subject_cert == NULL && ctx->subject_req == NULL)) {
354 X509V3err(X509V3_F_COPY_EMAIL, X509V3_R_NO_SUBJECT_DETAILS);
355 goto err;
356 }
357 /* Find the subject name */
358 if (ctx->subject_cert)
359 nm = X509_get_subject_name(ctx->subject_cert);
360 else
361 nm = X509_REQ_get_subject_name(ctx->subject_req);
362
363 /* Now add any email address(es) to STACK */
364 while ((i = X509_NAME_get_index_by_NID(nm,
365 NID_pkcs9_emailAddress, i)) >= 0) {
366 ne = X509_NAME_get_entry(nm, i);
367 email = ASN1_STRING_dup(X509_NAME_ENTRY_get_data(ne));
368 if (move_p) {
369 X509_NAME_delete_entry(nm, i);
370 X509_NAME_ENTRY_free(ne);
371 i--;
372 }
373 if (email == NULL || (gen = GENERAL_NAME_new()) == NULL) {
374 X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
375 goto err;
376 }
377 gen->d.ia5 = email;
378 email = NULL;
379 gen->type = GEN_EMAIL;
380 if (!sk_GENERAL_NAME_push(gens, gen)) {
381 X509V3err(X509V3_F_COPY_EMAIL, ERR_R_MALLOC_FAILURE);
382 goto err;
383 }
384 gen = NULL;
385 }
386
387 return 1;
388
389 err:
390 GENERAL_NAME_free(gen);
391 ASN1_IA5STRING_free(email);
392 return 0;
393
394}
395
396GENERAL_NAMES *v2i_GENERAL_NAMES(const X509V3_EXT_METHOD *method,
397 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
398{
399 GENERAL_NAME *gen;
400 GENERAL_NAMES *gens;
401 CONF_VALUE *cnf;
402 const int num = sk_CONF_VALUE_num(nval);
403 int i;
404
405 gens = sk_GENERAL_NAME_new_reserve(NULL, num);
406 if (gens == NULL) {
407 X509V3err(X509V3_F_V2I_GENERAL_NAMES, ERR_R_MALLOC_FAILURE);
408 sk_GENERAL_NAME_free(gens);
409 return NULL;
410 }
411
412 for (i = 0; i < num; i++) {
413 cnf = sk_CONF_VALUE_value(nval, i);
414 if ((gen = v2i_GENERAL_NAME(method, ctx, cnf)) == NULL)
415 goto err;
416 sk_GENERAL_NAME_push(gens, gen); /* no failure as it was reserved */
417 }
418 return gens;
419 err:
420 sk_GENERAL_NAME_pop_free(gens, GENERAL_NAME_free);
421 return NULL;
422}
423
424GENERAL_NAME *v2i_GENERAL_NAME(const X509V3_EXT_METHOD *method,
425 X509V3_CTX *ctx, CONF_VALUE *cnf)
426{
427 return v2i_GENERAL_NAME_ex(NULL, method, ctx, cnf, 0);
428}
429
430GENERAL_NAME *a2i_GENERAL_NAME(GENERAL_NAME *out,
431 const X509V3_EXT_METHOD *method,
432 X509V3_CTX *ctx, int gen_type, const char *value,
433 int is_nc)
434{
435 char is_string = 0;
436 GENERAL_NAME *gen = NULL;
437
438 if (!value) {
439 X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_MISSING_VALUE);
440 return NULL;
441 }
442
443 if (out)
444 gen = out;
445 else {
446 gen = GENERAL_NAME_new();
447 if (gen == NULL) {
448 X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
449 return NULL;
450 }
451 }
452
453 switch (gen_type) {
454 case GEN_URI:
455 case GEN_EMAIL:
456 case GEN_DNS:
457 is_string = 1;
458 break;
459
460 case GEN_RID:
461 {
462 ASN1_OBJECT *obj;
463 if ((obj = OBJ_txt2obj(value, 0)) == NULL) {
464 X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_OBJECT);
465 ERR_add_error_data(2, "value=", value);
466 goto err;
467 }
468 gen->d.rid = obj;
469 }
470 break;
471
472 case GEN_IPADD:
473 if (is_nc)
474 gen->d.ip = a2i_IPADDRESS_NC(value);
475 else
476 gen->d.ip = a2i_IPADDRESS(value);
477 if (gen->d.ip == NULL) {
478 X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_BAD_IP_ADDRESS);
479 ERR_add_error_data(2, "value=", value);
480 goto err;
481 }
482 break;
483
484 case GEN_DIRNAME:
485 if (!do_dirname(gen, value, ctx)) {
486 X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_DIRNAME_ERROR);
487 goto err;
488 }
489 break;
490
491 case GEN_OTHERNAME:
492 if (!do_othername(gen, value, ctx)) {
493 X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_OTHERNAME_ERROR);
494 goto err;
495 }
496 break;
497 default:
498 X509V3err(X509V3_F_A2I_GENERAL_NAME, X509V3_R_UNSUPPORTED_TYPE);
499 goto err;
500 }
501
502 if (is_string) {
503 if ((gen->d.ia5 = ASN1_IA5STRING_new()) == NULL ||
504 !ASN1_STRING_set(gen->d.ia5, (unsigned char *)value,
505 strlen(value))) {
506 X509V3err(X509V3_F_A2I_GENERAL_NAME, ERR_R_MALLOC_FAILURE);
507 goto err;
508 }
509 }
510
511 gen->type = gen_type;
512
513 return gen;
514
515 err:
516 if (!out)
517 GENERAL_NAME_free(gen);
518 return NULL;
519}
520
521GENERAL_NAME *v2i_GENERAL_NAME_ex(GENERAL_NAME *out,
522 const X509V3_EXT_METHOD *method,
523 X509V3_CTX *ctx, CONF_VALUE *cnf, int is_nc)
524{
525 int type;
526
527 char *name, *value;
528
529 name = cnf->name;
530 value = cnf->value;
531
532 if (!value) {
533 X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_MISSING_VALUE);
534 return NULL;
535 }
536
537 if (!name_cmp(name, "email"))
538 type = GEN_EMAIL;
539 else if (!name_cmp(name, "URI"))
540 type = GEN_URI;
541 else if (!name_cmp(name, "DNS"))
542 type = GEN_DNS;
543 else if (!name_cmp(name, "RID"))
544 type = GEN_RID;
545 else if (!name_cmp(name, "IP"))
546 type = GEN_IPADD;
547 else if (!name_cmp(name, "dirName"))
548 type = GEN_DIRNAME;
549 else if (!name_cmp(name, "otherName"))
550 type = GEN_OTHERNAME;
551 else {
552 X509V3err(X509V3_F_V2I_GENERAL_NAME_EX, X509V3_R_UNSUPPORTED_OPTION);
553 ERR_add_error_data(2, "name=", name);
554 return NULL;
555 }
556
557 return a2i_GENERAL_NAME(out, method, ctx, type, value, is_nc);
558
559}
560
561static int do_othername(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
562{
563 char *objtmp = NULL, *p;
564 int objlen;
565
566 if ((p = strchr(value, ';')) == NULL)
567 return 0;
568 if ((gen->d.otherName = OTHERNAME_new()) == NULL)
569 return 0;
570 /*
571 * Free this up because we will overwrite it. no need to free type_id
572 * because it is static
573 */
574 ASN1_TYPE_free(gen->d.otherName->value);
575 if ((gen->d.otherName->value = ASN1_generate_v3(p + 1, ctx)) == NULL)
576 return 0;
577 objlen = p - value;
578 objtmp = OPENSSL_strndup(value, objlen);
579 if (objtmp == NULL)
580 return 0;
581 gen->d.otherName->type_id = OBJ_txt2obj(objtmp, 0);
582 OPENSSL_free(objtmp);
583 if (!gen->d.otherName->type_id)
584 return 0;
585 return 1;
586}
587
588static int do_dirname(GENERAL_NAME *gen, const char *value, X509V3_CTX *ctx)
589{
590 int ret = 0;
591 STACK_OF(CONF_VALUE) *sk = NULL;
592 X509_NAME *nm;
593
594 if ((nm = X509_NAME_new()) == NULL)
595 goto err;
596 sk = X509V3_get_section(ctx, value);
597 if (!sk) {
598 X509V3err(X509V3_F_DO_DIRNAME, X509V3_R_SECTION_NOT_FOUND);
599 ERR_add_error_data(2, "section=", value);
600 goto err;
601 }
602 /* FIXME: should allow other character types... */
603 ret = X509V3_NAME_from_section(nm, sk, MBSTRING_ASC);
604 if (!ret)
605 goto err;
606 gen->d.dirn = nm;
607
608err:
609 if (ret == 0)
610 X509_NAME_free(nm);
611 X509V3_section_free(ctx, sk);
612 return ret;
613}
Note: See TracBrowser for help on using the repository browser.

© 2024 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette