Coverage Report

Created: 2022-08-24 06:31

/src/libressl/crypto/x509/x509_crld.c
Line
Count
Source (jump to first uncovered line)
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
109
static STACK_OF(GENERAL_NAME) *
110
gnames_from_sectname(X509V3_CTX *ctx, char *sect)
111
0
{
112
0
  STACK_OF(CONF_VALUE) *gnsect;
113
0
  STACK_OF(GENERAL_NAME) *gens;
114
115
0
  if (*sect == '@')
116
0
    gnsect = X509V3_get_section(ctx, sect + 1);
117
0
  else
118
0
    gnsect = X509V3_parse_list(sect);
119
0
  if (!gnsect) {
120
0
    X509V3error(X509V3_R_SECTION_NOT_FOUND);
121
0
    return NULL;
122
0
  }
123
0
  gens = v2i_GENERAL_NAMES(NULL, ctx, gnsect);
124
0
  if (*sect == '@')
125
0
    X509V3_section_free(ctx, gnsect);
126
0
  else
127
0
    sk_CONF_VALUE_pop_free(gnsect, X509V3_conf_free);
128
0
  return gens;
129
0
}
130
131
static int
132
set_dist_point_name(DIST_POINT_NAME **pdp, X509V3_CTX *ctx, CONF_VALUE *cnf)
133
0
{
134
0
  STACK_OF(GENERAL_NAME) *fnm = NULL;
135
0
  STACK_OF(X509_NAME_ENTRY) *rnm = NULL;
136
137
0
  if (!strncmp(cnf->name, "fullname", 9)) {
138
0
    fnm = gnames_from_sectname(ctx, cnf->value);
139
0
    if (!fnm)
140
0
      goto err;
141
0
  } else if (!strcmp(cnf->name, "relativename")) {
142
0
    int ret;
143
0
    STACK_OF(CONF_VALUE) *dnsect;
144
0
    X509_NAME *nm;
145
0
    nm = X509_NAME_new();
146
0
    if (!nm)
147
0
      return -1;
148
0
    dnsect = X509V3_get_section(ctx, cnf->value);
149
0
    if (!dnsect) {
150
0
      X509V3error(X509V3_R_SECTION_NOT_FOUND);
151
0
      X509_NAME_free(nm);
152
0
      return -1;
153
0
    }
154
0
    ret = X509V3_NAME_from_section(nm, dnsect, MBSTRING_ASC);
155
0
    X509V3_section_free(ctx, dnsect);
156
0
    rnm = nm->entries;
157
0
    nm->entries = NULL;
158
0
    X509_NAME_free(nm);
159
0
    if (!ret || sk_X509_NAME_ENTRY_num(rnm) <= 0)
160
0
      goto err;
161
    /* Since its a name fragment can't have more than one
162
     * RDNSequence
163
     */
164
0
    if (sk_X509_NAME_ENTRY_value(rnm,
165
0
        sk_X509_NAME_ENTRY_num(rnm) - 1)->set) {
166
0
      X509V3error(X509V3_R_INVALID_MULTIPLE_RDNS);
167
0
      goto err;
168
0
    }
169
0
  } else
170
0
    return 0;
171
172
0
  if (*pdp) {
173
0
    X509V3error(X509V3_R_DISTPOINT_ALREADY_SET);
174
0
    goto err;
175
0
  }
176
177
0
  *pdp = DIST_POINT_NAME_new();
178
0
  if (!*pdp)
179
0
    goto err;
180
0
  if (fnm) {
181
0
    (*pdp)->type = 0;
182
0
    (*pdp)->name.fullname = fnm;
183
0
  } else {
184
0
    (*pdp)->type = 1;
185
0
    (*pdp)->name.relativename = rnm;
186
0
  }
187
188
0
  return 1;
189
190
0
err:
191
0
  sk_GENERAL_NAME_pop_free(fnm, GENERAL_NAME_free);
192
0
  sk_X509_NAME_ENTRY_pop_free(rnm, X509_NAME_ENTRY_free);
193
0
  return -1;
194
0
}
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
210
set_reasons(ASN1_BIT_STRING **preas, char *value)
211
0
{
212
0
  STACK_OF(CONF_VALUE) *rsk = NULL;
213
0
  const BIT_STRING_BITNAME *pbn;
214
0
  const char *bnam;
215
0
  int i, ret = 0;
216
217
0
  if (*preas != NULL)
218
0
    return 0;
219
0
  rsk = X509V3_parse_list(value);
220
0
  if (rsk == NULL)
221
0
    return 0;
222
0
  for (i = 0; i < sk_CONF_VALUE_num(rsk); i++) {
223
0
    bnam = sk_CONF_VALUE_value(rsk, i)->name;
224
0
    if (!*preas) {
225
0
      *preas = ASN1_BIT_STRING_new();
226
0
      if (!*preas)
227
0
        goto err;
228
0
    }
229
0
    for (pbn = reason_flags; pbn->lname; pbn++) {
230
0
      if (!strcmp(pbn->sname, bnam)) {
231
0
        if (!ASN1_BIT_STRING_set_bit(*preas,
232
0
            pbn->bitnum, 1))
233
0
          goto err;
234
0
        break;
235
0
      }
236
0
    }
237
0
    if (!pbn->lname)
238
0
      goto err;
239
0
  }
240
0
  ret = 1;
241
242
0
err:
243
0
  sk_CONF_VALUE_pop_free(rsk, X509V3_conf_free);
244
0
  return ret;
245
0
}
246
247
static int
248
print_reasons(BIO *out, const char *rname, ASN1_BIT_STRING *rflags, int indent)
249
0
{
250
0
  int first = 1;
251
0
  const BIT_STRING_BITNAME *pbn;
252
253
0
  BIO_printf(out, "%*s%s:\n%*s", indent, "", rname, indent + 2, "");
254
0
  for (pbn = reason_flags; pbn->lname; pbn++) {
255
0
    if (ASN1_BIT_STRING_get_bit(rflags, pbn->bitnum)) {
256
0
      if (first)
257
0
        first = 0;
258
0
      else
259
0
        BIO_puts(out, ", ");
260
0
      BIO_puts(out, pbn->lname);
261
0
    }
262
0
  }
263
0
  if (first)
264
0
    BIO_puts(out, "<EMPTY>\n");
265
0
  else
266
0
    BIO_puts(out, "\n");
267
0
  return 1;
268
0
}
269
270
static DIST_POINT *
271
crldp_from_section(X509V3_CTX *ctx, STACK_OF(CONF_VALUE) *nval)
272
0
{
273
0
  int i;
274
0
  CONF_VALUE *cnf;
275
0
  DIST_POINT *point = NULL;
276
277
0
  point = DIST_POINT_new();
278
0
  if (!point)
279
0
    goto err;
280
0
  for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
281
0
    int ret;
282
0
    cnf = sk_CONF_VALUE_value(nval, i);
283
0
    ret = set_dist_point_name(&point->distpoint, ctx, cnf);
284
0
    if (ret > 0)
285
0
      continue;
286
0
    if (ret < 0)
287
0
      goto err;
288
0
    if (!strcmp(cnf->name, "reasons")) {
289
0
      if (!set_reasons(&point->reasons, cnf->value))
290
0
        goto err;
291
0
    }
292
0
    else if (!strcmp(cnf->name, "CRLissuer")) {
293
0
      point->CRLissuer =
294
0
          gnames_from_sectname(ctx, cnf->value);
295
0
      if (!point->CRLissuer)
296
0
        goto err;
297
0
    }
298
0
  }
