XRootD
XrdCl::Tls Class Reference

TLS layer for socket connection. More...

#include <XrdClTls.hh>

+ Collaboration diagram for XrdCl::Tls:

Public Member Functions

 Tls (Socket *socket, AsyncSocketHandler *socketHandler)
 Constructor - creates async TLS layer for given socker file descriptor. More...
 
 ~Tls ()
 Destructor. More...
 
XRootDStatus Connect (const std::string &thehost, XrdNetAddrInfo *netInfo)
 Establish a TLS/SSL session and perform host verification. More...
 
uint8_t MapEvent (uint8_t event)
 
XRootDStatus Read (char *buffer, size_t size, int &bytesRead)
 
XRootDStatus ReadV (iovec *iov, int iocnt, int &bytesRead)
 
XRootDStatus Send (const char *buffer, size_t size, int &bytesWritten)
 
void Shutdown ()
 Shutdown the TLS/SSL connection. More...
 

Static Public Member Functions

static void ClearErrorQueue ()
 Clear the error queue for the calling thread. More...
 

Detailed Description

TLS layer for socket connection.

Definition at line 39 of file XrdClTls.hh.

Constructor & Destructor Documentation

◆ Tls()

XrdCl::Tls::Tls ( Socket socket,
AsyncSocketHandler socketHandler 
)

Constructor - creates async TLS layer for given socker file descriptor.

Definition at line 144 of file XrdClTls.cc.

144  : pSocket( socket ), pTlsHSRevert( None ), pSocketHandler( socketHandler )
145  {
146  //----------------------------------------------------------------------
147  // Set the message callback for TLS layer
148  //----------------------------------------------------------------------
149  SetTlsMsgCB::Once();
150 
151  if( !InitTLS() )
152  throw std::runtime_error( "Failed to initialize TLS" );
153 
154  pTls.reset(
156  XrdTlsSocket::TLS_HS_NOBLK, true ) );
157  }
static std::unique_ptr< XrdTlsContext > tlsContext
Definition: XrdClTls.cc:34
int GetFD()
Get the file descriptor.
Definition: XrdClSocket.hh:214
Socket wrapper for TLS I/O.
Definition: XrdTlsSocket.hh:40
@ TLS_HS_NOBLK
Do not block during handshake.
Definition: XrdTlsSocket.hh:54
@ TLS_RNB_WNB
Non-blocking read non-blocking write.
Definition: XrdTlsSocket.hh:45
bool InitTLS()
Definition: XrdClTls.cc:96

References XrdCl::Socket::GetFD(), XrdCl::InitTLS(), XrdTlsSocket::TLS_HS_NOBLK, XrdTlsSocket::TLS_RNB_WNB, and tlsContext.

+ Here is the call graph for this function:

◆ ~Tls()

XrdCl::Tls::~Tls ( )
inline

Destructor.

Definition at line 51 of file XrdClTls.hh.

52  {
53  }

Member Function Documentation

◆ ClearErrorQueue()

void XrdCl::Tls::ClearErrorQueue ( )
static

Clear the error queue for the calling thread.

Definition at line 422 of file XrdClTls.cc.

423  {
425  }
static void ClearErrorQueue()
Clear the SSL error queue for the calling thread.
Definition: XrdTls.cc:265

References XrdTls::ClearErrorQueue().

+ Here is the call graph for this function:

◆ Connect()

XRootDStatus XrdCl::Tls::Connect ( const std::string &  thehost,
XrdNetAddrInfo netInfo 
)

Establish a TLS/SSL session and perform host verification.

Definition at line 162 of file XrdClTls.cc.

163  {
164  std::string errmsg;
165  const char *verhost = 0;
166  if( thehost != "localhost" && thehost != "127.0.0.1" && thehost != "[::1]" )
167  verhost = thehost.c_str();
168  XrdTls::RC error = pTls->Connect( verhost, &errmsg );
169  XRootDStatus status = ToStatus( error );
170  if( !status.IsOK() )
171  status.SetErrorMessage( errmsg );
172 
173  //--------------------------------------------------------------------------
174  // There's no follow up if the read simply failed
175  //--------------------------------------------------------------------------
176  if( !status.IsOK() )
177  {
179  log->Error( XrdCl::TlsMsg, "Failed to do TLS connect: %s", errmsg.c_str() );
180  return status;
181  }
182 
183 
184  if( pTls->NeedHandShake() )
185  {
186  //------------------------------------------------------------------------
187  // Make sure the socket is uncorked so the TLS hand-shake can go through
188  //------------------------------------------------------------------------
189  if( pSocket->IsCorked() )
190  {
191  XRootDStatus st = pSocket->Uncork();
192  if( !st.IsOK() ) return st;
193  }
194 
195  //----------------------------------------------------------------------
196  // Check if TLS hand-shake wants to write something
197  //----------------------------------------------------------------------
198  if( error == XrdTls::TLS_WantWrite )
199  {
200  XRootDStatus st = pSocketHandler->EnableUplink();
201  if( !st.IsOK() ) return st;
202  }
203  //----------------------------------------------------------------------
204  // Otherwise disable uplink
205  //----------------------------------------------------------------------
206  else if( error == XrdTls::TLS_WantRead )
207  {
208  XRootDStatus st = pSocketHandler->DisableUplink();
209  if( !st.IsOK() ) return st;
210  }
211  }
212 
213  return status;
214  }
XRootDStatus EnableUplink()
Enable uplink.
XRootDStatus DisableUplink()
Disable uplink.
static Log * GetLog()
Get default log.
Handle diagnostics.
Definition: XrdClLog.hh:101
void Error(uint64_t topic, const char *format,...)
Report an error.
Definition: XrdClLog.cc:231
XRootDStatus Uncork()
Definition: XrdClSocket.cc:800
bool IsCorked() const
Definition: XrdClSocket.hh:286
@ TLS_WantWrite
Reissue call when writes do not block.
Definition: XrdTls.hh:52
@ TLS_WantRead
Reissue call when reads do not block.
Definition: XrdTls.hh:51
const uint64_t TlsMsg

