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-2024 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, write to the Free Software Foundation, Inc.,
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
23 */
24
30#ifdef HAVE_CONFIG_H
31#include "config.h"
32#endif
33
34#include "syshead.h"
35
36#if defined(ENABLE_CRYPTO_OPENSSL)
37
38#include "ssl_verify_openssl.h"
39
40#include "error.h"
41#include "ssl_openssl.h"
42#include "ssl_verify.h"
43#include "ssl_verify_backend.h"
44#include "openssl_compat.h"
45
46#include <openssl/bn.h>
47#include <openssl/err.h>
48#include <openssl/x509v3.h>
49
50int
51verify_callback(int preverify_ok, X509_STORE_CTX *ctx)
52{
53 int ret = 0;
54 struct tls_session *session;
55 SSL *ssl;
56 struct gc_arena gc = gc_new();
57
58 /* get the tls_session pointer */
59 ssl = X509_STORE_CTX_get_ex_data(ctx, SSL_get_ex_data_X509_STORE_CTX_idx());
60 ASSERT(ssl);
61 session = (struct tls_session *) SSL_get_ex_data(ssl, mydata_index);
63
64 X509 *current_cert = X509_STORE_CTX_get_current_cert(ctx);
67
68 /* did peer present cert which was signed by our root cert? */
69 if (!preverify_ok && !session->opt->verify_hash_no_ca)
70 {
71 /* get the X509 name */
74
75 if (!subject)
76 {
77 subject = "(Failed to retrieve certificate subject)";
78 }
79
80 /* Log and ignore missing CRL errors */
82 {
83 msg(D_TLS_DEBUG_LOW, "VERIFY WARNING: depth=%d, %s: %s",
86 subject);
87 ret = 1;
88 goto cleanup;
89 }
90
91 /* Remote site specified a certificate, but it's not correct */
92 msg(D_TLS_ERRORS, "VERIFY ERROR: depth=%d, error=%s: %s, serial=%s",
95 subject, serial ? serial : "<not available>");
96
98
99 session->verified = false;
100 goto cleanup;
101 }
102
104 {
105 goto cleanup;
106 }
107
108 ret = 1;
109
110cleanup:
111 gc_free(&gc);
112
113 return ret;
114}
115
116#ifdef ENABLE_X509ALTUSERNAME
117bool
119{
120 int nid = OBJ_txt2nid(fieldname);
121 return nid == NID_subject_alt_name || nid == NID_issuer_alt_name;
122}
123
124static
125bool
126extract_x509_extension(X509 *cert, char *fieldname, char *out, int size)
127{
128 bool retval = false;
129 char *buf = 0;
130
132 {
134 "ERROR: --x509-username-field 'ext:%s' not supported", fieldname);
135 return false;
136 }
137
138 int nid = OBJ_txt2nid(fieldname);
140 if (extensions)
141 {
142 int numalts;
143 int i;
144 /* get amount of alternatives,
145 * RFC2459 claims there MUST be at least
146 * one, but we don't depend on it...
147 */
148
150
151 /* loop through all alternatives */
152 for (i = 0; i<numalts; i++)
153 {
154 /* get a handle to alternative name number i */
156
157 switch (name->type)
158 {
159 case GEN_EMAIL:
160 if (ASN1_STRING_to_UTF8((unsigned char **)&buf, name->d.ia5) < 0)
161 {
162 continue;
163 }
164 if (strlen(buf) != name->d.ia5->length)
165 {
166 msg(D_TLS_ERRORS, "ASN1 ERROR: string contained terminating zero");
167 OPENSSL_free(buf);
168 }
169 else
170 {
171 strncpynt(out, buf, size);
172 OPENSSL_free(buf);
173 retval = true;
174 }
175 break;
176
177 default:
178 msg(D_TLS_DEBUG, "%s: ignoring general name field type %i",
179 __func__, name->type);
180 break;
181 }
182 }
184 }
185 return retval;
186}
187#endif /* ENABLE_X509ALTUSERNAME */
188
189/*
190 * Extract a field from an X509 subject name.
191 *
192 * Example:
193 *
194 * /C=US/ST=CO/L=Denver/O=ORG/CN=First-CN/CN=Test-CA/Email=jim@yonan.net
195 *
196 * The common name is 'Test-CA'
197 *
198 * Return true on success, false on error (insufficient buffer size in 'out'
199 * to contain result is grounds for error).
200 */
201static result_t
203 int size)
204{
205 int lastpos = -1;
206 int tmp = -1;
209 unsigned char *buf = NULL;
211
212 if (field_name_obj == NULL)
213 {
214 msg(D_TLS_ERRORS, "Invalid X509 attribute name '%s'", field_name);
215 return FAILURE;
216 }
217
218 ASSERT(size > 0);
219 *out = '\0';
220 do
221 {
222 lastpos = tmp;
224 } while (tmp > -1);
225
227
228 /* Nothing found */
229 if (lastpos == -1)
230 {
231 return FAILURE;
232 }
233
235 if (!x509ne)
236 {
237 return FAILURE;
238 }
239
241 if (!asn1)
242 {
243 return FAILURE;
244 }
245 if (ASN1_STRING_to_UTF8(&buf, asn1) < 0)
246 {
247 return FAILURE;
248 }
249
250 strncpynt(out, (char *)buf, size);
251
252 {
253 const result_t ret = (strlen((char *)buf) < size) ? SUCCESS : FAILURE;
254 OPENSSL_free(buf);
255 return ret;
256 }
257}
258
260backend_x509_get_username(char *common_name, int cn_len,
261 char *x509_username_field, X509 *peer_cert)
262{
263#ifdef ENABLE_X509ALTUSERNAME
264 if (strncmp("ext:", x509_username_field, 4) == 0)
265 {
266 if (!extract_x509_extension(peer_cert, x509_username_field+4, common_name, cn_len))
267 {
268 return FAILURE;
269 }
270 }
271 else if (strcmp(LN_serialNumber, x509_username_field) == 0)
272 {
274 struct gc_arena gc = gc_new();
275 char *serial = format_hex_ex(asn1_i->data, asn1_i->length,
276 0, 1 | FHE_CAPS, NULL, &gc);
277
278 if (!serial || cn_len <= strlen(serial)+2)
279 {
280 gc_free(&gc);
281 return FAILURE;
282 }
283 snprintf(common_name, cn_len, "0x%s", serial);
284 gc_free(&gc);
285 }
286 else
287#endif /* ifdef ENABLE_X509ALTUSERNAME */
288 if (FAILURE == extract_x509_field_ssl(X509_get_subject_name(peer_cert),
289 x509_username_field, common_name, cn_len))
290 {
291 return FAILURE;
292 }
293
294 return SUCCESS;
295}
296
297char *
299{
300 ASN1_INTEGER *asn1_i;
301 BIGNUM *bignum;
302 char *openssl_serial, *serial;
303
304 asn1_i = X509_get_serialNumber(cert);
305 bignum = ASN1_INTEGER_to_BN(asn1_i, NULL);
306 openssl_serial = BN_bn2dec(bignum);
307
308 serial = string_alloc(openssl_serial, gc);
309
310 BN_free(bignum);
311 OPENSSL_free(openssl_serial);
312
313 return serial;
314}
315
316char *
318{
319 const ASN1_INTEGER *asn1_i = X509_get_serialNumber(cert);
320
321 return format_hex_ex(asn1_i->data, asn1_i->length, 0, 1, ":", gc);
322}
323
325backend_x509_write_pem(openvpn_x509_cert_t *cert, const char *filename)
326{
327 BIO *out = BIO_new_file(filename, "w");
328 if (!out)
329 {
330 goto err;
331 }
332
333 if (!PEM_write_bio_X509(out, cert))
334 {
335 goto err;
336 }
337 BIO_free(out);
338
339 return SUCCESS;
340err:
341 BIO_free(out);
342 crypto_msg(D_TLS_DEBUG_LOW, "Error writing X509 certificate to file %s",
343 filename);
344 return FAILURE;
345}
346
347struct buffer
349{
350 const EVP_MD *sha1 = EVP_sha1();
352 X509_digest(cert, EVP_sha1(), BPTR(&hash), NULL);
354 return hash;
355}
356
357struct buffer
359{
360 const EVP_MD *sha256 = EVP_sha256();
362 X509_digest(cert, EVP_sha256(), BPTR(&hash), NULL);
364 return hash;
365}
366
367char *
369{
372 char *subject = NULL;
373
375 if (subject_bio == NULL)
376 {
377 goto err;
378 }
379
383
384 if (BIO_eof(subject_bio))
385 {
386 goto err;
387 }
388
390
391 subject = gc_malloc(subject_mem->length + 1, false, gc);
392
393 memcpy(subject, subject_mem->data, subject_mem->length);
394 subject[subject_mem->length] = '\0';
395
396err:
398 return subject;
399}
400
401
402/*
403 * x509-track implementation -- save X509 fields to environment,
404 * using the naming convention:
405 *
406 * X509_{cert_depth}_{name}={value}
407 *
408 * This function differs from x509_setenv below in the following ways:
409 *
410 * (1) Only explicitly named attributes in xt are saved, per usage
411 * of "x509-track" program options.
412 * (2) Only the level 0 cert info is saved unless the XT_FULL_CHAIN
413 * flag is set in xt->flags (corresponds with prepending a '+'
414 * to the name when specified by "x509-track" program option).
415 * (3) This function supports both X509 subject name fields as
416 * well as X509 V3 extensions.
417 * (4) This function can return the SHA1 fingerprint of a cert, e.g.
418 * x509-track "+SHA1"
419 * will return the SHA1 fingerprint for each certificate in the
420 * peer chain.
421 */
422
423void
424x509_track_add(const struct x509_track **ll_head, const char *name, int msglevel, struct gc_arena *gc)
425{
426 struct x509_track *xt;
427 ALLOC_OBJ_CLEAR_GC(xt, struct x509_track, gc);
428 if (*name == '+')
429 {
430 xt->flags |= XT_FULL_CHAIN;
431 ++name;
432 }
433 xt->name = name;
434 xt->nid = OBJ_txt2nid(name);
435 if (xt->nid != NID_undef)
436 {
437 xt->next = *ll_head;
438 *ll_head = xt;
439 }
440 else
441 {
442 msg(msglevel, "x509_track: no such attribute '%s'", name);
443 }
444}
445
446/* worker method for setenv_x509_track */
447static void
448do_setenv_x509(struct env_set *es, const char *name, char *value, int depth)
449{
450 char *name_expand;
451 size_t name_expand_size;
452
453 string_mod(value, CC_ANY, CC_CRLF, '?');
454 msg(D_X509_ATTR, "X509 ATTRIBUTE name='%s' value='%s' depth=%d", name, value, depth);
455 name_expand_size = 64 + strlen(name);
456 name_expand = (char *) malloc(name_expand_size);
457 check_malloc_return(name_expand);
458 snprintf(name_expand, name_expand_size, "X509_%d_%s", depth, name);
459 setenv_str(es, name_expand, value);
460 free(name_expand);
461}
462
463void
464x509_setenv_track(const struct x509_track *xt, struct env_set *es, const int depth, X509 *x509)
465{
466 struct gc_arena gc = gc_new();
467 X509_NAME *x509_name = X509_get_subject_name(x509);
468 const char nullc = '\0';
469
470 while (xt)
471 {
472 if (depth == 0 || (xt->flags & XT_FULL_CHAIN))
473 {
474 switch (xt->nid)
475 {
476 case NID_sha1:
477 case NID_sha256:
478 {
479 struct buffer fp_buf;
480 char *fp_str = NULL;
481
482 if (xt->nid == NID_sha1)
483 {
485 }
486 else
487 {
489 }
490
492 1 | FHE_CAPS, ":", &gc);
493 do_setenv_x509(es, xt->name, fp_str, depth);
494 }
495 break;
496
497 default:
498 {
499 int i = X509_NAME_get_index_by_NID(x509_name, xt->nid, -1);
500 if (i >= 0)
501 {
503 if (ent)
504 {
506 unsigned char *buf = NULL;
507 if (ASN1_STRING_to_UTF8(&buf, val) >= 0)
508 {
509 do_setenv_x509(es, xt->name, (char *)buf, depth);
510 OPENSSL_free(buf);
511 }
512 }
513 }
514 else
515 {
516 i = X509_get_ext_by_NID(x509, xt->nid, -1);
517 if (i >= 0)
518 {
520 if (ext)
521 {
522 BIO *bio = BIO_new(BIO_s_mem());
523 if (bio)
524 {
525 if (X509V3_EXT_print(bio, ext, 0, 0))
526 {
527 if (BIO_write(bio, &nullc, 1) == 1)
528 {
529 char *str;
531 do_setenv_x509(es, xt->name, str, depth);
532 }
533 }
534 BIO_free(bio);
535 }
536 }
537 }
538 }
539 }
540 }
541 }
542 xt = xt->next;
543 }
544 gc_free(&gc);
545}
546
547/*
548 * Save X509 fields to environment, using the naming convention:
549 *
550 * X509_{cert_depth}_{name}={value}
551 */
552void
554{
555 int i, n;
556 int fn_nid;
558 ASN1_STRING *val;
560 const char *objbuf;
561 unsigned char *buf = NULL;
562 char *name_expand;
563 size_t name_expand_size;
565
567 for (i = 0; i < n; ++i)
568 {
570 if (!ent)
571 {
572 continue;
573 }
575 if (!fn)
576 {
577 continue;
578 }
580 if (!val)
581 {
582 continue;
583 }
585 if (fn_nid == NID_undef)
586 {
587 continue;
588 }
590 if (!objbuf)
591 {
592 continue;
593 }
594 if (ASN1_STRING_to_UTF8(&buf, val) < 0)
595 {
596 continue;
597 }
602 objbuf);
604 string_mod((char *)buf, CC_PRINT, CC_CRLF, '_');
605 setenv_str_incr(es, name_expand, (char *)buf);
606 free(name_expand);
607 OPENSSL_free(buf);
608 }
609}
610
613{
615 {
616 return SUCCESS;
617 }
619 {
620 /*
621 * Unfortunately, X509_check_purpose() does some weird thing that
622 * prevent it to take a const argument
623 */
626
627 /*
628 * old versions of OpenSSL allow us to make the less strict check we used to
629 * do. If this less strict check pass, warn user that this might not be the
630 * case when its distribution will update to OpenSSL 1.1
631 */
632 if (result == FAILURE)
633 {
636 result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_CLIENT)) ? SUCCESS : FAILURE;
637 if (result == SUCCESS)
638 {
639 msg(M_WARN, "X509: Certificate is a client certificate yet it's purpose "
640 "cannot be verified (check may fail in the future)");
641 }
643 }
644 return result;
645 }
647 {
648 /*
649 * Unfortunately, X509_check_purpose() does some weird thing that
650 * prevent it to take a const argument
651 */
654
655 /*
656 * old versions of OpenSSL allow us to make the less strict check we used to
657 * do. If this less strict check pass, warn user that this might not be the
658 * case when its distribution will update to OpenSSL 1.1
659 */
660 if (result == FAILURE)
661 {
664 result = (ns && ns->length > 0 && (ns->data[0] & NS_SSL_SERVER)) ? SUCCESS : FAILURE;
665 if (result == SUCCESS)
666 {
667 msg(M_WARN, "X509: Certificate is a server certificate yet it's purpose "
668 "cannot be verified (check may fail in the future)");
669 }
671 }
672 return result;
673 }
674
675 return FAILURE;
676}
677
679x509_verify_cert_ku(X509 *x509, const unsigned *const expected_ku,
680 int expected_len)
681{
683
684 if (ku == NULL)
685 {
686 msg(D_TLS_ERRORS, "Certificate does not have key usage extension");
687 return FAILURE;
688 }
689
691 {
692 /* Extension required, value checked by TLS library */
694 return SUCCESS;
695 }
696
697 unsigned nku = 0;
698 for (size_t i = 0; i < 8; i++)
699 {
701 {
702 nku |= 1 << (7 - i);
703 }
704 }
705
706 /*
707 * Fixup if no LSB bits
708 */
709 if ((nku & 0xff) == 0)
710 {
711 nku >>= 8;
712 }
713
714 msg(D_HANDSHAKE, "Validating certificate key usage");
716 for (size_t i = 0; fFound != SUCCESS && i < expected_len; i++)
717 {
718 if (expected_ku[i] != 0 && (nku & expected_ku[i]) == expected_ku[i])
719 {
720 fFound = SUCCESS;
721 }
722 }
723
724 if (fFound != SUCCESS)
725 {
727 "ERROR: Certificate has key usage %04x, expected one of:", nku);
728 for (size_t i = 0; i < expected_len && expected_ku[i]; i++)
729 {
730 msg(D_TLS_ERRORS, " * %04x", expected_ku[i]);
731 }
732 }
733
735
736 return fFound;
737}
738
741{
744
746 NULL, NULL)) == NULL)
747 {
748 msg(D_HANDSHAKE, "Certificate does not have extended key usage extension");
749 }
750 else
751 {
752 int i;
753
754 msg(D_HANDSHAKE, "Validating certificate extended key usage");
755 for (i = 0; SUCCESS != fFound && i < sk_ASN1_OBJECT_num(eku); i++)
756 {
758 char szOid[1024];
759
760 if (SUCCESS != fFound && OBJ_obj2txt(szOid, sizeof(szOid), oid, 0) != -1)
761 {
762 msg(D_HANDSHAKE, "++ Certificate has EKU (str) %s, expects %s",
765 {
766 fFound = SUCCESS;
767 }
768 }
769 if (SUCCESS != fFound && OBJ_obj2txt(szOid, sizeof(szOid), oid, 1) != -1)
770 {
771 msg(D_HANDSHAKE, "++ Certificate has EKU (oid) %s, expects %s",
774 {
775 fFound = SUCCESS;
776 }
777 }
778 }
779 }
780
781 if (eku != NULL)
782 {
784 }
785
786 return fFound;
787}
788
789bool
791{
792 if (!opt->crl_file || (opt->ssl_flags & SSLF_CRL_VERIFY_DIR))
793 {
794 return false;
795 }
796
798 if (!store)
799 {
800 crypto_msg(M_FATAL, "Cannot get certificate store");
801 }
802
804 for (int i = 0; i < sk_X509_OBJECT_num(objs); i++)
805 {
807 ASSERT(obj);
809 {
810 return false;
811 }
812 }
813 return true;
814}
815
816#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:88
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:883
#define BPTR(buf)
Definition buffer.h:124
static bool buf_inc_len(struct buffer *buf, int inc)
Definition buffer.h:590
#define CC_CRLF
carriage return or newline
Definition buffer.h:920
#define ALLOC_OBJ_CLEAR_GC(dptr, type, gc)
Definition buffer.h:1097
#define BLEN(buf)
Definition buffer.h:127
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:1103
static void gc_free(struct gc_arena *a)
Definition buffer.h:1033
#define CC_PRINT
printable (>= 32, != 127)
Definition buffer.h:891
#define FHE_CAPS
Definition buffer.h:498
static struct gc_arena gc_new(void)
Definition buffer.h:1025
#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:283
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:305
#define D_TLS_DEBUG_LOW
Definition errlevel.h:77
#define D_X509_ATTR
Definition errlevel.h:103
#define D_HANDSHAKE
Definition errlevel.h:72
#define D_TLS_ERRORS
Definition errlevel.h:59
#define D_TLS_DEBUG
Definition errlevel.h:165
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:89
#define msg(flags,...)
Definition error.h:144
#define ASSERT(x)
Definition error.h:195
#define M_WARN
Definition error.h:91
static void usage(void)
Definition options.c:4934
#define SSLF_CRL_VERIFY_DIR
Definition ssl_common.h:420
int mydata_index
Allocate space in SSL objects in which to store a struct tls_session pointer back to parent.
Definition ssl_openssl.c:89
Control Channel OpenSSL Backend.
result_t verify_cert(struct tls_session *session, openvpn_x509_cert_t *cert, int cert_depth)
Definition ssl_verify.c:590
void cert_hash_remember(struct tls_session *session, const int error_depth, const struct buffer *cert_hash)
Definition ssl_verify.c:197
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:235
#define XT_FULL_CHAIN
Definition ssl_verify.h:219
#define NS_CERT_CHECK_CLIENT
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:232
#define NS_CERT_CHECK_NONE
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:228
#define NS_CERT_CHECK_SERVER
Do not perform Netscape certificate type verification.
Definition ssl_verify.h:230
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:61
int len
Length in bytes of the actual content within the allocated memory.
Definition buffer.h:66
Structure containing the hash for a single certificate.
Definition ssl_verify.h:55
Garbage collection arena used to keep track of dynamically allocated memory.
Definition buffer.h:117
Definition list.h:57
struct tls_root_ctx ssl_ctx
Definition ssl_common.h:300
unsigned int ssl_flags
Definition ssl_common.h:426
const char * crl_file
Definition ssl_common.h:345
SSL_CTX * ctx
Definition ssl_openssl.h:41
Security parameter state of a single session within a VPN tunnel.
Definition ssl_common.h:480
unsigned int flags
Definition ssl_verify.h:220
const struct x509_track * next
Definition ssl_verify.h:217
const char * name
Definition ssl_verify.h:218
struct env_set * es
static int cleanup(void **state)
struct gc_arena gc
Definition test_ssl.c:155