299
300
0
  return point;
301
302
0
err:
303
0
  DIST_POINT_free(point);
304
0
  return NULL;
305
0
}
306
307
static void *
308
v2i_crld(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
309
    STACK_OF(CONF_VALUE) *nval)
310
0
{
311
0
  STACK_OF(DIST_POINT) *crld = NULL;
312
0
  GENERAL_NAMES *gens = NULL;
313
0
  GENERAL_NAME *gen = NULL;
314
0
  CONF_VALUE *cnf;
315
0
  int i;
316
317
0
  if (!(crld = sk_DIST_POINT_new_null()))
318
0
    goto merr;
319
0
  for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
320
0
    DIST_POINT *point;
321
0
    cnf = sk_CONF_VALUE_value(nval, i);
322
0
    if (!cnf->value) {
323
0
      STACK_OF(CONF_VALUE) *dpsect;
324
0
      dpsect = X509V3_get_section(ctx, cnf->name);
325
0
      if (!dpsect)
326
0
        goto err;
327
0
      point = crldp_from_section(ctx, dpsect);
328
0
      X509V3_section_free(ctx, dpsect);
329
0
      if (!point)
330
0
        goto err;
331
0
      if (!sk_DIST_POINT_push(crld, point)) {
332
0
        DIST_POINT_free(point);
333
0
        goto merr;
334
0
      }
335
0
    } else {
336
0
      if (!(gen = v2i_GENERAL_NAME(method, ctx, cnf)))
337
0
        goto err;
338
0
      if (!(gens = GENERAL_NAMES_new()))
339
0
        goto merr;
340
0
      if (!sk_GENERAL_NAME_push(gens, gen))
341
0
        goto merr;
342
0
      gen = NULL;
343
0
      if (!(point = DIST_POINT_new()))
344
0
        goto merr;
345
0
      if (!sk_DIST_POINT_push(crld, point)) {
346
0
        DIST_POINT_free(point);
347
0
        goto merr;
348
0
      }
349
0
      if (!(point->distpoint = DIST_POINT_NAME_new()))
350
0
        goto merr;
351
0
      point->distpoint->name.fullname = gens;
352
0
      point->distpoint->type = 0;
353
0
      gens = NULL;
354
0
    }
355
0
  }
