diff --git a/src/XrdTls/XrdTlsConnection.cc b/src/XrdTls/XrdTlsConnection.cc
index 3c4d0689f1e..65dbedf5ebe 100644
--- a/src/XrdTls/XrdTlsConnection.cc
+++ b/src/XrdTls/XrdTlsConnection.cc
@@ -16,83 +16,299 @@
// along with XRootD. If not, see .
//------------------------------------------------------------------------------
-#include "XrdTlsConnection.hh"
+#include
+#include
+#include
+#include
+#include
+
+#include "XrdTls/XrdTlsConnection.hh"
+#include "XrdTls/XrdTlsContext.hh"
#include
-namespace XrdTls
+/******************************************************************************/
+/* C o n s t r u c t o r */
+/******************************************************************************/
+
+XrdTlsConnection::XrdTlsConnection( XrdTlsContext &ctx, int sfd,
+ XrdTlsConnection::RW_Mode rwm,
+ XrdTlsConnection::HS_Mode hsm,
+ bool isClient )
+ : hsDone( false )
{
- Connection::Connection( int sfd, Mode mode ) : hsDone( false )
- {
- sbio = BIO_new_socket( sfd, BIO_NOCLOSE );
- BIO_set_nbio( sbio, 1 );
- ssl = SSL_new( XrdTls::Context::Instance() );
-
- switch( mode )
- {
- case TLS_CLIENT:
- {
- SSL_set_connect_state( ssl );
- break;
- }
-
- case TLS_SERVER:
- {
- SSL_set_accept_state( ssl );
- break;
- }
-
- default:
- throw std::invalid_argument( "TLS I/O: expected TLS mode." );
- }
-
- SSL_set_bio( ssl, sbio, sbio );
- }
-
- Connection::~Connection()
- {
- SSL_free( ssl ); /* free the SSL object and its BIO's */
- }
+// Simply initialize this object and throw an exception if it fails
+//
+ const char *eMsg = Init(ctx, sfd, rwm, hsm, isClient);
+ if (eMsg) throw std::invalid_argument( eMsg );
+}
- int Connection::Accept()
+/******************************************************************************/
+/* A c c e p t */
+/******************************************************************************/
+
+int XrdTlsConnection::Accept()
{
int rc = SSL_accept( ssl );
int error = SSL_get_error( ssl, rc );
return error;
}
- int Connection::Connect()
+/******************************************************************************/
+/* C o n n e c t */
+/******************************************************************************/
+
+int XrdTlsConnection::Connect()
{
int rc = SSL_connect( ssl );
int error = SSL_get_error( ssl, rc );
return error;
}
+
+/******************************************************************************/
+/* G e t E r r o r s */
+/******************************************************************************/
+
+std::string XrdTlsConnection::GetErrs(const char *pfx)
+{
+ return (tlsctx ? tlsctx->GetErrs(pfx) : std::string(""));
+}
+
+/******************************************************************************/
+/* I n i t */
+/******************************************************************************/
+
+const char *XrdTlsConnection::Init( XrdTlsContext &ctx, int sfd,
+ XrdTlsConnection::RW_Mode rwm,
+ XrdTlsConnection::HS_Mode hsm,
+ bool isClient )
+{
+ BIO *rbio, *wbio = 0;
+
+// Make sure this connection is not in use
+//
+ if ( ssl ) return "TLS I/O: connection is still in use.";
+
+// Get the ssl object from the context, there better be one.
+//
+ SSL_CTX *ssl_ctx = ctx.Context();
+ if (ssl_ctx == 0) return "TLS I/O: context inialization failed.";
+
+// Save the tls context, we need it to print errors
+//
+ tlsctx = &ctx;
+
+// Obtain the ssl object at this point. Anything after this cannot fail.
+//
+ ssl = SSL_new( ssl_ctx );
+ if (ssl == 0) return "TLS I/O: failed to get ssl object.";
+
+// Set the ssl object state to correspond to client or server type
+//
+ if (isClient)
+ {SSL_set_connect_state( ssl );
+ cAttr = isServer;
+ } else {
+ SSL_set_accept_state( ssl );
+ cAttr = 0;
+ }
+
+// Allocate right number of bio's and initialize them as requested. Note
+// that when the read and write bios have the same attribue, we use only one.
+//
+ switch( rwm )
+ {
+ case TLS_RNB_WNB:
+ rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
+ BIO_set_nbio( rbio, 1 );
+ break;
+
+ case TLS_RNB_WBL:
+ rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
+ BIO_set_nbio( rbio, 1 );
+ wbio = BIO_new_socket( sfd, BIO_NOCLOSE );
+ cAttr |= wBlocking;
+ break;
+
+ case TLS_RBL_WNB:
+ rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
+ wbio = BIO_new_socket( sfd, BIO_NOCLOSE );
+ BIO_set_nbio( wbio, 1 );
+ cAttr |= rBlocking;
+ break;
+
+ case TLS_RBL_WBL:
+ rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
+ cAttr |= (rBlocking | wBlocking);
+ break;
+
+ default: return "TLS I/O: invalid TLS rw mode."; break;
+ }
+
+// Set correct handshake mode
+//
+ switch( hsm )
+ {
+ case TLS_HS_BLOCK: hsMode = rwBlock; break;
+ case TLS_HS_NOBLK: hsMode = noBlock; break;
+ case TLS_HS_XYBLK: hsMode = xyBlock; break;
- int Connection::Read( char *buffer, size_t size, int &bytesRead )
+ default: return "TLS I/O: invalid TLS hs mode."; break;
+ }
+
+// Finally attach the bios to the ssl object. When the ssl object is freed
+// the bios will be freed as well.
+//
+ sFD = sfd;
+ if (wbio == 0) wbio = rbio;
+ SSL_set_bio( ssl, rbio, wbio );
+ return 0;
+}
+
+/******************************************************************************/
+/* P r i n t E r r s */
+/******************************************************************************/
+
+void XrdTlsConnection::PrintErrs(const char *pfx, XrdSysError *eDest)
+{
+ if (tlsctx) tlsctx->PrintErrs(pfx, eDest);
+}
+
+/******************************************************************************/
+/* R e a d */
+/******************************************************************************/
+
+ int XrdTlsConnection::Read( char *buffer, size_t size, int &bytesRead )
{
+ int error;
+
//------------------------------------------------------------------------
// If necessary, SSL_read() will negotiate a TLS/SSL session, so we don't
// have to explicitly call SSL_connect or SSL_do_handshake.
//------------------------------------------------------------------------
- int rc = SSL_read( ssl, buffer, size );
- if( rc > 0 ) bytesRead = rc;
- else hsDone = bool( SSL_is_init_finished( ssl ) );
- int error = SSL_get_error( ssl, rc );
- return error;
+ do{int rc = SSL_read( ssl, buffer, size );
+
+ // Note that according to SSL whenever rc > 0 then SSL_ERROR_NONE can be
+ // returned to the caller. So, we short-circuit all the error handling.
+ //
+ if( rc > 0 )
+ {bytesRead = rc;
+ return SSL_ERROR_NONE;
+ }
+
+ // We have a potential error. Get the SSL error code and whether or
+ // not the handshake actually is finished (semi-accurate)
+ //
+ hsDone = bool( SSL_is_init_finished( ssl ) );
+ error = SSL_get_error( ssl, rc );
+
+ // The connection creator may wish that we wait for the handshake to
+ // complete. This is a tricky issue for non-blocking bio's as a read
+ // may force us to wait until writes are possible. All of this is rare!
+ //
+ if ((!hsMode || hsDone || (error != SSL_ERROR_WANT_READ &&
+ error != SSL_ERROR_WANT_WRITE))
+ || (hsMode == xyBlock && error == SSL_ERROR_WANT_READ)) return error;
+
+ } while(Wait4OK(error == SSL_ERROR_WANT_READ));
+
+ return SSL_ERROR_SYSCALL;
}
- int Connection::Write( char *buffer, size_t size, int &bytesWritten )
+/******************************************************************************/
+/* S h u t d o w n */
+/******************************************************************************/
+
+void XrdTlsConnection::Shutdown(bool force)
+{
+// Make sure we have an ssl object
+//
+ if (ssl == 0) return;
+
+// Perform shutdown as needed. This is required before freeing the ssl object
+//
+ if (force) SSL_set_shutdown( ssl, 1 );
+ else {int rc = SSL_shutdown( ssl );
+ if (!rc) rc = SSL_shutdown( ssl );
+ if (rc < 0)
+ {rc = SSL_get_error( ssl, rc );
+ if (rc)
+ {const char *eText = ERR_reason_error_string( rc );
+ if (eText) std::cerr<< "TlsCon: Shutdown("< 0 ) bytesWritten = rc;
- else hsDone = bool( SSL_is_init_finished( ssl ) );
- int error = SSL_get_error( ssl, rc );
- return error;
+ do{int rc = SSL_write( ssl, buffer, size );
+
+ // Note that according to SSL whenever rc > 0 then SSL_ERROR_NONE can be
+ // returned to the caller. So, we short-circuit all the error handling.
+ //
+ if( rc > 0 )
+ {bytesWritten = rc;
+ return SSL_ERROR_NONE;
+ }
+
+ // We have a potential error. Get the SSL error code and whether or
+ // not the handshake actually is finished (semi-accurate)
+ //
+ hsDone = bool( SSL_is_init_finished( ssl ) );
+ error = SSL_get_error( ssl, rc );
+
+ // The connection creator may wish that we wait for the handshake to
+ // complete. This is a tricky issue for non-blocking bio's as a write
+ // may force us to wait until reads are possible. All of this is rare!
+ //
+ if ((!hsMode || hsDone || (error != SSL_ERROR_WANT_READ &&
+ error != SSL_ERROR_WANT_WRITE))
+ || (hsMode == xyBlock && error == SSL_ERROR_WANT_WRITE)) return error;
+
+ } while(Wait4OK(error == SSL_ERROR_WANT_READ));
+
+ return SSL_ERROR_SYSCALL;
}
+/******************************************************************************/
+/* Private: W a i t 4 O K */
+/******************************************************************************/
+
+bool XrdTlsConnection::Wait4OK(bool wantRead)
+{
+ static const short rdOK = POLLIN |POLLRDNORM;
+ static const short wrOK = POLLOUT|POLLWRNORM;
+ struct pollfd polltab = {sFD, (wantRead ? rdOK : wrOK), 0};
+ int rc;
+
+ do {rc = poll(&polltab, 1, -1);} while(rc < 0 && errno == EINTR);
+
+ // Make sure we have a clean state, otherwise indicate we failed. The
+ // caller will need to perform the correct action.
+ //
+ if (rc == 1)
+ {if (polltab.revents & (wantRead ? rdOK : wrOK)) return true;
+ if (polltab.revents & POLLERR) errno = EIO;
+ else if (polltab.revents & (POLLHUP|POLLNVAL)) errno = EPIPE;
+ else errno = EINVAL;
+ } else if (!rc) errno = ETIMEDOUT; // This is not possible
+ return false;
}
diff --git a/src/XrdTls/XrdTlsConnection.hh b/src/XrdTls/XrdTlsConnection.hh
index 14f16fb13ce..f117f68d148 100644
--- a/src/XrdTls/XrdTlsConnection.hh
+++ b/src/XrdTls/XrdTlsConnection.hh
@@ -1,5 +1,7 @@
+#ifndef __XRD_TLS_IO_HH__
+#define __XRD_TLS_IO_HH__
//------------------------------------------------------------------------------
-// Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN)
+// Copyright (c) 2011-2018 by European Organization for Nuclear Research (CERN)
// Author: Michal Simon
//------------------------------------------------------------------------------
// XRootD is free software: you can redistribute it and/or modify
@@ -16,99 +18,215 @@
// along with XRootD. If not, see .
//------------------------------------------------------------------------------
-#ifndef __XRD_TLS_IO_HH__
-#define __XRD_TLS_IO_HH__
-
-#include
#include
+#include
+
+class XrdSysError;
+class XrdTlsContext;
-#include "XrdTls/XrdTlsCtx.hh"
+//----------------------------------------------------------------------------
+//! Socket wrapper for TLS I/O
+//----------------------------------------------------------------------------
-namespace XrdTls
+class XrdTlsConnection
{
- //----------------------------------------------------------------------------
- //! Socket wrapper for TLS I/O
- //----------------------------------------------------------------------------
- class Connection
+public:
+
+enum RW_Mode
+{
+ TLS_RNB_WNB, //!< Non-blocking read non-blocking write
+ TLS_RNB_WBL, //!< Non-blocking read blocking write
+ TLS_RBL_WNB, //!< blocking read non-blocking write
+ TLS_RBL_WBL //!< blocking read blocking write
+};
+
+enum HS_Mode
+{
+ TLS_HS_BLOCK, //!< Always block during handshake
+ TLS_HS_NOBLK, //!< Do not block during handshake
+ TLS_HS_XYBLK //!< Block during handshake if it conflicts with request
+};
+
+//------------------------------------------------------------------------
+//! Constructor - creates specified mode TLS I/O wrapper for given socket
+//! file descriptor. Note this constructor throws an exception should any
+//! error be encountered. Use the parameterless constructor if you wish
+//! to avoid handling exceptions. When an exception is thrown, you should
+//! print all associated errors by calling GetErrs() or PrintErrs().
+//!
+//! @param ctx - the context for the connection. Be aware that a
+//! context can be associated wity multiple connections.
+//! @param sfd - the file descriptor associated with the connection.
+//! @param rwm - One of the above enums describing how connection I/O
+//! should be handled.
+//! @param hsm - One of the above enums describing how handshakes during
+//! read/write calls should be handled.
+//! @param isClient - When true initialize for client use.
+//! Otherwise, initialize for server use.
+//------------------------------------------------------------------------
+
+ XrdTlsConnection( XrdTlsContext &ctx, int sfd, RW_Mode rwm,
+ HS_Mode hsm, bool isClient );
+
+//------------------------------------------------------------------------
+//! Constructor - reserves space for a TLS I/O wrapper. Use the Init()
+//! method to fully initialize this object. If an errror occurs, you should
+//! print all associated errors by calling ctx.GetErrs() or ctx.PrintErrs().
+//------------------------------------------------------------------------
+
+ XrdTlsConnection() : tlsctx(0), ssl(0), sFD(-1), hsDone(false),
+ cAttr(0), hsMode(0) {}
+
+//------------------------------------------------------------------------
+//! Destructor
+//------------------------------------------------------------------------
+
+ ~XrdTlsConnection() { if (ssl) Shutdown(true); }
+
+//------------------------------------------------------------------------
+//! Accept an incoming TLS connection
+//------------------------------------------------------------------------
+
+ int Accept();
+
+//------------------------------------------------------------------------
+//! Establish a TLS connection
+//------------------------------------------------------------------------
+
+ int Connect();
+
+//------------------------------------------------------------------------
+//! Obtain context associated with this connection.
+//!
+//! @return : Tls connection object
+//------------------------------------------------------------------------
+
+ XrdTlsContext *Context() {return tlsctx;}
+
+//------------------------------------------------------------------------
+//! Retrieve all errors encountered so far.
+//!
+//! @param pfx The message prefix to be used (i.e. pfx: msg).
+//!
+//! @return A string containing newline separated messages.
+//------------------------------------------------------------------------
+
+ std::string GetErrs(const char *pfx=0);
+
+//------------------------------------------------------------------------
+//! Initialize this object to handle the specified TLS I/O mode for the
+//! given file descriptor. To maintain sanity, an error occurs if the
+//! this object is already associated with a connection (use Disconnect()
+//! before calling Init() just to keep yourself honest). Should an error
+//! occur, you should print all associated errors via ctx.GetErrs() or
+//! ctx.PrintErrs(). Errors are thread-specific.
+//!
+//! @param ctx - the context for the connection. Be aware that a
+//! context can be associated wity multiple connections.
+//! @param sfd - the file descriptor associated with the connection.
+//! @param rwm - One of the above enums describing how connection I/O
+//! should be handled.
+//! @param hsm - One of the above enums describing how handshakes during
+//! read/write calls should be handled.
+//! @param isClient - When true initialize for client use.
+//! Otherwise, initialize for server use.
+//!
+//! @return =0 - object has been initialized.
+//! @return !0 - an error occurred, the return value is a pointer to a
+//! message summarizing the error. This message is the same
+//! as would be thrown by the parameterized constructor.
+//------------------------------------------------------------------------
+
+ const char *Init( XrdTlsContext &ctx, int sfd, RW_Mode rwm,
+ HS_Mode hsm, bool isClient );
+//------------------------------------------------------------------------
+//! Print all errors encountered so far.
+//!
+//! @param pfx The message prefix to be used (i.e. pfx: msg).
+//! @param eDest Message routing object. If nil, messages are routed
+//! to standard error.
+//------------------------------------------------------------------------
+
+ void PrintErrs(const char *pfx="TlsCon", XrdSysError *eDest=0);
+
+//------------------------------------------------------------------------
+//! Read from the TLS connection
+//! (If necessary, will establish a TLS/SSL session.)
+//------------------------------------------------------------------------
+
+ int Read( char *buffer, size_t size, int &bytesRead );
+
+//------------------------------------------------------------------------
+//! Tear down a TLS connection
+//!
+//! @param force when true, the connection will not wait for a proper
+//! shutdown (i.e. termination handshake).
+//------------------------------------------------------------------------
+
+ void Shutdown(bool force=false);
+
+//------------------------------------------------------------------------
+//! Write to the TLS connection
+//! (If necessary, will establish a TLS/SSL session.)
+//------------------------------------------------------------------------
+
+ int Write( char *buffer, size_t size, int &bytesWritten );
+
+//------------------------------------------------------------------------
+//! @return : true if the TLS/SSL session is not established yet,
+//! false otherwise
+//------------------------------------------------------------------------
+
+ bool NeedHandShake()
{
- public:
-
- enum Mode
- {
- TLS_CLIENT,
- TLS_SERVER
- };
-
- //------------------------------------------------------------------------
- //! Constructor - creates async TLS I/O wrapper for given socket
- //! file descriptor
- //------------------------------------------------------------------------
- Connection( int sfd, Mode mode );
-
- //------------------------------------------------------------------------
- //! Destructor
- //------------------------------------------------------------------------
- ~Connection();
-
- //------------------------------------------------------------------------
- //! Accept an incoming TLS connection
- //------------------------------------------------------------------------
- int Accept();
-
- //------------------------------------------------------------------------
- //! Establish a TLS connection
- //------------------------------------------------------------------------
- int Connect();
-
- //------------------------------------------------------------------------
- //! Read from the TLS connection
- //! (If necessary, will establish a TLS/SSL session.)
- //------------------------------------------------------------------------
- int Read( char *buffer, size_t size, int &bytesRead );
-
- //------------------------------------------------------------------------
- //! Write to the TLS connection
- //! (If necessary, will establish a TLS/SSL session.)
- //------------------------------------------------------------------------
- int Write( char *buffer, size_t size, int &bytesWritten );
-
- //------------------------------------------------------------------------
- //! @return : true if the TLS/SSL session is not established yet,
- //! false otherwise
- //------------------------------------------------------------------------
- bool NeedHandShake()
- {
- return !hsDone;
- }
-
- //------------------------------------------------------------------------
- //! Conversion to native OpenSSL connection object
- //!
- //! @return : SSL connection object
- //------------------------------------------------------------------------
- operator SSL*()
- {
- return ssl;
- }
-
- private:
-
- //------------------------------------------------------------------------
- //! The TSL/SSL object.
- //------------------------------------------------------------------------
- SSL *ssl;
-
- //------------------------------------------------------------------------
- //! The I/O interface.
- //------------------------------------------------------------------------
- BIO *sbio;
-
- //------------------------------------------------------------------------
- //! True if TSL/SSL handshake has been done, flase otherwise.
- //------------------------------------------------------------------------
- bool hsDone;
- };
-}
+ return !hsDone;
+ }
-#endif // __XRD_CL_TLS_HH__
+//------------------------------------------------------------------------
+//! Conversion to native OpenSSL connection object
+//!
+//! @return : SSL connection object
+//------------------------------------------------------------------------
+
+ operator SSL*()
+ {
+ return ssl;
+ }
+private:
+
+bool Wait4OK(bool wantRead);
+
+//------------------------------------------------------------------------
+//! The TLS/SSL object.
+//------------------------------------------------------------------------
+
+ XrdTlsContext *tlsctx;
+ SSL *ssl;
+
+//------------------------------------------------------------------------
+//! The socket file descriptor
+//------------------------------------------------------------------------
+
+ int sFD;
+
+//------------------------------------------------------------------------
+//! True if TSL/SSL handshake has been done, flase otherwise.
+//------------------------------------------------------------------------
+
+ bool hsDone;
+
+// Additional attributes
+//
+ char cAttr;
+ static const int isServer = 0x01;
+ static const int rBlocking = 0x02;
+ static const int wBlocking = 0x03;
+
+ char hsMode;
+ static const int noBlock = 0;
+ static const int rwBlock = 'a';
+ static const int xyBlock = 'x';
+};
+
+#endif // __XRD_CL_TLS_HH__
diff --git a/src/XrdTls/XrdTlsContext.cc b/src/XrdTls/XrdTlsContext.cc
new file mode 100644
index 00000000000..d8113ba5000
--- /dev/null
+++ b/src/XrdTls/XrdTlsContext.cc
@@ -0,0 +1,261 @@
+//------------------------------------------------------------------------------
+// Copyright (c) 2011-2018 by European Organization for Nuclear Research (CERN)
+// Author: Michal Simon
+//------------------------------------------------------------------------------
+// XRootD is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// XRootD is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with XRootD. If not, see .
+//------------------------------------------------------------------------------
+
+#include
+#include
+#include
+#include
+#include
+
+#include "XrdSys/XrdSysAtomics.hh"
+#include "XrdSys/XrdSysError.hh"
+#include "XrdSys/XrdSysPthread.hh"
+#include "XrdTls/XrdTlsContext.hh"
+
+/******************************************************************************/
+/* S S L T h r e a d i n g S u p p o r t */
+/******************************************************************************/
+
+// The following may confusing because SSL MT support is somewhat bizarre.
+// Versions < 1.0 require a numeric thread_id and lock callbasks.
+// Versions < 1.1 require a lock_callbacks but the thread_is callback is
+// optional. While the numeric thread_id callback can be used
+// it's deprecated and fancier pointer/numeric call should be
+// used. In our case, we use the deprecated version.
+// Versions >- 1.1 Do not need any callbacks as all threading functions are
+// internally defined to use native MT functions.
+
+#if OPENSSL_VERSION_NUMBER < 0x10100000L && defined(OPENSSL_THREADS)
+namespace
+{
+#define XRDTLS_SET_CALLBACKS 1
+#ifdef __solaris__
+extern "C" {
+#endif
+
+unsigned long sslTLS_id_callback(void)
+{
+ return (unsigned long)XrdSysThread::ID();
+}
+
+XrdSysMutex *MutexVector = 0;
+
+void sslTLS_lock(int mode, int n, const char *file, int line)
+{
+// Use exclusive locks. At some point, SSL categorizes these as read and
+// write locks but it's not clear when this actually occurs, sigh.
+//
+ if (mode & CRYPTO_LOCK) MutexVector[n].Lock();
+ else MutexVector[n].UnLock();
+}
+#ifdef __solaris__
+}
+#endif
+} // namespace
+#else
+#undef XRDTLS_SET_CALLBACKS
+#endif
+
+/******************************************************************************/
+/* F i l e L o c a l D e f i n i t i o n s */
+/******************************************************************************/
+
+namespace
+{
+int sslOpts = SSL_OP_ALL | SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3;
+int sslMode = SSL_MODE_AUTO_RETRY | SSL_MODE_ENABLE_PARTIAL_WRITE;
+
+XrdSysMutex ctxMutex;
+bool initDone = false;
+
+void InitTLS()
+{
+ XrdSysMutexHelper ctxHelper(ctxMutex);
+
+// Make sure we are not trying to load the ssl library more than once. This can
+// happen when a server and a client instance happen to be both defined.
+//
+ if (initDone) return;
+
+// SSL library initialisation
+//
+ SSL_library_init();
+ OpenSSL_add_all_algorithms();
+ SSL_load_error_strings();
+ OpenSSL_add_all_ciphers();
+ ERR_load_BIO_strings();
+ ERR_load_crypto_strings();
+
+// Set callbacks if we need to do this
+//
+#ifdef XRDTLS_SET_CALLBACKS
+
+ int n = CRYPTO_num_locks();
+ if (n > 0)
+ {MutexVector = new XrdSysMutex[n];
+ CRYPTO_set_locking_callback(sslTLS_lock);
+ }
+ CRYPTO_set_id_callback(sslTLS_id_callback);
+
+#endif
+}
+
+void eMsg(XrdSysError *eDest, const char *pfx, const char *eTxt)
+{
+ if (eDest)
+ {if (pfx) eDest->Say(pfx, ": ", eTxt);
+ else eDest->Say(eTxt);
+ } else {
+ if (pfx) std::cerr <
+//------------------------------------------------------------------------------
+// XRootD is free software: you can redistribute it and/or modify
+// it under the terms of the GNU Lesser General Public License as published by
+// the Free Software Foundation, either version 3 of the License, or
+// (at your option) any later version.
+//
+// XRootD is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU Lesser General Public License
+// along with XRootD. If not, see .
+//------------------------------------------------------------------------------
+
+#include
+#include
+
+/******************************************************************************/
+/* X r d T l s C o n t e x t */
+/******************************************************************************/
+
+class XrdSysError;
+
+class XrdTlsContext
+{
+public:
+
+//------------------------------------------------------------------------
+//! Obtain SSL context attached to this object
+//!
+//! @return Pointer to the SSL context to be used by a server.
+//------------------------------------------------------------------------
+
+ SSL_CTX *Context() {return ctx;}
+
+//------------------------------------------------------------------------
+//! Retrieve all errors encountered so far.
+//!
+//! @param pfx The message prefix to be used (i.e. pfx: msg).
+//!
+//! @return A string containing newline separated messages.
+//------------------------------------------------------------------------
+
+std::string GetErrs(const char *pfx=0);
+
+//------------------------------------------------------------------------
+//! Print all errors encountered so far.
+//!
+//! @param pfx The message prefix to be used (i.e. pfx: msg).
+//! @param eDest Message routing object. If nil, messages are routed
+//! to standard error.
+//------------------------------------------------------------------------
+
+ void PrintErrs(const char *pfx="Tls", XrdSysError *eDest=0);
+
+//------------------------------------------------------------------------
+//! Constructor. Note that you should use Context() to determine if
+//! construction was successful. A nil return indicates failure.
+//!
+//! @param cert Pointer to the certificate file to be used. If nil,
+//! a generic client oriented context is created.
+//! @param key Pointer to the private key flle to be used. It must
+//! correspond to the certificate file. If nil, it is
+//! assumed that the key is contained in the cert file.
+//! @param prot The protocols that the context should support. Choose
+//! one of the enums defined below. Note that doSSL includes
+//! TLS but deprecates SSL protocols mainly for https support.
+//------------------------------------------------------------------------
+
+ enum Protocol {doSSL = 0, doTLS};
+
+ XrdTlsContext(const char *cert=0, const char *key=0, Protocol prot=doTLS);
+
+//------------------------------------------------------------------------
+//! Destructor
+//------------------------------------------------------------------------
+ ~XrdTlsContext();
+
+//------------------------------------------------------------------------
+//! Conversion to SSL_CTX
+//------------------------------------------------------------------------
+
+operator SSL_CTX*() {return ctx;}
+
+//------------------------------------------------------------------------
+//! Disallow any copies of this object
+//------------------------------------------------------------------------
+
+ XrdTlsContext( const XrdTlsContext &ctx ) = delete;
+ XrdTlsContext( XrdTlsContext &&ctx ) = delete;
+
+ XrdTlsContext& operator=( const XrdTlsContext &ctx ) = delete;
+ XrdTlsContext& operator=( XrdTlsContext &&ctx ) = delete;
+
+private:
+
+ SSL_CTX *ctx;
+ const char *eText;
+};
+#endif // __XRD_TLSCONTEXT_HH__
diff --git a/src/XrdUtils.cmake b/src/XrdUtils.cmake
index 4717596438e..25722207d92 100644
--- a/src/XrdUtils.cmake
+++ b/src/XrdUtils.cmake
@@ -57,6 +57,12 @@ add_library(
XrdSys/XrdSysXSLock.cc XrdSys/XrdSysXSLock.hh
+ #-----------------------------------------------------------------------------
+ # XrdTls
+ #-----------------------------------------------------------------------------
+ XrdTls/XrdTlsConnection.cc XrdTls/XrdTlsConnection.hh
+ XrdTls/XrdTlsContext.cc XrdTls/XrdTlsContext.hh
+
#-----------------------------------------------------------------------------
# XrdOuc
#-----------------------------------------------------------------------------
@@ -202,6 +208,7 @@ target_link_libraries(
XrdUtils
pthread
${CMAKE_DL_LIBS}
+ ssl
${SOCKET_LIBRARY}
${SENDFILE_LIBRARY}
${EXTRA_LIBS} )