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 #define SET_HOST 0
80 #define ADD_HOST 1
81
82 static void
str_free(char * s)83 str_free(char *s)
84 {
85 free(s);
86 }
87
88 #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 *
sk_deep_copy(void * sk_void,void * copy_func_void,void * free_func_void)99 sk_deep_copy(void *sk_void, void *copy_func_void, void *free_func_void)
100 {
101 _STACK *sk = sk_void;
102 void *(*copy_func)(void *) = copy_func_void;
103 void (*free_func)(void *) = free_func_void;
104 _STACK *ret = sk_dup(sk);
105 size_t i;
106
107 if (ret == NULL)
108 return NULL;
109
110 for (i = 0; i < ret->num; i++) {
111 if (ret->data[i] == NULL)
112 continue;
113 ret->data[i] = copy_func(ret->data[i]);
114 if (ret->data[i] == NULL) {
115 size_t j;
116 for (j = 0; j < i; j++) {
117 if (ret->data[j] != NULL)
118 free_func(ret->data[j]);
119 }
120 sk_free(ret);
121 return NULL;
122 }
123 }
124
125 return ret;
126 }
127
128 static int
x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID * id,int mode,const char * name,size_t namelen)129 x509_param_set_hosts_internal(X509_VERIFY_PARAM_ID *id, int mode,
130 const char *name, size_t namelen)
131 {
132 char *copy;
133
134 if (name != NULL && namelen == 0)
135 namelen = strlen(name);
136 /*
137 * Refuse names with embedded NUL bytes.
138 */
139 if (name && memchr(name, '\0', namelen))
140 return 0;
141
142 if (mode == SET_HOST && id->hosts) {
143 string_stack_free(id->hosts);
144 id->hosts = NULL;
145 }
146 if (name == NULL || namelen == 0)
147 return 1;
148 copy = strndup(name, namelen);
149 if (copy == NULL)
150 return 0;
151
152 if (id->hosts == NULL &&
153 (id->hosts = sk_OPENSSL_STRING_new_null()) == NULL) {
154 free(copy);
155 return 0;
156 }
157
158 if (!sk_OPENSSL_STRING_push(id->hosts, copy)) {
159 free(copy);
160 if (sk_OPENSSL_STRING_num(id->hosts) == 0) {
161 sk_OPENSSL_STRING_free(id->hosts);
162 id->hosts = NULL;
163 }
164 return 0;
165 }
166
167 return 1;
168 }
169
170 static void
x509_verify_param_zero(X509_VERIFY_PARAM * param)171 x509_verify_param_zero(X509_VERIFY_PARAM *param)
172 {
173 X509_VERIFY_PARAM_ID *paramid;
174 if (!param)
175 return;
176 free(param->name);
177 param->name = NULL;
178 param->purpose = 0;
179 param->trust = 0;
180 /*param->inh_flags = X509_VP_FLAG_DEFAULT;*/
181 param->inh_flags = 0;
182 param->flags = 0;
183 param->depth = -1;
184 if (param->policies) {
185 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
186 param->policies = NULL;
187 }
188 paramid = param->id;
189 if (paramid->hosts) {
190 string_stack_free(paramid->hosts);
191 paramid->hosts = NULL;
192 }
193 free(paramid->peername);
194 paramid->peername = NULL;
195 free(paramid->email);
196 paramid->email = NULL;
197 paramid->emaillen = 0;
198 free(paramid->ip);
199 paramid->ip = NULL;
200 paramid->iplen = 0;
201 paramid->poisoned = 0;
202 }
203
204 X509_VERIFY_PARAM *
X509_VERIFY_PARAM_new(void)205 X509_VERIFY_PARAM_new(void)
206 {
207 X509_VERIFY_PARAM *param;
208 X509_VERIFY_PARAM_ID *paramid;
209 param = calloc(1, sizeof(X509_VERIFY_PARAM));
210 if (param == NULL)
211 return NULL;
212 paramid = calloc(1, sizeof(X509_VERIFY_PARAM_ID));
213 if (paramid == NULL) {
214 free(param);
215 return NULL;
216 }
217 param->id = paramid;
218 x509_verify_param_zero(param);
219 return param;
220 }
221
222 void
X509_VERIFY_PARAM_free(X509_VERIFY_PARAM * param)223 X509_VERIFY_PARAM_free(X509_VERIFY_PARAM *param)
224 {
225 if (param == NULL)
226 return;
227 x509_verify_param_zero(param);
228 free(param->id);
229 free(param);
230 }
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 (to_overwrite || \
268 ((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 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 if (test_x509_verify_param_copy(field, def)) \
279 dest->field = src->field
280
281 int
X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM * dest,const X509_VERIFY_PARAM * src)282 X509_VERIFY_PARAM_inherit(X509_VERIFY_PARAM *dest, const X509_VERIFY_PARAM *src)
283 {
284 unsigned long inh_flags;
285 int to_default, to_overwrite;
286 X509_VERIFY_PARAM_ID *id;
287
288 if (!src)
289 return 1;
290 id = src->id;
291 inh_flags = dest->inh_flags | src->inh_flags;
292
293 if (inh_flags & X509_VP_FLAG_ONCE)
294 dest->inh_flags = 0;
295
296 if (inh_flags & X509_VP_FLAG_LOCKED)
297 return 1;
298
299 if (inh_flags & X509_VP_FLAG_DEFAULT)
300 to_default = 1;
301 else
302 to_default = 0;
303
304 if (inh_flags & X509_VP_FLAG_OVERWRITE)
305 to_overwrite = 1;
306 else
307 to_overwrite = 0;
308
309 x509_verify_param_copy(purpose, 0);
310 x509_verify_param_copy(trust, 0);
311 x509_verify_param_copy(depth, -1);
312
313 /* If overwrite or check time not set, copy across */
314
315 if (to_overwrite || !(dest->flags & X509_V_FLAG_USE_CHECK_TIME)) {
316 dest->check_time = src->check_time;
317 dest->flags &= ~X509_V_FLAG_USE_CHECK_TIME;
318 /* Don't need to copy flag: that is done below */
319 }
320
321 if (inh_flags & X509_VP_FLAG_RESET_FLAGS)
322 dest->flags = 0;
323
324 dest->flags |= src->flags;
325
326 if (test_x509_verify_param_copy(policies, NULL)) {
327 if (!X509_VERIFY_PARAM_set1_policies(dest, src->policies))
328 return 0;
329 }
330
331 /* Copy the host flags if and only if we're copying the host list */
332 if (test_x509_verify_param_copy_id(hosts, NULL)) {
333 if (dest->id->hosts) {
334 string_stack_free(dest->id->hosts);
335 dest->id->hosts = NULL;
336 }
337 if (id->hosts) {
338 dest->id->hosts =
339 sk_deep_copy(id->hosts, strdup, str_free);
340 if (dest->id->hosts == NULL)
341 return 0;
342 dest->id->hostflags = id->hostflags;
343 }
344 }
345
346 if (test_x509_verify_param_copy_id(email, NULL)) {
347 if (!X509_VERIFY_PARAM_set1_email(dest, id->email,
348 id->emaillen))
349 return 0;
350 }
351
352 if (test_x509_verify_param_copy_id(ip, NULL)) {
353 if (!X509_VERIFY_PARAM_set1_ip(dest, id->ip, id->iplen))
354 return 0;
355 }
356
357 return 1;
358 }
359
360 int
X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM * to,const X509_VERIFY_PARAM * from)361 X509_VERIFY_PARAM_set1(X509_VERIFY_PARAM *to, const X509_VERIFY_PARAM *from)
362 {
363 unsigned long save_flags = to->inh_flags;
364 int ret;
365
366 to->inh_flags |= X509_VP_FLAG_DEFAULT;
367 ret = X509_VERIFY_PARAM_inherit(to, from);
368 to->inh_flags = save_flags;
369 return ret;
370 }
371
372 static int
x509_param_set1_internal(char ** pdest,size_t * pdestlen,const char * src,size_t srclen,int nonul)373 x509_param_set1_internal(char **pdest, size_t *pdestlen, const char *src,
374 size_t srclen, int nonul)
375 {
376 char *tmp;
377
378 if (src == NULL)
379 return 0;
380
381 if (srclen == 0) {
382 srclen = strlen(src);
383 if (srclen == 0)
384 return 0;
385 if ((tmp = strdup(src)) == NULL)
386 return 0;
387 } else {
388 if (nonul && memchr(src, '\0', srclen))
389 return 0;
390 if ((tmp = malloc(srclen)) == NULL)
391 return 0;
392 memcpy(tmp, src, srclen);
393 }
394
395 if (*pdest)
396 free(*pdest);
397 *pdest = tmp;
398 if (pdestlen)
399 *pdestlen = srclen;
400 return 1;
401 }
402
403 int
X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM * param,const char * name)404 X509_VERIFY_PARAM_set1_name(X509_VERIFY_PARAM *param, const char *name)
405 {
406 free(param->name);
407 param->name = NULL;
408 if (name == NULL)
409 return 1;
410 param->name = strdup(name);
411 if (param->name)
412 return 1;
413 return 0;
414 }
415
416 int
X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM * param,unsigned long flags)417 X509_VERIFY_PARAM_set_flags(X509_VERIFY_PARAM *param, unsigned long flags)
418 {
419 param->flags |= flags;
420 if (flags & X509_V_FLAG_POLICY_MASK)
421 param->flags |= X509_V_FLAG_POLICY_CHECK;
422 return 1;
423 }
424
425 int
X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM * param,unsigned long flags)426 X509_VERIFY_PARAM_clear_flags(X509_VERIFY_PARAM *param, unsigned long flags)
427 {
428 param->flags &= ~flags;
429 return 1;
430 }
431
432 unsigned long
X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM * param)433 X509_VERIFY_PARAM_get_flags(X509_VERIFY_PARAM *param)
434 {
435 return param->flags;
436 }
437
438 int
X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM * param,int purpose)439 X509_VERIFY_PARAM_set_purpose(X509_VERIFY_PARAM *param, int purpose)
440 {
441 return X509_PURPOSE_set(¶m->purpose, purpose);
442 }
443
444 int
X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM * param,int trust)445 X509_VERIFY_PARAM_set_trust(X509_VERIFY_PARAM *param, int trust)
446 {
447 return X509_TRUST_set(¶m->trust, trust);
448 }
449
450 void
X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM * param,int depth)451 X509_VERIFY_PARAM_set_depth(X509_VERIFY_PARAM *param, int depth)
452 {
453 param->depth = depth;
454 }
455
456 void
X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM * param,int auth_level)457 X509_VERIFY_PARAM_set_auth_level(X509_VERIFY_PARAM *param, int auth_level)
458 {
459 param->security_level = auth_level;
460 }
461
462 time_t
X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM * param)463 X509_VERIFY_PARAM_get_time(const X509_VERIFY_PARAM *param)
464 {
465 return param->check_time;
466 }
467
468 void
X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM * param,time_t t)469 X509_VERIFY_PARAM_set_time(X509_VERIFY_PARAM *param, time_t t)
470 {
471 param->check_time = t;
472 param->flags |= X509_V_FLAG_USE_CHECK_TIME;
473 }
474
475 int
X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM * param,ASN1_OBJECT * policy)476 X509_VERIFY_PARAM_add0_policy(X509_VERIFY_PARAM *param, ASN1_OBJECT *policy)
477 {
478 if (!param->policies) {
479 param->policies = sk_ASN1_OBJECT_new_null();
480 if (!param->policies)
481 return 0;
482 }
483 if (!sk_ASN1_OBJECT_push(param->policies, policy))
484 return 0;
485 return 1;
486 }
487
488 int
X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM * param,STACK_OF (ASN1_OBJECT)* policies)489 X509_VERIFY_PARAM_set1_policies(X509_VERIFY_PARAM *param,
490 STACK_OF(ASN1_OBJECT) *policies)
491 {
492 int i;
493 ASN1_OBJECT *oid, *doid;
494
495 if (!param)
496 return 0;
497 if (param->policies)
498 sk_ASN1_OBJECT_pop_free(param->policies, ASN1_OBJECT_free);
499
500 if (!policies) {
501 param->policies = NULL;
502 return 1;
503 }
504
505 param->policies = sk_ASN1_OBJECT_new_null();
506 if (!param->policies)
507 return 0;
508
509 for (i = 0; i < sk_ASN1_OBJECT_num(policies); i++) {
510 oid = sk_ASN1_OBJECT_value(policies, i);
511 doid = OBJ_dup(oid);
512 if (!doid)
513 return 0;
514 if (!sk_ASN1_OBJECT_push(param->policies, doid)) {
515 ASN1_OBJECT_free(doid);
516 return 0;
517 }
518 }
519 param->flags |= X509_V_FLAG_POLICY_CHECK;
520 return 1;
521 }
522
523 int
X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)524 X509_VERIFY_PARAM_set1_host(X509_VERIFY_PARAM *param,
525 const char *name, size_t namelen)
526 {
527 if (x509_param_set_hosts_internal(param->id, SET_HOST, name, namelen))
528 return 1;
529 param->id->poisoned = 1;
530 return 0;
531 }
532
533 int
X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM * param,const char * name,size_t namelen)534 X509_VERIFY_PARAM_add1_host(X509_VERIFY_PARAM *param,
535 const char *name, size_t namelen)
536 {
537 if (x509_param_set_hosts_internal(param->id, ADD_HOST, name, namelen))
538 return 1;
539 param->id->poisoned = 1;
540 return 0;
541 }
542
543 void
X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM * param,unsigned int flags)544 X509_VERIFY_PARAM_set_hostflags(X509_VERIFY_PARAM *param, unsigned int flags)
545 {
546 param->id->hostflags = flags;
547 }
548
549 char *
X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM * param)550 X509_VERIFY_PARAM_get0_peername(X509_VERIFY_PARAM *param)
551 {
552 return param->id->peername;
553 }
554
555 int
X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM * param,const char * email,size_t emaillen)556 X509_VERIFY_PARAM_set1_email(X509_VERIFY_PARAM *param, const char *email,
557 size_t emaillen)
558 {
559 if (x509_param_set1_internal(¶m->id->email, ¶m->id->emaillen,
560 email, emaillen, 1))
561 return 1;
562 param->id->poisoned = 1;
563 return 0;
564 }
565
566 int
X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM * param,const unsigned char * ip,size_t iplen)567 X509_VERIFY_PARAM_set1_ip(X509_VERIFY_PARAM *param, const unsigned char *ip,
568 size_t iplen)
569 {
570 if (iplen != 4 && iplen != 16)
571 goto err;
572 if (x509_param_set1_internal((char **)¶m->id->ip, ¶m->id->iplen,
573 (char *)ip, iplen, 0))
574 return 1;
575 err:
576 param->id->poisoned = 1;
577 return 0;
578 }
579
580 int
X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM * param,const char * ipasc)581 X509_VERIFY_PARAM_set1_ip_asc(X509_VERIFY_PARAM *param, const char *ipasc)
582 {
583 unsigned char ipout[16];
584 size_t iplen;
585
586 iplen = (size_t)a2i_ipadd(ipout, ipasc);
587 return X509_VERIFY_PARAM_set1_ip(param, ipout, iplen);
588 }
589
590 int
X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM * param)591 X509_VERIFY_PARAM_get_depth(const X509_VERIFY_PARAM *param)
592 {
593 return param->depth;
594 }
595
596 const char *
X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM * param)597 X509_VERIFY_PARAM_get0_name(const X509_VERIFY_PARAM *param)
598 {
599 return param->name;
600 }
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
param_cmp(const X509_VERIFY_PARAM * const * a,const X509_VERIFY_PARAM * const * b)652 param_cmp(const X509_VERIFY_PARAM * const *a,
653 const X509_VERIFY_PARAM * const *b)
654 {
655 return strcmp((*a)->name, (*b)->name);
656 }
657
658 int
X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM * param)659 X509_VERIFY_PARAM_add0_table(X509_VERIFY_PARAM *param)
660 {
661 X509_VERIFY_PARAM *ptmp;
662 if (!param_table) {
663 param_table = sk_X509_VERIFY_PARAM_new(param_cmp);
664 if (!param_table)
665 return 0;
666 } else {
667 size_t idx;
668
669 if ((idx = sk_X509_VERIFY_PARAM_find(param_table, param))
670 != -1) {
671 ptmp = sk_X509_VERIFY_PARAM_value(param_table,
672 idx);
673 X509_VERIFY_PARAM_free(ptmp);
674 (void)sk_X509_VERIFY_PARAM_delete(param_table,
675 idx);
676 }
677 }
678 if (!sk_X509_VERIFY_PARAM_push(param_table, param))
679 return 0;
680 return 1;
681 }
682
683 int
X509_VERIFY_PARAM_get_count(void)684 X509_VERIFY_PARAM_get_count(void)
685 {
686 int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
687 if (param_table)
688 num += sk_X509_VERIFY_PARAM_num(param_table);
689 return num;
690 }
691
692 const X509_VERIFY_PARAM *
X509_VERIFY_PARAM_get0(int id)693 X509_VERIFY_PARAM_get0(int id)
694 {
695 int num = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
696 if (id < num)
697 return default_table + id;
698 return sk_X509_VERIFY_PARAM_value(param_table, id - num);
699 }
700
701 const X509_VERIFY_PARAM *
X509_VERIFY_PARAM_lookup(const char * name)702 X509_VERIFY_PARAM_lookup(const char *name)
703 {
704 X509_VERIFY_PARAM pm;
705 unsigned int i, limit;
706
707 pm.name = (char *)name;
708 if (param_table) {
709 size_t idx;
710 if ((idx = sk_X509_VERIFY_PARAM_find(param_table, &pm)) != -1)
711 return sk_X509_VERIFY_PARAM_value(param_table, idx);
712 }
713
714 limit = sizeof(default_table) / sizeof(X509_VERIFY_PARAM);
715 for (i = 0; i < limit; i++) {
716 if (strcmp(default_table[i].name, name) == 0) {
717 return &default_table[i];
718 }
719 }
720 return NULL;
721 }
722
723 void
X509_VERIFY_PARAM_table_cleanup(void)724 X509_VERIFY_PARAM_table_cleanup(void)
725 {
726 if (param_table)
727 sk_X509_VERIFY_PARAM_pop_free(param_table,
728 X509_VERIFY_PARAM_free);
729 param_table = NULL;
730 }
731