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