356
0
  return crld;
357
358
0
merr:
359
0
  X509V3error(ERR_R_MALLOC_FAILURE);
360
0
err:
361
0
  GENERAL_NAME_free(gen);
362
0
  GENERAL_NAMES_free(gens);
363
0
  sk_DIST_POINT_pop_free(crld, DIST_POINT_free);
364
0
  return NULL;
365
0
}
366
367
static int
368
dpn_cb(int operation, ASN1_VALUE **pval, const ASN1_ITEM *it, void *exarg)
369
499
{
370
499
  DIST_POINT_NAME *dpn = (DIST_POINT_NAME *)*pval;
371
372
499
  switch (operation) {
373
90
  case ASN1_OP_NEW_POST:
374
90
    dpn->dpname = NULL;
375
90
    break;
376
377
90
  case ASN1_OP_FREE_POST:
378
90
    if (dpn->dpname)
379
0
      X509_NAME_free(dpn->dpname);
380
90
    break;
381
499
  }
382
499
  return 1;
383
499
}
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 *
424
d2i_DIST_POINT_NAME(DIST_POINT_NAME **a, const unsigned char **in, long len)
425
0
{
426
0
  return (DIST_POINT_NAME *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
427
0
      &DIST_POINT_NAME_it);
428
0
}
429
430
int
431
i2d_DIST_POINT_NAME(DIST_POINT_NAME *a, unsigned char **out)
432
0
{
433
0
  return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_NAME_it);
434
0
}
435
436
DIST_POINT_NAME *
437
DIST_POINT_NAME_new(void)
438
0
{
439
0
  return (DIST_POINT_NAME *)ASN1_item_new(&DIST_POINT_NAME_it);
440
0
}
441
442
void
443
DIST_POINT_NAME_free(DIST_POINT_NAME *a)
444
0
{
445
0
  ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_NAME_it);
