Coverage Report

Created: 2022-08-24 06:30

/src/libressl/crypto/x509/x509_vpm.c
Line
Count
Source (jump to first uncovered line)
1
/* $OpenBSD: x509_vpm.c,v 1.30 2022/07/04 12:17:32 tb Exp $ */
2
/* Written by Dr Stephen N Henson (steve@openssl.org) for the OpenSSL
3
 * project 2004.
4
 */
5
/* ====================================================================
6
 * Copyright (c) 2004 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/buffer.h>
63
#include <openssl/crypto.h>
64
#include <openssl/lhash.h>
65
#include <openssl/stack.h>
66
#include <openssl/x509.h>
67
#include <openssl/x509v3.h>
68
69
#include "vpm_int.h"
70
#include "x509_lcl.h"
71
72
/* X509_VERIFY_PARAM functions */
73
74
int X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
75
    size_t emaillen);
76
int X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
77
    size_t iplen);
78
79
0
#define SET_HOST 0
80
0
#define ADD_HOST 1
81
82
static void
83
str_free(char *s)
84
0
{
85
0
    free(s);
86
0
}
87
88
0
#define string_stack_free(sk) sk_OPENSSL_STRING_pop_free(sk, str_free)
89
90
91
/*
92
 * Post 1.0.1 sk function "deep_copy".  For the moment we simply make
93
 * these take void * and use them directly without a glorious blob of
94
 * obfuscating macros of dubious value in front of them. All this in
95
 * preparation for a rototilling of safestack.h (likely inspired by
96
 * this).
97
 */
98
static void *
99
sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
100
0
{
101
0
  _STACK *sk = sk_void;
102
0
  void *(*copy_func)(void *) = copy_func_void;
103
0
  void (*free_func)(void *) = free_func_void;
104
0
  _STACK *ret = sk_dup(sk);
105
0
  size_t i;
106
107
0
  if (ret == NULL)
108
0
    return NULL;
109
110
0
  for (i = 0; i < ret->num; i++) {
111
0
    if (ret->data[i] == NULL)
112
0
      continue;
113
0
    ret->data[i] = copy_func(ret->data[i]);
114
0
    if (ret->data[i] == NULL) {
115
0
      size_t j;
116
0
      for (j = 0; j < i; j++) {
117
0
        if (ret->data[j] != NULL)
118
0
          free_func(ret->data[j]);
119
0
      }
120
0
      sk_free(ret);
121
0
      return NULL;
122
0
    }
123
0
  }
124
125
0
  return ret;
126
0
}
127
128
static int
129
x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID *id, int mode,
130
    const char *name, size_t namelen)
131
0
{
132
0
  char *copy;
133
134
0
  if (name != NULL && namelen == 0)
135
0
    namelen = strlen(name);
136
  /*
137
   * Refuse names with embedded NUL bytes.
138
   */
139
0
  if (name && memchr(name, '\0', namelen))
140
0
    return 0;
141
142
0
  if (mode == SET_HOST && id->hosts) {
143
0
    string_stack_free(id->hosts);
144
0
    id->hosts = NULL;
145
0
  }
146
0
  if (name == NULL || namelen == 0)
147
0
    return 1;
148
0
  copy = strndup(name, namelen);
149
0
  if (copy == NULL)
150
0
    return 0;
151
152
0
  if (id->hosts == NULL &&
153
0
      (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
154
0
    free(copy);
155
0
    return 0;
156
0
  }
157
158
0
  if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
159
0
    free(copy);
160
0
    if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
161
0
      sk_OPENSSL_STRING_free(id->hosts);
162
0
      id->hosts = NULL;
163
0
    }
164
0
    return 0;
165
0
  }
166
167
0
  return 1;
