xref: /dragonfly/crypto/libressl/crypto/x509/x509_crld.c (revision 961e30ea7dc61d1112b778ea4981eac68129fb86)
1 /* $OpenBSD: x509_crld.c,v 1.2 2021/11/01 20:53:08 tb Exp $ */
2 /* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3  * project 1999.
4  */
5 /* ====================================================================
6  * Copyright (c) 1999-2008 The OpenSSL Project.  All rights reserved.
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 <string.h>
61 
62 #include <openssl/asn1.h>
63 #include <openssl/asn1t.h>
64 #include <openssl/conf.h>
65 #include <openssl/err.h>
66 #include <openssl/x509v3.h>
67 
68 #include "x509_lcl.h"
69 
70 static void *v2i_crld(const X509V3_EXT_METHOD *method,
71     X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval);
72 static int i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out,
73     int indent);
74 
75 const X509V3_EXT_METHOD v3_crld = {
76           .ext_nid = NID_crl_distribution_points,
77           .ext_flags = 0,
78           .it = &CRL_DIST_POINTS_it,
79           .ext_new = NULL,
80           .ext_free = NULL,
81           .d2i = NULL,
82           .i2d = NULL,
83           .i2s = NULL,
84           .s2i = NULL,
85           .i2v = NULL,
86           .v2i = v2i_crld,
87           .i2r = i2r_crldp,
88           .r2i = NULL,
89           .usr_data = NULL,
90 };
91 
92 const X509V3_EXT_METHOD v3_freshest_crl = {
93           .ext_nid = NID_freshest_crl,
94           .ext_flags = 0,
95           .it = &CRL_DIST_POINTS_it,
96           .ext_new = NULL,
97           .ext_free = NULL,
98           .d2i = NULL,
99           .i2d = NULL,
100           .i2s = NULL,
101           .s2i = NULL,
102           .i2v = NULL,
103           .v2i = v2i_crld,
104           .i2r = i2r_crldp,
105           .r2i = NULL,
106           .usr_data = NULL,
107 };
108 
STACK_OF(GENERAL_NAME)109 static STACK_OF(GENERAL_NAME) *
110 gnames_from_sectname(X509V3_CTX *ctx, char *sect)
111 {
112           STACK_OF(CONF_VALUE) *gnsect;
113           STACK_OF(GENERAL_NAME) *gens;
114 
115           if (*sect == '@')
116                     gnsect = X509V3_get_section(ctx, sect + 1);
117           else
118                     gnsect = X509V3_parse_list(sect);
119           if (!gnsect) {
120                     X509V3error(X509V3_R_SECTION_NOT_FOUND);
121                     return NULL;
122           }
123           gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
124           if (*sect == '@')
125                     X509V3_section_free(ctx, gnsect);
126           else
127                     sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
128           return gens;
129 }
130 
131 static int
set_dist_point_name(DIST_POINT_NAME ** pdp,X509V3_CTX * ctx,CONF_VALUE * cnf)132 set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, CONF_VALUE *cnf)
133 {
134           STACK_OF(GENERAL_NAME) *fnm = NULL;
135           STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
136 
137           if (!strncmp(cnf->name, "fullname", 9)) {
138                     fnm = gnames_from_sectname(ctx, cnf->value);
139                     if (!fnm)
140                               goto err;
141           } else if (!strcmp(cnf->name, "relativename")) {
142                     int ret;
143                     STACK_OF(CONF_VALUE) *dnsect;
144                     X509_NAME *nm;
145                     nm = X509_NAME_new();
146                     if (!nm)
147                               return -1;
148                     dnsect = X509V3_get_section(ctx, cnf->value);
149                     if (!dnsect) {
150                               X509V3error(X509V3_R_SECTION_NOT_FOUND);
151                               X509_NAME_free(nm);
152                               return -1;
153                     }
154                     ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
155                     X509V3_section_free(ctx, dnsect);
156                     rnm = nm->entries;
157                     nm->entries = NULL;
158                     X509_NAME_free(nm);
159                     if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
160                               goto err;
161                     /* Since its a name fragment can't have more than one
162                      * RDNSequence
163                      */
164                     if (sk_X509_NAME_ENTRY_value(rnm,
165                         sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
166                               X509V3error(X509V3_R_INVALID_MULTIPLE_RDNS);
167                               goto err;
168                     }
169           } else
170                     return 0;
171 
172           if (*pdp) {
173                     X509V3error(X509V3_R_DISTPOINT_ALREADY_SET);
174                     goto err;
175           }
176 
177           *pdp = DIST_POINT_NAME_new();
178           if (!*pdp)
179                     goto err;
180           if (fnm) {
181                     (*pdp)->type = 0;
182                     (*pdp)->name.fullname = fnm;
183           } else {
184                     (*pdp)->type = 1;
185                     (*pdp)->name.relativename = rnm;
186           }
187 
188           return 1;
189 
190 err:
191           sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
192           sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
193           return -1;
194 }
195 
196 static const BIT_STRING_BITNAME reason_flags[] = {
197           {0, "Unused", "unused"},
198           {1, "Key Compromise", "keyCompromise"},
199           {2, "CA Compromise", "CACompromise"},
200           {3, "Affiliation Changed", "affiliationChanged"},
201           {4, "Superseded", "superseded"},
202           {5, "Cessation Of Operation", "cessationOfOperation"},
203           {6, "Certificate Hold", "certificateHold"},
204           {7, "Privilege Withdrawn", "privilegeWithdrawn"},
205           {8, "AA Compromise", "AACompromise"},
206           {-1, NULL, NULL}
207 };
208 
209 static int
set_reasons(ASN1_BIT_STRING ** preas,char * value)210 set_reasons(ASN1_BIT_STRING **preas, char *value)
211 {
212           STACK_OF(CONF_VALUE) *rsk = NULL;
213           const BIT_STRING_BITNAME *pbn;
214           const char *bnam;
215           int i, ret = 0;
216 
217           if (*preas != NULL)
218                     return 0;
219           rsk = X509V3_parse_list(value);
220           if (rsk == NULL)
221                     return 0;
222           for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
223                     bnam = sk_CONF_VALUE_value(rsk, i)->name;
224                     if (!*preas) {
225                               *preas = ASN1_BIT_STRING_new();
226                               if (!*preas)
227                                         goto err;
228                     }
229                     for (pbn = reason_flags; pbn->lname; pbn++) {
230                               if (!strcmp(pbn->sname, bnam)) {
231                                         if (!ASN1_BIT_STRING_set_bit(*preas,
232                                             pbn->bitnum, 1))
233                                                   goto err;
234                                         break;
235                               }
236                     }
237                     if (!pbn->lname)
238                               goto err;
239           }
240           ret = 1;
241 
242 err:
243           sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
244           return ret;
245 }
246 
247 static int
print_reasons(BIO * out,const char * rname,ASN1_BIT_STRING * rflags,int indent)248 print_reasons(BIO *out, const char *rname, ASN1_BIT_STRING *rflags, int indent)
249 {
250           int first = 1;
251           const BIT_STRING_BITNAME *pbn;
252 
253           BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
254           for (pbn = reason_flags; pbn->lname; pbn++) {
255                     if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
256                               if (first)
257                                         first = 0;
258                               else
259                                         BIO_puts(out, ", ");
260                               BIO_puts(out, pbn->lname);
261                     }
262           }
263           if (first)
264                     BIO_puts(out, "<EMPTY>\n");
265           else
266                     BIO_puts(out, "\n");
267           return 1;
268 }
269 
270 static DIST_POINT *
crldp_from_section(X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)271 crldp_from_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
272 {
273           int i;
274           CONF_VALUE *cnf;
275           DIST_POINT *point = NULL;
276 
277           point = DIST_POINT_new();
278           if (!point)
279                     goto err;
280           for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
281                     int ret;
282                     cnf = sk_CONF_VALUE_value(nval, i);
283                     ret = set_dist_point_name(&point->distpoint, ctx, cnf);
284                     if (ret > 0)
285                               continue;
286                     if (ret < 0)
287                               goto err;
288                     if (!strcmp(cnf->name, "reasons")) {
289                               if (!set_reasons(&point->reasons, cnf->value))
290                                         goto err;
291                     }
292                     else if (!strcmp(cnf->name, "CRLissuer")) {
293                               point->CRLissuer =
294                                   gnames_from_sectname(ctx, cnf->value);
295                               if (!point->CRLissuer)
296                                         goto err;
297                     }
298           }
299 
300           return point;
301 
302 err:
303           DIST_POINT_free(point);
304           return NULL;
305 }
306 
307 static void *
v2i_crld(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)308 v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
309     STACK_OF(CONF_VALUE) *nval)
310 {
311           STACK_OF(DIST_POINT) *crld = NULL;
312           GENERAL_NAMES *gens = NULL;
313           GENERAL_NAME *gen = NULL;
314           CONF_VALUE *cnf;
315           int i;
316 
317           if (!(crld = sk_DIST_POINT_new_null()))
318                     goto merr;
319           for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
320                     DIST_POINT *point;
321                     cnf = sk_CONF_VALUE_value(nval, i);
322                     if (!cnf->value) {
323                               STACK_OF(CONF_VALUE) *dpsect;
324                               dpsect = X509V3_get_section(ctx, cnf->name);
325                               if (!dpsect)
326                                         goto err;
327                               point = crldp_from_section(ctx, dpsect);
328                               X509V3_section_free(ctx, dpsect);
329                               if (!point)
330                                         goto err;
331                               if (!sk_DIST_POINT_push(crld, point)) {
332                                         DIST_POINT_free(point);
333                                         goto merr;
334                               }
335                     } else {
336                               if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
337                                         goto err;
338                               if (!(gens = GENERAL_NAMES_new()))
339                                         goto merr;
340                               if (!sk_GENERAL_NAME_push(gens, gen))
341                                         goto merr;
342                               gen = NULL;
343                               if (!(point = DIST_POINT_new()))
344                                         goto merr;
345                               if (!sk_DIST_POINT_push(crld, point)) {
346                                         DIST_POINT_free(point);
347                                         goto merr;
348                               }
349                               if (!(point->distpoint = DIST_POINT_NAME_new()))
350                                         goto merr;
351                               point->distpoint->name.fullname = gens;
352                               point->distpoint->type = 0;
353                               gens = NULL;
354                     }
355           }
356           return crld;
357 
358 merr:
359           X509V3error(ERR_R_MALLOC_FAILURE);
360 err:
361           GENERAL_NAME_free(gen);
362           GENERAL_NAMES_free(gens);
363           sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
364           return NULL;
365 }
366 
367 static int
dpn_cb(int operation,ASN1_VALUE ** pval,const ASN1_ITEM * it,void * exarg)368 dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
369 {
370           DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
371 
372           switch (operation) {
373           case ASN1_OP_NEW_POST:
374                     dpn->dpname = NULL;
375                     break;
376 
377           case ASN1_OP_FREE_POST:
378                     if (dpn->dpname)
379                               X509_NAME_free(dpn->dpname);
380                     break;
381           }
382           return 1;
383 }
384 
385 
386 static const ASN1_AUX DIST_POINT_NAME_aux = {
387           .app_data = NULL,
388           .flags = 0,
389           .ref_offset = 0,
390           .ref_lock = 0,
391           .asn1_cb = dpn_cb,
392           .enc_offset = 0,
393 };
394 static const ASN1_TEMPLATE DIST_POINT_NAME_ch_tt[] = {
395           {
396                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF,
397                     .tag = 0,
398                     .offset = offsetof(DIST_POINT_NAME, name.fullname),
399                     .field_name = "name.fullname",
400                     .item = &GENERAL_NAME_it,
401           },
402           {
403                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SET_OF,
404                     .tag = 1,
405                     .offset = offsetof(DIST_POINT_NAME, name.relativename),
406                     .field_name = "name.relativename",
407                     .item = &X509_NAME_ENTRY_it,
408           },
409 };
410 
411 const ASN1_ITEM DIST_POINT_NAME_it = {
412           .itype = ASN1_ITYPE_CHOICE,
413           .utype = offsetof(DIST_POINT_NAME, type),
414           .templates = DIST_POINT_NAME_ch_tt,
415           .tcount = sizeof(DIST_POINT_NAME_ch_tt) / sizeof(ASN1_TEMPLATE),
416           .funcs = &DIST_POINT_NAME_aux,
417           .size = sizeof(DIST_POINT_NAME),
418           .sname = "DIST_POINT_NAME",
419 };
420 
421 
422 
423 DIST_POINT_NAME *
d2i_DIST_POINT_NAME(DIST_POINT_NAME ** a,const unsigned char ** in,long len)424 d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, const unsigned char **in, long len)
425 {
426           return (DIST_POINT_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
427               &DIST_POINT_NAME_it);
428 }
429 
430 int
i2d_DIST_POINT_NAME(DIST_POINT_NAME * a,unsigned char ** out)431 i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **out)
432 {
433           return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_NAME_it);
434 }
435 
436 DIST_POINT_NAME *
DIST_POINT_NAME_new(void)437 DIST_POINT_NAME_new(void)
438 {
439           return (DIST_POINT_NAME *)ASN1_item_new(&DIST_POINT_NAME_it);
440 }
441 
442 void
DIST_POINT_NAME_free(DIST_POINT_NAME * a)443 DIST_POINT_NAME_free(DIST_POINT_NAME *a)
444 {
445           ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_NAME_it);
446 }
447 
448 static const ASN1_TEMPLATE DIST_POINT_seq_tt[] = {
449           {
450                     .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
451                     .tag = 0,
452                     .offset = offsetof(DIST_POINT, distpoint),
453                     .field_name = "distpoint",
454                     .item = &DIST_POINT_NAME_it,
455           },
456           {
457                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
458                     .tag = 1,
459                     .offset = offsetof(DIST_POINT, reasons),
460                     .field_name = "reasons",
461                     .item = &ASN1_BIT_STRING_it,
462           },
463           {
464                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_SEQUENCE_OF | ASN1_TFLG_OPTIONAL,
465                     .tag = 2,
466                     .offset = offsetof(DIST_POINT, CRLissuer),
467                     .field_name = "CRLissuer",
468                     .item = &GENERAL_NAME_it,
469           },
470 };
471 
472 const ASN1_ITEM DIST_POINT_it = {
473           .itype = ASN1_ITYPE_SEQUENCE,
474           .utype = V_ASN1_SEQUENCE,
475           .templates = DIST_POINT_seq_tt,
476           .tcount = sizeof(DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE),
477           .funcs = NULL,
478           .size = sizeof(DIST_POINT),
479           .sname = "DIST_POINT",
480 };
481 
482 
483 DIST_POINT *
d2i_DIST_POINT(DIST_POINT ** a,const unsigned char ** in,long len)484 d2i_DIST_POINT(DIST_POINT **a, const unsigned char **in, long len)
485 {
486           return (DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
487               &DIST_POINT_it);
488 }
489 
490 int
i2d_DIST_POINT(DIST_POINT * a,unsigned char ** out)491 i2d_DIST_POINT(DIST_POINT *a, unsigned char **out)
492 {
493           return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_it);
494 }
495 
496 DIST_POINT *
DIST_POINT_new(void)497 DIST_POINT_new(void)
498 {
499           return (DIST_POINT *)ASN1_item_new(&DIST_POINT_it);
500 }
501 
502 void
DIST_POINT_free(DIST_POINT * a)503 DIST_POINT_free(DIST_POINT *a)
504 {
505           ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_it);
506 }
507 
508 static const ASN1_TEMPLATE CRL_DIST_POINTS_item_tt = {
509           .flags = ASN1_TFLG_SEQUENCE_OF,
510           .tag = 0,
511           .offset = 0,
512           .field_name = "CRLDistributionPoints",
513           .item = &DIST_POINT_it,
514 };
515 
516 const ASN1_ITEM CRL_DIST_POINTS_it = {
517           .itype = ASN1_ITYPE_PRIMITIVE,
518           .utype = -1,
519           .templates = &CRL_DIST_POINTS_item_tt,
520           .tcount = 0,
521           .funcs = NULL,
522           .size = 0,
523           .sname = "CRL_DIST_POINTS",
524 };
525 
526 
527 CRL_DIST_POINTS *
d2i_CRL_DIST_POINTS(CRL_DIST_POINTS ** a,const unsigned char ** in,long len)528 d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **a, const unsigned char **in, long len)
529 {
530           return (CRL_DIST_POINTS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
531               &CRL_DIST_POINTS_it);
532 }
533 
534 int
i2d_CRL_DIST_POINTS(CRL_DIST_POINTS * a,unsigned char ** out)535 i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *a, unsigned char **out)
536 {
537           return ASN1_item_i2d((ASN1_VALUE *)a, out, &CRL_DIST_POINTS_it);
538 }
539 
540 CRL_DIST_POINTS *
CRL_DIST_POINTS_new(void)541 CRL_DIST_POINTS_new(void)
542 {
543           return (CRL_DIST_POINTS *)ASN1_item_new(&CRL_DIST_POINTS_it);
544 }
545 
546 void
CRL_DIST_POINTS_free(CRL_DIST_POINTS * a)547 CRL_DIST_POINTS_free(CRL_DIST_POINTS *a)
548 {
549           ASN1_item_free((ASN1_VALUE *)a, &CRL_DIST_POINTS_it);
550 }
551 
552 static const ASN1_TEMPLATE ISSUING_DIST_POINT_seq_tt[] = {
553           {
554                     .flags = ASN1_TFLG_EXPLICIT | ASN1_TFLG_OPTIONAL,
555                     .tag = 0,
556                     .offset = offsetof(ISSUING_DIST_POINT, distpoint),
557                     .field_name = "distpoint",
558                     .item = &DIST_POINT_NAME_it,
559           },
560           {
561                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
562                     .tag = 1,
563                     .offset = offsetof(ISSUING_DIST_POINT, onlyuser),
564                     .field_name = "onlyuser",
565                     .item = &ASN1_FBOOLEAN_it,
566           },
567           {
568                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
569                     .tag = 2,
570                     .offset = offsetof(ISSUING_DIST_POINT, onlyCA),
571                     .field_name = "onlyCA",
572                     .item = &ASN1_FBOOLEAN_it,
573           },
574           {
575                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
576                     .tag = 3,
577                     .offset = offsetof(ISSUING_DIST_POINT, onlysomereasons),
578                     .field_name = "onlysomereasons",
579                     .item = &ASN1_BIT_STRING_it,
580           },
581           {
582                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
583                     .tag = 4,
584                     .offset = offsetof(ISSUING_DIST_POINT, indirectCRL),
585                     .field_name = "indirectCRL",
586                     .item = &ASN1_FBOOLEAN_it,
587           },
588           {
589                     .flags = ASN1_TFLG_IMPLICIT | ASN1_TFLG_OPTIONAL,
590                     .tag = 5,
591                     .offset = offsetof(ISSUING_DIST_POINT, onlyattr),
592                     .field_name = "onlyattr",
593                     .item = &ASN1_FBOOLEAN_it,
594           },
595 };
596 
597 const ASN1_ITEM ISSUING_DIST_POINT_it = {
598           .itype = ASN1_ITYPE_SEQUENCE,
599           .utype = V_ASN1_SEQUENCE,
600           .templates = ISSUING_DIST_POINT_seq_tt,
601           .tcount = sizeof(ISSUING_DIST_POINT_seq_tt) / sizeof(ASN1_TEMPLATE),
602           .funcs = NULL,
603           .size = sizeof(ISSUING_DIST_POINT),
604           .sname = "ISSUING_DIST_POINT",
605 };
606 
607 
608 ISSUING_DIST_POINT *
d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT ** a,const unsigned char ** in,long len)609 d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT **a, const unsigned char **in, long len)
610 {
611           return (ISSUING_DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
612               &ISSUING_DIST_POINT_it);
613 }
614 
615 int
i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT * a,unsigned char ** out)616 i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *a, unsigned char **out)
617 {
618           return ASN1_item_i2d((ASN1_VALUE *)a, out, &ISSUING_DIST_POINT_it);
619 }
620 
621 ISSUING_DIST_POINT *
ISSUING_DIST_POINT_new(void)622 ISSUING_DIST_POINT_new(void)
623 {
624           return (ISSUING_DIST_POINT *)ASN1_item_new(&ISSUING_DIST_POINT_it);
625 }
626 
627 void
ISSUING_DIST_POINT_free(ISSUING_DIST_POINT * a)628 ISSUING_DIST_POINT_free(ISSUING_DIST_POINT *a)
629 {
630           ASN1_item_free((ASN1_VALUE *)a, &ISSUING_DIST_POINT_it);
631 }
632 
633 static int i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out,
634     int indent);
635 static void *v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
636     STACK_OF(CONF_VALUE) *nval);
637 
638 const X509V3_EXT_METHOD v3_idp = {
639           NID_issuing_distribution_point, X509V3_EXT_MULTILINE,
640           &ISSUING_DIST_POINT_it,
641           0, 0, 0, 0,
642           0, 0,
643           0,
644           v2i_idp,
645           i2r_idp, 0,
646           NULL
647 };
648 
649 static void *
v2i_idp(const X509V3_EXT_METHOD * method,X509V3_CTX * ctx,STACK_OF (CONF_VALUE)* nval)650 v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
651     STACK_OF(CONF_VALUE) *nval)
652 {
653           ISSUING_DIST_POINT *idp = NULL;
654           CONF_VALUE *cnf;
655           char *name, *val;
656           int i, ret;
657 
658           idp = ISSUING_DIST_POINT_new();
659           if (!idp)
660                     goto merr;
661           for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
662                     cnf = sk_CONF_VALUE_value(nval, i);
663                     name = cnf->name;
664                     val = cnf->value;
665                     ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
666                     if (ret > 0)
667                               continue;
668                     if (ret < 0)
669                               goto err;
670                     if (!strcmp(name, "onlyuser")) {
671                               if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
672                                         goto err;
673                     }
674                     else if (!strcmp(name, "onlyCA")) {
675                               if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
676                                         goto err;
677                     }
678                     else if (!strcmp(name, "onlyAA")) {
679                               if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
680                                         goto err;
681                     }
682                     else if (!strcmp(name, "indirectCRL")) {
683                               if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
684                                         goto err;
685                     }
686                     else if (!strcmp(name, "onlysomereasons")) {
687                               if (!set_reasons(&idp->onlysomereasons, val))
688                                         goto err;
689                     } else {
690                               X509V3error(X509V3_R_INVALID_NAME);
691                               X509V3_conf_err(cnf);
692                               goto err;
693                     }
694           }
695           return idp;
696 
697 merr:
698           X509V3error(ERR_R_MALLOC_FAILURE);
699 err:
700           ISSUING_DIST_POINT_free(idp);
701           return NULL;
702 }
703 
704 static int
print_gens(BIO * out,STACK_OF (GENERAL_NAME)* gens,int indent)705 print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
706 {
707           int i;
708 
709           for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
710                     BIO_printf(out, "%*s", indent + 2, "");
711                     GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
712                     BIO_puts(out, "\n");
713           }
714           return 1;
715 }
716 
717 static int
print_distpoint(BIO * out,DIST_POINT_NAME * dpn,int indent)718 print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
719 {
720           if (dpn->type == 0) {
721                     BIO_printf(out, "%*sFull Name:\n", indent, "");
722                     print_gens(out, dpn->name.fullname, indent);
723           } else {
724                     X509_NAME ntmp;
725                     ntmp.entries = dpn->name.relativename;
726                     BIO_printf(out, "%*sRelative Name:\n%*s",
727                         indent, "", indent + 2, "");
728                     X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
729                     BIO_puts(out, "\n");
730           }
731           return 1;
732 }
733 
734 static int
i2r_idp(const X509V3_EXT_METHOD * method,void * pidp,BIO * out,int indent)735 i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, int indent)
736 {
737           ISSUING_DIST_POINT *idp = pidp;
738 
739           if (idp->distpoint)
740                     print_distpoint(out, idp->distpoint, indent);
741           if (idp->onlyuser > 0)
742                     BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
743           if (idp->onlyCA > 0)
744                     BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
745           if (idp->indirectCRL > 0)
746                     BIO_printf(out, "%*sIndirect CRL\n", indent, "");
747           if (idp->onlysomereasons)
748                     print_reasons(out, "Only Some Reasons",
749               idp->onlysomereasons, indent);
750           if (idp->onlyattr > 0)
751                     BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
752           if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) &&
753               (idp->indirectCRL <= 0) && !idp->onlysomereasons &&
754               (idp->onlyattr <= 0))
755                     BIO_printf(out, "%*s<EMPTY>\n", indent, "");
756 
757           return 1;
758 }
759 
760 static int
i2r_crldp(const X509V3_EXT_METHOD * method,void * pcrldp,BIO * out,int indent)761 i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, int indent)
762 {
763           STACK_OF(DIST_POINT) *crld = pcrldp;
764           DIST_POINT *point;
765           int i;
766 
767           for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
768                     BIO_puts(out, "\n");
769                     point = sk_DIST_POINT_value(crld, i);
770                     if (point->distpoint)
771                               print_distpoint(out, point->distpoint, indent);
772                     if (point->reasons)
773                               print_reasons(out, "Reasons", point->reasons,
774                         indent);
775                     if (point->CRLissuer) {
776                               BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
777                               print_gens(out, point->CRLissuer, indent);
778                     }
779           }
780           return 1;
781 }
782 
783 int
DIST_POINT_set_dpname(DIST_POINT_NAME * dpn,X509_NAME * iname)784 DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
785 {
786           int i;
787           STACK_OF(X509_NAME_ENTRY) *frag;
788           X509_NAME_ENTRY *ne;
789 
790           if (!dpn || (dpn->type != 1))
791                     return 1;
792           frag = dpn->name.relativename;
793           dpn->dpname = X509_NAME_dup(iname);
794           if (!dpn->dpname)
795                     return 0;
796           for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
797                     ne = sk_X509_NAME_ENTRY_value(frag, i);
798                     if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
799                               X509_NAME_free(dpn->dpname);
800                               dpn->dpname = NULL;
801                               return 0;
802                     }
803           }
804           /* generate cached encoding of name */
805           if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
806                     X509_NAME_free(dpn->dpname);
807                     dpn->dpname = NULL;
808                     return 0;
809           }
810           return 1;
811 }
812