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