446
0
}
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 *
484
d2i_DIST_POINT(DIST_POINT **a, const unsigned char **in, long len)
485
0
{
486
0
  return (DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
487
0
      &DIST_POINT_it);
488
0
}
489
490
int
491
i2d_DIST_POINT(DIST_POINT *a, unsigned char **out)
492
0
{
493
0
  return ASN1_item_i2d((ASN1_VALUE *)a, out, &DIST_POINT_it);
494
0
}
495
496
DIST_POINT *
497
DIST_POINT_new(void)
498
0
{
499
0
  return (DIST_POINT *)ASN1_item_new(&DIST_POINT_it);
500
0
}
501
502
void
503
DIST_POINT_free(DIST_POINT *a)
504
0
{
505
0
  ASN1_item_free((ASN1_VALUE *)a, &DIST_POINT_it);
506
0
}
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 *
528
d2i_CRL_DIST_POINTS(CRL_DIST_POINTS **a, const unsigned char **in, long len)
529
0
{
530
0
  return (CRL_DIST_POINTS *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
531
0
      &CRL_DIST_POINTS_it);
532
0
}
533
534
int
535
i2d_CRL_DIST_POINTS(CRL_DIST_POINTS *a, unsigned char **out)
536
0
{
537
0
  return ASN1_item_i2d((ASN1_VALUE *)a, out, &CRL_DIST_POINTS_it);
538
0
}
539
540
CRL_DIST_POINTS *
541
CRL_DIST_POINTS_new(void)
542
0
{
543
0
  return (CRL_DIST_POINTS *)ASN1_item_new(&CRL_DIST_POINTS_it);
544
0
}
545
546
void
547
CRL_DIST_POINTS_free(CRL_DIST_POINTS *a)
548
2.20k
{
549
2.20k
  ASN1_item_free((ASN1_VALUE *)a, &CRL_DIST_POINTS_it);
550
2.20k
}
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 *
609
d2i_ISSUING_DIST_POINT(ISSUING_DIST_POINT **a, const unsigned char **in, long len)
610
0
{
611
0
  return (ISSUING_DIST_POINT *)ASN1_item_d2i((ASN1_VALUE **)a, in, len,
612
0
      &ISSUING_DIST_POINT_it);
613
0
}
614
615
int
616
i2d_ISSUING_DIST_POINT(ISSUING_DIST_POINT *a, unsigned char **out)
617
0
{
618
0
  return ASN1_item_i2d((ASN1_VALUE *)a, out, &ISSUING_DIST_POINT_it);
619
0
}
620
621
ISSUING_DIST_POINT *
622
ISSUING_DIST_POINT_new(void)
623
0
{
624
0
  return (ISSUING_DIST_POINT *)ASN1_item_new(&ISSUING_DIST_POINT_it);
625
0
}
626
627
void
628
ISSUING_DIST_POINT_free(ISSUING_DIST_POINT *a)
629
0
{
630
0
  ASN1_item_free((ASN1_VALUE *)a, &ISSUING_DIST_POINT_it);
631
0
}
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 *
650
v2i_idp(const X509V3_EXT_METHOD *method, X509V3_CTX *ctx,
651
    STACK_OF(CONF_VALUE) *nval)
