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} )