• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 <string.h>
12 
13 #include <openssl/asn1.h>
14 #include <openssl/asn1t.h>
15 #include <openssl/conf.h>
16 #include <openssl/err.h>
17 #include <openssl/mem.h>
18 #include <openssl/obj.h>
19 #include <openssl/x509.h>
20 
21 #include "ext_dat.h"
22 #include "internal.h"
23 
24 
25 static void *v2i_crld(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx,
26                       const STACK_OF(CONF_VALUE) *nval);
27 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
28                      int indent);
29 
30 const X509V3_EXT_METHOD v3_crld = {
31     NID_crl_distribution_points,
32     0,
33     ASN1_ITEM_ref(CRL_DIST_POINTS),
34     0,
35     0,
36     0,
37     0,
38     0,
39     0,
40     0,
41     v2i_crld,
42     i2r_crldp,
43     0,
44     NULL,
45 };
46 
47 const X509V3_EXT_METHOD v3_freshest_crl = {
48     NID_freshest_crl,
49     0,
50     ASN1_ITEM_ref(CRL_DIST_POINTS),
51     0,
52     0,
53     0,
54     0,
55     0,
56     0,
57     0,
58     v2i_crld,
59     i2r_crldp,
60     0,
61     NULL,
62 };
63 
STACK_OF(GENERAL_NAME)64 static STACK_OF(GENERAL_NAME) *gnames_from_sectname(const X509V3_CTX *ctx,
65                                                     char *sect) {
66   const STACK_OF(CONF_VALUE) *gnsect;
67   STACK_OF(CONF_VALUE) *gnsect_owned = NULL;
68   if (*sect == '@') {
69     gnsect = X509V3_get_section(ctx, sect + 1);
70   } else {
71     gnsect_owned = X509V3_parse_list(sect);
72     gnsect = gnsect_owned;
73   }
74   if (!gnsect) {
75     OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
76     return NULL;
77   }
78   STACK_OF(GENERAL_NAME) *gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
79   sk_CONF_VALUE_pop_free(gnsect_owned, X509V3_conf_free);
80   return gens;
81 }
82 
83 // set_dist_point_name decodes a DistributionPointName from |cnf| and writes the
84 // result in |*pdp|. It returns 1 on success, -1 on error, and 0 if |cnf| used
85 // an unrecognized input type. The zero return can be used by callers to support
86 // additional syntax.
set_dist_point_name(DIST_POINT_NAME ** pdp,const X509V3_CTX * ctx,const CONF_VALUE * cnf)87 static int set_dist_point_name(DIST_POINT_NAME **pdp, const X509V3_CTX *ctx,
88                                const CONF_VALUE *cnf) {
89   STACK_OF(GENERAL_NAME) *fnm = NULL;
90   STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
91   if (!strncmp(cnf->name, "fullname", 9)) {
92     // If |cnf| comes from |X509V3_parse_list|, which is possible for a v2i
93     // function, |cnf->value| may be NULL.
94     if (cnf->value == NULL) {
95       OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
96       return -1;
97     }
98     fnm = gnames_from_sectname(ctx, cnf->value);
99     if (!fnm) {
100       goto err;
101     }
102   } else if (!strcmp(cnf->name, "relativename")) {
103     // If |cnf| comes from |X509V3_parse_list|, which is possible for a v2i
104     // function, |cnf->value| may be NULL.
105     if (cnf->value == NULL) {
106       OPENSSL_PUT_ERROR(X509V3, X509V3_R_MISSING_VALUE);
107       return -1;
108     }
109     const STACK_OF(CONF_VALUE) *dnsect = X509V3_get_section(ctx, cnf->value);
110     if (!dnsect) {
111       OPENSSL_PUT_ERROR(X509V3, X509V3_R_SECTION_NOT_FOUND);
112       return -1;
113     }
114     X509_NAME *nm = X509_NAME_new();
115     if (!nm) {
116       return -1;
117     }
118     int ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
119     rnm = nm->entries;
120     nm->entries = NULL;
121     X509_NAME_free(nm);
122     if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0) {
123       goto err;
124     }
125     // There can only be one RDN in nameRelativeToCRLIssuer.
126     if (sk_X509_NAME_ENTRY_value(rnm, sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
127       OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_MULTIPLE_RDNS);
128       goto err;
129     }
130   } else {
131     return 0;
132   }
133 
134   if (*pdp) {
135     OPENSSL_PUT_ERROR(X509V3, X509V3_R_DISTPOINT_ALREADY_SET);
136     goto err;
137   }
138 
139   *pdp = DIST_POINT_NAME_new();
140   if (!*pdp) {
141     goto err;
142   }
143   if (fnm) {
144     (*pdp)->type = 0;
145     (*pdp)->name.fullname = fnm;
146   } else {
147     (*pdp)->type = 1;
148     (*pdp)->name.relativename = rnm;
149   }
150 
151   return 1;
152 
153 err:
154   sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
155   sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
156   return -1;
157 }
158 
159 static const BIT_STRING_BITNAME reason_flags[] = {
160     {0, "Unused", "unused"},
161     {1, "Key Compromise", "keyCompromise"},
162     {2, "CA Compromise", "CACompromise"},
163     {3, "Affiliation Changed", "affiliationChanged"},
164     {4, "Superseded", "superseded"},
165     {5, "Cessation Of Operation", "cessationOfOperation"},
166     {6, "Certificate Hold", "certificateHold"},
167     {7, "Privilege Withdrawn", "privilegeWithdrawn"},
168     {8, "AA Compromise", "AACompromise"},
169     {-1, NULL, NULL}};
170 
set_reasons(ASN1_BIT_STRING ** preas,const char * value)171 static int set_reasons(ASN1_BIT_STRING **preas, const char *value) {
172   if (*preas) {
173     // Duplicate "reasons" or "onlysomereasons" key.
174     OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_VALUE);
175     return 0;
176   }
177   int ret = 0;
178   STACK_OF(CONF_VALUE) *rsk = X509V3_parse_list(value);
179   if (!rsk) {
180     return 0;
181   }
182   for (size_t i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
183     const char *bnam = sk_CONF_VALUE_value(rsk, i)->name;
184     if (!*preas) {
185       *preas = ASN1_BIT_STRING_new();
186       if (!*preas) {
187         goto err;
188       }
189     }
190     const BIT_STRING_BITNAME *pbn;
191     for (pbn = reason_flags; pbn->lname; pbn++) {
192       if (!strcmp(pbn->sname, bnam)) {
193         if (!ASN1_BIT_STRING_set_bit(*preas, pbn->bitnum, 1)) {
194           goto err;
195         }
196         break;
197       }
198     }
199     if (!pbn->lname) {
200       goto err;
201     }
202   }
203   ret = 1;
204 
205 err:
206   sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
207   return ret;
208 }
209 
print_reasons(BIO * out,const char * rname,ASN1_BIT_STRING * rflags,int indent)210 static int print_reasons(BIO *out, const char *rname, ASN1_BIT_STRING *rflags,
211                          int indent) {
212   int first = 1;
213   const BIT_STRING_BITNAME *pbn;
214   BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
215   for (pbn = reason_flags; pbn->lname; pbn++) {
216     if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
217       if (first) {
218         first = 0;
219       } else {
220         BIO_puts(out, ", ");
221       }
222       BIO_puts(out, pbn->lname);
223     }
224   }
225   if (first) {
226     BIO_puts(out, "<EMPTY>\n");
227   } else {
228     BIO_puts(out, "\n");
229   }
230   return 1;
231 }
232 
crldp_from_section(const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)233 static DIST_POINT *crldp_from_section(const X509V3_CTX *ctx,
234                                       const STACK_OF(CONF_VALUE) *nval) {
235   DIST_POINT *point = NULL;
236   point = DIST_POINT_new();
237   if (!point) {
238     goto err;
239   }
240   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
241     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
242     int ret = set_dist_point_name(&point->distpoint, ctx, cnf);
243     if (ret > 0) {
244       continue;
245     }
246     if (ret < 0) {
247       goto err;
248     }
249     if (!strcmp(cnf->name, "reasons")) {
250       if (!set_reasons(&point->reasons, cnf->value)) {
251         goto err;
252       }
253     } else if (!strcmp(cnf->name, "CRLissuer")) {
254       GENERAL_NAMES_free(point->CRLissuer);
255       point->CRLissuer = gnames_from_sectname(ctx, cnf->value);
256       if (!point->CRLissuer) {
257         goto err;
258       }
259     }
260   }
261 
262   return point;
263 
264 err:
265   DIST_POINT_free(point);
266   return NULL;
267 }
268 
v2i_crld(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)269 static void *v2i_crld(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx,
270                       const STACK_OF(CONF_VALUE) *nval) {
271   STACK_OF(DIST_POINT) *crld = NULL;
272   GENERAL_NAMES *gens = NULL;
273   GENERAL_NAME *gen = NULL;
274   if (!(crld = sk_DIST_POINT_new_null())) {
275     goto err;
276   }
277   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
278     DIST_POINT *point;
279     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
280     if (!cnf->value) {
281       const STACK_OF(CONF_VALUE) *dpsect = X509V3_get_section(ctx, cnf->name);
282       if (!dpsect) {
283         goto err;
284       }
285       point = crldp_from_section(ctx, dpsect);
286       if (!point) {
287         goto err;
288       }
289       if (!sk_DIST_POINT_push(crld, point)) {
290         DIST_POINT_free(point);
291         goto err;
292       }
293     } else {
294       if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf))) {
295         goto err;
296       }
297       if (!(gens = GENERAL_NAMES_new())) {
298         goto err;
299       }
300       if (!sk_GENERAL_NAME_push(gens, gen)) {
301         goto err;
302       }
303       gen = NULL;
304       if (!(point = DIST_POINT_new())) {
305         goto err;
306       }
307       if (!sk_DIST_POINT_push(crld, point)) {
308         DIST_POINT_free(point);
309         goto err;
310       }
311       if (!(point->distpoint = DIST_POINT_NAME_new())) {
312         goto err;
313       }
314       point->distpoint->name.fullname = gens;
315       point->distpoint->type = 0;
316       gens = NULL;
317     }
318   }
319   return crld;
320 
321 err:
322   GENERAL_NAME_free(gen);
323   GENERAL_NAMES_free(gens);
324   sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
325   return NULL;
326 }
327 
dpn_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)328 static int dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it,
329                   void *exarg) {
330   DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
331 
332   switch (operation) {
333     case ASN1_OP_NEW_POST:
334       dpn->dpname = NULL;
335       break;
336 
337     case ASN1_OP_FREE_POST:
338       X509_NAME_free(dpn->dpname);
339       break;
340   }
341   return 1;
342 }
343 
344 
345 ASN1_CHOICE_cb(DIST_POINT_NAME, dpn_cb) = {
346     ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
347     ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1),
348 } ASN1_CHOICE_END_cb(DIST_POINT_NAME, DIST_POINT_NAME, type)
349 
350 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(DIST_POINT_NAME)
351 
352 ASN1_SEQUENCE(DIST_POINT) = {
353     ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
354     ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
355     ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2),
356 } ASN1_SEQUENCE_END(DIST_POINT)
357 
358 IMPLEMENT_ASN1_ALLOC_FUNCTIONS(DIST_POINT)
359 
360 ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) = ASN1_EX_TEMPLATE_TYPE(
361     ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
362 ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
363 
364 IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
365 
366 ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
367     ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
368     ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
369     ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
370     ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
371     ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
372     ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5),
373 } ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
374 
375 IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
376 
377 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
378                    int indent);
379 static void *v2i_idp(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx,
380                      const STACK_OF(CONF_VALUE) *nval);
381 
382 const X509V3_EXT_METHOD v3_idp = {
383     NID_issuing_distribution_point,
384     X509V3_EXT_MULTILINE,
385     ASN1_ITEM_ref(ISSUING_DIST_POINT),
386     0,
387     0,
388     0,
389     0,
390     0,
391     0,
392     0,
393     v2i_idp,
394     i2r_idp,
395     0,
396     NULL,
397 };
398 
v2i_idp(const X509V3_EXT_METHOD * method,const X509V3_CTX * ctx,const STACK_OF (CONF_VALUE)* nval)399 static void *v2i_idp(const X509V3_EXT_METHOD *method, const X509V3_CTX *ctx,
400                      const STACK_OF(CONF_VALUE) *nval) {
401   ISSUING_DIST_POINT *idp = ISSUING_DIST_POINT_new();
402   if (!idp) {
403     goto err;
404   }
405   for (size_t i = 0; i < sk_CONF_VALUE_num(nval); i++) {
406     const CONF_VALUE *cnf = sk_CONF_VALUE_value(nval, i);
407     const char *name = cnf->name;
408     const char *val = cnf->value;
409     int ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
410     if (ret > 0) {
411       continue;
412     }
413     if (ret < 0) {
414       goto err;
415     }
416     if (!strcmp(name, "onlyuser")) {
417       if (!X509V3_get_value_bool(cnf, &idp->onlyuser)) {
418         goto err;
419       }
420     } else if (!strcmp(name, "onlyCA")) {
421       if (!X509V3_get_value_bool(cnf, &idp->onlyCA)) {
422         goto err;
423       }
424     } else if (!strcmp(name, "onlyAA")) {
425       if (!X509V3_get_value_bool(cnf, &idp->onlyattr)) {
426         goto err;
427       }
428     } else if (!strcmp(name, "indirectCRL")) {
429       if (!X509V3_get_value_bool(cnf, &idp->indirectCRL)) {
430         goto err;
431       }
432     } else if (!strcmp(name, "onlysomereasons")) {
433       if (!set_reasons(&idp->onlysomereasons, val)) {
434         goto err;
435       }
436     } else {
437       OPENSSL_PUT_ERROR(X509V3, X509V3_R_INVALID_NAME);
438       X509V3_conf_err(cnf);
439       goto err;
440     }
441   }
442   return idp;
443 
444 err:
445   ISSUING_DIST_POINT_free(idp);
446   return NULL;
447 }
448 
print_gens(BIO * out,STACK_OF (GENERAL_NAME)* gens,int indent)449 static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent) {
450   size_t i;
451   for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
452     BIO_printf(out, "%*s", indent + 2, "");
453     GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
454     BIO_puts(out, "\n");
455   }
456   return 1;
457 }
458 
print_distpoint(BIO * out,DIST_POINT_NAME * dpn,int indent)459 static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent) {
460   if (dpn->type == 0) {
461     BIO_printf(out, "%*sFull Name:\n", indent, "");
462     print_gens(out, dpn->name.fullname, indent);
463   } else {
464     X509_NAME ntmp;
465     ntmp.entries = dpn->name.relativename;
466     BIO_printf(out, "%*sRelative Name:\n%*s", indent, "", indent + 2, "");
467     X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
468     BIO_puts(out, "\n");
469   }
470   return 1;
471 }
472 
i2r_idp(const X509V3_EXT_METHOD * method,void * pidp,BIO * out,int indent)473 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
474                    int indent) {
475   ISSUING_DIST_POINT *idp = reinterpret_cast<ISSUING_DIST_POINT *>(pidp);
476   if (idp->distpoint) {
477     print_distpoint(out, idp->distpoint, indent);
478   }
479   if (idp->onlyuser > 0) {
480     BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
481   }
482   if (idp->onlyCA > 0) {
483     BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
484   }
485   if (idp->indirectCRL > 0) {
486     BIO_printf(out, "%*sIndirect CRL\n", indent, "");
487   }
488   if (idp->onlysomereasons) {
489     print_reasons(out, "Only Some Reasons", idp->onlysomereasons, indent);
490   }
491   if (idp->onlyattr > 0) {
492     BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
493   }
494   if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) &&
495       (idp->indirectCRL <= 0) && !idp->onlysomereasons &&
496       (idp->onlyattr <= 0)) {
497     BIO_printf(out, "%*s<EMPTY>\n", indent, "");
498   }
499 
500   return 1;
501 }
502 
i2r_crldp(const X509V3_EXT_METHOD * method,void * pcrldp,BIO * out,int indent)503 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
504                      int indent) {
505   STACK_OF(DIST_POINT) *crld = reinterpret_cast<STACK_OF(DIST_POINT) *>(pcrldp);
506   DIST_POINT *point;
507   size_t i;
508   for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
509     BIO_puts(out, "\n");
510     point = sk_DIST_POINT_value(crld, i);
511     if (point->distpoint) {
512       print_distpoint(out, point->distpoint, indent);
513     }
514     if (point->reasons) {
515       print_reasons(out, "Reasons", point->reasons, indent);
516     }
517     if (point->CRLissuer) {
518       BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
519       print_gens(out, point->CRLissuer, indent);
520     }
521   }
522   return 1;
523 }
524 
DIST_POINT_set_dpname(DIST_POINT_NAME * dpn,X509_NAME * iname)525 int DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname) {
526   size_t i;
527   STACK_OF(X509_NAME_ENTRY) *frag;
528   X509_NAME_ENTRY *ne;
529   if (!dpn || (dpn->type != 1)) {
530     return 1;
531   }
532   frag = dpn->name.relativename;
533   dpn->dpname = X509_NAME_dup(iname);
534   if (!dpn->dpname) {
535     return 0;
536   }
537   for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
538     ne = sk_X509_NAME_ENTRY_value(frag, i);
539     if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
540       X509_NAME_free(dpn->dpname);
541       dpn->dpname = NULL;
542       return 0;
543     }
544   }
545   // generate cached encoding of name
546   if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
547     X509_NAME_free(dpn->dpname);
548     dpn->dpname = NULL;
549     return 0;
550   }
551   return 1;
552 }
553