XRootD
XrdTlsSocket.cc
Go to the documentation of this file.
1 //------------------------------------------------------------------------------
2 // Copyright (c) 2011-2012 by European Organization for Nuclear Research (CERN)
3 // Author: Michal Simon <simonm@cern.ch>
4 //------------------------------------------------------------------------------
5 // XRootD is free software: you can redistribute it and/or modify
6 // it under the terms of the GNU Lesser General Public License as published by
7 // the Free Software Foundation, either version 3 of the License, or
8 // (at your option) any later version.
9 //
10 // XRootD is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU Lesser General Public License
16 // along with XRootD. If not, see <http://www.gnu.org/licenses/>.
17 //------------------------------------------------------------------------------
18 
19 #include <cstring>
20 #include <cerrno>
21 #include <fcntl.h>
22 #include <iostream>
23 #include <poll.h>
24 #include <cstdio>
25 #include <ctime>
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>
31 
32 #include "XrdNet/XrdNetAddrInfo.hh"
33 #include "XrdSys/XrdSysE2T.hh"
34 #include "XrdSys/XrdSysPthread.hh"
35 #include "XrdTls/XrdTls.hh"
36 #include "XrdTls/XrdTlsContext.hh"
37 #include "XrdTls/XrdTlsNotary.hh"
39 #include "XrdTls/XrdTlsSocket.hh"
40 #include "XrdTls/XrdTlsTrace.hh"
41 
42 #include <stdexcept>
43 
44 /******************************************************************************/
45 /* X r d T l s S o c k e t I m p l */
46 /******************************************************************************/
47 
49 {
50  XrdTlsSocketImpl() : tlsctx(0), ssl(0), traceID(""), sFD(-1), hsWait(15),
51  hsDone(false), fatal(0), isClient(false),
52  cOpts(0), cAttr(0), hsNoBlock(false), isSerial(true) {}
53 
56  SSL *ssl;
57  const char *traceID;
58  int sFD;
59  int hsWait;
60  bool hsDone;
61  char fatal;
62  bool isClient;
63  char cOpts;
64  char cAttr;
65  bool hsNoBlock;
66  bool isSerial;
67 };
68 
69 /******************************************************************************/
70 /* L o c a l C l a s s e s */
71 /******************************************************************************/
72 
73 namespace
74 {
75 class undoImpl
76 {
77 public:
78 
79  undoImpl(XrdTlsSocketImpl *pImpl) : theImpl(pImpl) {}
80  ~undoImpl() {if (theImpl && theImpl->ssl)
81  {SSL_free( theImpl->ssl );
82  theImpl->ssl = 0;
83  }
84  }
85 
86  void KeepImpl() {theImpl = 0;}
87 
88 private:
89 XrdTlsSocketImpl *theImpl;
90 };
91 }
92 
93 /******************************************************************************/
94 /* G l o b a l s */
95 /******************************************************************************/
96 
97 namespace XrdTlsGlobal
98 {
99 extern XrdSysTrace SysTrace;
100 }
101 
102 /******************************************************************************/
103 /* l o c a l s */
104 /******************************************************************************/
105 
106 namespace
107 {
108 static const int noBlock = 0;
109 static const int rwBlock = 'a';
110 static const int xyBlock = 'x';
111 
112 static const int xVerify = 0x01;
113 static const int DNSok = 0x04;
114 
115 static const int isServer = 0x01;
116 static const int rBlocking = 0x02;
117 static const int wBlocking = 0x04;
118 static const int acc2Block = 0x08;
119 }
120 
121 /******************************************************************************/
122 /* C o n s t r u c t o r */
123 /******************************************************************************/
124 
126 {
127 
128 }
129 
130 /******************************************************************************/
131 /* C o n s t r u c t o r */
132 /******************************************************************************/
133 
137  bool isClient, bool serial )
138  : pImpl( new XrdTlsSocketImpl() )
139 {
140 
141 // Simply initialize this object and throw an exception if it fails
142 //
143  const char *eMsg = Init(ctx, sfd, rwm, hsm, isClient, serial);
144  if (eMsg) throw std::invalid_argument( eMsg );
145 }
146 
147 /******************************************************************************/
148 /* D e s t r u c t o r */
149 /******************************************************************************/
150 
152 {
153  if (pImpl->ssl) Shutdown(sdForce);
154  delete pImpl;
155 }
156 
157 /******************************************************************************/
158 /* A c c e p t */
159 /******************************************************************************/
160 
162 {
163  EPNAME("Accept");
164  int rc, ssler;
165  bool wOK, aOK = true;
166 
167 // Make sure there is a context here
168 //
169  if (pImpl->ssl == 0)
170  {AcceptEMsg(eWhy, "TLS socket has no context");
172  }
173  undoImpl ImplTracker(pImpl);
174 
175 // Do some tracing
176 //
177  DBG_SOK("Accepting a TLS connection...");
178 
179 // An accept may require several tries, so we do that here.
180 //
181 do{if ((rc = SSL_accept( pImpl->ssl )) > 0)
182  {if (pImpl->cOpts & xVerify)
183  {X509 *theCert = SSL_get_peer_certificate(pImpl->ssl);
184  if (!theCert)
185  {AcceptEMsg(eWhy, "x509 certificate is missing");
187  }
188  X509_free(theCert);
189  rc = SSL_get_verify_result(pImpl->ssl);
190  if (rc != X509_V_OK)
191  {AcceptEMsg(eWhy, "x509 certificate verification failed");
192  return XrdTls::TLS_VER_Error;
193  }
194  }
195  ImplTracker.KeepImpl();
196 
197 // Reset the socket to blocking mode if we need to. Note that we have to brute
198 // force this on the socket as setting a BIO after accept has no effect. We
199 // also tell ssl that we want to block on a handshake from now on.
200 //
201  if (pImpl->cAttr & acc2Block)
202 // BIO_set_nbio(SSL_get_rbio(pImpl->ssl), 0); *Does not work after accept*
203  {int eNO = errno;
204  int flags = fcntl(pImpl->sFD, F_GETFL, 0);
205  flags &= ~O_NONBLOCK;
206  fcntl(pImpl->sFD, F_SETFL, flags);
207  SSL_set_mode(pImpl->ssl, SSL_MODE_AUTO_RETRY);
208  errno = eNO;
209  }
210  return XrdTls::TLS_AOK;
211  }
212 
213  // Get the actual SSL error code.
214  //
215  ssler = Diagnose("TLS_Accept", rc, XrdTls::dbgSOK);
216 
217  // Check why we did not succeed. We may be able to recover.
218  //
219  if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE) {
220  if(ssler == SSL_ERROR_SSL){
221  //In the case the accept does have an error related to OpenSSL,
222  //shutdown the TLSSocket in case the link associated to that connection
223  //is re-used
224  Shutdown();
225  }
226  aOK = false; break;
227  }
228 
229  if (pImpl->hsNoBlock) return XrdTls::ssl2RC(ssler);
230 
231  } while((wOK = Wait4OK(ssler == SSL_ERROR_WANT_READ)));
232 
233 // If we are here then we got an error
234 //
235  AcceptEMsg(eWhy, (!aOK ? Err2Text(ssler).c_str() : XrdSysE2T(errno)));
236  errno = ECONNABORTED;
237  return XrdTls::TLS_SYS_Error;
238 }
239 
240 /******************************************************************************/
241 /* Private: A c c e p t E M s g */
242 /******************************************************************************/
243 
244 void XrdTlsSocket::AcceptEMsg(std::string *eWhy, const char *reason)
245 {
246  if (eWhy)
247  {*eWhy = "TLS connection from ";
248  *eWhy += pImpl->traceID;
249  *eWhy += " failed; ";
250  *eWhy += reason;
251  }
252 }
253 
254 /******************************************************************************/
255 /* C o n n e c t */
256 /******************************************************************************/
257 
258 XrdTls::RC XrdTlsSocket::Connect(const char *thehost, std::string *eWhy)
259 {
260  EPNAME("Connect");
261  int ssler, rc;
262  bool wOK = true, aOK = true;
263 
264 // Setup host verification of a host has been specified. This is a to-do
265 // when we move to new versions of SSL. For now, we use the notary object.
266 //
267 
268 // Do some tracing
269 //
270  DBG_SOK("Connecting to " <<(thehost ? thehost : "unverified host")
271  <<(thehost && pImpl->cOpts & DNSok ? " dnsok" : "" ));
272 
273 // Do the connect.
274 //
275 do{int rc = SSL_connect( pImpl->ssl );
276  if (rc == 1) break;
277 
278  ssler = Diagnose("TLS_Connect", rc, XrdTls::dbgSOK);
279 
280  if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
281  {aOK = false; break;}
282 
283  if (pImpl->hsNoBlock) return XrdTls::ssl2RC(ssler);
284 
285  } while((wOK = Wait4OK(ssler == SSL_ERROR_WANT_READ)));
286 
287 // Check if everything went well. Note that we need to save the errno as
288 // we may be calling external methods that may generate other errors. We
289 //
290  if (!aOK || !wOK)
291  {rc = errno;
292  DBG_SOK("Handshake failed; "<<(!aOK ? Err2Text(ssler) : XrdSysE2T(rc)));
293  if (eWhy)
294  {const char *hName = (thehost ? thehost : "host");
295  *eWhy = "Unable to connect to ";
296  *eWhy += hName;
297  *eWhy += "; ";
298  if (!aOK) *eWhy += Err2Text(ssler);
299  else *eWhy += XrdSysE2T(rc);
300  }
301  if (!aOK) return XrdTls::ssl2RC(ssler);
302  errno = rc;
303  return XrdTls::TLS_SYS_Error;
304  }
305 
306 // Set the hsDone flag!
307 //
308  pImpl->hsDone = bool( SSL_is_init_finished( pImpl->ssl ) );
309 
310 // Validate the host name if so desired. Note that cert verification is
311 // checked by the notary since hostname validation requires it. We currently
312 // do not support dnsOK but doing so just means we need to check the option
313 // and if on, also pass a XrdNetAddrInfo object generated from the hostname.
314 //
315  if (thehost)
316  {const char *eTxt = XrdTlsNotary::Validate(pImpl->ssl, thehost, 0);
317  if (eTxt)
318  {DBG_SOK(thehost << " verification failed; " <<eTxt);
319  if (eWhy)
320  {
321  *eWhy = "Unable to validate "; *eWhy += thehost;
322  *eWhy += "; "; *eWhy += eTxt;
323  }
324  return XrdTls::TLS_HNV_Error;
325  }
326  }
327 
328  DBG_SOK("Connect completed without error.");
329  return XrdTls::TLS_AOK;
330 }
331 
332 /******************************************************************************/
333 /* C o n t e x t */
334 /******************************************************************************/
335 
337 {
338  return pImpl->tlsctx;
339 }
340 
341 /******************************************************************************/
342 /* Private: D i a g n o s e */
343 /******************************************************************************/
344 
345 int XrdTlsSocket::Diagnose(const char *what, int sslrc, int tcode)
346 {
347  int eCode = SSL_get_error( pImpl->ssl, sslrc );
348 
349 // We need to dispose of the error queue otherwise the next operation will
350 // fail. We do this by either printing them or flushing them down the drain.
351 // We avoid the tracing hangups indicated by SSL_ERROR_SYSCALL w/ errno == 0.
352 //
353  if (TRACING(tcode)
354  || (eCode != SSL_ERROR_WANT_READ && eCode != SSL_ERROR_WANT_WRITE))
355  {int eNO = errno;
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.",
360  sslrc, eCode, XrdTls::ssl2Text(eCode), eNO);
361  XrdTls::Emsg(pImpl->traceID, eBuff, true);
362  errno = eNO;
363  }
364  } else ERR_clear_error();
365 
366 // Make sure we can shutdown
367 //
368  if (eCode == SSL_ERROR_SYSCALL)
369  pImpl->fatal = (char)XrdTls::TLS_SYS_Error;
370  else if (eCode == SSL_ERROR_SSL)
371  pImpl->fatal = (char)XrdTls::TLS_SSL_Error;
372 
373 // Return the errors
374 //
375  return eCode;
376 }
377 
378 /******************************************************************************/
379 /* Private: E r r 2 T e x t */
380 /******************************************************************************/
381 
382 std::string XrdTlsSocket::Err2Text(int sslerr)
383 {
384  const char *eP;
385  char eBuff[256];
386 
387  if (sslerr == SSL_ERROR_SYSCALL)
388  {int rc = errno;
389  if (!rc) rc = EPIPE;
390  snprintf(eBuff, sizeof(eBuff), "%s", XrdSysE2T(rc));
391  *eBuff = tolower(*eBuff);
392  eP = eBuff;
393  } else eP = XrdTls::ssl2Text(sslerr,0);
394 
395  return std::string(eP);
396 }
397 
398 /******************************************************************************/
399 /* g e t C e r t s */
400 /******************************************************************************/
401 
403 {
404  XrdSysMutexHelper mHelper;
405 
406 // Serialize call if need be
407 //
408  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
409 
410 // If verified certs need to be returned, make sure the certs are verified
411 //
412  if (ver && SSL_get_verify_result(pImpl->ssl) != X509_V_OK) return 0;
413 
414 // Get the certs and return
415 //
416  X509 *pcert = SSL_get_peer_certificate(pImpl->ssl);
417  if (pcert == 0) return 0;
418  return new XrdTlsPeerCerts(pcert, SSL_get_peer_cert_chain(pImpl->ssl));
419 }
420 
421 /******************************************************************************/
422 /* I n i t */
423 /******************************************************************************/
424 
425 const char *XrdTlsSocket::Init( XrdTlsContext &ctx, int sfd,
428  bool isClient, bool serial,
429  const char *tid )
430 {
431  BIO *rbio, *wbio = 0;
432 
433 // Make sure this connection is not in use if this is a client. Servers are
434 // allowed to throw away the previous setup as they reuse sockets.
435 //
436  if ( pImpl->ssl )
437  {if (isClient) return "TLS I/O: connection is still in use.";
438  else {SSL_free( pImpl->ssl );
439  pImpl->ssl = 0;
440  }
441  }
442 
443 // Obtain the ssl object at this point.
444 //
445  pImpl->ssl = static_cast<SSL *>(ctx.Session());
446  if (pImpl->ssl == 0) return "TLS I/O: failed to get ssl object.";
447 
448 // Initialze values from the context.
449 //
450  pImpl->tlsctx = &ctx;
451  const XrdTlsContext::CTX_Params *parms = ctx.GetParams();
452  pImpl->hsWait = (parms->opts & XrdTlsContext::hsto) * 1000; // Poll timeout
453  if (ctx.x509Verify()) pImpl->cOpts = xVerify;
454  else pImpl->cOpts = 0;
455  if (parms->opts & XrdTlsContext::dnsok) pImpl->cOpts |= DNSok;
456  pImpl->traceID = tid;
457  pImpl->isClient= isClient;
458  pImpl->isSerial= serial;
459 
460 // Set the ssl object state to correspond to client or server type
461 //
462  if (isClient)
463  {SSL_set_connect_state( pImpl->ssl );
464  pImpl->cAttr = 0;
465  } else {
466  SSL_set_accept_state( pImpl->ssl );
467  pImpl->cAttr = isServer;
468  }
469 
470 // Allocate right number of bio's and initialize them as requested. Note
471 // that when the read and write bios have the same attribue, we use only one.
472 //
473  switch( rwm )
474  {
475  case TLS_RNB_WNB:
476  rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
477  BIO_set_nbio( rbio, 1 );
478  break;
479 
480  case TLS_RNB_WBL:
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;
485  break;
486 
487  case TLS_RBL_WNB:
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;
492  break;
493 
494  case TLS_RBL_WBL:
495  rbio = BIO_new_socket( sfd, BIO_NOCLOSE );
496  pImpl->cAttr |= (rBlocking | wBlocking);
497  break;
498 
499  default:
500  return "TLS I/O: invalid TLS rw mode."; break;
501  }
502 
503 // Set correct handshake mode
504 //
505  if (hsm) pImpl->hsNoBlock = false;
506  else pImpl->hsNoBlock = true;
507 
508 // Reset the handshake and fatal error indicators
509 //
510  pImpl->hsDone = false;
511  pImpl->fatal = 0;
512 
513 // The glories of OpenSSL require that we do some fancy footwork with the
514 // handshake timeout. If there is one and this is a server and the server
515 // wants blocking reads, we initially set the socket as non-blocking as the
516 // bio's can handle it. Then after the accept we set it back to blocking mode.
517 // Note: doing this via the bio causes the socket to remain nonblocking. yech!
518 //
519  if (pImpl->hsWait && !hsm && pImpl->cAttr & rBlocking)
520  {int flags = fcntl(sfd, F_GETFL, 0);
521  flags |= O_NONBLOCK;
522  fcntl(sfd, F_SETFL, flags);
523  pImpl->cAttr |= acc2Block;
524  }
525 
526 // Finally attach the bios to the ssl object. When the ssl object is freed
527 // the bios will be freed as well.
528 //
529  pImpl->sFD = sfd;
530  if (wbio == 0) wbio = rbio;
531  SSL_set_bio( pImpl->ssl, rbio, wbio );
532 
533 // All done. The caller will do an Accept() or Connect() afterwards.
534 //
535  return 0;
536 }
537 
538 /******************************************************************************/
539 /* P e e k */
540 /******************************************************************************/
541 
542 XrdTls::RC XrdTlsSocket::Peek( char *buffer, size_t size, int &bytesPeek )
543  {
544  EPNAME("Peek");
545  XrdSysMutexHelper mHelper;
546  int ssler;
547 
548  //------------------------------------------------------------------------
549  // Serialize call if need be
550  //------------------------------------------------------------------------
551 
552  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
553 
554  //------------------------------------------------------------------------
555  // Return an error if this socket received a fatal error as OpenSSL will
556  // SEGV when called after such an error.
557  //------------------------------------------------------------------------
558 
559  if (pImpl->fatal)
560  {DBG_SIO("Failing due to previous error, fatal=" << (int)pImpl->fatal);
561  return (XrdTls::RC)pImpl->fatal;
562  }
563 
564  //------------------------------------------------------------------------
565  // If necessary, SSL_read() will negotiate a TLS/SSL session, so we don't
566  // have to explicitly call SSL_connect or SSL_do_handshake.
567  //------------------------------------------------------------------------
568 
569  do{int rc = SSL_peek( pImpl->ssl, buffer, size );
570 
571  // Note that according to SSL whenever rc > 0 then SSL_ERROR_NONE can be
572  // returned to the caller. So, we short-circuit all the error handling.
573  //
574  if( rc > 0 )
575  {bytesPeek = rc;
576  return XrdTls::TLS_AOK;
577  }
578 
579  // We have a potential error. Get the SSL error code and whether or
580  // not the handshake actually is finished (semi-accurate)
581  //
582  pImpl->hsDone = bool( SSL_is_init_finished( pImpl->ssl ) );
583  ssler = Diagnose("TLS_Peek", rc, XrdTls::dbgSIO);
584 
585  // If the error isn't due to blocking issues, we are done.
586  //
587  if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
588  return XrdTls::ssl2RC(ssler);
589 
590  // If the caller is non-blocking, the return the issue. Otherwise, block.
591  //
592  if ((pImpl->hsNoBlock && NeedHS()) || !(pImpl->cAttr & rBlocking))
593  return XrdTls::ssl2RC(ssler);
594 
595  } while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
596 
597  // Return failure as the Wait failed.
598  //
599  return XrdTls::TLS_SYS_Error;
600  }
601 
602 /******************************************************************************/
603 /* P e n d i n g */
604 /******************************************************************************/
605 
607 {
608  XrdSysMutexHelper mHelper;
609 
610  //------------------------------------------------------------------------
611  // Return an error if this socket received a fatal error as OpenSSL will
612  // SEGV when called after such an error. So, return something reasonable.
613  //------------------------------------------------------------------------
614 
615  if (pImpl->fatal) return 0;
616 
617  //------------------------------------------------------------------------
618  // Serialize call if need be
619  //------------------------------------------------------------------------
620 
621  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
622 
623  if (!any) return SSL_pending(pImpl->ssl);
624 #if OPENSSL_VERSION_NUMBER < 0x10100000L
625  return SSL_pending(pImpl->ssl) != 0;
626 #else
627  return SSL_has_pending(pImpl->ssl);
628 #endif
629 }
630 
631 /******************************************************************************/
632 /* R e a d */
633 /******************************************************************************/
634 
635 XrdTls::RC XrdTlsSocket::Read( char *buffer, size_t size, int &bytesRead )
636 {
637  EPNAME("Read");
638  XrdSysMutexHelper mHelper;
639  int ssler;
640 
641  //------------------------------------------------------------------------
642  // Serialize call if need be
643  //------------------------------------------------------------------------
644 
645  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
646 
647  //------------------------------------------------------------------------
648  // Return an error if this socket received a fatal error as OpenSSL will
649  // SEGV when called after such an error.
650  //------------------------------------------------------------------------
651 
652  if (pImpl->fatal)
653  {DBG_SIO("Failing due to previous error, fatal=" << (int)pImpl->fatal);
654  return (XrdTls::RC)pImpl->fatal;
655  }
656 
657  //------------------------------------------------------------------------
658  // If necessary, SSL_read() will negotiate a TLS/SSL session, so we don't
659  // have to explicitly call SSL_connect or SSL_do_handshake.
660  //------------------------------------------------------------------------
661 
662  do{int rc = SSL_read( pImpl->ssl, buffer, size );
663 
664  // Note that according to SSL whenever rc > 0 then SSL_ERROR_NONE can be
665  // returned to the caller. So, we short-circuit all the error handling.
666  //
667  if( rc > 0 )
668  {bytesRead = rc;
669  DBG_SIO(rc <<" out of " <<size <<" bytes.");
670  return XrdTls::TLS_AOK;
671  }
672 
673  // We have a potential error. Get the SSL error code and whether or
674  // not the handshake actually is finished (semi-accurate)
675  //
676  ssler = Diagnose("TLS_Read", rc, XrdTls::dbgSIO);
677  if (ssler == SSL_ERROR_NONE)
678  {bytesRead = 0;
679  DBG_SIO("0 out of " <<size <<" bytes.");
680  return XrdTls::TLS_AOK;
681  }
682 
683  // If the error isn't due to blocking issues, we are done.
684  //
685  if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
686  return XrdTls::ssl2RC(ssler);
687 
688  // If the caller is non-blocking for reads, return the issue. Otherwise,
689  // block for the caller.
690  //
691  if ((pImpl->hsNoBlock && NeedHS()) || !(pImpl->cAttr & rBlocking))
692  return XrdTls::ssl2RC(ssler);
693 
694  // Wait until we can read again.
695 
696  } while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
697 
698  return XrdTls::TLS_SYS_Error;
699  }
700 
701 /******************************************************************************/
702 /* S e t T r a c e I D */
703 /******************************************************************************/
704 
705 void XrdTlsSocket::SetTraceID(const char *tid)
706 {
707  if (pImpl) pImpl->traceID = tid;
708 }
709 
710 /******************************************************************************/
711 /* S h u t d o w n */
712 /******************************************************************************/
713 
715 {
716  EPNAME("Shutdown");
717  XrdSysMutexHelper mHelper;
718  const char *how;
719  int sdMode, rc;
720 
721 // Make sure we have an ssl object.
722 //
723  if (pImpl->ssl == 0) return;
724 
725 // While we do not need to technically serialize here, we're being conservative
726 //
727  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
728 
729 // Perform shutdown as needed. This is required before freeing the ssl object.
730 // If we previously encountered a SYSCALL or SSL error, shutdown is prohibited!
731 // The following code is patterned after code in the public TomCat server.
732 //
733  if (!pImpl->fatal)
734  {switch(sdType)
735  {case sdForce: // Forced shutdown which violate TLS standard!
736  sdMode = SSL_SENT_SHUTDOWN|SSL_RECEIVED_SHUTDOWN;
737  how = "forced";
738  break;
739  case sdWait: // Wait for client acknowledgement
740  sdMode = 0;
741  how = "clean";
742  break;
743  default: // Fast shutdown, don't wait for ack (compliant)
744  sdMode = SSL_RECEIVED_SHUTDOWN;
745  how = "fast";
746  break;
747  }
748 
749  DBG_SOK("Doing " <<how <<" shutdown.");
750  SSL_set_shutdown(pImpl->ssl, sdMode);
751 
752  for (int i = 0; i < 4; i++)
753  {rc = SSL_shutdown( pImpl->ssl );
754  if (rc > 0) break;
755  if (rc < 0)
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;
760  }
761  char msgBuff[512];
762  std::string eMsg = Err2Text(rc);
763  snprintf(msgBuff, sizeof(msgBuff),
764  "FD %d TLS shutdown failed; %s.\n",pImpl->sFD,eMsg.c_str());
765  XrdTls::Emsg(pImpl->traceID, msgBuff, true);
766  break;
767  }
768  }
769  }
770 
771 // Now free the ssl object which will free all the BIO's associated with it
772 //
773  SSL_free( pImpl->ssl );
774  pImpl->ssl = 0;
775  pImpl->fatal = 0;
776 }
777 
778 /******************************************************************************/
779 /* W r i t e */
780 /******************************************************************************/
781 
782 XrdTls::RC XrdTlsSocket::Write( const char *buffer, size_t size,
783  int &bytesWritten )
784 {
785  EPNAME("Write");
786  XrdSysMutexHelper mHelper;
787  int ssler;
788 
789  //------------------------------------------------------------------------
790  // Serialize call if need be
791  //------------------------------------------------------------------------
792 
793  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
794 
795  //------------------------------------------------------------------------
796  // Return an error if this socket received a fatal error as OpenSSL will
797  // SEGV when called after such an error.
798  //------------------------------------------------------------------------
799 
800  if (pImpl->fatal)
801  {DBG_SIO("Failing due to previous error, fatal=" << (int)pImpl->fatal);
802  return (XrdTls::RC)pImpl->fatal;
803  }
804 
805  //------------------------------------------------------------------------
806  // If necessary, SSL_write() will negotiate a TLS/SSL session, so we don't
807  // have to explicitly call SSL_connect or SSL_do_handshake.
808  //------------------------------------------------------------------------
809 
810  do{int rc = SSL_write( pImpl->ssl, buffer, size );
811 
812  // Note that according to SSL whenever rc > 0 then SSL_ERROR_NONE can be
813  // returned to the caller. So, we short-circuit all the error handling.
814  //
815  if (rc > 0)
816  {bytesWritten = rc;
817  DBG_SIO(rc <<" out of " <<size <<" bytes.");
818  return XrdTls::TLS_AOK;
819  }
820 
821  // We have a potential error. Get the SSL error code and whether or
822  // not the handshake actually is finished (semi-accurate)
823  //
824  ssler = Diagnose("TLS_Write", rc, XrdTls::dbgSIO);
825  if (ssler == SSL_ERROR_NONE)
826  {bytesWritten = 0;
827  DBG_SIO(rc <<" out of " <<size <<" bytes.");
828  return XrdTls::TLS_AOK;
829  }
830 
831  // If the error isn't due to blocking issues, we are done.
832  //
833  if (ssler != SSL_ERROR_WANT_READ && ssler != SSL_ERROR_WANT_WRITE)
834  return XrdTls::ssl2RC(ssler);
835 
836  // If the caller is non-blocking for reads, return the issue. Otherwise,
837  // block for the caller.
838  //
839  if ((pImpl->hsNoBlock && NeedHS()) || !(pImpl->cAttr & wBlocking))
840  return XrdTls::ssl2RC(ssler);
841 
842  // Wait unil the write can get restarted
843 
844  } while(Wait4OK(ssler == SSL_ERROR_WANT_READ));
845 
846  return XrdTls::TLS_SYS_Error;
847 }
848 
849 /******************************************************************************/
850 /* N e e d H a n d S h a k e */
851 /******************************************************************************/
852 
854  {
855  XrdSysMutexHelper mHelper;
856 
857  //------------------------------------------------------------------------
858  // Return an error if this socket received a fatal error as OpenSSL will
859  // SEGV when called after such an error. So, return something reasonable.
860  // Technically, we don't need to serialize this because nothing get
861  // modified. We do so anyway out of abundance of caution.
862  //------------------------------------------------------------------------
863 
864  if (pImpl->isSerial) mHelper.Lock(&(pImpl->sslMutex));
865  if (pImpl->fatal) return false;
866  pImpl->hsDone = bool( SSL_is_init_finished( pImpl->ssl ) );
867  return !pImpl->hsDone;
868  }
869 
870 /******************************************************************************/
871 /* Private: N e e d H S */
872 /******************************************************************************/
873 
874  bool XrdTlsSocket::NeedHS()
875  {
876  //------------------------------------------------------------------------
877  // The following code is identical to NeedHandshake() except that it does
878  // serialize the call because the caller already has done so. While we
879  // could use a recursive mutex the overhead in doing so is not worth it
880  // and it is only used for internal purposes.
881  //------------------------------------------------------------------------
882 
883  if (pImpl->fatal) return false;
884  pImpl->hsDone = bool( SSL_is_init_finished( pImpl->ssl ) );
885  return !pImpl->hsDone;
886  }
887 
888 /******************************************************************************/
889 /* V e r s i o n */
890 /******************************************************************************/
891 
892  const char *XrdTlsSocket::Version()
893  {
894  // This call modifies nothing nor does it depend on modified data once the
895  // connection is esablished and doesn't need serialization.
896  //
897  return SSL_get_version(pImpl->ssl);
898  }
899 
900 /******************************************************************************/
901 /* Private: W a i t 4 O K */
902 /******************************************************************************/
903 
904 bool XrdTlsSocket::Wait4OK(bool wantRead)
905 {
906  static const short rdOK = POLLIN |POLLRDNORM;
907  static const short wrOK = POLLOUT|POLLWRNORM;
908  struct pollfd polltab = {pImpl->sFD, (wantRead ? rdOK : wrOK), 0};
909  int rc, timeout;
910 
911  // Establish how long we will wait. This depends on hsDone being current!
912  //
913  if (pImpl->hsDone) timeout = -1;
914  else timeout = (pImpl->hsWait ? pImpl->hsWait : -1);
915 
916  do {rc = poll(&polltab, 1, timeout);} while(rc < 0 && errno == EINTR);
917 
918  // Make sure we have a clean state, otherwise indicate we failed. The
919  // caller will need to perform the correct action.
920  //
921  if (rc == 1)
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;
925  else errno = EINVAL;
926  } else if (!rc) errno = ETIMEDOUT; // This is not possible
927  return false;
928 }
#define EPNAME(x)
Definition: XrdBwmTrace.hh:56
int fcntl(int fd, int cmd,...)
#define eMsg(x)
const char * XrdSysE2T(int errcode)
Definition: XrdSysE2T.cc:104
if(Avsz)
#define DBG_SOK(y)
Definition: XrdTlsTrace.hh:43
#define DBG_SIO(y)
Definition: XrdTlsTrace.hh:47
#define TRACING(x)
Definition: XrdTrace.hh:70
void Lock(XrdSysMutex *Mutex)
static const uint64_t hsto
Mask to isolate the hsto.
void * Session()
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)
Definition: XrdTlsNotary.cc:56
XrdTlsContext * Context()
XrdTls::RC Accept(std::string *eMsg=0)
void Shutdown(SDType=sdImmed)
~XrdTlsSocket()
Destructor.
@ TLS_RNB_WBL
Non-blocking read blocking write.
Definition: XrdTlsSocket.hh:46
@ TLS_RBL_WNB
blocking read non-blocking write
Definition: XrdTlsSocket.hh:47
@ TLS_RBL_WBL
blocking read blocking write
Definition: XrdTlsSocket.hh:48
@ TLS_RNB_WNB
Non-blocking read non-blocking write.
Definition: XrdTlsSocket.hh:45
bool NeedHandShake()
XrdTls::RC Write(const char *buffer, size_t size, int &bytesOut)
const char * Version()
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)
Definition: XrdTls.cc:205
static const int dbgSIO
Turn debugging in for socket I/O.
Definition: XrdTls.hh:102
static const int dbgSOK
Turn debugging in for socket operations.
Definition: XrdTls.hh:101
static void Emsg(const char *tid, const char *msg=0, bool flush=true)
Definition: XrdTls.cc:104
static const char * ssl2Text(int sslrc, const char *dflt="unknown_error")
Definition: XrdTls.cc:235
@ TLS_AOK
All went well, will always be zero.
Definition: XrdTls.hh:40
@ TLS_HNV_Error
A hostname validation error occuured.
Definition: XrdTls.hh:44
@ TLS_VER_Error
Certificate verification failed.
Definition: XrdTls.hh:48
@ TLS_CRT_Missing
The x509 certificate missing.
Definition: XrdTls.hh:42
@ TLS_SYS_Error
A system call error occurred.
Definition: XrdTls.hh:46
@ TLS_SSL_Error
An SSL error occurred.
Definition: XrdTls.hh:45
@ TLS_CTX_Missing
The TLS context is missing.
Definition: XrdTls.hh:43
XrdSysTrace SysTrace("TLS", 0)
uint64_t opts
Options as passed to the constructor.
char cOpts
Connection options.
Definition: XrdTlsSocket.cc:63
XrdSysMutex sslMutex
Mutex to serialize calls.
Definition: XrdTlsSocket.cc:54
bool isClient
True if for client use.
Definition: XrdTlsSocket.cc:62
bool hsDone
True if the handshake has completed.
Definition: XrdTlsSocket.cc:60
char fatal
!0 if fatal error prevents shutdown call
Definition: XrdTlsSocket.cc:61
bool hsNoBlock
Handshake handling nonblocking if true.
Definition: XrdTlsSocket.cc:65
int sFD
Associated file descriptor (never closed)
Definition: XrdTlsSocket.cc:58
char cAttr
Connection attributes.
Definition: XrdTlsSocket.cc:64
bool isSerial
True if calls must be serialized.
Definition: XrdTlsSocket.cc:66
XrdTlsContext * tlsctx
Associated context object.
Definition: XrdTlsSocket.cc:55
const char * traceID
Trace identifier.
Definition: XrdTlsSocket.cc:57
SSL * ssl
Associated SSL object.
Definition: XrdTlsSocket.cc:56
int hsWait
Maximum amount of time to wait for handshake.
Definition: XrdTlsSocket.cc:59