History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/sun/security/ssl/SSLSocketImpl.java (1 of 18352 files). Show all

Unified · Split

java/pkg/sun/security/ssl/SSLSocketImpl.java+2493−0
@@ -0,0 +1,2493 @@
1+/*
2+ * Copyright (c) 1996, 2011, Oracle and/or its affiliates. All rights reserved.
3+ * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4+ *
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
7+ * published by the Free Software Foundation. Oracle designates this
8+ * particular file as subject to the "Classpath" exception as provided
9+ * by Oracle in the LICENSE file that accompanied this code.
10+ *
11+ * This code is distributed in the hope that it will be useful, but WITHOUT
12+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
14+ * version 2 for more details (a copy is included in the LICENSE file that
15+ * accompanied this code).
16+ *
17+ * You should have received a copy of the GNU General Public License version
18+ * 2 along with this work; if not, write to the Free Software Foundation,
19+ * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20+ *
21+ * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22+ * or visit www.oracle.com if you need additional information or have any
23+ * questions.
24+ */
25+
26+
27+package sun.security.ssl;
28+
29+import java.io.*;
30+import java.net.*;
31+import java.security.GeneralSecurityException;
32+import java.security.AccessController;
33+import java.security.AccessControlContext;
34+import java.security.PrivilegedAction;
35+import java.security.AlgorithmConstraints;
36+import java.util.*;
37+import java.util.concurrent.TimeUnit;
38+import java.util.concurrent.locks.ReentrantLock;
39+
40+import javax.crypto.BadPaddingException;
41+
42+import javax.net.ssl.*;
43+
44+import com.sun.net.ssl.internal.ssl.X509ExtendedTrustManager;
45+
46+/**
47+ * Implementation of an SSL socket. This is a normal connection type
48+ * socket, implementing SSL over some lower level socket, such as TCP.
49+ * Because it is layered over some lower level socket, it MUST override
50+ * all default socket methods.
51+ *
52+ * <P> This API offers a non-traditional option for establishing SSL
53+ * connections. You may first establish the connection directly, then pass
54+ * that connection to the SSL socket constructor with a flag saying which
55+ * role should be taken in the handshake protocol. (The two ends of the
56+ * connection must not choose the same role!) This allows setup of SSL
57+ * proxying or tunneling, and also allows the kind of "role reversal"
58+ * that is required for most FTP data transfers.
59+ *
60+ * @see javax.net.ssl.SSLSocket
61+ * @see SSLServerSocket
62+ *
63+ * @author David Brownell
64+ */
65+final public class SSLSocketImpl extends BaseSSLSocketImpl {
66+
67+ /*
68+ * ERROR HANDLING GUIDELINES
69+ * (which exceptions to throw and catch and which not to throw and catch)
70+ *
71+ * . if there is an IOException (SocketException) when accessing the
72+ * underlying Socket, pass it through
73+ *
74+ * . do not throw IOExceptions, throw SSLExceptions (or a subclass)
75+ *
76+ * . for internal errors (things that indicate a bug in JSSE or a
77+ * grossly misconfigured J2RE), throw either an SSLException or
78+ * a RuntimeException at your convenience.
79+ *
80+ * . handshaking code (Handshaker or HandshakeMessage) should generally
81+ * pass through exceptions, but can handle them if they know what to
82+ * do.
83+ *
84+ * . exception chaining should be used for all new code. If you happen
85+ * to touch old code that does not use chaining, you should change it.
86+ *
87+ * . there is a top level exception handler that sits at all entry
88+ * points from application code to SSLSocket read/write code. It
89+ * makes sure that all errors are handled (see handleException()).
90+ *
91+ * . JSSE internal code should generally not call close(), call
92+ * closeInternal().
93+ */
94+
95+ /*
96+ * There's a state machine associated with each connection, which
97+ * among other roles serves to negotiate session changes.
98+ *
99+ * - START with constructor, until the TCP connection's around.
100+ * - HANDSHAKE picks session parameters before allowing traffic.
101+ * There are many substates due to sequencing requirements
102+ * for handshake messages.
103+ * - DATA may be transmitted.
104+ * - RENEGOTIATE state allows concurrent data and handshaking
105+ * traffic ("same" substates as HANDSHAKE), and terminates
106+ * in selection of new session (and connection) parameters
107+ * - ERROR state immediately precedes abortive disconnect.
108+ * - SENT_CLOSE sent a close_notify to the peer. For layered,
109+ * non-autoclose socket, must now read close_notify
110+ * from peer before closing the connection. For nonlayered or
111+ * non-autoclose socket, close connection and go onto
112+ * cs_CLOSED state.
113+ * - CLOSED after sending close_notify alert, & socket is closed.
114+ * SSL connection objects are not reused.
115+ * - APP_CLOSED once the application calls close(). Then it behaves like
116+ * a closed socket, e.g.. getInputStream() throws an Exception.
117+ *
118+ * State affects what SSL record types may legally be sent:
119+ *
120+ * - Handshake ... only in HANDSHAKE and RENEGOTIATE states
121+ * - App Data ... only in DATA and RENEGOTIATE states
122+ * - Alert ... in HANDSHAKE, DATA, RENEGOTIATE
123+ *
124+ * Re what may be received: same as what may be sent, except that
125+ * HandshakeRequest handshaking messages can come from servers even
126+ * in the application data state, to request entry to RENEGOTIATE.
127+ *
128+ * The state machine within HANDSHAKE and RENEGOTIATE states controls
129+ * the pending session, not the connection state, until the change
130+ * cipher spec and "Finished" handshake messages are processed and
131+ * make the "new" session become the current one.
132+ *
133+ * NOTE: details of the SMs always need to be nailed down better.
134+ * The text above illustrates the core ideas.
135+ *
136+ * +---->-------+------>--------->-------+
137+ * | | |
138+ * <-----< ^ ^ <-----< v
139+ *START>----->HANDSHAKE>----->DATA>----->RENEGOTIATE SENT_CLOSE
140+ * v v v | |
141+ * | | | | v
142+ * +------------+---------------+ v ERROR
143+ * | | |
144+ * v | |
145+ * ERROR>------>----->CLOSED<--------<----+-- +
146+ * |
147+ * v
148+ * APP_CLOSED
149+ *
150+ * ALSO, note that the the purpose of handshaking (renegotiation is
151+ * included) is to assign a different, and perhaps new, session to
152+ * the connection. The SSLv3 spec is a bit confusing on that new
153+ * protocol feature.
154+ */
155+ private static final int cs_START = 0;
156+ private static final int cs_HANDSHAKE = 1;
157+ private static final int cs_DATA = 2;
158+ private static final int cs_RENEGOTIATE = 3;
159+ private static final int cs_ERROR = 4;
160+ private static final int cs_SENT_CLOSE = 5;
161+ private static final int cs_CLOSED = 6;
162+ private static final int cs_APP_CLOSED = 7;
163+
164+
165+ /*
166+ * Client authentication be off, requested, or required.
167+ *
168+ * Migrated to SSLEngineImpl:
169+ * clauth_none/cl_auth_requested/clauth_required
170+ */
171+
172+ /*
173+ * Drives the protocol state machine.
174+ */
175+ private int connectionState;
176+
177+ /*
178+ * Flag indicating if the next record we receive MUST be a Finished
179+ * message. Temporarily set during the handshake to ensure that
180+ * a change cipher spec message is followed by a finished message.
181+ */
182+ private boolean expectingFinished;
183+
184+ /*
185+ * For improved diagnostics, we detail connection closure
186+ * If the socket is closed (connectionState >= cs_ERROR),
187+ * closeReason != null indicates if the socket was closed
188+ * because of an error or because or normal shutdown.
189+ */
190+ private SSLException closeReason;
191+
192+ /*
193+ * Per-connection private state that doesn't change when the
194+ * session is changed.
195+ */
196+ private byte doClientAuth;
197+ private boolean roleIsServer;
198+ private boolean enableSessionCreation = true;
199+ private String host;
200+ private boolean autoClose = true;
201+ private AccessControlContext acc;
202+
203+ /*
204+ * We cannot use the hostname resolved from name services. For
205+ * virtual hosting, multiple hostnames may be bound to the same IP
206+ * address, so the hostname resolved from name services is not
207+ * reliable.
208+ */
209+ private String rawHostname;
210+
211+ // The cipher suites enabled for use on this connection.
212+ private CipherSuiteList enabledCipherSuites;
213+
214+ // The endpoint identification protocol
215+ private String identificationProtocol = null;
216+
217+ // The cryptographic algorithm constraints
218+ private AlgorithmConstraints algorithmConstraints = null;
219+
220+ /*
221+ * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
222+ * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
223+ * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
224+ *
225+ * There are several locks here.
226+ *
227+ * The primary lock is the per-instance lock used by
228+ * synchronized(this) and the synchronized methods. It controls all
229+ * access to things such as the connection state and variables which
230+ * affect handshaking. If we are inside a synchronized method, we
231+ * can access the state directly, otherwise, we must use the
232+ * synchronized equivalents.
233+ *
234+ * The handshakeLock is used to ensure that only one thread performs
235+ * the *complete initial* handshake. If someone is handshaking, any
236+ * stray application or startHandshake() requests who find the
237+ * connection state is cs_HANDSHAKE will stall on handshakeLock
238+ * until handshaking is done. Once the handshake is done, we either
239+ * succeeded or failed, but we can never go back to the cs_HANDSHAKE
240+ * or cs_START state again.
241+ *
242+ * Note that the read/write() calls here in SSLSocketImpl are not
243+ * obviously synchronized. In fact, it's very nonintuitive, and
244+ * requires careful examination of code paths. Grab some coffee,
245+ * and be careful with any code changes.
246+ *
247+ * There can be only three threads active at a time in the I/O
248+ * subsection of this class.
249+ * 1. startHandshake
250+ * 2. AppInputStream
251+ * 3. AppOutputStream
252+ * One thread could call startHandshake().
253+ * AppInputStream/AppOutputStream read() and write() calls are each
254+ * synchronized on 'this' in their respective classes, so only one
255+ * app. thread will be doing a SSLSocketImpl.read() or .write()'s at
256+ * a time.
257+ *
258+ * If handshaking is required (state cs_HANDSHAKE), and
259+ * getConnectionState() for some/all threads returns cs_HANDSHAKE,
260+ * only one can grab the handshakeLock, and the rest will stall
261+ * either on getConnectionState(), or on the handshakeLock if they
262+ * happen to successfully race through the getConnectionState().
263+ *
264+ * If a writer is doing the initial handshaking, it must create a
265+ * temporary reader to read the responses from the other side. As a
266+ * side-effect, the writer's reader will have priority over any
267+ * other reader. However, the writer's reader is not allowed to
268+ * consume any application data. When handshakeLock is finally
269+ * released, we either have a cs_DATA connection, or a
270+ * cs_CLOSED/cs_ERROR socket.
271+ *
272+ * The writeLock is held while writing on a socket connection and
273+ * also to protect the MAC and cipher for their direction. The
274+ * writeLock is package private for Handshaker which holds it while
275+ * writing the ChangeCipherSpec message.
276+ *
277+ * To avoid the problem of a thread trying to change operational
278+ * modes on a socket while handshaking is going on, we synchronize
279+ * on 'this'. If handshaking has not started yet, we tell the
280+ * handshaker to change its mode. If handshaking has started,
281+ * we simply store that request until the next pending session
282+ * is created, at which time the new handshaker's state is set.
283+ *
284+ * The readLock is held during readRecord(), which is responsible
285+ * for reading an InputRecord, decrypting it, and processing it.
286+ * The readLock ensures that these three steps are done atomically
287+ * and that once started, no other thread can block on InputRecord.read.
288+ * This is necessary so that processing of close_notify alerts
289+ * from the peer are handled properly.
290+ */
291+ final private Object handshakeLock = new Object();
292+ final ReentrantLock writeLock = new ReentrantLock();
293+ final private Object readLock = new Object();
294+
295+ private InputRecord inrec;
296+
297+ /*
298+ * Crypto state that's reinitialized when the session changes.
299+ */
300+ private MAC readMAC, writeMAC;
301+ private CipherBox readCipher, writeCipher;
302+ // NOTE: compression state would be saved here
303+
304+ /*
305+ * security parameters for secure renegotiation.
306+ */
307+ private boolean secureRenegotiation;
308+ private byte[] clientVerifyData;
309+ private byte[] serverVerifyData;
310+
311+ /*
312+ * The authentication context holds all information used to establish
313+ * who this end of the connection is (certificate chains, private keys,
314+ * etc) and who is trusted (e.g. as CAs or websites).
315+ */
316+ private SSLContextImpl sslContext;
317+
318+
319+ /*
320+ * This connection is one of (potentially) many associated with
321+ * any given session. The output of the handshake protocol is a
322+ * new session ... although all the protocol description talks
323+ * about changing the cipher spec (and it does change), in fact
324+ * that's incidental since it's done by changing everything that
325+ * is associated with a session at the same time. (TLS/IETF may
326+ * change that to add client authentication w/o new key exchg.)
327+ */
328+ private Handshaker handshaker;
329+ private SSLSessionImpl sess;
330+ private volatile SSLSessionImpl handshakeSession;
331+
332+
333+ /*
334+ * If anyone wants to get notified about handshake completions,
335+ * they'll show up on this list.
336+ */
337+ private HashMap<HandshakeCompletedListener, AccessControlContext>
338+ handshakeListeners;
339+
340+ /*
341+ * Reuse the same internal input/output streams.
342+ */
343+ private InputStream sockInput;
344+ private OutputStream sockOutput;
345+
346+
347+ /*
348+ * These input and output streams block their data in SSL records,
349+ * and usually arrange integrity and privacy protection for those
350+ * records. The guts of the SSL protocol are wrapped up in these
351+ * streams, and in the handshaking that establishes the details of
352+ * that integrity and privacy protection.
353+ */
354+ private AppInputStream input;
355+ private AppOutputStream output;
356+
357+ /*
358+ * The protocol versions enabled for use on this connection.
359+ *
360+ * Note: we support a pseudo protocol called SSLv2Hello which when
361+ * set will result in an SSL v2 Hello being sent with SSL (version 3.0)
362+ * or TLS (version 3.1, 3.2, etc.) version info.
363+ */
364+ private ProtocolList enabledProtocols;
365+
366+ /*
367+ * The SSL version associated with this connection.
368+ */
369+ private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT;
370+
371+ /* Class and subclass dynamic debugging support */
372+ private static final Debug debug = Debug.getInstance("ssl");
373+
374+ //
375+ // CONSTRUCTORS AND INITIALIZATION CODE
376+ //
377+
378+ /**
379+ * Constructs an SSL connection to a named host at a specified port,
380+ * using the authentication context provided. This endpoint acts as
381+ * the client, and may rejoin an existing SSL session if appropriate.
382+ *
383+ * @param context authentication context to use
384+ * @param host name of the host with which to connect
385+ * @param port number of the server's port
386+ */
387+ SSLSocketImpl(SSLContextImpl context, String host, int port)
388+ throws IOException, UnknownHostException {
389+ super();
390+ this.host = host;
391+ this.rawHostname = host;
392+ init(context, false);
393+ SocketAddress socketAddress =
394+ host != null ? new InetSocketAddress(host, port) :
395+ new InetSocketAddress(InetAddress.getByName(null), port);
396+ connect(socketAddress, 0);
397+ }
398+
399+
400+ /**
401+ * Constructs an SSL connection to a server at a specified address.
402+ * and TCP port, using the authentication context provided. This
403+ * endpoint acts as the client, and may rejoin an existing SSL session
404+ * if appropriate.
405+ *
406+ * @param context authentication context to use
407+ * @param address the server's host
408+ * @param port its port
409+ */
410+ SSLSocketImpl(SSLContextImpl context, InetAddress host, int port)
411+ throws IOException {
412+ super();
413+ init(context, false);
414+ SocketAddress socketAddress = new InetSocketAddress(host, port);
415+ connect(socketAddress, 0);
416+ }
417+
418+ /**
419+ * Constructs an SSL connection to a named host at a specified port,
420+ * using the authentication context provided. This endpoint acts as
421+ * the client, and may rejoin an existing SSL session if appropriate.
422+ *
423+ * @param context authentication context to use
424+ * @param host name of the host with which to connect
425+ * @param port number of the server's port
426+ * @param localAddr the local address the socket is bound to
427+ * @param localPort the local port the socket is bound to
428+ */
429+ SSLSocketImpl(SSLContextImpl context, String host, int port,
430+ InetAddress localAddr, int localPort)
431+ throws IOException, UnknownHostException {
432+ super();
433+ this.host = host;
434+ this.rawHostname = host;
435+ init(context, false);
436+ bind(new InetSocketAddress(localAddr, localPort));
437+ SocketAddress socketAddress =
438+ host != null ? new InetSocketAddress(host, port) :
439+ new InetSocketAddress(InetAddress.getByName(null), port);
440+ connect(socketAddress, 0);
441+ }
442+
443+
444+ /**
445+ * Constructs an SSL connection to a server at a specified address.
446+ * and TCP port, using the authentication context provided. This
447+ * endpoint acts as the client, and may rejoin an existing SSL session
448+ * if appropriate.
449+ *
450+ * @param context authentication context to use
451+ * @param address the server's host
452+ * @param port its port
453+ * @param localAddr the local address the socket is bound to
454+ * @param localPort the local port the socket is bound to
455+ */
456+ SSLSocketImpl(SSLContextImpl context, InetAddress host, int port,
457+ InetAddress localAddr, int localPort)
458+ throws IOException {
459+ super();
460+ init(context, false);
461+ bind(new InetSocketAddress(localAddr, localPort));
462+ SocketAddress socketAddress = new InetSocketAddress(host, port);
463+ connect(socketAddress, 0);
464+ }
465+
466+ /*
467+ * Package-private constructor used ONLY by SSLServerSocket. The
468+ * java.net package accepts the TCP connection after this call is
469+ * made. This just initializes handshake state to use "server mode",
470+ * giving control over the use of SSL client authentication.
471+ */
472+ SSLSocketImpl(SSLContextImpl context, boolean serverMode,
473+ CipherSuiteList suites, byte clientAuth,
474+ boolean sessionCreation, ProtocolList protocols,
475+ String identificationProtocol,
476+ AlgorithmConstraints algorithmConstraints) throws IOException {
477+
478+ super();
479+ doClientAuth = clientAuth;
480+ enableSessionCreation = sessionCreation;
481+ this.identificationProtocol = identificationProtocol;
482+ this.algorithmConstraints = algorithmConstraints;
483+ init(context, serverMode);
484+
485+ /*
486+ * Override what was picked out for us.
487+ */
488+ enabledCipherSuites = suites;
489+ enabledProtocols = protocols;
490+ }
491+
492+
493+ /**
494+ * Package-private constructor used to instantiate an unconnected
495+ * socket. The java.net package will connect it, either when the
496+ * connect() call is made by the application. This instance is
497+ * meant to set handshake state to use "client mode".
498+ */
499+ SSLSocketImpl(SSLContextImpl context) {
500+ super();
501+ init(context, false);
502+ }
503+
504+
505+ /**
506+ * Layer SSL traffic over an existing connection, rather than creating
507+ * a new connection. The existing connection may be used only for SSL
508+ * traffic (using this SSLSocket) until the SSLSocket.close() call
509+ * returns. However, if a protocol error is detected, that existing
510+ * connection is automatically closed.
511+ *
512+ * <P> This particular constructor always uses the socket in the
513+ * role of an SSL client. It may be useful in cases which start
514+ * using SSL after some initial data transfers, for example in some
515+ * SSL tunneling applications or as part of some kinds of application
516+ * protocols which negotiate use of a SSL based security.
517+ *
518+ * @param sock the existing connection
519+ * @param context the authentication context to use
520+ */
521+ SSLSocketImpl(SSLContextImpl context, Socket sock, String host,
522+ int port, boolean autoClose) throws IOException {
523+ super(sock);
524+ // We always layer over a connected socket
525+ if (!sock.isConnected()) {
526+ throw new SocketException("Underlying socket is not connected");
527+ }
528+ this.host = host;
529+ this.rawHostname = host;
530+ init(context, false);
531+ this.autoClose = autoClose;
532+ doneConnect();
533+ }
534+
535+ /**
536+ * Initializes the client socket.
537+ */
538+ private void init(SSLContextImpl context, boolean isServer) {
539+ sslContext = context;
540+ sess = SSLSessionImpl.nullSession;
541+ handshakeSession = null;
542+
543+ /*
544+ * role is as specified, state is START until after
545+ * the low level connection's established.
546+ */
547+ roleIsServer = isServer;
548+ connectionState = cs_START;
549+
550+ /*
551+ * default read and write side cipher and MAC support
552+ *
553+ * Note: compression support would go here too
554+ */
555+ readCipher = CipherBox.NULL;
556+ readMAC = MAC.NULL;
557+ writeCipher = CipherBox.NULL;
558+ writeMAC = MAC.NULL;
559+
560+ // initial security parameters for secure renegotiation
561+ secureRenegotiation = false;
562+ clientVerifyData = new byte[0];
563+ serverVerifyData = new byte[0];
564+
565+ enabledCipherSuites =
566+ sslContext.getDefaultCipherSuiteList(roleIsServer);
567+ enabledProtocols =
568+ sslContext.getDefaultProtocolList(roleIsServer);
569+
570+ inrec = null;
571+
572+ // save the acc
573+ acc = AccessController.getContext();
574+
575+ input = new AppInputStream(this);
576+ output = new AppOutputStream(this);
577+ }
578+
579+ /**
580+ * Connects this socket to the server with a specified timeout
581+ * value.
582+ *
583+ * This method is either called on an unconnected SSLSocketImpl by the
584+ * application, or it is called in the constructor of a regular
585+ * SSLSocketImpl. If we are layering on top on another socket, then
586+ * this method should not be called, because we assume that the
587+ * underlying socket is already connected by the time it is passed to
588+ * us.
589+ *
590+ * @param endpoint the <code>SocketAddress</code>
591+ * @param timeout the timeout value to be used, 0 is no timeout
592+ * @throws IOException if an error occurs during the connection
593+ * @throws SocketTimeoutException if timeout expires before connecting
594+ */
595+ public void connect(SocketAddress endpoint, int timeout)
596+ throws IOException {
597+
598+ if (self != this) {
599+ throw new SocketException("Already connected");
600+ }
601+
602+ if (!(endpoint instanceof InetSocketAddress)) {
603+ throw new SocketException(
604+ "Cannot handle non-Inet socket addresses.");
605+ }
606+
607+ super.connect(endpoint, timeout);
608+ doneConnect();
609+ }
610+
611+ /**
612+ * Initialize the handshaker and socket streams.
613+ *
614+ * Called by connect, the layered constructor, and SSLServerSocket.
615+ */
616+ void doneConnect() throws IOException {
617+ /*
618+ * Save the input and output streams. May be done only after
619+ * java.net actually connects using the socket "self", else
620+ * we get some pretty bizarre failure modes.
621+ */
622+ if (self == this) {
623+ sockInput = super.getInputStream();
624+ sockOutput = super.getOutputStream();
625+ } else {
626+ sockInput = self.getInputStream();
627+ sockOutput = self.getOutputStream();
628+ }
629+
630+ /*
631+ * Move to handshaking state, with pending session initialized
632+ * to defaults and the appropriate kind of handshaker set up.
633+ */
634+ initHandshaker();
635+ }
636+
637+ synchronized private int getConnectionState() {
638+ return connectionState;
639+ }
640+
641+ synchronized private void setConnectionState(int state) {
642+ connectionState = state;
643+ }
644+
645+ AccessControlContext getAcc() {
646+ return acc;
647+ }
648+
649+ //
650+ // READING AND WRITING RECORDS
651+ //
652+
653+ /*
654+ * Record Output. Application data can't be sent until the first
655+ * handshake establishes a session.
656+ *
657+ * NOTE: we let empty records be written as a hook to force some
658+ * TCP-level activity, notably handshaking, to occur.
659+ */
660+ void writeRecord(OutputRecord r) throws IOException {
661+ /*
662+ * The loop is in case of HANDSHAKE --> ERROR transitions, etc
663+ */
664+ loop:
665+ while (r.contentType() == Record.ct_application_data) {
666+ /*
667+ * Not all states support passing application data. We
668+ * synchronize access to the connection state, so that
669+ * synchronous handshakes can complete cleanly.
670+ */
671+ switch (getConnectionState()) {
672+
673+ /*
674+ * We've deferred the initial handshaking till just now,
675+ * when presumably a thread's decided it's OK to block for
676+ * longish periods of time for I/O purposes (as well as
677+ * configured the cipher suites it wants to use).
678+ */
679+ case cs_HANDSHAKE:
680+ performInitialHandshake();
681+ break;
682+
683+ case cs_DATA:
684+ case cs_RENEGOTIATE:
685+ break loop;
686+
687+ case cs_ERROR:
688+ fatal(Alerts.alert_close_notify,
689+ "error while writing to socket");
690+ break; // dummy
691+
692+ case cs_SENT_CLOSE:
693+ case cs_CLOSED:
694+ case cs_APP_CLOSED:
695+ // we should never get here (check in AppOutputStream)
696+ // this is just a fallback
697+ if (closeReason != null) {
698+ throw closeReason;
699+ } else {
700+ throw new SocketException("Socket closed");
701+ }
702+
703+ /*
704+ * Else something's goofy in this state machine's use.
705+ */
706+ default:
707+ throw new SSLProtocolException("State error, send app data");
708+ }
709+ }
710+
711+ //
712+ // Don't bother to really write empty records. We went this
713+ // far to drive the handshake machinery, for correctness; not
714+ // writing empty records improves performance by cutting CPU
715+ // time and network resource usage. However, some protocol
716+ // implementations are fragile and don't like to see empty
717+ // records, so this also increases robustness.
718+ //
719+ if (!r.isEmpty()) {
720+
721+ // If the record is a close notify alert, we need to honor
722+ // socket option SO_LINGER. Note that we will try to send
723+ // the close notify even if the SO_LINGER set to zero.
724+ if (r.isAlert(Alerts.alert_close_notify) && getSoLinger() >= 0) {
725+
726+ // keep and clear the current thread interruption status.
727+ boolean interrupted = Thread.interrupted();
728+ try {
729+ if (writeLock.tryLock(getSoLinger(), TimeUnit.SECONDS)) {
730+ try {
731+ writeRecordInternal(r);
732+ } finally {
733+ writeLock.unlock();
734+ }
735+ } else {
736+ SSLException ssle = new SSLException(
737+ "SO_LINGER timeout," +
738+ " close_notify message cannot be sent.");
739+
740+
741+ // For layered, non-autoclose sockets, we are not
742+ // able to bring them into a usable state, so we
743+ // treat it as fatal error.
744+ if (self != this && !autoClose) {
745+ // Note that the alert description is
746+ // specified as -1, so no message will be send
747+ // to peer anymore.
748+ fatal((byte)(-1), ssle);
749+ } else if ((debug != null) && Debug.isOn("ssl")) {
750+ System.out.println(threadName() +
751+ ", received Exception: " + ssle);
752+ }
753+
754+ // RFC2246 requires that the session becomes
755+ // unresumable if any connection is terminated
756+ // without proper close_notify messages with
757+ // level equal to warning.
758+ //
759+ // RFC4346 no longer requires that a session not be
760+ // resumed if failure to properly close a connection.
761+ //
762+ // We choose to make the session unresumable if
763+ // failed to send the close_notify message.
764+ //
765+ sess.invalidate();
766+ }
767+ } catch (InterruptedException ie) {
768+ // keep interrupted status
769+ interrupted = true;
770+ }
771+
772+ // restore the interrupted status
773+ if (interrupted) {
774+ Thread.currentThread().interrupt();
775+ }
776+ } else {
777+ writeLock.lock();
778+ try {
779+ writeRecordInternal(r);
780+ } finally {
781+ writeLock.unlock();
782+ }
783+ }
784+ }
785+ }
786+
787+ private void writeRecordInternal(OutputRecord r) throws IOException {
788+ // r.compress(c);
789+ r.addMAC(writeMAC);
790+ r.encrypt(writeCipher);
791+ r.write(sockOutput);
792+
793+ /*
794+ * Check the sequence number state
795+ *
796+ * Note that in order to maintain the connection I/O
797+ * properly, we check the sequence number after the last
798+ * record writing process. As we request renegotiation
799+ * or close the connection for wrapped sequence number
800+ * when there is enough sequence number space left to
801+ * handle a few more records, so the sequence number
802+ * of the last record cannot be wrapped.
803+ */
804+ if (connectionState < cs_ERROR) {
805+ checkSequenceNumber(writeMAC, r.contentType());
806+ }
807+ }
808+
809+
810+ /*
811+ * Read an application data record. Alerts and handshake
812+ * messages are handled directly.
813+ */
814+ void readDataRecord(InputRecord r) throws IOException {
815+ if (getConnectionState() == cs_HANDSHAKE) {
816+ performInitialHandshake();
817+ }
818+ readRecord(r, true);
819+ }
820+
821+
822+ /*
823+ * Clear the pipeline of records from the peer, optionally returning
824+ * application data. Caller is responsible for knowing that it's
825+ * possible to do this kind of clearing, if they don't want app
826+ * data -- e.g. since it's the initial SSL handshake.
827+ *
828+ * Don't synchronize (this) during a blocking read() since it
829+ * protects data which is accessed on the write side as well.
830+ */
831+ private void readRecord(InputRecord r, boolean needAppData)
832+ throws IOException {
833+ int state;
834+
835+ // readLock protects reading and processing of an InputRecord.
836+ // It keeps the reading from sockInput and processing of the record
837+ // atomic so that no two threads can be blocked on the
838+ // read from the same input stream at the same time.
839+ // This is required for example when a reader thread is
840+ // blocked on the read and another thread is trying to
841+ // close the socket. For a non-autoclose, layered socket,
842+ // the thread performing the close needs to read the close_notify.
843+ //
844+ // Use readLock instead of 'this' for locking because
845+ // 'this' also protects data accessed during writing.
846+ synchronized (readLock) {
847+ /*
848+ * Read and handle records ... return application data
849+ * ONLY if it's needed.
850+ */
851+
852+ while (((state = getConnectionState()) != cs_CLOSED) &&
853+ (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
854+ /*
855+ * Read a record ... maybe emitting an alert if we get a
856+ * comprehensible but unsupported "hello" message during
857+ * format checking (e.g. V2).
858+ */
859+ try {
860+ r.setAppDataValid(false);
861+ r.read(sockInput, sockOutput);
862+ } catch (SSLProtocolException e) {
863+ try {
864+ fatal(Alerts.alert_unexpected_message, e);
865+ } catch (IOException x) {
866+ // discard this exception
867+ }
868+ throw e;
869+ } catch (EOFException eof) {
870+ boolean handshaking = (getConnectionState() <= cs_HANDSHAKE);
871+ boolean rethrow = requireCloseNotify || handshaking;
872+ if ((debug != null) && Debug.isOn("ssl")) {
873+ System.out.println(threadName() +
874+ ", received EOFException: "
875+ + (rethrow ? "error" : "ignored"));
876+ }
877+ if (rethrow) {
878+ SSLException e;
879+ if (handshaking) {
880+ e = new SSLHandshakeException
881+ ("Remote host closed connection during handshake");
882+ } else {
883+ e = new SSLProtocolException
884+ ("Remote host closed connection incorrectly");
885+ }
886+ e.initCause(eof);
887+ throw e;
888+ } else {
889+ // treat as if we had received a close_notify
890+ closeInternal(false);
891+ continue;
892+ }
893+ }
894+
895+
896+ /*
897+ * The basic SSLv3 record protection involves (optional)
898+ * encryption for privacy, and an integrity check ensuring
899+ * data origin authentication. We do them both here, and
900+ * throw a fatal alert if the integrity check fails.
901+ */
902+ try {
903+ r.decrypt(readCipher);
904+ } catch (BadPaddingException e) {
905+ // RFC 2246 states that decryption_failed should be used
906+ // for this purpose. However, that allows certain attacks,
907+ // so we just send bad record MAC. We also need to make
908+ // sure to always check the MAC to avoid a timing attack
909+ // for the same issue. See paper by Vaudenay et al.
910+ r.checkMAC(readMAC);
911+ // use the same alert types as for MAC failure below
912+ byte alertType = (r.contentType() == Record.ct_handshake)
913+ ? Alerts.alert_handshake_failure
914+ : Alerts.alert_bad_record_mac;
915+ fatal(alertType, "Invalid padding", e);
916+ }
917+ if (!r.checkMAC(readMAC)) {
918+ if (r.contentType() == Record.ct_handshake) {
919+ fatal(Alerts.alert_handshake_failure,
920+ "bad handshake record MAC");
921+ } else {
922+ fatal(Alerts.alert_bad_record_mac, "bad record MAC");
923+ }
924+ }
925+
926+
927+ // if (!r.decompress(c))
928+ // fatal(Alerts.alert_decompression_failure,
929+ // "decompression failure");
930+
931+ /*
932+ * Process the record.
933+ */
934+ synchronized (this) {
935+ switch (r.contentType()) {
936+ case Record.ct_handshake:
937+ /*
938+ * Handshake messages always go to a pending session
939+ * handshaker ... if there isn't one, create one. This
940+ * must work asynchronously, for renegotiation.
941+ *
942+ * NOTE that handshaking will either resume a session
943+ * which was in the cache (and which might have other
944+ * connections in it already), or else will start a new
945+ * session (new keys exchanged) with just this connection
946+ * in it.
947+ */
948+ initHandshaker();
949+ if (!handshaker.activated()) {
950+ // prior to handshaking, activate the handshake
951+ if (connectionState == cs_RENEGOTIATE) {
952+ // don't use SSLv2Hello when renegotiating
953+ handshaker.activate(protocolVersion);
954+ } else {
955+ handshaker.activate(null);
956+ }
957+ }
958+
959+ /*
960+ * process the handshake record ... may contain just
961+ * a partial handshake message or multiple messages.
962+ *
963+ * The handshaker state machine will ensure that it's
964+ * a finished message.
965+ */
966+ handshaker.process_record(r, expectingFinished);
967+ expectingFinished = false;
968+
969+ if (handshaker.invalidated) {
970+ handshaker = null;
971+ // if state is cs_RENEGOTIATE, revert it to cs_DATA
972+ if (connectionState == cs_RENEGOTIATE) {
973+ connectionState = cs_DATA;
974+ }
975+ } else if (handshaker.isDone()) {
976+ // reset the parameters for secure renegotiation.
977+ secureRenegotiation =
978+ handshaker.isSecureRenegotiation();
979+ clientVerifyData = handshaker.getClientVerifyData();
980+ serverVerifyData = handshaker.getServerVerifyData();
981+
982+ sess = handshaker.getSession();
983+ handshakeSession = null;
984+ handshaker = null;
985+ connectionState = cs_DATA;
986+
987+ //
988+ // Tell folk about handshake completion, but do
989+ // it in a separate thread.
990+ //
991+ if (handshakeListeners != null) {
992+ HandshakeCompletedEvent event =
993+ new HandshakeCompletedEvent(this, sess);
994+
995+ Thread t = new NotifyHandshakeThread(
996+ handshakeListeners.entrySet(), event);
997+ t.start();
998+ }
999+ }
1000+
1001+ if (needAppData || connectionState != cs_DATA) {
1002+ continue;
1003+ }
1004+ break;
1005+
1006+ case Record.ct_application_data:
1007+ // Pass this right back up to the application.
1008+ if (connectionState != cs_DATA
1009+ && connectionState != cs_RENEGOTIATE
1010+ && connectionState != cs_SENT_CLOSE) {
1011+ throw new SSLProtocolException(
1012+ "Data received in non-data state: " +
1013+ connectionState);
1014+ }
1015+ if (expectingFinished) {
1016+ throw new SSLProtocolException
1017+ ("Expecting finished message, received data");
1018+ }
1019+ if (!needAppData) {
1020+ throw new SSLException("Discarding app data");
1021+ }
1022+
1023+ r.setAppDataValid(true);
1024+ break;
1025+
1026+ case Record.ct_alert:
1027+ recvAlert(r);
1028+ continue;
1029+
1030+ case Record.ct_change_cipher_spec:
1031+ if ((connectionState != cs_HANDSHAKE
1032+ && connectionState != cs_RENEGOTIATE)
1033+ || r.available() != 1
1034+ || r.read() != 1) {
1035+ fatal(Alerts.alert_unexpected_message,
1036+ "illegal change cipher spec msg, state = "
1037+ + connectionState);
1038+ }
1039+
1040+ //
1041+ // The first message after a change_cipher_spec
1042+ // record MUST be a "Finished" handshake record,
1043+ // else it's a protocol violation. We force this
1044+ // to be checked by a minor tweak to the state
1045+ // machine.
1046+ //
1047+ changeReadCiphers();
1048+ // next message MUST be a finished message
1049+ expectingFinished = true;
1050+ continue;
1051+
1052+ default:
1053+ //
1054+ // TLS requires that unrecognized records be ignored.
1055+ //
1056+ if (debug != null && Debug.isOn("ssl")) {
1057+ System.out.println(threadName() +
1058+ ", Received record type: "
1059+ + r.contentType());
1060+ }
1061+ continue;
1062+ } // switch
1063+
1064+ /*
1065+ * Check the sequence number state
1066+ *
1067+ * Note that in order to maintain the connection I/O
1068+ * properly, we check the sequence number after the last
1069+ * record reading process. As we request renegotiation
1070+ * or close the connection for wrapped sequence number
1071+ * when there is enough sequence number space left to
1072+ * handle a few more records, so the sequence number
1073+ * of the last record cannot be wrapped.
1074+ */
1075+ if (connectionState < cs_ERROR) {
1076+ checkSequenceNumber(readMAC, r.contentType());
1077+ }
1078+
1079+ return;
1080+ } // synchronized (this)
1081+ }
1082+
1083+ //
1084+ // couldn't read, due to some kind of error
1085+ //
1086+ r.close();
1087+ return;
1088+ } // synchronized (readLock)
1089+ }
1090+
1091+ /**
1092+ * Check the sequence number state
1093+ *
1094+ * RFC 4346 states that, "Sequence numbers are of type uint64 and
1095+ * may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS
1096+ * implementation would need to wrap a sequence number, it must
1097+ * renegotiate instead."
1098+ */
1099+ private void checkSequenceNumber(MAC mac, byte type)
1100+ throws IOException {
1101+
1102+ /*
1103+ * Don't bother to check the sequence number for error or
1104+ * closed connections, or NULL MAC.
1105+ */
1106+ if (connectionState >= cs_ERROR || mac == MAC.NULL) {
1107+ return;
1108+ }
1109+
1110+ /*
1111+ * Conservatively, close the connection immediately when the
1112+ * sequence number is close to overflow
1113+ */
1114+ if (mac.seqNumOverflow()) {
1115+ /*
1116+ * TLS protocols do not define a error alert for sequence
1117+ * number overflow. We use handshake_failure error alert
1118+ * for handshaking and bad_record_mac for other records.
1119+ */
1120+ if (debug != null && Debug.isOn("ssl")) {
1121+ System.out.println(threadName() +
1122+ ", sequence number extremely close to overflow " +
1123+ "(2^64-1 packets). Closing connection.");
1124+
1125+ }
1126+
1127+ fatal(Alerts.alert_handshake_failure, "sequence number overflow");
1128+ }
1129+
1130+ /*
1131+ * Ask for renegotiation when need to renew sequence number.
1132+ *
1133+ * Don't bother to kickstart the renegotiation when the local is
1134+ * asking for it.
1135+ */
1136+ if ((type != Record.ct_handshake) && mac.seqNumIsHuge()) {
1137+ if (debug != null && Debug.isOn("ssl")) {
1138+ System.out.println(threadName() + ", request renegotiation " +
1139+ "to avoid sequence number overflow");
1140+ }
1141+
1142+ startHandshake();
1143+ }
1144+ }
1145+
1146+ //
1147+ // HANDSHAKE RELATED CODE
1148+ //
1149+
1150+ /**
1151+ * Return the AppInputStream. For use by Handshaker only.
1152+ */
1153+ AppInputStream getAppInputStream() {
1154+ return input;
1155+ }
1156+
1157+ /**
1158+ * Return the AppOutputStream. For use by Handshaker only.
1159+ */
1160+ AppOutputStream getAppOutputStream() {
1161+ return output;
1162+ }
1163+
1164+ /**
1165+ * Initialize the handshaker object. This means:
1166+ *
1167+ * . if a handshake is already in progress (state is cs_HANDSHAKE
1168+ * or cs_RENEGOTIATE), do nothing and return
1169+ *
1170+ * . if the socket is already closed, throw an Exception (internal error)
1171+ *
1172+ * . otherwise (cs_START or cs_DATA), create the appropriate handshaker
1173+ * object, and advance the connection state (to cs_HANDSHAKE or
1174+ * cs_RENEGOTIATE, respectively).
1175+ *
1176+ * This method is called right after a new socket is created, when
1177+ * starting renegotiation, or when changing client/ server mode of the
1178+ * socket.
1179+ */
1180+ private void initHandshaker() {
1181+ switch (connectionState) {
1182+
1183+ //
1184+ // Starting a new handshake.
1185+ //
1186+ case cs_START:
1187+ case cs_DATA:
1188+ break;
1189+
1190+ //
1191+ // We're already in the middle of a handshake.
1192+ //
1193+ case cs_HANDSHAKE:
1194+ case cs_RENEGOTIATE:
1195+ return;
1196+
1197+ //
1198+ // Anyone allowed to call this routine is required to
1199+ // do so ONLY if the connection state is reasonable...
1200+ //
1201+ default:
1202+ throw new IllegalStateException("Internal error");
1203+ }
1204+
1205+ // state is either cs_START or cs_DATA
1206+ if (connectionState == cs_START) {
1207+ connectionState = cs_HANDSHAKE;
1208+ } else { // cs_DATA
1209+ connectionState = cs_RENEGOTIATE;
1210+ }
1211+ if (roleIsServer) {
1212+ handshaker = new ServerHandshaker(this, sslContext,
1213+ enabledProtocols, doClientAuth,
1214+ protocolVersion, connectionState == cs_HANDSHAKE,
1215+ secureRenegotiation, clientVerifyData, serverVerifyData);
1216+ } else {
1217+ handshaker = new ClientHandshaker(this, sslContext,
1218+ enabledProtocols,
1219+ protocolVersion, connectionState == cs_HANDSHAKE,
1220+ secureRenegotiation, clientVerifyData, serverVerifyData);
1221+ }
1222+ handshaker.setEnabledCipherSuites(enabledCipherSuites);
1223+ handshaker.setEnableSessionCreation(enableSessionCreation);
1224+ }
1225+
1226+ /**
1227+ * Synchronously perform the initial handshake.
1228+ *
1229+ * If the handshake is already in progress, this method blocks until it
1230+ * is completed. If the initial handshake has already been completed,
1231+ * it returns immediately.
1232+ */
1233+ private void performInitialHandshake() throws IOException {
1234+ // use handshakeLock and the state check to make sure only
1235+ // one thread performs the handshake
1236+ synchronized (handshakeLock) {
1237+ if (getConnectionState() == cs_HANDSHAKE) {
1238+ kickstartHandshake();
1239+
1240+ /*
1241+ * All initial handshaking goes through this
1242+ * InputRecord until we have a valid SSL connection.
1243+ * Once initial handshaking is finished, AppInputStream's
1244+ * InputRecord can handle any future renegotiation.
1245+ *
1246+ * Keep this local so that it goes out of scope and is
1247+ * eventually GC'd.
1248+ */
1249+ if (inrec == null) {
1250+ inrec = new InputRecord();
1251+
1252+ /*
1253+ * Grab the characteristics already assigned to
1254+ * AppInputStream's InputRecord. Enable checking for
1255+ * SSLv2 hellos on this first handshake.
1256+ */
1257+ inrec.setHandshakeHash(input.r.getHandshakeHash());
1258+ inrec.setHelloVersion(input.r.getHelloVersion());
1259+ inrec.enableFormatChecks();
1260+ }
1261+
1262+ readRecord(inrec, false);
1263+ inrec = null;
1264+ }
1265+ }
1266+ }
1267+
1268+ /**
1269+ * Starts an SSL handshake on this connection.
1270+ */
1271+ public void startHandshake() throws IOException {
1272+ // start an ssl handshake that could be resumed from timeout exception
1273+ startHandshake(true);
1274+ }
1275+
1276+ /**
1277+ * Starts an ssl handshake on this connection.
1278+ *
1279+ * @param resumable indicates the handshake process is resumable from a
1280+ * certain exception. If <code>resumable</code>, the socket will
1281+ * be reserved for exceptions like timeout; otherwise, the socket
1282+ * will be closed, no further communications could be done.
1283+ */
1284+ private void startHandshake(boolean resumable) throws IOException {
1285+ checkWrite();
1286+ try {
1287+ if (getConnectionState() == cs_HANDSHAKE) {
1288+ // do initial handshake
1289+ performInitialHandshake();
1290+ } else {
1291+ // start renegotiation
1292+ kickstartHandshake();
1293+ }
1294+ } catch (Exception e) {
1295+ // shutdown and rethrow (wrapped) exception as appropriate
1296+ handleException(e, resumable);
1297+ }
1298+ }
1299+
1300+ /**
1301+ * Kickstart the handshake if it is not already in progress.
1302+ * This means:
1303+ *
1304+ * . if handshaking is already underway, do nothing and return
1305+ *
1306+ * . if the socket is not connected or already closed, throw an
1307+ * Exception.
1308+ *
1309+ * . otherwise, call initHandshake() to initialize the handshaker
1310+ * object and progress the state. Then, send the initial
1311+ * handshaking message if appropriate (always on clients and
1312+ * on servers when renegotiating).
1313+ */
1314+ private synchronized void kickstartHandshake() throws IOException {
1315+
1316+ switch (connectionState) {
1317+
1318+ case cs_HANDSHAKE:
1319+ // handshaker already setup, proceed
1320+ break;
1321+
1322+ case cs_DATA:
1323+ if (!secureRenegotiation && !Handshaker.allowUnsafeRenegotiation) {
1324+ throw new SSLHandshakeException(
1325+ "Insecure renegotiation is not allowed");
1326+ }
1327+
1328+ if (!secureRenegotiation) {
1329+ if (debug != null && Debug.isOn("handshake")) {
1330+ System.out.println(
1331+ "Warning: Using insecure renegotiation");
1332+ }
1333+ }
1334+
1335+ // initialize the handshaker, move to cs_RENEGOTIATE
1336+ initHandshaker();
1337+ break;
1338+
1339+ case cs_RENEGOTIATE:
1340+ // handshaking already in progress, return
1341+ return;
1342+
1343+ /*
1344+ * The only way to get a socket in the state is when
1345+ * you have an unconnected socket.
1346+ */
1347+ case cs_START:
1348+ throw new SocketException(
1349+ "handshaking attempted on unconnected socket");
1350+
1351+ default:
1352+ throw new SocketException("connection is closed");
1353+ }
1354+
1355+ //
1356+ // Kickstart handshake state machine if we need to ...
1357+ //
1358+ // Note that handshaker.kickstart() writes the message
1359+ // to its HandshakeOutStream, which calls back into
1360+ // SSLSocketImpl.writeRecord() to send it.
1361+ //
1362+ if (!handshaker.activated()) {
1363+ // prior to handshaking, activate the handshake
1364+ if (connectionState == cs_RENEGOTIATE) {
1365+ // don't use SSLv2Hello when renegotiating
1366+ handshaker.activate(protocolVersion);
1367+ } else {
1368+ handshaker.activate(null);
1369+ }
1370+
1371+ if (handshaker instanceof ClientHandshaker) {
1372+ // send client hello
1373+ handshaker.kickstart();
1374+ } else {
1375+ if (connectionState == cs_HANDSHAKE) {
1376+ // initial handshake, no kickstart message to send
1377+ } else {
1378+ // we want to renegotiate, send hello request
1379+ handshaker.kickstart();
1380+ // hello request is not included in the handshake
1381+ // hashes, reset them
1382+ handshaker.handshakeHash.reset();
1383+ }
1384+ }
1385+ }
1386+ }
1387+
1388+ //
1389+ // CLOSURE RELATED CALLS
1390+ //
1391+
1392+ /**
1393+ * Return whether the socket has been explicitly closed by the application.
1394+ */
1395+ public boolean isClosed() {
1396+ return getConnectionState() == cs_APP_CLOSED;
1397+ }
1398+
1399+ /**
1400+ * Return whether we have reached end-of-file.
1401+ *
1402+ * If the socket is not connected, has been shutdown because of an error
1403+ * or has been closed, throw an Exception.
1404+ */
1405+ boolean checkEOF() throws IOException {
1406+ switch (getConnectionState()) {
1407+ case cs_START:
1408+ throw new SocketException("Socket is not connected");
1409+
1410+ case cs_HANDSHAKE:
1411+ case cs_DATA:
1412+ case cs_RENEGOTIATE:
1413+ case cs_SENT_CLOSE:
1414+ return false;
1415+
1416+ case cs_APP_CLOSED:
1417+ throw new SocketException("Socket is closed");
1418+
1419+ case cs_ERROR:
1420+ case cs_CLOSED:
1421+ default:
1422+ // either closed because of error, or normal EOF
1423+ if (closeReason == null) {
1424+ return true;
1425+ }
1426+ IOException e = new SSLException
1427+ ("Connection has been shutdown: " + closeReason);
1428+ e.initCause(closeReason);
1429+ throw e;
1430+
1431+ }
1432+ }
1433+
1434+ /**
1435+ * Check if we can write data to this socket. If not, throw an IOException.
1436+ */
1437+ void checkWrite() throws IOException {
1438+ if (checkEOF() || (getConnectionState() == cs_SENT_CLOSE)) {
1439+ // we are at EOF, write must throw Exception
1440+ throw new SocketException("Connection closed by remote host");
1441+ }
1442+ }
1443+
1444+ protected void closeSocket() throws IOException {
1445+
1446+ if ((debug != null) && Debug.isOn("ssl")) {
1447+ System.out.println(threadName() + ", called closeSocket()");
1448+ }
1449+ if (self == this) {
1450+ super.close();
1451+ } else {
1452+ self.close();
1453+ }
1454+ }
1455+
1456+ private void closeSocket(boolean selfInitiated) throws IOException {
1457+ if ((debug != null) && Debug.isOn("ssl")) {
1458+ System.out.println(threadName() + ", called closeSocket(selfInitiated)");
1459+ }
1460+ if (self == this) {
1461+ super.close();
1462+ } else if (autoClose) {
1463+ self.close();
1464+ } else if (selfInitiated) {
1465+ // layered && non-autoclose
1466+ // read close_notify alert to clear input stream
1467+ waitForClose(false);
1468+ }
1469+ }
1470+
1471+ /*
1472+ * Closing the connection is tricky ... we can't officially close the
1473+ * connection until we know the other end is ready to go away too,
1474+ * and if ever the connection gets aborted we must forget session
1475+ * state (it becomes invalid).
1476+ */
1477+
1478+ /**
1479+ * Closes the SSL connection. SSL includes an application level
1480+ * shutdown handshake; you should close SSL sockets explicitly
1481+ * rather than leaving it for finalization, so that your remote
1482+ * peer does not experience a protocol error.
1483+ */
1484+ public void close() throws IOException {
1485+ if ((debug != null) && Debug.isOn("ssl")) {
1486+ System.out.println(threadName() + ", called close()");
1487+ }
1488+ closeInternal(true); // caller is initiating close
1489+ setConnectionState(cs_APP_CLOSED);
1490+ }
1491+
1492+ /**
1493+ * Don't synchronize the whole method because waitForClose()
1494+ * (which calls readRecord()) might be called.
1495+ *
1496+ * @param selfInitiated Indicates which party initiated the close.
1497+ * If selfInitiated, this side is initiating a close; for layered and
1498+ * non-autoclose socket, wait for close_notify response.
1499+ * If !selfInitiated, peer sent close_notify; we reciprocate but
1500+ * no need to wait for response.
1501+ */
1502+ private void closeInternal(boolean selfInitiated) throws IOException {
1503+ if ((debug != null) && Debug.isOn("ssl")) {
1504+ System.out.println(threadName() + ", called closeInternal("
1505+ + selfInitiated + ")");
1506+ }
1507+
1508+ int state = getConnectionState();
1509+ boolean closeSocketCalled = false;
1510+ Throwable cachedThrowable = null;
1511+ try {
1512+ switch (state) {
1513+ /*
1514+ * java.net code sometimes closes sockets "early", when
1515+ * we can't actually do I/O on them.
1516+ */
1517+ case cs_START:
1518+ break;
1519+
1520+ /*
1521+ * If we're closing down due to error, we already sent (or else
1522+ * received) the fatal alert ... no niceties, blow the connection
1523+ * away as quickly as possible (even if we didn't allocate the
1524+ * socket ourselves; it's unusable, regardless).
1525+ */
1526+ case cs_ERROR:
1527+ closeSocket();
1528+ break;
1529+
1530+ /*
1531+ * Sometimes close() gets called more than once.
1532+ */
1533+ case cs_CLOSED:
1534+ case cs_APP_CLOSED:
1535+ break;
1536+
1537+ /*
1538+ * Otherwise we indicate clean termination.
1539+ */
1540+ // case cs_HANDSHAKE:
1541+ // case cs_DATA:
1542+ // case cs_RENEGOTIATE:
1543+ // case cs_SENT_CLOSE:
1544+ default:
1545+ synchronized (this) {
1546+ if (((state = getConnectionState()) == cs_CLOSED) ||
1547+ (state == cs_ERROR) || (state == cs_APP_CLOSED)) {
1548+ return; // connection was closed while we waited
1549+ }
1550+ if (state != cs_SENT_CLOSE) {
1551+ try {
1552+ warning(Alerts.alert_close_notify);
1553+ connectionState = cs_SENT_CLOSE;
1554+ } catch (Throwable th) {
1555+ // we need to ensure socket is closed out
1556+ // if we encounter any errors.
1557+ connectionState = cs_ERROR;
1558+ // cache this for later use
1559+ cachedThrowable = th;
1560+ closeSocketCalled = true;
1561+ closeSocket(selfInitiated);
1562+ }
1563+ }
1564+ }
1565+ // If state was cs_SENT_CLOSE before, we don't do the actual
1566+ // closing since it is already in progress.
1567+ if (state == cs_SENT_CLOSE) {
1568+ if (debug != null && Debug.isOn("ssl")) {
1569+ System.out.println(threadName() +
1570+ ", close invoked again; state = " +
1571+ getConnectionState());
1572+ }
1573+ if (selfInitiated == false) {
1574+ // We were called because a close_notify message was
1575+ // received. This may be due to another thread calling
1576+ // read() or due to our call to waitForClose() below.
1577+ // In either case, just return.
1578+ return;
1579+ }
1580+ // Another thread explicitly called close(). We need to
1581+ // wait for the closing to complete before returning.
1582+ synchronized (this) {
1583+ while (connectionState < cs_CLOSED) {
1584+ try {
1585+ this.wait();
1586+ } catch (InterruptedException e) {
1587+ // ignore
1588+ }
1589+ }
1590+ }
1591+ if ((debug != null) && Debug.isOn("ssl")) {
1592+ System.out.println(threadName() +
1593+ ", after primary close; state = " +
1594+ getConnectionState());
1595+ }
1596+ return;
1597+ }
1598+
1599+ if (!closeSocketCalled) {
1600+ closeSocketCalled = true;
1601+ closeSocket(selfInitiated);
1602+ }
1603+
1604+ break;
1605+ }
1606+ } finally {
1607+ synchronized (this) {
1608+ // Upon exit from this method, the state is always >= cs_CLOSED
1609+ connectionState = (connectionState == cs_APP_CLOSED)
1610+ ? cs_APP_CLOSED : cs_CLOSED;
1611+ // notify any threads waiting for the closing to finish
1612+ this.notifyAll();
1613+ }
1614+ if (closeSocketCalled) {
1615+ // Dispose of ciphers since we've closed socket
1616+ disposeCiphers();
1617+ }
1618+ if (cachedThrowable != null) {
1619+ /*
1620+ * Rethrow the error to the calling method
1621+ * The Throwable caught can only be an Error or RuntimeException
1622+ */
1623+ if (cachedThrowable instanceof Error)
1624+ throw (Error) cachedThrowable;
1625+ if (cachedThrowable instanceof RuntimeException)
1626+ throw (RuntimeException) cachedThrowable;
1627+ }
1628+ }
1629+ }
1630+
1631+ /**
1632+ * Reads a close_notify or a fatal alert from the input stream.
1633+ * Keep reading records until we get a close_notify or until
1634+ * the connection is otherwise closed. The close_notify or alert
1635+ * might be read by another reader,
1636+ * which will then process the close and set the connection state.
1637+ */
1638+ void waitForClose(boolean rethrow) throws IOException {
1639+ if (debug != null && Debug.isOn("ssl")) {
1640+ System.out.println(threadName() +
1641+ ", waiting for close_notify or alert: state "
1642+ + getConnectionState());
1643+ }
1644+
1645+ try {
1646+ int state;
1647+
1648+ while (((state = getConnectionState()) != cs_CLOSED) &&
1649+ (state != cs_ERROR) && (state != cs_APP_CLOSED)) {
1650+ // create the InputRecord if it isn't intialized.
1651+ if (inrec == null) {
1652+ inrec = new InputRecord();
1653+ }
1654+
1655+ // Ask for app data and then throw it away
1656+ try {
1657+ readRecord(inrec, true);
1658+ } catch (SocketTimeoutException e) {
1659+ // if time out, ignore the exception and continue
1660+ }
1661+ }
1662+ inrec = null;
1663+ } catch (IOException e) {
1664+ if (debug != null && Debug.isOn("ssl")) {
1665+ System.out.println(threadName() +
1666+ ", Exception while waiting for close " +e);
1667+ }
1668+ if (rethrow) {
1669+ throw e; // pass exception up
1670+ }
1671+ }
1672+ }
1673+
1674+ /**
1675+ * Called by closeInternal() only. Be sure to consider the
1676+ * synchronization locks carefully before calling it elsewhere.
1677+ */
1678+ private void disposeCiphers() {
1679+ // See comment in changeReadCiphers()
1680+ synchronized (readLock) {
1681+ readCipher.dispose();
1682+ }
1683+ // See comment in changeReadCiphers()
1684+ writeLock.lock();
1685+ try {
1686+ writeCipher.dispose();
1687+ } finally {
1688+ writeLock.unlock();
1689+ }
1690+ }
1691+
1692+ //
1693+ // EXCEPTION AND ALERT HANDLING
1694+ //
1695+
1696+ /**
1697+ * Handle an exception. This method is called by top level exception
1698+ * handlers (in read(), write()) to make sure we always shutdown the
1699+ * connection correctly and do not pass runtime exception to the
1700+ * application.
1701+ */
1702+ void handleException(Exception e) throws IOException {
1703+ handleException(e, true);
1704+ }
1705+
1706+ /**
1707+ * Handle an exception. This method is called by top level exception
1708+ * handlers (in read(), write(), startHandshake()) to make sure we
1709+ * always shutdown the connection correctly and do not pass runtime
1710+ * exception to the application.
1711+ *
1712+ * This method never returns normally, it always throws an IOException.
1713+ *
1714+ * We first check if the socket has already been shutdown because of an
1715+ * error. If so, we just rethrow the exception. If the socket has not
1716+ * been shutdown, we sent a fatal alert and remember the exception.
1717+ *
1718+ * @param e the Exception
1719+ * @param resumable indicates the caller process is resumable from the
1720+ * exception. If <code>resumable</code>, the socket will be
1721+ * reserved for exceptions like timeout; otherwise, the socket
1722+ * will be closed, no further communications could be done.
1723+ */
1724+ synchronized private void handleException(Exception e, boolean resumable)
1725+ throws IOException {
1726+ if ((debug != null) && Debug.isOn("ssl")) {
1727+ System.out.println(threadName()
1728+ + ", handling exception: " + e.toString());
1729+ }
1730+
1731+ // don't close the Socket in case of timeouts or interrupts if
1732+ // the process is resumable.
1733+ if (e instanceof InterruptedIOException && resumable) {
1734+ throw (IOException)e;
1735+ }
1736+
1737+ // if we've already shutdown because of an error,
1738+ // there is nothing to do except rethrow the exception
1739+ if (closeReason != null) {
1740+ if (e instanceof IOException) { // includes SSLException
1741+ throw (IOException)e;
1742+ } else {
1743+ // this is odd, not an IOException.
1744+ // normally, this should not happen
1745+ // if closeReason has been already been set
1746+ throw Alerts.getSSLException(Alerts.alert_internal_error, e,
1747+ "Unexpected exception");
1748+ }
1749+ }
1750+
1751+ // need to perform error shutdown
1752+ boolean isSSLException = (e instanceof SSLException);
1753+ if ((isSSLException == false) && (e instanceof IOException)) {
1754+ // IOException from the socket
1755+ // this means the TCP connection is already dead
1756+ // we call fatal just to set the error status
1757+ try {
1758+ fatal(Alerts.alert_unexpected_message, e);
1759+ } catch (IOException ee) {
1760+ // ignore (IOException wrapped in SSLException)
1761+ }
1762+ // rethrow original IOException
1763+ throw (IOException)e;
1764+ }
1765+
1766+ // must be SSLException or RuntimeException
1767+ byte alertType;
1768+ if (isSSLException) {
1769+ if (e instanceof SSLHandshakeException) {
1770+ alertType = Alerts.alert_handshake_failure;
1771+ } else {
1772+ alertType = Alerts.alert_unexpected_message;
1773+ }
1774+ } else {
1775+ alertType = Alerts.alert_internal_error;
1776+ }
1777+ fatal(alertType, e);
1778+ }
1779+
1780+ /*
1781+ * Send a warning alert.
1782+ */
1783+ void warning(byte description) {
1784+ sendAlert(Alerts.alert_warning, description);
1785+ }
1786+
1787+ synchronized void fatal(byte description, String diagnostic)
1788+ throws IOException {
1789+ fatal(description, diagnostic, null);
1790+ }
1791+
1792+ synchronized void fatal(byte description, Throwable cause)
1793+ throws IOException {
1794+ fatal(description, null, cause);
1795+ }
1796+
1797+ /*
1798+ * Send a fatal alert, and throw an exception so that callers will
1799+ * need to stand on their heads to accidentally continue processing.
1800+ */
1801+ synchronized void fatal(byte description, String diagnostic,
1802+ Throwable cause) throws IOException {
1803+ if ((input != null) && (input.r != null)) {
1804+ input.r.close();
1805+ }
1806+ sess.invalidate();
1807+ if (handshakeSession != null) {
1808+ handshakeSession.invalidate();
1809+ }
1810+
1811+ int oldState = connectionState;
1812+ if (connectionState < cs_ERROR) {
1813+ connectionState = cs_ERROR;
1814+ }
1815+
1816+ /*
1817+ * Has there been an error received yet? If not, remember it.
1818+ * By RFC 2246, we don't bother waiting for a response.
1819+ * Fatal errors require immediate shutdown.
1820+ */
1821+ if (closeReason == null) {
1822+ /*
1823+ * Try to clear the kernel buffer to avoid TCP connection resets.
1824+ */
1825+ if (oldState == cs_HANDSHAKE) {
1826+ sockInput.skip(sockInput.available());
1827+ }
1828+
1829+ // If the description equals -1, the alert won't be sent to peer.
1830+ if (description != -1) {
1831+ sendAlert(Alerts.alert_fatal, description);
1832+ }
1833+ if (cause instanceof SSLException) { // only true if != null
1834+ closeReason = (SSLException)cause;
1835+ } else {
1836+ closeReason =
1837+ Alerts.getSSLException(description, cause, diagnostic);
1838+ }
1839+ }
1840+
1841+ /*
1842+ * Clean up our side.
1843+ */
1844+ closeSocket();
1845+ // Another thread may have disposed the ciphers during closing
1846+ if (connectionState < cs_CLOSED) {
1847+ connectionState = (oldState == cs_APP_CLOSED) ? cs_APP_CLOSED
1848+ : cs_CLOSED;
1849+
1850+ // We should lock readLock and writeLock if no deadlock risks.
1851+ // See comment in changeReadCiphers()
1852+ readCipher.dispose();
1853+ writeCipher.dispose();
1854+ }
1855+
1856+ throw closeReason;
1857+ }
1858+
1859+
1860+ /*
1861+ * Process an incoming alert ... caller must already have synchronized
1862+ * access to "this".
1863+ */
1864+ private void recvAlert(InputRecord r) throws IOException {
1865+ byte level = (byte)r.read();
1866+ byte description = (byte)r.read();
1867+ if (description == -1) { // check for short message
1868+ fatal(Alerts.alert_illegal_parameter, "Short alert message");
1869+ }
1870+
1871+ if (debug != null && (Debug.isOn("record") ||
1872+ Debug.isOn("handshake"))) {
1873+ synchronized (System.out) {
1874+ System.out.print(threadName());
1875+ System.out.print(", RECV " + protocolVersion + " ALERT: ");
1876+ if (level == Alerts.alert_fatal) {
1877+ System.out.print("fatal, ");
1878+ } else if (level == Alerts.alert_warning) {
1879+ System.out.print("warning, ");
1880+ } else {
1881+ System.out.print("<level " + (0x0ff & level) + ">, ");
1882+ }
1883+ System.out.println(Alerts.alertDescription(description));
1884+ }
1885+ }
1886+
1887+ if (level == Alerts.alert_warning) {
1888+ if (description == Alerts.alert_close_notify) {
1889+ if (connectionState == cs_HANDSHAKE) {
1890+ fatal(Alerts.alert_unexpected_message,
1891+ "Received close_notify during handshake");
1892+ } else {
1893+ closeInternal(false); // reply to close
1894+ }
1895+ } else {
1896+
1897+ //
1898+ // The other legal warnings relate to certificates,
1899+ // e.g. no_certificate, bad_certificate, etc; these
1900+ // are important to the handshaking code, which can
1901+ // also handle illegal protocol alerts if needed.
1902+ //
1903+ if (handshaker != null) {
1904+ handshaker.handshakeAlert(description);
1905+ }
1906+ }
1907+ } else { // fatal or unknown level
1908+ String reason = "Received fatal alert: "
1909+ + Alerts.alertDescription(description);
1910+ if (closeReason == null) {
1911+ closeReason = Alerts.getSSLException(description, reason);
1912+ }
1913+ fatal(Alerts.alert_unexpected_message, reason);
1914+ }
1915+ }
1916+
1917+
1918+ /*
1919+ * Emit alerts. Caller must have synchronized with "this".
1920+ */
1921+ private void sendAlert(byte level, byte description) {
1922+ // the connectionState cannot be cs_START
1923+ if (connectionState >= cs_SENT_CLOSE) {
1924+ return;
1925+ }
1926+
1927+ // For initial handshaking, don't send alert message to peer if
1928+ // handshaker has not started.
1929+ if (connectionState == cs_HANDSHAKE &&
1930+ (handshaker == null || !handshaker.started())) {
1931+ return;
1932+ }
1933+
1934+ OutputRecord r = new OutputRecord(Record.ct_alert);
1935+ r.setVersion(protocolVersion);
1936+
1937+ boolean useDebug = debug != null && Debug.isOn("ssl");
1938+ if (useDebug) {
1939+ synchronized (System.out) {
1940+ System.out.print(threadName());
1941+ System.out.print(", SEND " + protocolVersion + " ALERT: ");
1942+ if (level == Alerts.alert_fatal) {
1943+ System.out.print("fatal, ");
1944+ } else if (level == Alerts.alert_warning) {
1945+ System.out.print("warning, ");
1946+ } else {
1947+ System.out.print("<level = " + (0x0ff & level) + ">, ");
1948+ }
1949+ System.out.println("description = "
1950+ + Alerts.alertDescription(description));
1951+ }
1952+ }
1953+
1954+ r.write(level);
1955+ r.write(description);
1956+ try {
1957+ writeRecord(r);
1958+ } catch (IOException e) {
1959+ if (useDebug) {
1960+ System.out.println(threadName() +
1961+ ", Exception sending alert: " + e);
1962+ }
1963+ }
1964+ }
1965+
1966+ //
1967+ // VARIOUS OTHER METHODS
1968+ //
1969+
1970+ /*
1971+ * When a connection finishes handshaking by enabling use of a newly
1972+ * negotiated session, each end learns about it in two halves (read,
1973+ * and write). When both read and write ciphers have changed, and the
1974+ * last handshake message has been read, the connection has joined
1975+ * (rejoined) the new session.
1976+ *
1977+ * NOTE: The SSLv3 spec is rather unclear on the concepts here.
1978+ * Sessions don't change once they're established (including cipher
1979+ * suite and master secret) but connections can join them (and leave
1980+ * them). They're created by handshaking, though sometime handshaking
1981+ * causes connections to join up with pre-established sessions.
1982+ */
1983+ private void changeReadCiphers() throws SSLException {
1984+ if (connectionState != cs_HANDSHAKE
1985+ && connectionState != cs_RENEGOTIATE) {
1986+ throw new SSLProtocolException(
1987+ "State error, change cipher specs");
1988+ }
1989+
1990+ // ... create decompressor
1991+
1992+ CipherBox oldCipher = readCipher;
1993+
1994+ try {
1995+ readCipher = handshaker.newReadCipher();
1996+ readMAC = handshaker.newReadMAC();
1997+ } catch (GeneralSecurityException e) {
1998+ // "can't happen"
1999+ throw (SSLException)new SSLException
2000+ ("Algorithm missing: ").initCause(e);
2001+ }
2002+
2003+ /*
2004+ * Dispose of any intermediate state in the underlying cipher.
2005+ * For PKCS11 ciphers, this will release any attached sessions,
2006+ * and thus make finalization faster.
2007+ *
2008+ * Since MAC's doFinal() is called for every SSL/TLS packet, it's
2009+ * not necessary to do the same with MAC's.
2010+ */
2011+ oldCipher.dispose();
2012+ }
2013+
2014+ // used by Handshaker
2015+ void changeWriteCiphers() throws SSLException {
2016+ if (connectionState != cs_HANDSHAKE
2017+ && connectionState != cs_RENEGOTIATE) {
2018+ throw new SSLProtocolException(
2019+ "State error, change cipher specs");
2020+ }
2021+
2022+ // ... create compressor
2023+
2024+ CipherBox oldCipher = writeCipher;
2025+
2026+ try {
2027+ writeCipher = handshaker.newWriteCipher();
2028+ writeMAC = handshaker.newWriteMAC();
2029+ } catch (GeneralSecurityException e) {
2030+ // "can't happen"
2031+ throw (SSLException)new SSLException
2032+ ("Algorithm missing: ").initCause(e);
2033+ }
2034+
2035+ // See comment above.
2036+ oldCipher.dispose();
2037+ }
2038+
2039+ /*
2040+ * Updates the SSL version associated with this connection.
2041+ * Called from Handshaker once it has determined the negotiated version.
2042+ */
2043+ synchronized void setVersion(ProtocolVersion protocolVersion) {
2044+ this.protocolVersion = protocolVersion;
2045+ output.r.setVersion(protocolVersion);
2046+ }
2047+
2048+ synchronized String getHost() {
2049+ // Note that the host may be null or empty for localhost.
2050+ if (host == null || host.length() == 0) {
2051+ host = getInetAddress().getHostName();
2052+ }
2053+ return host;
2054+ }
2055+
2056+ synchronized String getRawHostname() {
2057+ return rawHostname;
2058+ }
2059+
2060+ // ONLY used by HttpsClient to setup the URI specified hostname
2061+ synchronized public void setHost(String host) {
2062+ this.host = host;
2063+ this.rawHostname = host;
2064+ }
2065+
2066+ /**
2067+ * Gets an input stream to read from the peer on the other side.
2068+ * Data read from this stream was always integrity protected in
2069+ * transit, and will usually have been confidentiality protected.
2070+ */
2071+ synchronized public InputStream getInputStream() throws IOException {
2072+ if (isClosed()) {
2073+ throw new SocketException("Socket is closed");
2074+ }
2075+
2076+ /*
2077+ * Can't call isConnected() here, because the Handshakers
2078+ * do some initialization before we actually connect.
2079+ */
2080+ if (connectionState == cs_START) {
2081+ throw new SocketException("Socket is not connected");
2082+ }
2083+
2084+ return input;
2085+ }
2086+
2087+ /**
2088+ * Gets an output stream to write to the peer on the other side.
2089+ * Data written on this stream is always integrity protected, and
2090+ * will usually be confidentiality protected.
2091+ */
2092+ synchronized public OutputStream getOutputStream() throws IOException {
2093+ if (isClosed()) {
2094+ throw new SocketException("Socket is closed");
2095+ }
2096+
2097+ /*
2098+ * Can't call isConnected() here, because the Handshakers
2099+ * do some initialization before we actually connect.
2100+ */
2101+ if (connectionState == cs_START) {
2102+ throw new SocketException("Socket is not connected");
2103+ }
2104+
2105+ return output;
2106+ }
2107+
2108+ /**
2109+ * Returns the the SSL Session in use by this connection. These can
2110+ * be long lived, and frequently correspond to an entire login session
2111+ * for some user.
2112+ */
2113+ public SSLSession getSession() {
2114+ /*
2115+ * Force a synchronous handshake, if appropriate.
2116+ */
2117+ if (getConnectionState() == cs_HANDSHAKE) {
2118+ try {
2119+ // start handshaking, if failed, the connection will be closed.
2120+ startHandshake(false);
2121+ } catch (IOException e) {
2122+ // handshake failed. log and return a nullSession
2123+ if (debug != null && Debug.isOn("handshake")) {
2124+ System.out.println(threadName() +
2125+ ", IOException in getSession(): " + e);
2126+ }
2127+ }
2128+ }
2129+ synchronized (this) {
2130+ return sess;
2131+ }
2132+ }
2133+
2134+ @Override
2135+ synchronized public SSLSession getHandshakeSession() {
2136+ return handshakeSession;
2137+ }
2138+
2139+ synchronized void setHandshakeSession(SSLSessionImpl session) {
2140+ handshakeSession = session;
2141+ }
2142+
2143+ /**
2144+ * Controls whether new connections may cause creation of new SSL
2145+ * sessions.
2146+ *
2147+ * As long as handshaking has not started, we can change
2148+ * whether we enable session creations. Otherwise,
2149+ * we will need to wait for the next handshake.
2150+ */
2151+ synchronized public void setEnableSessionCreation(boolean flag) {
2152+ enableSessionCreation = flag;
2153+
2154+ if ((handshaker != null) && !handshaker.activated()) {
2155+ handshaker.setEnableSessionCreation(enableSessionCreation);
2156+ }
2157+ }
2158+
2159+ /**
2160+ * Returns true if new connections may cause creation of new SSL
2161+ * sessions.
2162+ */
2163+ synchronized public boolean getEnableSessionCreation() {
2164+ return enableSessionCreation;
2165+ }
2166+
2167+
2168+ /**
2169+ * Sets the flag controlling whether a server mode socket
2170+ * *REQUIRES* SSL client authentication.
2171+ *
2172+ * As long as handshaking has not started, we can change
2173+ * whether client authentication is needed. Otherwise,
2174+ * we will need to wait for the next handshake.
2175+ */
2176+ synchronized public void setNeedClientAuth(boolean flag) {
2177+ doClientAuth = (flag ?
2178+ SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
2179+
2180+ if ((handshaker != null) &&
2181+ (handshaker instanceof ServerHandshaker) &&
2182+ !handshaker.activated()) {
2183+ ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
2184+ }
2185+ }
2186+
2187+ synchronized public boolean getNeedClientAuth() {
2188+ return (doClientAuth == SSLEngineImpl.clauth_required);
2189+ }
2190+
2191+ /**
2192+ * Sets the flag controlling whether a server mode socket
2193+ * *REQUESTS* SSL client authentication.
2194+ *
2195+ * As long as handshaking has not started, we can change
2196+ * whether client authentication is requested. Otherwise,
2197+ * we will need to wait for the next handshake.
2198+ */
2199+ synchronized public void setWantClientAuth(boolean flag) {
2200+ doClientAuth = (flag ?
2201+ SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
2202+
2203+ if ((handshaker != null) &&
2204+ (handshaker instanceof ServerHandshaker) &&
2205+ !handshaker.activated()) {
2206+ ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
2207+ }
2208+ }
2209+
2210+ synchronized public boolean getWantClientAuth() {
2211+ return (doClientAuth == SSLEngineImpl.clauth_requested);
2212+ }
2213+
2214+
2215+ /**
2216+ * Sets the flag controlling whether the socket is in SSL
2217+ * client or server mode. Must be called before any SSL
2218+ * traffic has started.
2219+ */
2220+ synchronized public void setUseClientMode(boolean flag) {
2221+ switch (connectionState) {
2222+
2223+ case cs_START:
2224+ /*
2225+ * If we need to change the socket mode and the enabled
2226+ * protocols haven't specifically been set by the user,
2227+ * change them to the corresponding default ones.
2228+ */
2229+ if (roleIsServer != (!flag) &&
2230+ sslContext.isDefaultProtocolList(enabledProtocols)) {
2231+ enabledProtocols = sslContext.getDefaultProtocolList(!flag);
2232+ }
2233+ roleIsServer = !flag;
2234+ break;
2235+
2236+ case cs_HANDSHAKE:
2237+ /*
2238+ * If we have a handshaker, but haven't started
2239+ * SSL traffic, we can throw away our current
2240+ * handshaker, and start from scratch. Don't
2241+ * need to call doneConnect() again, we already
2242+ * have the streams.
2243+ */
2244+ assert(handshaker != null);
2245+ if (!handshaker.activated()) {
2246+ /*
2247+ * If we need to change the socket mode and the enabled
2248+ * protocols haven't specifically been set by the user,
2249+ * change them to the corresponding default ones.
2250+ */
2251+ if (roleIsServer != (!flag) &&
2252+ sslContext.isDefaultProtocolList(enabledProtocols)) {
2253+ enabledProtocols = sslContext.getDefaultProtocolList(!flag);
2254+ }
2255+ roleIsServer = !flag;
2256+ connectionState = cs_START;
2257+ initHandshaker();
2258+ break;
2259+ }
2260+
2261+ // If handshake has started, that's an error. Fall through...
2262+
2263+ default:
2264+ if (debug != null && Debug.isOn("ssl")) {
2265+ System.out.println(threadName() +
2266+ ", setUseClientMode() invoked in state = " +
2267+ connectionState);
2268+ }
2269+ throw new IllegalArgumentException(
2270+ "Cannot change mode after SSL traffic has started");
2271+ }
2272+ }
2273+
2274+ synchronized public boolean getUseClientMode() {
2275+ return !roleIsServer;
2276+ }
2277+
2278+
2279+ /**
2280+ * Returns the names of the cipher suites which could be enabled for use
2281+ * on an SSL connection. Normally, only a subset of these will actually
2282+ * be enabled by default, since this list may include cipher suites which
2283+ * do not support the mutual authentication of servers and clients, or
2284+ * which do not protect data confidentiality. Servers may also need
2285+ * certain kinds of certificates to use certain cipher suites.
2286+ *
2287+ * @return an array of cipher suite names
2288+ */
2289+ public String[] getSupportedCipherSuites() {
2290+ return sslContext.getSuportedCipherSuiteList().toStringArray();
2291+ }
2292+
2293+ /**
2294+ * Controls which particular cipher suites are enabled for use on
2295+ * this connection. The cipher suites must have been listed by
2296+ * getCipherSuites() as being supported. Even if a suite has been
2297+ * enabled, it might never be used if no peer supports it or the
2298+ * requisite certificates (and private keys) are not available.
2299+ *
2300+ * @param suites Names of all the cipher suites to enable.
2301+ */
2302+ synchronized public void setEnabledCipherSuites(String[] suites) {
2303+ enabledCipherSuites = new CipherSuiteList(suites);
2304+ if ((handshaker != null) && !handshaker.activated()) {
2305+ handshaker.setEnabledCipherSuites(enabledCipherSuites);
2306+ }
2307+ }
2308+
2309+ /**
2310+ * Returns the names of the SSL cipher suites which are currently enabled
2311+ * for use on this connection. When an SSL socket is first created,
2312+ * all enabled cipher suites <em>(a)</em> protect data confidentiality,
2313+ * by traffic encryption, and <em>(b)</em> can mutually authenticate
2314+ * both clients and servers. Thus, in some environments, this value
2315+ * might be empty.
2316+ *
2317+ * @return an array of cipher suite names
2318+ */
2319+ synchronized public String[] getEnabledCipherSuites() {
2320+ return enabledCipherSuites.toStringArray();
2321+ }
2322+
2323+
2324+ /**
2325+ * Returns the protocols that are supported by this implementation.
2326+ * A subset of the supported protocols may be enabled for this connection
2327+ * @return an array of protocol names.
2328+ */
2329+ public String[] getSupportedProtocols() {
2330+ return sslContext.getSuportedProtocolList().toStringArray();
2331+ }
2332+
2333+ /**
2334+ * Controls which protocols are enabled for use on
2335+ * this connection. The protocols must have been listed by
2336+ * getSupportedProtocols() as being supported.
2337+ *
2338+ * @param protocols protocols to enable.
2339+ * @exception IllegalArgumentException when one of the protocols
2340+ * named by the parameter is not supported.
2341+ */
2342+ synchronized public void setEnabledProtocols(String[] protocols) {
2343+ enabledProtocols = new ProtocolList(protocols);
2344+ if ((handshaker != null) && !handshaker.activated()) {
2345+ handshaker.setEnabledProtocols(enabledProtocols);
2346+ }
2347+ }
2348+
2349+ synchronized public String[] getEnabledProtocols() {
2350+ return enabledProtocols.toStringArray();
2351+ }
2352+
2353+ /**
2354+ * Assigns the socket timeout.
2355+ * @see java.net.Socket#setSoTimeout
2356+ */
2357+ public void setSoTimeout(int timeout) throws SocketException {
2358+ if ((debug != null) && Debug.isOn("ssl")) {
2359+ System.out.println(threadName() +
2360+ ", setSoTimeout(" + timeout + ") called");
2361+ }
2362+ if (self == this) {
2363+ super.setSoTimeout(timeout);
2364+ } else {
2365+ self.setSoTimeout(timeout);
2366+ }
2367+ }
2368+
2369+ /**
2370+ * Registers an event listener to receive notifications that an
2371+ * SSL handshake has completed on this connection.
2372+ */
2373+ public synchronized void addHandshakeCompletedListener(
2374+ HandshakeCompletedListener listener) {
2375+ if (listener == null) {
2376+ throw new IllegalArgumentException("listener is null");
2377+ }
2378+ if (handshakeListeners == null) {
2379+ handshakeListeners = new
2380+ HashMap<HandshakeCompletedListener, AccessControlContext>(4);
2381+ }
2382+ handshakeListeners.put(listener, AccessController.getContext());
2383+ }
2384+
2385+
2386+ /**
2387+ * Removes a previously registered handshake completion listener.
2388+ */
2389+ public synchronized void removeHandshakeCompletedListener(
2390+ HandshakeCompletedListener listener) {
2391+ if (handshakeListeners == null) {
2392+ throw new IllegalArgumentException("no listeners");
2393+ }
2394+ if (handshakeListeners.remove(listener) == null) {
2395+ throw new IllegalArgumentException("listener not registered");
2396+ }
2397+ if (handshakeListeners.isEmpty()) {
2398+ handshakeListeners = null;
2399+ }
2400+ }
2401+
2402+ /**
2403+ * Returns the SSLParameters in effect for this SSLSocket.
2404+ */
2405+ synchronized public SSLParameters getSSLParameters() {
2406+ SSLParameters params = super.getSSLParameters();
2407+
2408+ // the super implementation does not handle the following parameters
2409+ params.setEndpointIdentificationAlgorithm(identificationProtocol);
2410+ params.setAlgorithmConstraints(algorithmConstraints);
2411+
2412+ return params;
2413+ }
2414+
2415+ /**
2416+ * Applies SSLParameters to this socket.
2417+ */
2418+ synchronized public void setSSLParameters(SSLParameters params) {
2419+ super.setSSLParameters(params);
2420+
2421+ // the super implementation does not handle the following parameters
2422+ identificationProtocol = params.getEndpointIdentificationAlgorithm();
2423+ algorithmConstraints = params.getAlgorithmConstraints();
2424+ if ((handshaker != null) && !handshaker.started()) {
2425+ handshaker.setIdentificationProtocol(identificationProtocol);
2426+ handshaker.setAlgorithmConstraints(algorithmConstraints);
2427+ }
2428+ }
2429+
2430+ //
2431+ // We allocate a separate thread to deliver handshake completion
2432+ // events. This ensures that the notifications don't block the
2433+ // protocol state machine.
2434+ //
2435+ private static class NotifyHandshakeThread extends Thread {
2436+
2437+ private Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
2438+ targets; // who gets notified
2439+ private HandshakeCompletedEvent event; // the notification
2440+
2441+ NotifyHandshakeThread(
2442+ Set<Map.Entry<HandshakeCompletedListener,AccessControlContext>>
2443+ entrySet, HandshakeCompletedEvent e) {
2444+
2445+ super("HandshakeCompletedNotify-Thread");
2446+ targets = entrySet;
2447+ event = e;
2448+ }
2449+
2450+ public void run() {
2451+ for (Map.Entry<HandshakeCompletedListener,AccessControlContext>
2452+ entry : targets) {
2453+
2454+ final HandshakeCompletedListener l = entry.getKey();
2455+ AccessControlContext acc = entry.getValue();
2456+ AccessController.doPrivileged(new PrivilegedAction<Void>() {
2457+ public Void run() {
2458+ l.handshakeCompleted(event);
2459+ return null;
2460+ }
2461+ }, acc);
2462+ }
2463+ }
2464+ }
2465+
2466+ /**
2467+ * Return the name of the current thread. Utility method.
2468+ */
2469+ private static String threadName() {
2470+ return Thread.currentThread().getName();
2471+ }
2472+
2473+ /**
2474+ * Returns a printable representation of this end of the connection.
2475+ */
2476+ public String toString() {
2477+ StringBuffer retval = new StringBuffer(80);
2478+
2479+ retval.append(Integer.toHexString(hashCode()));
2480+ retval.append("[");
2481+ retval.append(sess.getCipherSuite());
2482+ retval.append(": ");
2483+
2484+ if (self == this) {
2485+ retval.append(super.toString());
2486+ } else {
2487+ retval.append(self.toString());
2488+ }
2489+ retval.append("]");
2490+
2491+ return retval.toString();
2492+ }
2493+}