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