168
0
}
169
170
static void
171
x509_verify_param_zero(X509_VERIFY_PARAM *param)
172
0
{
173
0
  X509_VERIFY_PARAM_ID *paramid;
174
0
  if (!param)
175
0
    return;
176
0
  free(param->name);
177
0
  param->name = NULL;
178
0
  param->purpose = 0;
179
0
  param->trust = 0;
180
  /*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
181
0
  param->inh_flags = 0;
182
0
  param->flags = 0;
183
0
  param->depth = -1;
184
0
  if (param->policies) {
185
0
    sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
186
0
    param->policies = NULL;
187
0
  }
188
0
  paramid = param->id;
189
0
  if (paramid->hosts) {
190
0
    string_stack_free(paramid->hosts);
191
0
    paramid->hosts = NULL;
192
0
  }
193
0
  free(paramid->peername);
194
0
  paramid->peername = NULL;
195
0
  free(paramid->email);
196
0
  paramid->email = NULL;
197
0
  paramid->emaillen = 0;
198
0
  free(paramid->ip);
199
0
  paramid->ip = NULL;
200
0
  paramid->iplen = 0;
201
0
  paramid->poisoned = 0;
202
0
}
203
204
X509_VERIFY_PARAM *
205
X509_VERIFY_PARAM_new(void)
206
0
{
207
0
  X509_VERIFY_PARAM *param;
208
0
  X509_VERIFY_PARAM_ID *paramid;
209
0
  param = calloc(1, sizeof(X509_VERIFY_PARAM));
210
0
  if (param == NULL)
211
0
    return NULL;
212
0
  paramid = calloc(1, sizeof(X509_VERIFY_PARAM_ID));
213
0
  if (paramid == NULL) {
214
0
    free(param);
215
0
    return NULL;
216
0
  }
217
0
  param->id = paramid;
218
0
  x509_verify_param_zero(param);
219
0
  return param;
220
0
}
221
222
void
223
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
224
0
{
225
0
  if (param == NULL)
226
0
    return;
227
0
  x509_verify_param_zero(param);
228
0
  free(param->id);
229
0
  free(param);
230
0
}
231
232
/*
233
 * This function determines how parameters are "inherited" from one structure
234
 * to another. There are several different ways this can happen.
235
 *
236
 * 1. If a child structure needs to have its values initialized from a parent
237
 *    they are simply copied across. For example SSL_CTX copied to SSL.
238
 * 2. If the structure should take on values only if they are currently unset.
239
 *    For example the values in an SSL structure will take appropriate value
240
 *    for SSL servers or clients but only if the application has not set new
241
 *    ones.
242
 *
243
 * The "inh_flags" field determines how this function behaves.
244
 *
245
 * Normally any values which are set in the default are not copied from the
246
 * destination and verify flags are ORed together.
247
 *
248
 * If X509_VP_FLAG_DEFAULT is set then anything set in the source is copied
249
 * to the destination. Effectively the values in "to" become default values
250
 * which will be used only if nothing new is set in "from".
251
 *
252
 * If X509_VP_FLAG_OVERWRITE is set then all value are copied across whether
253
 * they are set or not. Flags is still Ored though.
254
 *
255
 * If X509_VP_FLAG_RESET_FLAGS is set then the flags value is copied instead
256
 * of ORed.
257
 *
258
 * If X509_VP_FLAG_LOCKED is set then no values are copied.
259
 *
260
 * If X509_VP_FLAG_ONCE is set then the current inh_flags setting is zeroed
261
 * after the next call.
262
 */
263
264
/* Macro to test if a field should be copied from src to dest */
265
266
#define test_x509_verify_param_copy(field, def) \
267
0
  (to_overwrite || \
268
0
    ((src->field != def) && (to_default || (dest->field == def))))
269
270
/* As above but for ID fields */
271
272
#define test_x509_verify_param_copy_id(idf, def) \
273
0
  test_x509_verify_param_copy(id->idf, def)
274
275
/* Macro to test and copy a field if necessary */
276
277
#define x509_verify_param_copy(field, def) \
278
0
  if (test_x509_verify_param_copy(field, def)) \
279
0
    dest->field = src->field
280
281
int
282
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, const X509_VERIFY_PARAM *src)
283
0
{
284
0
  unsigned long inh_flags;
285
0
  int to_default, to_overwrite;
286
0
  X509_VERIFY_PARAM_ID *id;
287
288
0
  if (!src)
289
0
    return 1;
290
0
  id = src->id;
291
0
  inh_flags = dest->inh_flags | src->inh_flags;
292
293
0
  if (inh_flags & X509_VP_FLAG_ONCE)
294
0
    dest->inh_flags = 0;
295
296
0
  if (inh_flags & X509_VP_FLAG_LOCKED)
297
0
    return 1;
298
299
0
  if (inh_flags & X509_VP_FLAG_DEFAULT)
300
0
    to_default = 1;
301
0
  else
302
0
    to_default = 0;
303
304
0
  if (inh_flags & X509_VP_FLAG_OVERWRITE)
305
0
    to_overwrite = 1;
306
0
  else
307
0
    to_overwrite = 0;
308
309
0
  x509_verify_param_copy(purpose, 0);
310
0
  x509_verify_param_copy(trust, 0);
311
0
  x509_verify_param_copy(depth, -1);
312
313
  /* If overwrite or check time not set, copy across */
314
315
0
  if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
316
0
    dest->check_time = src->check_time;
317
0
    dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
318
    /* Don't need to copy flag: that is done below */
319
0
  }
