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