001    /*
002     * CDDL HEADER START
003     *
004     * The contents of this file are subject to the terms of the
005     * Common Development and Distribution License, Version 1.0 only
006     * (the "License").  You may not use this file except in compliance
007     * with the License.
008     *
009     * You can obtain a copy of the license at
010     * trunk/opends/resource/legal-notices/OpenDS.LICENSE
011     * or https://OpenDS.dev.java.net/OpenDS.LICENSE.
012     * See the License for the specific language governing permissions
013     * and limitations under the License.
014     *
015     * When distributing Covered Code, include this CDDL HEADER in each
016     * file and include the License file at
017     * trunk/opends/resource/legal-notices/OpenDS.LICENSE.  If applicable,
018     * add the following below this CDDL HEADER, with the fields enclosed
019     * by brackets "[]" replaced with your own identifying information:
020     *      Portions Copyright [yyyy] [name of copyright owner]
021     *
022     * CDDL HEADER END
023     *
024     *
025     *      Copyright 2006-2008 Sun Microsystems, Inc.
026     */
027    package org.opends.server.extensions;
028    
029    
030    
031    import java.io.IOException;
032    import java.net.InetAddress;
033    import java.net.Socket;
034    import java.nio.ByteBuffer;
035    import java.nio.channels.SocketChannel;
036    import java.security.cert.Certificate;
037    import javax.net.ssl.SSLContext;
038    import javax.net.ssl.SSLEngine;
039    import javax.net.ssl.SSLEngineResult;
040    import javax.net.ssl.SSLSession;
041    
042    import org.opends.messages.Message;
043    import org.opends.server.api.ClientConnection;
044    import org.opends.server.api.ConnectionSecurityProvider;
045    import org.opends.server.api.KeyManagerProvider;
046    import org.opends.server.api.TrustManagerProvider;
047    import org.opends.server.config.ConfigEntry;
048    import org.opends.server.config.ConfigException;
049    import org.opends.server.core.DirectoryServer;
050    import org.opends.server.loggers.debug.DebugTracer;
051    import org.opends.server.types.DebugLogLevel;
052    import org.opends.server.types.DirectoryException;
053    import org.opends.server.types.DisconnectReason;
054    import org.opends.server.types.InitializationException;
055    import org.opends.server.types.SSLClientAuthPolicy;
056    import org.opends.server.util.SelectableCertificateKeyManager;
057    
058    import static org.opends.messages.ExtensionMessages.*;
059    import static org.opends.server.loggers.debug.DebugLogger.*;
060    import static org.opends.server.util.StaticUtils.*;
061    
062    
063    
064    /**
065     * This class provides an implementation of a connection security provider that
066     * uses SSL/TLS to encrypt the communication to and from the client.  It uses
067     * the {@code javax.net.ssl.SSLEngine} class to provide the actual SSL
068     * communication layer, and the Directory Server key and trust store providers
069     * to determine which key and trust stores to use.
070     */
071    public class TLSConnectionSecurityProvider
072           extends ConnectionSecurityProvider
073    {
074      /**
075       * The tracer object for the debug logger.
076       */
077      private static final DebugTracer TRACER = getTracer();
078    
079    
080    
081      /**
082       * The SSL context name that should be used for this TLS connection security
083       * provider.
084       */
085      private static final String SSL_CONTEXT_INSTANCE_NAME = "TLS";
086    
087    
088    
089      // The buffer that will be used when reading clear-text data.
090      private ByteBuffer clearInBuffer;
091    
092      // The buffer that will be used when writing clear-text data.
093      private ByteBuffer clearOutBuffer;
094    
095      // The buffer that will be used when reading encrypted data.
096      private ByteBuffer sslInBuffer;
097    
098      // The buffer that willa be used when writing encrypted data.
099      private ByteBuffer sslOutBuffer;
100    
101      // The client connection with which this security provider is associated.
102      private ClientConnection clientConnection;
103    
104      // The size in bytes that should be used for the buffer holding clear-text
105      // data.
106      private int clearBufferSize;
107    
108      // The size in bytes that should be used for the buffer holding the encrypted
109      // data.
110      private int sslBufferSize;
111    
112      // The socket channel that may be used to communicate with the client.
113      private SocketChannel socketChannel;
114    
115      // The SSL client certificate policy.
116      private SSLClientAuthPolicy sslClientAuthPolicy;
117    
118      // The SSL context that will be used for all SSL/TLS communication.
119      private SSLContext sslContext;
120    
121      // The SSL engine that will be used for this connection.
122      private SSLEngine sslEngine;
123    
124      // The set of cipher suites to allow.
125      private String[] enabledCipherSuites;
126    
127      // The set of protocols to allow.
128      private String[] enabledProtocols;
129    
130    
131    
132      /**
133       * Creates a new instance of this connection security provider.  Note that
134       * no initialization should be done here, since it should all be done in the
135       * {@code initializeConnectionSecurityProvider} method.  Also note that this
136       * instance should only be used to create new instances that are associated
137       * with specific client connections.  This instance itself should not be used
138       * to attempt secure communication with the client.
139       */
140      public TLSConnectionSecurityProvider()
141      {
142        super();
143    
144      }
145    
146    
147    
148      /**
149       * Creates a new instance of this connection security provider that will be
150       * associated with the provided client connection.
151       *
152       * @param  clientConnection  The client connection with which this connection
153       *                           security provider should be associated.
154       * @param  socketChannel     The socket channel that may be used to
155       *                           communicate with the client.
156       * @param  parentProvider    A reference to the parent TLS connection security
157       *                           provider that is being used to create this
158       *                           instance.
159       */
160      private TLSConnectionSecurityProvider(ClientConnection clientConnection,
161                                            SocketChannel socketChannel,
162                                            TLSConnectionSecurityProvider
163                                                 parentProvider)
164              throws DirectoryException
165      {
166        super();
167    
168    
169        this.clientConnection = clientConnection;
170        this.socketChannel    = socketChannel;
171    
172        Socket socket = socketChannel.socket();
173        InetAddress inetAddress = socketChannel.socket().getInetAddress();
174    
175    
176        // Create an SSL session based on the configured key and trust stores in the
177        // Directory Server.
178        KeyManagerProvider keyManagerProvider =
179             DirectoryServer.getKeyManagerProvider(
180                  clientConnection.getKeyManagerProviderDN());
181        if (keyManagerProvider == null)
182        {
183          keyManagerProvider = new NullKeyManagerProvider();
184        }
185    
186        TrustManagerProvider trustManagerProvider =
187             DirectoryServer.getTrustManagerProvider(
188                  clientConnection.getTrustManagerProviderDN());
189        if (trustManagerProvider == null)
190        {
191          trustManagerProvider = new NullTrustManagerProvider();
192        }
193    
194        try
195        {
196          // FIXME -- Is it bad to create a new SSLContext for each connection?
197          sslContext = SSLContext.getInstance(SSL_CONTEXT_INSTANCE_NAME);
198    
199          String alias = clientConnection.getCertificateAlias();
200          if (alias == null)
201          {
202            sslContext.init(keyManagerProvider.getKeyManagers(),
203                            trustManagerProvider.getTrustManagers(), null);
204          }
205          else
206          {
207            sslContext.init(SelectableCertificateKeyManager.wrap(
208                                 keyManagerProvider.getKeyManagers(), alias),
209                            trustManagerProvider.getTrustManagers(), null);
210          }
211        }
212        catch (Exception e)
213        {
214          if (debugEnabled())
215          {
216            TRACER.debugCaught(DebugLogLevel.ERROR, e);
217          }
218    
219          Message message = ERR_TLS_SECURITY_PROVIDER_CANNOT_INITIALIZE.get(
220              getExceptionMessage(e));
221          throw new DirectoryException(DirectoryServer.getServerErrorResultCode(),
222                                       message, e);
223        }
224    
225        sslEngine = sslContext.createSSLEngine(inetAddress.getHostName(),
226                                               socket.getPort());
227        sslEngine.setUseClientMode(false);
228    
229        enabledProtocols = parentProvider.enabledProtocols;
230        if (enabledProtocols != null)
231        {
232          sslEngine.setEnabledProtocols(enabledProtocols);
233        }
234    
235        enabledCipherSuites = parentProvider.enabledCipherSuites;
236        if (enabledCipherSuites != null)
237        {
238          sslEngine.setEnabledCipherSuites(enabledCipherSuites);
239        }
240    
241        sslClientAuthPolicy = parentProvider.sslClientAuthPolicy;
242        if (sslClientAuthPolicy == null)
243        {
244          sslClientAuthPolicy = SSLClientAuthPolicy.OPTIONAL;
245        }
246        switch (sslClientAuthPolicy)
247        {
248          case REQUIRED:
249            sslEngine.setWantClientAuth(true);
250            sslEngine.setNeedClientAuth(true);
251            break;
252    
253          case DISABLED:
254            sslEngine.setNeedClientAuth(false);
255            sslEngine.setWantClientAuth(false);
256            break;
257    
258          case OPTIONAL:
259          default:
260            sslEngine.setNeedClientAuth(false);
261            sslEngine.setWantClientAuth(true);
262            break;
263        }
264    
265        SSLSession sslSession = sslEngine.getSession();
266    
267        clearBufferSize = sslSession.getApplicationBufferSize();
268        clearInBuffer   = ByteBuffer.allocate(clearBufferSize);
269        clearOutBuffer  = ByteBuffer.allocate(clearBufferSize);
270    
271        sslBufferSize   = sslSession.getPacketBufferSize();
272        sslInBuffer     = ByteBuffer.allocate(sslBufferSize);
273        sslOutBuffer    = ByteBuffer.allocate(sslBufferSize);
274      }
275    
276    
277    
278      /**
279       * {@inheritDoc}
280       */
281      @Override()
282      public void initializeConnectionSecurityProvider(ConfigEntry configEntry)
283             throws ConfigException, InitializationException
284      {
285        // Initialize default values for the connection-specific variables.
286        clientConnection = null;
287        socketChannel    = null;
288    
289        clearInBuffer    = null;
290        clearOutBuffer   = null;
291        sslInBuffer      = null;
292        sslOutBuffer     = null;
293        clearBufferSize  = -1;
294        sslBufferSize    = -1;
295    
296        sslEngine        = null;
297    
298        enabledProtocols    = null;
299        enabledCipherSuites = null;
300        sslClientAuthPolicy = SSLClientAuthPolicy.OPTIONAL;
301      }
302    
303    
304    
305      /**
306       * {@inheritDoc}
307       */
308      @Override()
309      public void finalizeConnectionSecurityProvider()
310      {
311        // No implementation is required.
312      }
313    
314    
315    
316      /**
317       * {@inheritDoc}
318       */
319      @Override()
320      public String getSecurityMechanismName()
321      {
322        return SSL_CONTEXT_INSTANCE_NAME;
323      }
324    
325    
326    
327      /**
328       * {@inheritDoc}
329       */
330      @Override()
331      public boolean isSecure()
332      {
333        // This should be considered secure.
334        return true;
335      }
336    
337    
338    
339      /**
340       * {@inheritDoc}
341       */
342      @Override()
343      public ConnectionSecurityProvider newInstance(ClientConnection
344                                                          clientConnection,
345                                                    SocketChannel socketChannel)
346             throws DirectoryException
347      {
348        return new TLSConnectionSecurityProvider(clientConnection, socketChannel,
349                                                 this);
350      }
351    
352    
353    
354      /**
355       * {@inheritDoc}
356       */
357      @Override()
358      public void disconnect(boolean connectionValid)
359      {
360        if (connectionValid)
361        {
362          try
363          {
364            sslEngine.closeInbound();
365            sslEngine.closeOutbound();
366    
367            while (true)
368            {
369              switch (sslEngine.getHandshakeStatus())
370              {
371                case FINISHED:
372                case NOT_HANDSHAKING:
373                  // We don't need to do anything else.
374                  return;
375    
376                case NEED_TASK:
377                  // We need to process some task before continuing.
378                  Runnable task = sslEngine.getDelegatedTask();
379                  task.run();
380                  break;
381    
382                case NEED_WRAP:
383                  // We need to send data to the client.
384                  clearOutBuffer.clear();
385                  sslOutBuffer.clear();
386                  sslEngine.wrap(clearOutBuffer, sslOutBuffer);
387                  sslOutBuffer.flip();
388                  while (sslOutBuffer.hasRemaining())
389                  {
390                    socketChannel.write(sslOutBuffer);
391                  }
392                  break;
393    
394                case NEED_UNWRAP:
395                  // We need to read data from the client.  We can do this if it's
396                  // immediately available, but otherwise, ignore it because
397                  // otherwise it could chew up a lot of time.
398                  if (sslInBuffer.hasRemaining())
399                  {
400                    clearInBuffer.clear();
401                    sslEngine.unwrap(sslInBuffer, clearInBuffer);
402                    clearInBuffer.flip();
403                  }
404                  else
405                  {
406                    sslInBuffer.clear();
407                    clearInBuffer.clear();
408                    int bytesRead = socketChannel.read(sslInBuffer);
409                    if (bytesRead <= 0)
410                    {
411                      return;
412                    }
413                    sslEngine.unwrap(sslInBuffer, clearInBuffer);
414                    clearInBuffer.flip();
415                  }
416              }
417            }
418          }
419          catch (Exception e)
420          {
421            if (debugEnabled())
422            {
423              TRACER.debugCaught(DebugLogLevel.ERROR, e);
424            }
425          }
426        }
427      }
428    
429    
430    
431      /**
432       * {@inheritDoc}
433       */
434      @Override()
435      public int getClearBufferSize()
436      {
437        return clearBufferSize;
438      }
439    
440    
441    
442      /**
443       * {@inheritDoc}
444       */
445      @Override()
446      public int getEncodedBufferSize()
447      {
448        return sslBufferSize;
449      }
450    
451    
452    
453      /**
454       * {@inheritDoc}
455       */
456      @Override()
457      public boolean readData()
458      {
459        while (true)
460        {
461          try
462          {
463            sslInBuffer.clear();
464            int bytesRead = socketChannel.read(sslInBuffer);
465            sslInBuffer.flip();
466    
467            if (bytesRead < 0)
468            {
469              // The client connection has been closed.  Disconnect and return.
470              clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT, false,
471                                          null);
472              return false;
473            }
474    
475    
476            // See if there is any preliminary handshake work to do.
477    handshakeLoop:
478            while (true)
479            {
480              switch (sslEngine.getHandshakeStatus())
481              {
482                case NEED_TASK:
483                  Runnable task = sslEngine.getDelegatedTask();
484                  task.run();
485                  break;
486    
487                case NEED_WRAP:
488                  clearOutBuffer.clear();
489                  sslOutBuffer.clear();
490                  sslEngine.wrap(clearOutBuffer, sslOutBuffer);
491                  sslOutBuffer.flip();
492    
493                  while (sslOutBuffer.hasRemaining())
494                  {
495                    int bytesWritten = socketChannel.write(sslOutBuffer);
496                    if (bytesWritten < 0)
497                    {
498                      // The client connection has been closed.  Disconnect and
499                      // return.
500                      clientConnection.disconnect(
501                           DisconnectReason.CLIENT_DISCONNECT, false, null);
502                      return false;
503                    }
504                  }
505                  break;
506    
507                default:
508                  break handshakeLoop;
509              }
510            }
511    
512            if (bytesRead == 0)
513            {
514              // We don't have any data to process, and we've already done any
515              // necessary handshaking, so we can break out and wait for more data
516              // to arrive.
517              return true;
518            }
519    
520    
521            // Read any SSL-encrypted data provided by the client.
522            while (sslInBuffer.hasRemaining())
523            {
524              clearInBuffer.clear();
525              SSLEngineResult unwrapResult = sslEngine.unwrap(sslInBuffer,
526                                                              clearInBuffer);
527              clearInBuffer.flip();
528    
529              switch (unwrapResult.getStatus())
530              {
531                case OK:
532                  // This is fine.
533                  break;
534    
535                case CLOSED:
536                  // The client connection (or at least the SSL side of it) has been
537                  // closed.
538                  // FIXME -- Allow for closing the SSL channel without closing the
539                  //          underlying connection.
540                  clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT,
541                                              false, null);
542                  return false;
543    
544                default:
545                  // This should not have happened.
546                  clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM,
547                          false,
548                          ERR_TLS_SECURITY_PROVIDER_UNEXPECTED_UNWRAP_STATUS.get(
549                                  String.valueOf(unwrapResult.getStatus())));
550                  return false;
551              }
552    
553              switch (unwrapResult.getHandshakeStatus())
554              {
555                case NEED_TASK:
556                  Runnable task = sslEngine.getDelegatedTask();
557                  task.run();
558                  break;
559    
560                case NEED_WRAP:
561                  clearOutBuffer.clear();
562                  sslOutBuffer.clear();
563                  sslEngine.wrap(clearOutBuffer, sslOutBuffer);
564                  sslOutBuffer.flip();
565    
566                  while (sslOutBuffer.hasRemaining())
567                  {
568                    int bytesWritten = socketChannel.write(sslOutBuffer);
569                    if (bytesWritten < 0)
570                    {
571                      // The client connection has been closed.  Disconnect and
572                      // return.
573                      clientConnection.disconnect(
574                           DisconnectReason.CLIENT_DISCONNECT, false, null);
575                      return false;
576                    }
577                  }
578                  break;
579              }
580    
581              // If there is any clear-text data, then process it.
582              if (! clientConnection.processDataRead(clearInBuffer))
583              {
584                // If this happens, then the client connection disconnect method
585                // should have already been called, so we don't need to do it again.
586                return false;
587              }
588            }
589          }
590          catch (IOException ioe)
591          {
592            if (debugEnabled())
593            {
594              TRACER.debugCaught(DebugLogLevel.ERROR, ioe);
595            }
596    
597            // An error occurred while trying to communicate with the client.
598            // Disconnect and return.
599            clientConnection.disconnect(DisconnectReason.IO_ERROR, false, null);
600            return false;
601          }
602          catch (Exception e)
603          {
604            if (debugEnabled())
605            {
606              TRACER.debugCaught(DebugLogLevel.ERROR, e);
607            }
608    
609            // An unexpected error occurred while trying to process the data read.
610            // Disconnect and return.
611            clientConnection.disconnect(DisconnectReason.SERVER_ERROR, true,
612                                        ERR_TLS_SECURITY_PROVIDER_READ_ERROR.get(
613                                        getExceptionMessage(e)));
614            return false;
615          }
616        }
617      }
618    
619    
620    
621      /**
622       * {@inheritDoc}
623       */
624      @Override()
625      public boolean writeData(ByteBuffer clearData)
626      {
627        int originalPosition = clearData.position();
628        int originalLimit    = clearData.limit();
629        int length           = originalLimit - originalPosition;
630    
631        try
632        {
633          if (length > clearBufferSize)
634          {
635            // There is more data to write than we can deal with in one chunk, so
636            // break it up.
637            int pos = originalPosition;
638            int lim = originalPosition + clearBufferSize;
639    
640            while (pos < originalLimit)
641            {
642              clearData.position(pos);
643              clearData.limit(lim);
644    
645              if (! writeInternal(clearData))
646              {
647                return false;
648              }
649    
650              pos = lim;
651              lim = Math.min(originalLimit, pos+clearBufferSize);
652            }
653    
654            return true;
655          }
656          else
657          {
658            return writeInternal(clearData);
659          }
660        }
661        finally
662        {
663          clearData.position(originalPosition);
664          clearData.limit(originalLimit);
665        }
666      }
667    
668    
669    
670      /**
671       * Writes the data contained in the provided clear-text buffer to the client,
672       * performing any necessary encoding in the process.  The amount of data in
673       * the provided buffer must be less than or equal to the value returned by the
674       * {@code getClearBufferSize} method.
675       *
676       * @param  clearData  The buffer containing the clear-text data to write to
677       *                    the client.
678       *
679       * @return  {@code true} if all the data in the provided buffer was written to
680       *          the client and the connection may remain established, or
681       *          {@code false} if a problem occurred and the client connection is
682       *          no longer valid.  Note that if this method does return
683       *          {@code false}, then it must have already disconnected the client.
684       */
685      private boolean writeInternal(ByteBuffer clearData)
686      {
687        try
688        {
689          // See if there is any preliminary handshake work to be done.
690    handshakeStatusLoop:
691          while (true)
692          {
693            switch (sslEngine.getHandshakeStatus())
694            {
695              case NEED_TASK:
696                Runnable task = sslEngine.getDelegatedTask();
697                task.run();
698                break;
699    
700              case NEED_WRAP:
701                clearOutBuffer.clear();
702                sslOutBuffer.clear();
703                sslEngine.wrap(clearOutBuffer, sslOutBuffer);
704                sslOutBuffer.flip();
705    
706                while (sslOutBuffer.hasRemaining())
707                {
708                  int bytesWritten = socketChannel.write(sslOutBuffer);
709                  if (bytesWritten < 0)
710                  {
711                    // The client connection has been closed.  Disconnect and
712                    // return.
713                    clientConnection.disconnect(
714                         DisconnectReason.CLIENT_DISCONNECT, false, null);
715                    return false;
716                  }
717                  else if (bytesWritten == 0)
718                  {
719                    return NullConnectionSecurityProvider.writeWithTimeout(
720                                clientConnection, socketChannel, sslOutBuffer);
721                  }
722                }
723                break;
724    
725              case NEED_UNWRAP:
726                // We need to read data from the client before the negotiation can
727                // continue.  This is bad, because we don't know if there is data
728                // available but we do know that we can't write until we have read.
729                // See if there is something available for reading, and if not, then
730                // we can't afford to wait for it because otherwise we would be
731                // potentially blocking reads from other clients.  Our only recourse
732                // is to close the connection.
733                sslInBuffer.clear();
734                clearInBuffer.clear();
735                int bytesRead = socketChannel.read(sslInBuffer);
736                if (bytesRead < 0)
737                {
738                  // The client connection is already closed, so we don't need to
739                  // worry about it.
740                  clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT,
741                                              false, null);
742                  return false;
743                }
744                else if (bytesRead == 0)
745                {
746                  // We didn't get the data that we need.  We'll have to disconnect
747                  // to avoid blocking other clients.
748                  clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM,
749                       false, ERR_TLS_SECURITY_PROVIDER_WRITE_NEEDS_UNWRAP.get());
750                  return false;
751                }
752                else
753                {
754                  // We were lucky and got the data we were looking for, so read and
755                  // process it.
756                  sslEngine.unwrap(sslInBuffer, clearInBuffer);
757                  clearInBuffer.flip();
758                }
759                break;
760    
761              default:
762                break handshakeStatusLoop;
763            }
764          }
765    
766    
767          while (clearData.hasRemaining())
768          {
769            sslOutBuffer.clear();
770            SSLEngineResult wrapResult = sslEngine.wrap(clearData, sslOutBuffer);
771            sslOutBuffer.flip();
772    
773            switch (wrapResult.getStatus())
774            {
775              case OK:
776                // This is fine.
777                break;
778    
779              case CLOSED:
780                // The client connection (or at least the SSL side of it) has been
781                // closed.
782                // FIXME -- Allow for closing the SSL channel without closing the
783                //          underlying connection.
784                clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT,
785                                            false, null);
786                return false;
787    
788              default:
789                // This should not have happened.
790                clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM,
791                     false, ERR_TLS_SECURITY_PROVIDER_UNEXPECTED_WRAP_STATUS.get(
792                      String.valueOf(wrapResult.getStatus())));
793                return false;
794            }
795    
796            switch (wrapResult.getHandshakeStatus())
797            {
798              case NEED_TASK:
799                Runnable task = sslEngine.getDelegatedTask();
800                task.run();
801                break;
802    
803              case NEED_WRAP:
804                // FIXME -- Could this overwrite the SSL out that we just wrapped?
805                // FIXME -- Is this even a feasible result?
806                clearOutBuffer.clear();
807                sslOutBuffer.clear();
808                sslEngine.wrap(clearOutBuffer, sslOutBuffer);
809                sslOutBuffer.flip();
810    
811                while (sslOutBuffer.hasRemaining())
812                {
813                  int bytesWritten = socketChannel.write(sslOutBuffer);
814                  if (bytesWritten < 0)
815                  {
816                    // The client connection has been closed.  Disconnect and
817                    // return.
818                    clientConnection.disconnect(
819                         DisconnectReason.CLIENT_DISCONNECT, false, null);
820                    return false;
821                  }
822                  else if (bytesWritten == 0)
823                  {
824                    return NullConnectionSecurityProvider.writeWithTimeout(
825                                clientConnection, socketChannel, sslOutBuffer);
826                  }
827                }
828                break;
829    
830              case NEED_UNWRAP:
831                // We need to read data from the client before the negotiation can
832                // continue.  This is bad, because we don't know if there is data
833                // available but we do know that we can't write until we have read.
834                // See if there is something available for reading, and if not, then
835                // we can't afford to wait for it because otherwise we would be
836                // potentially blocking reads from other clients.  Our only recourse
837                // is to close the connection.
838                sslInBuffer.clear();
839                clearInBuffer.clear();
840                int bytesRead = socketChannel.read(sslInBuffer);
841                if (bytesRead < 0)
842                {
843                  // The client connection is already closed, so we don't need to
844                  // worry about it.
845                  clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT,
846                                              false, null);
847                  return false;
848                }
849                else if (bytesRead == 0)
850                {
851                  // We didn't get the data that we need.  We'll have to disconnect
852                  // to avoid blocking other clients.
853                  clientConnection.disconnect(DisconnectReason.SECURITY_PROBLEM,
854                       false, ERR_TLS_SECURITY_PROVIDER_WRITE_NEEDS_UNWRAP.get());
855                  return false;
856                }
857                else
858                {
859                  // We were lucky and got the data we were looking for, so read and
860                  // process it.
861                  sslEngine.unwrap(sslInBuffer, clearInBuffer);
862                  clearInBuffer.flip();
863                }
864                break;
865            }
866    
867            while (sslOutBuffer.hasRemaining())
868            {
869              int bytesWritten = socketChannel.write(sslOutBuffer);
870              if (bytesWritten < 0)
871              {
872                // The client connection has been closed.
873                clientConnection.disconnect(DisconnectReason.CLIENT_DISCONNECT,
874                                            false, null);
875                return false;
876              }
877              else if (bytesWritten == 0)
878              {
879                return NullConnectionSecurityProvider.writeWithTimeout(
880                            clientConnection, socketChannel, sslOutBuffer);
881              }
882            }
883          }
884    
885    
886          // If we've gotten here, then everything must have been written
887          // successfully.
888          return true;
889        }
890        catch (IOException ioe)
891        {
892          if (debugEnabled())
893          {
894            TRACER.debugCaught(DebugLogLevel.ERROR, ioe);
895          }
896    
897          // An error occurred while trying to communicate with the client.
898          // Disconnect and return.
899          clientConnection.disconnect(DisconnectReason.IO_ERROR, false, null);
900          return false;
901        }
902        catch (Exception e)
903        {
904          if (debugEnabled())
905          {
906            TRACER.debugCaught(DebugLogLevel.ERROR, e);
907          }
908    
909          // An unexpected error occurred while trying to process the data read.
910          // Disconnect and return.
911          clientConnection.disconnect(DisconnectReason.SERVER_ERROR, true,
912                  ERR_TLS_SECURITY_PROVIDER_WRITE_ERROR.get(
913                          getExceptionMessage(e)));
914          return false;
915        }
916      }
917    
918    
919    
920      /**
921       * Retrieves the set of SSL protocols that will be allowed.
922       *
923       * @return  The set of SSL protocols that will be allowed, or {@code null} if
924       *          the default set will be used.
925       */
926      public String[] getEnabledProtocols()
927      {
928        return enabledProtocols;
929      }
930    
931    
932    
933      /**
934       * Specifies the set of SSL protocols that will be allowed.
935       *
936       * @param  enabledProtocols  The set of SSL protocols that will be allowed, or
937       *                           {@code null} if the default set will be used.
938       */
939      public void setEnabledProtocols(String[] enabledProtocols)
940      {
941        this.enabledProtocols = enabledProtocols;
942      }
943    
944    
945    
946      /**
947       * Retrieves the set of SSL cipher suites that will be allowed.
948       *
949       * @return  The set of SSL cipher suites that will be allowed.
950       */
951      public String[] getEnabledCipherSuites()
952      {
953        return enabledCipherSuites;
954      }
955    
956    
957    
958      /**
959       * Specifies the set of SSL cipher suites that will be allowed.
960       *
961       * @param  enabledCipherSuites  The set of SSL cipher suites that will be
962       *                              allowed.
963       */
964      public void setEnabledCipherSuites(String[] enabledCipherSuites)
965      {
966        this.enabledCipherSuites = enabledCipherSuites;
967      }
968    
969    
970    
971      /**
972       * Retrieves the policy that should be used for SSL client authentication.
973       *
974       * @return  The policy that should be used for SSL client authentication.
975       */
976      public SSLClientAuthPolicy getSSLClientAuthPolicy()
977      {
978        return sslClientAuthPolicy;
979      }
980    
981    
982    
983      /**
984       * Specifies the policy that should be used for SSL client authentication.
985       *
986       * @param  sslClientAuthPolicy  The policy that should be used for SSL client
987       *                              authentication.
988       */
989      public void setSSLClientAuthPolicy(SSLClientAuthPolicy sslClientAuthPolicy)
990      {
991        this.sslClientAuthPolicy = sslClientAuthPolicy;
992      }
993    
994    
995    
996      /**
997       * Retrieves the SSL session associated with this client connection.
998       *
999       * @return  The SSL session associated with this client connection.
1000       */
1001      public SSLSession getSSLSession()
1002      {
1003        return sslEngine.getSession();
1004      }
1005    
1006    
1007    
1008      /**
1009       * Retrieves the certificate chain that the client presented to the server
1010       * during the handshake process.  The client's certificate will be the first
1011       * listed, followed by the certificates of any issuers in the chain.
1012       *
1013       * @return  The certificate chain that the client presented to the server
1014       *          during the handshake process, or {@code null} if the client did
1015       *          not present a certificate.
1016       */
1017      public Certificate[] getClientCertificateChain()
1018      {
1019        try
1020        {
1021          return sslEngine.getSession().getPeerCertificates();
1022        }
1023        catch (Exception e)
1024        {
1025          if (debugEnabled())
1026          {
1027            TRACER.debugCaught(DebugLogLevel.ERROR, e);
1028          }
1029    
1030          return null;
1031        }
1032      }
1033    }
1034