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