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