320
321
0
  if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
322
0
    dest->flags = 0;
323
324
0
  dest->flags |= src->flags;
325
326
0
  if (test_x509_verify_param_copy(policies, NULL)) {
327
0
    if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
328
0
      return 0;
329
0
  }
330
331
  /* Copy the host flags if and only if we're copying the host list */
332
0
  if (test_x509_verify_param_copy_id(hosts, NULL)) {
333
0
    if (dest->id->hosts) {
334
0
      string_stack_free(dest->id->hosts);
335
0
      dest->id->hosts = NULL;
336
0
    }
337
0
    if (id->hosts) {
338
0
      dest->id->hosts =
339
0
          sk_deep_copy(id->hosts, strdup, str_free);
340
0
      if (dest->id->hosts == NULL)
341
0
        return 0;
342
0
      dest->id->hostflags = id->hostflags;
343
0
    }
344
0
  }
345
346
0
  if (test_x509_verify_param_copy_id(email, NULL)) {
347
0
    if (!X509_VERIFY_PARAM_set1_email(dest, id->email,
348
0
        id->emaillen))
349
0
      return 0;
350
0
  }
351
352
0
  if (test_x509_verify_param_copy_id(ip, NULL)) {
353
0
    if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
354
0
      return 0;
355
0
  }
356
357
0
  return 1;
358
0
}
359
360
int
361
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
362
0
{
363
0
  unsigned long save_flags = to->inh_flags;
364
0
  int ret;
365
366
0
  to->inh_flags |= X509_VP_FLAG_DEFAULT;
367
0
  ret = X509_VERIFY_PARAM_inherit(to, from);
368
0
  to->inh_flags = save_flags;
369
0
  return ret;
370
0
}
371
372
static int
373
x509_param_set1_internal(char **pdest, size_t *pdestlen,  const char *src,
374
    size_t srclen, int nonul)
375
0
{
376
0
  char *tmp;
377
378
0
  if (src == NULL)
379
0
    return 0;
380
381
0
  if (srclen == 0) {
382
0
    srclen = strlen(src);
383
0
    if (srclen == 0)
384
0
      return 0;
385
0
    if ((tmp = strdup(src)) == NULL)
386
0
      return 0;
387
0
  } else {
388
0
    if (nonul && memchr(src, '\0', srclen))
389
0
      return 0;
390
0
    if ((tmp = malloc(srclen)) == NULL)
391
0
      return 0;
392
0
    memcpy(tmp, src, srclen);
393
0
  }
394
395
0
  if (*pdest)
396
0
    free(*pdest);
397
0
  *pdest = tmp;
398
0
  if (pdestlen)
399
0
    *pdestlen = srclen;
400
0
  return 1;
401
0
}
402
403
int
404
X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
405
0
{
406
0
  free(param->name);
407
0
  param->name = NULL;
408
0
  if (name == NULL)
409
0
    return 1;
410
0
  param->name = strdup(name);
411
0
  if (param->name)
412
0
    return 1;
413
0
  return 0;
414
0
}
415
416
int
417
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
418
0
{
419
0
  param->flags |= flags;
420
0
  if (flags & X509_V_FLAG_POLICY_MASK)
421
0
    param->flags |= X509_V_FLAG_POLICY_CHECK;
422
0
  return 1;
423
0
}
424
425
int
426
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
427
0
{
428
0
  param->flags &= ~flags;
429
0
  return 1;
430
0
}
431
432
unsigned long
433
X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
434
0
{
435
0
  return param->flags;
436
0
}
437
438
int
439
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
440
0
{
441
0
  return X509_PURPOSE_set(&param->purpose, purpose);
442
0
}
443
444
int
445
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
446
0
{
447
0
  return X509_TRUST_set(&param->trust, trust);
448
0
}
449
450
void
451
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
452
0
{
453
0
  param->depth = depth;
454
0
}
455
456
void
457
X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
458
0
{
459
0
  param->security_level = auth_level;
460
0
}
461
462
time_t
463
X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
464
0
{
465
0
  return param->check_time;
466
0
}
467
468
void
469
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
470
0
{
471
0
  param->check_time = t;
472
0
  param->flags |= X509_V_FLAG_USE_CHECK_TIME;
473
0
}
474
475
int
476
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
477
0
{
478
0
  if (!param->policies) {
479
0
    param->policies = sk_ASN1_OBJECT_new_null();
480
0
    if (!param->policies)
481
0
      return 0;
482
0
  }
483
0
  if (!sk_ASN1_OBJECT_push(param->policies, policy))
484
0
    return 0;
485
0
  return 1;
486
0
}
487
488
int
489
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
490
    STACK_OF(ASN1_OBJECT) *policies)
