blob: 4e94c08dce212c6405536fe4c596fb244dee6a3b [file] [log] [blame]
J. Duke319a3b92007-12-01 00:00:00 +00001/*
2 * Copyright 2003-2007 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any 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 SSLSessionImpl sess;
204 private Handshaker handshaker;
205
206 /*
207 * Client authentication be off, requested, or required.
208 *
209 * This will be used by both this class and SSLSocket's variants.
210 */
211 static final byte clauth_none = 0;
212 static final byte clauth_requested = 1;
213 static final byte clauth_required = 2;
214
215 /*
216 * Flag indicating if the next record we receive MUST be a Finished
217 * message. Temporarily set during the handshake to ensure that
218 * a change cipher spec message is followed by a finished message.
219 */
220 private boolean expectingFinished;
221
222
223 /*
224 * If someone tries to closeInbound() (say at End-Of-Stream)
225 * our engine having received a close_notify, we need to
226 * notify the app that we may have a truncation attack underway.
227 */
228 private boolean recvCN;
229
230 /*
231 * For improved diagnostics, we detail connection closure
232 * If the engine is closed (connectionState >= cs_ERROR),
233 * closeReason != null indicates if the engine was closed
234 * because of an error or because or normal shutdown.
235 */
236 private SSLException closeReason;
237
238 /*
239 * Per-connection private state that doesn't change when the
240 * session is changed.
241 */
242 private byte doClientAuth;
243 private CipherSuiteList enabledCipherSuites;
244 private boolean enableSessionCreation = true;
245 EngineInputRecord inputRecord;
246 EngineOutputRecord outputRecord;
247 private AccessControlContext acc;
248
249 // hostname identification algorithm, the hostname identification is
250 // disabled by default.
251 private String identificationAlg = null;
252
253 // Have we been told whether we're client or server?
254 private boolean serverModeSet = false;
255 private boolean roleIsServer;
256
257 /*
258 * The protocols we support are SSL Version 3.0) and
259 * TLS (version 3.1).
260 * In addition we support a pseudo protocol called
261 * SSLv2Hello which when set will result in an SSL v2 Hello
262 * being sent with SSLv3 or TLSv1 version info.
263 */
264 private ProtocolList enabledProtocols;
265
266 /*
267 * The SSL version associated with this connection.
268 */
269 private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT;
270
271 /*
272 * Crypto state that's reinitialized when the session changes.
273 */
274 private MAC readMAC, writeMAC;
275 private CipherBox readCipher, writeCipher;
276 // NOTE: compression state would be saved here
277
278
279 /*
280 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
281 * IMPORTANT STUFF TO UNDERSTANDING THE SYNCHRONIZATION ISSUES.
282 * READ ME * READ ME * READ ME * READ ME * READ ME * READ ME *
283 *
284 * There are several locks here.
285 *
286 * The primary lock is the per-instance lock used by
287 * synchronized(this) and the synchronized methods. It controls all
288 * access to things such as the connection state and variables which
289 * affect handshaking. If we are inside a synchronized method, we
290 * can access the state directly, otherwise, we must use the
291 * synchronized equivalents.
292 *
293 * Note that we must never acquire the <code>this</code> lock after
294 * <code>writeLock</code> or run the risk of deadlock.
295 *
296 * Grab some coffee, and be careful with any code changes.
297 */
298 private Object wrapLock;
299 private Object unwrapLock;
300 Object writeLock;
301
302 /*
303 * Class and subclass dynamic debugging support
304 */
305 private static final Debug debug = Debug.getInstance("ssl");
306
307 //
308 // Initialization/Constructors
309 //
310
311 /**
312 * Constructor for an SSLEngine from SSLContext, without
313 * host/port hints. This Engine will not be able to cache
314 * sessions, but must renegotiate everything by hand.
315 */
316 SSLEngineImpl(SSLContextImpl ctx) {
317 super();
318 init(ctx);
319 }
320
321 /**
322 * Constructor for an SSLEngine from SSLContext.
323 */
324 SSLEngineImpl(SSLContextImpl ctx, String host, int port) {
325 super(host, port);
326 init(ctx);
327 }
328
329 /**
330 * Initializes the Engine
331 */
332 private void init(SSLContextImpl ctx) {
333 if (debug != null && Debug.isOn("ssl")) {
334 System.out.println("Using SSLEngineImpl.");
335 }
336
337 sslContext = ctx;
338 sess = SSLSessionImpl.nullSession;
339
340 /*
341 * State is cs_START until we initialize the handshaker.
342 *
343 * Apps using SSLEngine are probably going to be server.
344 * Somewhat arbitrary choice.
345 */
346 roleIsServer = true;
347 connectionState = cs_START;
348
349 /*
350 * default read and write side cipher and MAC support
351 *
352 * Note: compression support would go here too
353 */
354 readCipher = CipherBox.NULL;
355 readMAC = MAC.NULL;
356 writeCipher = CipherBox.NULL;
357 writeMAC = MAC.NULL;
358
359 enabledCipherSuites = CipherSuiteList.getDefault();
360 enabledProtocols = ProtocolList.getDefault();
361
362 wrapLock = new Object();
363 unwrapLock = new Object();
364 writeLock = new Object();
365
366 /*
367 * Save the Access Control Context. This will be used later
368 * for a couple of things, including providing a context to
369 * run tasks in, and for determining which credentials
370 * to use for Subject based (JAAS) decisions
371 */
372 acc = AccessController.getContext();
373
374 /*
375 * All outbound application data goes through this OutputRecord,
376 * other data goes through their respective records created
377 * elsewhere. All inbound data goes through this one
378 * input record.
379 */
380 outputRecord =
381 new EngineOutputRecord(Record.ct_application_data, this);
382 inputRecord = new EngineInputRecord(this);
383 inputRecord.enableFormatChecks();
384
385 writer = new EngineWriter();
386 }
387
388 /**
389 * Initialize the handshaker object. This means:
390 *
391 * . if a handshake is already in progress (state is cs_HANDSHAKE
392 * or cs_RENEGOTIATE), do nothing and return
393 *
394 * . if the engine is already closed, throw an Exception (internal error)
395 *
396 * . otherwise (cs_START or cs_DATA), create the appropriate handshaker
397 * object, initialize it, and advance the connection state (to
398 * cs_HANDSHAKE or cs_RENEGOTIATE, respectively).
399 *
400 * This method is called right after a new engine is created, when
401 * starting renegotiation, or when changing client/server mode of the
402 * engine.
403 */
404 private void initHandshaker() {
405 switch (connectionState) {
406
407 //
408 // Starting a new handshake.
409 //
410 case cs_START:
411 case cs_DATA:
412 break;
413
414 //
415 // We're already in the middle of a handshake.
416 //
417 case cs_HANDSHAKE:
418 case cs_RENEGOTIATE:
419 return;
420
421 //
422 // Anyone allowed to call this routine is required to
423 // do so ONLY if the connection state is reasonable...
424 //
425 default:
426 throw new IllegalStateException("Internal error");
427 }
428
429 // state is either cs_START or cs_DATA
430 if (connectionState == cs_START) {
431 connectionState = cs_HANDSHAKE;
432 } else { // cs_DATA
433 connectionState = cs_RENEGOTIATE;
434 }
435 if (roleIsServer) {
436 handshaker = new ServerHandshaker
437 (this, sslContext, enabledProtocols, doClientAuth);
438 } else {
439 handshaker = new ClientHandshaker
440 (this, sslContext, enabledProtocols);
441 }
442 handshaker.enabledCipherSuites = enabledCipherSuites;
443 handshaker.setEnableSessionCreation(enableSessionCreation);
444 if (connectionState == cs_RENEGOTIATE) {
445 // don't use SSLv2Hello when renegotiating
446 handshaker.output.r.setHelloVersion(protocolVersion);
447 }
448 }
449
450 /*
451 * Report the current status of the Handshaker
452 */
453 private HandshakeStatus getHSStatus(HandshakeStatus hss) {
454
455 if (hss != null) {
456 return hss;
457 }
458
459 synchronized (this) {
460 if (writer.hasOutboundData()) {
461 return HandshakeStatus.NEED_WRAP;
462 } else if (handshaker != null) {
463 if (handshaker.taskOutstanding()) {
464 return HandshakeStatus.NEED_TASK;
465 } else {
466 return HandshakeStatus.NEED_UNWRAP;
467 }
468 } else if (connectionState == cs_CLOSED) {
469 /*
470 * Special case where we're closing, but
471 * still need the close_notify before we
472 * can officially be closed.
473 *
474 * Note isOutboundDone is taken care of by
475 * hasOutboundData() above.
476 */
477 if (!isInboundDone()) {
478 return HandshakeStatus.NEED_UNWRAP;
479 } // else not handshaking
480 }
481
482 return HandshakeStatus.NOT_HANDSHAKING;
483 }
484 }
485
486 synchronized private void checkTaskThrown() throws SSLException {
487 if (handshaker != null) {
488 handshaker.checkThrown();
489 }
490 }
491
492 //
493 // Handshaking and connection state code
494 //
495
496 /*
497 * Provides "this" synchronization for connection state.
498 * Otherwise, you can access it directly.
499 */
500 synchronized private int getConnectionState() {
501 return connectionState;
502 }
503
504 synchronized private void setConnectionState(int state) {
505 connectionState = state;
506 }
507
508 /*
509 * Get the Access Control Context.
510 *
511 * Used for a known context to
512 * run tasks in, and for determining which credentials
513 * to use for Subject-based (JAAS) decisions.
514 */
515 AccessControlContext getAcc() {
516 return acc;
517 }
518
519 /*
520 * Is a handshake currently underway?
521 */
522 public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
523 return getHSStatus(null);
524 }
525
526 /*
527 * When a connection finishes handshaking by enabling use of a newly
528 * negotiated session, each end learns about it in two halves (read,
529 * and write). When both read and write ciphers have changed, and the
530 * last handshake message has been read, the connection has joined
531 * (rejoined) the new session.
532 *
533 * NOTE: The SSLv3 spec is rather unclear on the concepts here.
534 * Sessions don't change once they're established (including cipher
535 * suite and master secret) but connections can join them (and leave
536 * them). They're created by handshaking, though sometime handshaking
537 * causes connections to join up with pre-established sessions.
538 *
539 * Synchronized on "this" from readRecord.
540 */
541 private void changeReadCiphers() throws SSLException {
542 if (connectionState != cs_HANDSHAKE
543 && connectionState != cs_RENEGOTIATE) {
544 throw new SSLProtocolException(
545 "State error, change cipher specs");
546 }
547
548 // ... create decompressor
549
550 try {
551 readCipher = handshaker.newReadCipher();
552 readMAC = handshaker.newReadMAC();
553 } catch (GeneralSecurityException e) {
554 // "can't happen"
555 throw (SSLException)new SSLException
556 ("Algorithm missing: ").initCause(e);
557 }
558 }
559
560 /*
561 * used by Handshaker to change the active write cipher, follows
562 * the output of the CCS message.
563 *
564 * Also synchronized on "this" from readRecord/delegatedTask.
565 */
566 void changeWriteCiphers() throws SSLException {
567 if (connectionState != cs_HANDSHAKE
568 && connectionState != cs_RENEGOTIATE) {
569 throw new SSLProtocolException(
570 "State error, change cipher specs");
571 }
572
573 // ... create compressor
574
575 try {
576 writeCipher = handshaker.newWriteCipher();
577 writeMAC = handshaker.newWriteMAC();
578 } catch (GeneralSecurityException e) {
579 // "can't happen"
580 throw (SSLException)new SSLException
581 ("Algorithm missing: ").initCause(e);
582 }
583 }
584
585 /*
586 * Updates the SSL version associated with this connection.
587 * Called from Handshaker once it has determined the negotiated version.
588 */
589 synchronized void setVersion(ProtocolVersion protocolVersion) {
590 this.protocolVersion = protocolVersion;
591 outputRecord.setVersion(protocolVersion);
592 }
593
594
595 /**
596 * Kickstart the handshake if it is not already in progress.
597 * This means:
598 *
599 * . if handshaking is already underway, do nothing and return
600 *
601 * . if the engine is not connected or already closed, throw an
602 * Exception.
603 *
604 * . otherwise, call initHandshake() to initialize the handshaker
605 * object and progress the state. Then, send the initial
606 * handshaking message if appropriate (always on clients and
607 * on servers when renegotiating).
608 */
609 private synchronized void kickstartHandshake() throws IOException {
610 switch (connectionState) {
611
612 case cs_START:
613 if (!serverModeSet) {
614 throw new IllegalStateException(
615 "Client/Server mode not yet set.");
616 }
617 initHandshaker();
618 break;
619
620 case cs_HANDSHAKE:
621 // handshaker already setup, proceed
622 break;
623
624 case cs_DATA:
625 // initialize the handshaker, move to cs_RENEGOTIATE
626 initHandshaker();
627 break;
628
629 case cs_RENEGOTIATE:
630 // handshaking already in progress, return
631 return;
632
633 default:
634 // cs_ERROR/cs_CLOSED
635 throw new SSLException("SSLEngine is closing/closed");
636 }
637
638 //
639 // Kickstart handshake state machine if we need to ...
640 //
641 // Note that handshaker.kickstart() writes the message
642 // to its HandshakeOutStream, which calls back into
643 // SSLSocketImpl.writeRecord() to send it.
644 //
645 if (!handshaker.started()) {
646 if (handshaker instanceof ClientHandshaker) {
647 // send client hello
648 handshaker.kickstart();
649 } else { // instanceof ServerHandshaker
650 if (connectionState == cs_HANDSHAKE) {
651 // initial handshake, no kickstart message to send
652 } else {
653 // we want to renegotiate, send hello request
654 handshaker.kickstart();
655 // hello request is not included in the handshake
656 // hashes, reset them
657 handshaker.handshakeHash.reset();
658 }
659 }
660 }
661 }
662
663 /*
664 * Start a SSLEngine handshake
665 */
666 public void beginHandshake() throws SSLException {
667 try {
668 kickstartHandshake();
669 } catch (Exception e) {
670 fatal(Alerts.alert_handshake_failure,
671 "Couldn't kickstart handshaking", e);
672 }
673 }
674
675
676 //
677 // Read/unwrap side
678 //
679
680
681 /**
682 * Unwraps a buffer. Does a variety of checks before grabbing
683 * the unwrapLock, which blocks multiple unwraps from occuring.
684 */
685 public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer [] appData,
686 int offset, int length) throws SSLException {
687
688 EngineArgs ea = new EngineArgs(netData, appData, offset, length);
689
690 try {
691 synchronized (unwrapLock) {
692 return readNetRecord(ea);
693 }
694 } catch (Exception e) {
695 /*
696 * Don't reset position so it looks like we didn't
697 * consume anything. We did consume something, and it
698 * got us into this situation, so report that much back.
699 * Our days of consuming are now over anyway.
700 */
701 fatal(Alerts.alert_internal_error,
702 "problem unwrapping net record", e);
703 return null; // make compiler happy
704 } finally {
705 /*
706 * Just in case something failed to reset limits properly.
707 */
708 ea.resetLim();
709 }
710 }
711
712 /*
713 * Makes additional checks for unwrap, but this time more
714 * specific to this packet and the current state of the machine.
715 */
716 private SSLEngineResult readNetRecord(EngineArgs ea) throws IOException {
717
718 Status status = null;
719 HandshakeStatus hsStatus = null;
720
721 /*
722 * See if the handshaker needs to report back some SSLException.
723 */
724 checkTaskThrown();
725
726 /*
727 * Check if we are closing/closed.
728 */
729 if (isInboundDone()) {
730 return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
731 }
732
733 /*
734 * If we're still in cs_HANDSHAKE, make sure it's been
735 * started.
736 */
737 synchronized (this) {
738 if ((connectionState == cs_HANDSHAKE) ||
739 (connectionState == cs_START)) {
740 kickstartHandshake();
741
742 /*
743 * If there's still outbound data to flush, we
744 * can return without trying to unwrap anything.
745 */
746 hsStatus = getHSStatus(null);
747
748 if (hsStatus == HandshakeStatus.NEED_WRAP) {
749 return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
750 }
751 }
752 }
753
754 /*
755 * Grab a copy of this if it doesn't already exist,
756 * and we can use it several places before anything major
757 * happens on this side. Races aren't critical
758 * here.
759 */
760 if (hsStatus == null) {
761 hsStatus = getHSStatus(null);
762 }
763
764 /*
765 * If we have a task outstanding, this *MUST* be done before
766 * doing any more unwrapping, because we could be in the middle
767 * of receiving a handshake message, for example, a finished
768 * message which would change the ciphers.
769 */
770 if (hsStatus == HandshakeStatus.NEED_TASK) {
771 return new SSLEngineResult(
772 Status.OK, hsStatus, 0, 0);
773 }
774
775 /*
776 * Check the packet to make sure enough is here.
777 * This will also indirectly check for 0 len packets.
778 */
779 int packetLen = inputRecord.bytesInCompletePacket(ea.netData);
780
781 // Is this packet bigger than SSL/TLS normally allows?
782 if (packetLen > sess.getPacketBufferSize()) {
783 if (packetLen > Record.maxLargeRecordSize) {
784 throw new SSLProtocolException(
785 "Input SSL/TLS record too big: max = " +
786 Record.maxLargeRecordSize +
787 " len = " + packetLen);
788 } else {
789 // Expand the expected maximum packet/application buffer
790 // sizes.
791 sess.expandBufferSizes();
792 }
793 }
794
795 /*
796 * Check for OVERFLOW.
797 *
798 * To be considered: We could delay enforcing the application buffer
799 * free space requirement until after the initial handshaking.
800 */
801 if ((packetLen - Record.headerSize) > ea.getAppRemaining()) {
802 return new SSLEngineResult(Status.BUFFER_OVERFLOW, hsStatus, 0, 0);
803 }
804
805 // check for UNDERFLOW.
806 if ((packetLen == -1) || (ea.netData.remaining() < packetLen)) {
807 return new SSLEngineResult(
808 Status.BUFFER_UNDERFLOW, hsStatus, 0, 0);
809 }
810
811 /*
812 * We're now ready to actually do the read.
813 * The only result code we really need to be exactly
814 * right is the HS finished, for signaling to
815 * HandshakeCompletedListeners.
816 */
817 try {
818 hsStatus = readRecord(ea);
819 } catch (SSLException e) {
820 throw e;
821 } catch (IOException e) {
822 SSLException ex = new SSLException("readRecord");
823 ex.initCause(e);
824 throw ex;
825 }
826
827 /*
828 * Check the various condition that we could be reporting.
829 *
830 * It's *possible* something might have happened between the
831 * above and now, but it was better to minimally lock "this"
832 * during the read process. We'll return the current
833 * status, which is more representative of the current state.
834 *
835 * status above should cover: FINISHED, NEED_TASK
836 */
837 status = (isInboundDone() ? Status.CLOSED : Status.OK);
838 hsStatus = getHSStatus(hsStatus);
839
840 return new SSLEngineResult(status, hsStatus,
841 ea.deltaNet(), ea.deltaApp());
842 }
843
844 /*
845 * Actually do the read record processing.
846 *
847 * Returns a Status if it can make specific determinations
848 * of the engine state. In particular, we need to signal
849 * that a handshake just completed.
850 *
851 * It would be nice to be symmetrical with the write side and move
852 * the majority of this to EngineInputRecord, but there's too much
853 * SSLEngine state to do that cleanly. It must still live here.
854 */
855 private HandshakeStatus readRecord(EngineArgs ea) throws IOException {
856
857 HandshakeStatus hsStatus = null;
858
859 /*
860 * The various operations will return new sliced BB's,
861 * this will avoid having to worry about positions and
862 * limits in the netBB.
863 */
864 ByteBuffer readBB = null;
865 ByteBuffer decryptedBB = null;
866
867 if (getConnectionState() != cs_ERROR) {
868
869 /*
870 * Read a record ... maybe emitting an alert if we get a
871 * comprehensible but unsupported "hello" message during
872 * format checking (e.g. V2).
873 */
874 try {
875 readBB = inputRecord.read(ea.netData);
876 } catch (IOException e) {
877 fatal(Alerts.alert_unexpected_message, e);
878 }
879
880 /*
881 * The basic SSLv3 record protection involves (optional)
882 * encryption for privacy, and an integrity check ensuring
883 * data origin authentication. We do them both here, and
884 * throw a fatal alert if the integrity check fails.
885 */
886 try {
887 decryptedBB = inputRecord.decrypt(readCipher, readBB);
888 } catch (BadPaddingException e) {
889 // RFC 2246 states that decryption_failed should be used
890 // for this purpose. However, that allows certain attacks,
891 // so we just send bad record MAC. We also need to make
892 // sure to always check the MAC to avoid a timing attack
893 // for the same issue. See paper by Vaudenay et al.
894 //
895 // rewind the BB if necessary.
896 readBB.rewind();
897
898 inputRecord.checkMAC(readMAC, readBB);
899
900 // use the same alert types as for MAC failure below
901 byte alertType = (inputRecord.contentType() ==
902 Record.ct_handshake) ?
903 Alerts.alert_handshake_failure :
904 Alerts.alert_bad_record_mac;
905 fatal(alertType, "Invalid padding", e);
906 }
907
908 if (!inputRecord.checkMAC(readMAC, decryptedBB)) {
909 if (inputRecord.contentType() == Record.ct_handshake) {
910 fatal(Alerts.alert_handshake_failure,
911 "bad handshake record MAC");
912 } else {
913 fatal(Alerts.alert_bad_record_mac, "bad record MAC");
914 }
915 }
916
917 // if (!inputRecord.decompress(c))
918 // fatal(Alerts.alert_decompression_failure,
919 // "decompression failure");
920
921
922 /*
923 * Process the record.
924 */
925
926 synchronized (this) {
927 switch (inputRecord.contentType()) {
928 case Record.ct_handshake:
929 /*
930 * Handshake messages always go to a pending session
931 * handshaker ... if there isn't one, create one. This
932 * must work asynchronously, for renegotiation.
933 *
934 * NOTE that handshaking will either resume a session
935 * which was in the cache (and which might have other
936 * connections in it already), or else will start a new
937 * session (new keys exchanged) with just this connection
938 * in it.
939 */
940 initHandshaker();
941
942 /*
943 * process the handshake record ... may contain just
944 * a partial handshake message or multiple messages.
945 *
946 * The handshaker state machine will ensure that it's
947 * a finished message.
948 */
949 handshaker.process_record(inputRecord, expectingFinished);
950 expectingFinished = false;
951
952 if (handshaker.isDone()) {
953 sess = handshaker.getSession();
954 if (!writer.hasOutboundData()) {
955 hsStatus = HandshakeStatus.FINISHED;
956 }
957 handshaker = null;
958 connectionState = cs_DATA;
959
960 // No handshakeListeners here. That's a
961 // SSLSocket thing.
962 } else if (handshaker.taskOutstanding()) {
963 hsStatus = HandshakeStatus.NEED_TASK;
964 }
965 break;
966
967 case Record.ct_application_data:
968 // Pass this right back up to the application.
969 if ((connectionState != cs_DATA)
970 && (connectionState != cs_RENEGOTIATE)
971 && (connectionState != cs_CLOSED)) {
972 throw new SSLProtocolException(
973 "Data received in non-data state: " +
974 connectionState);
975 }
976
977 if (expectingFinished) {
978 throw new SSLProtocolException
979 ("Expecting finished message, received data");
980 }
981
982 /*
983 * Don't return data once the inbound side is
984 * closed.
985 */
986 if (!inboundDone) {
987 ea.scatter(decryptedBB.slice());
988 }
989 break;
990
991 case Record.ct_alert:
992 recvAlert();
993 break;
994
995 case Record.ct_change_cipher_spec:
996 if ((connectionState != cs_HANDSHAKE
997 && connectionState != cs_RENEGOTIATE)
998 || inputRecord.available() != 1
999 || inputRecord.read() != 1) {
1000 fatal(Alerts.alert_unexpected_message,
1001 "illegal change cipher spec msg, state = "
1002 + connectionState);
1003 }
1004
1005 //
1006 // The first message after a change_cipher_spec
1007 // record MUST be a "Finished" handshake record,
1008 // else it's a protocol violation. We force this
1009 // to be checked by a minor tweak to the state
1010 // machine.
1011 //
1012 changeReadCiphers();
1013 // next message MUST be a finished message
1014 expectingFinished = true;
1015 break;
1016
1017 default:
1018 //
1019 // TLS requires that unrecognized records be ignored.
1020 //
1021 if (debug != null && Debug.isOn("ssl")) {
1022 System.out.println(threadName() +
1023 ", Received record type: "
1024 + inputRecord.contentType());
1025 }
1026 break;
1027 } // switch
1028 } // synchronized (this)
1029 }
1030
1031 return hsStatus;
1032 }
1033
1034
1035 //
1036 // write/wrap side
1037 //
1038
1039
1040 /**
1041 * Wraps a buffer. Does a variety of checks before grabbing
1042 * the wrapLock, which blocks multiple wraps from occuring.
1043 */
1044 public SSLEngineResult wrap(ByteBuffer [] appData,
1045 int offset, int length, ByteBuffer netData) throws SSLException {
1046
1047 EngineArgs ea = new EngineArgs(appData, offset, length, netData);
1048
1049 /*
1050 * We can be smarter about using smaller buffer sizes later.
1051 * For now, force it to be large enough to handle any
1052 * valid SSL/TLS record.
1053 */
1054 if (netData.remaining() < outputRecord.maxRecordSize) {
1055 return new SSLEngineResult(
1056 Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0);
1057 }
1058
1059 try {
1060 synchronized (wrapLock) {
1061 return writeAppRecord(ea);
1062 }
1063 } catch (Exception e) {
1064 ea.resetPos();
1065
1066 fatal(Alerts.alert_internal_error,
1067 "problem unwrapping net record", e);
1068 return null; // make compiler happy
1069 } finally {
1070 /*
1071 * Just in case something didn't reset limits properly.
1072 */
1073 ea.resetLim();
1074 }
1075 }
1076
1077 /*
1078 * Makes additional checks for unwrap, but this time more
1079 * specific to this packet and the current state of the machine.
1080 */
1081 private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException {
1082
1083 Status status = null;
1084 HandshakeStatus hsStatus = null;
1085
1086 /*
1087 * See if the handshaker needs to report back some SSLException.
1088 */
1089 checkTaskThrown();
1090
1091 /*
1092 * short circuit if we're closed/closing.
1093 */
1094 if (writer.isOutboundDone()) {
1095 return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0);
1096 }
1097
1098 /*
1099 * If we're still in cs_HANDSHAKE, make sure it's been
1100 * started.
1101 */
1102 synchronized (this) {
1103 if ((connectionState == cs_HANDSHAKE) ||
1104 (connectionState == cs_START)) {
1105 kickstartHandshake();
1106
1107 /*
1108 * If there's no HS data available to write, we can return
1109 * without trying to wrap anything.
1110 */
1111 hsStatus = getHSStatus(null);
1112
1113 if (hsStatus == HandshakeStatus.NEED_UNWRAP) {
1114 return new SSLEngineResult(Status.OK, hsStatus, 0, 0);
1115 }
1116 }
1117 }
1118
1119 /*
1120 * Grab a copy of this if it doesn't already exist,
1121 * and we can use it several places before anything major
1122 * happens on this side. Races aren't critical
1123 * here.
1124 */
1125 if (hsStatus == null) {
1126 hsStatus = getHSStatus(null);
1127 }
1128
1129 /*
1130 * If we have a task outstanding, this *MUST* be done before
1131 * doing any more wrapping, because we could be in the middle
1132 * of receiving a handshake message, for example, a finished
1133 * message which would change the ciphers.
1134 */
1135 if (hsStatus == HandshakeStatus.NEED_TASK) {
1136 return new SSLEngineResult(
1137 Status.OK, hsStatus, 0, 0);
1138 }
1139
1140 /*
1141 * This will obtain any waiting outbound data, or will
1142 * process the outbound appData.
1143 */
1144 try {
1145 synchronized (writeLock) {
1146 hsStatus = writeRecord(outputRecord, ea);
1147 }
1148 } catch (SSLException e) {
1149 throw e;
1150 } catch (IOException e) {
1151 SSLException ex = new SSLException("Write problems");
1152 ex.initCause(e);
1153 throw ex;
1154 }
1155
1156 /*
1157 * writeRecord might have reported some status.
1158 * Now check for the remaining cases.
1159 *
1160 * status above should cover: NEED_WRAP/FINISHED
1161 */
1162 status = (isOutboundDone() ? Status.CLOSED : Status.OK);
1163 hsStatus = getHSStatus(hsStatus);
1164
1165 return new SSLEngineResult(status, hsStatus,
1166 ea.deltaApp(), ea.deltaNet());
1167 }
1168
1169 /*
1170 * Central point to write/get all of the outgoing data.
1171 */
1172 private HandshakeStatus writeRecord(EngineOutputRecord eor,
1173 EngineArgs ea) throws IOException {
1174
1175 // eventually compress as well.
1176 return writer.writeRecord(eor, ea, writeMAC, writeCipher);
1177 }
1178
1179 /*
1180 * Non-application OutputRecords go through here.
1181 */
1182 void writeRecord(EngineOutputRecord eor) throws IOException {
1183 // eventually compress as well.
1184 writer.writeRecord(eor, writeMAC, writeCipher);
1185 }
1186
1187 //
1188 // Close code
1189 //
1190
1191 /**
1192 * Signals that no more outbound application data will be sent
1193 * on this <code>SSLEngine</code>.
1194 */
1195 private void closeOutboundInternal() {
1196
1197 if ((debug != null) && Debug.isOn("ssl")) {
1198 System.out.println(threadName() + ", closeOutboundInternal()");
1199 }
1200
1201 /*
1202 * Already closed, ignore
1203 */
1204 if (writer.isOutboundDone()) {
1205 return;
1206 }
1207
1208 switch (connectionState) {
1209
1210 /*
1211 * If we haven't even started yet, don't bother reading inbound.
1212 */
1213 case cs_START:
1214 writer.closeOutbound();
1215 inboundDone = true;
1216 break;
1217
1218 case cs_ERROR:
1219 case cs_CLOSED:
1220 break;
1221
1222 /*
1223 * Otherwise we indicate clean termination.
1224 */
1225 // case cs_HANDSHAKE:
1226 // case cs_DATA:
1227 // case cs_RENEGOTIATE:
1228 default:
1229 warning(Alerts.alert_close_notify);
1230 writer.closeOutbound();
1231 break;
1232 }
1233
1234 connectionState = cs_CLOSED;
1235 }
1236
1237 synchronized public void closeOutbound() {
1238 /*
1239 * Dump out a close_notify to the remote side
1240 */
1241 if ((debug != null) && Debug.isOn("ssl")) {
1242 System.out.println(threadName() + ", called closeOutbound()");
1243 }
1244
1245 closeOutboundInternal();
1246 }
1247
1248 /**
1249 * Returns the outbound application data closure state
1250 */
1251 public boolean isOutboundDone() {
1252 return writer.isOutboundDone();
1253 }
1254
1255 /**
1256 * Signals that no more inbound network data will be sent
1257 * to this <code>SSLEngine</code>.
1258 */
1259 private void closeInboundInternal() {
1260
1261 if ((debug != null) && Debug.isOn("ssl")) {
1262 System.out.println(threadName() + ", closeInboundInternal()");
1263 }
1264
1265 /*
1266 * Already closed, ignore
1267 */
1268 if (inboundDone) {
1269 return;
1270 }
1271
1272 closeOutboundInternal();
1273 inboundDone = true;
1274 connectionState = cs_CLOSED;
1275 }
1276
1277 /*
1278 * Close the inbound side of the connection. We grab the
1279 * lock here, and do the real work in the internal verison.
1280 * We do check for truncation attacks.
1281 */
1282 synchronized public void closeInbound() throws SSLException {
1283 /*
1284 * Currently closes the outbound side as well. The IETF TLS
1285 * working group has expressed the opinion that 1/2 open
1286 * connections are not allowed by the spec. May change
1287 * someday in the future.
1288 */
1289 if ((debug != null) && Debug.isOn("ssl")) {
1290 System.out.println(threadName() + ", called closeInbound()");
1291 }
1292
1293 /*
1294 * No need to throw an Exception if we haven't even started yet.
1295 */
1296 if ((connectionState != cs_START) && !recvCN) {
1297 recvCN = true; // Only receive the Exception once
1298 fatal(Alerts.alert_internal_error,
1299 "Inbound closed before receiving peer's close_notify: " +
1300 "possible truncation attack?");
1301 } else {
1302 /*
1303 * Currently, this is a no-op, but in case we change
1304 * the close inbound code later.
1305 */
1306 closeInboundInternal();
1307 }
1308 }
1309
1310 /**
1311 * Returns the network inbound data closure state
1312 */
1313 synchronized public boolean isInboundDone() {
1314 return inboundDone;
1315 }
1316
1317
1318 //
1319 // Misc stuff
1320 //
1321
1322
1323 /**
1324 * Returns the current <code>SSLSession</code> for this
1325 * <code>SSLEngine</code>
1326 * <P>
1327 * These can be long lived, and frequently correspond to an
1328 * entire login session for some user.
1329 */
1330 synchronized public SSLSession getSession() {
1331 return sess;
1332 }
1333
1334 /**
1335 * Returns a delegated <code>Runnable</code> task for
1336 * this <code>SSLEngine</code>.
1337 */
1338 synchronized public Runnable getDelegatedTask() {
1339 if (handshaker != null) {
1340 return handshaker.getTask();
1341 }
1342 return null;
1343 }
1344
1345
1346 //
1347 // EXCEPTION AND ALERT HANDLING
1348 //
1349
1350 /*
1351 * Send a warning alert.
1352 */
1353 void warning(byte description) {
1354 sendAlert(Alerts.alert_warning, description);
1355 }
1356
1357 synchronized void fatal(byte description, String diagnostic)
1358 throws SSLException {
1359 fatal(description, diagnostic, null);
1360 }
1361
1362 synchronized void fatal(byte description, Throwable cause)
1363 throws SSLException {
1364 fatal(description, null, cause);
1365 }
1366
1367 /*
1368 * We've got a fatal error here, so start the shutdown process.
1369 *
1370 * Because of the way the code was written, we have some code
1371 * calling fatal directly when the "description" is known
1372 * and some throwing Exceptions which are then caught by higher
1373 * levels which then call here. This code needs to determine
1374 * if one of the lower levels has already started the process.
1375 *
1376 * We won't worry about Error's, if we have one of those,
1377 * we're in worse trouble. Note: the networking code doesn't
1378 * deal with Errors either.
1379 */
1380 synchronized void fatal(byte description, String diagnostic,
1381 Throwable cause) throws SSLException {
1382
1383 /*
1384 * If we have no further information, make a general-purpose
1385 * message for folks to see. We generally have one or the other.
1386 */
1387 if (diagnostic == null) {
1388 diagnostic = "General SSLEngine problem";
1389 }
1390 if (cause == null) {
1391 cause = Alerts.getSSLException(description, cause, diagnostic);
1392 }
1393
1394 /*
1395 * If we've already shutdown because of an error,
1396 * there is nothing we can do except rethrow the exception.
1397 *
1398 * Most exceptions seen here will be SSLExceptions.
1399 * We may find the occasional Exception which hasn't been
1400 * converted to a SSLException, so we'll do it here.
1401 */
1402 if (closeReason != null) {
1403 if ((debug != null) && Debug.isOn("ssl")) {
1404 System.out.println(threadName() +
1405 ", fatal: engine already closed. Rethrowing " +
1406 cause.toString());
1407 }
1408 if (cause instanceof RuntimeException) {
1409 throw (RuntimeException)cause;
1410 } else if (cause instanceof SSLException) {
1411 throw (SSLException)cause;
1412 } else if (cause instanceof Exception) {
1413 SSLException ssle = new SSLException(
1414 "fatal SSLEngine condition");
1415 ssle.initCause(cause);
1416 throw ssle;
1417 }
1418 }
1419
1420 if ((debug != null) && Debug.isOn("ssl")) {
1421 System.out.println(threadName()
1422 + ", fatal error: " + description +
1423 ": " + diagnostic + "\n" + cause.toString());
1424 }
1425
1426 /*
1427 * Ok, this engine's going down.
1428 */
1429 int oldState = connectionState;
1430 connectionState = cs_ERROR;
1431
1432 inboundDone = true;
1433
1434 sess.invalidate();
1435
1436 /*
1437 * If we haven't even started handshaking yet, no need
1438 * to generate the fatal close alert.
1439 */
1440 if (oldState != cs_START) {
1441 sendAlert(Alerts.alert_fatal, description);
1442 }
1443
1444 if (cause instanceof SSLException) { // only true if != null
1445 closeReason = (SSLException)cause;
1446 } else {
1447 /*
1448 * Including RuntimeExceptions, but we'll throw those
1449 * down below. The closeReason isn't used again,
1450 * except for null checks.
1451 */
1452 closeReason =
1453 Alerts.getSSLException(description, cause, diagnostic);
1454 }
1455
1456 writer.closeOutbound();
1457
1458 connectionState = cs_CLOSED;
1459
1460 if (cause instanceof RuntimeException) {
1461 throw (RuntimeException)cause;
1462 } else {
1463 throw closeReason;
1464 }
1465 }
1466
1467 /*
1468 * Process an incoming alert ... caller must already have synchronized
1469 * access to "this".
1470 */
1471 private void recvAlert() throws IOException {
1472 byte level = (byte)inputRecord.read();
1473 byte description = (byte)inputRecord.read();
1474 if (description == -1) { // check for short message
1475 fatal(Alerts.alert_illegal_parameter, "Short alert message");
1476 }
1477
1478 if (debug != null && (Debug.isOn("record") ||
1479 Debug.isOn("handshake"))) {
1480 synchronized (System.out) {
1481 System.out.print(threadName());
1482 System.out.print(", RECV " + protocolVersion + " ALERT: ");
1483 if (level == Alerts.alert_fatal) {
1484 System.out.print("fatal, ");
1485 } else if (level == Alerts.alert_warning) {
1486 System.out.print("warning, ");
1487 } else {
1488 System.out.print("<level " + (0x0ff & level) + ">, ");
1489 }
1490 System.out.println(Alerts.alertDescription(description));
1491 }
1492 }
1493
1494 if (level == Alerts.alert_warning) {
1495 if (description == Alerts.alert_close_notify) {
1496 if (connectionState == cs_HANDSHAKE) {
1497 fatal(Alerts.alert_unexpected_message,
1498 "Received close_notify during handshake");
1499 } else {
1500 recvCN = true;
1501 closeInboundInternal(); // reply to close
1502 }
1503 } else {
1504
1505 //
1506 // The other legal warnings relate to certificates,
1507 // e.g. no_certificate, bad_certificate, etc; these
1508 // are important to the handshaking code, which can
1509 // also handle illegal protocol alerts if needed.
1510 //
1511 if (handshaker != null) {
1512 handshaker.handshakeAlert(description);
1513 }
1514 }
1515 } else { // fatal or unknown level
1516 String reason = "Received fatal alert: "
1517 + Alerts.alertDescription(description);
1518 if (closeReason == null) {
1519 closeReason = Alerts.getSSLException(description, reason);
1520 }
1521 fatal(Alerts.alert_unexpected_message, reason);
1522 }
1523 }
1524
1525
1526 /*
1527 * Emit alerts. Caller must have synchronized with "this".
1528 */
1529 private void sendAlert(byte level, byte description) {
1530 if (connectionState >= cs_CLOSED) {
1531 return;
1532 }
1533
1534 EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this);
1535 r.setVersion(protocolVersion);
1536
1537 boolean useDebug = debug != null && Debug.isOn("ssl");
1538 if (useDebug) {
1539 synchronized (System.out) {
1540 System.out.print(threadName());
1541 System.out.print(", SEND " + protocolVersion + " ALERT: ");
1542 if (level == Alerts.alert_fatal) {
1543 System.out.print("fatal, ");
1544 } else if (level == Alerts.alert_warning) {
1545 System.out.print("warning, ");
1546 } else {
1547 System.out.print("<level = " + (0x0ff & level) + ">, ");
1548 }
1549 System.out.println("description = "
1550 + Alerts.alertDescription(description));
1551 }
1552 }
1553
1554 r.write(level);
1555 r.write(description);
1556 try {
1557 writeRecord(r);
1558 } catch (IOException e) {
1559 if (useDebug) {
1560 System.out.println(threadName() +
1561 ", Exception sending alert: " + e);
1562 }
1563 }
1564 }
1565
1566
1567 //
1568 // VARIOUS OTHER METHODS (COMMON TO SSLSocket)
1569 //
1570
1571
1572 /**
1573 * Controls whether new connections may cause creation of new SSL
1574 * sessions.
1575 *
1576 * As long as handshaking has not started, we can change
1577 * whether we enable session creations. Otherwise,
1578 * we will need to wait for the next handshake.
1579 */
1580 synchronized public void setEnableSessionCreation(boolean flag) {
1581 enableSessionCreation = flag;
1582
1583 if ((handshaker != null) && !handshaker.started()) {
1584 handshaker.setEnableSessionCreation(enableSessionCreation);
1585 }
1586 }
1587
1588 /**
1589 * Returns true if new connections may cause creation of new SSL
1590 * sessions.
1591 */
1592 synchronized public boolean getEnableSessionCreation() {
1593 return enableSessionCreation;
1594 }
1595
1596
1597 /**
1598 * Sets the flag controlling whether a server mode engine
1599 * *REQUIRES* SSL client authentication.
1600 *
1601 * As long as handshaking has not started, we can change
1602 * whether client authentication is needed. Otherwise,
1603 * we will need to wait for the next handshake.
1604 */
1605 synchronized public void setNeedClientAuth(boolean flag) {
1606 doClientAuth = (flag ?
1607 SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none);
1608
1609 if ((handshaker != null) &&
1610 (handshaker instanceof ServerHandshaker) &&
1611 !handshaker.started()) {
1612 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
1613 }
1614 }
1615
1616 synchronized public boolean getNeedClientAuth() {
1617 return (doClientAuth == SSLEngineImpl.clauth_required);
1618 }
1619
1620 /**
1621 * Sets the flag controlling whether a server mode engine
1622 * *REQUESTS* SSL client authentication.
1623 *
1624 * As long as handshaking has not started, we can change
1625 * whether client authentication is requested. Otherwise,
1626 * we will need to wait for the next handshake.
1627 */
1628 synchronized public void setWantClientAuth(boolean flag) {
1629 doClientAuth = (flag ?
1630 SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none);
1631
1632 if ((handshaker != null) &&
1633 (handshaker instanceof ServerHandshaker) &&
1634 !handshaker.started()) {
1635 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth);
1636 }
1637 }
1638
1639 synchronized public boolean getWantClientAuth() {
1640 return (doClientAuth == SSLEngineImpl.clauth_requested);
1641 }
1642
1643
1644 /**
1645 * Sets the flag controlling whether the engine is in SSL
1646 * client or server mode. Must be called before any SSL
1647 * traffic has started.
1648 */
1649 synchronized public void setUseClientMode(boolean flag) {
1650 switch (connectionState) {
1651
1652 case cs_START:
1653 roleIsServer = !flag;
1654 serverModeSet = true;
1655 break;
1656
1657 case cs_HANDSHAKE:
1658 /*
1659 * If we have a handshaker, but haven't started
1660 * SSL traffic, we can throw away our current
1661 * handshaker, and start from scratch. Don't
1662 * need to call doneConnect() again, we already
1663 * have the streams.
1664 */
1665 assert(handshaker != null);
1666 if (!handshaker.started()) {
1667 roleIsServer = !flag;
1668 connectionState = cs_START;
1669 initHandshaker();
1670 break;
1671 }
1672
1673 // If handshake has started, that's an error. Fall through...
1674
1675 default:
1676 if (debug != null && Debug.isOn("ssl")) {
1677 System.out.println(threadName() +
1678 ", setUseClientMode() invoked in state = " +
1679 connectionState);
1680 }
1681
1682 /*
1683 * We can let them continue if they catch this correctly,
1684 * we don't need to shut this down.
1685 */
1686 throw new IllegalArgumentException(
1687 "Cannot change mode after SSL traffic has started");
1688 }
1689 }
1690
1691 synchronized public boolean getUseClientMode() {
1692 return !roleIsServer;
1693 }
1694
1695
1696 /**
1697 * Returns the names of the cipher suites which could be enabled for use
1698 * on an SSL connection. Normally, only a subset of these will actually
1699 * be enabled by default, since this list may include cipher suites which
1700 * do not support the mutual authentication of servers and clients, or
1701 * which do not protect data confidentiality. Servers may also need
1702 * certain kinds of certificates to use certain cipher suites.
1703 *
1704 * @return an array of cipher suite names
1705 */
1706 public String[] getSupportedCipherSuites() {
1707 CipherSuiteList.clearAvailableCache();
1708 return CipherSuiteList.getSupported().toStringArray();
1709 }
1710
1711 /**
1712 * Controls which particular cipher suites are enabled for use on
1713 * this connection. The cipher suites must have been listed by
1714 * getCipherSuites() as being supported. Even if a suite has been
1715 * enabled, it might never be used if no peer supports it or the
1716 * requisite certificates (and private keys) are not available.
1717 *
1718 * @param suites Names of all the cipher suites to enable.
1719 */
1720 synchronized public void setEnabledCipherSuites(String[] suites) {
1721 enabledCipherSuites = new CipherSuiteList(suites);
1722 if ((handshaker != null) && !handshaker.started()) {
1723 handshaker.enabledCipherSuites = enabledCipherSuites;
1724 }
1725 }
1726
1727 /**
1728 * Returns the names of the SSL cipher suites which are currently enabled
1729 * for use on this connection. When an SSL engine is first created,
1730 * all enabled cipher suites <em>(a)</em> protect data confidentiality,
1731 * by traffic encryption, and <em>(b)</em> can mutually authenticate
1732 * both clients and servers. Thus, in some environments, this value
1733 * might be empty.
1734 *
1735 * @return an array of cipher suite names
1736 */
1737 synchronized public String[] getEnabledCipherSuites() {
1738 return enabledCipherSuites.toStringArray();
1739 }
1740
1741
1742 /**
1743 * Returns the protocols that are supported by this implementation.
1744 * A subset of the supported protocols may be enabled for this connection
1745 * @ returns an array of protocol names.
1746 */
1747 public String[] getSupportedProtocols() {
1748 return ProtocolList.getSupported().toStringArray();
1749 }
1750
1751 /**
1752 * Controls which protocols are enabled for use on
1753 * this connection. The protocols must have been listed by
1754 * getSupportedProtocols() as being supported.
1755 *
1756 * @param protocols protocols to enable.
1757 * @exception IllegalArgumentException when one of the protocols
1758 * named by the parameter is not supported.
1759 */
1760 synchronized public void setEnabledProtocols(String[] protocols) {
1761 enabledProtocols = new ProtocolList(protocols);
1762 if ((handshaker != null) && !handshaker.started()) {
1763 handshaker.setEnabledProtocols(enabledProtocols);
1764 }
1765 }
1766
1767 synchronized public String[] getEnabledProtocols() {
1768 return enabledProtocols.toStringArray();
1769 }
1770
1771 /**
1772 * Try to configure the endpoint identification algorithm of the engine.
1773 *
1774 * @param identificationAlgorithm the algorithm used to check the
1775 * endpoint identity.
1776 * @return true if the identification algorithm configuration success.
1777 */
1778 synchronized public boolean trySetHostnameVerification(
1779 String identificationAlgorithm) {
1780 if (sslContext.getX509TrustManager() instanceof
1781 X509ExtendedTrustManager) {
1782 this.identificationAlg = identificationAlgorithm;
1783 return true;
1784 } else {
1785 return false;
1786 }
1787 }
1788
1789 /**
1790 * Returns the endpoint identification algorithm of the engine.
1791 */
1792 synchronized public String getHostnameVerification() {
1793 return identificationAlg;
1794 }
1795
1796 /**
1797 * Return the name of the current thread. Utility method.
1798 */
1799 private static String threadName() {
1800 return Thread.currentThread().getName();
1801 }
1802
1803 /**
1804 * Returns a printable representation of this end of the connection.
1805 */
1806 public String toString() {
1807 StringBuilder retval = new StringBuilder(80);
1808
1809 retval.append(Integer.toHexString(hashCode()));
1810 retval.append("[");
1811 retval.append("SSLEngine[hostname=");
1812 String host = getPeerHost();
1813 retval.append((host == null) ? "null" : host);
1814 retval.append(" port=");
1815 retval.append(Integer.toString(getPeerPort()));
1816 retval.append("] ");
1817 retval.append(getSession().getCipherSuite());
1818 retval.append("]");
1819
1820 return retval.toString();
1821 }
1822}