References XrdCl::AsyncSocketHandler::DisableUplink(), XrdCl::AsyncSocketHandler::EnableUplink(), XrdCl::Log::Error(), XrdCl::DefaultEnv::GetLog(), XrdCl::Socket::IsCorked(), XrdCl::Status::IsOK(), XrdCl::XRootDStatus::SetErrorMessage(), XrdTls::TLS_WantRead, XrdTls::TLS_WantWrite, XrdCl::TlsMsg, and XrdCl::Socket::Uncork().

+ Here is the call graph for this function:

◆ MapEvent()

uint8_t XrdCl::Tls::MapEvent ( uint8_t  event)

Map:

  • in case the TLS layer requested reads on writes map ReadyToWrite to ReadyToRead
  • in case the TLS layer requested writes on reads map ReadyToRead to ReadyToWrite

Definition at line 402 of file XrdClTls.cc.

403  {
404  if( pTlsHSRevert == ReadOnWrite )
405  {
406  //------------------------------------------------------------------------
407  // In this case we would like to call the OnRead routine on the Write event
408  //------------------------------------------------------------------------
410  }
411  else if( pTlsHSRevert == WriteOnRead )
412  {
413  //------------------------------------------------------------------------
414  // In this case we would like to call the OnWrite routine on the Read event
415  //------------------------------------------------------------------------
417  }
418 
419  return event;
420  }
@ ReadyToWrite
Writing won't block.
Definition: XrdClPoller.hh:43
@ ReadyToRead
New data has arrived.
Definition: XrdClPoller.hh:41

References XrdCl::SocketHandler::ReadyToRead, and XrdCl::SocketHandler::ReadyToWrite.

◆ Read()

XRootDStatus XrdCl::Tls::Read ( char *  buffer,
size_t  size,
int &  bytesRead 
)

Read through the TLS layer from the socket If necessary, will establish a TLS/SSL session.

Definition at line 216 of file XrdClTls.cc.

217  {
218  //--------------------------------------------------------------------------
219  // If necessary, TLS_read() will negotiate a TLS/SSL session, so we don't
220  // have to explicitly call connect or do_handshake.
221  //--------------------------------------------------------------------------
222  XrdTls::RC error = pTls->Read( buffer, size, bytesRead );
223  XRootDStatus status = ToStatus( error );
224 
225  //--------------------------------------------------------------------------
226  // There's no follow up if the read simply failed
227  //--------------------------------------------------------------------------
228  if( !status.IsOK() ) return status;
229 
230  if( pTls->NeedHandShake() )
231  {
232  //------------------------------------------------------------------------
233  // Make sure the socket is uncorked so the TLS hand-shake can go through
234  //------------------------------------------------------------------------
235  if( pSocket->IsCorked() )
236  {
237  XRootDStatus st = pSocket->Uncork();
238  if( !st.IsOK() ) return st;
239  }
240 
241  //----------------------------------------------------------------------
242  // Check if we need to switch on a revert state
243  //----------------------------------------------------------------------
244  if( error == XrdTls::TLS_WantWrite )
245  {
246  pTlsHSRevert = ReadOnWrite;
247  XRootDStatus st = pSocketHandler->EnableUplink();
248  if( !st.IsOK() ) status = st;
249  //--------------------------------------------------------------------
250  // Return early so the revert state won't get cleared
251  //--------------------------------------------------------------------
252  return status;
253  }
254  }
255 
256  //------------------------------------------------------------------------
257  // If we got up until here we need to clear the revert state
258  //------------------------------------------------------------------------
259  if( pTlsHSRevert == ReadOnWrite )
260  {
261  XRootDStatus st = pSocketHandler->DisableUplink();
262  if( !st.IsOK() ) status = st;
263  }
264  pTlsHSRevert = None;
265 
266  //------------------------------------------------------------------------
267  // If we didn't manage to read any data wait for another read event
268  //------------------------------------------------------------------------
269  if( bytesRead == 0 )
270  return XRootDStatus( stOK, suRetry );
271 
272  return status;
273  }
const uint16_t suRetry
Definition: XrdClStatus.hh:40
const uint16_t stOK
Everything went OK.
Definition: XrdClStatus.hh:31

