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/SSLEngineImpl.java (1 of 18352 files). Show all

Unified · Split

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