Skip to content

Commit

Permalink
[XrdCl] Respect server TLS flags in kXR_protocol response.
Browse files Browse the repository at this point in the history
Part 1. Only for the main stream (0).
  • Loading branch information
simonmichal committed Oct 16, 2019
1 parent b67fb34 commit f04e02e
Show file tree
Hide file tree
Showing 10 changed files with 99 additions and 122 deletions.
85 changes: 12 additions & 73 deletions src/XrdCl/XrdClAsyncSocketHandler.cc
Expand Up @@ -738,6 +738,18 @@ namespace XrdCl
//--------------------------------------------------------------------------
++pHandShakeData->step;

if( pTransport->UseEncryption( pHandShakeData, *pChannelData ) )
{
Status st = EnableEncryption();
if( !st.IsOK() )
{
OnFaultWhileHandshaking( st );
return;
}
}

// TODO query transport if should switch to encrypted

//--------------------------------------------------------------------------
// The transport handler gave us something to write
//--------------------------------------------------------------------------
Expand Down Expand Up @@ -887,79 +899,6 @@ namespace XrdCl
OnFaultWhileHandshaking( Status( stError, errSocketTimeout ) );
}

//------------------------------------------------------------------------
// Initialize the iovec with given message
//------------------------------------------------------------------------
void AsyncSocketHandler::ToIov( Message &msg, iovec &iov )
{
iov.iov_base = msg.GetBufferAtCursor();
iov.iov_len = msg.GetSize() - msg.GetCursor();
}

//------------------------------------------------------------------------
// Update iovec after write
//------------------------------------------------------------------------
void AsyncSocketHandler::UpdateAfterWrite( Message &msg,
iovec &iov,
int &bytesWritten )
{
size_t advance = ( bytesWritten < (int)iov.iov_len ) ? bytesWritten : iov.iov_len;
bytesWritten -= advance;
msg.AdvanceCursor( advance );
ToIov( msg, iov );
}

//------------------------------------------------------------------------
// Add chunks to the given iovec
//------------------------------------------------------------------------
uint32_t AsyncSocketHandler::ToIov( ChunkList *chunks,
const uint32_t *offset,
iovec *iov )
{
if( !chunks || !offset ) return 0;

uint32_t off = *offset;
uint32_t size = 0;

for( auto itr = chunks->begin(); itr != chunks->end(); ++itr )
{
auto &chunk = *itr;
if( off > chunk.length )
{
iov->iov_len = 0;
iov->iov_base = 0;
off -= chunk.length;
}
else if( off > 0 )
{
iov->iov_len = chunk.length - off;
iov->iov_base = reinterpret_cast<char*>( chunk.buffer ) + off;
size += iov->iov_len;
off = 0;
}
else
{
iov->iov_len = chunk.length;
iov->iov_base = chunk.buffer;
size += iov->iov_len;
}
++iov;
}

return size;
}

void AsyncSocketHandler::UpdateAfterWrite( ChunkList *chunks,
uint32_t *offset,
iovec *iov,
int &bytesWritten )
{
*offset += bytesWritten;
bytesWritten = 0;
ToIov( chunks, offset, iov );
}


void AsyncSocketHandler::RetryHSMsg( Message *msg )
{
pHSOutgoing = msg;
Expand Down
25 changes: 0 additions & 25 deletions src/XrdCl/XrdClAsyncSocketHandler.hh
Expand Up @@ -226,31 +226,6 @@ namespace XrdCl
//------------------------------------------------------------------------
void OnTimeoutWhileHandshaking();

//------------------------------------------------------------------------
// Initialize the iovec with given message
//------------------------------------------------------------------------
inline void ToIov( Message &msg, iovec &iov );

//------------------------------------------------------------------------
// Update iovec after write
//------------------------------------------------------------------------
inline void UpdateAfterWrite( Message &msg, iovec &iov, int &bytesRead );

//------------------------------------------------------------------------
// Add chunks to the given iovec
//------------------------------------------------------------------------
inline uint32_t ToIov( ChunkList *chunks,
const uint32_t *offset,
iovec *iov );

//------------------------------------------------------------------------
// Update raw data after write
//------------------------------------------------------------------------
inline void UpdateAfterWrite( ChunkList *chunks,
uint32_t *offset,
iovec *iov,
int &bytesWritten );

//------------------------------------------------------------------------
// Retry hand shake message
//------------------------------------------------------------------------
Expand Down
2 changes: 1 addition & 1 deletion src/XrdCl/XrdClChannel.cc
Expand Up @@ -244,7 +244,7 @@ namespace XrdCl
int timeoutResolution = DefaultTimeoutResolution;
env->GetInt( "TimeoutResolution", timeoutResolution );

pTransport->InitializeChannel( pChannelData );
pTransport->InitializeChannel( pChannelData, url.IsSecure() );
log->Debug( PostMasterMsg, "Creating new channel to: %s",
url.GetHostId().c_str() );

Expand Down
9 changes: 8 additions & 1 deletion src/XrdCl/XrdClPostMasterInterfaces.hh
Expand Up @@ -352,7 +352,8 @@ namespace XrdCl
//------------------------------------------------------------------------
//! Initialize channel
//------------------------------------------------------------------------
virtual void InitializeChannel( AnyObject &channelData ) = 0;
virtual void InitializeChannel( AnyObject &channelData,
bool encrypted ) = 0;

//------------------------------------------------------------------------
//! Finalize channel
Expand Down Expand Up @@ -438,6 +439,12 @@ namespace XrdCl
//------------------------------------------------------------------------
virtual void WaitBeforeExit() = 0;

//------------------------------------------------------------------------
//! @return : true if encryption should be turned on, false otherwise
//------------------------------------------------------------------------
virtual bool UseEncryption( HandShakeData *handShakeData,
AnyObject &channelData ) = 0;

//------------------------------------------------------------------------
//! Get signature for given message
//------------------------------------------------------------------------
Expand Down
12 changes: 4 additions & 8 deletions src/XrdCl/XrdClStream.cc
Expand Up @@ -35,7 +35,6 @@
#include "XrdCl/XrdClMessageUtils.hh"
#include "XrdCl/XrdClXRootDTransport.hh"
#include "XrdClAsyncSocketHandler.hh"
#include "XrdClAsyncTlsSocketHandler.hh"

#include <sys/types.h>
#include <algorithm>
Expand Down Expand Up @@ -181,9 +180,8 @@ namespace XrdCl
if( !pTransport || !pPoller || !pChannelData )
return Status( stError, errUninitialized );

AsyncSocketHandler *s = IsSecure() ?
new AsyncTlsSocketHandler( pPoller, pTransport, pChannelData, 0 ) :
new AsyncSocketHandler( pPoller, pTransport, pChannelData, 0 );
AsyncSocketHandler *s = new AsyncSocketHandler( pPoller, pTransport,
pChannelData, 0 );
s->SetStream( this );

pSubStreams.push_back( new SubStreamData() );
Expand Down Expand Up @@ -580,10 +578,8 @@ namespace XrdCl
{
for( uint16_t i = 1; i < numSub; ++i )
{
AsyncSocketHandler *s = IsSecure() ?
new AsyncTlsSocketHandler( pPoller, pTransport, pChannelData, i ) :
new AsyncSocketHandler( pPoller, pTransport, pChannelData, i );

AsyncSocketHandler *s = new AsyncSocketHandler( pPoller, pTransport,
pChannelData, 0 );
s->SetStream( this );
pSubStreams.push_back( new SubStreamData() );
pSubStreams[i]->socket = s;
Expand Down
10 changes: 0 additions & 10 deletions src/XrdCl/XrdClStream.hh
Expand Up @@ -312,16 +312,6 @@ namespace XrdCl
//------------------------------------------------------------------------
Status RequestClose( Message *resp );

//------------------------------------------------------------------------
//! @return : true if this stream is for roots/xroots protocol,
//! false otherwise
//------------------------------------------------------------------------
bool IsSecure()
{
const std::string& protocol = pUrl->GetProtocol();
return ( protocol == "roots" || protocol == "xroots" );
}

typedef std::vector<SubStreamData*> SubStreamList;

//------------------------------------------------------------------------
Expand Down
8 changes: 8 additions & 0 deletions src/XrdCl/XrdClURL.cc
Expand Up @@ -440,6 +440,14 @@ namespace XrdCl
return pProtocol == "file" && pHostName == "localhost";
}

//------------------------------------------------------------------------
// Does the protocol indicate encryption
//------------------------------------------------------------------------
bool URL::IsSecure() const
{
return ( pProtocol == "roots" || pProtocol == "xroots" );
}

bool URL::PathEndsWith(const std::string & sufix) const
{
if (sufix.size() > pPath.size()) return false;
Expand Down
5 changes: 5 additions & 0 deletions src/XrdCl/XrdClURL.hh
Expand Up @@ -70,6 +70,11 @@ namespace XrdCl
//------------------------------------------------------------------------
bool IsLocalFile() const;

//------------------------------------------------------------------------
//! Does the protocol indicate encryption
//------------------------------------------------------------------------
bool IsSecure() const;

//------------------------------------------------------------------------
//! Get the URL
//------------------------------------------------------------------------
Expand Down
56 changes: 53 additions & 3 deletions src/XrdCl/XrdClXRootDTransport.cc
Expand Up @@ -43,6 +43,7 @@
#include "XrdSec/XrdSecProtect.hh"
#include "XrdCl/XrdClTls.hh"
#include "XrdCl/XrdClSocket.hh"
#include "XProtocol/XProtocol.hh"
#include "XrdVersion.hh"

#include <arpa/inet.h>
Expand Down Expand Up @@ -204,6 +205,7 @@ namespace XrdCl
protRespBody(0),
protRespSize(0),
strmSelector(0)
encrypted(false)
{
sidManager = new SIDManager();
memset( sessionId, 0, 16 );
Expand Down Expand Up @@ -246,6 +248,7 @@ namespace XrdCl
ServerResponseBody_Protocol *protRespBody;
unsigned int protRespSize;
StreamSelector *strmSelector;
bool encrypted;
XrdSysMutex mutex;
};

Expand Down Expand Up @@ -337,7 +340,8 @@ namespace XrdCl
//----------------------------------------------------------------------------
// Initialize channel
//----------------------------------------------------------------------------
void XRootDTransport::InitializeChannel( AnyObject &channelData )
void XRootDTransport::InitializeChannel( AnyObject &channelData,
bool encrypted )
{
XRootDChannelInfo *info = new XRootDChannelInfo();
XrdSysMutexHelper scopedLock( info->mutex );
Expand All @@ -349,6 +353,7 @@ namespace XrdCl
if( streams < 1 ) streams = 1;
info->stream.resize( streams );
info->strmSelector = new StreamSelector( streams );
info->encrypted = encrypted;
}

//----------------------------------------------------------------------------
Expand Down Expand Up @@ -1369,12 +1374,44 @@ namespace XrdCl
pSecUnloadHandler->unloaded = true;
}

//------------------------------------------------------------------------
// @return : true if encryption should be turned on, false otherwise
//------------------------------------------------------------------------
bool XRootDTransport::UseEncryption( HandShakeData *handShakeData,
AnyObject &channelData )
{
XRootDChannelInfo *info = 0;
channelData.Get( info );

// Did the server instructed us to switch to TLS?
if( !( info->serverFlags & kXR_gotoTLS ) ) return false;

XRootDStreamInfo &sInfo = info->stream[handShakeData->subStreamId];

//----------------------------------------------------------------------
// We are about to login and the server asked to start encrypting with
// before login
//----------------------------------------------------------------------
if( ( sInfo.status == XRootDStreamInfo::HandShakeReceived ) &&
( info->serverFlags & kXR_tlsLogin ) )
return true;

//----------------------------------------------------------------------
// The hand-shake is done and the server requested to encrypt the session
//----------------------------------------------------------------------
if( (sInfo.status == XRootDStreamInfo::Connected ) &&
( info->serverFlags & kXR_tlsSess ) )
return true;

return false;
}

//----------------------------------------------------------------------------
// Generate the message to be sent as an initial handshake
// (handshake+kXR_protocol)
//----------------------------------------------------------------------------
Message *XRootDTransport::GenerateInitialHSProtocol( HandShakeData *hsData,
XRootDChannelInfo * )
XRootDChannelInfo *info )
{
Log *log = DefaultEnv::GetLog();
log->Debug( XRootDTransportMsg,
Expand All @@ -1393,7 +1430,11 @@ namespace XrdCl

proto->requestid = htons(kXR_protocol);
proto->clientpv = htonl(kXR_PROTOCOLVERSION);
proto->flags = ClientProtocolRequest::kXR_secreqs;
proto->flags = ClientProtocolRequest::kXR_secreqs |
ClientProtocolRequest::kXR_ableTLS;
if( info->encrypted ) proto->flags |= ClientProtocolRequest::kXR_wantTLS;
proto->expect = ClientProtocolRequest::kXR_ExpLogin; // we generate the initial HS + protocol
// the next step is kXR_login
return msg;
}

Expand Down Expand Up @@ -1494,6 +1535,15 @@ namespace XrdCl
hsData->streamName.c_str(),
ServerFlagsToStr( info->serverFlags ).c_str(),
info->protocolVersion );

if( !( info->serverFlags & kXR_haveTLS ) && info->encrypted )
{
//------------------------------------------------------------------------
// User requested an encrypted connection but the server does not support
// encryption!
//------------------------------------------------------------------------
return Status( stError, errTlsError, errNotSupported );
}

return Status( stOK, suContinue );
}
Expand Down
9 changes: 8 additions & 1 deletion src/XrdCl/XrdClXRootDTransport.hh
Expand Up @@ -95,7 +95,8 @@ namespace XrdCl
//------------------------------------------------------------------------
//! Initialize channel
//------------------------------------------------------------------------
virtual void InitializeChannel( AnyObject &channelData );
virtual void InitializeChannel( AnyObject &channelData,
bool encrypted );

//------------------------------------------------------------------------
//! Finalize channel
Expand Down Expand Up @@ -231,6 +232,12 @@ namespace XrdCl
//------------------------------------------------------------------------
virtual void WaitBeforeExit();

//------------------------------------------------------------------------
//! @return : true if encryption should be turned on, false otherwise
//------------------------------------------------------------------------
virtual bool UseEncryption( HandShakeData *handShakeData,
AnyObject &channelData );

private:

//------------------------------------------------------------------------
Expand Down

0 comments on commit f04e02e

Please sign in to comment.