652
0
{
653
0
  ISSUING_DIST_POINT *idp = NULL;
654
0
  CONF_VALUE *cnf;
655
0
  char *name, *val;
656
0
  int i, ret;
657
658
0
  idp = ISSUING_DIST_POINT_new();
659
0
  if (!idp)
660
0
    goto merr;
661
0
  for (i = 0; i < sk_CONF_VALUE_num(nval); i++) {
662
0
    cnf = sk_CONF_VALUE_value(nval, i);
663
0
    name = cnf->name;
664
0
    val = cnf->value;
665
0
    ret = set_dist_point_name(&idp->distpoint, ctx, cnf);
666
0
    if (ret > 0)
667
0
      continue;
668
0
    if (ret < 0)
669
0
      goto err;
670
0
    if (!strcmp(name, "onlyuser")) {
671
0
      if (!X509V3_get_value_bool(cnf, &idp->onlyuser))
672
0
        goto err;
673
0
    }
674
0
    else if (!strcmp(name, "onlyCA")) {
675
0
      if (!X509V3_get_value_bool(cnf, &idp->onlyCA))
676
0
        goto err;
677
0
    }
678
0
    else if (!strcmp(name, "onlyAA")) {
679
0
      if (!X509V3_get_value_bool(cnf, &idp->onlyattr))
680
0
        goto err;
681
0
    }
682
0
    else if (!strcmp(name, "indirectCRL")) {
683
0
      if (!X509V3_get_value_bool(cnf, &idp->indirectCRL))
684
0
        goto err;
685
0
    }
686
0
    else if (!strcmp(name, "onlysomereasons")) {
687
0
      if (!set_reasons(&idp->onlysomereasons, val))
688
0
        goto err;
689
0
    } else {
690
0
      X509V3error(X509V3_R_INVALID_NAME);
691
0
      X509V3_conf_err(cnf);
692
0
      goto err;
693
0
    }
694
0
  }
695
0
  return idp;
696
697
0
merr:
698
0
  X509V3error(ERR_R_MALLOC_FAILURE);
699
0
err:
700
0
  ISSUING_DIST_POINT_free(idp);
701
0
  return NULL;
702
0
}
703
704
static int
705
print_gens(BIO *out, STACK_OF(GENERAL_NAME) *gens, int indent)
706
0
{
707
0
  int i;
708
709
0
  for (i = 0; i < sk_GENERAL_NAME_num(gens); i++) {
710
0
    BIO_printf(out, "%*s", indent + 2, "");
711
0
    GENERAL_NAME_print(out, sk_GENERAL_NAME_value(gens, i));
712
0
    BIO_puts(out, "\n");
713
0
  }
714
0
  return 1;
715
0
}
716
717
static int
718
print_distpoint(BIO *out, DIST_POINT_NAME *dpn, int indent)
719
0
{
720
0
  if (dpn->type == 0) {
721
0
    BIO_printf(out, "%*sFull Name:\n", indent, "");
722
0
    print_gens(out, dpn->name.fullname, indent);
723
0
  } else {
724
0
    X509_NAME ntmp;
725
0
    ntmp.entries = dpn->name.relativename;
726
0
    BIO_printf(out, "%*sRelative Name:\n%*s",
727
0
        indent, "", indent + 2, "");
728
0
    X509_NAME_print_ex(out, &ntmp, 0, XN_FLAG_ONELINE);
729
0
    BIO_puts(out, "\n");
730
0
  }
731
0
  return 1;
732
0
}
733
734
static int
735
i2r_idp(const X509V3_EXT_METHOD *method, void *pidp, BIO *out, int indent)
736
0
{
737
0
  ISSUING_DIST_POINT *idp = pidp;
738
739
0
  if (idp->distpoint)
740
0
    print_distpoint(out, idp->distpoint, indent);
741
0
  if (idp->onlyuser > 0)
742
0
    BIO_printf(out, "%*sOnly User Certificates\n", indent, "");
743
0
  if (idp->onlyCA > 0)
744
0
    BIO_printf(out, "%*sOnly CA Certificates\n", indent, "");
745
0
  if (idp->indirectCRL > 0)
746
0
    BIO_printf(out, "%*sIndirect CRL\n", indent, "");
747
0
  if (idp->onlysomereasons)
748
0
    print_reasons(out, "Only Some Reasons",
749
0
      idp->onlysomereasons, indent);
750
0
  if (idp->onlyattr > 0)
751
0
    BIO_printf(out, "%*sOnly Attribute Certificates\n", indent, "");
752
0
  if (!idp->distpoint && (idp->onlyuser <= 0) && (idp->onlyCA <= 0) &&
753
0
      (idp->indirectCRL <= 0) && !idp->onlysomereasons &&
754
0
      (idp->onlyattr <= 0))
755
0
    BIO_printf(out, "%*s<EMPTY>\n", indent, "");
756
757
0
  return 1;
758
0
}
759
760
static int
761
i2r_crldp(const X509V3_EXT_METHOD *method, void *pcrldp, BIO *out, int indent)
762
0
{
763
0
  STACK_OF(DIST_POINT) *crld = pcrldp;
764
0
  DIST_POINT *point;
765
0
  int i;
766
767
0
  for (i = 0; i < sk_DIST_POINT_num(crld); i++) {
768
0
    BIO_puts(out, "\n");
769
0
    point = sk_DIST_POINT_value(crld, i);
770
0
    if (point->distpoint)
771
0
      print_distpoint(out, point->distpoint, indent);
772
0
    if (point->reasons)
773
0
      print_reasons(out, "Reasons", point->reasons,
774
0
        indent);
775
0
    if (point->CRLissuer) {
776
0
      BIO_printf(out, "%*sCRL Issuer:\n", indent, "");
777
0
      print_gens(out, point->CRLissuer, indent);
778
0
    }
779
0
  }
780
0
  return 1;
781
0
}
782
783
int
784
DIST_POINT_set_dpname(DIST_POINT_NAME *dpn, X509_NAME *iname)
785
0
{
786
0
  int i;
787
0
  STACK_OF(X509_NAME_ENTRY) *frag;
788
0
  X509_NAME_ENTRY *ne;
789
790
0
  if (!dpn || (dpn->type != 1))
791
0
    return 1;
792
0
  frag = dpn->name.relativename;
793
0
  dpn->dpname = X509_NAME_dup(iname);
794
0
  if (!dpn->dpname)
795
0
    return 0;
796
0
  for (i = 0; i < sk_X509_NAME_ENTRY_num(frag); i++) {
797
0
    ne = sk_X509_NAME_ENTRY_value(frag, i);
798
0
    if (!X509_NAME_add_entry(dpn->dpname, ne, -1, i ? 0 : 1)) {
799
0
      X509_NAME_free(dpn->dpname);
800
0
      dpn->dpname = NULL;
801
0
      return 0;
802
0
    }
803
0
  }
804
  /* generate cached encoding of name */
805
0
  if (i2d_X509_NAME(dpn->dpname, NULL) < 0) {
806
0
    X509_NAME_free(dpn->dpname);
807
0
    dpn->dpname = NULL;
808
0
    return 0;
809
0
  }
810
0
  return 1;
811
0
}