References XrdCl::AsyncSocketHandler::DisableUplink(), XrdCl::AsyncSocketHandler::EnableUplink(), XrdCl::Socket::IsCorked(), XrdCl::Status::IsOK(), XrdCl::stOK, XrdCl::suRetry, XrdTls::TLS_WantWrite, and XrdCl::Socket::Uncork().

Referenced by ReadV().

+ Here is the call graph for this function:
+ Here is the caller graph for this function:

◆ ReadV()

XRootDStatus XrdCl::Tls::ReadV ( iovec *  iov,
int  iocnt,
int &  bytesRead 
)

(Fake) ReadV through the TLS layer from the socket If necessary, will establish a TLS/SSL session.

Definition at line 279 of file XrdClTls.cc.

280  {
281  bytesRead = 0;
282  for( int i = 0; i < iocnt; ++i )
283  {
284  int btsread = 0;
285  auto st = Read( static_cast<char*>( iov[i].iov_base ),
286  iov[i].iov_len, btsread );
287  if( !st.IsOK() ) return st;
288  bytesRead += btsread;
289  if( st.code == suRetry ) return st;
290  }
291  return XRootDStatus();
292  }
XRootDStatus Read(char *buffer, size_t size, int &bytesRead)
Definition: XrdClTls.cc:216

References Read(), and XrdCl::suRetry.

+ Here is the call graph for this function:

◆ Send()

XRootDStatus XrdCl::Tls::Send ( const char *  buffer,
size_t  size,
int &  bytesWritten 
)

Write through the TLS layer to the socket If necessary, will establish a TLS/SSL session.

Definition at line 294 of file XrdClTls.cc.

295  {
296  //--------------------------------------------------------------------------
297  // If necessary, TLS_write() will negotiate a TLS/SSL session, so we don't
298  // have to explicitly call connect or do_handshake.
299  //--------------------------------------------------------------------------
300  XrdTls::RC error = pTls->Write( buffer, size, bytesWritten );
301  XRootDStatus status = ToStatus( error );
302 
303  //--------------------------------------------------------------------------
304  // There's no follow up if the write simply failed
305  //--------------------------------------------------------------------------
306  if( !status.IsOK() ) return status;
307 
308  //--------------------------------------------------------------------------
309  // We are in the middle of a TLS hand-shake
310  //--------------------------------------------------------------------------
311  if( pTls->NeedHandShake() )
312  {
313  //------------------------------------------------------------------------
314  // Make sure the socket is uncorked so the TLS hand-shake can go through
315  //------------------------------------------------------------------------
316  if( pSocket->IsCorked() )
317  {
318  XRootDStatus st = pSocket->Uncork();
319  if( !st.IsOK() ) return st;
320  }
321 
322  //------------------------------------------------------------------------
323  // Check if we need to switch on a revert state
324  //------------------------------------------------------------------------
325  if( error == XrdTls::TLS_WantRead )
326  {
327  pTlsHSRevert = WriteOnRead;
328  XRootDStatus st = pSocketHandler->DisableUplink();
329  if( !st.IsOK() ) status = st;
330  //----------------------------------------------------------------------
331  // Return early so the revert state won't get cleared
332  //----------------------------------------------------------------------
333  return status;
334  }
335  }
336 
337  //--------------------------------------------------------------------------
338  // If we got up until here we need to clear the revert state
339  //--------------------------------------------------------------------------
340  if( pTlsHSRevert == WriteOnRead )
341  {
342  XRootDStatus st = pSocketHandler->EnableUplink();
343  if( !st.IsOK() ) status = st;
344  }
345  pTlsHSRevert = None;
346 
347  //------------------------------------------------------------------------
348  // If we didn't manage to read any data wait for another write event
349  //
350  // Adding this by symmetry, never actually experienced this (for reads
351  // it has been experienced)
352  //------------------------------------------------------------------------
353  if( bytesWritten == 0 )
354  return XRootDStatus( stOK, suRetry );
355 
356  return status;
357  }

References XrdCl::AsyncSocketHandler::DisableUplink(), XrdCl::AsyncSocketHandler::EnableUplink(), XrdCl::Socket::IsCorked(), XrdCl::Status::IsOK(), XrdCl::stOK, XrdCl::suRetry, XrdTls::TLS_WantRead, and XrdCl::Socket::Uncork().

+ Here is the call graph for this function:

◆ Shutdown()

void XrdCl::Tls::Shutdown ( )

Shutdown the TLS/SSL connection.

Definition at line 362 of file XrdClTls.cc.

363  {
364  pTls->Shutdown();
365  }

The documentation for this class was generated from the following files: