XRootD
Loading...
Searching...
No Matches
XrdTlsContext.cc
Go to the documentation of this file.
1//------------------------------------------------------------------------------
2// Copyright (c) 2011-2018 by European Organization for Nuclear Research (CERN)
3// Author: Michal Simon <simonm@cern.ch>
4//------------------------------------------------------------------------------
5// XRootD is free software: you can redistribute it and/or modify
6// it under the terms of the GNU Lesser General Public License as published by
7// the Free Software Foundation, either version 3 of the License, or
8// (at your option) any later version.
9//
10// XRootD is distributed in the hope that it will be useful,
11// but WITHOUT ANY WARRANTY; without even the implied warranty of
12// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13// GNU General Public License for more details.
14//
15// You should have received a copy of the GNU Lesser General Public License
16// along with XRootD. If not, see <http://www.gnu.org/licenses/>.
17//------------------------------------------------------------------------------
18
19#include <cstdio>
20#include <cstdlib>
21#include <mutex>
22
23// Include OpenSSL config headers first to get feature detection macros
24#include <openssl/opensslconf.h>
25#include <openssl/opensslv.h>
26
27// PKCS#11 support strategy:
28// - OpenSSL 3.x+ (EL9+, AlmaLinux 10): Prefer OSSL_STORE API with pkcs11-provider (modern)
29// Falls back to ENGINE if pkcs11-provider is not installed but engine_pkcs11 is
30// - OpenSSL 1.1.x (EL8): Use ENGINE API with libp11/engine_pkcs11 (legacy compatibility)
31
32// OpenSSL 3.0+ Provider/OSSL_STORE support (preferred for modern systems)
33#if OPENSSL_VERSION_NUMBER >= 0x30000000L
34 #define XRDTLS_HAVE_OSSL_STORE 1
35 #include <openssl/store.h>
36 #include <openssl/provider.h>
37#endif
38
39// ENGINE API support:
40// - OpenSSL 1.1.x: Primary method for PKCS#11
41#if !defined(OPENSSL_NO_ENGINE)
42 #define XRDTLS_HAVE_ENGINE 1
43 #include <openssl/engine.h>
44#endif
45
46#include <openssl/bio.h>
47#include <openssl/crypto.h>
48#include <openssl/err.h>
49#include <openssl/conf.h>
50#include <openssl/ssl.h>
51#include <sys/stat.h>
52
53#include "XrdOuc/XrdOucUtils.hh"
55#include "XrdSys/XrdSysError.hh"
57#include "XrdSys/XrdSysTimer.hh"
58
59#include "XrdTls/XrdTls.hh"
61#include "XrdTls/XrdTlsTrace.hh"
62
63#if OPENSSL_VERSION_NUMBER >= 0x30400010
64#define SSL_CTX_flush_sessions SSL_CTX_flush_sessions_ex
65#endif
66
67/******************************************************************************/
68/* G l o b a l s */
69/******************************************************************************/
70
71namespace XrdTlsGlobal
72{
74};
75
76namespace
77{
78#ifndef OPENSSL_NO_CONF
79bool EnsureOpenSSLConfigLoaded()
80{
81 static std::once_flag configFlag;
82 static bool loadOK = true;
83
84 std::call_once(configFlag, []() {
85#if OPENSSL_VERSION_NUMBER >= 0x10100000L
86 if (!OPENSSL_init_ssl(OPENSSL_INIT_LOAD_CONFIG, nullptr))
87 loadOK = false;
88#else
89 OPENSSL_config(nullptr);
90#endif
91 });
92 return loadOK;
93}
94#else
95bool EnsureOpenSSLConfigLoaded()
96{
97 return false;
98}
99#endif
100
101#if OPENSSL_VERSION_NUMBER >= 0x30000000L
102// Initialize an isolated OSSL_LIB_CTX for PKCS11 operations
103// This prevents PKCS11 from affecting other parts of the process (e.g., SciTokens library)
104bool InitIsolatedPKCS11Context(OSSL_LIB_CTX **libCtx, OSSL_PROVIDER **pkcs11Prov, OSSL_PROVIDER **defaultProv)
105{
106 // Create an isolated library context
107 *libCtx = OSSL_LIB_CTX_new();
108 if (!*libCtx) {
109 return false;
110 }
111
112 // Load the OpenSSL configuration into the isolated context
113 // This allows the pkcs11-provider to be properly configured with module paths, etc.
114 const char *opensslConf = getenv("OPENSSL_CONF");
115 if (opensslConf && opensslConf[0]) {
116 // Load the config file into the isolated context
117 if (!OSSL_LIB_CTX_load_config(*libCtx, opensslConf)) {
118 // Config loading failed, cleanup and return error
119 OSSL_LIB_CTX_free(*libCtx);
120 *libCtx = nullptr;
121 return false;
122 }
123 } else {
124 // No OPENSSL_CONF set, try loading providers manually
125 // Load the default provider in the isolated context (needed for basic crypto)
126 *defaultProv = OSSL_PROVIDER_load(*libCtx, "default");
127 if (!*defaultProv) {
128 OSSL_LIB_CTX_free(*libCtx);
129 *libCtx = nullptr;
130 return false;
131 }
132
133 // Load the pkcs11 provider in the isolated context
134 *pkcs11Prov = OSSL_PROVIDER_load(*libCtx, "pkcs11");
135 if (!*pkcs11Prov) {
136 OSSL_PROVIDER_unload(*defaultProv);
137 OSSL_LIB_CTX_free(*libCtx);
138 *libCtx = nullptr;
139 *defaultProv = nullptr;
140 return false;
141 }
142 }
143
144 return true;
145}
146#endif
147}
148
149/******************************************************************************/
150/* X r d T l s C o n t e x t I m p l */
151/******************************************************************************/
152
154{
156 : ctx(0), ctxnew(0), owner(p), flsCVar(0),
157 flushT(0),
158 crlRunning(false), flsRunning(false)
159#if OPENSSL_VERSION_NUMBER >= 0x30000000L
160 , pkcs11LibCtx(0), pkcs11Provider(0)
161#endif
162 {}
163 ~XrdTlsContextImpl() {if (ctx) SSL_CTX_free(ctx);
164 if (ctxnew) delete ctxnew;
165 if (flsCVar) delete flsCVar;
166#if OPENSSL_VERSION_NUMBER >= 0x30000000L
167 if (pkcs11Provider) OSSL_PROVIDER_unload(pkcs11Provider);
168 if (pkcs11LibCtx) OSSL_LIB_CTX_free(pkcs11LibCtx);
169#endif
170 }
171
172 SSL_CTX *ctx;
178 short flushT;
181 time_t lastCertModTime = 0;
183 std::string sessionCacheId;
184#if OPENSSL_VERSION_NUMBER >= 0x30000000L
185 OSSL_LIB_CTX *pkcs11LibCtx; // Isolated context for PKCS11
186 OSSL_PROVIDER *pkcs11Provider; // PKCS11 provider handle
187#endif
188};
189
190/******************************************************************************/
191/* C r l R e f r e s h S u p p o r t */
192/******************************************************************************/
193
194namespace XrdTlsCrl
195{
196// Inital entry for refreshing crls
197//
198void *Refresh(void *parg)
199{
200 EPNAME("Refresh");
201 int sleepTime;
202 bool doreplace;
203
204// Get the implementation details
205//
206 XrdTlsContextImpl *ctxImpl = static_cast<XrdTlsContextImpl*>(parg);
207
208// Indicate we have started in the trace record
209//
210 DBG_CTX("CRL refresh started.")
211
212// Do this forever but first get the sleep time
213//
214do{ctxImpl->crlMutex.ReadLock();
215 sleepTime = ctxImpl->Parm.crlRT;
216 ctxImpl->crlMutex.UnLock();
217
218// We may have been cancelled, in which case we just exit
219//
220 if (!sleepTime)
221 {ctxImpl->crlMutex.WriteLock();
222 ctxImpl->crlRunning = false;
223 ctxImpl->crlMutex.UnLock();
224 DBG_CTX("CRL refresh ending by request!");
225 return (void *)0;
226 }
227
228// Indicate we how long before a refresh
229//
230 DBG_CTX("CRL refresh will happen in " <<sleepTime <<" seconds.");
231
232// Now sleep the request amount of time
233//
234 XrdSysTimer::Snooze(sleepTime);
235
236 if (ctxImpl->owner->x509Verify() || ctxImpl->owner->newHostCertificateDetected()) {
237 // Check if this context is still alive. Generally, it never gets deleted.
238 //
239 ctxImpl->crlMutex.WriteLock();
240 if (!ctxImpl->owner) break;
241
242 // We clone the original, this will give us the latest crls (i.e. refreshed).
243 // We drop the lock while doing so as this may take a long time. This is
244 // completely safe to do because we implicitly own the implementation.
245 //
246 ctxImpl->crlMutex.UnLock();
247 XrdTlsContext *newctx = ctxImpl->owner->Clone();
248
249 // Verify that the context was properly built
250 //
251 if (!newctx || !newctx->isOK())
252 {XrdTls::Emsg("CrlRefresh:","Refresh of context failed!!!",false);
253 continue;
254 }
255
256 // OK, set the new context to be used next time Session() is called.
257 //
258 ctxImpl->crlMutex.WriteLock();
259 doreplace = (ctxImpl->ctxnew != 0);
260 if (doreplace) delete ctxImpl->ctxnew;
261 ctxImpl->ctxnew = newctx;
262 ctxImpl->crlMutex.UnLock();
263
264 // Do some debugging
265 //
266 if (doreplace) {DBG_CTX("CRL refresh created replacement x509 store.");}
267 else {DBG_CTX("CRL refresh created new x509 store.");}
268 }
269 } while(true);
270
271// If we are here the context that started us has gone away and we are done
272//
273 bool keepctx = ctxImpl->flsRunning;
274 ctxImpl->crlRunning = false;
275 ctxImpl->crlMutex.UnLock();
276 if (!keepctx) delete ctxImpl;
277 return (void *)0;
278}
279}
280
281/******************************************************************************/
282/* C a c h e F l u s h S u p p o r t */
283/******************************************************************************/
284
285namespace XrdTlsFlush
286{
287/******************************************************************************/
288/* F l u s h e r */
289/******************************************************************************/
290// Inital entry for refreshing crls
291//
292void *Flusher(void *parg)
293{
294 EPNAME("Flusher");
295 time_t tStart, tWaited;
296 int flushT, waitT, hits, miss, sesn, tmos;
297 long tNow;
298
299// Get the implementation details
300//
301 XrdTlsContextImpl *ctxImpl = static_cast<XrdTlsContextImpl*>(parg);
302
303// Get the interval as it may change as we are running
304//
305 ctxImpl->crlMutex.ReadLock();
306 waitT = flushT = ctxImpl->flushT;
307 ctxImpl->crlMutex.UnLock();
308
309// Indicate we have started in the trace record
310//
311 DBG_CTX("Cache flusher started; interval="<<flushT<<" seconds.");
312
313// Do this forever
314//
315do{tStart = time(0);
316 ctxImpl->flsCVar->Wait(waitT);
317 tWaited= time(0) - tStart;
318
319// Check if this context is still alive. Generally, it never gets deleted.
320//
321 ctxImpl->crlMutex.ReadLock();
322 if (!ctxImpl->owner) break;
323
324// If the interval changed, see if we should wait a bit longer
325//
326 if (flushT != ctxImpl->flushT && tWaited < ctxImpl->flushT-1)
327 {waitT = ctxImpl->flushT - tWaited;
328 ctxImpl->crlMutex.UnLock();
329 continue;
330 }
331
332// Get the new values and drop the lock
333//
334 waitT = flushT = ctxImpl->flushT;
335 ctxImpl->crlMutex.UnLock();
336
337// Get some relevant statistics
338//
339 sesn = SSL_CTX_sess_number(ctxImpl->ctx);
340 hits = SSL_CTX_sess_hits(ctxImpl->ctx);
341 miss = SSL_CTX_sess_misses(ctxImpl->ctx);
342 tmos = SSL_CTX_sess_timeouts(ctxImpl->ctx);
343
344// Flush the cache
345//
346 tNow = time(0);
347 SSL_CTX_flush_sessions(ctxImpl->ctx, tNow);
348
349// Print some stuff should debugging be on
350//
352 {char mBuff[512];
353 snprintf(mBuff, sizeof(mBuff), "sess=%d hits=%d miss=%d timeouts=%d",
354 sesn, hits, miss, tmos);
355 DBG_CTX("Cache flushed; " <<mBuff);
356 }
357 } while(true);
358
359// If we are here the context that started us has gone away and we are done
360//
361 bool keepctx = ctxImpl->crlRunning;
362 ctxImpl->flsRunning = false;
363 ctxImpl->crlMutex.UnLock();
364 if (!keepctx) delete ctxImpl;
365 return (void *)0;
366}
367
368/******************************************************************************/
369/* S e t u p _ F l u s h e r */
370/******************************************************************************/
371
372bool Setup_Flusher(XrdTlsContextImpl *pImpl, int flushT)
373{
374 pthread_t tid;
375 int rc;
376
377// Set the new flush interval
378//
379 pImpl->crlMutex.WriteLock();
380 pImpl->flushT = flushT;
381 pImpl->crlMutex.UnLock();
382
383// If the flush thread is already running, then wake it up to get the new value
384//
385 if (pImpl->flsRunning)
386 {pImpl->flsCVar->Signal();
387 return true;
388 }
389
390// Start the flusher thread
391//
392 pImpl->flsCVar = new XrdSysCondVar();
393 if ((rc = XrdSysThread::Run(&tid, XrdTlsFlush::Flusher, (void *)pImpl,
394 0, "Cache Flusher")))
395 {char eBuff[512];
396 snprintf(eBuff, sizeof(eBuff),
397 "Unable to start cache flusher thread; rc=%d", rc);
398 XrdTls::Emsg("SessCache:", eBuff, false);
399 return false;
400 }
401
402// Finish up
403//
404 pImpl->flsRunning = true;
405 SSL_CTX_set_session_cache_mode(pImpl->ctx, SSL_SESS_CACHE_NO_AUTO_CLEAR);
406 return true;
407}
408}
409
410/******************************************************************************/
411/* S S L T h r e a d i n g S u p p o r t */
412/******************************************************************************/
413
414// The following may confusing because SSL MT support is somewhat bizarre.
415// Versions < 1.0 require a numeric thread_id and lock callbasks.
416// Versions < 1.1 require a lock_callbacks but the thread_is callback is
417// optional. While the numeric thread_id callback can be used
418// it's deprecated and fancier pointer/numeric call should be
419// used. In our case, we use the deprecated version.
420// Versions >- 1.1 Do not need any callbacks as all threading functions are
421// internally defined to use native MT functions.
422
423#if OPENSSL_VERSION_NUMBER < 0x10100000L && defined(OPENSSL_THREADS)
424namespace
425{
426#define XRDTLS_SET_CALLBACKS 1
427#ifdef __solaris__
428extern "C" {
429#endif
430
431template<bool is32>
432struct tlsmix;
433
434template<>
435struct tlsmix<false> {
436 static unsigned long mixer(unsigned long x) {
437 // mixer based on splitmix64
438 x ^= x >> 30;
439 x *= 0xbf58476d1ce4e5b9UL;
440 x ^= x >> 27;
441 x *= 0x94d049bb133111ebUL;
442 x ^= x >> 31;
443 return x;
444 }
445};
446
447template<>
448struct tlsmix<true> {
449 static unsigned long mixer(unsigned long x) {
450 // mixer based on murmurhash3
451 x ^= x >> 16;
452 x *= 0x85ebca6bU;
453 x ^= x >> 13;
454 x *= 0xc2b2ae35U;
455 x ^= x >> 16;
456 return x;
457 }
458};
459
460unsigned long sslTLS_id_callback(void)
461{
462 // base thread-id on the id given by XrdSysThread;
463 // but openssl 1.0 uses thread-id as a key for looking
464 // up per thread crypto ERR structures in a hash-table.
465 // So mix bits so that the table's hash function gives
466 // better distribution.
467
468 unsigned long x = (unsigned long)XrdSysThread::ID();
469 return tlsmix<sizeof(unsigned long)==4>::mixer(x);
470}
471
472XrdSysMutex *MutexVector = 0;
473
474void sslTLS_lock(int mode, int n, const char *file, int line)
475{
476// Use exclusive locks. At some point, SSL categorizes these as read and
477// write locks but it's not clear when this actually occurs, sigh.
478//
479 if (mode & CRYPTO_LOCK) MutexVector[n].Lock();
480 else MutexVector[n].UnLock();
481}
482#ifdef __solaris__
483}
484#endif
485} // namespace
486#else
487#undef XRDTLS_SET_CALLBACKS
488#endif
489
490/******************************************************************************/
491/* F i l e L o c a l D e f i n i t i o n s */
492/******************************************************************************/
493
494namespace
495{
496// The following is the default cipher list. Note that for OpenSSL v1.0.2+ we
497// use the recommended cipher list from Mozilla. Otherwise, we use the dumber
498// less secure ciphers as older versions of openssl have issues with them. See
499// ssl-config.mozilla.org/#config=intermediate&openssl=1.0.2k&guideline=5.4
500//
501#if OPENSSL_VERSION_NUMBER >= 0x10002000L
502const char *sslCiphers = "ECDHE-ECDSA-AES128-GCM-SHA256:"
503 "ECDHE-RSA-AES128-GCM-SHA256:"
504 "ECDHE-ECDSA-AES256-GCM-SHA384:"
505 "ECDHE-RSA-AES256-GCM-SHA384:"
506 "ECDHE-ECDSA-CHACHA20-POLY1305:"
507 "ECDHE-RSA-CHACHA20-POLY1305:"
508 "DHE-RSA-AES128-GCM-SHA256:"
509 "DHE-RSA-AES256-GCM-SHA384";
510#else
511const char *sslCiphers = "ALL:!LOW:!EXP:!MD5:!MD2";
512#endif
513
514XrdSysMutex dbgMutex, tlsMutex;
515XrdSys::RAtomic<bool> initDbgDone{ false };
516bool initTlsDone{ false };
517
518/******************************************************************************/
519/* I n i t T L S */
520/******************************************************************************/
521
522void InitTLS() // This is strictly a one-time call!
523{
524 XrdSysMutexHelper tlsHelper(tlsMutex);
525
526// Make sure we are not trying to load the ssl library more than once. This can
527// happen when a server and a client instance happen to be both defined.
528//
529 if (initTlsDone) return;
530 initTlsDone = true;
531
532// SSL library initialisation
533//
534 SSL_library_init();
535 OpenSSL_add_all_algorithms();
536 SSL_load_error_strings();
537 OpenSSL_add_all_ciphers();
538#if OPENSSL_VERSION_NUMBER < 0x30000000L
539 ERR_load_BIO_strings();
540#endif
541 ERR_load_crypto_strings();
542
543// Set callbacks if we need to do this
544//
545#ifdef XRDTLS_SET_CALLBACKS
546
547 int n = CRYPTO_num_locks();
548 if (n > 0)
549 {MutexVector = new XrdSysMutex[n];
550 CRYPTO_set_locking_callback(sslTLS_lock);
551 }
552 CRYPTO_set_id_callback(sslTLS_id_callback);
553
554#endif
555}
556
557/******************************************************************************/
558/* F a t a l */
559/******************************************************************************/
560
561void Fatal(std::string *eMsg, const char *msg, bool sslmsg=false)
562{
563// If there is an outboard error string object, return the message there.
564//
565 if (eMsg) *eMsg = msg;
566
567// Now route the message to the message callback function. If this is an ssl
568// related error we also flush the ssl error queue to prevent suprises.
569//
570 XrdTls::Emsg("TLS_Context:", msg, sslmsg);
571}
572
573/******************************************************************************/
574/* G e t T l s M e t h o d */
575/******************************************************************************/
576
577const char *GetTlsMethod(const SSL_METHOD *&meth)
578{
579#if OPENSSL_VERSION_NUMBER > 0x1010000fL /* v1.1.0 */
580 meth = TLS_method();
581#else
582 meth = SSLv23_method();
583#endif
584 if (meth == 0) return "No negotiable TLS method available.";
585 return 0;
586}
587
588/******************************************************************************/
589/* V e r P a t h s */
590/******************************************************************************/
591
592bool VerPaths(const char *cert, const char *pkey,
593 const char *cadr, const char *cafl, std::string &eMsg)
594{
595 static const mode_t cert_mode = S_IRUSR | S_IWUSR | S_IRWXG | S_IROTH;
596 static const mode_t pkey_mode = S_IRUSR | S_IWUSR;
597 static const mode_t cadr_mode = S_IRWXU | S_IRGRP | S_IXGRP
598 | S_IROTH | S_IXOTH;
599 static const mode_t cafl_mode = S_IRUSR | S_IWUSR | S_IRWXG | S_IROTH;
600 const char *emsg;
601
602// If the ca cert directory is present make sure it's a directory and
603// only the ower can write to that directory (anyone can read from it).
604//
605 if (cadr && (emsg = XrdOucUtils::ValPath(cadr, cadr_mode, true)))
606 {eMsg = "Unable to use CA cert directory ";
607 eMsg += cadr; eMsg += "; "; eMsg += emsg;
608 return false;
609 }
610
611// If a ca cert file is present make sure it's a file and only the owner can
612// write it (anyone can read it).
613//
614 if (cafl && (emsg = XrdOucUtils::ValPath(cafl, cafl_mode, false)))
615 {eMsg = "Unable to use CA cert file ";
616 eMsg += cafl; eMsg += "; "; eMsg += emsg;
617 return false;
618 }
619
620// If a private key is provided as a filesystem path, verify it's a file and only the
621// owner has access to it. If it's a PKCS#11 URI, it will be validated later.
622//
623 if (pkey && pkey[0] == '/' && (emsg = XrdOucUtils::ValPath(pkey, pkey_mode, false)))
624 {eMsg = "Unable to use key file ";
625 eMsg += pkey; eMsg += "; "; eMsg += emsg;
626 return false;
627 }
628
629// If a cert file is present then make sure it's a file. If a keyfile is
630// present then anyone can read it but only the owner can write it.
631// Otherwise, only the owner can gave access to it (it contains the key).
632//
633 if (cert)
634 {mode_t cmode = (pkey ? cert_mode : pkey_mode);
635 if ((emsg = XrdOucUtils::ValPath(cert, cmode, false)))
636 {if (pkey) eMsg = "Unable to use cert file ";
637 else eMsg = "Unable to use cert+key file ";
638 eMsg += cert; eMsg += "; "; eMsg += emsg;
639 return false;
640 }
641 }
642
643// All tests succeeded.
644//
645 return true;
646}
647
648/******************************************************************************/
649/* V e r C B */
650/******************************************************************************/
651
652extern "C"
653{
658int verifyPeerCB(int aOK, X509_STORE_CTX *x509P) {
659 if (!aOK) {
660 SSL *ssl = (SSL*)X509_STORE_CTX_get_ex_data(x509P, SSL_get_ex_data_X509_STORE_CTX_idx());
661 SSL_CTX *sslCtx = SSL_get_SSL_CTX(ssl);
662 XrdTlsContext *self = (XrdTlsContext*)SSL_CTX_get_ex_data(sslCtx, XrdTlsContext::ctxIndex);
663 bool LogVF = (self->GetParams()->opts & XrdTlsContext::logVF) != 0;
664 bool crlAllowMissingCA = (self->GetParams()->opts & XrdTlsContext::crlAM) != 0;
665 if (crlAllowMissingCA) {
666 int err = X509_STORE_CTX_get_error(x509P);
667 if (err == X509_V_ERR_UNABLE_TO_GET_CRL) {
668 X509_STORE_CTX_set_error(x509P, X509_V_OK);
669 return 1;
670 }
671 }
672 if (LogVF) {
673 X509 *cert = X509_STORE_CTX_get_current_cert(x509P);
674 int depth = X509_STORE_CTX_get_error_depth(x509P);
675 int err = X509_STORE_CTX_get_error(x509P);
676 char name[512], info[1024];
677
678 X509_NAME_oneline(X509_get_subject_name(cert), name, sizeof(name));
679 snprintf(info,sizeof(info),"Cert verification failed for DN=%s",name);
680 XrdTls::Emsg("CertVerify:", info, false);
681
682 X509_NAME_oneline(X509_get_issuer_name(cert), name, sizeof(name));
683 snprintf(info,sizeof(info),"Failing cert issuer=%s", name);
684 XrdTls::Emsg("CertVerify:", info, false);
685
686 snprintf(info, sizeof(info), "Error %d at depth %d [%s]", err, depth,
687 X509_verify_cert_error_string(err));
688 XrdTls::Emsg("CertVerify:", info, true);
689 }
690 }
691 return aOK;
692}
693
694}
695
696} // Anonymous namespace end
697
698/******************************************************************************/
699/* C o n s t r u c t o r */
700/******************************************************************************/
701
702#define KILL_CTX(x) if (x) {SSL_CTX_free(x); x = 0;}
703
704#define FATAL(msg) {Fatal(eMsg, msg); KILL_CTX(pImpl->ctx); return;}
705
706#define FATAL_SSL(msg) {Fatal(eMsg, msg, true); KILL_CTX(pImpl->ctx); return;}
707
708int XrdTlsContext::ctxIndex = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
709
710XrdTlsContext::XrdTlsContext(const char *cert, const char *key,
711 const char *caDir, const char *caFile,
712 uint64_t opts, std::string *eMsg)
713 : pImpl( new XrdTlsContextImpl(this) )
714{
715 class ctx_helper
716 {public:
717
718 void Keep() {ctxLoc = 0;}
719
720 ctx_helper(SSL_CTX **ctxP) : ctxLoc(ctxP) {}
721 ~ctx_helper() {if (ctxLoc && *ctxLoc)
722 {SSL_CTX_free(*ctxLoc); *ctxLoc = 0;}
723 }
724 private:
725 SSL_CTX **ctxLoc;
726 } ctx_tracker(&pImpl->ctx);
727
728 static const uint64_t sslOpts = SSL_OP_ALL
729 | SSL_OP_NO_SSLv2
730 | SSL_OP_NO_SSLv3
731 | SSL_OP_NO_COMPRESSION
732#ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
733 | SSL_OP_IGNORE_UNEXPECTED_EOF
734#endif
735#if OPENSSL_VERSION_NUMBER >= 0x10101000L
736 | SSL_OP_NO_RENEGOTIATION
737#endif
738 ;
739
740 std::string certFN, eText;
741 const char *emsg;
742
743// Assume we will fail
744//
745 pImpl->ctx = 0;
746
747// Verify that initialzation has occurred. This is not heavy weight as
748// there will usually be no more than two instances of this object.
749//
750 if (!initDbgDone)
751 {XrdSysMutexHelper dbgHelper(dbgMutex);
752 if (!initDbgDone)
753 {const char *dbg;
754 if (!(opts & servr) && (dbg = getenv("XRDTLS_DEBUG")))
755 {int dbgOpts = 0;
756 if (strstr(dbg, "ctx")) dbgOpts |= XrdTls::dbgCTX;
757 if (strstr(dbg, "sok")) dbgOpts |= XrdTls::dbgSOK;
758 if (strstr(dbg, "sio")) dbgOpts |= XrdTls::dbgSIO;
759 if (!dbgOpts) dbgOpts = XrdTls::dbgALL;
761 }
762 if ((emsg = Init())) FATAL(emsg);
763 initDbgDone = true;
764 }
765 }
766
767// If no CA cert information is specified and this is not a server context,
768// then get the paths from the environment. They must exist as we need to
769// verify peer certs in order to verify target host names client-side. We
770// also use this setupt to see if we should use a specific cert and key.
771//
772 if (!(opts & servr))
773 {if (!caDir && !caFile)
774 {caDir = getenv("X509_CERT_DIR");
775 caFile = getenv("X509_CERT_FILE");
776 if (!caDir && !caFile)
777 FATAL("No CA cert specified; host identity cannot be verified.");
778 }
779 if (!key) key = getenv("X509_USER_KEY");
780 if (!cert) cert = getenv("X509_USER_PROXY");
781 if (!cert)
782 {struct stat Stat;
783 long long int uid = static_cast<long long int>(getuid());
784 certFN = std::string("/tmp/x509up_u") + std::to_string(uid);
785 if (!stat(certFN.c_str(), &Stat)) cert = certFN.c_str();
786 }
787 }
788
789// Before we try to use any specified files, make sure they exist, are of
790// the right type and do not have excessive access privileges.
791// .a
792 if (!VerPaths(cert, key, caDir, caFile, eText)) FATAL( eText.c_str());
793
794// Copy parameters to out parm structure.
795//
796 if (cert) {
797 pImpl->Parm.cert = cert;
798 //This call should not fail as a stat is already performed in the call of VerPaths() above
799 XrdOucUtils::getModificationTime(pImpl->Parm.cert.c_str(),pImpl->lastCertModTime);
800 }
801 if (key) pImpl->Parm.pkey = key;
802 if (caDir) pImpl->Parm.cadir = caDir;
803 if (caFile) pImpl->Parm.cafile = caFile;
804 pImpl->Parm.opts = opts;
805 if (opts & crlRF) {
806 // What we store in crlRF is the time in minutes, convert it back to seconds
807 pImpl->Parm.crlRT = static_cast<int>((opts & crlRF) >> crlRS) * 60;
808 }
809
810// Get the correct method to use for TLS and check if successful create a
811// server context that uses the method.
812//
813 const SSL_METHOD *meth;
814 emsg = GetTlsMethod(meth);
815 if (emsg) FATAL(emsg);
816
817 pImpl->ctx = SSL_CTX_new(meth);
818
819// Make sure we have a context here
820//
821 if (pImpl->ctx == 0) FATAL_SSL("Unable to allocate TLS context!");
822
823 //Add the XrdTlsContext object as extra information for OpenSSL callback re-use
824 SSL_CTX_set_ex_data(pImpl->ctx, ctxIndex, this);
825
826// Always prohibit SSLv2 & SSLv3 as these are not secure.
827//
828 SSL_CTX_set_options(pImpl->ctx, sslOpts);
829
830// Handle session re-negotiation automatically
831//
832// SSL_CTX_set_mode(pImpl->ctx, sslMode);
833
834// Turn off the session cache as it's useless with peer cert chains
835//
836 SSL_CTX_set_session_cache_mode(pImpl->ctx, SSL_SESS_CACHE_OFF);
837
838// Establish the CA cert locations, if specified. Then set the verification
839// depth and turn on peer cert validation. For now, we don't set a callback.
840// In the future we may to grab debugging information.
841//
842 if ((caDir || caFile) && !(opts & clcOF))
843 {if (!SSL_CTX_load_verify_locations(pImpl->ctx, caFile, caDir))
844 FATAL_SSL("Unable to load the CA cert file or directory.");
845
846 int vDepth = (opts & vdept) >> vdepS;
847 SSL_CTX_set_verify_depth(pImpl->ctx, (vDepth ? vDepth : 9));
848
849 bool LogVF = (opts & logVF) != 0;
850 bool crlAllowMissingCA = (opts & crlAM) != 0;
851
852 if (crlAllowMissingCA || LogVF) {
853 SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_PEER, verifyPeerCB);
854 } else {
855 SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_PEER, 0);
856 }
857
858 unsigned long xFlags = (opts & nopxy ? 0 : X509_V_FLAG_ALLOW_PROXY_CERTS);
859 if (opts & crlON)
860 {xFlags |= X509_V_FLAG_CRL_CHECK;
861 if (opts & crlFC) xFlags |= X509_V_FLAG_CRL_CHECK_ALL;
862 }
863 if (opts) X509_STORE_set_flags(SSL_CTX_get_cert_store(pImpl->ctx),xFlags);
864 } else {
865 SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_NONE, 0);
866 }
867
868// Set cipher list
869//
870 if (!SSL_CTX_set_cipher_list(pImpl->ctx, sslCiphers))
871 FATAL_SSL("Unable to set SSL cipher list; no supported ciphers.");
872
873// If we need to enable eliptic-curve support, do so now. Note that for
874// OpenSSL 1.1.0+ this is automatically done for us.
875//
876#if SSL_CTRL_SET_ECDH_AUTO
877 SSL_CTX_set_ecdh_auto(pImpl->ctx, 1);
878#endif
879
880// We normally handle renegotiation during reads and writes or selective
881// prohibit on a SSL socket basis. The calle may request this be applied
882// to all SSL's generated from this context. If so, do it here.
883//
884 if (opts & artON) SSL_CTX_set_mode(pImpl->ctx, SSL_MODE_AUTO_RETRY);
885
886// If there is no cert then assume this is a generic context for a client
887//
888 if (cert == 0)
889 {ctx_tracker.Keep();
890 return;
891 }
892
893// We have a cert. If the key is missing then we assume the key is in the
894// cert file (ssl will complain if it isn't).
895//
896 if (!key) key = cert;
897
898// Load certificate
899//
900 if (SSL_CTX_use_certificate_chain_file(pImpl->ctx, cert) != 1)
901 FATAL_SSL("Unable to create TLS context; invalid certificate.");
902
903// Load the private key
904//
905 if (key[0] == 'p') {
906 if (!EnsureOpenSSLConfigLoaded())
907 FATAL_SSL("Unable to load OpenSSL configuration; cannot initialize pkcs11.");
908
909#ifdef XRDTLS_HAVE_OSSL_STORE
910 // OpenSSL 3.x+: Use OSSL_STORE API with pkcs11-provider in an ISOLATED context
911 // This prevents PKCS11 from affecting other TLS operations (e.g., SciTokens library)
912
913 OSSL_PROVIDER *defaultProv = nullptr;
914
915 // Initialize isolated PKCS11 context
916 // This loads the OPENSSL_CONF into an isolated context so PKCS11 doesn't affect
917 // other libraries in the process (like SciTokens)
918 if (!InitIsolatedPKCS11Context(&pImpl->pkcs11LibCtx, &pImpl->pkcs11Provider, &defaultProv)) {
919 FATAL_SSL("Failed to initialize isolated PKCS11 context. Check OPENSSL_CONF and pkcs11-provider installation.");
920 }
921
922 // Open PKCS11 URI using the isolated context
923 OSSL_STORE_CTX *store_ctx = OSSL_STORE_open_ex(key, pImpl->pkcs11LibCtx, nullptr,
924 nullptr, nullptr, nullptr, nullptr, nullptr);
925 if (!store_ctx) {
926 if (defaultProv) OSSL_PROVIDER_unload(defaultProv);
927 FATAL_SSL("Failed to open PKCS11 URI in isolated context.");
928 }
929
930 EVP_PKEY *priv_key = nullptr;
931 while (!OSSL_STORE_eof(store_ctx)) {
932 OSSL_STORE_INFO *info = OSSL_STORE_load(store_ctx);
933 if (info) {
934 int type = OSSL_STORE_INFO_get_type(info);
935 if (type == OSSL_STORE_INFO_PKEY) {
936 priv_key = OSSL_STORE_INFO_get1_PKEY(info);
937 OSSL_STORE_INFO_free(info);
938 break;
939 }
940 OSSL_STORE_INFO_free(info);
941 }
942 }
943 OSSL_STORE_close(store_ctx);
944 if (defaultProv) OSSL_PROVIDER_unload(defaultProv);
945
946 if (!priv_key)
947 FATAL_SSL("Failed to load private key from PKCS11 URI in isolated context.");
948
949 if (SSL_CTX_use_PrivateKey(pImpl->ctx, priv_key) != 1) {
950 EVP_PKEY_free(priv_key);
951 FATAL_SSL("Failed to have SSL context use private key");
952 }
953 EVP_PKEY_free(priv_key);
954
955#elif defined(XRDTLS_HAVE_ENGINE)
956 // OpenSSL 1.1.x (EL8): Use ENGINE API with libp11/engine_pkcs11
957 ENGINE *e = ENGINE_by_id("pkcs11");
958 if (e) {
959 const char* modulePath = getenv("PKCS11_MODULE_PATH");
960 if (modulePath && modulePath[0]) {
961 if (!ENGINE_ctrl_cmd_string(e, "MODULE_PATH", modulePath, 0)) {
962 ENGINE_free(e);
963 FATAL_SSL("Unable to configure pkcs11 engine MODULE_PATH");
964 }
965 }
966 if(!ENGINE_init(e)) {
967 ENGINE_free(e);
968 FATAL_SSL("Unable to initialize pkcs11 engine");
969 }
970 } else {
971 FATAL_SSL("Unable to create pkcs11 engine");
972 }
973 auto priv_key = ENGINE_load_private_key(e, key, nullptr, nullptr);
974
975 if (!priv_key) {
976 FATAL_SSL("Failed to load private key through engine");
977 }
978 if (SSL_CTX_use_PrivateKey(pImpl->ctx, priv_key) != 1)
979 FATAL_SSL("Failed to have SSL context use private key");
980 EVP_PKEY_free(priv_key);
981#else
982 FATAL_SSL("PKCS11 support not available.");
983#endif
984
985 } else if (SSL_CTX_use_PrivateKey_file(pImpl->ctx, key, SSL_FILETYPE_PEM) != 1 )
986 FATAL_SSL("Unable to create TLS context; invalid private key.");
987
988// Make sure the key and certificate file match.
989//
990 if (SSL_CTX_check_private_key(pImpl->ctx) != 1 )
991 FATAL_SSL("Unable to create TLS context; cert-key mismatch.");
992
993// All went well, start the CRL refresh thread and keep the context.
994//
995 if(opts & rfCRL) {
997 }
998 ctx_tracker.Keep();
999}
1000
1001/******************************************************************************/
1002/* D e s t r u c t o r */
1003/******************************************************************************/
1004
1006{
1007// We can delet eour implementation of there is no refresh thread running. If
1008// there is then the refresh thread has to delete the implementation.
1009//
1010 if (pImpl->crlRunning | pImpl->flsRunning)
1011 {pImpl->crlMutex.WriteLock();
1012 pImpl->owner = 0;
1013 pImpl->crlMutex.UnLock();
1014 } else delete pImpl;
1015}
1016
1017/******************************************************************************/
1018/* C l o n e */
1019/******************************************************************************/
1020
1021XrdTlsContext *XrdTlsContext::Clone(bool full,bool startCRLRefresh)
1022{
1023 XrdTlsContext::CTX_Params &my = pImpl->Parm;
1024 const char *cert = (my.cert.size() ? my.cert.c_str() : 0);
1025 const char *pkey = (my.pkey.size() ? my.pkey.c_str() : 0);
1026 const char *caD = (my.cadir.size() ? my.cadir.c_str() : 0);
1027 const char *caF = (my.cafile.size() ? my.cafile.c_str() : 0);
1028
1029// If this is a non-full context, get rid of any verification
1030//
1031 if (!full) caD = caF = 0;
1032
1033// Cloning simply means getting a object with the old parameters.
1034//
1035 uint64_t myOpts = my.opts;
1036 if(startCRLRefresh){
1038 } else {
1040 }
1041 XrdTlsContext *xtc = new XrdTlsContext(cert, pkey, caD, caF, myOpts);
1042
1043// Verify that the context was built
1044//
1045 if (xtc->isOK()) {
1046 if(pImpl->sessionCacheOpts != -1){
1047 //A SessionCache() call was done for the current context, so apply it for this new cloned context
1048 xtc->SessionCache(pImpl->sessionCacheOpts,pImpl->sessionCacheId.c_str(),pImpl->sessionCacheId.size());
1049 }
1050 return xtc;
1051 }
1052
1053// We failed, cleanup.
1054//
1055 delete xtc;
1056 return 0;
1057}
1058
1059/******************************************************************************/
1060/* C o n t e x t */
1061/******************************************************************************/
1062
1064{
1065 return pImpl->ctx;
1066}
1067
1068/******************************************************************************/
1069/* G e t P a r a m s */
1070/******************************************************************************/
1071
1073{
1074 return &pImpl->Parm;
1075}
1076
1077/******************************************************************************/
1078/* I n i t */
1079/******************************************************************************/
1080
1082{
1083
1084// Disallow use if this object unless SSL provides thread-safety!
1085//
1086#ifndef OPENSSL_THREADS
1087 return "Installed OpenSSL lacks the required thread support!";
1088#endif
1089
1090// Initialize the library (one time call)
1091//
1092 InitTLS();
1093 return 0;
1094}
1095
1096/******************************************************************************/
1097/* i s O K */
1098/******************************************************************************/
1099
1101{
1102 return pImpl->ctx != 0;
1103}
1104
1105/******************************************************************************/
1106/* S e s s i o n */
1107/******************************************************************************/
1108
1109// Note: The reason we handle the x509 store update here is because allow the
1110// SSL context to be exported and then have no lock control over it. This may
1111// happen for transient purposes other than creating sessions. Once we
1112// disallow direct access to the context, the exchange can happen in the
1113// refresh thread which simplifies this whole process.
1114
1116{
1117#if OPENSSL_VERSION_NUMBER >= 0x10002000L
1118
1119 EPNAME("Session");
1120 SSL *ssl;
1121
1122// Check if we have a refreshed context. If so, we need to replace the X509
1123// store in the current context with the new one before we create the session.
1124//
1125 pImpl->crlMutex.ReadLock();
1126 if (!(pImpl->ctxnew))
1127 {ssl = SSL_new(pImpl->ctx);
1128 pImpl->crlMutex.UnLock();
1129 return ssl;
1130 }
1131
1132// Things have changed, so we need to take the long route here. We need to
1133// replace the x509 cache with the current cache. Get a R/W lock now.
1134//
1135 pImpl->crlMutex.UnLock();
1136 pImpl->crlMutex.WriteLock();
1137
1138// If some other thread beat us to the punch, just return what we have.
1139//
1140 if (!(pImpl->ctxnew))
1141 {ssl = SSL_new(pImpl->ctx);
1142 pImpl->crlMutex.UnLock();
1143 return ssl;
1144 }
1145
1146// Do some tracing
1147//
1148 DBG_CTX("Replacing x509 store with new contents.");
1149
1150// Get the new store and set it in our context. Setting the store is black
1151// magic. For OpenSSL < 1.1, Two stores need to be set with the "set1" variant.
1152// Newer version only require SSL_CTX_set1_cert_store() to be used.
1153//
1154 //We have a new context generated by Refresh, so we must use it.
1155 XrdTlsContext * ctxnew = pImpl->ctxnew;
1156
1157 /*X509_STORE *newX509 = SSL_CTX_get_cert_store(ctxnew->pImpl->ctx);
1158 SSL_CTX_set1_verify_cert_store(pImpl->ctx, newX509);
1159 SSL_CTX_set1_chain_cert_store(pImpl->ctx, newX509);*/
1160 //The above two macros actually do not replace the certificate that has
1161 //to be used for that SSL session, so we will create the session with the SSL_CTX * of
1162 //the TlsContext created by Refresh()
1163 //First, free the current SSL_CTX, if it is used by any transfer, it will just decrease
1164 //the reference counter of it. There is therefore no risk of double free...
1165 SSL_CTX_free(pImpl->ctx);
1166 pImpl->ctx = ctxnew->pImpl->ctx;
1167
1168 //Update ex_data to point to this (the surviving owner), not the
1169 //cloned context which is about to be deleted.
1170 SSL_CTX_set_ex_data(pImpl->ctx, ctxIndex, this);
1171
1172 //In the destructor of XrdTlsContextImpl, SSL_CTX_Free() is
1173 //called if ctx is != 0. As this new ctx is used by the session
1174 //we just created, we don't want that to happen. We therefore set it to 0.
1175 //The SSL_free called on the session will cleanup the context for us.
1176 ctxnew->pImpl->ctx = 0;
1177
1178// Save the generated context and clear it's presence
1179//
1180 XrdTlsContext *ctxold = pImpl->ctxnew;
1181 pImpl->ctxnew = 0;
1182
1183// Generate a new session (might as well to keep the lock we have)
1184//
1185 ssl = SSL_new(pImpl->ctx);
1186
1187// OK, now we can drop all the locks and get rid of the old context
1188//
1189 pImpl->crlMutex.UnLock();
1190 delete ctxold;
1191 return ssl;
1192
1193#else
1194// If we did not compile crl refresh code, we can simply return the OpenSSL
1195// session using our context. Otherwise, we need to see if we have a refreshed
1196// context and if so, carry forward the X509_store to our original context.
1197//
1198 return SSL_new(pImpl->ctx);
1199#endif
1200}
1201
1202/******************************************************************************/
1203/* S e s s i o n C a c h e */
1204/******************************************************************************/
1205
1206int XrdTlsContext::SessionCache(int opts, const char *id, int idlen)
1207{
1208 static const int doSet = scSrvr | scClnt | scOff;
1209 long sslopt = 0;
1210 int flushT = opts & scFMax;
1211
1212 pImpl->sessionCacheOpts = opts;
1213 pImpl->sessionCacheId = id;
1214
1215// If initialization failed there is nothing to do
1216//
1217 if (pImpl->ctx == 0) return 0;
1218
1219// Set options as appropriate
1220//
1221 if (opts & doSet)
1222 {if (opts & scOff) sslopt = SSL_SESS_CACHE_OFF;
1223 else {if (opts & scSrvr) sslopt = SSL_SESS_CACHE_SERVER;
1224 if (opts & scClnt) sslopt |= SSL_SESS_CACHE_CLIENT;
1225 }
1226 }
1227
1228// Check if we should set any cache options or simply get them
1229//
1230 if (!(opts & doSet)) sslopt = SSL_CTX_get_session_cache_mode(pImpl->ctx);
1231 else {sslopt = SSL_CTX_set_session_cache_mode(pImpl->ctx, sslopt);
1232 if (opts & scOff) SSL_CTX_set_options(pImpl->ctx, SSL_OP_NO_TICKET);
1233 }
1234
1235// Compute what he previous cache options were
1236//
1237 opts = scNone;
1238 if (sslopt & SSL_SESS_CACHE_SERVER) opts |= scSrvr;
1239 if (sslopt & SSL_SESS_CACHE_CLIENT) opts |= scClnt;
1240 if (!opts) opts = scOff;
1241 if (sslopt & SSL_SESS_CACHE_NO_AUTO_CLEAR) opts |= scKeep;
1242 opts |= (static_cast<int>(pImpl->flushT) & scFMax);
1243
1244// Set the id is so wanted
1245//
1246 if (id && idlen > 0)
1247 {if (!SSL_CTX_set_session_id_context(pImpl->ctx,
1248 (unsigned const char *)id,
1249 (unsigned int)idlen)) opts |= scIdErr;
1250 }
1251
1252// If a flush interval was specified and it is different from what we have
1253// then reset the flush interval.
1254//
1255 if (flushT && flushT != pImpl->flushT)
1256 XrdTlsFlush::Setup_Flusher(pImpl, flushT);
1257
1258// All done
1259//
1260 return opts;
1261}
1262
1263/******************************************************************************/
1264/* S e t C o n t e x t C i p h e r s */
1265/******************************************************************************/
1266
1267bool XrdTlsContext::SetContextCiphers(const char *ciphers)
1268{
1269 if (pImpl->ctx && SSL_CTX_set_cipher_list(pImpl->ctx, ciphers)) return true;
1270
1271 char eBuff[2048];
1272 snprintf(eBuff,sizeof(eBuff),"Unable to set context ciphers '%s'",ciphers);
1273 Fatal(0, eBuff, true);
1274 return false;
1275}
1276
1277/******************************************************************************/
1278/* S e t D e f a u l t C i p h e r s */
1279/******************************************************************************/
1280
1281void XrdTlsContext::SetDefaultCiphers(const char *ciphers)
1282{
1283 sslCiphers = ciphers;
1284}
1285
1286/******************************************************************************/
1287/* S e t C r l R e f r e s h */
1288/******************************************************************************/
1289
1291{
1292#if OPENSSL_VERSION_NUMBER >= 0x10002000L
1293
1294 pthread_t tid;
1295 int rc;
1296
1297// If it's negative or equal to 0, use the current setting
1298//
1299 if (refsec <= 0)
1300 {pImpl->crlMutex.WriteLock();
1301 refsec = pImpl->Parm.crlRT;
1302 pImpl->crlMutex.UnLock();
1303 if (!refsec) refsec = XrdTlsContext::DEFAULT_CRL_REF_INT_SEC;
1304 }
1305
1306// Make sure this is at least 60 seconds between refreshes
1307//
1308// if (refsec < 60) refsec = 60;
1309
1310// We will set the new interval and start a refresh thread if not running.
1311//
1312 pImpl->crlMutex.WriteLock();
1313 pImpl->Parm.crlRT = refsec;
1314 if (!pImpl->crlRunning)
1315 {if ((rc = XrdSysThread::Run(&tid, XrdTlsCrl::Refresh, (void *)pImpl,
1316 0, "CRL Refresh")))
1317 {char eBuff[512];
1318 snprintf(eBuff, sizeof(eBuff),
1319 "Unable to start CRL refresh thread; rc=%d", rc);
1320 XrdTls::Emsg("CrlRefresh:", eBuff, false);
1321 pImpl->crlMutex.UnLock();
1322 return false;
1323 } else pImpl->crlRunning = true;
1324 pImpl->crlMutex.UnLock();
1325 }
1326
1327// All done
1328//
1329 return true;
1330
1331#else
1332// We use features present on OpenSSL 1.02 and above to implement crl refresh.
1333// Older version are too difficult to deal with. Issue a message if this
1334// feature is being enabled on an old version.
1335//
1336 XrdTls::Emsg("CrlRefresh:", "Refreshing CRLs only supported in "
1337 "OpenSSL version >= 1.02; CRL refresh disabled!", false);
1338 return false;
1339#endif
1340}
1341
1342/******************************************************************************/
1343/* x 5 0 9 V e r i f y */
1344/******************************************************************************/
1345
1347{
1348 return !(pImpl->Parm.cadir.empty()) || !(pImpl->Parm.cafile.empty());
1349}
1350
1352 const std::string certPath = pImpl->Parm.cert;
1353 if(certPath.empty()) {
1354 //No certificate provided, should not happen though
1355 return false;
1356 }
1357 time_t modificationTime;
1358 if(!XrdOucUtils::getModificationTime(certPath.c_str(),modificationTime)){
1359 if (pImpl->lastCertModTime != modificationTime) {
1360 //The certificate file has changed
1361 pImpl->lastCertModTime = modificationTime;
1362 return true;
1363 }
1364 }
1365 return false;
1366}
1367
1369 if (setting)
1370 {pImpl->Parm.opts &= ~clcOF;
1371 bool LogVF = (pImpl->Parm.opts & logVF) != 0;
1372 bool crlAllowMissingCA = (pImpl->Parm.opts & crlAM) != 0;
1373
1374 if (LogVF || crlAllowMissingCA)
1375 SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_PEER, verifyPeerCB);
1376 else
1377 SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_PEER, 0);
1378 } else
1379 {pImpl->Parm.opts |= clcOF;
1380 SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_NONE, 0);
1381 }
1382}
#define EPNAME(x)
struct stat Stat
Definition XrdCks.cc:49
void Fatal(const char *op, const char *target)
Definition XrdCrc32c.cc:58
#define stat(a, b)
Definition XrdPosix.hh:101
#define eMsg(x)
struct myOpts opts
int emsg(int rc, char *msg)
if(Avsz)
#define FATAL_SSL(msg)
#define FATAL(msg)
#define DBG_CTX(y)
#define TRACING(x)
Definition XrdTrace.hh:70
static int getModificationTime(const char *path, time_t &modificationTime)
static const char * ValPath(const char *path, mode_t allow, bool isdir)
static int Run(pthread_t *, void *(*proc)(void *), void *arg, int opts=0, const char *desc=0)
static pthread_t ID(void)
static void Snooze(int seconds)
static const int scIdErr
Info: Id not set, is too long.
XrdTlsContext * Clone(bool full=true, bool startCRLRefresh=false)
~XrdTlsContext()
Destructor.
static const uint64_t vdept
Mask to isolate vdept.
static const int crlRS
Bits to shift vdept.
int SessionCache(int opts=scNone, const char *id=0, int idlen=0)
static void SetDefaultCiphers(const char *ciphers)
XrdTlsContext(const char *cert=0, const char *key=0, const char *cadir=0, const char *cafile=0, uint64_t opts=0, std::string *eMsg=0)
static const uint64_t clcOF
Disable client certificate request.
static const int scClnt
Turn on cache client mode.
static const int DEFAULT_CRL_REF_INT_SEC
Default CRL refresh interval in seconds.
static const uint64_t servr
This is a server context.
static const uint64_t rfCRL
Turn on the CRL refresh thread.
static const int scKeep
Info: TLS-controlled flush disabled.
static const uint64_t nopxy
Do not allow proxy certs.
static const int scNone
Do not change any option settings.
static const uint64_t logVF
Log verify failures.
static const uint64_t crlFC
Full crl chain checking.
static int ctxIndex
static const uint64_t crlON
Enables crl checking.
static const uint64_t artON
Auto retry Handshake.
static const int vdepS
Bits to shift vdept.
const CTX_Params * GetParams()
static const int scOff
Turn off cache.
static const char * Init()
bool newHostCertificateDetected()
bool SetContextCiphers(const char *ciphers)
static const int scFMax
static const uint64_t crlAM
Allow CA validation when CRL is missing (CRL soft-fail)
bool SetCrlRefresh(int refsec=-1)
static const int scSrvr
Turn on cache server mode (default)
void SetTlsClientAuth(bool setting)
static const uint64_t crlRF
Mask to isolate crl refresh in min.
static const int dbgSIO
Turn debugging in for socket I/O.
Definition XrdTls.hh:102
static const int dbgSOK
Turn debugging in for socket operations.
Definition XrdTls.hh:101
static const int dbgOUT
Force msgs to stderr for easier client debug.
Definition XrdTls.hh:104
static void Emsg(const char *tid, const char *msg=0, bool flush=true)
Definition XrdTls.cc:104
static const int dbgALL
Turn debugging for everything.
Definition XrdTls.hh:103
static const int dbgCTX
Turn debugging in for context operations.
Definition XrdTls.hh:100
static void SetDebug(int opts, XrdSysLogger *logP=0)
Definition XrdTls.cc:177
bool InitTLS()
Definition XrdClTls.cc:96
void * Refresh(void *parg)
bool Setup_Flusher(XrdTlsContextImpl *pImpl, int flushT)
void * Flusher(void *parg)
XrdSysTrace SysTrace("TLS", 0)
XrdTlsContextImpl(XrdTlsContext *p)
std::string sessionCacheId
XrdTlsContext * owner
XrdTlsContext::CTX_Params Parm
XrdTlsContext * ctxnew
XrdSysCondVar * flsCVar
XrdSysRWLock crlMutex
std::string cafile
-> ca cert file.
uint64_t opts
Options as passed to the constructor.
std::string cadir
-> ca cert directory.
int crlRT
crl refresh interval time in seconds
std::string pkey
-> private key path.
std::string cert
-> certificate path.