]> git.ipfire.org Git - thirdparty/openssl.git/blame - crypto/x509v3/v3_crld.c
Make explicit_policy handling match expected RFC3280 behaviour.
[thirdparty/openssl.git] / crypto / x509v3 / v3_crld.c
CommitLineData
d943e372
DSH
1/* v3_crld.c */
2/* Written by Dr Stephen N Henson (shenson@bigfoot.com) for the OpenSSL
3 * project 1999.
4 */
5/* ====================================================================
231493c9 6 * Copyright (c) 1999, 2005 The OpenSSL Project. All rights reserved.
d943e372
DSH
7 *
8 * Redistribution and use in source and binary forms, with or without
9 * modification, are permitted provided that the following conditions
10 * are met:
11 *
12 * 1. Redistributions of source code must retain the above copyright
13 * notice, this list of conditions and the following disclaimer.
14 *
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 *
20 * 3. All advertising materials mentioning features or use of this
21 * software must display the following acknowledgment:
22 * "This product includes software developed by the OpenSSL Project
23 * for use in the OpenSSL Toolkit. (http://www.OpenSSL.org/)"
24 *
25 * 4. The names "OpenSSL Toolkit" and "OpenSSL Project" must not be used to
26 * endorse or promote products derived from this software without
27 * prior written permission. For written permission, please contact
28 * licensing@OpenSSL.org.
29 *
30 * 5. Products derived from this software may not be called "OpenSSL"
31 * nor may "OpenSSL" appear in their names without prior written
32 * permission of the OpenSSL Project.
33 *
34 * 6. Redistributions of any form whatsoever must retain the following
35 * acknowledgment:
36 * "This product includes software developed by the OpenSSL Project
37 * for use in the OpenSSL Toolkit (http://www.OpenSSL.org/)"
38 *
39 * THIS SOFTWARE IS PROVIDED BY THE OpenSSL PROJECT ``AS IS'' AND ANY
40 * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
41 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
42 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE OpenSSL PROJECT OR
43 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
45 * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
46 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
47 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
48 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
49 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
50 * OF THE POSSIBILITY OF SUCH DAMAGE.
51 * ====================================================================
52 *
53 * This product includes cryptographic software written by Eric Young
54 * (eay@cryptsoft.com). This product includes software written by Tim
55 * Hudson (tjh@cryptsoft.com).
56 *
57 */
58
59#include <stdio.h>
60#include "cryptlib.h"
ec577822
BM
61#include <openssl/conf.h>
62#include <openssl/asn1.h>
9d6b1ce6 63#include <openssl/asn1t.h>
ec577822 64#include <openssl/x509v3.h>
d943e372 65
0745d089 66static void *v2i_crld(X509V3_EXT_METHOD *method,
ba404b5e 67 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
9aa9d70d
DSH
68static int i2r_crldp(X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
69 int indent);
d943e372 70
560b79cb 71const X509V3_EXT_METHOD v3_crld =
0745d089
DSH
72 {
73 NID_crl_distribution_points, 0, ASN1_ITEM_ref(CRL_DIST_POINTS),
74 0,0,0,0,
75 0,0,
76 0,
77 v2i_crld,
78 i2r_crldp,0,
79 NULL
80 };
81
82static STACK_OF(GENERAL_NAME) *gnames_from_sectname(X509V3_CTX *ctx, char *sect)
83 {
84 STACK_OF(CONF_VALUE) *gnsect;
85 STACK_OF(GENERAL_NAME) *gens;
86 if (*sect == '@')
87 gnsect = X509V3_get_section(ctx, sect + 1);
88 else
89 gnsect = X509V3_parse_list(sect);
90 if (!gnsect)
91 {
92 X509V3err(X509V3_F_GNAMES_FROM_SECTNAME,
93 X509V3_R_SECTION_NOT_FOUND);
94 return NULL;
95 }
96 gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
97 if (*sect == '@')
98 X509V3_section_free(ctx, gnsect);
99 else
100 sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
101 return gens;
102 }
103
0537f968 104static int set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx,
0745d089
DSH
105 CONF_VALUE *cnf)
106 {
107 STACK_OF(GENERAL_NAME) *fnm = NULL;
108 STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
109 if (!strncmp(cnf->name, "fullname", 9))
110 {
111 fnm = gnames_from_sectname(ctx, cnf->value);
112 if (!fnm)
113 goto err;
114 }
115 else if (!strcmp(cnf->name, "relativename"))
116 {
117 int ret;
118 STACK_OF(CONF_VALUE) *dnsect;
119 X509_NAME *nm;
120 nm = X509_NAME_new();
121 if (!nm)
122 return -1;
123 dnsect = X509V3_get_section(ctx, cnf->value);
124 if (!dnsect)
125 {
0537f968 126 X509V3err(X509V3_F_SET_DIST_POINT_NAME,
0745d089
DSH
127 X509V3_R_SECTION_NOT_FOUND);
128 return -1;
129 }
130 ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
131 X509V3_section_free(ctx, dnsect);
132 rnm = nm->entries;
133 nm->entries = NULL;
134 X509_NAME_free(nm);
135 if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
136 goto err;
137 /* Since its a name fragment can't have more than one
138 * RDNSequence
139 */
140 if (sk_X509_NAME_ENTRY_value(rnm,
141 sk_X509_NAME_ENTRY_num(rnm) - 1)->set)
142 {
0537f968 143 X509V3err(X509V3_F_SET_DIST_POINT_NAME,
0745d089
DSH
144 X509V3_R_INVAID_MULTIPLE_RDNS);
145 goto err;
146 }
147 }
148 else
149 return 0;
150
151 if (*pdp)
152 {
0537f968 153 X509V3err(X509V3_F_SET_DIST_POINT_NAME,
0745d089
DSH
154 X509V3_R_DISTPOINT_ALREADY_SET);
155 goto err;
156 }
157
158 *pdp = DIST_POINT_NAME_new();
159 if (!*pdp)
160 goto err;
161 if (fnm)
162 {
163 (*pdp)->type = 0;
164 (*pdp)->name.fullname = fnm;
165 }
166 else
167 {
168 (*pdp)->type = 1;
169 (*pdp)->name.relativename = rnm;
170 }
171
172 return 1;
173
174 err:
175 if (fnm)
176 sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
177 if (rnm)
178 sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
179 return -1;
180 }
181
0745d089
DSH
182static const BIT_STRING_BITNAME reason_flags[] = {
183{1, "Key Compromise", "keyCompromise"},
184{2, "CA Compromise", "CACompromise"},
185{3, "Affiliation Changed", "affiliationChanged"},
186{4, "Superseded", "superseded"},
187{5, "Cessation Of Operation", "cessationOfOperation"},
188{6, "Certificate Hold", "certificateHold"},
189{7, "Privilege Withdrawn", "privilegeWithdrawn"},
190{8, "AA Compromise", "AACompromise"},
191{-1, NULL, NULL}
d943e372
DSH
192};
193
0745d089
DSH
194static int set_reasons(ASN1_BIT_STRING **preas, char *value)
195 {
196 STACK_OF(CONF_VALUE) *rsk = NULL;
197 const BIT_STRING_BITNAME *pbn;
198 const char *bnam;
199 int i, ret = 0;
200 rsk = X509V3_parse_list(value);
201 if (!rsk)
202 return 0;
203 if (*preas)
204 return 0;
205 for (i = 0; i < sk_CONF_VALUE_num(rsk); i++)
206 {
207 bnam = sk_CONF_VALUE_value(rsk, i)->name;
208 if (!*preas)
209 {
210 *preas = ASN1_BIT_STRING_new();
211 if (!*preas)
212 goto err;
213 }
214 for (pbn = reason_flags; pbn->lname; pbn++)
215 {
216 if (!strcmp(pbn->sname, bnam))
217 {
218 if (!ASN1_BIT_STRING_set_bit(*preas,
219 pbn->bitnum, 1))
220 goto err;
221 break;
222 }
223 }
224 if (!pbn->lname)
225 goto err;
226 }
227 ret = 1;
228
229 err:
230 sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
231 return ret;
232 }
233
234static int print_reasons(BIO *out, const char *rname,
235 ASN1_BIT_STRING *rflags, int indent)
236 {
237 int first = 1;
238 const BIT_STRING_BITNAME *pbn;
239 BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
240 for (pbn = reason_flags; pbn->lname; pbn++)
241 {
242 if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum))
243 {
244 if (first)
245 first = 0;
246 else
247 BIO_puts(out, ", ");
248 BIO_puts(out, pbn->lname);
249 }
250 }
251 if (first)
252 BIO_puts(out, "<EMPTY>\n");
253 else
254 BIO_puts(out, "\n");
255 return 1;
256 }
257
258static DIST_POINT *crldp_from_section(X509V3_CTX *ctx,
259 STACK_OF(CONF_VALUE) *nval)
260 {
261 int i;
262 CONF_VALUE *cnf;
263 DIST_POINT *point = NULL;
264 point = DIST_POINT_new();
265 if (!point)
266 goto err;
267 for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
268 {
269 int ret;
270 cnf = sk_CONF_VALUE_value(nval, i);
0537f968 271 ret = set_dist_point_name(&point->distpoint, ctx, cnf);
0745d089
DSH
272 if (ret > 0)
273 continue;
274 if (ret < 0)
275 goto err;
276 if (!strcmp(cnf->name, "reasons"))
277 {
278 if (!set_reasons(&point->reasons, cnf->value))
279 goto err;
280 }
281 else if (!strcmp(cnf->name, "CRLissuer"))
282 {
283 point->CRLissuer =
284 gnames_from_sectname(ctx, cnf->value);
285 if (!point->CRLissuer)
286 goto err;
287 }
288 }
289
290 return point;
291
292
293 err:
294 if (point)
295 DIST_POINT_free(point);
296 return NULL;
297 }
298
299static void *v2i_crld(X509V3_EXT_METHOD *method,
ba404b5e 300 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
0745d089 301 {
d943e372 302 STACK_OF(DIST_POINT) *crld = NULL;
9d6b1ce6 303 GENERAL_NAMES *gens = NULL;
d943e372
DSH
304 GENERAL_NAME *gen = NULL;
305 CONF_VALUE *cnf;
306 int i;
62324627 307 if(!(crld = sk_DIST_POINT_new_null())) goto merr;
ba404b5e 308 for(i = 0; i < sk_CONF_VALUE_num(nval); i++) {
d943e372 309 DIST_POINT *point;
ba404b5e 310 cnf = sk_CONF_VALUE_value(nval, i);
0c010a15 311 if (!cnf->value)
0745d089
DSH
312 {
313 STACK_OF(CONF_VALUE) *dpsect;
0c010a15 314 dpsect = X509V3_get_section(ctx, cnf->name);
0745d089
DSH
315 if (!dpsect)
316 goto err;
317 point = crldp_from_section(ctx, dpsect);
318 X509V3_section_free(ctx, dpsect);
319 if (!point)
320 goto err;
321 if(!sk_DIST_POINT_push(crld, point))
322 {
323 DIST_POINT_free(point);
324 goto merr;
325 }
326 }
327 else
328 {
329 if(!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
330 goto err;
331 if(!(gens = GENERAL_NAMES_new()))
332 goto merr;
333 if(!sk_GENERAL_NAME_push(gens, gen))
334 goto merr;
335 gen = NULL;
336 if(!(point = DIST_POINT_new()))
337 goto merr;
338 if(!sk_DIST_POINT_push(crld, point))
339 {
340 DIST_POINT_free(point);
341 goto merr;
342 }
343 if(!(point->distpoint = DIST_POINT_NAME_new()))
344 goto merr;
345 point->distpoint->name.fullname = gens;
346 point->distpoint->type = 0;
347 gens = NULL;
348 }
d943e372
DSH
349 }
350 return crld;
351
352 merr:
353 X509V3err(X509V3_F_V2I_CRLD,ERR_R_MALLOC_FAILURE);
354 err:
355 GENERAL_NAME_free(gen);
356 GENERAL_NAMES_free(gens);
357 sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
358 return NULL;
359}
360
d943e372
DSH
361IMPLEMENT_STACK_OF(DIST_POINT)
362IMPLEMENT_ASN1_SET_OF(DIST_POINT)
363
d943e372 364
9d6b1ce6
DSH
365ASN1_CHOICE(DIST_POINT_NAME) = {
366 ASN1_IMP_SEQUENCE_OF(DIST_POINT_NAME, name.fullname, GENERAL_NAME, 0),
367 ASN1_IMP_SET_OF(DIST_POINT_NAME, name.relativename, X509_NAME_ENTRY, 1)
d339187b 368} ASN1_CHOICE_END(DIST_POINT_NAME)
d943e372 369
9d6b1ce6 370IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT_NAME)
d943e372 371
9d6b1ce6
DSH
372ASN1_SEQUENCE(DIST_POINT) = {
373 ASN1_EXP_OPT(DIST_POINT, distpoint, DIST_POINT_NAME, 0),
374 ASN1_IMP_OPT(DIST_POINT, reasons, ASN1_BIT_STRING, 1),
bf0d176e 375 ASN1_IMP_SEQUENCE_OF_OPT(DIST_POINT, CRLissuer, GENERAL_NAME, 2)
d339187b 376} ASN1_SEQUENCE_END(DIST_POINT)
d943e372 377
9d6b1ce6 378IMPLEMENT_ASN1_FUNCTIONS(DIST_POINT)
d943e372 379
9d6b1ce6 380ASN1_ITEM_TEMPLATE(CRL_DIST_POINTS) =
a8287a90 381 ASN1_EX_TEMPLATE_TYPE(ASN1_TFLG_SEQUENCE_OF, 0, CRLDistributionPoints, DIST_POINT)
d339187b 382ASN1_ITEM_TEMPLATE_END(CRL_DIST_POINTS)
d943e372 383
9d6b1ce6 384IMPLEMENT_ASN1_FUNCTIONS(CRL_DIST_POINTS)
231493c9
DSH
385
386ASN1_SEQUENCE(ISSUING_DIST_POINT) = {
387 ASN1_EXP_OPT(ISSUING_DIST_POINT, distpoint, DIST_POINT_NAME, 0),
388 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyuser, ASN1_FBOOLEAN, 1),
389 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyCA, ASN1_FBOOLEAN, 2),
390 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlysomereasons, ASN1_BIT_STRING, 3),
391 ASN1_IMP_OPT(ISSUING_DIST_POINT, indirectCRL, ASN1_FBOOLEAN, 4),
392 ASN1_IMP_OPT(ISSUING_DIST_POINT, onlyattr, ASN1_FBOOLEAN, 5)
393} ASN1_SEQUENCE_END(ISSUING_DIST_POINT)
394
0537f968
DSH
395IMPLEMENT_ASN1_FUNCTIONS(ISSUING_DIST_POINT)
396
231493c9
DSH
397static int i2r_idp(X509V3_EXT_METHOD *method,
398 void *pidp, BIO *out, int indent);
0537f968
DSH
399static void *v2i_idp(X509V3_EXT_METHOD *method,
400 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
231493c9 401
560b79cb 402const X509V3_EXT_METHOD v3_idp =
231493c9
DSH
403 {
404 NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
405 ASN1_ITEM_ref(ISSUING_DIST_POINT),
406 0,0,0,0,
407 0,0,
0537f968
DSH
408 0,
409 v2i_idp,
231493c9
DSH
410 i2r_idp,0,
411 NULL
412 };
413
0537f968
DSH
414static void *v2i_idp(X509V3_EXT_METHOD *method,
415 X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
416 {
417 ISSUING_DIST_POINT *idp = NULL;
418 CONF_VALUE *cnf;
419 char *name, *val;
420 int i, ret;
421 idp = ISSUING_DIST_POINT_new();
422 if (!idp)
423 goto merr;
424 for(i = 0; i < sk_CONF_VALUE_num(nval); i++)
425 {
426 cnf = sk_CONF_VALUE_value(nval, i);
427 name = cnf->name;
428 val = cnf->value;
429 ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
430 if (ret > 0)
431 continue;
432 if (ret < 0)
433 goto err;
434 if (!strcmp(name, "onlyuser"))
435 {
436 if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
437 goto err;
438 }
439 else if (!strcmp(name, "onlyCA"))
440 {
441 if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
442 goto err;
443 }
444 else if (!strcmp(name, "onlyAA"))
445 {
446 if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
447 goto err;
448 }
449 else if (!strcmp(name, "indirectCRL"))
450 {
451 if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
452 goto err;
453 }
454 else if (!strcmp(name, "onlysomereasons"))
455 {
456 if (!set_reasons(&idp->onlysomereasons, val))
457 goto err;
458 }
459 else
460 {
461 X509V3err(X509V3_F_V2I_IDP, X509V3_R_INVALID_NAME);
462 X509V3_conf_err(cnf);
463 goto err;
464 }
465 }
466 return idp;
467
468 merr:
469 X509V3err(X509V3_F_V2I_IDP,ERR_R_MALLOC_FAILURE);
470 err:
471 ISSUING_DIST_POINT_free(idp);
472 return NULL;
473 }
474
9aa9d70d 475static int print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
231493c9
DSH
476 {
477 int i;
9aa9d70d
DSH
478 for (i = 0; i < sk_GENERAL_NAME_num(gens); i++)
479 {
480 BIO_printf(out, "%*s", indent + 2, "");
481 GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
482 BIO_puts(out, "\n");
483 }
484 return 1;
485 }
486
487static int print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
488 {
231493c9
DSH
489 if (dpn->type == 0)
490 {
231493c9 491 BIO_printf(out, "%*sFull Name:\n", indent, "");
0745d089 492 print_gens(out, dpn->name.fullname, indent);
231493c9
DSH
493 }
494 else
495 {
496 X509_NAME ntmp;
497 ntmp.entries = dpn->name.relativename;
498 BIO_printf(out, "%*sRelative Name:\n%*s",
499 indent, "", indent + 2, "");
500 X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
501 BIO_puts(out, "\n");
502 }
503 return 1;
504 }
505
506static int i2r_idp(X509V3_EXT_METHOD *method, void *pidp, BIO *out, int indent)
507 {
508 ISSUING_DIST_POINT *idp = pidp;
509 if (idp->distpoint)
510 print_distpoint(out, idp->distpoint, indent);
511 if (idp->onlyuser > 0)
512 BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
513 if (idp->onlyCA > 0)
514 BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
515 if (idp->indirectCRL > 0)
516 BIO_printf(out, "%*sIndirect CRL\n", indent, "");
517 if (idp->onlysomereasons)
518 print_reasons(out, "Only Some Reasons",
519 idp->onlysomereasons, indent);
520 if (idp->onlyattr > 0)
521 BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
522 if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0)
523 && (idp->indirectCRL <= 0) && !idp->onlysomereasons
524 && (idp->onlyattr <= 0))
525 BIO_printf(out, "%*s<EMPTY>\n", indent, "");
526
527 return 1;
528 }
9aa9d70d
DSH
529
530static int i2r_crldp(X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
531 int indent)
532 {
533 STACK_OF(DIST_POINT) *crld = pcrldp;
534 DIST_POINT *point;
535 int i;
536 for(i = 0; i < sk_DIST_POINT_num(crld); i++)
537 {
0745d089 538 BIO_puts(out, "\n");
9aa9d70d
DSH
539 point = sk_DIST_POINT_value(crld, i);
540 if(point->distpoint)
0745d089 541 print_distpoint(out, point->distpoint, indent);
9aa9d70d
DSH
542 if(point->reasons)
543 print_reasons(out, "Reasons", point->reasons,
0745d089 544 indent);
9aa9d70d
DSH
545 if(point->CRLissuer)
546 {
547 BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
0745d089 548 print_gens(out, point->CRLissuer, indent);
9aa9d70d
DSH
549 }
550 }
551 return 1;
552 }