26 #include <openssl/ssl.h>
27 #include <openssl/bio.h>
28 #include <openssl/err.h>
29 #include <sys/types.h>
30 #include <sys/socket.h>
80 ~undoImpl() {
if (theImpl && theImpl->ssl)
81 {SSL_free( theImpl->ssl );
86 void KeepImpl() {theImpl = 0;}
108 static const int xVerify = 0x01;
109 static const int DNSok = 0x04;
111 static const int isServer = 0x01;
112 static const int rBlocking = 0x02;
113 static const int wBlocking = 0x04;
114 static const int acc2Block = 0x08;
133 bool isClient,
bool serial )
139 const char *
eMsg =
Init(ctx, sfd, rwm, hsm, isClient, serial);
140 if (
eMsg)
throw std::invalid_argument(
eMsg );
161 bool wOK, aOK =
true;
166 {AcceptEMsg(eWhy,
"TLS socket has no context");
169 undoImpl ImplTracker(pImpl);
173 DBG_SOK(
"Accepting a TLS connection...");
177 do{
if ((rc = SSL_accept( pImpl->
ssl )) > 0)
178 {
if (pImpl->
cOpts & xVerify)
179 {X509 *theCert = SSL_get_peer_certificate(pImpl->
ssl);
181 {AcceptEMsg(eWhy,
"x509 certificate is missing");
185 rc = SSL_get_verify_result(pImpl->
ssl);
187 {AcceptEMsg(eWhy,
"x509 certificate verification failed");
191 ImplTracker.KeepImpl();
197 if (pImpl->
cAttr & acc2Block)
200 int flags = fcntl(pImpl->
sFD, F_GETFL, 0);
201 flags &= ~O_NONBLOCK;
202 fcntl(pImpl->
sFD, F_SETFL, flags);
203 SSL_set_mode(pImpl->
ssl, SSL_MODE_AUTO_RETRY);
215 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE) {
216 if(ssler == SSL_ERROR_SSL){
227 }
while((wOK = Wait4OK(ssler == SSL_ERROR_WANT_READ)));
231 AcceptEMsg(eWhy, (!aOK ? Err2Text(ssler).c_str() :
XrdSysE2T(errno)));
232 errno = ECONNABORTED;
240 void XrdTlsSocket::AcceptEMsg(std::string *eWhy,
const char *reason)
243 {*eWhy =
"TLS connection from ";
245 *eWhy +=
" failed; ";
258 bool wOK =
true, aOK =
true;
266 DBG_SOK(
"Connecting to " <<(thehost ? thehost :
"unverified host")
267 <<(thehost && pImpl->
cOpts & DNSok ?
" dnsok" :
"" ));
271 do{
int rc = SSL_connect( pImpl->
ssl );
276 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
277 {aOK =
false;
break;}
281 }
while((wOK = Wait4OK(ssler == SSL_ERROR_WANT_READ)));
290 {
const char *hName = (thehost ? thehost :
"host");
291 *eWhy =
"Unable to connect to ";
294 if (!aOK) *eWhy += Err2Text(ssler);
304 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
314 {
DBG_SOK(thehost <<
" verification failed; " <<eTxt);
317 *eWhy =
"Unable to validate "; *eWhy += thehost;
318 *eWhy +=
"; "; *eWhy += eTxt;
324 DBG_SOK(
"Connect completed without error.");
341 int XrdTlsSocket::Diagnose(
const char *what,
int sslrc,
int tcode)
343 int eCode = SSL_get_error( pImpl->
ssl, sslrc );
350 || (eCode != SSL_ERROR_WANT_READ && eCode != SSL_ERROR_WANT_WRITE))
352 if (!eNO && eCode == SSL_ERROR_SYSCALL) ERR_clear_error();
353 else {
char eBuff[256];
354 snprintf(eBuff,
sizeof(eBuff),
355 "TLS error rc=%d ec=%d (%s) errno=%d.",
360 }
else ERR_clear_error();
364 if (eCode == SSL_ERROR_SYSCALL)
366 else if (eCode == SSL_ERROR_SSL)
378 std::string XrdTlsSocket::Err2Text(
int sslerr)
383 if (sslerr == SSL_ERROR_SYSCALL)
386 snprintf(eBuff,
sizeof(eBuff),
"%s",
XrdSysE2T(rc));
387 *eBuff = tolower(*eBuff);
391 return std::string(eP);
408 if (ver && SSL_get_verify_result(pImpl->
ssl) != X509_V_OK)
return 0;
412 X509 *pcert = SSL_get_peer_certificate(pImpl->
ssl);
413 if (pcert == 0)
return 0;
424 bool isClient,
bool serial,
427 BIO *rbio, *wbio = 0;
433 {
if (isClient)
return "TLS I/O: connection is still in use.";
434 else {SSL_free( pImpl->
ssl );
441 pImpl->
ssl =
static_cast<SSL *
>(ctx.
Session());
442 if (pImpl->
ssl == 0)
return "TLS I/O: failed to get ssl object.";
450 else pImpl->
cOpts = 0;
459 {SSL_set_connect_state( pImpl->
ssl );
462 SSL_set_accept_state( pImpl->
ssl );
463 pImpl->
cAttr = isServer;
472 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
473 BIO_set_nbio( rbio, 1 );
477 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
478 BIO_set_nbio( rbio, 1 );
479 wbio = BIO_new_socket( sfd, BIO_NOCLOSE );
480 pImpl->
cAttr |= wBlocking;
484 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
485 wbio = BIO_new_socket( sfd, BIO_NOCLOSE );
486 BIO_set_nbio( wbio, 1 );
487 pImpl->
cAttr |= rBlocking;
491 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
492 pImpl->
cAttr |= (rBlocking | wBlocking);
496 return "TLS I/O: invalid TLS rw mode.";
break;
515 if (pImpl->
hsWait && !hsm && pImpl->
cAttr & rBlocking)
516 {
int flags = fcntl(sfd, F_GETFL, 0);
518 fcntl(sfd, F_SETFL, flags);
519 pImpl->
cAttr |= acc2Block;
526 if (wbio == 0) wbio = rbio;
527 SSL_set_bio( pImpl->
ssl, rbio, wbio );
556 {
DBG_SIO(
"Failing due to previous error, fatal=" << (
int)pImpl->
fatal);
565 do{
int rc = SSL_peek( pImpl->
ssl, buffer, size );
578 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
583 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
588 if ((pImpl->
hsNoBlock && NeedHS()) || !(pImpl->
cAttr & rBlocking))
591 }
while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
611 if (pImpl->
fatal)
return 0;
619 if (!any)
return SSL_pending(pImpl->
ssl);
620 #if OPENSSL_VERSION_NUMBER < 0x10100000L
621 return SSL_pending(pImpl->
ssl) != 0;
623 return SSL_has_pending(pImpl->
ssl);
649 {
DBG_SIO(
"Failing due to previous error, fatal=" << (
int)pImpl->
fatal);
658 do{
int rc = SSL_read( pImpl->
ssl, buffer, size );
665 DBG_SIO(rc <<
" out of " <<size <<
" bytes.");
673 if (ssler == SSL_ERROR_NONE)
675 DBG_SIO(
"0 out of " <<size <<
" bytes.");
681 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
687 if ((pImpl->
hsNoBlock && NeedHS()) || !(pImpl->
cAttr & rBlocking))
692 }
while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
703 if (pImpl) pImpl->
traceID = tid;
719 if (pImpl->
ssl == 0)
return;
732 sdMode = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;
740 sdMode = SSL_RECEIVED_SHUTDOWN;
745 DBG_SOK(
"Doing " <<how <<
" shutdown.");
746 SSL_set_shutdown(pImpl->
ssl, sdMode);
748 for (
int i = 0; i < 4; i++)
749 {rc = SSL_shutdown( pImpl->
ssl );
752 {rc = SSL_get_error( pImpl->
ssl, rc );
753 if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE)
754 {
if (Wait4OK(rc == SSL_ERROR_WANT_READ))
continue;
755 rc = SSL_ERROR_SYSCALL;
758 std::string
eMsg = Err2Text(rc);
759 snprintf(msgBuff,
sizeof(msgBuff),
760 "FD %d TLS shutdown failed; %s.\n",pImpl->
sFD,
eMsg.c_str());
769 SSL_free( pImpl->
ssl );
797 {
DBG_SIO(
"Failing due to previous error, fatal=" << (
int)pImpl->
fatal);
806 do{
int rc = SSL_write( pImpl->
ssl, buffer, size );
813 DBG_SIO(rc <<
" out of " <<size <<
" bytes.");
821 if (ssler == SSL_ERROR_NONE)
823 DBG_SIO(rc <<
" out of " <<size <<
" bytes.");
829 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
835 if ((pImpl->
hsNoBlock && NeedHS()) || !(pImpl->
cAttr & wBlocking))
840 }
while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
861 if (pImpl->
fatal)
return false;
862 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
870 bool XrdTlsSocket::NeedHS()
879 if (pImpl->
fatal)
return false;
880 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
893 return SSL_get_version(pImpl->
ssl);
900 bool XrdTlsSocket::Wait4OK(
bool wantRead)
902 static const short rdOK = POLLIN |POLLRDNORM;
903 static const short wrOK = POLLOUT|POLLWRNORM;
904 struct pollfd polltab = {pImpl->
sFD, (wantRead ? rdOK : wrOK), 0};
909 if (pImpl->
hsDone) timeout = -1;
912 do {rc = poll(&polltab, 1, timeout);}
while(rc < 0 && errno == EINTR);
918 {
if (polltab.revents & (wantRead ? rdOK : wrOK))
return true;
919 if (polltab.revents & POLLERR) errno = EIO;
920 else if (polltab.revents & (POLLHUP|POLLNVAL)) errno = EPIPE;
922 }
else if (!rc) errno = ETIMEDOUT;
const char * XrdSysE2T(int errcode)
void Lock(XrdSysMutex *Mutex)
static const uint64_t hsto
Mask to isolate the hsto.
const CTX_Params * GetParams()
static const uint64_t dnsok
Trust DNS for host name.
static const char * Validate(const SSL *ssl, const char *hName, XrdNetAddrInfo *netInfo=0)
XrdTlsContext * Context()
XrdTls::RC Accept(std::string *eMsg=0)
void Shutdown(SDType=sdImmed)
~XrdTlsSocket()
Destructor.
@ TLS_RNB_WBL
Non-blocking read blocking write.
@ TLS_RBL_WNB
blocking read non-blocking write
@ TLS_RBL_WBL
blocking read blocking write
@ TLS_RNB_WNB
Non-blocking read non-blocking write.
XrdTls::RC Write(const char *buffer, size_t size, int &bytesOut)
XrdTls::RC Read(char *buffer, size_t size, int &bytesRead)
Read from the TLS connection. If necessary, a handshake will be done.
const char * Init(XrdTlsContext &ctx, int sfd, RW_Mode rwm, HS_Mode hsm, bool isClient, bool serial=true, const char *tid="")
XrdTls::RC Connect(const char *thehost=0, std::string *eWhy=0)
void SetTraceID(const char *tid)
int Pending(bool any=true)
XrdTls::RC Peek(char *buffer, size_t size, int &bytesPeek)
XrdTlsPeerCerts * getCerts(bool ver=true)
static RC ssl2RC(int sslrc)
static const int dbgSIO
Turn debugging in for socket I/O.
static const int dbgSOK
Turn debugging in for socket operations.
static void Emsg(const char *tid, const char *msg=0, bool flush=true)
static const char * ssl2Text(int sslrc, const char *dflt="unknown_error")
@ TLS_AOK
All went well, will always be zero.
@ TLS_HNV_Error
A hostname validation error occuured.
@ TLS_VER_Error
Certificate verification failed.
@ TLS_CRT_Missing
The x509 certificate missing.
@ TLS_SYS_Error
A system call error occurred.
@ TLS_SSL_Error
An SSL error occurred.
@ TLS_CTX_Missing
The TLS context is missing.
XrdSysTrace SysTrace("TLS", 0)
uint64_t opts
Options as passed to the constructor.
char cOpts
Connection options.
XrdSysMutex sslMutex
Mutex to serialize calls.
bool isClient
True if for client use.
bool hsDone
True if the handshake has completed.
char fatal
!0 if fatal error prevents shutdown call
bool hsNoBlock
Handshake handling nonblocking if true.
int sFD
Associated file descriptor (never closed)
char cAttr
Connection attributes.
bool isSerial
True if calls must be serialized.
XrdTlsContext * tlsctx
Associated context object.
const char * traceID
Trace identifier.
SSL * ssl
Associated SSL object.
int hsWait
Maximum amount of time to wait for handshake.