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 <openssl/bio.h>
21 #include <openssl/crypto.h>
22 #include <openssl/err.h>
23 #include <openssl/ssl.h>
24 #include <openssl/opensslv.h>
25 #include <sys/stat.h>
26 
27 #include "XrdOuc/XrdOucUtils.hh"
28 #include "XrdSys/XrdSysRAtomic.hh"
29 #include "XrdSys/XrdSysError.hh"
30 #include "XrdSys/XrdSysPthread.hh"
31 #include "XrdSys/XrdSysTimer.hh"
32 
33 #include "XrdTls/XrdTls.hh"
34 #include "XrdTls/XrdTlsContext.hh"
35 #include "XrdTls/XrdTlsTrace.hh"
36 
37 /******************************************************************************/
38 /* G l o b a l s */
39 /******************************************************************************/
40 
41 namespace XrdTlsGlobal
42 {
44 };
45 
46 /******************************************************************************/
47 /* X r d T l s C o n t e x t I m p l */
48 /******************************************************************************/
49 
51 {
53  : ctx(0), ctxnew(0), owner(p), flsCVar(0),
54  flushT(0),
55  crlRunning(false), flsRunning(false) {}
56  ~XrdTlsContextImpl() {if (ctx) SSL_CTX_free(ctx);
57  if (ctxnew) delete ctxnew;
58  if (flsCVar) delete flsCVar;
59  }
60 
61  SSL_CTX *ctx;
67  short flushT;
68  bool crlRunning;
69  bool flsRunning;
70  time_t lastCertModTime = 0;
71  int sessionCacheOpts = -1;
72  std::string sessionCacheId;
73  uint64_t opts{0};
74 };
75 
76 /******************************************************************************/
77 /* C r l R e f r e s h S u p p o r t */
78 /******************************************************************************/
79 
80 namespace XrdTlsCrl
81 {
82 // Inital entry for refreshing crls
83 //
84 void *Refresh(void *parg)
85 {
86  EPNAME("Refresh");
87  int sleepTime;
88  bool doreplace;
89 
90 // Get the implementation details
91 //
92  XrdTlsContextImpl *ctxImpl = static_cast<XrdTlsContextImpl*>(parg);
93 
94 // Indicate we have started in the trace record
95 //
96  DBG_CTX("CRL refresh started.")
97 
98 // Do this forever but first get the sleep time
99 //
100 do{ctxImpl->crlMutex.ReadLock();
101  sleepTime = ctxImpl->Parm.crlRT;
102  ctxImpl->crlMutex.UnLock();
103 
104 // We may have been cancelled, in which case we just exit
105 //
106  if (!sleepTime)
107  {ctxImpl->crlMutex.WriteLock();
108  ctxImpl->crlRunning = false;
109  ctxImpl->crlMutex.UnLock();
110  DBG_CTX("CRL refresh ending by request!");
111  return (void *)0;
112  }
113 
114 // Indicate we how long before a refresh
115 //
116  DBG_CTX("CRL refresh will happen in " <<sleepTime <<" seconds.");
117 
118 // Now sleep the request amount of time
119 //
120  XrdSysTimer::Snooze(sleepTime);
121 
122  if (ctxImpl->owner->x509Verify() || ctxImpl->owner->newHostCertificateDetected()) {
123  // Check if this context is still alive. Generally, it never gets deleted.
124  //
125  ctxImpl->crlMutex.WriteLock();
126  if (!ctxImpl->owner) break;
127 
128  // We clone the original, this will give us the latest crls (i.e. refreshed).
129  // We drop the lock while doing so as this may take a long time. This is
130  // completely safe to do because we implicitly own the implementation.
131  //
132  ctxImpl->crlMutex.UnLock();
133  XrdTlsContext *newctx = ctxImpl->owner->Clone();
134 
135  // Verify that the context was properly built
136  //
137  if (!newctx || !newctx->isOK())
138  {XrdTls::Emsg("CrlRefresh:","Refresh of context failed!!!",false);
139  continue;
140  }
141 
142  // OK, set the new context to be used next time Session() is called.
143  //
144  ctxImpl->crlMutex.WriteLock();
145  doreplace = (ctxImpl->ctxnew != 0);
146  if (doreplace) delete ctxImpl->ctxnew;
147  ctxImpl->ctxnew = newctx;
148  ctxImpl->crlMutex.UnLock();
149 
150  // Do some debugging
151  //
152  if (doreplace) {DBG_CTX("CRL refresh created replacement x509 store.");}
153  else {DBG_CTX("CRL refresh created new x509 store.");}
154  }
155  } while(true);
156 
157 // If we are here the context that started us has gone away and we are done
158 //
159  bool keepctx = ctxImpl->flsRunning;
160  ctxImpl->crlRunning = false;
161  ctxImpl->crlMutex.UnLock();
162  if (!keepctx) delete ctxImpl;
163  return (void *)0;
164 }
165 }
166 
167 /******************************************************************************/
168 /* C a c h e F l u s h S u p p o r t */
169 /******************************************************************************/
170 
171 namespace XrdTlsFlush
172 {
173 /******************************************************************************/
174 /* F l u s h e r */
175 /******************************************************************************/
176 // Inital entry for refreshing crls
177 //
178 void *Flusher(void *parg)
179 {
180  EPNAME("Flusher");
181  time_t tStart, tWaited;
182  int flushT, waitT, hits, miss, sesn, tmos;
183  long tNow;
184 
185 // Get the implementation details
186 //
187  XrdTlsContextImpl *ctxImpl = static_cast<XrdTlsContextImpl*>(parg);
188 
189 // Get the interval as it may change as we are running
190 //
191  ctxImpl->crlMutex.ReadLock();
192  waitT = flushT = ctxImpl->flushT;
193  ctxImpl->crlMutex.UnLock();
194 
195 // Indicate we have started in the trace record
196 //
197  DBG_CTX("Cache flusher started; interval="<<flushT<<" seconds.");
198 
199 // Do this forever
200 //
201 do{tStart = time(0);
202  ctxImpl->flsCVar->Wait(waitT);
203  tWaited= time(0) - tStart;
204 
205 // Check if this context is still alive. Generally, it never gets deleted.
206 //
207  ctxImpl->crlMutex.ReadLock();
208  if (!ctxImpl->owner) break;
209 
210 // If the interval changed, see if we should wait a bit longer
211 //
212  if (flushT != ctxImpl->flushT && tWaited < ctxImpl->flushT-1)
213  {waitT = ctxImpl->flushT - tWaited;
214  ctxImpl->crlMutex.UnLock();
215  continue;
216  }
217 
218 // Get the new values and drop the lock
219 //
220  waitT = flushT = ctxImpl->flushT;
221  ctxImpl->crlMutex.UnLock();
222 
223 // Get some relevant statistics
224 //
225  sesn = SSL_CTX_sess_number(ctxImpl->ctx);
226  hits = SSL_CTX_sess_hits(ctxImpl->ctx);
227  miss = SSL_CTX_sess_misses(ctxImpl->ctx);
228  tmos = SSL_CTX_sess_timeouts(ctxImpl->ctx);
229 
230 // Flush the cache
231 //
232  tNow = time(0);
233  SSL_CTX_flush_sessions(ctxImpl->ctx, tNow);
234 
235 // Print some stuff should debugging be on
236 //
237  if (TRACING(XrdTls::dbgCTX))
238  {char mBuff[512];
239  snprintf(mBuff, sizeof(mBuff), "sess=%d hits=%d miss=%d timeouts=%d",
240  sesn, hits, miss, tmos);
241  DBG_CTX("Cache flushed; " <<mBuff);
242  }
243  } while(true);
244 
245 // If we are here the context that started us has gone away and we are done
246 //
247  bool keepctx = ctxImpl->crlRunning;
248  ctxImpl->flsRunning = false;
249  ctxImpl->crlMutex.UnLock();
250  if (!keepctx) delete ctxImpl;
251  return (void *)0;
252 }
253 
254 /******************************************************************************/
255 /* S e t u p _ F l u s h e r */
256 /******************************************************************************/
257 
258 bool Setup_Flusher(XrdTlsContextImpl *pImpl, int flushT)
259 {
260  pthread_t tid;
261  int rc;
262 
263 // Set the new flush interval
264 //
265  pImpl->crlMutex.WriteLock();
266  pImpl->flushT = flushT;
267  pImpl->crlMutex.UnLock();
268 
269 // If the flush thread is already running, then wake it up to get the new value
270 //
271  if (pImpl->flsRunning)
272  {pImpl->flsCVar->Signal();
273  return true;
274  }
275 
276 // Start the flusher thread
277 //
278  pImpl->flsCVar = new XrdSysCondVar();
279  if ((rc = XrdSysThread::Run(&tid, XrdTlsFlush::Flusher, (void *)pImpl,
280  0, "Cache Flusher")))
281  {char eBuff[512];
282  snprintf(eBuff, sizeof(eBuff),
283  "Unable to start cache flusher thread; rc=%d", rc);
284  XrdTls::Emsg("SessCache:", eBuff, false);
285  return false;
286  }
287 
288 // Finish up
289 //
290  pImpl->flsRunning = true;
291  SSL_CTX_set_session_cache_mode(pImpl->ctx, SSL_SESS_CACHE_NO_AUTO_CLEAR);
292  return true;
293 }
294 }
295 
296 /******************************************************************************/
297 /* S S L T h r e a d i n g S u p p o r t */
298 /******************************************************************************/
299 
300 // The following may confusing because SSL MT support is somewhat bizarre.
301 // Versions < 1.0 require a numeric thread_id and lock callbasks.
302 // Versions < 1.1 require a lock_callbacks but the thread_is callback is
303 // optional. While the numeric thread_id callback can be used
304 // it's deprecated and fancier pointer/numeric call should be
305 // used. In our case, we use the deprecated version.
306 // Versions >- 1.1 Do not need any callbacks as all threading functions are
307 // internally defined to use native MT functions.
308 
309 #if OPENSSL_VERSION_NUMBER < 0x10100000L && defined(OPENSSL_THREADS)
310 namespace
311 {
312 #define XRDTLS_SET_CALLBACKS 1
313 #ifdef __solaris__
314 extern "C" {
315 #endif
316 
317 template<bool is32>
318 struct tlsmix;
319 
320 template<>
321 struct tlsmix<false> {
322  static unsigned long mixer(unsigned long x) {
323  // mixer based on splitmix64
324  x ^= x >> 30;
325  x *= 0xbf58476d1ce4e5b9UL;
326  x ^= x >> 27;
327  x *= 0x94d049bb133111ebUL;
328  x ^= x >> 31;
329  return x;
330  }
331 };
332 
333 template<>
334 struct tlsmix<true> {
335  static unsigned long mixer(unsigned long x) {
336  // mixer based on murmurhash3
337  x ^= x >> 16;
338  x *= 0x85ebca6bU;
339  x ^= x >> 13;
340  x *= 0xc2b2ae35U;
341  x ^= x >> 16;
342  return x;
343  }
344 };
345 
346 unsigned long sslTLS_id_callback(void)
347 {
348  // base thread-id on the id given by XrdSysThread;
349  // but openssl 1.0 uses thread-id as a key for looking
350  // up per thread crypto ERR structures in a hash-table.
351  // So mix bits so that the table's hash function gives
352  // better distribution.
353 
354  unsigned long x = (unsigned long)XrdSysThread::ID();
355  return tlsmix<sizeof(unsigned long)==4>::mixer(x);
356 }
357 
358 XrdSysMutex *MutexVector = 0;
359 
360 void sslTLS_lock(int mode, int n, const char *file, int line)
361 {
362 // Use exclusive locks. At some point, SSL categorizes these as read and
363 // write locks but it's not clear when this actually occurs, sigh.
364 //
365  if (mode & CRYPTO_LOCK) MutexVector[n].Lock();
366  else MutexVector[n].UnLock();
367 }
368 #ifdef __solaris__
369 }
370 #endif
371 } // namespace
372 #else
373 #undef XRDTLS_SET_CALLBACKS
374 #endif
375 
376 /******************************************************************************/
377 /* F i l e L o c a l D e f i n i t i o n s */
378 /******************************************************************************/
379 
380 namespace
381 {
382 // The following is the default cipher list. Note that for OpenSSL v1.0.2+ we
383 // use the recommended cipher list from Mozilla. Otherwise, we use the dumber
384 // less secure ciphers as older versions of openssl have issues with them. See
385 // ssl-config.mozilla.org/#config=intermediate&openssl=1.0.2k&guideline=5.4
386 //
387 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
388 const char *sslCiphers = "ECDHE-ECDSA-AES128-GCM-SHA256:"
389  "ECDHE-RSA-AES128-GCM-SHA256:"
390  "ECDHE-ECDSA-AES256-GCM-SHA384:"
391  "ECDHE-RSA-AES256-GCM-SHA384:"
392  "ECDHE-ECDSA-CHACHA20-POLY1305:"
393  "ECDHE-RSA-CHACHA20-POLY1305:"
394  "DHE-RSA-AES128-GCM-SHA256:"
395  "DHE-RSA-AES256-GCM-SHA384";
396 #else
397 const char *sslCiphers = "ALL:!LOW:!EXP:!MD5:!MD2";
398 #endif
399 
400 XrdSysMutex dbgMutex, tlsMutex;
401 XrdSys::RAtomic<bool> initDbgDone{ false };
402 bool initTlsDone{ false };
403 
404 /******************************************************************************/
405 /* I n i t T L S */
406 /******************************************************************************/
407 
408 void InitTLS() // This is strictly a one-time call!
409 {
410  XrdSysMutexHelper tlsHelper(tlsMutex);
411 
412 // Make sure we are not trying to load the ssl library more than once. This can
413 // happen when a server and a client instance happen to be both defined.
414 //
415  if (initTlsDone) return;
416  initTlsDone = true;
417 
418 // SSL library initialisation
419 //
420  SSL_library_init();
421  OpenSSL_add_all_algorithms();
422  SSL_load_error_strings();
423  OpenSSL_add_all_ciphers();
424 #if OPENSSL_VERSION_NUMBER < 0x30000000L
425  ERR_load_BIO_strings();
426 #endif
427  ERR_load_crypto_strings();
428 
429 // Set callbacks if we need to do this
430 //
431 #ifdef XRDTLS_SET_CALLBACKS
432 
433  int n = CRYPTO_num_locks();
434  if (n > 0)
435  {MutexVector = new XrdSysMutex[n];
436  CRYPTO_set_locking_callback(sslTLS_lock);
437  }
438  CRYPTO_set_id_callback(sslTLS_id_callback);
439 
440 #endif
441 }
442 
443 /******************************************************************************/
444 /* F a t a l */
445 /******************************************************************************/
446 
447 void Fatal(std::string *eMsg, const char *msg, bool sslmsg=false)
448 {
449 // If there is an outboard error string object, return the message there.
450 //
451  if (eMsg) *eMsg = msg;
452 
453 // Now route the message to the message callback function. If this is an ssl
454 // related error we also flush the ssl error queue to prevent suprises.
455 //
456  XrdTls::Emsg("TLS_Context:", msg, sslmsg);
457 }
458 
459 /******************************************************************************/
460 /* G e t T l s M e t h o d */
461 /******************************************************************************/
462 
463 const char *GetTlsMethod(const SSL_METHOD *&meth)
464 {
465 #if OPENSSL_VERSION_NUMBER > 0x1010000fL /* v1.1.0 */
466  meth = TLS_method();
467 #else
468  meth = SSLv23_method();
469 #endif
470  if (meth == 0) return "No negotiable TLS method available.";
471  return 0;
472 }
473 
474 /******************************************************************************/
475 /* V e r P a t h s */
476 /******************************************************************************/
477 
478 bool VerPaths(const char *cert, const char *pkey,
479  const char *cadr, const char *cafl, std::string &eMsg)
480 {
481  static const mode_t cert_mode = S_IRUSR | S_IWUSR | S_IRWXG | S_IROTH;
482  static const mode_t pkey_mode = S_IRUSR | S_IWUSR;
483  static const mode_t cadr_mode = S_IRWXU | S_IRGRP | S_IXGRP
484  | S_IROTH | S_IXOTH;
485  static const mode_t cafl_mode = S_IRUSR | S_IWUSR | S_IRWXG | S_IROTH;
486  const char *emsg;
487 
488 // If the ca cert directory is present make sure it's a directory and
489 // only the ower can write to that directory (anyone can read from it).
490 //
491  if (cadr && (emsg = XrdOucUtils::ValPath(cadr, cadr_mode, true)))
492  {eMsg = "Unable to use CA cert directory ";
493  eMsg += cadr; eMsg += "; "; eMsg += emsg;
494  return false;
495  }
496 
497 // If a ca cert file is present make sure it's a file and only the owner can
498 // write it (anyone can read it).
499 //
500  if (cafl && (emsg = XrdOucUtils::ValPath(cafl, cafl_mode, false)))
501  {eMsg = "Unable to use CA cert file ";
502  eMsg += cafl; eMsg += "; "; eMsg += emsg;
503  return false;
504  }
505 
506 // If a private key is present than make sure it's a file and only the
507 // owner has access to it.
508 //
509  if (pkey && (emsg = XrdOucUtils::ValPath(pkey, pkey_mode, false)))
510  {eMsg = "Unable to use key file ";
511  eMsg += pkey; eMsg += "; "; eMsg += emsg;
512  return false;
513  }
514 
515 // If a cert file is present then make sure it's a file. If a keyfile is
516 // present then anyone can read it but only the owner can write it.
517 // Otherwise, only the owner can gave access to it (it contains the key).
518 //
519  if (cert)
520  {mode_t cmode = (pkey ? cert_mode : pkey_mode);
521  if ((emsg = XrdOucUtils::ValPath(cert, cmode, false)))
522  {if (pkey) eMsg = "Unable to use cert file ";
523  else eMsg = "Unable to use cert+key file ";
524  eMsg += cert; eMsg += "; "; eMsg += emsg;
525  return false;
526  }
527  }
528 
529 // All tests succeeded.
530 //
531  return true;
532 }
533 
534 /******************************************************************************/
535 /* V e r C B */
536 /******************************************************************************/
537 
538 extern "C"
539 {
540 int VerCB(int aOK, X509_STORE_CTX *x509P)
541 {
542  if (!aOK)
543  {X509 *cert = X509_STORE_CTX_get_current_cert(x509P);
544  int depth = X509_STORE_CTX_get_error_depth(x509P);
545  int err = X509_STORE_CTX_get_error(x509P);
546  char name[512], info[1024];
547 
548  X509_NAME_oneline(X509_get_subject_name(cert), name, sizeof(name));
549  snprintf(info,sizeof(info),"Cert verification failed for DN=%s",name);
550  XrdTls::Emsg("CertVerify:", info, false);
551 
552  X509_NAME_oneline(X509_get_issuer_name(cert), name, sizeof(name));
553  snprintf(info,sizeof(info),"Failing cert issuer=%s", name);
554  XrdTls::Emsg("CertVerify:", info, false);
555 
556  snprintf(info, sizeof(info), "Error %d at depth %d [%s]", err, depth,
557  X509_verify_cert_error_string(err));
558  XrdTls::Emsg("CertVerify:", info, true);
559  }
560 
561  return aOK;
562 }
563 }
564 
565 } // Anonymous namespace end
566 
567 /******************************************************************************/
568 /* C o n s t r u c t o r */
569 /******************************************************************************/
570 
571 #define KILL_CTX(x) if (x) {SSL_CTX_free(x); x = 0;}
572 
573 #define FATAL(msg) {Fatal(eMsg, msg); KILL_CTX(pImpl->ctx); return;}
574 
575 #define FATAL_SSL(msg) {Fatal(eMsg, msg, true); KILL_CTX(pImpl->ctx); return;}
576 
577 XrdTlsContext::XrdTlsContext(const char *cert, const char *key,
578  const char *caDir, const char *caFile,
579  uint64_t opts, std::string *eMsg)
580  : pImpl( new XrdTlsContextImpl(this) )
581 {
582  class ctx_helper
583  {public:
584 
585  void Keep() {ctxLoc = 0;}
586 
587  ctx_helper(SSL_CTX **ctxP) : ctxLoc(ctxP) {}
588  ~ctx_helper() {if (ctxLoc && *ctxLoc)
589  {SSL_CTX_free(*ctxLoc); *ctxLoc = 0;}
590  }
591  private:
592  SSL_CTX **ctxLoc;
593  } ctx_tracker(&pImpl->ctx);
594 
595  pImpl->opts = opts;
596 
597  static const uint64_t sslOpts = SSL_OP_ALL
598  | SSL_OP_NO_SSLv2
599  | SSL_OP_NO_SSLv3
600  | SSL_OP_NO_COMPRESSION
601 #ifdef SSL_OP_IGNORE_UNEXPECTED_EOF
602  | SSL_OP_IGNORE_UNEXPECTED_EOF
603 #endif
604 #if OPENSSL_VERSION_NUMBER >= 0x10101000L
605  | SSL_OP_NO_RENEGOTIATION
606 #endif
607  ;
608 
609  std::string certFN, eText;
610  const char *emsg;
611 
612 // Assume we will fail
613 //
614  pImpl->ctx = 0;
615 
616 // Verify that initialzation has occurred. This is not heavy weight as
617 // there will usually be no more than two instances of this object.
618 //
619  if (!initDbgDone)
620  {XrdSysMutexHelper dbgHelper(dbgMutex);
621  if (!initDbgDone)
622  {const char *dbg;
623  if (!(opts & servr) && (dbg = getenv("XRDTLS_DEBUG")))
624  {int dbgOpts = 0;
625  if (strstr(dbg, "ctx")) dbgOpts |= XrdTls::dbgCTX;
626  if (strstr(dbg, "sok")) dbgOpts |= XrdTls::dbgSOK;
627  if (strstr(dbg, "sio")) dbgOpts |= XrdTls::dbgSIO;
628  if (!dbgOpts) dbgOpts = XrdTls::dbgALL;
630  }
631  if ((emsg = Init())) FATAL(emsg);
632  initDbgDone = true;
633  }
634  }
635 
636 // If no CA cert information is specified and this is not a server context,
637 // then get the paths from the environment. They must exist as we need to
638 // verify peer certs in order to verify target host names client-side. We
639 // also use this setupt to see if we should use a specific cert and key.
640 //
641  if (!(opts & servr))
642  {if (!caDir && !caFile)
643  {caDir = getenv("X509_CERT_DIR");
644  caFile = getenv("X509_CERT_FILE");
645  if (!caDir && !caFile)
646  FATAL("No CA cert specified; host identity cannot be verified.");
647  }
648  if (!key) key = getenv("X509_USER_KEY");
649  if (!cert) cert = getenv("X509_USER_PROXY");
650  if (!cert)
651  {struct stat Stat;
652  long long int uid = static_cast<long long int>(getuid());
653  certFN = std::string("/tmp/x509up_u") + std::to_string(uid);
654  if (!stat(certFN.c_str(), &Stat)) cert = certFN.c_str();
655  }
656  }
657 
658 // Before we try to use any specified files, make sure they exist, are of
659 // the right type and do not have excessive access privileges.
660 // .a
661  if (!VerPaths(cert, key, caDir, caFile, eText)) FATAL( eText.c_str());
662 
663 // Copy parameters to out parm structure.
664 //
665  if (cert) {
666  pImpl->Parm.cert = cert;
667  //This call should not fail as a stat is already performed in the call of VerPaths() above
669  }
670  if (key) pImpl->Parm.pkey = key;
671  if (caDir) pImpl->Parm.cadir = caDir;
672  if (caFile) pImpl->Parm.cafile = caFile;
673  pImpl->Parm.opts = opts;
674  if (opts & crlRF) {
675  // What we store in crlRF is the time in minutes, convert it back to seconds
676  pImpl->Parm.crlRT = static_cast<int>((opts & crlRF) >> crlRS) * 60;
677  }
678 
679 // Get the correct method to use for TLS and check if successful create a
680 // server context that uses the method.
681 //
682  const SSL_METHOD *meth;
683  emsg = GetTlsMethod(meth);
684  if (emsg) FATAL(emsg);
685 
686  pImpl->ctx = SSL_CTX_new(meth);
687 
688 // Make sure we have a context here
689 //
690  if (pImpl->ctx == 0) FATAL_SSL("Unable to allocate TLS context!");
691 
692 // Always prohibit SSLv2 & SSLv3 as these are not secure.
693 //
694  SSL_CTX_set_options(pImpl->ctx, sslOpts);
695 
696 // Handle session re-negotiation automatically
697 //
698 // SSL_CTX_set_mode(pImpl->ctx, sslMode);
699 
700 // Turn off the session cache as it's useless with peer cert chains
701 //
702  SSL_CTX_set_session_cache_mode(pImpl->ctx, SSL_SESS_CACHE_OFF);
703 
704 // Establish the CA cert locations, if specified. Then set the verification
705 // depth and turn on peer cert validation. For now, we don't set a callback.
706 // In the future we may to grab debugging information.
707 //
708  if (caDir || caFile)
709  {if (!SSL_CTX_load_verify_locations(pImpl->ctx, caFile, caDir))
710  FATAL_SSL("Unable to load the CA cert file or directory.");
711 
712  int vDepth = (opts & vdept) >> vdepS;
713  SSL_CTX_set_verify_depth(pImpl->ctx, (vDepth ? vDepth : 9));
714 
715  bool LogVF = (opts & logVF) != 0;
716  SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_PEER, (LogVF ? VerCB : 0));
717 
718  unsigned long xFlags = (opts & nopxy ? 0 : X509_V_FLAG_ALLOW_PROXY_CERTS);
719  if (opts & crlON)
720  {xFlags |= X509_V_FLAG_CRL_CHECK;
721  if (opts & crlFC) xFlags |= X509_V_FLAG_CRL_CHECK_ALL;
722  }
723  if (opts) X509_STORE_set_flags(SSL_CTX_get_cert_store(pImpl->ctx),xFlags);
724  } else {
725  SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_NONE, 0);
726  }
727 
728 // Set cipher list
729 //
730  if (!SSL_CTX_set_cipher_list(pImpl->ctx, sslCiphers))
731  FATAL_SSL("Unable to set SSL cipher list; no supported ciphers.");
732 
733 // If we need to enable eliptic-curve support, do so now. Note that for
734 // OpenSSL 1.1.0+ this is automatically done for us.
735 //
736 #if SSL_CTRL_SET_ECDH_AUTO
737  SSL_CTX_set_ecdh_auto(pImpl->ctx, 1);
738 #endif
739 
740 // We normally handle renegotiation during reads and writes or selective
741 // prohibit on a SSL socket basis. The calle may request this be applied
742 // to all SSL's generated from this context. If so, do it here.
743 //
744  if (opts & artON) SSL_CTX_set_mode(pImpl->ctx, SSL_MODE_AUTO_RETRY);
745 
746 // If there is no cert then assume this is a generic context for a client
747 //
748  if (cert == 0)
749  {ctx_tracker.Keep();
750  return;
751  }
752 
753 // We have a cert. If the key is missing then we assume the key is in the
754 // cert file (ssl will complain if it isn't).
755 //
756  if (!key) key = cert;
757 
758 // Load certificate
759 //
760  if (SSL_CTX_use_certificate_chain_file(pImpl->ctx, cert) != 1)
761  FATAL_SSL("Unable to create TLS context; invalid certificate.");
762 
763 // Load the private key
764 //
765  if (SSL_CTX_use_PrivateKey_file(pImpl->ctx, key, SSL_FILETYPE_PEM) != 1 )
766  FATAL_SSL("Unable to create TLS context; invalid private key.");
767 
768 // Make sure the key and certificate file match.
769 //
770  if (SSL_CTX_check_private_key(pImpl->ctx) != 1 )
771  FATAL_SSL("Unable to create TLS context; cert-key mismatch.");
772 
773 // All went well, start the CRL refresh thread and keep the context.
774 //
775  if(opts & rfCRL) {
776  SetCrlRefresh();
777  }
778  ctx_tracker.Keep();
779 }
780 
781 /******************************************************************************/
782 /* D e s t r u c t o r */
783 /******************************************************************************/
784 
786 {
787 // We can delet eour implementation of there is no refresh thread running. If
788 // there is then the refresh thread has to delete the implementation.
789 //
790  if (pImpl->crlRunning | pImpl->flsRunning)
791  {pImpl->crlMutex.WriteLock();
792  pImpl->owner = 0;
793  pImpl->crlMutex.UnLock();
794  } else delete pImpl;
795 }
796 
797 /******************************************************************************/
798 /* C l o n e */
799 /******************************************************************************/
800 
801 XrdTlsContext *XrdTlsContext::Clone(bool full,bool startCRLRefresh)
802 {
803  XrdTlsContext::CTX_Params &my = pImpl->Parm;
804  const char *cert = (my.cert.size() ? my.cert.c_str() : 0);
805  const char *pkey = (my.pkey.size() ? my.pkey.c_str() : 0);
806  const char *caD = (my.cadir.size() ? my.cadir.c_str() : 0);
807  const char *caF = (my.cafile.size() ? my.cafile.c_str() : 0);
808 
809 // If this is a non-full context, get rid of any verification
810 //
811  if (!full) caD = caF = 0;
812 
813 // Cloning simply means getting a object with the old parameters.
814 //
815  uint64_t myOpts = my.opts;
816  if(startCRLRefresh){
818  } else {
820  }
821  XrdTlsContext *xtc = new XrdTlsContext(cert, pkey, caD, caF, myOpts);
822 
823 // Verify that the context was built
824 //
825  if (xtc->isOK()) {
826  if(pImpl->sessionCacheOpts != -1){
827  //A SessionCache() call was done for the current context, so apply it for this new cloned context
828  xtc->SessionCache(pImpl->sessionCacheOpts,pImpl->sessionCacheId.c_str(),pImpl->sessionCacheId.size());
829  }
830  return xtc;
831  }
832 
833 // We failed, cleanup.
834 //
835  delete xtc;
836  return 0;
837 }
838 
839 /******************************************************************************/
840 /* C o n t e x t */
841 /******************************************************************************/
842 
844 {
845  return pImpl->ctx;
846 }
847 
848 /******************************************************************************/
849 /* G e t P a r a m s */
850 /******************************************************************************/
851 
853 {
854  return &pImpl->Parm;
855 }
856 
857 /******************************************************************************/
858 /* I n i t */
859 /******************************************************************************/
860 
861 const char *XrdTlsContext::Init()
862 {
863 
864 // Disallow use if this object unless SSL provides thread-safety!
865 //
866 #ifndef OPENSSL_THREADS
867  return "Installed OpenSSL lacks the required thread support!";
868 #endif
869 
870 // Initialize the library (one time call)
871 //
872  InitTLS();
873  return 0;
874 }
875 
876 /******************************************************************************/
877 /* i s O K */
878 /******************************************************************************/
879 
881 {
882  return pImpl->ctx != 0;
883 }
884 
885 /******************************************************************************/
886 /* S e s s i o n */
887 /******************************************************************************/
888 
889 // Note: The reason we handle the x509 store update here is because allow the
890 // SSL context to be exported and then have no lock control over it. This may
891 // happen for transient purposes other than creating sessions. Once we
892 // disallow direct access to the context, the exchange can happen in the
893 // refresh thread which simplifies this whole process.
894 
896 {
897 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
898 
899  EPNAME("Session");
900  SSL *ssl;
901 
902 // Check if we have a refreshed context. If so, we need to replace the X509
903 // store in the current context with the new one before we create the session.
904 //
905  pImpl->crlMutex.ReadLock();
906  if (!(pImpl->ctxnew))
907  {ssl = SSL_new(pImpl->ctx);
908  pImpl->crlMutex.UnLock();
909  return ssl;
910  }
911 
912 // Things have changed, so we need to take the long route here. We need to
913 // replace the x509 cache with the current cache. Get a R/W lock now.
914 //
915  pImpl->crlMutex.UnLock();
916  pImpl->crlMutex.WriteLock();
917 
918 // If some other thread beat us to the punch, just return what we have.
919 //
920  if (!(pImpl->ctxnew))
921  {ssl = SSL_new(pImpl->ctx);
922  pImpl->crlMutex.UnLock();
923  return ssl;
924  }
925 
926 // Do some tracing
927 //
928  DBG_CTX("Replacing x509 store with new contents.");
929 
930 // Get the new store and set it in our context. Setting the store is black
931 // magic. For OpenSSL < 1.1, Two stores need to be set with the "set1" variant.
932 // Newer version only require SSL_CTX_set1_cert_store() to be used.
933 //
934  //We have a new context generated by Refresh, so we must use it.
935  XrdTlsContext * ctxnew = pImpl->ctxnew;
936 
937  /*X509_STORE *newX509 = SSL_CTX_get_cert_store(ctxnew->pImpl->ctx);
938  SSL_CTX_set1_verify_cert_store(pImpl->ctx, newX509);
939  SSL_CTX_set1_chain_cert_store(pImpl->ctx, newX509);*/
940  //The above two macros actually do not replace the certificate that has
941  //to be used for that SSL session, so we will create the session with the SSL_CTX * of
942  //the TlsContext created by Refresh()
943  //First, free the current SSL_CTX, if it is used by any transfer, it will just decrease
944  //the reference counter of it. There is therefore no risk of double free...
945  SSL_CTX_free(pImpl->ctx);
946  pImpl->ctx = ctxnew->pImpl->ctx;
947  //In the destructor of XrdTlsContextImpl, SSL_CTX_Free() is
948  //called if ctx is != 0. As this new ctx is used by the session
949  //we just created, we don't want that to happen. We therefore set it to 0.
950  //The SSL_free called on the session will cleanup the context for us.
951  ctxnew->pImpl->ctx = 0;
952 
953 // Save the generated context and clear it's presence
954 //
955  XrdTlsContext *ctxold = pImpl->ctxnew;
956  pImpl->ctxnew = 0;
957 
958 // Generate a new session (might as well to keep the lock we have)
959 //
960  ssl = SSL_new(pImpl->ctx);
961 
962 // OK, now we can drop all the locks and get rid of the old context
963 //
964  pImpl->crlMutex.UnLock();
965  delete ctxold;
966  return ssl;
967 
968 #else
969 // If we did not compile crl refresh code, we can simply return the OpenSSL
970 // session using our context. Otherwise, we need to see if we have a refreshed
971 // context and if so, carry forward the X509_store to our original context.
972 //
973  return SSL_new(pImpl->ctx);
974 #endif
975 }
976 
977 /******************************************************************************/
978 /* S e s s i o n C a c h e */
979 /******************************************************************************/
980 
981 int XrdTlsContext::SessionCache(int opts, const char *id, int idlen)
982 {
983  static const int doSet = scSrvr | scClnt | scOff;
984  long sslopt = 0;
985  int flushT = opts & scFMax;
986 
987  pImpl->sessionCacheOpts = opts;
988  pImpl->sessionCacheId = id;
989 
990 // If initialization failed there is nothing to do
991 //
992  if (pImpl->ctx == 0) return 0;
993 
994 // Set options as appropriate
995 //
996  if (opts & doSet)
997  {if (opts & scOff) sslopt = SSL_SESS_CACHE_OFF;
998  else {if (opts & scSrvr) sslopt = SSL_SESS_CACHE_SERVER;
999  if (opts & scClnt) sslopt |= SSL_SESS_CACHE_CLIENT;
1000  }
1001  }
1002 
1003 // Check if we should set any cache options or simply get them
1004 //
1005  if (!(opts & doSet)) sslopt = SSL_CTX_get_session_cache_mode(pImpl->ctx);
1006  else {sslopt = SSL_CTX_set_session_cache_mode(pImpl->ctx, sslopt);
1007  if (opts & scOff) SSL_CTX_set_options(pImpl->ctx, SSL_OP_NO_TICKET);
1008  }
1009 
1010 // Compute what he previous cache options were
1011 //
1012  opts = scNone;
1013  if (sslopt & SSL_SESS_CACHE_SERVER) opts |= scSrvr;
1014  if (sslopt & SSL_SESS_CACHE_CLIENT) opts |= scClnt;
1015  if (!opts) opts = scOff;
1016  if (sslopt & SSL_SESS_CACHE_NO_AUTO_CLEAR) opts |= scKeep;
1017  opts |= (static_cast<int>(pImpl->flushT) & scFMax);
1018 
1019 // Set the id is so wanted
1020 //
1021  if (id && idlen > 0)
1022  {if (!SSL_CTX_set_session_id_context(pImpl->ctx,
1023  (unsigned const char *)id,
1024  (unsigned int)idlen)) opts |= scIdErr;
1025  }
1026 
1027 // If a flush interval was specified and it is different from what we have
1028 // then reset the flush interval.
1029 //
1030  if (flushT && flushT != pImpl->flushT)
1031  XrdTlsFlush::Setup_Flusher(pImpl, flushT);
1032 
1033 // All done
1034 //
1035  return opts;
1036 }
1037 
1038 /******************************************************************************/
1039 /* S e t C o n t e x t C i p h e r s */
1040 /******************************************************************************/
1041 
1042 bool XrdTlsContext::SetContextCiphers(const char *ciphers)
1043 {
1044  if (pImpl->ctx && SSL_CTX_set_cipher_list(pImpl->ctx, ciphers)) return true;
1045 
1046  char eBuff[2048];
1047  snprintf(eBuff,sizeof(eBuff),"Unable to set context ciphers '%s'",ciphers);
1048  Fatal(0, eBuff, true);
1049  return false;
1050 }
1051 
1052 /******************************************************************************/
1053 /* S e t D e f a u l t C i p h e r s */
1054 /******************************************************************************/
1055 
1056 void XrdTlsContext::SetDefaultCiphers(const char *ciphers)
1057 {
1058  sslCiphers = ciphers;
1059 }
1060 
1061 /******************************************************************************/
1062 /* S e t C r l R e f r e s h */
1063 /******************************************************************************/
1064 
1066 {
1067 #if OPENSSL_VERSION_NUMBER >= 0x10002000L
1068 
1069  pthread_t tid;
1070  int rc;
1071 
1072 // If it's negative or equal to 0, use the current setting
1073 //
1074  if (refsec <= 0)
1075  {pImpl->crlMutex.WriteLock();
1076  refsec = pImpl->Parm.crlRT;
1077  pImpl->crlMutex.UnLock();
1078  if (!refsec) refsec = XrdTlsContext::DEFAULT_CRL_REF_INT_SEC;
1079  }
1080 
1081 // Make sure this is at least 60 seconds between refreshes
1082 //
1083 // if (refsec < 60) refsec = 60;
1084 
1085 // We will set the new interval and start a refresh thread if not running.
1086 //
1087  pImpl->crlMutex.WriteLock();
1088  pImpl->Parm.crlRT = refsec;
1089  if (!pImpl->crlRunning)
1090  {if ((rc = XrdSysThread::Run(&tid, XrdTlsCrl::Refresh, (void *)pImpl,
1091  0, "CRL Refresh")))
1092  {char eBuff[512];
1093  snprintf(eBuff, sizeof(eBuff),
1094  "Unable to start CRL refresh thread; rc=%d", rc);
1095  XrdTls::Emsg("CrlRefresh:", eBuff, false);
1096  pImpl->crlMutex.UnLock();
1097  return false;
1098  } else pImpl->crlRunning = true;
1099  pImpl->crlMutex.UnLock();
1100  }
1101 
1102 // All done
1103 //
1104  return true;
1105 
1106 #else
1107 // We use features present on OpenSSL 1.02 and above to implement crl refresh.
1108 // Older version are too difficult to deal with. Issue a message if this
1109 // feature is being enabled on an old version.
1110 //
1111  XrdTls::Emsg("CrlRefresh:", "Refreshing CRLs only supported in "
1112  "OpenSSL version >= 1.02; CRL refresh disabled!", false);
1113  return false;
1114 #endif
1115 }
1116 
1117 /******************************************************************************/
1118 /* x 5 0 9 V e r i f y */
1119 /******************************************************************************/
1120 
1122 {
1123  return !(pImpl->Parm.cadir.empty()) || !(pImpl->Parm.cafile.empty());
1124 }
1125 
1127  const std::string certPath = pImpl->Parm.cert;
1128  if(certPath.empty()) {
1129  //No certificate provided, should not happen though
1130  return false;
1131  }
1132  time_t modificationTime;
1133  if(!XrdOucUtils::getModificationTime(certPath.c_str(),modificationTime)){
1134  if (pImpl->lastCertModTime != modificationTime) {
1135  //The certificate file has changed
1136  pImpl->lastCertModTime = modificationTime;
1137  return true;
1138  }
1139  }
1140  return false;
1141 }
1142 
1144 
1145  bool LogVF = (pImpl->opts & logVF) != 0;
1146  switch (setting) {
1147  case kOn:
1148  SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_PEER, (LogVF ? VerCB : 0));
1149  break;
1150  case kOff:
1151  SSL_CTX_set_verify(pImpl->ctx, SSL_VERIFY_NONE, 0);
1152  break;
1153  default:
1154  return false;
1155  }
1156  return true;
1157 }
#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
int stat(const char *path, struct stat *buf)
#define eMsg(x)
struct myOpts opts
int emsg(int rc, char *msg)
#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 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.
bool SetTlsClientAuth(ClientAuthSetting setting)
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 const uint64_t crlON
Enables crl checking.
static const uint64_t artON
Auto retry Handshake.
void * Session()
void * Context()
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
bool SetCrlRefresh(int refsec=-1)
static const int scSrvr
Turn on cache server mode (default)
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.