OpenVPN
ssl_verify_openssl.c
Go to the documentation of this file.
1/*
2 * OpenVPN -- An application to securely tunnel IP networks
3 * over a single TCP/UDP port, with support for SSL/TLS-based
4 * session authentication and key exchange,
5 * packet encryption, packet authentication, and
6 * packet compression.
7 *
8 * Copyright (C) 2002-2025 OpenVPN Inc <sales@openvpn.net>
9 * Copyright (C) 2010-2021 Fox Crypto B.V. <openvpn@foxcrypto.com>
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License version 2
13 * as published by the Free Software Foundation.
14 *
15 * This program is distributed in the hope that it will be useful,
16 * but WITHOUT ANY WARRANTY; without even the implied warranty of
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
18 * GNU General Public License for more details.
19 *
20 * You should have received a copy of the GNU General Public License along
21 * with this program; if not, see <https://www.gnu.org/licenses/>.
22 */
23
29#ifdef HAVE_CONFIG_H
30#include "config.h"
31#endif
32
33#include "syshead.h"
34
35#if defined(ENABLE_CRYPTO_OPENSSL)
36
37#include "ssl_verify_openssl.h"
38
39#include "error.h"
40#include "ssl_openssl.h"
41#include "ssl_verify.h"
42#include "ssl_verify_backend.h"
43#include "openssl_compat.h"
44
45#include <openssl/bn.h>
46#include <openssl/err.h>
47#include <openssl/x509v3.h>
48
49int
50verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
51{
52 int ret = 0;
53 struct tls_session *session;
54 SSL *ssl;
55 struct gc_arena gc = gc_new();
56
57 /* get the tls_session pointer */
58 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
59 ASSERT(ssl);
60 session = (struct tls_session *)SSL_get_ex_data(ssl, mydata_index);
62
63 X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
66
67 /* did peer present cert which was signed by our root cert? */
68 if (!preverify_ok && !session->opt->verify_hash_no_ca)
69 {
70 /* get the X509 name */
73
74 if (!subject)
75 {
76 subject = "(Failed to retrieve certificate subject)";
77 }
78
79 /* Log and ignore missing CRL errors */
81 {
82 msg(D_TLS_DEBUG_LOW, "VERIFY WARNING: depth=%d, %s: %s",
85 ret = 1;
86 goto cleanup;
87 }
88
89 /* Remote site specified a certificate, but it's not correct */
90 msg(D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s, serial=%s",
93 serial ? serial : "<not available>");
94
96
97 session->verified = false;
98 goto cleanup;
99 }
100
102 {
103 goto cleanup;
104 }
105
106 ret = 1;
107
108cleanup:
109 gc_free(&gc);
110
111 return ret;
112}
113
114#ifdef ENABLE_X509ALTUSERNAME
115bool
117{
118 int nid = OBJ_txt2nid(fieldname);
119 return nid == NID_subject_alt_name || nid == NID_issuer_alt_name;
120}
121
122static bool
123extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)
124{
125 bool retval = false;
126 char *buf = 0;
127
129 {
130 msg(D_TLS_ERRORS, "ERROR: --x509-username-field 'ext:%s' not supported", fieldname);
131 return false;
132 }
133
134 int nid = OBJ_txt2nid(fieldname);
136 if (extensions)
137 {
138 int numalts;
139 int i;
140 /* get amount of alternatives,
141 * RFC2459 claims there MUST be at least
142 * one, but we don't depend on it...
143 */
144
146
147 /* loop through all alternatives */
148 for (i = 0; i < numalts; i++)
149 {
150 /* get a handle to alternative name number i */
152
153 switch (name->type)
154 {
155 case GEN_EMAIL:
156 if (ASN1_STRING_to_UTF8((unsigned char **)&buf, name->d.ia5) < 0)
157 {
158 continue;
159 }
160 if (strlen(buf) != name->d.ia5->length)
161 {
162 msg(D_TLS_ERRORS, "ASN1 ERROR: string contained terminating zero");
163 OPENSSL_free(buf);
164 }
165 else
166 {
167 strncpynt(out, buf, size);
168 OPENSSL_free(buf);
169 retval = true;
170 }
171 break;
172
173 default:
174 msg(D_TLS_DEBUG, "%s: ignoring general name field type %i", __func__,
175 name->type);
176 break;
177 }
178 }
180 }
181 return retval;
182}
183#endif /* ENABLE_X509ALTUSERNAME */
184
185/*
186 * Extract a field from an X509 subject name.
187 *
188 * Example:
189 *
190 * /C=US/ST=CO/L=Denver/O=ORG/CN=First-CN/CN=Test-CA/Email=jim@yonan.net
191 *
192 * The common name is 'Test-CA'
193 *
194 * Return true on success, false on error (insufficient buffer size in 'out'
195 * to contain result is grounds for error).
196 */
197static result_t
198extract_x509_field_ssl(X509_NAME *x509, const char *field_name, char *out, int size)
199{
200 int lastpos = -1;
201 int tmp = -1;
204 unsigned char *buf = NULL;
206
207 if (field_name_obj == NULL)
208 {
209 msg(D_TLS_ERRORS, "Invalid X509 attribute name '%s'", field_name);
210 return FAILURE;
211 }
212
213 ASSERT(size > 0);
214 *out = '\0';
215 do
216 {
217 lastpos = tmp;
219 } while (tmp > -1);
220
222
223 /* Nothing found */
224 if (lastpos == -1)
225 {
226 return FAILURE;
227 }
228
230 if (!x509ne)
231 {
232 return FAILURE;
233 }
234
236 if (!asn1)
237 {
238 return FAILURE;
239 }
240 if (ASN1_STRING_to_UTF8(&buf, asn1) < 0)
241 {
242 return FAILURE;
243 }
244
245 strncpynt(out, (char *)buf, size);
246
247 {
248 const result_t ret = (strlen((char *)buf) < size) ? SUCCESS : FAILURE;
249 OPENSSL_free(buf);
250 return ret;
251 }
252}
253
255backend_x509_get_username(char *common_name, int cn_len, char *x509_username_field, X509 *peer_cert)
256{
257#ifdef ENABLE_X509ALTUSERNAME
258 if (strncmp("ext:", x509_username_field, 4) == 0)
259 {
260 if (!extract_x509_extension(peer_cert, x509_username_field + 4, common_name, cn_len))
261 {
262 return FAILURE;
263 }
264 }
265 else if (strcmp(LN_serialNumber, x509_username_field) == 0)
266 {
268 struct gc_arena gc = gc_new();
269 char *serial = format_hex_ex(asn1_i->data, asn1_i->length, 0, 1 | FHE_CAPS, NULL, &gc);
270
271 if (!serial || cn_len <= strlen(serial) + 2)
272 {
273 gc_free(&gc);
274 return FAILURE;
275 }
276 snprintf(common_name, cn_len, "0x%s", serial);
277 gc_free(&gc);
278 }
279 else
280#endif /* ifdef ENABLE_X509ALTUSERNAME */
281 if (FAILURE
282 == extract_x509_field_ssl(X509_get_subject_name(peer_cert), x509_username_field,
283 common_name, cn_len))
284 {
285 return FAILURE;
286 }
287
288 return SUCCESS;
289}
290
291char *
293{
294 ASN1_INTEGER *asn1_i;
295 BIGNUM *bignum;
296 char *openssl_serial, *serial;
297
298 asn1_i = X509_get_serialNumber(cert);
299 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
300 openssl_serial = BN_bn2dec(bignum);
301
302 serial = string_alloc(openssl_serial, gc);
303
304 BN_free(bignum);
305 OPENSSL_free(openssl_serial);
306
307 return serial;
308}
309
310char *
312{
313 const ASN1_INTEGER *asn1_i = X509_get_serialNumber(cert);
314
315 return format_hex_ex(asn1_i->data, asn1_i->length, 0, 1, ":", gc);
316}
317
319backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
320{
321 BIO *out = BIO_new_file(filename, "w");
322 if (!out)
323 {
324 goto err;
325 }
326
327 if (!PEM_write_bio_X509(out, cert))
328 {
329 goto err;
330 }
331 BIO_free(out);
332
333 return SUCCESS;
334err:
335 BIO_free(out);
336 crypto_msg(D_TLS_DEBUG_LOW, "Error writing X509 certificate to file %s", filename);
337 return FAILURE;
338}
339
340struct buffer
342{
343 const EVP_MD *sha1 = EVP_sha1();
345 X509_digest(cert, EVP_sha1(), BPTR(&hash), NULL);
347 return hash;
348}
349
350struct buffer
352{
353 const EVP_MD *sha256 = EVP_sha256();
355 X509_digest(cert, EVP_sha256(), BPTR(&hash), NULL);
357 return hash;
358}
359
360char *
362{
365 char *subject = NULL;
366
368 if (subject_bio == NULL)
369 {
370 goto err;
371 }
372
376
377 if (BIO_eof(subject_bio))
378 {
379 goto err;
380 }
381
383
384 subject = gc_malloc(subject_mem->length + 1, false, gc);
385
386 memcpy(subject, subject_mem->data, subject_mem->length);
387 subject[subject_mem->length] = '\0';
388
389err:
391 return subject;
392}
393
394
395/*
396 * x509-track implementation -- save X509 fields to environment,
397 * using the naming convention:
398 *
399 * X509_{cert_depth}_{name}={value}
400 *
401 * This function differs from x509_setenv below in the following ways:
402 *
403 * (1) Only explicitly named attributes in xt are saved, per usage
404 * of "x509-track" program options.
405 * (2) Only the level 0 cert info is saved unless the XT_FULL_CHAIN
406 * flag is set in xt->flags (corresponds with prepending a '+'
407 * to the name when specified by "x509-track" program option).
408 * (3) This function supports both X509 subject name fields as
409 * well as X509 V3 extensions.
410 * (4) This function can return the SHA1 fingerprint of a cert, e.g.
411 * x509-track "+SHA1"
412 * will return the SHA1 fingerprint for each certificate in the
413 * peer chain.
414 */
415
416void
417x509_track_add(const struct x509_track **ll_head, const char *name, int msglevel,
418 struct gc_arena *gc)
419{
420 struct x509_track *xt;
421 ALLOC_OBJ_CLEAR_GC(xt, struct x509_track, gc);
422 if (*name == '+')
423 {
424 xt->flags |= XT_FULL_CHAIN;
425 ++name;
426 }
427 xt->name = name;
428 xt->nid = OBJ_txt2nid(name);
429 if (xt->nid != NID_undef)
430 {
431 xt->next = *ll_head;
432 *ll_head = xt;
433 }
434 else
435 {
436 msg(msglevel, "x509_track: no such attribute '%s'", name);
437 }
438}
439
440/* worker method for setenv_x509_track */
441static void
442do_setenv_x509(struct env_set *es, const char *name, char *value, int depth)
443{
444 char *name_expand;
445 size_t name_expand_size;
446
447 string_mod(value, CC_ANY, CC_CRLF, '?');
448 msg(D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
449 name_expand_size = 64 + strlen(name);
450 name_expand = (char *)malloc(name_expand_size);
451 check_malloc_return(name_expand);
452 snprintf(name_expand, name_expand_size, "X509_%d_%s", depth, name);
453 setenv_str(es, name_expand, value);
454 free(name_expand);
455}
456
457void
458x509_setenv_track(const struct x509_track *xt, struct env_set *es, const int depth, X509 *x509)
459{
460 struct gc_arena gc = gc_new();
461 X509_NAME *x509_name = X509_get_subject_name(x509);
462 const char nullc = '\0';
463
464 while (xt)
465 {
466 if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
467 {
468 switch (xt->nid)
469 {
470 case NID_sha1:
471 case NID_sha256:
472 {
473 struct buffer fp_buf;
474 char *fp_str = NULL;
475
476 if (xt->nid == NID_sha1)
477 {
479 }
480 else
481 {
483 }
484
485 fp_str = format_hex_ex(BPTR(&fp_buf), BLEN(&fp_buf), 0, 1 | FHE_CAPS, ":", &gc);
486 do_setenv_x509(es, xt->name, fp_str, depth);
487 }
488 break;
489
490 default:
491 {
492 int i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
493 if (i >= 0)
494 {
496 if (ent)
497 {
499 unsigned char *buf = NULL;
500 if (ASN1_STRING_to_UTF8(&buf, val) >= 0)
501 {
502 do_setenv_x509(es, xt->name, (char *)buf, depth);
503 OPENSSL_free(buf);
504 }
505 }
506 }
507 else
508 {
509 i = X509_get_ext_by_NID(x509, xt->nid, -1);
510 if (i >= 0)
511 {
513 if (ext)
514 {
515 BIO *bio = BIO_new(BIO_s_mem());
516 if (bio)
517 {
518 if (X509V3_EXT_print(bio, ext, 0, 0))
519 {
520 if (BIO_write(bio, &nullc, 1) == 1)
521 {
522 char *str;
524 do_setenv_x509(es, xt->name, str, depth);
525 }
526 }
527 BIO_free(bio);
528 }
529 }
530 }
531 }
532 }
533 }
534 }
535 xt = xt->next;
536 }
537 gc_free(&gc);
538}
539
540/*
541 * Save X509 fields to environment, using the naming convention:
542 *
543 * X509_{cert_depth}_{name}={value}
544 */
545void
547{
548 int i, n;
549 int fn_nid;
551 ASN1_STRING *val;
553 const char *objbuf;
554 unsigned char *buf = NULL;
555 char *name_expand;
556 size_t name_expand_size;
558
560 for (i = 0; i < n; ++i)
561 {
563 if (!ent)
564 {
565 continue;
566 }
568 if (!fn)
569 {
570 continue;
571 }
573 if (!val)
574 {
575 continue;
576 }
578 if (fn_nid == NID_undef)
579 {
580 continue;
581 }
583 if (!objbuf)
584 {
585 continue;
586 }
587 if (ASN1_STRING_to_UTF8(&buf, val) < 0)
588 {
589 continue;
590 }
596 string_mod((char *)buf, CC_PRINT, CC_CRLF, '_');
597 setenv_str_incr(es, name_expand, (char *)buf);
598 free(name_expand);
599 OPENSSL_free(buf);
600 }
601}
602
605{
607 {
608 return SUCCESS;
609 }
611 {
612 /*
613 * Unfortunately, X509_check_purpose() does some weird thing that
614 * prevent it to take a const argument
615 */
618
619 /*
620 * old versions of OpenSSL allow us to make the less strict check we used to
621 * do. If this less strict check pass, warn user that this might not be the
622 * case when its distribution will update to OpenSSL 1.1
623 */
624 if (result == FAILURE)
625 {
628 result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_CLIENT)) ? SUCCESS : FAILURE;
629 if (result == SUCCESS)
630 {
631 msg(M_WARN, "X509: Certificate is a client certificate yet it's purpose "
632 "cannot be verified (check may fail in the future)");
633 }
635 }
636 return result;
637 }
639 {
640 /*
641 * Unfortunately, X509_check_purpose() does some weird thing that
642 * prevent it to take a const argument
643 */
646
647 /*
648 * old versions of OpenSSL allow us to make the less strict check we used to
649 * do. If this less strict check pass, warn user that this might not be the
650 * case when its distribution will update to OpenSSL 1.1
651 */
652 if (result == FAILURE)
653 {
656 result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_SERVER)) ? SUCCESS : FAILURE;
657 if (result == SUCCESS)
658 {
659 msg(M_WARN, "X509: Certificate is a server certificate yet it's purpose "
660 "cannot be verified (check may fail in the future)");
661 }
663 }
664 return result;
665 }
666
667 return FAILURE;
668}
669
672{
674
675 if (ku == NULL)
676 {
677 msg(D_TLS_ERRORS, "Certificate does not have key usage extension");
678 return FAILURE;
679 }
680
682 {
683 /* Extension required, value checked by TLS library */
685 return SUCCESS;
686 }
687
688 unsigned nku = 0;
689 for (size_t i = 0; i < 8; i++)
690 {
692 {
693 nku |= 1 << (7 - i);
694 }
695 }
696
697 /*
698 * Fixup if no LSB bits
699 */
700 if ((nku & 0xff) == 0)
701 {
702 nku >>= 8;
703 }
704
705 msg(D_HANDSHAKE, "Validating certificate key usage");
707 for (size_t i = 0; fFound != SUCCESS && i < expected_len; i++)
708 {
709 if (expected_ku[i] != 0 && (nku & expected_ku[i]) == expected_ku[i])
710 {
711 fFound = SUCCESS;
712 }
713 }
714
715 if (fFound != SUCCESS)
716 {
717 msg(D_TLS_ERRORS, "ERROR: Certificate has key usage %04x, expected one of:", nku);
718 for (size_t i = 0; i < expected_len && expected_ku[i]; i++)
719 {
720 msg(D_TLS_ERRORS, " * %04x", expected_ku[i]);
721 }
722 }
723
725
726 return fFound;
727}
728
731{
734
736 {
737 msg(D_HANDSHAKE, "Certificate does not have extended key usage extension");
738 }
739 else
740 {
741 int i;
742
743 msg(D_HANDSHAKE, "Validating certificate extended key usage");
744 for (i = 0; SUCCESS != fFound && i < sk_ASN1_OBJECT_num(eku); i++)
745 {
747 char szOid[1024];
748
749 if (SUCCESS != fFound && OBJ_obj2txt(szOid, sizeof(szOid), oid, 0) != -1)
750 {
751 msg(D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s", szOid,
754 {
755 fFound = SUCCESS;
756 }
757 }
758 if (SUCCESS != fFound && OBJ_obj2txt(szOid, sizeof(szOid), oid, 1) != -1)
759 {
760 msg(D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s", szOid,
763 {
764 fFound = SUCCESS;
765 }
766 }
767 }
768 }
769
770 if (eku != NULL)
771 {
773 }
774
775 return fFound;
776}
777
778bool
780{
781 if (!opt->crl_file || (opt->ssl_flags & SSLF_CRL_VERIFY_DIR))
782 {
783 return false;
784 }
785
787 if (!store)
788 {
789 crypto_msg(M_FATAL, "Cannot get certificate store");
790 }
791
793 for (int i = 0; i < sk_X509_OBJECT_num(objs); i++)
794 {
796 ASSERT(obj);
798 {
799 return false;
800 }
801 }
802 return true;
803}
804
805#endif /* defined(ENABLE_CRYPTO_OPENSSL) */
char * format_hex_ex(const uint8_t *data, int size, int maxoutput, unsigned int space_break_flags, const char *separator, struct gc_arena *gc)
Definition buffer.c:483
void * gc_malloc(size_t size, bool clear, struct gc_arena *a)
Definition buffer.c:336
struct buffer alloc_buf_gc(size_t size, struct gc_arena *gc)
Definition buffer.c:89
bool string_mod(char *str, const unsigned int inclusive, const unsigned int exclusive, const char replace)
Modifies a string in place by replacing certain classes of characters of it with a specified characte...
Definition buffer.c:1041
char * string_alloc(const char *str, struct gc_arena *gc)
Definition buffer.c:649
#define CC_ANY
any character
Definition buffer.h:867
#define BPTR(buf)
Definition buffer.h:123
static bool buf_inc_len(struct buffer *buf, int inc)
Definition buffer.h:588
#define CC_CRLF
carriage return or newline
Definition buffer.h:904
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1079
#define BLEN(buf)
Definition buffer.h:126
static void strncpynt(char *dest, const char *src, size_t maxlen)
Definition buffer.h:361
static void check_malloc_return(void *p)
Definition buffer.h:1085
static void gc_free(struct gc_arena *a)
Definition buffer.h:1015
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:875
#define FHE_CAPS
Definition buffer.h:498
static struct gc_arena gc_new(void)
Definition buffer.h:1007
#define crypto_msg(flags,...)
Retrieve any OpenSSL errors, then print the supplied error message.
void setenv_str(struct env_set *es, const char *name, const char *value)
Definition env_set.c:307
void setenv_str_incr(struct env_set *es, const char *name, const char *value)
Store the supplied name value pair in the env_set.
Definition env_set.c:329
#define D_TLS_DEBUG_LOW
Definition errlevel.h:76
#define D_X509_ATTR
Definition errlevel.h:102
#define D_HANDSHAKE
Definition errlevel.h:71
#define D_TLS_ERRORS
Definition errlevel.h:58
#define D_TLS_DEBUG
Definition errlevel.h:164
int verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
Verify that the remote OpenVPN peer's certificate allows setting up a VPN tunnel.
OpenSSL compatibility stub.
#define M_FATAL
Definition error.h:88
#define msg(flags,...)
Definition error.h:150
#define ASSERT(x)
Definition error.h:217
#define M_WARN
Definition error.h:90
static void usage(void)
Definition options.c:4833
#define SSLF_CRL_VERIFY_DIR
Definition ssl_common.h:429
int mydata_index
Allocate space in SSL objects in which to store a struct tls_session pointer back to parent.
Definition ssl_openssl.c:88
Control Channel OpenSSL Backend.
result_t verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_depth)
Definition ssl_verify.c:577
void cert_hash_remember(struct tls_session *session, const int error_depth, const struct buffer *cert_hash)
Definition ssl_verify.c:194
Control Channel Verification Module.
#define OPENVPN_KU_REQUIRED
Require keyUsage to be present in cert (0xFFFF is an invalid KU value)
Definition ssl_verify.h:257
#define XT_FULL_CHAIN
Definition ssl_verify.h:241
#define NS_CERT_CHECK_CLIENT
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:254
#define NS_CERT_CHECK_NONE
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:250
#define NS_CERT_CHECK_SERVER
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:252
Control Channel Verification Module library-specific backend interface.
result_t
Result of verification function.
@ FAILURE
@ SUCCESS
mbedtls_x509_crt openvpn_x509_cert_t
char * x509_get_subject(X509 *cert, struct gc_arena *gc)
static result_t extract_x509_field_ssl(X509_NAME *x509, const char *field_name, char *out, int size)
struct buffer x509_get_sha1_fingerprint(X509 *cert, struct gc_arena *gc)
result_t x509_verify_cert_ku(X509 *x509, const unsigned *const expected_ku, int expected_len)
bool tls_verify_crl_missing(const struct tls_options *opt)
Return true iff a CRL is configured, but is not loaded.
result_t backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
struct buffer x509_get_sha256_fingerprint(X509 *cert, struct gc_arena *gc)
result_t x509_verify_cert_eku(X509 *x509, const char *const expected_oid)
static void do_setenv_x509(struct env_set *es, const char *name, char *value, int depth)
char * backend_x509_get_serial_hex(openvpn_x509_cert_t *cert, struct gc_arena *gc)
result_t x509_verify_ns_cert_type(openvpn_x509_cert_t *peer_cert, const int usage)
void x509_setenv_track(const struct x509_track *xt, struct env_set *es, const int depth, X509 *x509)
char * backend_x509_get_serial(openvpn_x509_cert_t *cert, struct gc_arena *gc)
void x509_track_add(const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc)
result_t backend_x509_get_username(char *common_name, int cn_len, char *x509_username_field, X509 *peer_cert)
void x509_setenv(struct env_set *es, int cert_depth, openvpn_x509_cert_t *peer_cert)
Control Channel Verification Module OpenSSL backend.
Wrapper structure for dynamically allocated memory.
Definition buffer.h:60
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:65
Structure containing the hash for a single certificate.
Definition ssl_verify.h:58
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:116
Definition list.h:56
struct tls_root_ctx ssl_ctx
Definition ssl_common.h:309
unsigned int ssl_flags
Definition ssl_common.h:435
const char * crl_file
Definition ssl_common.h:354
SSL_CTX * ctx
Definition ssl_openssl.h:41
Security parameter state of a single session within a VPN tunnel.
Definition ssl_common.h:490
unsigned int flags
Definition ssl_verify.h:242
const struct x509_track * next
Definition ssl_verify.h:239
const char * name
Definition ssl_verify.h:240
struct env_set * es
static int cleanup(void **state)
struct gc_arena gc
Definition test_ssl.c:154