]> git.ipfire.org Git - thirdparty/squid.git/blob - src/security/PeerOptions.cc
SourceFormat Enforcement
[thirdparty/squid.git] / src / security / PeerOptions.cc
1 /*
2 * Copyright (C) 1996-2017 The Squid Software Foundation and contributors
3 *
4 * Squid software is distributed under GPLv2+ license and includes
5 * contributions from numerous individuals and organizations.
6 * Please see the COPYING and CONTRIBUTORS files for details.
7 */
8
9 #include "squid.h"
10 #include "base/Packable.h"
11 #include "Debug.h"
12 #include "fatal.h"
13 #include "globals.h"
14 #include "parser/Tokenizer.h"
15 #include "Parsing.h"
16 #include "security/PeerOptions.h"
17
18 #if USE_OPENSSL
19 #include "ssl/support.h"
20 #endif
21
22 Security::PeerOptions Security::ProxyOutgoingConfig;
23
24 Security::PeerOptions::PeerOptions(const Security::PeerOptions &p) :
25 sslOptions(p.sslOptions),
26 caDir(p.caDir),
27 crlFile(p.crlFile),
28 sslCipher(p.sslCipher),
29 sslFlags(p.sslFlags),
30 sslDomain(p.sslDomain),
31 parsedOptions(p.parsedOptions),
32 parsedFlags(p.parsedFlags),
33 certs(p.certs),
34 caFiles(p.caFiles),
35 parsedCrl(p.parsedCrl),
36 sslVersion(p.sslVersion),
37 encryptTransport(p.encryptTransport)
38 {
39 memcpy(&flags, &p.flags, sizeof(flags));
40 }
41
42 void
43 Security::PeerOptions::parse(const char *token)
44 {
45 if (!*token) {
46 // config says just "ssl" or "tls" (or "tls-")
47 encryptTransport = true;
48 return;
49 }
50
51 if (strncmp(token, "disable", 7) == 0) {
52 clear();
53 return;
54 }
55
56 if (strncmp(token, "cert=", 5) == 0) {
57 KeyData t;
58 t.privateKeyFile = t.certFile = SBuf(token + 5);
59 certs.emplace_back(t);
60 } else if (strncmp(token, "key=", 4) == 0) {
61 if (certs.empty() || certs.back().certFile.isEmpty()) {
62 fatal("cert= option must be set before key= is used.");
63 return;
64 }
65 KeyData &t = certs.back();
66 t.privateKeyFile = SBuf(token + 4);
67 } else if (strncmp(token, "version=", 8) == 0) {
68 debugs(0, DBG_PARSE_NOTE(1), "UPGRADE WARNING: SSL version= is deprecated. Use options= to limit protocols instead.");
69 sslVersion = xatoi(token + 8);
70 } else if (strncmp(token, "min-version=", 12) == 0) {
71 tlsMinVersion = SBuf(token + 12);
72 } else if (strncmp(token, "options=", 8) == 0) {
73 sslOptions = SBuf(token + 8);
74 parsedOptions = parseOptions();
75 } else if (strncmp(token, "cipher=", 7) == 0) {
76 sslCipher = SBuf(token + 7);
77 } else if (strncmp(token, "cafile=", 7) == 0) {
78 caFiles.emplace_back(SBuf(token + 7));
79 } else if (strncmp(token, "capath=", 7) == 0) {
80 caDir = SBuf(token + 7);
81 #if !USE_OPENSSL
82 debugs(3, DBG_PARSE_NOTE(1), "WARNING: capath= option requires --with-openssl.");
83 #endif
84 } else if (strncmp(token, "crlfile=", 8) == 0) {
85 crlFile = SBuf(token + 8);
86 loadCrlFile();
87 } else if (strncmp(token, "flags=", 6) == 0) {
88 if (parsedFlags != 0) {
89 debugs(3, DBG_PARSE_NOTE(1), "WARNING: Overwriting flags=" << sslFlags << " with " << SBuf(token + 6));
90 }
91 sslFlags = SBuf(token + 6);
92 parsedFlags = parseFlags();
93 } else if (strncmp(token, "default-ca=off", 14) == 0 || strncmp(token, "no-default-ca", 13) == 0) {
94 if (flags.tlsDefaultCa.configured() && flags.tlsDefaultCa)
95 fatalf("ERROR: previous default-ca settings conflict with %s", token);
96 flags.tlsDefaultCa.configure(false);
97 } else if (strncmp(token, "default-ca=on", 13) == 0 || strncmp(token, "default-ca", 10) == 0) {
98 if (flags.tlsDefaultCa.configured() && !flags.tlsDefaultCa)
99 fatalf("ERROR: previous default-ca settings conflict with %s", token);
100 flags.tlsDefaultCa.configure(true);
101 } else if (strncmp(token, "domain=", 7) == 0) {
102 sslDomain = SBuf(token + 7);
103 } else if (strncmp(token, "no-npn", 6) == 0) {
104 flags.tlsNpn = false;
105 } else {
106 debugs(3, DBG_CRITICAL, "ERROR: Unknown TLS option '" << token << "'");
107 return;
108 }
109
110 encryptTransport = true;
111 }
112
113 void
114 Security::PeerOptions::dumpCfg(Packable *p, const char *pfx) const
115 {
116 if (!encryptTransport) {
117 p->appendf(" %sdisable", pfx);
118 return; // no other settings are relevant
119 }
120
121 for (auto &i : certs) {
122 if (!i.certFile.isEmpty())
123 p->appendf(" %scert=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(i.certFile));
124
125 if (!i.privateKeyFile.isEmpty() && i.privateKeyFile != i.certFile)
126 p->appendf(" %skey=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(i.privateKeyFile));
127 }
128
129 if (!sslOptions.isEmpty())
130 p->appendf(" %soptions=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslOptions));
131
132 if (!sslCipher.isEmpty())
133 p->appendf(" %scipher=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslCipher));
134
135 for (auto i : caFiles) {
136 p->appendf(" %scafile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(i));
137 }
138
139 if (!caDir.isEmpty())
140 p->appendf(" %scapath=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(caDir));
141
142 if (!crlFile.isEmpty())
143 p->appendf(" %scrlfile=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(crlFile));
144
145 if (!sslFlags.isEmpty())
146 p->appendf(" %sflags=" SQUIDSBUFPH, pfx, SQUIDSBUFPRINT(sslFlags));
147
148 if (flags.tlsDefaultCa.configured()) {
149 // default ON for peers / upstream servers
150 // default OFF for listening ports
151 if (flags.tlsDefaultCa)
152 p->appendf(" %sdefault-ca", pfx);
153 else
154 p->appendf(" %sdefault-ca=off", pfx);
155 }
156
157 if (!flags.tlsNpn)
158 p->appendf(" %sno-npn", pfx);
159 }
160
161 void
162 Security::PeerOptions::updateTlsVersionLimits()
163 {
164 if (!tlsMinVersion.isEmpty()) {
165 ::Parser::Tokenizer tok(tlsMinVersion);
166 int64_t v = 0;
167 if (tok.skip('1') && tok.skip('.') && tok.int64(v, 10, false, 1) && v <= 3) {
168 // only account for TLS here - SSL versions are handled by options= parameter
169 // avoid affecting options= parameter in cachemgr config report
170 #if SSL_OP_NO_TLSv1
171 if (v > 0)
172 parsedOptions |= SSL_OP_NO_TLSv1;
173 #endif
174 #if SSL_OP_NO_TLSv1_1
175 if (v > 1)
176 parsedOptions |= SSL_OP_NO_TLSv1_1;
177 #endif
178 #if SSL_OP_NO_TLSv1_2
179 if (v > 2)
180 parsedOptions |= SSL_OP_NO_TLSv1_2;
181 #endif
182
183 } else {
184 debugs(0, DBG_PARSE_NOTE(1), "WARNING: Unknown TLS minimum version: " << tlsMinVersion);
185 }
186
187 } else if (sslVersion > 2) {
188 // backward compatibility hack for sslversion= configuration
189 // only use if tls-min-version=N.N is not present
190 // values 0-2 for auto and SSLv2 are not supported any longer.
191 // Do it this way so we DO cause changes to options= in cachemgr config report
192 const char *add = NULL;
193 switch (sslVersion) {
194 case 3:
195 add = "NO_TLSv1,NO_TLSv1_1,NO_TLSv1_2";
196 break;
197 case 4:
198 add = "NO_SSLv3,NO_TLSv1_1,NO_TLSv1_2";
199 break;
200 case 5:
201 add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_2";
202 break;
203 case 6:
204 add = "NO_SSLv3,NO_TLSv1,NO_TLSv1_1";
205 break;
206 default: // nothing
207 break;
208 }
209 if (add) {
210 if (!sslOptions.isEmpty())
211 sslOptions.append(",",1);
212 sslOptions.append(add, strlen(add));
213 }
214 sslVersion = 0; // prevent sslOptions being repeatedly appended
215 }
216 }
217
218 Security::ContextPointer
219 Security::PeerOptions::createBlankContext() const
220 {
221 Security::ContextPointer ctx;
222 #if USE_OPENSSL
223 Ssl::Initialize();
224
225 #if (OPENSSL_VERSION_NUMBER >= 0x10100000L)
226 SSL_CTX *t = SSL_CTX_new(TLS_client_method());
227 #else
228 SSL_CTX *t = SSL_CTX_new(SSLv23_client_method());
229 #endif
230 if (!t) {
231 const auto x = ERR_get_error();
232 fatalf("Failed to allocate TLS client context: %s\n", Security::ErrorString(x));
233 }
234 ctx.resetWithoutLocking(t);
235
236 #elif USE_GNUTLS
237 // Initialize for X.509 certificate exchange
238 gnutls_certificate_credentials_t t;
239 if (const int x = gnutls_certificate_allocate_credentials(&t)) {
240 fatalf("Failed to allocate TLS client context: %s\n", Security::ErrorString(x));
241 }
242 ctx.resetWithoutLocking(t);
243
244 #else
245 debugs(83, 1, "WARNING: Failed to allocate TLS client context: No TLS library");
246
247 #endif
248
249 return ctx;
250 }
251
252 Security::ContextPointer
253 Security::PeerOptions::createClientContext(bool setOptions)
254 {
255 updateTlsVersionLimits();
256
257 Security::ContextPointer t(createBlankContext());
258 if (t) {
259 #if USE_OPENSSL
260 // XXX: temporary performance regression. c_str() data copies and prevents this being a const method
261 Ssl::InitClientContext(t, *this, (setOptions ? parsedOptions : 0), parsedFlags);
262 #endif
263 updateContextNpn(t);
264 updateContextCa(t);
265 updateContextCrl(t);
266 }
267
268 return t;
269 }
270
271 /// set of options we can parse and what they map to
272 static struct ssl_option {
273 const char *name;
274 long value;
275
276 } ssl_options[] = {
277
278 #if SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
279 {
280 "NETSCAPE_REUSE_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_REUSE_CIPHER_CHANGE_BUG
281 },
282 #endif
283 #if SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
284 {
285 "SSLREF2_REUSE_CERT_TYPE_BUG", SSL_OP_SSLREF2_REUSE_CERT_TYPE_BUG
286 },
287 #endif
288 #if SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
289 {
290 "MICROSOFT_BIG_SSLV3_BUFFER", SSL_OP_MICROSOFT_BIG_SSLV3_BUFFER
291 },
292 #endif
293 #if SSL_OP_SSLEAY_080_CLIENT_DH_BUG
294 {
295 "SSLEAY_080_CLIENT_DH_BUG", SSL_OP_SSLEAY_080_CLIENT_DH_BUG
296 },
297 #endif
298 #if SSL_OP_TLS_D5_BUG
299 {
300 "TLS_D5_BUG", SSL_OP_TLS_D5_BUG
301 },
302 #endif
303 #if SSL_OP_TLS_BLOCK_PADDING_BUG
304 {
305 "TLS_BLOCK_PADDING_BUG", SSL_OP_TLS_BLOCK_PADDING_BUG
306 },
307 #endif
308 #if SSL_OP_TLS_ROLLBACK_BUG
309 {
310 "TLS_ROLLBACK_BUG", SSL_OP_TLS_ROLLBACK_BUG
311 },
312 #endif
313 #if SSL_OP_ALL
314 {
315 "ALL", (long)SSL_OP_ALL
316 },
317 #endif
318 #if SSL_OP_SINGLE_DH_USE
319 {
320 "SINGLE_DH_USE", SSL_OP_SINGLE_DH_USE
321 },
322 #endif
323 #if SSL_OP_EPHEMERAL_RSA
324 {
325 "EPHEMERAL_RSA", SSL_OP_EPHEMERAL_RSA
326 },
327 #endif
328 #if SSL_OP_PKCS1_CHECK_1
329 {
330 "PKCS1_CHECK_1", SSL_OP_PKCS1_CHECK_1
331 },
332 #endif
333 #if SSL_OP_PKCS1_CHECK_2
334 {
335 "PKCS1_CHECK_2", SSL_OP_PKCS1_CHECK_2
336 },
337 #endif
338 #if SSL_OP_NETSCAPE_CA_DN_BUG
339 {
340 "NETSCAPE_CA_DN_BUG", SSL_OP_NETSCAPE_CA_DN_BUG
341 },
342 #endif
343 #if SSL_OP_NON_EXPORT_FIRST
344 {
345 "NON_EXPORT_FIRST", SSL_OP_NON_EXPORT_FIRST
346 },
347 #endif
348 #if SSL_OP_CIPHER_SERVER_PREFERENCE
349 {
350 "CIPHER_SERVER_PREFERENCE", SSL_OP_CIPHER_SERVER_PREFERENCE
351 },
352 #endif
353 #if SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
354 {
355 "NETSCAPE_DEMO_CIPHER_CHANGE_BUG", SSL_OP_NETSCAPE_DEMO_CIPHER_CHANGE_BUG
356 },
357 #endif
358 #if SSL_OP_NO_SSLv3
359 {
360 "NO_SSLv3", SSL_OP_NO_SSLv3
361 },
362 #endif
363 #if SSL_OP_NO_TLSv1
364 {
365 "NO_TLSv1", SSL_OP_NO_TLSv1
366 },
367 #endif
368 #if SSL_OP_NO_TLSv1_1
369 {
370 "NO_TLSv1_1", SSL_OP_NO_TLSv1_1
371 },
372 #endif
373 #if SSL_OP_NO_TLSv1_2
374 {
375 "NO_TLSv1_2", SSL_OP_NO_TLSv1_2
376 },
377 #endif
378 #if SSL_OP_NO_COMPRESSION
379 {
380 "No_Compression", SSL_OP_NO_COMPRESSION
381 },
382 #endif
383 #if SSL_OP_NO_TICKET
384 {
385 "NO_TICKET", SSL_OP_NO_TICKET
386 },
387 #endif
388 #if SSL_OP_SINGLE_ECDH_USE
389 {
390 "SINGLE_ECDH_USE", SSL_OP_SINGLE_ECDH_USE
391 },
392 #endif
393 {
394 "", 0
395 },
396 {
397 NULL, 0
398 }
399 };
400
401 /**
402 * Pre-parse TLS options= parameter to be applied when the TLS objects created.
403 * Options must not used in the case of peek or stare bump mode.
404 */
405 long
406 Security::PeerOptions::parseOptions()
407 {
408 long op = 0;
409 ::Parser::Tokenizer tok(sslOptions);
410
411 do {
412 enum {
413 MODE_ADD, MODE_REMOVE
414 } mode;
415
416 if (tok.skip('-') || tok.skip('!'))
417 mode = MODE_REMOVE;
418 else {
419 (void)tok.skip('+'); // default action is add. ignore if missing operator
420 mode = MODE_ADD;
421 }
422
423 static const CharacterSet optChars = CharacterSet("TLS-option", "_") + CharacterSet::ALPHA + CharacterSet::DIGIT;
424 int64_t hex = 0;
425 SBuf option;
426 long value = 0;
427
428 // Bug 4429: identify the full option name before determining text or numeric
429 if (tok.prefix(option, optChars)) {
430
431 // find the named option in our supported set
432 for (struct ssl_option *opttmp = ssl_options; opttmp->name; ++opttmp) {
433 if (option.cmp(opttmp->name) == 0) {
434 value = opttmp->value;
435 break;
436 }
437 }
438
439 // Special case.. hex specification
440 ::Parser::Tokenizer tmp(option);
441 if (!value && tmp.int64(hex, 16, false) && tmp.atEnd()) {
442 value = hex;
443 }
444 }
445
446 if (value) {
447 switch (mode) {
448 case MODE_ADD:
449 op |= value;
450 break;
451 case MODE_REMOVE:
452 op &= ~value;
453 break;
454 }
455 } else {
456 debugs(83, DBG_PARSE_NOTE(1), "ERROR: Unknown TLS option " << option);
457 }
458
459 static const CharacterSet delims("TLS-option-delim",":,");
460 if (!tok.skipAll(delims) && !tok.atEnd()) {
461 fatalf("Unknown TLS option '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(tok.remaining()));
462 }
463
464 } while (!tok.atEnd());
465
466 #if SSL_OP_NO_SSLv2
467 // compliance with RFC 6176: Prohibiting Secure Sockets Layer (SSL) Version 2.0
468 op = op | SSL_OP_NO_SSLv2;
469 #endif
470 return op;
471 }
472
473 /**
474 * Parses the TLS flags squid.conf parameter
475 */
476 long
477 Security::PeerOptions::parseFlags()
478 {
479 if (sslFlags.isEmpty())
480 return 0;
481
482 static struct {
483 SBuf label;
484 long mask;
485 } flagTokens[] = {
486 { SBuf("NO_DEFAULT_CA"), SSL_FLAG_NO_DEFAULT_CA },
487 { SBuf("DELAYED_AUTH"), SSL_FLAG_DELAYED_AUTH },
488 { SBuf("DONT_VERIFY_PEER"), SSL_FLAG_DONT_VERIFY_PEER },
489 { SBuf("DONT_VERIFY_DOMAIN"), SSL_FLAG_DONT_VERIFY_DOMAIN },
490 { SBuf("NO_SESSION_REUSE"), SSL_FLAG_NO_SESSION_REUSE },
491 #if X509_V_FLAG_CRL_CHECK
492 { SBuf("VERIFY_CRL"), SSL_FLAG_VERIFY_CRL },
493 { SBuf("VERIFY_CRL_ALL"), SSL_FLAG_VERIFY_CRL_ALL },
494 #endif
495 { SBuf(), 0 }
496 };
497
498 ::Parser::Tokenizer tok(sslFlags);
499 static const CharacterSet delims("Flag-delimiter", ":,");
500
501 long fl = 0;
502 do {
503 long found = 0;
504 for (size_t i = 0; flagTokens[i].mask; ++i) {
505 if (tok.skip(flagTokens[i].label)) {
506 found = flagTokens[i].mask;
507 break;
508 }
509 }
510 if (!found)
511 fatalf("Unknown TLS flag '" SQUIDSBUFPH "'", SQUIDSBUFPRINT(tok.remaining()));
512 if (found == SSL_FLAG_NO_DEFAULT_CA) {
513 if (flags.tlsDefaultCa.configured() && flags.tlsDefaultCa)
514 fatal("ERROR: previous default-ca settings conflict with sslflags=NO_DEFAULT_CA");
515 debugs(83, DBG_PARSE_NOTE(2), "WARNING: flags=NO_DEFAULT_CA is deprecated. Use tls-default-ca=off instead.");
516 flags.tlsDefaultCa.configure(false);
517 } else
518 fl |= found;
519 } while (tok.skipOne(delims));
520
521 return fl;
522 }
523
524 /// Load a CRLs list stored in the file whose /path/name is in crlFile
525 /// replaces any CRL loaded previously
526 void
527 Security::PeerOptions::loadCrlFile()
528 {
529 parsedCrl.clear();
530 if (crlFile.isEmpty())
531 return;
532
533 #if USE_OPENSSL
534 BIO *in = BIO_new_file(crlFile.c_str(), "r");
535 if (!in) {
536 debugs(83, 2, "WARNING: Failed to open CRL file " << crlFile);
537 return;
538 }
539
540 while (X509_CRL *crl = PEM_read_bio_X509_CRL(in,NULL,NULL,NULL)) {
541 parsedCrl.emplace_back(Security::CrlPointer(crl));
542 }
543 BIO_free(in);
544 #endif
545 }
546
547 #if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
548 // Dummy next_proto_neg callback
549 static int
550 ssl_next_proto_cb(SSL *s, unsigned char **out, unsigned char *outlen, const unsigned char *in, unsigned int inlen, void *arg)
551 {
552 static const unsigned char supported_protos[] = {8, 'h','t','t', 'p', '/', '1', '.', '1'};
553 (void)SSL_select_next_proto(out, outlen, in, inlen, supported_protos, sizeof(supported_protos));
554 return SSL_TLSEXT_ERR_OK;
555 }
556 #endif
557
558 void
559 Security::PeerOptions::updateContextNpn(Security::ContextPointer &ctx)
560 {
561 if (!flags.tlsNpn)
562 return;
563
564 #if USE_OPENSSL && defined(TLSEXT_TYPE_next_proto_neg)
565 SSL_CTX_set_next_proto_select_cb(ctx.get(), &ssl_next_proto_cb, nullptr);
566 #endif
567
568 // NOTE: GnuTLS does not support the obsolete NPN extension.
569 // it does support ALPN per-session, not per-context.
570 }
571
572 static const char *
573 loadSystemTrustedCa(Security::ContextPointer &ctx)
574 {
575 #if USE_OPENSSL
576 if (SSL_CTX_set_default_verify_paths(ctx.get()) == 0)
577 return Security::ErrorString(ERR_get_error());
578
579 #elif USE_GNUTLS
580 auto x = gnutls_certificate_set_x509_system_trust(ctx.get());
581 if (x < 0)
582 return Security::ErrorString(x);
583
584 #endif
585 return nullptr;
586 }
587
588 void
589 Security::PeerOptions::updateContextCa(Security::ContextPointer &ctx)
590 {
591 debugs(83, 8, "Setting CA certificate locations.");
592 #if USE_OPENSSL
593 const char *path = caDir.isEmpty() ? nullptr : caDir.c_str();
594 #endif
595 for (auto i : caFiles) {
596 #if USE_OPENSSL
597 if (!SSL_CTX_load_verify_locations(ctx.get(), i.c_str(), path)) {
598 const auto x = ERR_get_error();
599 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate location " <<
600 i << ": " << Security::ErrorString(x));
601 }
602 #elif USE_GNUTLS
603 const auto x = gnutls_certificate_set_x509_trust_file(ctx.get(), i.c_str(), GNUTLS_X509_FMT_PEM);
604 if (x < 0) {
605 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting CA certificate location " <<
606 i << ": " << Security::ErrorString(x));
607 }
608 #endif
609 }
610
611 if (!flags.tlsDefaultCa)
612 return;
613
614 if (const char *err = loadSystemTrustedCa(ctx)) {
615 debugs(83, DBG_IMPORTANT, "WARNING: Ignoring error setting default trusted CA : " << err);
616 }
617 }
618
619 void
620 Security::PeerOptions::updateContextCrl(Security::ContextPointer &ctx)
621 {
622 #if USE_OPENSSL
623 bool verifyCrl = false;
624 X509_STORE *st = SSL_CTX_get_cert_store(ctx.get());
625 if (parsedCrl.size()) {
626 for (auto &i : parsedCrl) {
627 if (!X509_STORE_add_crl(st, i.get()))
628 debugs(83, 2, "WARNING: Failed to add CRL");
629 else
630 verifyCrl = true;
631 }
632 }
633
634 #if X509_V_FLAG_CRL_CHECK
635 if ((parsedFlags & SSL_FLAG_VERIFY_CRL_ALL))
636 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK|X509_V_FLAG_CRL_CHECK_ALL);
637 else if (verifyCrl || (parsedFlags & SSL_FLAG_VERIFY_CRL))
638 X509_STORE_set_flags(st, X509_V_FLAG_CRL_CHECK);
639 #endif
640
641 #endif /* USE_OPENSSL */
642 }
643
644 void
645 parse_securePeerOptions(Security::PeerOptions *opt)
646 {
647 while(const char *token = ConfigParser::NextToken())
648 opt->parse(token);
649 }
650