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 noBlock = 0;
109 static const int rwBlock =
'a';
110 static const int xyBlock =
'x';
112 static const int xVerify = 0x01;
113 static const int DNSok = 0x04;
115 static const int isServer = 0x01;
116 static const int rBlocking = 0x02;
117 static const int wBlocking = 0x04;
118 static const int acc2Block = 0x08;
137 bool isClient,
bool serial )
143 const char *
eMsg =
Init(ctx, sfd, rwm, hsm, isClient, serial);
144 if (
eMsg)
throw std::invalid_argument(
eMsg );
165 bool wOK, aOK =
true;
170 {AcceptEMsg(eWhy,
"TLS socket has no context");
173 undoImpl ImplTracker(pImpl);
177 DBG_SOK(
"Accepting a TLS connection...");
181 do{
if ((rc = SSL_accept( pImpl->
ssl )) > 0)
182 {
if (pImpl->
cOpts & xVerify)
183 {X509 *theCert = SSL_get_peer_certificate(pImpl->
ssl);
185 {AcceptEMsg(eWhy,
"x509 certificate is missing");
189 rc = SSL_get_verify_result(pImpl->
ssl);
191 {AcceptEMsg(eWhy,
"x509 certificate verification failed");
195 ImplTracker.KeepImpl();
201 if (pImpl->
cAttr & acc2Block)
204 int flags =
fcntl(pImpl->
sFD, F_GETFL, 0);
205 flags &= ~O_NONBLOCK;
207 SSL_set_mode(pImpl->
ssl, SSL_MODE_AUTO_RETRY);
219 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE) {
220 if(ssler == SSL_ERROR_SSL){
231 }
while((wOK = Wait4OK(ssler == SSL_ERROR_WANT_READ)));
235 AcceptEMsg(eWhy, (!aOK ? Err2Text(ssler).c_str() :
XrdSysE2T(errno)));
236 errno = ECONNABORTED;
244 void XrdTlsSocket::AcceptEMsg(std::string *eWhy,
const char *reason)
247 {*eWhy =
"TLS connection from ";
249 *eWhy +=
" failed; ";
262 bool wOK =
true, aOK =
true;
270 DBG_SOK(
"Connecting to " <<(thehost ? thehost :
"unverified host")
271 <<(thehost && pImpl->
cOpts & DNSok ?
" dnsok" :
"" ));
275 do{
int rc = SSL_connect( pImpl->
ssl );
280 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
281 {aOK =
false;
break;}
285 }
while((wOK = Wait4OK(ssler == SSL_ERROR_WANT_READ)));
294 {
const char *hName = (thehost ? thehost :
"host");
295 *eWhy =
"Unable to connect to ";
298 if (!aOK) *eWhy += Err2Text(ssler);
308 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
318 {
DBG_SOK(thehost <<
" verification failed; " <<eTxt);
321 *eWhy =
"Unable to validate "; *eWhy += thehost;
322 *eWhy +=
"; "; *eWhy += eTxt;
328 DBG_SOK(
"Connect completed without error.");
345 int XrdTlsSocket::Diagnose(
const char *what,
int sslrc,
int tcode)
347 int eCode = SSL_get_error( pImpl->
ssl, sslrc );
354 || (eCode != SSL_ERROR_WANT_READ && eCode != SSL_ERROR_WANT_WRITE))
356 if (!eNO && eCode == SSL_ERROR_SYSCALL) ERR_clear_error();
357 else {
char eBuff[256];
358 snprintf(eBuff,
sizeof(eBuff),
359 "TLS error rc=%d ec=%d (%s) errno=%d.",
364 }
else ERR_clear_error();
368 if (eCode == SSL_ERROR_SYSCALL)
370 else if (eCode == SSL_ERROR_SSL)
382 std::string XrdTlsSocket::Err2Text(
int sslerr)
387 if (sslerr == SSL_ERROR_SYSCALL)
390 snprintf(eBuff,
sizeof(eBuff),
"%s",
XrdSysE2T(rc));
391 *eBuff = tolower(*eBuff);
395 return std::string(eP);
412 if (ver && SSL_get_verify_result(pImpl->
ssl) != X509_V_OK)
return 0;
416 X509 *pcert = SSL_get_peer_certificate(pImpl->
ssl);
417 if (pcert == 0)
return 0;
428 bool isClient,
bool serial,
431 BIO *rbio, *wbio = 0;
437 {
if (isClient)
return "TLS I/O: connection is still in use.";
438 else {SSL_free( pImpl->
ssl );
445 pImpl->
ssl =
static_cast<SSL *
>(ctx.
Session());
446 if (pImpl->
ssl == 0)
return "TLS I/O: failed to get ssl object.";
454 else pImpl->
cOpts = 0;
463 {SSL_set_connect_state( pImpl->
ssl );
466 SSL_set_accept_state( pImpl->
ssl );
467 pImpl->
cAttr = isServer;
476 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
477 BIO_set_nbio( rbio, 1 );
481 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
482 BIO_set_nbio( rbio, 1 );
483 wbio = BIO_new_socket( sfd, BIO_NOCLOSE );
484 pImpl->
cAttr |= wBlocking;
488 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
489 wbio = BIO_new_socket( sfd, BIO_NOCLOSE );
490 BIO_set_nbio( wbio, 1 );
491 pImpl->
cAttr |= rBlocking;
495 rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
496 pImpl->
cAttr |= (rBlocking | wBlocking);
500 return "TLS I/O: invalid TLS rw mode.";
break;
519 if (pImpl->
hsWait && !hsm && pImpl->
cAttr & rBlocking)
520 {
int flags =
fcntl(sfd, F_GETFL, 0);
522 fcntl(sfd, F_SETFL, flags);
523 pImpl->
cAttr |= acc2Block;
530 if (wbio == 0) wbio = rbio;
531 SSL_set_bio( pImpl->
ssl, rbio, wbio );
560 {
DBG_SIO(
"Failing due to previous error, fatal=" << (
int)pImpl->
fatal);
569 do{
int rc = SSL_peek( pImpl->
ssl, buffer, size );
582 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
587 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
592 if ((pImpl->
hsNoBlock && NeedHS()) || !(pImpl->
cAttr & rBlocking))
595 }
while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
615 if (pImpl->
fatal)
return 0;
623 if (!any)
return SSL_pending(pImpl->
ssl);
624 #if OPENSSL_VERSION_NUMBER < 0x10100000L
625 return SSL_pending(pImpl->
ssl) != 0;
627 return SSL_has_pending(pImpl->
ssl);
653 {
DBG_SIO(
"Failing due to previous error, fatal=" << (
int)pImpl->
fatal);
662 do{
int rc = SSL_read( pImpl->
ssl, buffer, size );
669 DBG_SIO(rc <<
" out of " <<size <<
" bytes.");
677 if (ssler == SSL_ERROR_NONE)
679 DBG_SIO(
"0 out of " <<size <<
" bytes.");
685 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
691 if ((pImpl->
hsNoBlock && NeedHS()) || !(pImpl->
cAttr & rBlocking))
696 }
while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
707 if (pImpl) pImpl->
traceID = tid;
723 if (pImpl->
ssl == 0)
return;
736 sdMode = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;
744 sdMode = SSL_RECEIVED_SHUTDOWN;
749 DBG_SOK(
"Doing " <<how <<
" shutdown.");
750 SSL_set_shutdown(pImpl->
ssl, sdMode);
752 for (
int i = 0; i < 4; i++)
753 {rc = SSL_shutdown( pImpl->
ssl );
756 {rc = SSL_get_error( pImpl->
ssl, rc );
757 if (rc == SSL_ERROR_WANT_READ || rc == SSL_ERROR_WANT_WRITE)
758 {
if (Wait4OK(rc == SSL_ERROR_WANT_READ))
continue;
759 rc = SSL_ERROR_SYSCALL;
762 std::string
eMsg = Err2Text(rc);
763 snprintf(msgBuff,
sizeof(msgBuff),
764 "FD %d TLS shutdown failed; %s.\n",pImpl->
sFD,
eMsg.c_str());
773 SSL_free( pImpl->
ssl );
801 {
DBG_SIO(
"Failing due to previous error, fatal=" << (
int)pImpl->
fatal);
810 do{
int rc = SSL_write( pImpl->
ssl, buffer, size );
817 DBG_SIO(rc <<
" out of " <<size <<
" bytes.");
825 if (ssler == SSL_ERROR_NONE)
827 DBG_SIO(rc <<
" out of " <<size <<
" bytes.");
833 if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
839 if ((pImpl->
hsNoBlock && NeedHS()) || !(pImpl->
cAttr & wBlocking))
844 }
while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
865 if (pImpl->
fatal)
return false;
866 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
874 bool XrdTlsSocket::NeedHS()
883 if (pImpl->
fatal)
return false;
884 pImpl->
hsDone = bool( SSL_is_init_finished( pImpl->
ssl ) );
897 return SSL_get_version(pImpl->
ssl);
904 bool XrdTlsSocket::Wait4OK(
bool wantRead)
906 static const short rdOK = POLLIN |POLLRDNORM;
907 static const short wrOK = POLLOUT|POLLWRNORM;
908 struct pollfd polltab = {pImpl->
sFD, (wantRead ? rdOK : wrOK), 0};
913 if (pImpl->
hsDone) timeout = -1;
916 do {rc = poll(&polltab, 1, timeout);}
while(rc < 0 && errno == EINTR);
922 {
if (polltab.revents & (wantRead ? rdOK : wrOK))
return true;
923 if (polltab.revents & POLLERR) errno = EIO;
924 else if (polltab.revents & (POLLHUP|POLLNVAL)) errno = EPIPE;
926 }
else if (!rc) errno = ETIMEDOUT;
int fcntl(int fd, int cmd,...)
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.