491
0
{
492
0
  int i;
493
0
  ASN1_OBJECT *oid, *doid;
494
495
0
  if (!param)
496
0
    return 0;
497
0
  if (param->policies)
498
0
    sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
499
500
0
  if (!policies) {
501
0
    param->policies = NULL;
502
0
    return 1;
503
0
  }
504
505
0
  param->policies = sk_ASN1_OBJECT_new_null();
506
0
  if (!param->policies)
507
0
    return 0;
508
509
0
  for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
510
0
    oid = sk_ASN1_OBJECT_value(policies, i);
511
0
    doid = OBJ_dup(oid);
512
0
    if (!doid)
513
0
      return 0;
514
0
    if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
515
0
      ASN1_OBJECT_free(doid);
516
0
      return 0;
517
0
    }
518
0
  }
519
0
  param->flags |= X509_V_FLAG_POLICY_CHECK;
520
0
  return 1;
521
0
}
522
523
int
524
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
525
    const char *name, size_t namelen)
526
0
{
527
0
  if (x509_param_set_hosts_internal(param->id, SET_HOST, name, namelen))
528
0
    return 1;
529
0
  param->id->poisoned = 1;
530
0
  return 0;
531
0
}
532
533
int
534
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
535
    const char *name, size_t namelen)
536
0
{
537
0
  if (x509_param_set_hosts_internal(param->id, ADD_HOST, name, namelen))
538
0
    return 1;
539
0
  param->id->poisoned = 1;
540
0
  return 0;
541
0
}
542
543
void
544
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags)
545
0
{
546
0
  param->id->hostflags = flags;
547
0
}
548
549
char *
550
X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
551
0
{
552
0
  return param->id->peername;
553
0
}
554
555
int
556
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param,  const char *email,
557
    size_t emaillen)
558
0
{
559
0
  if (x509_param_set1_internal(&param->id->email, &param->id->emaillen,
560
0
      email, emaillen, 1))
561
0
    return 1;
562
0
  param->id->poisoned = 1;
563
0
  return 0;
564
0
}
565
566
int
567
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
568
    size_t iplen)
569
0
{
570
0
  if (iplen != 4 && iplen != 16)
571
0
    goto err;
572
0
  if (x509_param_set1_internal((char **)&param->id->ip, &param->id->iplen,
573
0
    (char *)ip, iplen, 0))
574
0
    return 1;
575
0
 err:
576
0
  param->id->poisoned = 1;
577
0
  return 0;
578
0
}
579
580
int
581
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
582
0
{
583
0
  unsigned char ipout[16];
584
0
  size_t iplen;
585
586
0
  iplen = (size_t)a2i_ipadd(ipout, ipasc);
587
0
  return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
588
0
}
589
590
int
591
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
592
0
{
593
0
  return param->depth;
594
0
}
595
596
const char *
597
X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
598
0
{
599
0
  return param->name;
600
0
}
601
602
static const X509_VERIFY_PARAM_ID _empty_id = { NULL };
603
604
#define vpm_empty_id (X509_VERIFY_PARAM_ID *)&_empty_id
605
606
/*
607
 * Default verify parameters: these are used for various applications and can
608
 * be overridden by the user specified table.
609
 */
