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