src/java.base/share/classes/sun/security/ssl/SSLEngineImpl.java
branchJDK-8145252-TLS13-branch
changeset 56542 56aaa6cb3693
parent 47216 71c04702a3d5
child 56544 ad120e0dfcfb
equal deleted inserted replaced
56541:92cbbfc996f3 56542:56aaa6cb3693
     1 /*
     1 /*
     2  * Copyright (c) 2003, 2016, Oracle and/or its affiliates. All rights reserved.
     2  * Copyright (c) 2003, 2018, Oracle and/or its affiliates. All rights reserved.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
     4  *
     4  *
     5  * This code is free software; you can redistribute it and/or modify it
     5  * This code is free software; you can redistribute it and/or modify it
     6  * under the terms of the GNU General Public License version 2 only, as
     6  * under the terms of the GNU General Public License version 2 only, as
     7  * published by the Free Software Foundation.  Oracle designates this
     7  * published by the Free Software Foundation.  Oracle designates this
    23  * questions.
    23  * questions.
    24  */
    24  */
    25 
    25 
    26 package sun.security.ssl;
    26 package sun.security.ssl;
    27 
    27 
    28 import java.io.*;
    28 import java.io.IOException;
    29 import java.nio.*;
    29 import java.nio.ByteBuffer;
    30 import java.security.*;
    30 import java.nio.ReadOnlyBufferException;
    31 import java.util.*;
    31 import java.security.AccessController;
       
    32 import java.security.PrivilegedActionException;
       
    33 import java.security.PrivilegedExceptionAction;
       
    34 import java.util.List;
       
    35 import java.util.Map;
    32 import java.util.function.BiFunction;
    36 import java.util.function.BiFunction;
    33 
    37 import javax.net.ssl.SSLEngine;
    34 import javax.crypto.BadPaddingException;
    38 import javax.net.ssl.SSLEngineResult;
    35 
    39 import javax.net.ssl.SSLEngineResult.HandshakeStatus;
    36 import javax.net.ssl.*;
    40 import javax.net.ssl.SSLEngineResult.Status;
    37 import javax.net.ssl.SSLEngineResult.*;
    41 import javax.net.ssl.SSLException;
       
    42 import javax.net.ssl.SSLHandshakeException;
       
    43 import javax.net.ssl.SSLKeyException;
       
    44 import javax.net.ssl.SSLParameters;
       
    45 import javax.net.ssl.SSLPeerUnverifiedException;
       
    46 import javax.net.ssl.SSLProtocolException;
       
    47 import javax.net.ssl.SSLSession;
    38 
    48 
    39 /**
    49 /**
    40  * Implementation of an non-blocking SSLEngine.
    50  * Implementation of an non-blocking SSLEngine.
    41  *
    51  *
    42  * *Currently*, the SSLEngine code exists in parallel with the current
       
    43  * SSLSocket.  As such, the current implementation is using legacy code
       
    44  * with many of the same abstractions.  However, it varies in many
       
    45  * areas, most dramatically in the IO handling.
       
    46  *
       
    47  * There are three main I/O threads that can be existing in parallel:
       
    48  * wrap(), unwrap(), and beginHandshake().  We are encouraging users to
       
    49  * not call multiple instances of wrap or unwrap, because the data could
       
    50  * appear to flow out of the SSLEngine in a non-sequential order.  We
       
    51  * take all steps we can to at least make sure the ordering remains
       
    52  * consistent, but once the calls returns, anything can happen.  For
       
    53  * example, thread1 and thread2 both call wrap, thread1 gets the first
       
    54  * packet, thread2 gets the second packet, but thread2 gets control back
       
    55  * before thread1, and sends the data.  The receiving side would see an
       
    56  * out-of-order error.
       
    57  *
       
    58  * @author Brad Wetmore
    52  * @author Brad Wetmore
    59  */
    53  */
    60 public final class SSLEngineImpl extends SSLEngine {
    54 final class SSLEngineImpl extends SSLEngine implements SSLTransport {
    61 
    55     private final SSLContextImpl        sslContext;
    62     //
    56     final TransportContext              conContext;
    63     // Fields and global comments
       
    64     //
       
    65 
       
    66     /*
       
    67      * There's a state machine associated with each connection, which
       
    68      * among other roles serves to negotiate session changes.
       
    69      *
       
    70      * - START with constructor, until the TCP connection's around.
       
    71      * - HANDSHAKE picks session parameters before allowing traffic.
       
    72      *          There are many substates due to sequencing requirements
       
    73      *          for handshake messages.
       
    74      * - DATA may be transmitted.
       
    75      * - RENEGOTIATE state allows concurrent data and handshaking
       
    76      *          traffic ("same" substates as HANDSHAKE), and terminates
       
    77      *          in selection of new session (and connection) parameters
       
    78      * - ERROR state immediately precedes abortive disconnect.
       
    79      * - CLOSED when one side closes down, used to start the shutdown
       
    80      *          process.  SSL connection objects are not reused.
       
    81      *
       
    82      * State affects what SSL record types may legally be sent:
       
    83      *
       
    84      * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
       
    85      * - App Data ... only in DATA and RENEGOTIATE states
       
    86      * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
       
    87      *
       
    88      * Re what may be received:  same as what may be sent, except that
       
    89      * HandshakeRequest handshaking messages can come from servers even
       
    90      * in the application data state, to request entry to RENEGOTIATE.
       
    91      *
       
    92      * The state machine within HANDSHAKE and RENEGOTIATE states controls
       
    93      * the pending session, not the connection state, until the change
       
    94      * cipher spec and "Finished" handshake messages are processed and
       
    95      * make the "new" session become the current one.
       
    96      *
       
    97      * NOTE: details of the SMs always need to be nailed down better.
       
    98      * The text above illustrates the core ideas.
       
    99      *
       
   100      *                +---->-------+------>--------->-------+
       
   101      *                |            |                        |
       
   102      *     <-----<    ^            ^  <-----<               |
       
   103      *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE    |
       
   104      *                v            v               v        |
       
   105      *                |            |               |        |
       
   106      *                +------------+---------------+        |
       
   107      *                |                                     |
       
   108      *                v                                     |
       
   109      *               ERROR>------>----->CLOSED<--------<----+
       
   110      *
       
   111      * ALSO, note that the purpose of handshaking (renegotiation is
       
   112      * included) is to assign a different, and perhaps new, session to
       
   113      * the connection.  The SSLv3 spec is a bit confusing on that new
       
   114      * protocol feature.
       
   115      */
       
   116     private int                 connectionState;
       
   117 
       
   118     private static final int    cs_START = 0;
       
   119     private static final int    cs_HANDSHAKE = 1;
       
   120     private static final int    cs_DATA = 2;
       
   121     private static final int    cs_RENEGOTIATE = 3;
       
   122     private static final int    cs_ERROR = 4;
       
   123     private static final int    cs_CLOSED = 6;
       
   124 
       
   125     /*
       
   126      * Once we're in state cs_CLOSED, we can continue to
       
   127      * wrap/unwrap until we finish sending/receiving the messages
       
   128      * for close_notify.
       
   129      */
       
   130     private boolean             inboundDone = false;
       
   131     private boolean             outboundDone = false;
       
   132 
       
   133     /*
       
   134      * The authentication context holds all information used to establish
       
   135      * who this end of the connection is (certificate chains, private keys,
       
   136      * etc) and who is trusted (e.g. as CAs or websites).
       
   137      */
       
   138     private SSLContextImpl      sslContext;
       
   139 
       
   140     /*
       
   141      * This connection is one of (potentially) many associated with
       
   142      * any given session.  The output of the handshake protocol is a
       
   143      * new session ... although all the protocol description talks
       
   144      * about changing the cipher spec (and it does change), in fact
       
   145      * that's incidental since it's done by changing everything that
       
   146      * is associated with a session at the same time.  (TLS/IETF may
       
   147      * change that to add client authentication w/o new key exchg.)
       
   148      */
       
   149     private Handshaker                  handshaker;
       
   150     private SSLSessionImpl              sess;
       
   151     private volatile SSLSessionImpl     handshakeSession;
       
   152 
       
   153     /*
       
   154      * Flag indicating if the next record we receive MUST be a Finished
       
   155      * message. Temporarily set during the handshake to ensure that
       
   156      * a change cipher spec message is followed by a finished message.
       
   157      */
       
   158     private boolean             expectingFinished;
       
   159 
       
   160 
       
   161     /*
       
   162      * If someone tries to closeInbound() (say at End-Of-Stream)
       
   163      * our engine having received a close_notify, we need to
       
   164      * notify the app that we may have a truncation attack underway.
       
   165      */
       
   166     private boolean             recvCN;
       
   167 
       
   168     /*
       
   169      * For improved diagnostics, we detail connection closure
       
   170      * If the engine is closed (connectionState >= cs_ERROR),
       
   171      * closeReason != null indicates if the engine was closed
       
   172      * because of an error or because or normal shutdown.
       
   173      */
       
   174     private SSLException        closeReason;
       
   175 
       
   176     /*
       
   177      * Per-connection private state that doesn't change when the
       
   178      * session is changed.
       
   179      */
       
   180     private ClientAuthType          doClientAuth =
       
   181                                             ClientAuthType.CLIENT_AUTH_NONE;
       
   182     private boolean                 enableSessionCreation = true;
       
   183     InputRecord                     inputRecord;
       
   184     OutputRecord                    outputRecord;
       
   185     private AccessControlContext    acc;
       
   186 
       
   187     // The cipher suites enabled for use on this connection.
       
   188     private CipherSuiteList             enabledCipherSuites;
       
   189 
       
   190     // the endpoint identification protocol
       
   191     private String                      identificationProtocol = null;
       
   192 
       
   193     // The cryptographic algorithm constraints
       
   194     private AlgorithmConstraints        algorithmConstraints = null;
       
   195 
       
   196     // The server name indication and matchers
       
   197     List<SNIServerName>         serverNames =
       
   198                                     Collections.<SNIServerName>emptyList();
       
   199     Collection<SNIMatcher>      sniMatchers =
       
   200                                     Collections.<SNIMatcher>emptyList();
       
   201 
       
   202     // Configured application protocol values
       
   203     String[] applicationProtocols = new String[0];
       
   204 
       
   205     // Negotiated application protocol value.
       
   206     //
       
   207     // The value under negotiation will be obtained from handshaker.
       
   208     String applicationProtocol = null;
       
   209 
       
   210     // Callback function that selects the application protocol value during
       
   211     // the SSL/TLS handshake.
       
   212     BiFunction<SSLEngine, List<String>, String> applicationProtocolSelector;
       
   213 
       
   214     // Have we been told whether we're client or server?
       
   215     private boolean                     serverModeSet = false;
       
   216     private boolean                     roleIsServer;
       
   217 
       
   218     /*
       
   219      * The protocol versions enabled for use on this connection.
       
   220      *
       
   221      * Note: we support a pseudo protocol called SSLv2Hello which when
       
   222      * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
       
   223      * or TLS (version 3.1, 3.2, etc.) version info.
       
   224      */
       
   225     private ProtocolList        enabledProtocols;
       
   226 
       
   227     /*
       
   228      * The SSL version associated with this connection.
       
   229      */
       
   230     private ProtocolVersion     protocolVersion;
       
   231 
       
   232     /*
       
   233      * security parameters for secure renegotiation.
       
   234      */
       
   235     private boolean             secureRenegotiation;
       
   236     private byte[]              clientVerifyData;
       
   237     private byte[]              serverVerifyData;
       
   238 
       
   239     /*
       
   240      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
       
   241      * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
       
   242      * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
       
   243      *
       
   244      * There are several locks here.
       
   245      *
       
   246      * The primary lock is the per-instance lock used by
       
   247      * synchronized(this) and the synchronized methods.  It controls all
       
   248      * access to things such as the connection state and variables which
       
   249      * affect handshaking.  If we are inside a synchronized method, we
       
   250      * can access the state directly, otherwise, we must use the
       
   251      * synchronized equivalents.
       
   252      *
       
   253      * Note that we must never acquire the <code>this</code> lock after
       
   254      * <code>writeLock</code> or run the risk of deadlock.
       
   255      *
       
   256      * Grab some coffee, and be careful with any code changes.
       
   257      */
       
   258     private Object              wrapLock;
       
   259     private Object              unwrapLock;
       
   260     Object                      writeLock;
       
   261 
       
   262     /*
       
   263      * Whether local cipher suites preference in server side should be
       
   264      * honored during handshaking?
       
   265      */
       
   266     private boolean preferLocalCipherSuites = false;
       
   267 
       
   268     /*
       
   269      * whether DTLS handshake retransmissions should be enabled?
       
   270      */
       
   271     private boolean enableRetransmissions = false;
       
   272 
       
   273     /*
       
   274      * The maximum expected network packet size for SSL/TLS/DTLS records.
       
   275      */
       
   276     private int maximumPacketSize = 0;
       
   277 
       
   278     /*
       
   279      * Is this an instance for Datagram Transport Layer Security (DTLS)?
       
   280      */
       
   281     private final boolean isDTLS;
       
   282 
       
   283     /*
       
   284      * Class and subclass dynamic debugging support
       
   285      */
       
   286     private static final Debug debug = Debug.getInstance("ssl");
       
   287 
       
   288     //
       
   289     // Initialization/Constructors
       
   290     //
       
   291 
    57 
   292     /**
    58     /**
   293      * Constructor for an SSLEngine from SSLContext, without
    59      * Constructor for an SSLEngine from SSLContext, without
   294      * host/port hints.  This Engine will not be able to cache
    60      * host/port hints.
   295      * sessions, but must renegotiate everything by hand.
    61      *
       
    62      * This Engine will not be able to cache sessions, but must renegotiate
       
    63      * everything by hand.
   296      */
    64      */
   297     SSLEngineImpl(SSLContextImpl ctx, boolean isDTLS) {
    65     SSLEngineImpl(SSLContextImpl sslContext) {
   298         super();
    66         this(sslContext, null, -1);
   299         this.isDTLS = isDTLS;
       
   300         init(ctx, isDTLS);
       
   301     }
    67     }
   302 
    68 
   303     /**
    69     /**
   304      * Constructor for an SSLEngine from SSLContext.
    70      * Constructor for an SSLEngine from SSLContext.
   305      */
    71      */
   306     SSLEngineImpl(SSLContextImpl ctx, String host, int port, boolean isDTLS) {
    72     SSLEngineImpl(SSLContextImpl sslContext,
       
    73             String host, int port) {
   307         super(host, port);
    74         super(host, port);
   308         this.isDTLS = isDTLS;
    75         this.sslContext = sslContext;
   309         init(ctx, isDTLS);
    76         HandshakeHash handshakeHash = new HandshakeHash();
   310     }
    77         if (sslContext.isDTLS()) {
   311 
    78             this.conContext = new TransportContext(sslContext, this,
   312     /**
    79                     new DTLSInputRecord(handshakeHash),
   313      * Initializes the Engine
    80                     new DTLSOutputRecord(handshakeHash));
   314      */
       
   315     private void init(SSLContextImpl ctx, boolean isDTLS) {
       
   316         if (debug != null && Debug.isOn("ssl")) {
       
   317             System.out.println("Using SSLEngineImpl.");
       
   318         }
       
   319 
       
   320         sslContext = ctx;
       
   321         sess = SSLSessionImpl.nullSession;
       
   322         handshakeSession = null;
       
   323         protocolVersion = isDTLS ?
       
   324                 ProtocolVersion.DEFAULT_DTLS : ProtocolVersion.DEFAULT_TLS;
       
   325 
       
   326         /*
       
   327          * State is cs_START until we initialize the handshaker.
       
   328          *
       
   329          * Apps using SSLEngine are probably going to be server.
       
   330          * Somewhat arbitrary choice.
       
   331          */
       
   332         roleIsServer = true;
       
   333         connectionState = cs_START;
       
   334 
       
   335         // default server name indication
       
   336         serverNames =
       
   337             Utilities.addToSNIServerNameList(serverNames, getPeerHost());
       
   338 
       
   339         // default security parameters for secure renegotiation
       
   340         secureRenegotiation = false;
       
   341         clientVerifyData = new byte[0];
       
   342         serverVerifyData = new byte[0];
       
   343 
       
   344         enabledCipherSuites =
       
   345                 sslContext.getDefaultCipherSuiteList(roleIsServer);
       
   346         enabledProtocols =
       
   347                 sslContext.getDefaultProtocolList(roleIsServer);
       
   348 
       
   349         wrapLock = new Object();
       
   350         unwrapLock = new Object();
       
   351         writeLock = new Object();
       
   352 
       
   353         /*
       
   354          * Save the Access Control Context.  This will be used later
       
   355          * for a couple of things, including providing a context to
       
   356          * run tasks in, and for determining which credentials
       
   357          * to use for Subject based (JAAS) decisions
       
   358          */
       
   359         acc = AccessController.getContext();
       
   360 
       
   361         /*
       
   362          * All outbound application data goes through this OutputRecord,
       
   363          * other data goes through their respective records created
       
   364          * elsewhere.  All inbound data goes through this one
       
   365          * input record.
       
   366          */
       
   367         if (isDTLS) {
       
   368             enableRetransmissions = true;
       
   369 
       
   370             // SSLEngine needs no record local buffer
       
   371             outputRecord = new DTLSOutputRecord();
       
   372             inputRecord = new DTLSInputRecord();
       
   373 
       
   374         } else {
    81         } else {
   375             outputRecord = new SSLEngineOutputRecord();
    82             this.conContext = new TransportContext(sslContext, this,
   376             inputRecord = new SSLEngineInputRecord();
    83                     new SSLEngineInputRecord(handshakeHash),
   377         }
    84                     new SSLEngineOutputRecord(handshakeHash));
   378 
    85         }
   379         maximumPacketSize = outputRecord.getMaxPacketSize();
    86 
   380     }
    87         // Server name indication is a connection scope extension.
   381 
    88         if (host != null) {
   382     /**
    89             this.conContext.sslConfig.serverNames =
   383      * Initialize the handshaker object. This means:
    90                     Utilities.addToSNIServerNameList(
   384      *
    91                             conContext.sslConfig.serverNames, host);
   385      *  . if a handshake is already in progress (state is cs_HANDSHAKE
    92         }
   386      *    or cs_RENEGOTIATE), do nothing and return
    93     }
   387      *
    94 
   388      *  . if the engine is already closed, throw an Exception (internal error)
    95     @Override
   389      *
    96     public synchronized void beginHandshake() throws SSLException {
   390      *  . otherwise (cs_START or cs_DATA), create the appropriate handshaker
    97         if (conContext.isUnsureMode) {
   391      *    object and advance the connection state (to cs_HANDSHAKE or
    98             throw new IllegalStateException(
   392      *    cs_RENEGOTIATE, respectively).
    99                     "Client/Server mode has not yet been set.");
   393      *
   100         }
   394      * This method is called right after a new engine is created, when
   101 
   395      * starting renegotiation, or when changing client/server mode of the
       
   396      * engine.
       
   397      */
       
   398     private void initHandshaker() {
       
   399         switch (connectionState) {
       
   400 
       
   401         //
       
   402         // Starting a new handshake.
       
   403         //
       
   404         case cs_START:
       
   405         case cs_DATA:
       
   406             break;
       
   407 
       
   408         //
       
   409         // We're already in the middle of a handshake.
       
   410         //
       
   411         case cs_HANDSHAKE:
       
   412         case cs_RENEGOTIATE:
       
   413             return;
       
   414 
       
   415         //
       
   416         // Anyone allowed to call this routine is required to
       
   417         // do so ONLY if the connection state is reasonable...
       
   418         //
       
   419         default:
       
   420             throw new IllegalStateException("Internal error");
       
   421         }
       
   422 
       
   423         // state is either cs_START or cs_DATA
       
   424         if (connectionState == cs_START) {
       
   425             connectionState = cs_HANDSHAKE;
       
   426         } else { // cs_DATA
       
   427             connectionState = cs_RENEGOTIATE;
       
   428         }
       
   429 
       
   430         if (roleIsServer) {
       
   431             handshaker = new ServerHandshaker(this, sslContext,
       
   432                     enabledProtocols, doClientAuth,
       
   433                     protocolVersion, connectionState == cs_HANDSHAKE,
       
   434                     secureRenegotiation, clientVerifyData, serverVerifyData,
       
   435                     isDTLS);
       
   436             handshaker.setSNIMatchers(sniMatchers);
       
   437             handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
       
   438         } else {
       
   439             handshaker = new ClientHandshaker(this, sslContext,
       
   440                     enabledProtocols,
       
   441                     protocolVersion, connectionState == cs_HANDSHAKE,
       
   442                     secureRenegotiation, clientVerifyData, serverVerifyData,
       
   443                     isDTLS);
       
   444             handshaker.setSNIServerNames(serverNames);
       
   445         }
       
   446         handshaker.setMaximumPacketSize(maximumPacketSize);
       
   447         handshaker.setEnabledCipherSuites(enabledCipherSuites);
       
   448         handshaker.setEnableSessionCreation(enableSessionCreation);
       
   449         handshaker.setApplicationProtocols(applicationProtocols);
       
   450         handshaker.setApplicationProtocolSelectorSSLEngine(
       
   451             applicationProtocolSelector);
       
   452 
       
   453         outputRecord.initHandshaker();
       
   454     }
       
   455 
       
   456     /*
       
   457      * Report the current status of the Handshaker
       
   458      */
       
   459     private HandshakeStatus getHSStatus(HandshakeStatus hss) {
       
   460 
       
   461         if (hss != null) {
       
   462             return hss;
       
   463         }
       
   464 
       
   465         synchronized (this) {
       
   466             if (!outputRecord.isEmpty()) {
       
   467                 // If no handshaking, special case to wrap alters.
       
   468                 return HandshakeStatus.NEED_WRAP;
       
   469             } else if (handshaker != null) {
       
   470                 if (handshaker.taskOutstanding()) {
       
   471                     return HandshakeStatus.NEED_TASK;
       
   472                 } else if (isDTLS && !inputRecord.isEmpty()) {
       
   473                     return HandshakeStatus.NEED_UNWRAP_AGAIN;
       
   474                 } else {
       
   475                     return HandshakeStatus.NEED_UNWRAP;
       
   476                 }
       
   477             } else if (connectionState == cs_CLOSED) {
       
   478                 /*
       
   479                  * Special case where we're closing, but
       
   480                  * still need the close_notify before we
       
   481                  * can officially be closed.
       
   482                  *
       
   483                  * Note isOutboundDone is taken care of by
       
   484                  * hasOutboundData() above.
       
   485                  */
       
   486                 if (!isInboundDone()) {
       
   487                     return HandshakeStatus.NEED_UNWRAP;
       
   488                 } // else not handshaking
       
   489             }
       
   490 
       
   491             return HandshakeStatus.NOT_HANDSHAKING;
       
   492         }
       
   493     }
       
   494 
       
   495     private synchronized void checkTaskThrown() throws SSLException {
       
   496         if (handshaker != null) {
       
   497             handshaker.checkThrown();
       
   498         }
       
   499     }
       
   500 
       
   501     //
       
   502     // Handshaking and connection state code
       
   503     //
       
   504 
       
   505     /*
       
   506      * Provides "this" synchronization for connection state.
       
   507      * Otherwise, you can access it directly.
       
   508      */
       
   509     private synchronized int getConnectionState() {
       
   510         return connectionState;
       
   511     }
       
   512 
       
   513     private synchronized void setConnectionState(int state) {
       
   514         connectionState = state;
       
   515     }
       
   516 
       
   517     /*
       
   518      * Get the Access Control Context.
       
   519      *
       
   520      * Used for a known context to
       
   521      * run tasks in, and for determining which credentials
       
   522      * to use for Subject-based (JAAS) decisions.
       
   523      */
       
   524     AccessControlContext getAcc() {
       
   525         return acc;
       
   526     }
       
   527 
       
   528     /*
       
   529      * Is a handshake currently underway?
       
   530      */
       
   531     @Override
       
   532     public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
       
   533         return getHSStatus(null);
       
   534     }
       
   535 
       
   536     /*
       
   537      * used by Handshaker to change the active write cipher, follows
       
   538      * the output of the CCS message.
       
   539      *
       
   540      * Also synchronized on "this" from readRecord/delegatedTask.
       
   541      */
       
   542     void changeWriteCiphers() throws IOException {
       
   543 
       
   544         Authenticator writeAuthenticator;
       
   545         CipherBox writeCipher;
       
   546         try {
   102         try {
   547             writeCipher = handshaker.newWriteCipher();
   103             conContext.kickstart();
   548             writeAuthenticator = handshaker.newWriteAuthenticator();
   104         } catch (IOException ioe) {
   549         } catch (GeneralSecurityException e) {
   105             conContext.fatal(Alert.HANDSHAKE_FAILURE,
   550             // "can't happen"
   106                 "Couldn't kickstart handshaking", ioe);
   551             throw new SSLException("Algorithm missing:  ", e);
   107         } catch (Exception ex) {     // including RuntimeException
   552         }
   108             conContext.fatal(Alert.INTERNAL_ERROR,
   553 
   109                 "Fail to begin handshake", ex);
   554         outputRecord.changeWriteCiphers(writeAuthenticator, writeCipher);
   110         }
   555     }
   111     }
   556 
   112 
   557     /*
   113     @Override
   558      * Updates the SSL version associated with this connection.
   114     public synchronized SSLEngineResult wrap(ByteBuffer[] appData,
   559      * Called from Handshaker once it has determined the negotiated version.
   115             int offset, int length, ByteBuffer netData) throws SSLException {
   560      */
   116         return wrap(
   561     synchronized void setVersion(ProtocolVersion protocolVersion) {
   117                 appData, offset, length, new ByteBuffer[]{ netData }, 0, 1);
   562         this.protocolVersion = protocolVersion;
   118     }
   563         outputRecord.setVersion(protocolVersion);
   119 
   564     }
   120     // @Override
   565 
   121     public synchronized SSLEngineResult wrap(
   566 
   122         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
   567     /**
   123         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException {
   568      * Kickstart the handshake if it is not already in progress.
   124 
   569      * This means:
   125         if (conContext.isUnsureMode) {
   570      *
   126             throw new IllegalStateException(
   571      *  . if handshaking is already underway, do nothing and return
   127                     "Client/Server mode has not yet been set.");
   572      *
   128         }
   573      *  . if the engine is not connected or already closed, throw an
   129 
   574      *    Exception.
   130         // See if the handshaker needs to report back some SSLException.
   575      *
   131         if (conContext.outputRecord.isEmpty()) {
   576      *  . otherwise, call initHandshake() to initialize the handshaker
   132             checkTaskThrown();
   577      *    object and progress the state. Then, send the initial
   133         }   // Otherwise, deliver cached records before throwing task exception.
   578      *    handshaking message if appropriate (always on clients and
   134 
   579      *    on servers when renegotiating).
   135         // check parameters
   580      */
   136         checkParams(srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
   581     private synchronized void kickstartHandshake() throws IOException {
   137 
   582         switch (connectionState) {
       
   583 
       
   584         case cs_START:
       
   585             if (!serverModeSet) {
       
   586                 throw new IllegalStateException(
       
   587                     "Client/Server mode not yet set.");
       
   588             }
       
   589             initHandshaker();
       
   590             break;
       
   591 
       
   592         case cs_HANDSHAKE:
       
   593             // handshaker already setup, proceed
       
   594             break;
       
   595 
       
   596         case cs_DATA:
       
   597             if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
       
   598                 throw new SSLHandshakeException(
       
   599                         "Insecure renegotiation is not allowed");
       
   600             }
       
   601 
       
   602             if (!secureRenegotiation) {
       
   603                 if (debug != null && Debug.isOn("handshake")) {
       
   604                     System.out.println(
       
   605                         "Warning: Using insecure renegotiation");
       
   606                 }
       
   607             }
       
   608 
       
   609             // initialize the handshaker, move to cs_RENEGOTIATE
       
   610             initHandshaker();
       
   611             break;
       
   612 
       
   613         case cs_RENEGOTIATE:
       
   614             // handshaking already in progress, return
       
   615             return;
       
   616 
       
   617         default:
       
   618             // cs_ERROR/cs_CLOSED
       
   619             throw new SSLException("SSLEngine is closing/closed");
       
   620         }
       
   621 
       
   622         //
       
   623         // Kickstart handshake state machine if we need to ...
       
   624         //
       
   625         if (!handshaker.activated()) {
       
   626              // prior to handshaking, activate the handshake
       
   627             if (connectionState == cs_RENEGOTIATE) {
       
   628                 // don't use SSLv2Hello when renegotiating
       
   629                 handshaker.activate(protocolVersion);
       
   630             } else {
       
   631                 handshaker.activate(null);
       
   632             }
       
   633 
       
   634             if (handshaker instanceof ClientHandshaker) {
       
   635                 // send client hello
       
   636                 handshaker.kickstart();
       
   637             } else {    // instanceof ServerHandshaker
       
   638                 if (connectionState == cs_HANDSHAKE) {
       
   639                     // initial handshake, no kickstart message to send
       
   640                 } else {
       
   641                     // we want to renegotiate, send hello request
       
   642                     handshaker.kickstart();
       
   643                 }
       
   644             }
       
   645         }
       
   646     }
       
   647 
       
   648     /*
       
   649      * Start a SSLEngine handshake
       
   650      */
       
   651     @Override
       
   652     public void beginHandshake() throws SSLException {
       
   653         try {
   138         try {
   654             kickstartHandshake();
   139             return writeRecord(
   655         } catch (Exception e) {
   140                 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
   656             fatal(Alerts.alert_handshake_failure,
       
   657                 "Couldn't kickstart handshaking", e);
       
   658         }
       
   659     }
       
   660 
       
   661 
       
   662     //
       
   663     // Read/unwrap side
       
   664     //
       
   665 
       
   666 
       
   667     /**
       
   668      * Unwraps a buffer.  Does a variety of checks before grabbing
       
   669      * the unwrapLock, which blocks multiple unwraps from occurring.
       
   670      */
       
   671     @Override
       
   672     public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer[] appData,
       
   673             int offset, int length) throws SSLException {
       
   674 
       
   675         // check engine parameters
       
   676         checkEngineParas(netData, appData, offset, length, false);
       
   677 
       
   678         try {
       
   679             synchronized (unwrapLock) {
       
   680                 return readNetRecord(netData, appData, offset, length);
       
   681             }
       
   682         } catch (SSLProtocolException spe) {
   141         } catch (SSLProtocolException spe) {
   683             // may be an unexpected handshake message
   142             // may be an unexpected handshake message
   684             fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
   143             conContext.fatal(Alert.UNEXPECTED_MESSAGE, spe);
   685             return null;  // make compiler happy
   144         } catch (IOException ioe) {
   686         } catch (Exception e) {
   145             conContext.fatal(Alert.INTERNAL_ERROR,
       
   146                 "problem wrapping app data", ioe);
       
   147         } catch (Exception ex) {     // including RuntimeException
       
   148             conContext.fatal(Alert.INTERNAL_ERROR,
       
   149                 "Fail to wrap application data", ex);
       
   150         }
       
   151 
       
   152         return null;    // make compiler happy
       
   153     }
       
   154 
       
   155     private SSLEngineResult writeRecord(
       
   156         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
       
   157         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
       
   158 
       
   159         if (isOutboundDone()) {
       
   160             return new SSLEngineResult(
       
   161                     Status.CLOSED, getHandshakeStatus(), 0, 0);
       
   162         }
       
   163 
       
   164         HandshakeContext hc = conContext.handshakeContext;
       
   165         HandshakeStatus hsStatus = null;
       
   166         if (!conContext.isNegotiated) {
       
   167             conContext.kickstart();
       
   168 
       
   169             hsStatus = getHandshakeStatus();
       
   170             if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
       
   171                 /*
       
   172                  * For DTLS, if the handshake state is
       
   173                  * HandshakeStatus.NEED_UNWRAP, a call to SSLEngine.wrap()
       
   174                  * means that the previous handshake packets (if delivered)
       
   175                  * get lost, and need retransmit the handshake messages.
       
   176                  */
       
   177                 if (!sslContext.isDTLS() || hc == null ||
       
   178                         !hc.sslConfig.enableRetransmissions ||
       
   179                         conContext.outputRecord.firstMessage) {
       
   180 
       
   181                     return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
       
   182                 }   // otherwise, need retransmission
       
   183             }
       
   184         }
       
   185 
       
   186         if (hsStatus == null) {
       
   187             hsStatus = getHandshakeStatus();
       
   188         }
       
   189 
       
   190         /*
       
   191          * If we have a task outstanding, this *MUST* be done before
       
   192          * doing any more wrapping, because we could be in the middle
       
   193          * of receiving a handshake message, for example, a finished
       
   194          * message which would change the ciphers.
       
   195          */
       
   196         if (hsStatus == HandshakeStatus.NEED_TASK) {
       
   197             return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
       
   198         }
       
   199 
       
   200         int dstsRemains = 0;
       
   201         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
       
   202             dstsRemains += dsts[i].remaining();
       
   203         }
       
   204 
       
   205         // Check destination buffer size.
       
   206         //
       
   207         // We can be smarter about using smaller buffer sizes later.  For
       
   208         // now, force it to be large enough to handle any valid record.
       
   209         if (dstsRemains < conContext.conSession.getPacketBufferSize()) {
       
   210             return new SSLEngineResult(
       
   211                 Status.BUFFER_OVERFLOW, getHandshakeStatus(), 0, 0);
       
   212         }
       
   213 
       
   214         int srcsRemains = 0;
       
   215         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
       
   216             srcsRemains += srcs[i].remaining();
       
   217         }
       
   218 
       
   219         Ciphertext ciphertext = null;
       
   220         try {
       
   221             // Acquire the buffered to-be-delivered records or retransmissions.
       
   222             //
       
   223             // May have buffered records, or need retransmission if handshaking.
       
   224             if (!conContext.outputRecord.isEmpty() || (hc != null &&
       
   225                     hc.sslConfig.enableRetransmissions &&
       
   226                     hc.sslContext.isDTLS() &&
       
   227                     hsStatus == HandshakeStatus.NEED_UNWRAP)) {
       
   228                 ciphertext = encode(null, 0, 0,
       
   229                         dsts, dstsOffset, dstsLength);
       
   230             }
       
   231 
       
   232             if (ciphertext == null && srcsRemains != 0) {
       
   233                 ciphertext = encode(srcs, srcsOffset, srcsLength,
       
   234                         dsts, dstsOffset, dstsLength);
       
   235             }
       
   236         } catch (IOException ioe) {
       
   237             if (ioe instanceof SSLException) {
       
   238                 throw ioe;
       
   239             } else {
       
   240                 throw new SSLException("Write problems", ioe);
       
   241             }
       
   242         }
       
   243 
       
   244         /*
       
   245          * Check for status.
       
   246          */
       
   247         Status status = (isOutboundDone() ? Status.CLOSED : Status.OK);
       
   248         if (ciphertext != null && ciphertext.handshakeStatus != null) {
       
   249             hsStatus = ciphertext.handshakeStatus;
       
   250         } else {
       
   251             hsStatus = getHandshakeStatus();
       
   252         }
       
   253 
       
   254         int deltaSrcs = srcsRemains;
       
   255         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
       
   256             deltaSrcs -= srcs[i].remaining();
       
   257         }
       
   258 
       
   259         int deltaDsts = dstsRemains;
       
   260         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
       
   261             deltaDsts -= dsts[i].remaining();
       
   262         }
       
   263 
       
   264         return new SSLEngineResult(status, hsStatus, deltaSrcs, deltaDsts,
       
   265                 ciphertext != null ? ciphertext.recordSN : -1L);
       
   266     }
       
   267 
       
   268     private Ciphertext encode(
       
   269         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
       
   270         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
       
   271 
       
   272         Ciphertext ciphertext = null;
       
   273         try {
       
   274             ciphertext = conContext.outputRecord.encode(
       
   275                 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
       
   276         } catch (SSLHandshakeException she) {
       
   277             // may be record sequence number overflow
       
   278             conContext.fatal(Alert.HANDSHAKE_FAILURE, she);
       
   279         } catch (IOException e) {
       
   280             conContext.fatal(Alert.UNEXPECTED_MESSAGE, e);
       
   281         }
       
   282 
       
   283         if (ciphertext == null) {
       
   284             return Ciphertext.CIPHERTEXT_NULL;
       
   285         }
       
   286 
       
   287         // Is the handshake completed?
       
   288         boolean needRetransmission =
       
   289                 conContext.sslContext.isDTLS() &&
       
   290                 conContext.handshakeContext != null &&
       
   291                 conContext.handshakeContext.sslConfig.enableRetransmissions;
       
   292         HandshakeStatus hsStatus =
       
   293                 tryToFinishHandshake(ciphertext.contentType);
       
   294         if (needRetransmission &&
       
   295                 hsStatus == HandshakeStatus.FINISHED &&
       
   296                 conContext.sslContext.isDTLS() &&
       
   297                 ciphertext.handshakeType == SSLHandshake.FINISHED.id) {
       
   298             // Retransmit the last flight for DTLS.
       
   299             //
       
   300             // The application data transactions may begin immediately
       
   301             // after the last flight.  If the last flight get lost, the
       
   302             // application data may be discarded accordingly.  As could
       
   303             // be an issue for some applications.  This impact can be
       
   304             // mitigated by sending the last fligth twice.
       
   305             if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) {
       
   306                 SSLLogger.finest("retransmit the last flight messages");
       
   307             }
       
   308 
       
   309             conContext.outputRecord.launchRetransmission();
       
   310             hsStatus = HandshakeStatus.NEED_WRAP;
       
   311         }
       
   312 
       
   313         if (hsStatus == null) {
       
   314             hsStatus = conContext.getHandshakeStatus();
       
   315         }
       
   316 
       
   317         // Is the sequence number is nearly overflow?
       
   318         if (conContext.outputRecord.seqNumIsHuge()) {
       
   319             hsStatus = tryKeyUpdate(hsStatus);
       
   320         }
       
   321 
       
   322         // update context status
       
   323         ciphertext.handshakeStatus = hsStatus;
       
   324 
       
   325         return ciphertext;
       
   326     }
       
   327 
       
   328     private HandshakeStatus tryToFinishHandshake(byte contentType) {
       
   329         HandshakeStatus hsStatus = null;
       
   330         if ((contentType == ContentType.HANDSHAKE.id) &&
       
   331                 conContext.outputRecord.isEmpty()) {
       
   332             if (conContext.handshakeContext == null) {
       
   333                 hsStatus = HandshakeStatus.FINISHED;
       
   334             } else if (conContext.handshakeContext.handshakeFinished) {
       
   335                 hsStatus = conContext.finishHandshake();
       
   336             }
       
   337         }   // Otherwise, the followed call to getHSStatus() will help.
       
   338 
       
   339         return hsStatus;
       
   340     }
       
   341 
       
   342     /**
       
   343      * Try renegotiation or key update for sequence number wrap.
       
   344      *
       
   345      * Note that in order to maintain the handshake status properly, we check
       
   346      * the sequence number after the last record reading/writing process.  As
       
   347      * we request renegotiation or close the connection for wrapped sequence
       
   348      * number when there is enough sequence number space left to handle a few
       
   349      * more records, so the sequence number of the last record cannot be
       
   350      * wrapped.
       
   351      */
       
   352     private HandshakeStatus tryKeyUpdate(
       
   353             HandshakeStatus currentHandshakeStatus) throws IOException {
       
   354         // Don't bother to kickstart the renegotiation or key update when the
       
   355         // local is asking for it.
       
   356         if ((conContext.handshakeContext == null) &&
       
   357                 !conContext.isClosed() && !conContext.isBroken) {
       
   358             if (SSLLogger.isOn && SSLLogger.isOn("ssl")) {
       
   359                 SSLLogger.finest("key update to wrap sequence number");
       
   360             }
       
   361             conContext.keyUpdate();
       
   362             return conContext.getHandshakeStatus();
       
   363         }
       
   364 
       
   365         return currentHandshakeStatus;
       
   366     }
       
   367 
       
   368     private static void checkParams(
       
   369             ByteBuffer[] srcs, int srcsOffset, int srcsLength,
       
   370             ByteBuffer[] dsts, int dstsOffset, int dstsLength) {
       
   371 
       
   372         if ((srcs == null) || (dsts == null)) {
       
   373             throw new IllegalArgumentException(
       
   374                     "source or destination buffer is null");
       
   375         }
       
   376 
       
   377         if ((srcsOffset < 0) || (srcsLength < 0) ||
       
   378                 (srcsOffset > srcs.length - srcsLength)) {
       
   379             throw new IndexOutOfBoundsException(
       
   380                     "index out of bound of the source buffers");
       
   381         }
       
   382 
       
   383         if ((dstsOffset < 0) || (dstsLength < 0) ||
       
   384                 (dstsOffset > dsts.length - dstsLength)) {
       
   385             throw new IndexOutOfBoundsException(
       
   386                     "index out of bound of the destination buffers");
       
   387         }
       
   388 
       
   389         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
       
   390             if (srcs[i] == null) {
       
   391                 throw new IllegalArgumentException(
       
   392                         "source buffer[" + i + "] == null");
       
   393             }
       
   394         }
       
   395 
       
   396         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
       
   397             if (dsts[i] == null) {
       
   398                 throw new IllegalArgumentException(
       
   399                         "destination buffer[" + i + "] == null");
       
   400             }
       
   401 
       
   402             /*
       
   403              * Make sure the destination bufffers are writable.
       
   404              */
       
   405             if (dsts[i].isReadOnly()) {
       
   406                 throw new ReadOnlyBufferException();
       
   407             }
       
   408         }
       
   409     }
       
   410 
       
   411     @Override
       
   412     public synchronized SSLEngineResult unwrap(ByteBuffer src,
       
   413             ByteBuffer[] dsts, int offset, int length) throws SSLException {
       
   414         return unwrap(
       
   415                 new ByteBuffer[]{src}, 0, 1, dsts, offset, length);
       
   416     }
       
   417 
       
   418     // @Override
       
   419     public synchronized SSLEngineResult unwrap(
       
   420         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
       
   421         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws SSLException {
       
   422 
       
   423         if (conContext.isUnsureMode) {
       
   424             throw new IllegalStateException(
       
   425                     "Client/Server mode has not yet been set.");
       
   426         }
       
   427 
       
   428         // See if the handshaker needs to report back some SSLException.
       
   429         checkTaskThrown();
       
   430 
       
   431         // check parameters
       
   432         checkParams(srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
       
   433 
       
   434         try {
       
   435             return readRecord(
       
   436                 srcs, srcsOffset, srcsLength, dsts, dstsOffset, dstsLength);
       
   437         } catch (SSLProtocolException spe) {
       
   438             // may be an unexpected handshake message
       
   439             conContext.fatal(Alert.UNEXPECTED_MESSAGE,
       
   440                     spe.getMessage(), spe);
       
   441         } catch (IOException ioe) {
   687             /*
   442             /*
   688              * Don't reset position so it looks like we didn't
   443              * Don't reset position so it looks like we didn't
   689              * consume anything.  We did consume something, and it
   444              * consume anything.  We did consume something, and it
   690              * got us into this situation, so report that much back.
   445              * got us into this situation, so report that much back.
   691              * Our days of consuming are now over anyway.
   446              * Our days of consuming are now over anyway.
   692              */
   447              */
   693             fatal(Alerts.alert_internal_error,
   448             conContext.fatal(Alert.INTERNAL_ERROR,
   694                 "problem unwrapping net record", e);
   449                     "problem unwrapping net record", ioe);
   695             return null;  // make compiler happy
   450         } catch (Exception ex) {     // including RuntimeException
   696         }
   451             conContext.fatal(Alert.INTERNAL_ERROR,
   697     }
   452                 "Fail to unwrap network record", ex);
   698 
   453         }
   699     private static void checkEngineParas(ByteBuffer netData,
   454 
   700             ByteBuffer[] appData, int offset, int len, boolean isForWrap) {
   455         return null;    // make compiler happy
   701 
   456     }
   702         if ((netData == null) || (appData == null)) {
   457 
   703             throw new IllegalArgumentException("src/dst is null");
   458     private SSLEngineResult readRecord(
   704         }
   459         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
   705 
   460         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
   706         if ((offset < 0) || (len < 0) || (offset > appData.length - len)) {
       
   707             throw new IndexOutOfBoundsException();
       
   708         }
       
   709 
       
   710         /*
       
   711          * If wrapping, make sure the destination bufffer is writable.
       
   712          */
       
   713         if (isForWrap && netData.isReadOnly()) {
       
   714             throw new ReadOnlyBufferException();
       
   715         }
       
   716 
       
   717         for (int i = offset; i < offset + len; i++) {
       
   718             if (appData[i] == null) {
       
   719                 throw new IllegalArgumentException(
       
   720                         "appData[" + i + "] == null");
       
   721             }
       
   722 
       
   723             /*
       
   724              * If unwrapping, make sure the destination bufffers are writable.
       
   725              */
       
   726             if (!isForWrap && appData[i].isReadOnly()) {
       
   727                 throw new ReadOnlyBufferException();
       
   728             }
       
   729         }
       
   730     }
       
   731 
       
   732     /*
       
   733      * Makes additional checks for unwrap, but this time more
       
   734      * specific to this packet and the current state of the machine.
       
   735      */
       
   736     private SSLEngineResult readNetRecord(ByteBuffer netData,
       
   737             ByteBuffer[] appData, int offset, int length) throws IOException {
       
   738 
       
   739         Status status = null;
       
   740         HandshakeStatus hsStatus = null;
       
   741 
       
   742         /*
       
   743          * See if the handshaker needs to report back some SSLException.
       
   744          */
       
   745         checkTaskThrown();
       
   746 
   461 
   747         /*
   462         /*
   748          * Check if we are closing/closed.
   463          * Check if we are closing/closed.
   749          */
   464          */
   750         if (isInboundDone()) {
   465         if (isInboundDone()) {
   751             return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
   466             return new SSLEngineResult(
   752         }
   467                     Status.CLOSED, getHandshakeStatus(), 0, 0);
   753 
   468         }
   754         /*
   469 
   755          * If we're still in cs_HANDSHAKE, make sure it's been
   470         HandshakeStatus hsStatus = null;
   756          * started.
   471         if (!conContext.isNegotiated) {
   757          */
   472             conContext.kickstart();
   758         synchronized (this) {
   473 
   759             if ((connectionState == cs_HANDSHAKE) ||
   474             /*
   760                     (connectionState == cs_START)) {
   475              * If there's still outbound data to flush, we
   761                 kickstartHandshake();
   476              * can return without trying to unwrap anything.
   762 
   477              */
   763                 /*
   478             hsStatus = getHandshakeStatus();
   764                  * If there's still outbound data to flush, we
   479             if (hsStatus == HandshakeStatus.NEED_WRAP) {
   765                  * can return without trying to unwrap anything.
   480                 return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
   766                  */
   481             }
   767                 hsStatus = getHSStatus(null);
   482         }
   768 
   483 
   769                 if (hsStatus == HandshakeStatus.NEED_WRAP) {
       
   770                     return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
       
   771                 }
       
   772             }
       
   773         }
       
   774 
       
   775         /*
       
   776          * Grab a copy of this if it doesn't already exist,
       
   777          * and we can use it several places before anything major
       
   778          * happens on this side.  Races aren't critical
       
   779          * here.
       
   780          */
       
   781         if (hsStatus == null) {
   484         if (hsStatus == null) {
   782             hsStatus = getHSStatus(null);
   485             hsStatus = getHandshakeStatus();
   783         }
   486         }
   784 
   487 
   785         /*
   488         /*
   786          * If we have a task outstanding, this *MUST* be done before
   489          * If we have a task outstanding, this *MUST* be done before
   787          * doing any more unwrapping, because we could be in the middle
   490          * doing any more unwrapping, because we could be in the middle
   793         }
   496         }
   794 
   497 
   795         if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
   498         if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) {
   796             Plaintext plainText = null;
   499             Plaintext plainText = null;
   797             try {
   500             try {
   798                 plainText = readRecord(null, null, 0, 0);
   501                 plainText = decode(null, 0, 0,
   799             } catch (SSLException e) {
   502                         dsts, dstsOffset, dstsLength);
   800                 throw e;
   503             } catch (IOException ioe) {
   801             } catch (IOException e) {
   504                 if (ioe instanceof SSLException) {
   802                 throw new SSLException("readRecord", e);
   505                     throw ioe;
   803             }
   506                 } else {
   804 
   507                     throw new SSLException("readRecord", ioe);
   805             status = (isInboundDone() ? Status.CLOSED : Status.OK);
   508                 }
   806             hsStatus = getHSStatus(plainText.handshakeStatus);
   509             }
       
   510 
       
   511             Status status = (isInboundDone() ? Status.CLOSED : Status.OK);
       
   512             if (plainText.handshakeStatus != null) {
       
   513                 hsStatus = plainText.handshakeStatus;
       
   514             } else {
       
   515                 hsStatus = getHandshakeStatus();
       
   516             }
   807 
   517 
   808             return new SSLEngineResult(
   518             return new SSLEngineResult(
   809                     status, hsStatus, 0, 0, plainText.recordSN);
   519                     status, hsStatus, 0, 0, plainText.recordSN);
       
   520         }
       
   521 
       
   522         int srcsRemains = 0;
       
   523         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
       
   524             srcsRemains += srcs[i].remaining();
       
   525         }
       
   526 
       
   527         if (srcsRemains == 0) {
       
   528             return new SSLEngineResult(Status.OK, getHandshakeStatus(), 0, 0);
   810         }
   529         }
   811 
   530 
   812         /*
   531         /*
   813          * Check the packet to make sure enough is here.
   532          * Check the packet to make sure enough is here.
   814          * This will also indirectly check for 0 len packets.
   533          * This will also indirectly check for 0 len packets.
   815          */
   534          */
   816         int packetLen = 0;
   535         int packetLen = 0;
   817         try {
   536         try {
   818             packetLen = inputRecord.bytesInCompletePacket(netData);
   537             packetLen = conContext.inputRecord.bytesInCompletePacket(
       
   538                     srcs, srcsOffset, srcsLength);
   819         } catch (SSLException ssle) {
   539         } catch (SSLException ssle) {
   820             // Need to discard invalid records for DTLS protocols.
   540             // Need to discard invalid records for DTLS protocols.
   821             if (isDTLS) {
   541             if (sslContext.isDTLS()) {
   822                 if (debug != null && Debug.isOn("ssl")) {
   542                 if (SSLLogger.isOn && SSLLogger.isOn("ssl,verbose")) {
   823                     System.out.println(
   543                     SSLLogger.finest("Discard invalid DTLS records", ssle);
   824                         Thread.currentThread().getName() +
       
   825                         " discard invalid record: " + ssle);
       
   826                 }
   544                 }
   827 
   545 
   828                 // invalid, discard the entire data [section 4.1.2.7, RFC 6347]
   546                 // invalid, discard the entire data [section 4.1.2.7, RFC 6347]
   829                 int deltaNet = netData.remaining();
   547                 // TODO
   830                 netData.position(netData.limit());
   548                 int deltaNet = 0;
   831 
   549                 // int deltaNet = netData.remaining();
   832                 status = (isInboundDone() ? Status.CLOSED : Status.OK);
   550                 // netData.position(netData.limit());
   833                 hsStatus = getHSStatus(hsStatus);
   551 
       
   552                 Status status = (isInboundDone() ? Status.CLOSED : Status.OK);
       
   553                 if (hsStatus == null) {
       
   554                     hsStatus = getHandshakeStatus();
       
   555                 }
   834 
   556 
   835                 return new SSLEngineResult(status, hsStatus, deltaNet, 0, -1L);
   557                 return new SSLEngineResult(status, hsStatus, deltaNet, 0, -1L);
   836             } else {
   558             } else {
   837                 throw ssle;
   559                 throw ssle;
   838             }
   560             }
   839         }
   561         }
   840 
   562 
   841         // Is this packet bigger than SSL/TLS normally allows?
   563         // Is this packet bigger than SSL/TLS normally allows?
   842         if (packetLen > sess.getPacketBufferSize()) {
   564         if (packetLen > conContext.conSession.getPacketBufferSize()) {
   843             int largestRecordSize = isDTLS ?
   565             int largestRecordSize = sslContext.isDTLS() ?
   844                     DTLSRecord.maxRecordSize : SSLRecord.maxLargeRecordSize;
   566                     DTLSRecord.maxRecordSize : SSLRecord.maxLargeRecordSize;
   845             if ((packetLen <= largestRecordSize) && !isDTLS) {
   567             if ((packetLen <= largestRecordSize) && !sslContext.isDTLS()) {
   846                 // Expand the expected maximum packet/application buffer
   568                 // Expand the expected maximum packet/application buffer
   847                 // sizes.
   569                 // sizes.
   848                 //
   570                 //
   849                 // Only apply to SSL/TLS protocols.
   571                 // Only apply to SSL/TLS protocols.
   850 
   572 
   851                 // Old behavior: shall we honor the System Property
   573                 // Old behavior: shall we honor the System Property
   852                 // "jsse.SSLEngine.acceptLargeFragments" if it is "false"?
   574                 // "jsse.SSLEngine.acceptLargeFragments" if it is "false"?
   853                 sess.expandBufferSizes();
   575                 conContext.conSession.expandBufferSizes();
   854             }
   576             }
   855 
   577 
   856             // check the packet again
   578             // check the packet again
   857             largestRecordSize = sess.getPacketBufferSize();
   579             largestRecordSize = conContext.conSession.getPacketBufferSize();
   858             if (packetLen > largestRecordSize) {
   580             if (packetLen > largestRecordSize) {
   859                 throw new SSLProtocolException(
   581                 throw new SSLProtocolException(
   860                         "Input record too big: max = " +
   582                         "Input record too big: max = " +
   861                         largestRecordSize + " len = " + packetLen);
   583                         largestRecordSize + " len = " + packetLen);
   862             }
   584             }
   863         }
       
   864 
       
   865         int netPos = netData.position();
       
   866         int appRemains = 0;
       
   867         for (int i = offset; i < offset + length; i++) {
       
   868             if (appData[i] == null) {
       
   869                 throw new IllegalArgumentException(
       
   870                         "appData[" + i + "] == null");
       
   871             }
       
   872             appRemains += appData[i].remaining();
       
   873         }
   585         }
   874 
   586 
   875         /*
   587         /*
   876          * Check for OVERFLOW.
   588          * Check for OVERFLOW.
   877          *
   589          *
   878          * Delay enforcing the application buffer free space requirement
   590          * Delay enforcing the application buffer free space requirement
   879          * until after the initial handshaking.
   591          * until after the initial handshaking.
   880          */
   592          */
   881         // synchronize connectionState?
   593         int dstsRemains = 0;
   882         if ((connectionState == cs_DATA) ||
   594         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
   883                 (connectionState == cs_RENEGOTIATE)) {
   595             dstsRemains += dsts[i].remaining();
   884 
   596         }
   885             int FragLen = inputRecord.estimateFragmentSize(packetLen);
   597 
   886             if (FragLen > appRemains) {
   598         if (conContext.isNegotiated) {
       
   599             int FragLen =
       
   600                     conContext.inputRecord.estimateFragmentSize(packetLen);
       
   601             if (FragLen > dstsRemains) {
   887                 return new SSLEngineResult(
   602                 return new SSLEngineResult(
   888                         Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
   603                         Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
   889             }
   604             }
   890         }
   605         }
   891 
   606 
   892         // check for UNDERFLOW.
   607         // check for UNDERFLOW.
   893         if ((packetLen == -1) || (netData.remaining() < packetLen)) {
   608         if ((packetLen == -1) || (srcsRemains < packetLen)) {
   894             return new SSLEngineResult(Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
   609             return new SSLEngineResult(Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
   895         }
   610         }
   896 
   611 
   897         /*
   612         /*
   898          * We're now ready to actually do the read.
   613          * We're now ready to actually do the read.
   899          */
   614          */
   900         Plaintext plainText = null;
   615         Plaintext plainText = null;
   901         try {
   616         try {
   902             plainText = readRecord(netData, appData, offset, length);
   617             plainText = decode(srcs, srcsOffset, srcsLength,
   903         } catch (SSLException e) {
   618                             dsts, dstsOffset, dstsLength);
   904             throw e;
   619         } catch (IOException ioe) {
   905         } catch (IOException e) {
   620             if (ioe instanceof SSLException) {
   906             throw new SSLException("readRecord", e);
   621                 throw ioe;
       
   622             } else {
       
   623                 throw new SSLException("readRecord", ioe);
       
   624             }
   907         }
   625         }
   908 
   626 
   909         /*
   627         /*
   910          * Check the various condition that we could be reporting.
   628          * Check the various condition that we could be reporting.
   911          *
   629          *
   914          * during the read process.  We'll return the current
   632          * during the read process.  We'll return the current
   915          * status, which is more representative of the current state.
   633          * status, which is more representative of the current state.
   916          *
   634          *
   917          * status above should cover:  FINISHED, NEED_TASK
   635          * status above should cover:  FINISHED, NEED_TASK
   918          */
   636          */
   919         status = (isInboundDone() ? Status.CLOSED : Status.OK);
   637         Status status = (isInboundDone() ? Status.CLOSED : Status.OK);
   920         hsStatus = getHSStatus(plainText.handshakeStatus);
   638         if (plainText.handshakeStatus != null) {
   921 
   639             hsStatus = plainText.handshakeStatus;
   922         int deltaNet = netData.position() - netPos;
   640         } else {
   923         int deltaApp = appRemains;
   641             hsStatus = getHandshakeStatus();
   924         for (int i = offset; i < offset + length; i++) {
   642         }
   925             deltaApp -= appData[i].remaining();
   643 
       
   644         int deltaNet = srcsRemains;
       
   645         for (int i = srcsOffset; i < srcsOffset + srcsLength; i++) {
       
   646             deltaNet -= srcs[i].remaining();
       
   647         }
       
   648 
       
   649         int deltaApp = dstsRemains;
       
   650         for (int i = dstsOffset; i < dstsOffset + dstsLength; i++) {
       
   651             deltaApp -= dsts[i].remaining();
   926         }
   652         }
   927 
   653 
   928         return new SSLEngineResult(
   654         return new SSLEngineResult(
   929                 status, hsStatus, deltaNet, deltaApp, plainText.recordSN);
   655                 status, hsStatus, deltaNet, deltaApp, plainText.recordSN);
   930     }
   656     }
   931 
   657 
   932     // the caller have synchronized readLock
   658     private Plaintext decode(
   933     void expectingFinishFlight() {
   659         ByteBuffer[] srcs, int srcsOffset, int srcsLength,
   934         inputRecord.expectingFinishFlight();
   660         ByteBuffer[] dsts, int dstsOffset, int dstsLength) throws IOException {
   935     }
   661 
   936 
   662         Plaintext pt = SSLTransport.decode(conContext,
   937     /*
   663                             srcs, srcsOffset, srcsLength,
   938      * Actually do the read record processing.
   664                             dsts, dstsOffset, dstsLength);
   939      *
   665 
   940      * Returns a Status if it can make specific determinations
   666         // Is the handshake completed?
   941      * of the engine state.  In particular, we need to signal
   667         if (pt != Plaintext.PLAINTEXT_NULL) {
   942      * that a handshake just completed.
   668             HandshakeStatus hsStatus = tryToFinishHandshake(pt.contentType);
   943      *
   669             if (hsStatus == null) {
   944      * It would be nice to be symmetrical with the write side and move
   670                 pt.handshakeStatus = conContext.getHandshakeStatus();
   945      * the majority of this to SSLInputRecord, but there's too much
   671             } else {
   946      * SSLEngine state to do that cleanly.  It must still live here.
   672                 pt.handshakeStatus = hsStatus;
       
   673             }
       
   674 
       
   675             // Is the sequence number is nearly overflow?
       
   676             if (conContext.inputRecord.seqNumIsHuge()) {
       
   677                 pt.handshakeStatus =
       
   678                         tryKeyUpdate(pt.handshakeStatus);
       
   679             }
       
   680         }
       
   681 
       
   682         return pt;
       
   683     }
       
   684 
       
   685     @Override
       
   686     public synchronized Runnable getDelegatedTask() {
       
   687         if (conContext.handshakeContext != null &&
       
   688                 !conContext.handshakeContext.taskDelegated &&
       
   689                 !conContext.handshakeContext.delegatedActions.isEmpty()) {
       
   690             conContext.handshakeContext.taskDelegated = true;
       
   691             return new DelegatedTask(this);
       
   692         }
       
   693 
       
   694         return null;
       
   695     }
       
   696 
       
   697     @Override
       
   698     public synchronized void closeInbound() throws SSLException {
       
   699         conContext.closeInbound();
       
   700     }
       
   701 
       
   702     @Override
       
   703     public synchronized boolean isInboundDone() {
       
   704         return conContext.isInboundDone();
       
   705     }
       
   706 
       
   707     @Override
       
   708     public synchronized void closeOutbound() {
       
   709         conContext.closeOutbound();
       
   710     }
       
   711 
       
   712     @Override
       
   713     public synchronized boolean isOutboundDone() {
       
   714         return conContext.isOutboundDone();
       
   715     }
       
   716 
       
   717     @Override
       
   718     public String[] getSupportedCipherSuites() {
       
   719         return CipherSuite.namesOf(sslContext.getSupportedCipherSuites());
       
   720     }
       
   721 
       
   722     @Override
       
   723     public synchronized String[] getEnabledCipherSuites() {
       
   724         return CipherSuite.namesOf(conContext.sslConfig.enabledCipherSuites);
       
   725     }
       
   726 
       
   727     @Override
       
   728     public synchronized void setEnabledCipherSuites(String[] suites) {
       
   729         if (suites == null) {
       
   730             throw new IllegalArgumentException("CipherSuites cannot be null");
       
   731         }
       
   732 
       
   733         conContext.sslConfig.enabledCipherSuites =
       
   734                 CipherSuite.validValuesOf(suites);
       
   735     }
       
   736 
       
   737     @Override
       
   738     public String[] getSupportedProtocols() {
       
   739         return ProtocolVersion.toStringArray(
       
   740                 sslContext.getSuportedProtocolVersions());
       
   741     }
       
   742 
       
   743     @Override
       
   744     public synchronized String[] getEnabledProtocols() {
       
   745         return ProtocolVersion.toStringArray(
       
   746                 conContext.sslConfig.enabledProtocols);
       
   747     }
       
   748 
       
   749     @Override
       
   750     public synchronized void setEnabledProtocols(String[] protocols) {
       
   751         if (protocols == null) {
       
   752             throw new IllegalArgumentException("Protocols cannot be null");
       
   753         }
       
   754 
       
   755         conContext.sslConfig.enabledProtocols =
       
   756                 ProtocolVersion.namesOf(protocols);
       
   757     }
       
   758 
       
   759     @Override
       
   760     public synchronized SSLSession getSession() {
       
   761         return conContext.conSession;
       
   762     }
       
   763 
       
   764     @Override
       
   765     public synchronized SSLSession getHandshakeSession() {
       
   766         return conContext.handshakeContext == null ?
       
   767                 null : conContext.handshakeContext.handshakeSession;
       
   768     }
       
   769 
       
   770     @Override
       
   771     public synchronized SSLEngineResult.HandshakeStatus getHandshakeStatus() {
       
   772         return conContext.getHandshakeStatus();
       
   773     }
       
   774 
       
   775     @Override
       
   776     public synchronized void setUseClientMode(boolean mode) {
       
   777         conContext.setUseClientMode(mode);
       
   778     }
       
   779 
       
   780     @Override
       
   781     public synchronized boolean getUseClientMode() {
       
   782         return conContext.sslConfig.isClientMode;
       
   783     }
       
   784 
       
   785     @Override
       
   786     public synchronized void setNeedClientAuth(boolean need) {
       
   787         conContext.sslConfig.clientAuthType =
       
   788                 (need ? ClientAuthType.CLIENT_AUTH_REQUIRED :
       
   789                         ClientAuthType.CLIENT_AUTH_NONE);
       
   790     }
       
   791 
       
   792     @Override
       
   793     public synchronized boolean getNeedClientAuth() {
       
   794         return (conContext.sslConfig.clientAuthType ==
       
   795                         ClientAuthType.CLIENT_AUTH_REQUIRED);
       
   796     }
       
   797 
       
   798     @Override
       
   799     public synchronized void setWantClientAuth(boolean want) {
       
   800         conContext.sslConfig.clientAuthType =
       
   801                 (want ? ClientAuthType.CLIENT_AUTH_REQUESTED :
       
   802                         ClientAuthType.CLIENT_AUTH_NONE);
       
   803     }
       
   804 
       
   805     @Override
       
   806     public synchronized boolean getWantClientAuth() {
       
   807         return (conContext.sslConfig.clientAuthType ==
       
   808                         ClientAuthType.CLIENT_AUTH_REQUESTED);
       
   809     }
       
   810 
       
   811     @Override
       
   812     public synchronized void setEnableSessionCreation(boolean flag) {
       
   813         conContext.sslConfig.enableSessionCreation = flag;
       
   814     }
       
   815 
       
   816     @Override
       
   817     public synchronized boolean getEnableSessionCreation() {
       
   818         return conContext.sslConfig.enableSessionCreation;
       
   819     }
       
   820 
       
   821     @Override
       
   822     public synchronized SSLParameters getSSLParameters() {
       
   823         return conContext.sslConfig.getSSLParameters();
       
   824     }
       
   825 
       
   826     @Override
       
   827     public synchronized void setSSLParameters(SSLParameters params) {
       
   828         conContext.sslConfig.setSSLParameters(params);
       
   829 
       
   830         if (conContext.sslConfig.maximumPacketSize != 0) {
       
   831             conContext.outputRecord.changePacketSize(
       
   832                     conContext.sslConfig.maximumPacketSize);
       
   833         }
       
   834     }
       
   835 
       
   836     @Override
       
   837     public synchronized String getApplicationProtocol() {
       
   838         return conContext.applicationProtocol;
       
   839     }
       
   840 
       
   841     @Override
       
   842     public synchronized String getHandshakeApplicationProtocol() {
       
   843         return conContext.handshakeContext == null ?
       
   844                 null : conContext.handshakeContext.applicationProtocol;
       
   845     }
       
   846 
       
   847     @Override
       
   848     public synchronized void setHandshakeApplicationProtocolSelector(
       
   849             BiFunction<SSLEngine, List<String>, String> selector) {
       
   850         conContext.sslConfig.engineAPSelector = selector;
       
   851     }
       
   852 
       
   853     @Override
       
   854     public synchronized BiFunction<SSLEngine, List<String>, String>
       
   855             getHandshakeApplicationProtocolSelector() {
       
   856         return conContext.sslConfig.engineAPSelector;
       
   857     }
       
   858 
       
   859     @Override
       
   860     public boolean useDelegatedTask() {
       
   861         return true;
       
   862     }
       
   863 
       
   864     private synchronized void checkTaskThrown() throws SSLException {
       
   865         HandshakeContext hc = conContext.handshakeContext;
       
   866         if (hc != null && hc.delegatedThrown != null) {
       
   867             try {
       
   868                 throw getTaskThrown(hc.delegatedThrown);
       
   869             } finally {
       
   870                 hc.delegatedThrown = null;
       
   871             }
       
   872         }
       
   873 
       
   874         if (conContext.isBroken && conContext.closeReason != null) {
       
   875             throw getTaskThrown(conContext.closeReason);
       
   876         }
       
   877     }
       
   878 
       
   879     private static SSLException getTaskThrown(Exception taskThrown) {
       
   880         String msg = taskThrown.getMessage();
       
   881 
       
   882         if (msg == null) {
       
   883             msg = "Delegated task threw Exception or Error";
       
   884         }
       
   885 
       
   886         if (taskThrown instanceof RuntimeException) {
       
   887             throw new RuntimeException(msg, taskThrown);
       
   888         } else if (taskThrown instanceof SSLHandshakeException) {
       
   889             return (SSLHandshakeException)
       
   890                 new SSLHandshakeException(msg).initCause(taskThrown);
       
   891         } else if (taskThrown instanceof SSLKeyException) {
       
   892             return (SSLKeyException)
       
   893                 new SSLKeyException(msg).initCause(taskThrown);
       
   894         } else if (taskThrown instanceof SSLPeerUnverifiedException) {
       
   895             return (SSLPeerUnverifiedException)
       
   896                 new SSLPeerUnverifiedException(msg).initCause(taskThrown);
       
   897         } else if (taskThrown instanceof SSLProtocolException) {
       
   898             return (SSLProtocolException)
       
   899                 new SSLProtocolException(msg).initCause(taskThrown);
       
   900         } else if (taskThrown instanceof SSLException) {
       
   901             return (SSLException)taskThrown;
       
   902         } else {
       
   903             return new SSLException(msg, taskThrown);
       
   904         }
       
   905     }
       
   906 
       
   907     /**
       
   908      * Implement a simple task delegator.
   947      */
   909      */
   948     private Plaintext readRecord(ByteBuffer netData,
   910     private static class DelegatedTask implements Runnable {
   949             ByteBuffer[] appData, int offset, int length) throws IOException {
   911         private final SSLEngineImpl engine;
   950 
   912 
   951         /*
   913         DelegatedTask(SSLEngineImpl engineInstance) {
   952          * The various operations will return new sliced BB's,
   914             this.engine = engineInstance;
   953          * this will avoid having to worry about positions and
   915         }
   954          * limits in the netBB.
   916 
   955          */
   917         @Override
   956         Plaintext plainText = null;
   918         public void run() {
   957 
   919             synchronized (engine) {
   958         if (getConnectionState() == cs_ERROR) {
   920                 HandshakeContext hc = engine.conContext.handshakeContext;
   959             return Plaintext.PLAINTEXT_NULL;
   921                 if (hc == null || hc.delegatedActions.isEmpty()) {
   960         }
   922                     return;
   961 
       
   962         /*
       
   963          * Read a record ... maybe emitting an alert if we get a
       
   964          * comprehensible but unsupported "hello" message during
       
   965          * format checking (e.g. V2).
       
   966          */
       
   967         try {
       
   968             if (isDTLS) {
       
   969                 // Don't process the incoming record until all of the
       
   970                 // buffered records get handled.
       
   971                 plainText = inputRecord.acquirePlaintext();
       
   972             }
       
   973 
       
   974             if ((!isDTLS || plainText == null) && netData != null) {
       
   975                 plainText = inputRecord.decode(netData);
       
   976             }
       
   977         } catch (UnsupportedOperationException unsoe) {         // SSLv2Hello
       
   978             // Hack code to deliver SSLv2 error message for SSL/TLS connections.
       
   979             if (!isDTLS) {
       
   980                 outputRecord.encodeV2NoCipher();
       
   981             }
       
   982 
       
   983             fatal(Alerts.alert_unexpected_message, unsoe);
       
   984         } catch (BadPaddingException e) {
       
   985             /*
       
   986              * The basic SSLv3 record protection involves (optional)
       
   987              * encryption for privacy, and an integrity check ensuring
       
   988              * data origin authentication.  We do them both here, and
       
   989              * throw a fatal alert if the integrity check fails.
       
   990              */
       
   991             byte alertType = (connectionState != cs_DATA) ?
       
   992                     Alerts.alert_handshake_failure :
       
   993                     Alerts.alert_bad_record_mac;
       
   994             fatal(alertType, e.getMessage(), e);
       
   995         } catch (SSLHandshakeException she) {
       
   996             // may be record sequence number overflow
       
   997             fatal(Alerts.alert_handshake_failure, she);
       
   998         } catch (IOException ioe) {
       
   999             fatal(Alerts.alert_unexpected_message, ioe);
       
  1000         }
       
  1001 
       
  1002         // plainText should never be null for TLS protocols
       
  1003         HandshakeStatus hsStatus = null;
       
  1004         if (plainText == Plaintext.PLAINTEXT_NULL) {
       
  1005             // Only happens for DTLS protocols.
       
  1006             //
       
  1007             // Received a retransmitted flight, and need to retransmit the
       
  1008             // previous delivered handshake flight messages.
       
  1009             if (enableRetransmissions) {
       
  1010                 if (debug != null && Debug.isOn("verbose")) {
       
  1011                     Debug.log(
       
  1012                         "Retransmit the previous handshake flight messages.");
       
  1013                 }
   923                 }
  1014 
   924 
  1015                 synchronized (this) {
   925                 try {
  1016                     outputRecord.launchRetransmission();
   926                     AccessController.doPrivileged(
  1017                 }
   927                             new DelegatedAction(hc), engine.conContext.acc);
  1018             }   // Otherwise, discard the retransmitted flight.
   928                 } catch (PrivilegedActionException pae) {
  1019         } else if (!isDTLS || plainText != null) {
   929                     // Get the handshake context again in case the
  1020             hsStatus = processInputRecord(plainText, appData, offset, length);
   930                     // handshaking has completed.
  1021         }
   931                     hc = engine.conContext.handshakeContext;
  1022 
   932                     if (hc != null) {
  1023         if (hsStatus == null) {
   933                         hc.delegatedThrown = pae.getException();
  1024             hsStatus = getHSStatus(null);
   934                     } else if (engine.conContext.closeReason != null) {
  1025         }
   935                         engine.conContext.closeReason =
  1026 
   936                                 getTaskThrown(pae.getException());
  1027         if (plainText == null) {
   937                     }
  1028             plainText = Plaintext.PLAINTEXT_NULL;
   938                 } catch (RuntimeException rte) {
  1029         }
   939                     // Get the handshake context again in case the
  1030         plainText.handshakeStatus = hsStatus;
   940                     // handshaking has completed.
  1031 
   941                     hc = engine.conContext.handshakeContext;
  1032         return plainText;
   942                     if (hc != null) {
  1033     }
   943                         hc.delegatedThrown = rte;
  1034 
   944                     } else if (engine.conContext.closeReason != null) {
  1035     /*
   945                         engine.conContext.closeReason = rte;
  1036      * Process the record.
       
  1037      */
       
  1038     private synchronized HandshakeStatus processInputRecord(
       
  1039             Plaintext plainText,
       
  1040             ByteBuffer[] appData, int offset, int length) throws IOException {
       
  1041 
       
  1042         HandshakeStatus hsStatus = null;
       
  1043         switch (plainText.contentType) {
       
  1044             case Record.ct_handshake:
       
  1045                 /*
       
  1046                  * Handshake messages always go to a pending session
       
  1047                  * handshaker ... if there isn't one, create one.  This
       
  1048                  * must work asynchronously, for renegotiation.
       
  1049                  *
       
  1050                  * NOTE that handshaking will either resume a session
       
  1051                  * which was in the cache (and which might have other
       
  1052                  * connections in it already), or else will start a new
       
  1053                  * session (new keys exchanged) with just this connection
       
  1054                  * in it.
       
  1055                  */
       
  1056                 initHandshaker();
       
  1057                 if (!handshaker.activated()) {
       
  1058                     // prior to handshaking, activate the handshake
       
  1059                     if (connectionState == cs_RENEGOTIATE) {
       
  1060                         // don't use SSLv2Hello when renegotiating
       
  1061                         handshaker.activate(protocolVersion);
       
  1062                     } else {
       
  1063                         handshaker.activate(null);
       
  1064                     }
   946                     }
  1065                 }
   947                 }
  1066 
   948 
  1067                 /*
   949                 // Get the handshake context again in case the
  1068                  * process the handshake record ... may contain just
   950                 // handshaking has completed.
  1069                  * a partial handshake message or multiple messages.
   951                 hc = engine.conContext.handshakeContext;
  1070                  *
   952                 if (hc != null) {
  1071                  * The handshaker state machine will ensure that it's
   953                     hc.taskDelegated = false;
  1072                  * a finished message.
   954                 }
  1073                  */
   955             }
  1074                 handshaker.processRecord(plainText.fragment, expectingFinished);
   956         }
  1075                 expectingFinished = false;
   957 
  1076 
   958         private static class DelegatedAction
  1077                 if (handshaker.invalidated) {
   959                 implements PrivilegedExceptionAction<Void> {
  1078                     finishHandshake();
   960             final HandshakeContext context;
  1079 
   961             DelegatedAction(HandshakeContext context) {
  1080                     // if state is cs_RENEGOTIATE, revert it to cs_DATA
   962                 this.context = context;
  1081                     if (connectionState == cs_RENEGOTIATE) {
   963             }
  1082                         connectionState = cs_DATA;
   964 
       
   965             @Override
       
   966             public Void run() throws Exception {
       
   967                 while (!context.delegatedActions.isEmpty()) {
       
   968                     // Report back the task SSLException
       
   969                     if (context.delegatedThrown != null) {
       
   970                         Exception delegatedThrown = context.delegatedThrown;
       
   971                         context.delegatedThrown = null;
       
   972                         throw getTaskThrown(delegatedThrown);
  1083                     }
   973                     }
  1084                 } else if (handshaker.isDone()) {
   974 
  1085                     // reset the parameters for secure renegotiation.
   975                     Map.Entry<Byte, ByteBuffer> me =
  1086                     secureRenegotiation =
   976                             context.delegatedActions.poll();
  1087                                 handshaker.isSecureRenegotiation();
   977                     if (me != null) {
  1088                     clientVerifyData = handshaker.getClientVerifyData();
   978                         context.dispatch(me.getKey(), me.getValue());
  1089                     serverVerifyData = handshaker.getServerVerifyData();
       
  1090                     // set connection ALPN value
       
  1091                     applicationProtocol =
       
  1092                         handshaker.getHandshakeApplicationProtocol();
       
  1093 
       
  1094                     sess = handshaker.getSession();
       
  1095                     handshakeSession = null;
       
  1096                     if (outputRecord.isEmpty()) {
       
  1097                         hsStatus = finishHandshake();
       
  1098                         connectionState = cs_DATA;
       
  1099                     }
       
  1100 
       
  1101                     // No handshakeListeners here.  That's a
       
  1102                     // SSLSocket thing.
       
  1103                 } else if (handshaker.taskOutstanding()) {
       
  1104                     hsStatus = HandshakeStatus.NEED_TASK;
       
  1105                 }
       
  1106                 break;
       
  1107 
       
  1108             case Record.ct_application_data:
       
  1109                 // Pass this right back up to the application.
       
  1110                 if ((connectionState != cs_DATA)
       
  1111                         && (connectionState != cs_RENEGOTIATE)
       
  1112                         && (connectionState != cs_CLOSED)) {
       
  1113                     throw new SSLProtocolException(
       
  1114                             "Data received in non-data state: " +
       
  1115                             connectionState);
       
  1116                 }
       
  1117 
       
  1118                 if (expectingFinished) {
       
  1119                     throw new SSLProtocolException
       
  1120                             ("Expecting finished message, received data");
       
  1121                 }
       
  1122 
       
  1123                 if (!inboundDone) {
       
  1124                     ByteBuffer fragment = plainText.fragment;
       
  1125                     int remains = fragment.remaining();
       
  1126 
       
  1127                     // Should have enough room in appData.
       
  1128                     for (int i = offset;
       
  1129                             ((i < (offset + length)) && (remains > 0)); i++) {
       
  1130                         int amount = Math.min(appData[i].remaining(), remains);
       
  1131                         fragment.limit(fragment.position() + amount);
       
  1132                         appData[i].put(fragment);
       
  1133                         remains -= amount;
       
  1134                     }
   979                     }
  1135                 }
   980                 }
  1136 
   981                 return null;
  1137                 break;
   982             }
  1138 
   983         }
  1139             case Record.ct_alert:
       
  1140                 recvAlert(plainText.fragment);
       
  1141                 break;
       
  1142 
       
  1143             case Record.ct_change_cipher_spec:
       
  1144                 if ((connectionState != cs_HANDSHAKE
       
  1145                         && connectionState != cs_RENEGOTIATE)) {
       
  1146                     // For the CCS message arriving in the wrong state
       
  1147                     fatal(Alerts.alert_unexpected_message,
       
  1148                             "illegal change cipher spec msg, conn state = "
       
  1149                             + connectionState);
       
  1150                 } else if (plainText.fragment.remaining() != 1
       
  1151                         || plainText.fragment.get() != 1) {
       
  1152                     // For structural/content issues with the CCS
       
  1153                     fatal(Alerts.alert_unexpected_message,
       
  1154                             "Malformed change cipher spec msg");
       
  1155                 }
       
  1156 
       
  1157                 //
       
  1158                 // The first message after a change_cipher_spec
       
  1159                 // record MUST be a "Finished" handshake record,
       
  1160                 // else it's a protocol violation.  We force this
       
  1161                 // to be checked by a minor tweak to the state
       
  1162                 // machine.
       
  1163                 //
       
  1164                 handshaker.receiveChangeCipherSpec();
       
  1165 
       
  1166                 CipherBox readCipher;
       
  1167                 Authenticator readAuthenticator;
       
  1168                 try {
       
  1169                     readCipher = handshaker.newReadCipher();
       
  1170                     readAuthenticator = handshaker.newReadAuthenticator();
       
  1171                 } catch (GeneralSecurityException e) {
       
  1172                     // can't happen
       
  1173                     throw new SSLException("Algorithm missing:  ", e);
       
  1174                 }
       
  1175                 inputRecord.changeReadCiphers(readAuthenticator, readCipher);
       
  1176 
       
  1177                 // next message MUST be a finished message
       
  1178                 expectingFinished = true;
       
  1179                 break;
       
  1180 
       
  1181             default:
       
  1182                 //
       
  1183                 // TLS requires that unrecognized records be ignored.
       
  1184                 //
       
  1185                 if (debug != null && Debug.isOn("ssl")) {
       
  1186                     System.out.println(Thread.currentThread().getName() +
       
  1187                             ", Received record type: " + plainText.contentType);
       
  1188                 }
       
  1189                 break;
       
  1190         } // switch
       
  1191 
       
  1192         /*
       
  1193          * We only need to check the sequence number state for
       
  1194          * non-handshaking record.
       
  1195          *
       
  1196          * Note that in order to maintain the handshake status
       
  1197          * properly, we check the sequence number after the last
       
  1198          * record reading process. As we request renegotiation
       
  1199          * or close the connection for wrapped sequence number
       
  1200          * when there is enough sequence number space left to
       
  1201          * handle a few more records, so the sequence number
       
  1202          * of the last record cannot be wrapped.
       
  1203          */
       
  1204         hsStatus = getHSStatus(hsStatus);
       
  1205         if (connectionState < cs_ERROR && !isInboundDone() &&
       
  1206                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) &&
       
  1207                 (inputRecord.seqNumIsHuge())) {
       
  1208             /*
       
  1209              * Ask for renegotiation when need to renew sequence number.
       
  1210              *
       
  1211              * Don't bother to kickstart the renegotiation when the local is
       
  1212              * asking for it.
       
  1213              */
       
  1214             if (debug != null && Debug.isOn("ssl")) {
       
  1215                 System.out.println(Thread.currentThread().getName() +
       
  1216                         ", request renegotiation " +
       
  1217                         "to avoid sequence number overflow");
       
  1218             }
       
  1219 
       
  1220             beginHandshake();
       
  1221 
       
  1222             hsStatus = getHSStatus(null);
       
  1223         }
       
  1224 
       
  1225         return hsStatus;
       
  1226     }
       
  1227 
       
  1228 
       
  1229     //
       
  1230     // write/wrap side
       
  1231     //
       
  1232 
       
  1233 
       
  1234     /**
       
  1235      * Wraps a buffer.  Does a variety of checks before grabbing
       
  1236      * the wrapLock, which blocks multiple wraps from occurring.
       
  1237      */
       
  1238     @Override
       
  1239     public SSLEngineResult wrap(ByteBuffer[] appData,
       
  1240             int offset, int length, ByteBuffer netData) throws SSLException {
       
  1241 
       
  1242         // check engine parameters
       
  1243         checkEngineParas(netData, appData, offset, length, true);
       
  1244 
       
  1245         /*
       
  1246          * We can be smarter about using smaller buffer sizes later.
       
  1247          * For now, force it to be large enough to handle any valid record.
       
  1248          */
       
  1249         if (netData.remaining() < sess.getPacketBufferSize()) {
       
  1250             return new SSLEngineResult(
       
  1251                 Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
       
  1252         }
       
  1253 
       
  1254         try {
       
  1255             synchronized (wrapLock) {
       
  1256                 return writeAppRecord(appData, offset, length, netData);
       
  1257             }
       
  1258         } catch (SSLProtocolException spe) {
       
  1259             // may be an unexpected handshake message
       
  1260             fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe);
       
  1261             return null;  // make compiler happy
       
  1262         } catch (Exception e) {
       
  1263             fatal(Alerts.alert_internal_error,
       
  1264                 "problem wrapping app data", e);
       
  1265             return null;  // make compiler happy
       
  1266         }
       
  1267     }
       
  1268 
       
  1269     /*
       
  1270      * Makes additional checks for unwrap, but this time more
       
  1271      * specific to this packet and the current state of the machine.
       
  1272      */
       
  1273     private SSLEngineResult writeAppRecord(ByteBuffer[] appData,
       
  1274             int offset, int length, ByteBuffer netData) throws IOException {
       
  1275 
       
  1276         Status status = null;
       
  1277         HandshakeStatus hsStatus = null;
       
  1278 
       
  1279         /*
       
  1280          * See if the handshaker needs to report back some SSLException.
       
  1281          */
       
  1282         checkTaskThrown();
       
  1283 
       
  1284         /*
       
  1285          * short circuit if we're closed/closing.
       
  1286          */
       
  1287         if (isOutboundDone()) {
       
  1288             return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
       
  1289         }
       
  1290 
       
  1291         /*
       
  1292          * If we're still in cs_HANDSHAKE, make sure it's been
       
  1293          * started.
       
  1294          */
       
  1295         synchronized (this) {
       
  1296             if ((connectionState == cs_HANDSHAKE) ||
       
  1297                 (connectionState == cs_START)) {
       
  1298 
       
  1299                 kickstartHandshake();
       
  1300 
       
  1301                 /*
       
  1302                  * If there's no HS data available to write, we can return
       
  1303                  * without trying to wrap anything.
       
  1304                  */
       
  1305                 hsStatus = getHSStatus(null);
       
  1306                 if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
       
  1307                     /*
       
  1308                      * For DTLS, if the handshake state is
       
  1309                      * HandshakeStatus.NEED_UNWRAP, a call to SSLEngine.wrap()
       
  1310                      * means that the previous handshake packets (if delivered)
       
  1311                      * get lost, and need retransmit the handshake messages.
       
  1312                      */
       
  1313                     if (!isDTLS || !enableRetransmissions ||
       
  1314                             (handshaker == null) || outputRecord.firstMessage) {
       
  1315 
       
  1316                         return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
       
  1317                     }   // otherwise, need retransmission
       
  1318                 }
       
  1319             }
       
  1320         }
       
  1321 
       
  1322         /*
       
  1323          * Grab a copy of this if it doesn't already exist,
       
  1324          * and we can use it several places before anything major
       
  1325          * happens on this side.  Races aren't critical
       
  1326          * here.
       
  1327          */
       
  1328         if (hsStatus == null) {
       
  1329             hsStatus = getHSStatus(null);
       
  1330         }
       
  1331 
       
  1332         /*
       
  1333          * If we have a task outstanding, this *MUST* be done before
       
  1334          * doing any more wrapping, because we could be in the middle
       
  1335          * of receiving a handshake message, for example, a finished
       
  1336          * message which would change the ciphers.
       
  1337          */
       
  1338         if (hsStatus == HandshakeStatus.NEED_TASK) {
       
  1339             return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
       
  1340         }
       
  1341 
       
  1342         /*
       
  1343          * This will obtain any waiting outbound data, or will
       
  1344          * process the outbound appData.
       
  1345          */
       
  1346         int netPos = netData.position();
       
  1347         int appRemains = 0;
       
  1348         for (int i = offset; i < offset + length; i++) {
       
  1349             if (appData[i] == null) {
       
  1350                 throw new IllegalArgumentException(
       
  1351                         "appData[" + i + "] == null");
       
  1352             }
       
  1353             appRemains += appData[i].remaining();
       
  1354         }
       
  1355 
       
  1356         Ciphertext ciphertext = null;
       
  1357         try {
       
  1358             if (appRemains != 0) {
       
  1359                 synchronized (writeLock) {
       
  1360                     ciphertext = writeRecord(appData, offset, length, netData);
       
  1361                 }
       
  1362             } else {
       
  1363                 synchronized (writeLock) {
       
  1364                     ciphertext = writeRecord(null, 0, 0, netData);
       
  1365                 }
       
  1366             }
       
  1367         } catch (SSLException e) {
       
  1368             throw e;
       
  1369         } catch (IOException e) {
       
  1370             throw new SSLException("Write problems", e);
       
  1371         }
       
  1372 
       
  1373         /*
       
  1374          * writeRecord might have reported some status.
       
  1375          * Now check for the remaining cases.
       
  1376          *
       
  1377          * status above should cover:  NEED_WRAP/FINISHED
       
  1378          */
       
  1379         status = (isOutboundDone() ? Status.CLOSED : Status.OK);
       
  1380         hsStatus = getHSStatus(ciphertext.handshakeStatus);
       
  1381 
       
  1382         int deltaNet = netData.position() - netPos;
       
  1383         int deltaApp = appRemains;
       
  1384         for (int i = offset; i < offset + length; i++) {
       
  1385             deltaApp -= appData[i].remaining();
       
  1386         }
       
  1387 
       
  1388         return new SSLEngineResult(
       
  1389                 status, hsStatus, deltaApp, deltaNet, ciphertext.recordSN);
       
  1390     }
       
  1391 
       
  1392     /*
       
  1393      * Central point to write/get all of the outgoing data.
       
  1394      */
       
  1395     private Ciphertext writeRecord(ByteBuffer[] appData,
       
  1396             int offset, int length, ByteBuffer netData) throws IOException {
       
  1397 
       
  1398         Ciphertext ciphertext = null;
       
  1399         try {
       
  1400             // Acquire the buffered to-be-delivered records or retransmissions.
       
  1401             //
       
  1402             // May have buffered records, or need retransmission if handshaking.
       
  1403             if (!outputRecord.isEmpty() ||
       
  1404                     (enableRetransmissions && handshaker != null)) {
       
  1405                 ciphertext = outputRecord.acquireCiphertext(netData);
       
  1406             }
       
  1407 
       
  1408             if ((ciphertext == null) && (appData != null)) {
       
  1409                 ciphertext = outputRecord.encode(
       
  1410                         appData, offset, length, netData);
       
  1411             }
       
  1412         } catch (SSLHandshakeException she) {
       
  1413             // may be record sequence number overflow
       
  1414             fatal(Alerts.alert_handshake_failure, she);
       
  1415 
       
  1416             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
       
  1417         } catch (IOException e) {
       
  1418             fatal(Alerts.alert_unexpected_message, e);
       
  1419 
       
  1420             return Ciphertext.CIPHERTEXT_NULL;   // make the complier happy
       
  1421         }
       
  1422 
       
  1423         if (ciphertext == null) {
       
  1424             return Ciphertext.CIPHERTEXT_NULL;
       
  1425         }
       
  1426 
       
  1427         HandshakeStatus hsStatus = null;
       
  1428         Ciphertext.RecordType recordType = ciphertext.recordType;
       
  1429         if ((recordType.contentType == Record.ct_handshake) &&
       
  1430             (recordType.handshakeType == HandshakeMessage.ht_finished) &&
       
  1431             outputRecord.isEmpty()) {
       
  1432 
       
  1433             if (handshaker == null) {
       
  1434                 hsStatus = HandshakeStatus.FINISHED;
       
  1435             } else if (handshaker.isDone()) {
       
  1436                 hsStatus = finishHandshake();
       
  1437                 connectionState = cs_DATA;
       
  1438 
       
  1439                 // Retransmit the last flight twice.
       
  1440                 //
       
  1441                 // The application data transactions may begin immediately
       
  1442                 // after the last flight.  If the last flight get lost, the
       
  1443                 // application data may be discarded accordingly.  As could
       
  1444                 // be an issue for some applications.  This impact can be
       
  1445                 // mitigated by sending the last fligth twice.
       
  1446                 if (isDTLS && enableRetransmissions) {
       
  1447                     if (debug != null && Debug.isOn("verbose")) {
       
  1448                         Debug.log(
       
  1449                             "Retransmit the last flight messages.");
       
  1450                     }
       
  1451 
       
  1452                     synchronized (this) {
       
  1453                         outputRecord.launchRetransmission();
       
  1454                     }
       
  1455 
       
  1456                     hsStatus = HandshakeStatus.NEED_WRAP;
       
  1457                 }
       
  1458             }
       
  1459         }   // Otherwise, the followed call to getHSStatus() will help.
       
  1460 
       
  1461         /*
       
  1462          * We only need to check the sequence number state for
       
  1463          * non-handshaking record.
       
  1464          *
       
  1465          * Note that in order to maintain the handshake status
       
  1466          * properly, we check the sequence number after the last
       
  1467          * record writing process. As we request renegotiation
       
  1468          * or close the connection for wrapped sequence number
       
  1469          * when there is enough sequence number space left to
       
  1470          * handle a few more records, so the sequence number
       
  1471          * of the last record cannot be wrapped.
       
  1472          */
       
  1473         hsStatus = getHSStatus(hsStatus);
       
  1474         if (connectionState < cs_ERROR && !isOutboundDone() &&
       
  1475                 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) &&
       
  1476                 (outputRecord.seqNumIsHuge())) {
       
  1477             /*
       
  1478              * Ask for renegotiation when need to renew sequence number.
       
  1479              *
       
  1480              * Don't bother to kickstart the renegotiation when the local is
       
  1481              * asking for it.
       
  1482              */
       
  1483             if (debug != null && Debug.isOn("ssl")) {
       
  1484                 System.out.println(Thread.currentThread().getName() +
       
  1485                         ", request renegotiation " +
       
  1486                         "to avoid sequence number overflow");
       
  1487             }
       
  1488 
       
  1489             beginHandshake();
       
  1490 
       
  1491             hsStatus = getHSStatus(null);
       
  1492         }
       
  1493         ciphertext.handshakeStatus = hsStatus;
       
  1494 
       
  1495         return ciphertext;
       
  1496     }
       
  1497 
       
  1498     private HandshakeStatus finishHandshake() {
       
  1499         handshaker = null;
       
  1500         inputRecord.setHandshakeHash(null);
       
  1501         outputRecord.setHandshakeHash(null);
       
  1502         connectionState = cs_DATA;
       
  1503 
       
  1504        return HandshakeStatus.FINISHED;
       
  1505    }
       
  1506 
       
  1507     //
       
  1508     // Close code
       
  1509     //
       
  1510 
       
  1511     /**
       
  1512      * Signals that no more outbound application data will be sent
       
  1513      * on this <code>SSLEngine</code>.
       
  1514      */
       
  1515     private void closeOutboundInternal() {
       
  1516 
       
  1517         if ((debug != null) && Debug.isOn("ssl")) {
       
  1518             System.out.println(Thread.currentThread().getName() +
       
  1519                                     ", closeOutboundInternal()");
       
  1520         }
       
  1521 
       
  1522         /*
       
  1523          * Already closed, ignore
       
  1524          */
       
  1525         if (outboundDone) {
       
  1526             return;
       
  1527         }
       
  1528 
       
  1529         switch (connectionState) {
       
  1530 
       
  1531         /*
       
  1532          * If we haven't even started yet, don't bother reading inbound.
       
  1533          */
       
  1534         case cs_START:
       
  1535             try {
       
  1536                 outputRecord.close();
       
  1537             } catch (IOException ioe) {
       
  1538                // ignore
       
  1539             }
       
  1540             outboundDone = true;
       
  1541 
       
  1542             try {
       
  1543                 inputRecord.close();
       
  1544             } catch (IOException ioe) {
       
  1545                // ignore
       
  1546             }
       
  1547             inboundDone = true;
       
  1548             break;
       
  1549 
       
  1550         case cs_ERROR:
       
  1551         case cs_CLOSED:
       
  1552             break;
       
  1553 
       
  1554         /*
       
  1555          * Otherwise we indicate clean termination.
       
  1556          */
       
  1557         // case cs_HANDSHAKE:
       
  1558         // case cs_DATA:
       
  1559         // case cs_RENEGOTIATE:
       
  1560         default:
       
  1561             warning(Alerts.alert_close_notify);
       
  1562             try {
       
  1563                 outputRecord.close();
       
  1564             } catch (IOException ioe) {
       
  1565                // ignore
       
  1566             }
       
  1567             outboundDone = true;
       
  1568             break;
       
  1569         }
       
  1570 
       
  1571         connectionState = cs_CLOSED;
       
  1572     }
       
  1573 
       
  1574     @Override
       
  1575     public synchronized void closeOutbound() {
       
  1576         /*
       
  1577          * Dump out a close_notify to the remote side
       
  1578          */
       
  1579         if ((debug != null) && Debug.isOn("ssl")) {
       
  1580             System.out.println(Thread.currentThread().getName() +
       
  1581                                     ", called closeOutbound()");
       
  1582         }
       
  1583 
       
  1584         closeOutboundInternal();
       
  1585     }
       
  1586 
       
  1587     /**
       
  1588      * Returns the outbound application data closure state
       
  1589      */
       
  1590     @Override
       
  1591     public boolean isOutboundDone() {
       
  1592         return outboundDone && outputRecord.isEmpty();
       
  1593     }
       
  1594 
       
  1595     /**
       
  1596      * Signals that no more inbound network data will be sent
       
  1597      * to this <code>SSLEngine</code>.
       
  1598      */
       
  1599     private void closeInboundInternal() {
       
  1600 
       
  1601         if ((debug != null) && Debug.isOn("ssl")) {
       
  1602             System.out.println(Thread.currentThread().getName() +
       
  1603                                     ", closeInboundInternal()");
       
  1604         }
       
  1605 
       
  1606         /*
       
  1607          * Already closed, ignore
       
  1608          */
       
  1609         if (inboundDone) {
       
  1610             return;
       
  1611         }
       
  1612 
       
  1613         closeOutboundInternal();
       
  1614 
       
  1615         try {
       
  1616             inputRecord.close();
       
  1617         } catch (IOException ioe) {
       
  1618            // ignore
       
  1619         }
       
  1620         inboundDone = true;
       
  1621 
       
  1622         connectionState = cs_CLOSED;
       
  1623     }
       
  1624 
       
  1625     /*
       
  1626      * Close the inbound side of the connection.  We grab the
       
  1627      * lock here, and do the real work in the internal verison.
       
  1628      * We do check for truncation attacks.
       
  1629      */
       
  1630     @Override
       
  1631     public synchronized void closeInbound() throws SSLException {
       
  1632         /*
       
  1633          * Currently closes the outbound side as well.  The IETF TLS
       
  1634          * working group has expressed the opinion that 1/2 open
       
  1635          * connections are not allowed by the spec.  May change
       
  1636          * someday in the future.
       
  1637          */
       
  1638         if ((debug != null) && Debug.isOn("ssl")) {
       
  1639             System.out.println(Thread.currentThread().getName() +
       
  1640                                     ", called closeInbound()");
       
  1641         }
       
  1642 
       
  1643         /*
       
  1644          * No need to throw an Exception if we haven't even started yet.
       
  1645          */
       
  1646         if ((connectionState != cs_START) && !recvCN) {
       
  1647             recvCN = true;  // Only receive the Exception once
       
  1648             fatal(Alerts.alert_internal_error,
       
  1649                 "Inbound closed before receiving peer's close_notify: " +
       
  1650                 "possible truncation attack?");
       
  1651         } else {
       
  1652             /*
       
  1653              * Currently, this is a no-op, but in case we change
       
  1654              * the close inbound code later.
       
  1655              */
       
  1656             closeInboundInternal();
       
  1657         }
       
  1658     }
       
  1659 
       
  1660     /**
       
  1661      * Returns the network inbound data closure state
       
  1662      */
       
  1663     @Override
       
  1664     public synchronized boolean isInboundDone() {
       
  1665         return inboundDone;
       
  1666     }
       
  1667 
       
  1668 
       
  1669     //
       
  1670     // Misc stuff
       
  1671     //
       
  1672 
       
  1673 
       
  1674     /**
       
  1675      * Returns the current <code>SSLSession</code> for this
       
  1676      * <code>SSLEngine</code>
       
  1677      * <P>
       
  1678      * These can be long lived, and frequently correspond to an
       
  1679      * entire login session for some user.
       
  1680      */
       
  1681     @Override
       
  1682     public synchronized SSLSession getSession() {
       
  1683         return sess;
       
  1684     }
       
  1685 
       
  1686     @Override
       
  1687     public synchronized SSLSession getHandshakeSession() {
       
  1688         return handshakeSession;
       
  1689     }
       
  1690 
       
  1691     synchronized void setHandshakeSession(SSLSessionImpl session) {
       
  1692         // update the fragment size, which may be negotiated during handshaking
       
  1693         inputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize());
       
  1694         outputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize());
       
  1695 
       
  1696         handshakeSession = session;
       
  1697     }
       
  1698 
       
  1699     /**
       
  1700      * Returns a delegated <code>Runnable</code> task for
       
  1701      * this <code>SSLEngine</code>.
       
  1702      */
       
  1703     @Override
       
  1704     public synchronized Runnable getDelegatedTask() {
       
  1705         if (handshaker != null) {
       
  1706             return handshaker.getTask();
       
  1707         }
       
  1708         return null;
       
  1709     }
       
  1710 
       
  1711 
       
  1712     //
       
  1713     // EXCEPTION AND ALERT HANDLING
       
  1714     //
       
  1715 
       
  1716     /*
       
  1717      * Send a warning alert.
       
  1718      */
       
  1719     void warning(byte description) {
       
  1720         sendAlert(Alerts.alert_warning, description);
       
  1721     }
       
  1722 
       
  1723     synchronized void fatal(byte description, String diagnostic)
       
  1724             throws SSLException {
       
  1725         fatal(description, diagnostic, null, false);
       
  1726     }
       
  1727 
       
  1728     synchronized void fatal(byte description, Throwable cause)
       
  1729             throws SSLException {
       
  1730         fatal(description, null, cause, false);
       
  1731     }
       
  1732 
       
  1733     synchronized void fatal(byte description, String diagnostic,
       
  1734             Throwable cause) throws SSLException {
       
  1735         fatal(description, diagnostic, cause, false);
       
  1736     }
       
  1737 
       
  1738     /*
       
  1739      * We've got a fatal error here, so start the shutdown process.
       
  1740      *
       
  1741      * Because of the way the code was written, we have some code
       
  1742      * calling fatal directly when the "description" is known
       
  1743      * and some throwing Exceptions which are then caught by higher
       
  1744      * levels which then call here.  This code needs to determine
       
  1745      * if one of the lower levels has already started the process.
       
  1746      *
       
  1747      * We won't worry about Errors, if we have one of those,
       
  1748      * we're in worse trouble.  Note:  the networking code doesn't
       
  1749      * deal with Errors either.
       
  1750      */
       
  1751     synchronized void fatal(byte description, String diagnostic,
       
  1752             Throwable cause, boolean recvFatalAlert) throws SSLException {
       
  1753 
       
  1754         /*
       
  1755          * If we have no further information, make a general-purpose
       
  1756          * message for folks to see.  We generally have one or the other.
       
  1757          */
       
  1758         if (diagnostic == null) {
       
  1759             diagnostic = "General SSLEngine problem";
       
  1760         }
       
  1761         if (cause == null) {
       
  1762             cause = Alerts.getSSLException(description, cause, diagnostic);
       
  1763         }
       
  1764 
       
  1765         /*
       
  1766          * If we've already shutdown because of an error,
       
  1767          * there is nothing we can do except rethrow the exception.
       
  1768          *
       
  1769          * Most exceptions seen here will be SSLExceptions.
       
  1770          * We may find the occasional Exception which hasn't been
       
  1771          * converted to a SSLException, so we'll do it here.
       
  1772          */
       
  1773         if (closeReason != null) {
       
  1774             if ((debug != null) && Debug.isOn("ssl")) {
       
  1775                 System.out.println(Thread.currentThread().getName() +
       
  1776                     ", fatal: engine already closed.  Rethrowing " +
       
  1777                     cause.toString());
       
  1778             }
       
  1779             if (cause instanceof RuntimeException) {
       
  1780                 throw (RuntimeException)cause;
       
  1781             } else if (cause instanceof SSLException) {
       
  1782                 throw (SSLException)cause;
       
  1783             } else if (cause instanceof Exception) {
       
  1784                 throw new SSLException("fatal SSLEngine condition", cause);
       
  1785             }
       
  1786         }
       
  1787 
       
  1788         if ((debug != null) && Debug.isOn("ssl")) {
       
  1789             System.out.println(Thread.currentThread().getName()
       
  1790                         + ", fatal error: " + description +
       
  1791                         ": " + diagnostic + "\n" + cause.toString());
       
  1792         }
       
  1793 
       
  1794         /*
       
  1795          * Ok, this engine's going down.
       
  1796          */
       
  1797         int oldState = connectionState;
       
  1798         connectionState = cs_ERROR;
       
  1799 
       
  1800         try {
       
  1801             inputRecord.close();
       
  1802         } catch (IOException ioe) {
       
  1803            // ignore
       
  1804         }
       
  1805         inboundDone = true;
       
  1806 
       
  1807         sess.invalidate();
       
  1808         if (handshakeSession != null) {
       
  1809             handshakeSession.invalidate();
       
  1810         }
       
  1811 
       
  1812         /*
       
  1813          * If we haven't even started handshaking yet, or we are the
       
  1814          * recipient of a fatal alert, no need to generate a fatal close
       
  1815          * alert.
       
  1816          */
       
  1817         if (oldState != cs_START && !recvFatalAlert) {
       
  1818             sendAlert(Alerts.alert_fatal, description);
       
  1819         }
       
  1820 
       
  1821         if (cause instanceof SSLException) { // only true if != null
       
  1822             closeReason = (SSLException)cause;
       
  1823         } else {
       
  1824             /*
       
  1825              * Including RuntimeExceptions, but we'll throw those
       
  1826              * down below.  The closeReason isn't used again,
       
  1827              * except for null checks.
       
  1828              */
       
  1829             closeReason =
       
  1830                 Alerts.getSSLException(description, cause, diagnostic);
       
  1831         }
       
  1832 
       
  1833         try {
       
  1834             outputRecord.close();
       
  1835         } catch (IOException ioe) {
       
  1836            // ignore
       
  1837         }
       
  1838         outboundDone = true;
       
  1839 
       
  1840         connectionState = cs_CLOSED;
       
  1841 
       
  1842         if (cause instanceof RuntimeException) {
       
  1843             throw (RuntimeException)cause;
       
  1844         } else {
       
  1845             throw closeReason;
       
  1846         }
       
  1847     }
       
  1848 
       
  1849     /*
       
  1850      * Process an incoming alert ... caller must already have synchronized
       
  1851      * access to "this".
       
  1852      */
       
  1853     private void recvAlert(ByteBuffer fragment) throws IOException {
       
  1854         byte level = fragment.get();
       
  1855         byte description = fragment.get();
       
  1856 
       
  1857         if (debug != null && (Debug.isOn("record") ||
       
  1858                 Debug.isOn("handshake"))) {
       
  1859             synchronized (System.out) {
       
  1860                 System.out.print(Thread.currentThread().getName());
       
  1861                 System.out.print(", RECV " + protocolVersion + " ALERT:  ");
       
  1862                 if (level == Alerts.alert_fatal) {
       
  1863                     System.out.print("fatal, ");
       
  1864                 } else if (level == Alerts.alert_warning) {
       
  1865                     System.out.print("warning, ");
       
  1866                 } else {
       
  1867                     System.out.print("<level " + (0x0ff & level) + ">, ");
       
  1868                 }
       
  1869                 System.out.println(Alerts.alertDescription(description));
       
  1870             }
       
  1871         }
       
  1872 
       
  1873         if (level == Alerts.alert_warning) {
       
  1874             if (description == -1) {    // check for short message
       
  1875                 fatal(Alerts.alert_illegal_parameter, "Short alert message");
       
  1876             } else if (description == Alerts.alert_close_notify) {
       
  1877                 if (connectionState == cs_HANDSHAKE) {
       
  1878                     fatal(Alerts.alert_unexpected_message,
       
  1879                                 "Received close_notify during handshake");
       
  1880                 } else {
       
  1881                     recvCN = true;
       
  1882                     closeInboundInternal();  // reply to close
       
  1883                 }
       
  1884             } else {
       
  1885 
       
  1886                 //
       
  1887                 // The other legal warnings relate to certificates,
       
  1888                 // e.g. no_certificate, bad_certificate, etc; these
       
  1889                 // are important to the handshaking code, which can
       
  1890                 // also handle illegal protocol alerts if needed.
       
  1891                 //
       
  1892                 if (handshaker != null) {
       
  1893                     handshaker.handshakeAlert(description);
       
  1894                 }
       
  1895             }
       
  1896         } else { // fatal or unknown level
       
  1897             String reason = "Received fatal alert: "
       
  1898                 + Alerts.alertDescription(description);
       
  1899 
       
  1900             // The inbound and outbound queues will be closed as part of
       
  1901             // the call to fatal.  The handhaker to needs to be set to null
       
  1902             // so subsequent calls to getHandshakeStatus will return
       
  1903             // NOT_HANDSHAKING.
       
  1904             handshaker = null;
       
  1905             Throwable cause = Alerts.getSSLException(description, reason);
       
  1906             fatal(description, null, cause, true);
       
  1907         }
       
  1908     }
       
  1909 
       
  1910 
       
  1911     /*
       
  1912      * Emit alerts.  Caller must have synchronized with "this".
       
  1913      */
       
  1914     private void sendAlert(byte level, byte description) {
       
  1915         // the connectionState cannot be cs_START
       
  1916         if (connectionState >= cs_CLOSED) {
       
  1917             return;
       
  1918         }
       
  1919 
       
  1920         // For initial handshaking, don't send alert message to peer if
       
  1921         // handshaker has not started.
       
  1922         //
       
  1923         // Shall we send an fatal alter to terminate the connection gracefully?
       
  1924         if (connectionState <= cs_HANDSHAKE &&
       
  1925                 (handshaker == null || !handshaker.started() ||
       
  1926                         !handshaker.activated())) {
       
  1927             return;
       
  1928         }
       
  1929 
       
  1930         try {
       
  1931             outputRecord.encodeAlert(level, description);
       
  1932         } catch (IOException ioe) {
       
  1933             // ignore
       
  1934         }
       
  1935     }
       
  1936 
       
  1937 
       
  1938     //
       
  1939     // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
       
  1940     //
       
  1941 
       
  1942 
       
  1943     /**
       
  1944      * Controls whether new connections may cause creation of new SSL
       
  1945      * sessions.
       
  1946      *
       
  1947      * As long as handshaking has not started, we can change
       
  1948      * whether we enable session creations.  Otherwise,
       
  1949      * we will need to wait for the next handshake.
       
  1950      */
       
  1951     @Override
       
  1952     public synchronized void setEnableSessionCreation(boolean flag) {
       
  1953         enableSessionCreation = flag;
       
  1954 
       
  1955         if ((handshaker != null) && !handshaker.activated()) {
       
  1956             handshaker.setEnableSessionCreation(enableSessionCreation);
       
  1957         }
       
  1958     }
       
  1959 
       
  1960     /**
       
  1961      * Returns true if new connections may cause creation of new SSL
       
  1962      * sessions.
       
  1963      */
       
  1964     @Override
       
  1965     public synchronized boolean getEnableSessionCreation() {
       
  1966         return enableSessionCreation;
       
  1967     }
       
  1968 
       
  1969 
       
  1970     /**
       
  1971      * Sets the flag controlling whether a server mode engine
       
  1972      * *REQUIRES* SSL client authentication.
       
  1973      *
       
  1974      * As long as handshaking has not started, we can change
       
  1975      * whether client authentication is needed.  Otherwise,
       
  1976      * we will need to wait for the next handshake.
       
  1977      */
       
  1978     @Override
       
  1979     public synchronized void setNeedClientAuth(boolean flag) {
       
  1980         doClientAuth = (flag ?
       
  1981                 ClientAuthType.CLIENT_AUTH_REQUIRED :
       
  1982                 ClientAuthType.CLIENT_AUTH_NONE);
       
  1983 
       
  1984         if ((handshaker != null) &&
       
  1985                 (handshaker instanceof ServerHandshaker) &&
       
  1986                 !handshaker.activated()) {
       
  1987             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
       
  1988         }
       
  1989     }
       
  1990 
       
  1991     @Override
       
  1992     public synchronized boolean getNeedClientAuth() {
       
  1993         return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUIRED);
       
  1994     }
       
  1995 
       
  1996     /**
       
  1997      * Sets the flag controlling whether a server mode engine
       
  1998      * *REQUESTS* SSL client authentication.
       
  1999      *
       
  2000      * As long as handshaking has not started, we can change
       
  2001      * whether client authentication is requested.  Otherwise,
       
  2002      * we will need to wait for the next handshake.
       
  2003      */
       
  2004     @Override
       
  2005     public synchronized void setWantClientAuth(boolean flag) {
       
  2006         doClientAuth = (flag ?
       
  2007                 ClientAuthType.CLIENT_AUTH_REQUESTED :
       
  2008                 ClientAuthType.CLIENT_AUTH_NONE);
       
  2009 
       
  2010         if ((handshaker != null) &&
       
  2011                 (handshaker instanceof ServerHandshaker) &&
       
  2012                 !handshaker.activated()) {
       
  2013             ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
       
  2014         }
       
  2015     }
       
  2016 
       
  2017     @Override
       
  2018     public synchronized boolean getWantClientAuth() {
       
  2019         return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUESTED);
       
  2020     }
       
  2021 
       
  2022 
       
  2023     /**
       
  2024      * Sets the flag controlling whether the engine is in SSL
       
  2025      * client or server mode.  Must be called before any SSL
       
  2026      * traffic has started.
       
  2027      */
       
  2028     @Override
       
  2029     @SuppressWarnings("fallthrough")
       
  2030     public synchronized void setUseClientMode(boolean flag) {
       
  2031         switch (connectionState) {
       
  2032 
       
  2033         case cs_START:
       
  2034             /*
       
  2035              * If we need to change the socket mode and the enabled
       
  2036              * protocols and cipher suites haven't specifically been
       
  2037              * set by the user, change them to the corresponding
       
  2038              * default ones.
       
  2039              */
       
  2040             if (roleIsServer != (!flag)) {
       
  2041                 if (sslContext.isDefaultProtocolList(enabledProtocols)) {
       
  2042                     enabledProtocols =
       
  2043                             sslContext.getDefaultProtocolList(!flag);
       
  2044                 }
       
  2045 
       
  2046                 if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) {
       
  2047                     enabledCipherSuites =
       
  2048                             sslContext.getDefaultCipherSuiteList(!flag);
       
  2049                 }
       
  2050             }
       
  2051 
       
  2052             roleIsServer = !flag;
       
  2053             serverModeSet = true;
       
  2054             break;
       
  2055 
       
  2056         case cs_HANDSHAKE:
       
  2057             /*
       
  2058              * If we have a handshaker, but haven't started
       
  2059              * SSL traffic, we can throw away our current
       
  2060              * handshaker, and start from scratch.  Don't
       
  2061              * need to call doneConnect() again, we already
       
  2062              * have the streams.
       
  2063              */
       
  2064             assert(handshaker != null);
       
  2065             if (!handshaker.activated()) {
       
  2066                 /*
       
  2067                  * If we need to change the socket mode and the enabled
       
  2068                  * protocols and cipher suites haven't specifically been
       
  2069                  * set by the user, change them to the corresponding
       
  2070                  * default ones.
       
  2071                  */
       
  2072                 if (roleIsServer != (!flag)) {
       
  2073                     if (sslContext.isDefaultProtocolList(enabledProtocols)) {
       
  2074                         enabledProtocols =
       
  2075                                 sslContext.getDefaultProtocolList(!flag);
       
  2076                     }
       
  2077 
       
  2078                     if (sslContext.isDefaultCipherSuiteList(
       
  2079                                                     enabledCipherSuites)) {
       
  2080                         enabledCipherSuites =
       
  2081                             sslContext.getDefaultCipherSuiteList(!flag);
       
  2082                     }
       
  2083                 }
       
  2084 
       
  2085                 roleIsServer = !flag;
       
  2086                 connectionState = cs_START;
       
  2087                 initHandshaker();
       
  2088                 break;
       
  2089             }
       
  2090 
       
  2091             // If handshake has started, that's an error.  Fall through...
       
  2092 
       
  2093         default:
       
  2094             if (debug != null && Debug.isOn("ssl")) {
       
  2095                 System.out.println(Thread.currentThread().getName() +
       
  2096                     ", setUseClientMode() invoked in state = " +
       
  2097                     connectionState);
       
  2098             }
       
  2099 
       
  2100             /*
       
  2101              * We can let them continue if they catch this correctly,
       
  2102              * we don't need to shut this down.
       
  2103              */
       
  2104             throw new IllegalArgumentException(
       
  2105                 "Cannot change mode after SSL traffic has started");
       
  2106         }
       
  2107     }
       
  2108 
       
  2109     @Override
       
  2110     public synchronized boolean getUseClientMode() {
       
  2111         return !roleIsServer;
       
  2112     }
       
  2113 
       
  2114 
       
  2115     /**
       
  2116      * Returns the names of the cipher suites which could be enabled for use
       
  2117      * on an SSL connection.  Normally, only a subset of these will actually
       
  2118      * be enabled by default, since this list may include cipher suites which
       
  2119      * do not support the mutual authentication of servers and clients, or
       
  2120      * which do not protect data confidentiality.  Servers may also need
       
  2121      * certain kinds of certificates to use certain cipher suites.
       
  2122      *
       
  2123      * @return an array of cipher suite names
       
  2124      */
       
  2125     @Override
       
  2126     public String[] getSupportedCipherSuites() {
       
  2127         return sslContext.getSupportedCipherSuiteList().toStringArray();
       
  2128     }
       
  2129 
       
  2130     /**
       
  2131      * Controls which particular cipher suites are enabled for use on
       
  2132      * this connection.  The cipher suites must have been listed by
       
  2133      * getCipherSuites() as being supported.  Even if a suite has been
       
  2134      * enabled, it might never be used if no peer supports it or the
       
  2135      * requisite certificates (and private keys) are not available.
       
  2136      *
       
  2137      * @param suites Names of all the cipher suites to enable.
       
  2138      */
       
  2139     @Override
       
  2140     public synchronized void setEnabledCipherSuites(String[] suites) {
       
  2141         enabledCipherSuites = new CipherSuiteList(suites);
       
  2142         if ((handshaker != null) && !handshaker.activated()) {
       
  2143             handshaker.setEnabledCipherSuites(enabledCipherSuites);
       
  2144         }
       
  2145     }
       
  2146 
       
  2147     /**
       
  2148      * Returns the names of the SSL cipher suites which are currently enabled
       
  2149      * for use on this connection.  When an SSL engine is first created,
       
  2150      * all enabled cipher suites <em>(a)</em> protect data confidentiality,
       
  2151      * by traffic encryption, and <em>(b)</em> can mutually authenticate
       
  2152      * both clients and servers.  Thus, in some environments, this value
       
  2153      * might be empty.
       
  2154      *
       
  2155      * @return an array of cipher suite names
       
  2156      */
       
  2157     @Override
       
  2158     public synchronized String[] getEnabledCipherSuites() {
       
  2159         return enabledCipherSuites.toStringArray();
       
  2160     }
       
  2161 
       
  2162 
       
  2163     /**
       
  2164      * Returns the protocols that are supported by this implementation.
       
  2165      * A subset of the supported protocols may be enabled for this connection
       
  2166      * @return an array of protocol names.
       
  2167      */
       
  2168     @Override
       
  2169     public String[] getSupportedProtocols() {
       
  2170         return sslContext.getSuportedProtocolList().toStringArray();
       
  2171     }
       
  2172 
       
  2173     /**
       
  2174      * Controls which protocols are enabled for use on
       
  2175      * this connection.  The protocols must have been listed by
       
  2176      * getSupportedProtocols() as being supported.
       
  2177      *
       
  2178      * @param protocols protocols to enable.
       
  2179      * @exception IllegalArgumentException when one of the protocols
       
  2180      *  named by the parameter is not supported.
       
  2181      */
       
  2182     @Override
       
  2183     public synchronized void setEnabledProtocols(String[] protocols) {
       
  2184         enabledProtocols = new ProtocolList(protocols);
       
  2185         if ((handshaker != null) && !handshaker.activated()) {
       
  2186             handshaker.setEnabledProtocols(enabledProtocols);
       
  2187         }
       
  2188     }
       
  2189 
       
  2190     @Override
       
  2191     public synchronized String[] getEnabledProtocols() {
       
  2192         return enabledProtocols.toStringArray();
       
  2193     }
       
  2194 
       
  2195     /**
       
  2196      * Returns the SSLParameters in effect for this SSLEngine.
       
  2197      */
       
  2198     @Override
       
  2199     public synchronized SSLParameters getSSLParameters() {
       
  2200         SSLParameters params = super.getSSLParameters();
       
  2201 
       
  2202         // the super implementation does not handle the following parameters
       
  2203         params.setEndpointIdentificationAlgorithm(identificationProtocol);
       
  2204         params.setAlgorithmConstraints(algorithmConstraints);
       
  2205         params.setSNIMatchers(sniMatchers);
       
  2206         params.setServerNames(serverNames);
       
  2207         params.setUseCipherSuitesOrder(preferLocalCipherSuites);
       
  2208         params.setEnableRetransmissions(enableRetransmissions);
       
  2209         params.setMaximumPacketSize(maximumPacketSize);
       
  2210         params.setApplicationProtocols(applicationProtocols);
       
  2211 
       
  2212         return params;
       
  2213     }
       
  2214 
       
  2215     /**
       
  2216      * Applies SSLParameters to this engine.
       
  2217      */
       
  2218     @Override
       
  2219     public synchronized void setSSLParameters(SSLParameters params) {
       
  2220         super.setSSLParameters(params);
       
  2221 
       
  2222         // the super implementation does not handle the following parameters
       
  2223         identificationProtocol = params.getEndpointIdentificationAlgorithm();
       
  2224         algorithmConstraints = params.getAlgorithmConstraints();
       
  2225         preferLocalCipherSuites = params.getUseCipherSuitesOrder();
       
  2226         enableRetransmissions = params.getEnableRetransmissions();
       
  2227         maximumPacketSize = params.getMaximumPacketSize();
       
  2228 
       
  2229         if (maximumPacketSize != 0) {
       
  2230             outputRecord.changePacketSize(maximumPacketSize);
       
  2231         } else {
       
  2232             // use the implicit maximum packet size.
       
  2233             maximumPacketSize = outputRecord.getMaxPacketSize();
       
  2234         }
       
  2235 
       
  2236         List<SNIServerName> sniNames = params.getServerNames();
       
  2237         if (sniNames != null) {
       
  2238             serverNames = sniNames;
       
  2239         }
       
  2240 
       
  2241         Collection<SNIMatcher> matchers = params.getSNIMatchers();
       
  2242         if (matchers != null) {
       
  2243             sniMatchers = matchers;
       
  2244         }
       
  2245         applicationProtocols = params.getApplicationProtocols();
       
  2246 
       
  2247         if ((handshaker != null) && !handshaker.activated()) {
       
  2248             handshaker.setIdentificationProtocol(identificationProtocol);
       
  2249             handshaker.setAlgorithmConstraints(algorithmConstraints);
       
  2250             handshaker.setMaximumPacketSize(maximumPacketSize);
       
  2251             handshaker.setApplicationProtocols(applicationProtocols);
       
  2252             if (roleIsServer) {
       
  2253                 handshaker.setSNIMatchers(sniMatchers);
       
  2254                 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites);
       
  2255             } else {
       
  2256                 handshaker.setSNIServerNames(serverNames);
       
  2257             }
       
  2258         }
       
  2259     }
       
  2260 
       
  2261     @Override
       
  2262     public synchronized String getApplicationProtocol() {
       
  2263         return applicationProtocol;
       
  2264     }
       
  2265 
       
  2266     @Override
       
  2267     public synchronized String getHandshakeApplicationProtocol() {
       
  2268         if ((handshaker != null) && handshaker.started()) {
       
  2269             return handshaker.getHandshakeApplicationProtocol();
       
  2270         }
       
  2271         return null;
       
  2272     }
       
  2273 
       
  2274     @Override
       
  2275     public synchronized void setHandshakeApplicationProtocolSelector(
       
  2276         BiFunction<SSLEngine, List<String>, String> selector) {
       
  2277         applicationProtocolSelector = selector;
       
  2278         if ((handshaker != null) && !handshaker.activated()) {
       
  2279             handshaker.setApplicationProtocolSelectorSSLEngine(selector);
       
  2280         }
       
  2281     }
       
  2282 
       
  2283     @Override
       
  2284     public synchronized BiFunction<SSLEngine, List<String>, String>
       
  2285         getHandshakeApplicationProtocolSelector() {
       
  2286         return this.applicationProtocolSelector;
       
  2287     }
       
  2288 
       
  2289     /**
       
  2290      * Returns a printable representation of this end of the connection.
       
  2291      */
       
  2292     @Override
       
  2293     public String toString() {
       
  2294         StringBuilder retval = new StringBuilder(80);
       
  2295 
       
  2296         retval.append(Integer.toHexString(hashCode()));
       
  2297         retval.append("[");
       
  2298         retval.append("SSLEngine[hostname=");
       
  2299         String host = getPeerHost();
       
  2300         retval.append((host == null) ? "null" : host);
       
  2301         retval.append(" port=");
       
  2302         retval.append(Integer.toString(getPeerPort()));
       
  2303         retval.append(" role=" + (roleIsServer ? "Server" : "Client"));
       
  2304         retval.append("] ");
       
  2305         retval.append(getSession().getCipherSuite());
       
  2306         retval.append("]");
       
  2307 
       
  2308         return retval.toString();
       
  2309     }
   984     }
  2310 }
   985 }