610
611
static const X509_VERIFY_PARAM default_table[] = {
612
  {
613
    .name = "default",
614
    .flags = X509_V_FLAG_TRUSTED_FIRST,
615
    .depth = 100,
616
    .trust = 0,  /* XXX This is not the default trust value */
617
    .id = vpm_empty_id
618
  },
619
  {
620
    .name = "pkcs7",
621
    .purpose = X509_PURPOSE_SMIME_SIGN,
622
    .trust = X509_TRUST_EMAIL,
623
    .depth = -1,
624
    .id = vpm_empty_id
625
  },
626
  {
627
    .name = "smime_sign",
628
    .purpose = X509_PURPOSE_SMIME_SIGN,
629
    .trust = X509_TRUST_EMAIL,
630
    .depth =  -1,
631
    .id = vpm_empty_id
632
  },
633
  {
634
    .name = "ssl_client",
635
    .purpose = X509_PURPOSE_SSL_CLIENT,
636
    .trust = X509_TRUST_SSL_CLIENT,
637
    .depth = -1,
638
    .id = vpm_empty_id
639
  },
640
  {
641
    .name = "ssl_server",
642
    .purpose = X509_PURPOSE_SSL_SERVER,
643
    .trust = X509_TRUST_SSL_SERVER,
644
    .depth = -1,
645
    .id = vpm_empty_id
646
  }
647
};
648
649
static STACK_OF(X509_VERIFY_PARAM) *param_table = NULL;
650
651
static int
652
param_cmp(const X509_VERIFY_PARAM * const *a,
653
    const X509_VERIFY_PARAM * const *b)
654
0
{
655
0
  return strcmp((*a)->name, (*b)->name);
656
0
}
657
658
int
659
X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
660
0
{
661
0
  X509_VERIFY_PARAM *ptmp;
662
0
  if (!param_table) {
663
0
    param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
664
0
    if (!param_table)
665
0
      return 0;
666
0
  } else {
667
0
    size_t idx;
668
669
0
    if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param))
670
0
        != -1) {
671
0
      ptmp = sk_X509_VERIFY_PARAM_value(param_table,
672
0
          idx);
673
0
      X509_VERIFY_PARAM_free(ptmp);
674
0
      (void)sk_X509_VERIFY_PARAM_delete(param_table,
675
0
          idx);
676
0
    }
677
0
  }
678
0
  if (!sk_X509_VERIFY_PARAM_push(param_table, param))
679
0
    return 0;
680
0
  return 1;
681
0
}
682
683
int
684
X509_VERIFY_PARAM_get_count(void)
685
0
{
686
0
  int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
687
0
  if (param_table)
688
0
    num += sk_X509_VERIFY_PARAM_num(param_table);
689
0
  return num;
690
0
}
691
692
const X509_VERIFY_PARAM *
693
X509_VERIFY_PARAM_get0(int id)
694
0
{
695
0
  int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
696
0
  if (id < num)
697
0
    return default_table + id;
698
0
  return sk_X509_VERIFY_PARAM_value(param_table, id - num);
699
0
}
700
701
const X509_VERIFY_PARAM *
702
X509_VERIFY_PARAM_lookup(const char *name)
703
0
{
704
0
  X509_VERIFY_PARAM pm;
705
0
  unsigned int i, limit;
706
707
0
  pm.name = (char *)name;
708
0
  if (param_table) {
709
0
    size_t idx;
710
0
    if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1)
711
0
      return sk_X509_VERIFY_PARAM_value(param_table, idx);
712
0
  }
713
714
0
  limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
715
0
  for (i = 0; i < limit; i++) {
716
0
    if (strcmp(default_table[i].name, name) == 0) {
717
0
      return &default_table[i];
718
0
    }
719
0
  }
720
0
  return NULL;
721
0
}
722
723
void
724
X509_VERIFY_PARAM_table_cleanup(void)
725
0
{
726
0
  if (param_table)
727
0
    sk_X509_VERIFY_PARAM_pop_free(param_table,
728
0
        X509_VERIFY_PARAM_free);
729
0
  param_table = NULL;
730
0
}