XRootD
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"
54 #include "XrdSys/XrdSysRAtomic.hh"
55 #include "XrdSys/XrdSysError.hh"
56 #include "XrdSys/XrdSysPthread.hh"
57 #include "XrdSys/XrdSysTimer.hh"
58 
59 #include "XrdTls/XrdTls.hh"
60 #include "XrdTls/XrdTlsContext.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 
71 namespace XrdTlsGlobal
72 {
74 };
75 
76 namespace
77 {
78 #ifndef OPENSSL_NO_CONF
79 bool 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
95 bool 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)
104 bool 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 
194 namespace XrdTlsCrl
195 {
196 // Inital entry for refreshing crls
197 //
198 void *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 //
214 do{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 
285 namespace XrdTlsFlush
286 {
287 /******************************************************************************/
288 /* F l u s h e r */
289 /******************************************************************************/
290 // Inital entry for refreshing crls
291 //
292 void *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 //
315 do{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 //
351  if (TRACING(XrdTls::dbgCTX))
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 
372 bool 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)
424 namespace
425 {
426 #define XRDTLS_SET_CALLBACKS 1
427 #ifdef __solaris__
428 extern "C" {
429 #endif
430 
431 template<bool is32>
432 struct tlsmix;
433 
434 template<>
435 struct 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 
447 template<>
448 struct 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 
460 unsigned 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 
472 XrdSysMutex *MutexVector = 0;
473 
474 void 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 
494 namespace
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
502 const 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
511 const char *sslCiphers = "ALL:!LOW:!EXP:!MD5:!MD2";
512 #endif
513 
514 XrdSysMutex dbgMutex, tlsMutex;
515 XrdSys::RAtomic<bool> initDbgDone{ false };
516 bool initTlsDone{ false };
517 
518 /******************************************************************************/
519 /* I n i t T L S */
520 /******************************************************************************/
521 
522 void 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 
561 void 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 
577 const 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 
592 bool 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 
652 extern "C"
653 {
658 int 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 
708 int XrdTlsContext::ctxIndex = SSL_CTX_get_ex_new_index(0, NULL, NULL, NULL, NULL);
709 
710 XrdTlsContext::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
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) {
996  SetCrlRefresh();
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 
1021 XrdTlsContext *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 
1081 const char *XrdTlsContext::Init()
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 
1206 int 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 
1267 bool 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 
1281 void 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)
Definition: XrdBwmTrace.hh:56
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)
Definition: XrdTlsTrace.hh:39
#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)
Definition: XrdSysTimer.cc:168
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)
void * Flusher(void *parg)
bool Setup_Flusher(XrdTlsContextImpl *pImpl, int flushT)
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.