changeset 30904 | ec0224270f90 |
parent 28550 | 003089aca6b9 |
child 32649 | 2ee9017c7597 |
30903:0c7d705209c6 | 30904:ec0224270f90 |
---|---|
52 * example, thread1 and thread2 both call wrap, thread1 gets the first |
52 * example, thread1 and thread2 both call wrap, thread1 gets the first |
53 * packet, thread2 gets the second packet, but thread2 gets control back |
53 * packet, thread2 gets the second packet, but thread2 gets control back |
54 * before thread1, and sends the data. The receiving side would see an |
54 * before thread1, and sends the data. The receiving side would see an |
55 * out-of-order error. |
55 * out-of-order error. |
56 * |
56 * |
57 * Handshaking is still done the same way as SSLSocket using the normal |
|
58 * InputStream/OutputStream abstactions. We create |
|
59 * ClientHandshakers/ServerHandshakers, which produce/consume the |
|
60 * handshaking data. The transfer of the data is largely handled by the |
|
61 * HandshakeInStream/HandshakeOutStreams. Lastly, the |
|
62 * InputRecord/OutputRecords still have the same functionality, except |
|
63 * that they are overridden with EngineInputRecord/EngineOutputRecord, |
|
64 * which provide SSLEngine-specific functionality. |
|
65 * |
|
66 * Some of the major differences are: |
|
67 * |
|
68 * EngineInputRecord/EngineOutputRecord/EngineWriter: |
|
69 * |
|
70 * In order to avoid writing whole new control flows for |
|
71 * handshaking, and to reuse most of the same code, we kept most |
|
72 * of the actual handshake code the same. As usual, reading |
|
73 * handshake data may trigger output of more handshake data, so |
|
74 * what we do is write this data to internal buffers, and wait for |
|
75 * wrap() to be called to give that data a ride. |
|
76 * |
|
77 * All data is routed through |
|
78 * EngineInputRecord/EngineOutputRecord. However, all handshake |
|
79 * data (ct_alert/ct_change_cipher_spec/ct_handshake) are passed |
|
80 * through to the underlying InputRecord/OutputRecord, and |
|
81 * the data uses the internal buffers. |
|
82 * |
|
83 * Application data is handled slightly different, we copy the data |
|
84 * directly from the src to the dst buffers, and do all operations |
|
85 * on those buffers, saving the overhead of multiple copies. |
|
86 * |
|
87 * In the case of an inbound record, unwrap passes the inbound |
|
88 * ByteBuffer to the InputRecord. If the data is handshake data, |
|
89 * the data is read into the InputRecord's internal buffer. If |
|
90 * the data is application data, the data is decoded directly into |
|
91 * the dst buffer. |
|
92 * |
|
93 * In the case of an outbound record, when the write to the |
|
94 * "real" OutputStream's would normally take place, instead we |
|
95 * call back up to the EngineOutputRecord's version of |
|
96 * writeBuffer, at which time we capture the resulting output in a |
|
97 * ByteBuffer, and send that back to the EngineWriter for internal |
|
98 * storage. |
|
99 * |
|
100 * EngineWriter is responsible for "handling" all outbound |
|
101 * data, be it handshake or app data, and for returning the data |
|
102 * to wrap() in the proper order. |
|
103 * |
|
104 * ClientHandshaker/ServerHandshaker/Handshaker: |
|
105 * Methods which relied on SSLSocket now have work on either |
|
106 * SSLSockets or SSLEngines. |
|
107 * |
|
108 * @author Brad Wetmore |
57 * @author Brad Wetmore |
109 */ |
58 */ |
110 final public class SSLEngineImpl extends SSLEngine { |
59 final public class SSLEngineImpl extends SSLEngine { |
111 |
60 |
112 // |
61 // |
173 private static final int cs_CLOSED = 6; |
122 private static final int cs_CLOSED = 6; |
174 |
123 |
175 /* |
124 /* |
176 * Once we're in state cs_CLOSED, we can continue to |
125 * Once we're in state cs_CLOSED, we can continue to |
177 * wrap/unwrap until we finish sending/receiving the messages |
126 * wrap/unwrap until we finish sending/receiving the messages |
178 * for close_notify. EngineWriter handles outboundDone. |
127 * for close_notify. |
179 */ |
128 */ |
180 private boolean inboundDone = false; |
129 private boolean inboundDone = false; |
181 |
130 private boolean outboundDone = false; |
182 EngineWriter writer; |
|
183 |
131 |
184 /* |
132 /* |
185 * The authentication context holds all information used to establish |
133 * The authentication context holds all information used to establish |
186 * who this end of the connection is (certificate chains, private keys, |
134 * who this end of the connection is (certificate chains, private keys, |
187 * etc) and who is trusted (e.g. as CAs or websites). |
135 * etc) and who is trusted (e.g. as CAs or websites). |
199 */ |
147 */ |
200 private Handshaker handshaker; |
148 private Handshaker handshaker; |
201 private SSLSessionImpl sess; |
149 private SSLSessionImpl sess; |
202 private volatile SSLSessionImpl handshakeSession; |
150 private volatile SSLSessionImpl handshakeSession; |
203 |
151 |
204 |
|
205 /* |
|
206 * Client authentication be off, requested, or required. |
|
207 * |
|
208 * This will be used by both this class and SSLSocket's variants. |
|
209 */ |
|
210 static final byte clauth_none = 0; |
|
211 static final byte clauth_requested = 1; |
|
212 static final byte clauth_required = 2; |
|
213 |
|
214 /* |
|
215 * Flag indicating that the engine has received a ChangeCipherSpec message. |
|
216 */ |
|
217 private boolean receivedCCS; |
|
218 |
|
219 /* |
152 /* |
220 * Flag indicating if the next record we receive MUST be a Finished |
153 * Flag indicating if the next record we receive MUST be a Finished |
221 * message. Temporarily set during the handshake to ensure that |
154 * message. Temporarily set during the handshake to ensure that |
222 * a change cipher spec message is followed by a finished message. |
155 * a change cipher spec message is followed by a finished message. |
223 */ |
156 */ |
241 |
174 |
242 /* |
175 /* |
243 * Per-connection private state that doesn't change when the |
176 * Per-connection private state that doesn't change when the |
244 * session is changed. |
177 * session is changed. |
245 */ |
178 */ |
246 private byte doClientAuth; |
179 private ClientAuthType doClientAuth = |
247 private boolean enableSessionCreation = true; |
180 ClientAuthType.CLIENT_AUTH_NONE; |
248 EngineInputRecord inputRecord; |
181 private boolean enableSessionCreation = true; |
249 EngineOutputRecord outputRecord; |
182 InputRecord inputRecord; |
250 private AccessControlContext acc; |
183 OutputRecord outputRecord; |
184 private AccessControlContext acc; |
|
251 |
185 |
252 // The cipher suites enabled for use on this connection. |
186 // The cipher suites enabled for use on this connection. |
253 private CipherSuiteList enabledCipherSuites; |
187 private CipherSuiteList enabledCipherSuites; |
254 |
188 |
255 // the endpoint identification protocol |
189 // the endpoint identification protocol |
278 private ProtocolList enabledProtocols; |
212 private ProtocolList enabledProtocols; |
279 |
213 |
280 /* |
214 /* |
281 * The SSL version associated with this connection. |
215 * The SSL version associated with this connection. |
282 */ |
216 */ |
283 private ProtocolVersion protocolVersion = ProtocolVersion.DEFAULT; |
217 private ProtocolVersion protocolVersion; |
284 |
|
285 /* |
|
286 * Crypto state that's reinitialized when the session changes. |
|
287 */ |
|
288 private Authenticator readAuthenticator, writeAuthenticator; |
|
289 private CipherBox readCipher, writeCipher; |
|
290 // NOTE: compression state would be saved here |
|
291 |
218 |
292 /* |
219 /* |
293 * security parameters for secure renegotiation. |
220 * security parameters for secure renegotiation. |
294 */ |
221 */ |
295 private boolean secureRenegotiation; |
222 private boolean secureRenegotiation; |
318 private Object wrapLock; |
245 private Object wrapLock; |
319 private Object unwrapLock; |
246 private Object unwrapLock; |
320 Object writeLock; |
247 Object writeLock; |
321 |
248 |
322 /* |
249 /* |
323 * Is it the first application record to write? |
|
324 */ |
|
325 private boolean isFirstAppOutputRecord = true; |
|
326 |
|
327 /* |
|
328 * Whether local cipher suites preference in server side should be |
250 * Whether local cipher suites preference in server side should be |
329 * honored during handshaking? |
251 * honored during handshaking? |
330 */ |
252 */ |
331 private boolean preferLocalCipherSuites = false; |
253 private boolean preferLocalCipherSuites = false; |
254 |
|
255 /* |
|
256 * whether DTLS handshake retransmissions should be enabled? |
|
257 */ |
|
258 private boolean enableRetransmissions = false; |
|
259 |
|
260 /* |
|
261 * The maximum expected network packet size for SSL/TLS/DTLS records. |
|
262 */ |
|
263 private int maximumPacketSize = 0; |
|
264 |
|
265 /* |
|
266 * Is this an instance for Datagram Transport Layer Security (DTLS)? |
|
267 */ |
|
268 private final boolean isDTLS; |
|
332 |
269 |
333 /* |
270 /* |
334 * Class and subclass dynamic debugging support |
271 * Class and subclass dynamic debugging support |
335 */ |
272 */ |
336 private static final Debug debug = Debug.getInstance("ssl"); |
273 private static final Debug debug = Debug.getInstance("ssl"); |
342 /** |
279 /** |
343 * Constructor for an SSLEngine from SSLContext, without |
280 * Constructor for an SSLEngine from SSLContext, without |
344 * host/port hints. This Engine will not be able to cache |
281 * host/port hints. This Engine will not be able to cache |
345 * sessions, but must renegotiate everything by hand. |
282 * sessions, but must renegotiate everything by hand. |
346 */ |
283 */ |
347 SSLEngineImpl(SSLContextImpl ctx) { |
284 SSLEngineImpl(SSLContextImpl ctx, boolean isDTLS) { |
348 super(); |
285 super(); |
349 init(ctx); |
286 this.isDTLS = isDTLS; |
287 init(ctx, isDTLS); |
|
350 } |
288 } |
351 |
289 |
352 /** |
290 /** |
353 * Constructor for an SSLEngine from SSLContext. |
291 * Constructor for an SSLEngine from SSLContext. |
354 */ |
292 */ |
355 SSLEngineImpl(SSLContextImpl ctx, String host, int port) { |
293 SSLEngineImpl(SSLContextImpl ctx, String host, int port, boolean isDTLS) { |
356 super(host, port); |
294 super(host, port); |
357 init(ctx); |
295 this.isDTLS = isDTLS; |
296 init(ctx, isDTLS); |
|
358 } |
297 } |
359 |
298 |
360 /** |
299 /** |
361 * Initializes the Engine |
300 * Initializes the Engine |
362 */ |
301 */ |
363 private void init(SSLContextImpl ctx) { |
302 private void init(SSLContextImpl ctx, boolean isDTLS) { |
364 if (debug != null && Debug.isOn("ssl")) { |
303 if (debug != null && Debug.isOn("ssl")) { |
365 System.out.println("Using SSLEngineImpl."); |
304 System.out.println("Using SSLEngineImpl."); |
366 } |
305 } |
367 |
306 |
368 sslContext = ctx; |
307 sslContext = ctx; |
369 sess = SSLSessionImpl.nullSession; |
308 sess = SSLSessionImpl.nullSession; |
370 handshakeSession = null; |
309 handshakeSession = null; |
310 protocolVersion = isDTLS ? |
|
311 ProtocolVersion.DEFAULT_DTLS : ProtocolVersion.DEFAULT_TLS; |
|
371 |
312 |
372 /* |
313 /* |
373 * State is cs_START until we initialize the handshaker. |
314 * State is cs_START until we initialize the handshaker. |
374 * |
315 * |
375 * Apps using SSLEngine are probably going to be server. |
316 * Apps using SSLEngine are probably going to be server. |
376 * Somewhat arbitrary choice. |
317 * Somewhat arbitrary choice. |
377 */ |
318 */ |
378 roleIsServer = true; |
319 roleIsServer = true; |
379 connectionState = cs_START; |
320 connectionState = cs_START; |
380 receivedCCS = false; |
|
381 |
321 |
382 // default server name indication |
322 // default server name indication |
383 serverNames = |
323 serverNames = |
384 Utilities.addToSNIServerNameList(serverNames, getPeerHost()); |
324 Utilities.addToSNIServerNameList(serverNames, getPeerHost()); |
385 |
|
386 /* |
|
387 * default read and write side cipher and MAC support |
|
388 * |
|
389 * Note: compression support would go here too |
|
390 */ |
|
391 readCipher = CipherBox.NULL; |
|
392 readAuthenticator = MAC.NULL; |
|
393 writeCipher = CipherBox.NULL; |
|
394 writeAuthenticator = MAC.NULL; |
|
395 |
325 |
396 // default security parameters for secure renegotiation |
326 // default security parameters for secure renegotiation |
397 secureRenegotiation = false; |
327 secureRenegotiation = false; |
398 clientVerifyData = new byte[0]; |
328 clientVerifyData = new byte[0]; |
399 serverVerifyData = new byte[0]; |
329 serverVerifyData = new byte[0]; |
419 * All outbound application data goes through this OutputRecord, |
349 * All outbound application data goes through this OutputRecord, |
420 * other data goes through their respective records created |
350 * other data goes through their respective records created |
421 * elsewhere. All inbound data goes through this one |
351 * elsewhere. All inbound data goes through this one |
422 * input record. |
352 * input record. |
423 */ |
353 */ |
424 outputRecord = |
354 if (isDTLS) { |
425 new EngineOutputRecord(Record.ct_application_data, this); |
355 enableRetransmissions = true; |
426 inputRecord = new EngineInputRecord(this); |
356 |
427 inputRecord.enableFormatChecks(); |
357 // SSLEngine needs no record local buffer |
428 |
358 outputRecord = new DTLSOutputRecord(); |
429 writer = new EngineWriter(); |
359 inputRecord = new DTLSInputRecord(); |
360 |
|
361 } else { |
|
362 outputRecord = new SSLEngineOutputRecord(); |
|
363 inputRecord = new SSLEngineInputRecord(); |
|
364 } |
|
365 |
|
366 maximumPacketSize = outputRecord.getMaxPacketSize(); |
|
430 } |
367 } |
431 |
368 |
432 /** |
369 /** |
433 * Initialize the handshaker object. This means: |
370 * Initialize the handshaker object. This means: |
434 * |
371 * |
478 } |
415 } |
479 if (roleIsServer) { |
416 if (roleIsServer) { |
480 handshaker = new ServerHandshaker(this, sslContext, |
417 handshaker = new ServerHandshaker(this, sslContext, |
481 enabledProtocols, doClientAuth, |
418 enabledProtocols, doClientAuth, |
482 protocolVersion, connectionState == cs_HANDSHAKE, |
419 protocolVersion, connectionState == cs_HANDSHAKE, |
483 secureRenegotiation, clientVerifyData, serverVerifyData); |
420 secureRenegotiation, clientVerifyData, serverVerifyData, |
421 isDTLS); |
|
484 handshaker.setSNIMatchers(sniMatchers); |
422 handshaker.setSNIMatchers(sniMatchers); |
485 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites); |
423 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites); |
486 } else { |
424 } else { |
487 handshaker = new ClientHandshaker(this, sslContext, |
425 handshaker = new ClientHandshaker(this, sslContext, |
488 enabledProtocols, |
426 enabledProtocols, |
489 protocolVersion, connectionState == cs_HANDSHAKE, |
427 protocolVersion, connectionState == cs_HANDSHAKE, |
490 secureRenegotiation, clientVerifyData, serverVerifyData); |
428 secureRenegotiation, clientVerifyData, serverVerifyData, |
429 isDTLS); |
|
491 handshaker.setSNIServerNames(serverNames); |
430 handshaker.setSNIServerNames(serverNames); |
492 } |
431 } |
432 handshaker.setMaximumPacketSize(maximumPacketSize); |
|
493 handshaker.setEnabledCipherSuites(enabledCipherSuites); |
433 handshaker.setEnabledCipherSuites(enabledCipherSuites); |
494 handshaker.setEnableSessionCreation(enableSessionCreation); |
434 handshaker.setEnableSessionCreation(enableSessionCreation); |
435 |
|
436 outputRecord.initHandshaker(); |
|
495 } |
437 } |
496 |
438 |
497 /* |
439 /* |
498 * Report the current status of the Handshaker |
440 * Report the current status of the Handshaker |
499 */ |
441 */ |
502 if (hss != null) { |
444 if (hss != null) { |
503 return hss; |
445 return hss; |
504 } |
446 } |
505 |
447 |
506 synchronized (this) { |
448 synchronized (this) { |
507 if (writer.hasOutboundData()) { |
449 if (!outputRecord.isEmpty()) { |
450 // If no handshaking, special case to wrap alters. |
|
508 return HandshakeStatus.NEED_WRAP; |
451 return HandshakeStatus.NEED_WRAP; |
509 } else if (handshaker != null) { |
452 } else if (handshaker != null) { |
510 if (handshaker.taskOutstanding()) { |
453 if (handshaker.taskOutstanding()) { |
511 return HandshakeStatus.NEED_TASK; |
454 return HandshakeStatus.NEED_TASK; |
455 } else if (isDTLS && !inputRecord.isEmpty()) { |
|
456 return HandshakeStatus.NEED_UNWRAP_AGAIN; |
|
512 } else { |
457 } else { |
513 return HandshakeStatus.NEED_UNWRAP; |
458 return HandshakeStatus.NEED_UNWRAP; |
514 } |
459 } |
515 } else if (connectionState == cs_CLOSED) { |
460 } else if (connectionState == cs_CLOSED) { |
516 /* |
461 /* |
570 public SSLEngineResult.HandshakeStatus getHandshakeStatus() { |
515 public SSLEngineResult.HandshakeStatus getHandshakeStatus() { |
571 return getHSStatus(null); |
516 return getHSStatus(null); |
572 } |
517 } |
573 |
518 |
574 /* |
519 /* |
575 * When a connection finishes handshaking by enabling use of a newly |
|
576 * negotiated session, each end learns about it in two halves (read, |
|
577 * and write). When both read and write ciphers have changed, and the |
|
578 * last handshake message has been read, the connection has joined |
|
579 * (rejoined) the new session. |
|
580 * |
|
581 * NOTE: The SSLv3 spec is rather unclear on the concepts here. |
|
582 * Sessions don't change once they're established (including cipher |
|
583 * suite and master secret) but connections can join them (and leave |
|
584 * them). They're created by handshaking, though sometime handshaking |
|
585 * causes connections to join up with pre-established sessions. |
|
586 * |
|
587 * Synchronized on "this" from readRecord. |
|
588 */ |
|
589 private void changeReadCiphers() throws SSLException { |
|
590 if (connectionState != cs_HANDSHAKE |
|
591 && connectionState != cs_RENEGOTIATE) { |
|
592 throw new SSLProtocolException( |
|
593 "State error, change cipher specs"); |
|
594 } |
|
595 |
|
596 // ... create decompressor |
|
597 |
|
598 CipherBox oldCipher = readCipher; |
|
599 |
|
600 try { |
|
601 readCipher = handshaker.newReadCipher(); |
|
602 readAuthenticator = handshaker.newReadAuthenticator(); |
|
603 } catch (GeneralSecurityException e) { |
|
604 // "can't happen" |
|
605 throw new SSLException("Algorithm missing: ", e); |
|
606 } |
|
607 |
|
608 /* |
|
609 * Dispose of any intermediate state in the underlying cipher. |
|
610 * For PKCS11 ciphers, this will release any attached sessions, |
|
611 * and thus make finalization faster. |
|
612 * |
|
613 * Since MAC's doFinal() is called for every SSL/TLS packet, it's |
|
614 * not necessary to do the same with MAC's. |
|
615 */ |
|
616 oldCipher.dispose(); |
|
617 } |
|
618 |
|
619 /* |
|
620 * used by Handshaker to change the active write cipher, follows |
520 * used by Handshaker to change the active write cipher, follows |
621 * the output of the CCS message. |
521 * the output of the CCS message. |
622 * |
522 * |
623 * Also synchronized on "this" from readRecord/delegatedTask. |
523 * Also synchronized on "this" from readRecord/delegatedTask. |
624 */ |
524 */ |
625 void changeWriteCiphers() throws SSLException { |
525 void changeWriteCiphers() throws IOException { |
626 if (connectionState != cs_HANDSHAKE |
526 |
627 && connectionState != cs_RENEGOTIATE) { |
527 Authenticator writeAuthenticator; |
628 throw new SSLProtocolException( |
528 CipherBox writeCipher; |
629 "State error, change cipher specs"); |
|
630 } |
|
631 |
|
632 // ... create compressor |
|
633 |
|
634 CipherBox oldCipher = writeCipher; |
|
635 |
|
636 try { |
529 try { |
637 writeCipher = handshaker.newWriteCipher(); |
530 writeCipher = handshaker.newWriteCipher(); |
638 writeAuthenticator = handshaker.newWriteAuthenticator(); |
531 writeAuthenticator = handshaker.newWriteAuthenticator(); |
639 } catch (GeneralSecurityException e) { |
532 } catch (GeneralSecurityException e) { |
640 // "can't happen" |
533 // "can't happen" |
641 throw new SSLException("Algorithm missing: ", e); |
534 throw new SSLException("Algorithm missing: ", e); |
642 } |
535 } |
643 |
536 |
644 // See comment above. |
537 outputRecord.changeWriteCiphers(writeAuthenticator, writeCipher); |
645 oldCipher.dispose(); |
|
646 |
|
647 // reset the flag of the first application record |
|
648 isFirstAppOutputRecord = true; |
|
649 } |
538 } |
650 |
539 |
651 /* |
540 /* |
652 * Updates the SSL version associated with this connection. |
541 * Updates the SSL version associated with this connection. |
653 * Called from Handshaker once it has determined the negotiated version. |
542 * Called from Handshaker once it has determined the negotiated version. |
713 throw new SSLException("SSLEngine is closing/closed"); |
602 throw new SSLException("SSLEngine is closing/closed"); |
714 } |
603 } |
715 |
604 |
716 // |
605 // |
717 // Kickstart handshake state machine if we need to ... |
606 // Kickstart handshake state machine if we need to ... |
718 // |
|
719 // Note that handshaker.kickstart() writes the message |
|
720 // to its HandshakeOutStream, which calls back into |
|
721 // SSLSocketImpl.writeRecord() to send it. |
|
722 // |
607 // |
723 if (!handshaker.activated()) { |
608 if (!handshaker.activated()) { |
724 // prior to handshaking, activate the handshake |
609 // prior to handshaking, activate the handshake |
725 if (connectionState == cs_RENEGOTIATE) { |
610 if (connectionState == cs_RENEGOTIATE) { |
726 // don't use SSLv2Hello when renegotiating |
611 // don't use SSLv2Hello when renegotiating |
736 if (connectionState == cs_HANDSHAKE) { |
621 if (connectionState == cs_HANDSHAKE) { |
737 // initial handshake, no kickstart message to send |
622 // initial handshake, no kickstart message to send |
738 } else { |
623 } else { |
739 // we want to renegotiate, send hello request |
624 // we want to renegotiate, send hello request |
740 handshaker.kickstart(); |
625 handshaker.kickstart(); |
741 |
|
742 // hello request is not included in the handshake |
|
743 // hashes, reset them |
|
744 handshaker.handshakeHash.reset(); |
|
745 } |
626 } |
746 } |
627 } |
747 } |
628 } |
748 } |
629 } |
749 |
630 |
769 /** |
650 /** |
770 * Unwraps a buffer. Does a variety of checks before grabbing |
651 * Unwraps a buffer. Does a variety of checks before grabbing |
771 * the unwrapLock, which blocks multiple unwraps from occurring. |
652 * the unwrapLock, which blocks multiple unwraps from occurring. |
772 */ |
653 */ |
773 @Override |
654 @Override |
774 public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer [] appData, |
655 public SSLEngineResult unwrap(ByteBuffer netData, ByteBuffer[] appData, |
775 int offset, int length) throws SSLException { |
656 int offset, int length) throws SSLException { |
776 |
657 |
777 EngineArgs ea = new EngineArgs(netData, appData, offset, length); |
658 // check engine parameters |
659 checkEngineParas(netData, appData, offset, length, false); |
|
778 |
660 |
779 try { |
661 try { |
780 synchronized (unwrapLock) { |
662 synchronized (unwrapLock) { |
781 return readNetRecord(ea); |
663 return readNetRecord(netData, appData, offset, length); |
782 } |
664 } |
665 } catch (SSLProtocolException spe) { |
|
666 // may be an unexpected handshake message |
|
667 fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe); |
|
668 return null; // make compiler happy |
|
783 } catch (Exception e) { |
669 } catch (Exception e) { |
784 /* |
670 /* |
785 * Don't reset position so it looks like we didn't |
671 * Don't reset position so it looks like we didn't |
786 * consume anything. We did consume something, and it |
672 * consume anything. We did consume something, and it |
787 * got us into this situation, so report that much back. |
673 * got us into this situation, so report that much back. |
788 * Our days of consuming are now over anyway. |
674 * Our days of consuming are now over anyway. |
789 */ |
675 */ |
790 fatal(Alerts.alert_internal_error, |
676 fatal(Alerts.alert_internal_error, |
791 "problem unwrapping net record", e); |
677 "problem unwrapping net record", e); |
792 return null; // make compiler happy |
678 return null; // make compiler happy |
793 } finally { |
679 } |
680 } |
|
681 |
|
682 private static void checkEngineParas(ByteBuffer netData, |
|
683 ByteBuffer[] appData, int offset, int len, boolean isForWrap) { |
|
684 |
|
685 if ((netData == null) || (appData == null)) { |
|
686 throw new IllegalArgumentException("src/dst is null"); |
|
687 } |
|
688 |
|
689 if ((offset < 0) || (len < 0) || (offset > appData.length - len)) { |
|
690 throw new IndexOutOfBoundsException(); |
|
691 } |
|
692 |
|
693 /* |
|
694 * If wrapping, make sure the destination bufffer is writable. |
|
695 */ |
|
696 if (isForWrap && netData.isReadOnly()) { |
|
697 throw new ReadOnlyBufferException(); |
|
698 } |
|
699 |
|
700 for (int i = offset; i < offset + len; i++) { |
|
701 if (appData[i] == null) { |
|
702 throw new IllegalArgumentException( |
|
703 "appData[" + i + "] == null"); |
|
704 } |
|
705 |
|
794 /* |
706 /* |
795 * Just in case something failed to reset limits properly. |
707 * If unwrapping, make sure the destination bufffers are writable. |
796 */ |
708 */ |
797 ea.resetLim(); |
709 if (!isForWrap && appData[i].isReadOnly()) { |
710 throw new ReadOnlyBufferException(); |
|
711 } |
|
798 } |
712 } |
799 } |
713 } |
800 |
714 |
801 /* |
715 /* |
802 * Makes additional checks for unwrap, but this time more |
716 * Makes additional checks for unwrap, but this time more |
803 * specific to this packet and the current state of the machine. |
717 * specific to this packet and the current state of the machine. |
804 */ |
718 */ |
805 private SSLEngineResult readNetRecord(EngineArgs ea) throws IOException { |
719 private SSLEngineResult readNetRecord(ByteBuffer netData, |
720 ByteBuffer[] appData, int offset, int length) throws IOException { |
|
806 |
721 |
807 Status status = null; |
722 Status status = null; |
808 HandshakeStatus hsStatus = null; |
723 HandshakeStatus hsStatus = null; |
809 |
724 |
810 /* |
725 /* |
855 * doing any more unwrapping, because we could be in the middle |
770 * doing any more unwrapping, because we could be in the middle |
856 * of receiving a handshake message, for example, a finished |
771 * of receiving a handshake message, for example, a finished |
857 * message which would change the ciphers. |
772 * message which would change the ciphers. |
858 */ |
773 */ |
859 if (hsStatus == HandshakeStatus.NEED_TASK) { |
774 if (hsStatus == HandshakeStatus.NEED_TASK) { |
775 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); |
|
776 } |
|
777 |
|
778 if (hsStatus == SSLEngineResult.HandshakeStatus.NEED_UNWRAP_AGAIN) { |
|
779 Plaintext plainText = null; |
|
780 try { |
|
781 plainText = readRecord(null, null, 0, 0); |
|
782 } catch (SSLException e) { |
|
783 throw e; |
|
784 } catch (IOException e) { |
|
785 throw new SSLException("readRecord", e); |
|
786 } |
|
787 |
|
788 status = (isInboundDone() ? Status.CLOSED : Status.OK); |
|
789 hsStatus = getHSStatus(plainText.handshakeStatus); |
|
790 |
|
860 return new SSLEngineResult( |
791 return new SSLEngineResult( |
861 Status.OK, hsStatus, 0, 0); |
792 status, hsStatus, 0, 0, plainText.recordSN); |
862 } |
793 } |
863 |
794 |
864 /* |
795 /* |
865 * Check the packet to make sure enough is here. |
796 * Check the packet to make sure enough is here. |
866 * This will also indirectly check for 0 len packets. |
797 * This will also indirectly check for 0 len packets. |
867 */ |
798 */ |
868 int packetLen = inputRecord.bytesInCompletePacket(ea.netData); |
799 int packetLen = 0; |
800 try { |
|
801 packetLen = inputRecord.bytesInCompletePacket(netData); |
|
802 } catch (SSLException ssle) { |
|
803 // Need to discard invalid records for DTLS protocols. |
|
804 if (isDTLS) { |
|
805 if (debug != null && Debug.isOn("ssl")) { |
|
806 System.out.println( |
|
807 Thread.currentThread().getName() + |
|
808 " discard invalid record: " + ssle); |
|
809 } |
|
810 |
|
811 // invalid, discard the entire data [section 4.1.2.7, RFC 6347] |
|
812 int deltaNet = netData.remaining(); |
|
813 netData.position(netData.limit()); |
|
814 |
|
815 status = (isInboundDone() ? Status.CLOSED : Status.OK); |
|
816 hsStatus = getHSStatus(hsStatus); |
|
817 |
|
818 return new SSLEngineResult(status, hsStatus, deltaNet, 0, -1L); |
|
819 } else { |
|
820 throw ssle; |
|
821 } |
|
822 } |
|
869 |
823 |
870 // Is this packet bigger than SSL/TLS normally allows? |
824 // Is this packet bigger than SSL/TLS normally allows? |
871 if (packetLen > sess.getPacketBufferSize()) { |
825 if (packetLen > sess.getPacketBufferSize()) { |
872 if (packetLen > Record.maxLargeRecordSize) { |
826 int largestRecordSize = isDTLS ? |
873 throw new SSLProtocolException( |
827 DTLSRecord.maxRecordSize : SSLRecord.maxLargeRecordSize; |
874 "Input SSL/TLS record too big: max = " + |
828 if ((packetLen <= largestRecordSize) && !isDTLS) { |
875 Record.maxLargeRecordSize + |
|
876 " len = " + packetLen); |
|
877 } else { |
|
878 // Expand the expected maximum packet/application buffer |
829 // Expand the expected maximum packet/application buffer |
879 // sizes. |
830 // sizes. |
831 // |
|
832 // Only apply to SSL/TLS protocols. |
|
833 |
|
834 // Old behavior: shall we honor the System Property |
|
835 // "jsse.SSLEngine.acceptLargeFragments" if it is "false"? |
|
880 sess.expandBufferSizes(); |
836 sess.expandBufferSizes(); |
881 } |
837 } |
838 |
|
839 // check the packet again |
|
840 largestRecordSize = sess.getPacketBufferSize(); |
|
841 if (packetLen > largestRecordSize) { |
|
842 throw new SSLProtocolException( |
|
843 "Input record too big: max = " + |
|
844 largestRecordSize + " len = " + packetLen); |
|
845 } |
|
846 } |
|
847 |
|
848 int netPos = netData.position(); |
|
849 int appRemains = 0; |
|
850 for (int i = offset; i < offset + length; i++) { |
|
851 if (appData[i] == null) { |
|
852 throw new IllegalArgumentException( |
|
853 "appData[" + i + "] == null"); |
|
854 } |
|
855 appRemains += appData[i].remaining(); |
|
882 } |
856 } |
883 |
857 |
884 /* |
858 /* |
885 * Check for OVERFLOW. |
859 * Check for OVERFLOW. |
886 * |
860 * |
887 * To be considered: We could delay enforcing the application buffer |
861 * Delay enforcing the application buffer free space requirement |
888 * free space requirement until after the initial handshaking. |
862 * until after the initial handshaking. |
889 */ |
863 */ |
890 if ((packetLen - Record.headerSize) > ea.getAppRemaining()) { |
864 // synchronize connectionState? |
891 return new SSLEngineResult(Status.BUFFER_OVERFLOW, hsStatus, 0, 0); |
865 if ((connectionState == cs_DATA) || |
866 (connectionState == cs_RENEGOTIATE)) { |
|
867 |
|
868 int FragLen = inputRecord.estimateFragmentSize(packetLen); |
|
869 if (FragLen > appRemains) { |
|
870 return new SSLEngineResult( |
|
871 Status.BUFFER_OVERFLOW, hsStatus, 0, 0); |
|
872 } |
|
892 } |
873 } |
893 |
874 |
894 // check for UNDERFLOW. |
875 // check for UNDERFLOW. |
895 if ((packetLen == -1) || (ea.netData.remaining() < packetLen)) { |
876 if ((packetLen == -1) || (netData.remaining() < packetLen)) { |
896 return new SSLEngineResult( |
877 return new SSLEngineResult(Status.BUFFER_UNDERFLOW, hsStatus, 0, 0); |
897 Status.BUFFER_UNDERFLOW, hsStatus, 0, 0); |
|
898 } |
878 } |
899 |
879 |
900 /* |
880 /* |
901 * We're now ready to actually do the read. |
881 * We're now ready to actually do the read. |
902 * The only result code we really need to be exactly |
882 */ |
903 * right is the HS finished, for signaling to |
883 Plaintext plainText = null; |
904 * HandshakeCompletedListeners. |
|
905 */ |
|
906 try { |
884 try { |
907 hsStatus = readRecord(ea); |
885 plainText = readRecord(netData, appData, offset, length); |
908 } catch (SSLException e) { |
886 } catch (SSLException e) { |
909 throw e; |
887 throw e; |
910 } catch (IOException e) { |
888 } catch (IOException e) { |
911 throw new SSLException("readRecord", e); |
889 throw new SSLException("readRecord", e); |
912 } |
890 } |
920 * status, which is more representative of the current state. |
898 * status, which is more representative of the current state. |
921 * |
899 * |
922 * status above should cover: FINISHED, NEED_TASK |
900 * status above should cover: FINISHED, NEED_TASK |
923 */ |
901 */ |
924 status = (isInboundDone() ? Status.CLOSED : Status.OK); |
902 status = (isInboundDone() ? Status.CLOSED : Status.OK); |
925 hsStatus = getHSStatus(hsStatus); |
903 hsStatus = getHSStatus(plainText.handshakeStatus); |
926 |
904 |
927 return new SSLEngineResult(status, hsStatus, |
905 int deltaNet = netData.position() - netPos; |
928 ea.deltaNet(), ea.deltaApp()); |
906 int deltaApp = appRemains; |
907 for (int i = offset; i < offset + length; i++) { |
|
908 deltaApp -= appData[i].remaining(); |
|
909 } |
|
910 |
|
911 return new SSLEngineResult( |
|
912 status, hsStatus, deltaNet, deltaApp, plainText.recordSN); |
|
913 } |
|
914 |
|
915 // the caller have synchronized readLock |
|
916 void expectingFinishFlight() { |
|
917 inputRecord.expectingFinishFlight(); |
|
929 } |
918 } |
930 |
919 |
931 /* |
920 /* |
932 * Actually do the read record processing. |
921 * Actually do the read record processing. |
933 * |
922 * |
934 * Returns a Status if it can make specific determinations |
923 * Returns a Status if it can make specific determinations |
935 * of the engine state. In particular, we need to signal |
924 * of the engine state. In particular, we need to signal |
936 * that a handshake just completed. |
925 * that a handshake just completed. |
937 * |
926 * |
938 * It would be nice to be symmetrical with the write side and move |
927 * It would be nice to be symmetrical with the write side and move |
939 * the majority of this to EngineInputRecord, but there's too much |
928 * the majority of this to SSLInputRecord, but there's too much |
940 * SSLEngine state to do that cleanly. It must still live here. |
929 * SSLEngine state to do that cleanly. It must still live here. |
941 */ |
930 */ |
942 private HandshakeStatus readRecord(EngineArgs ea) throws IOException { |
931 private Plaintext readRecord(ByteBuffer netData, |
943 |
932 ByteBuffer[] appData, int offset, int length) throws IOException { |
944 HandshakeStatus hsStatus = null; |
|
945 |
933 |
946 /* |
934 /* |
947 * The various operations will return new sliced BB's, |
935 * The various operations will return new sliced BB's, |
948 * this will avoid having to worry about positions and |
936 * this will avoid having to worry about positions and |
949 * limits in the netBB. |
937 * limits in the netBB. |
950 */ |
938 */ |
951 ByteBuffer readBB = null; |
939 Plaintext plainText = null; |
952 ByteBuffer decryptedBB = null; |
940 |
953 |
941 if (getConnectionState() == cs_ERROR) { |
954 if (getConnectionState() != cs_ERROR) { |
942 return Plaintext.PLAINTEXT_NULL; |
955 |
943 } |
956 /* |
944 |
957 * Read a record ... maybe emitting an alert if we get a |
945 /* |
958 * comprehensible but unsupported "hello" message during |
946 * Read a record ... maybe emitting an alert if we get a |
959 * format checking (e.g. V2). |
947 * comprehensible but unsupported "hello" message during |
960 */ |
948 * format checking (e.g. V2). |
961 try { |
949 */ |
962 readBB = inputRecord.read(ea.netData); |
950 try { |
963 } catch (IOException e) { |
951 if (isDTLS) { |
964 fatal(Alerts.alert_unexpected_message, e); |
952 // Don't process the incoming record until all of the |
965 } |
953 // buffered records get handled. |
966 |
954 plainText = inputRecord.acquirePlaintext(); |
955 } |
|
956 |
|
957 if ((!isDTLS || plainText == null) && netData != null) { |
|
958 plainText = inputRecord.decode(netData); |
|
959 } |
|
960 } catch (UnsupportedOperationException unsoe) { // SSLv2Hello |
|
961 // Hack code to deliver SSLv2 error message for SSL/TLS connections. |
|
962 if (!isDTLS) { |
|
963 outputRecord.encodeV2NoCipher(); |
|
964 } |
|
965 |
|
966 fatal(Alerts.alert_unexpected_message, unsoe); |
|
967 } catch (BadPaddingException e) { |
|
967 /* |
968 /* |
968 * The basic SSLv3 record protection involves (optional) |
969 * The basic SSLv3 record protection involves (optional) |
969 * encryption for privacy, and an integrity check ensuring |
970 * encryption for privacy, and an integrity check ensuring |
970 * data origin authentication. We do them both here, and |
971 * data origin authentication. We do them both here, and |
971 * throw a fatal alert if the integrity check fails. |
972 * throw a fatal alert if the integrity check fails. |
972 */ |
973 */ |
973 try { |
974 byte alertType = (connectionState != cs_DATA) ? |
974 decryptedBB = inputRecord.decrypt( |
975 Alerts.alert_handshake_failure : |
975 readAuthenticator, readCipher, readBB); |
976 Alerts.alert_bad_record_mac; |
976 } catch (BadPaddingException e) { |
977 fatal(alertType, e.getMessage(), e); |
977 byte alertType = (inputRecord.contentType() == |
978 } catch (SSLHandshakeException she) { |
978 Record.ct_handshake) ? |
979 // may be record sequence number overflow |
979 Alerts.alert_handshake_failure : |
980 fatal(Alerts.alert_handshake_failure, she); |
980 Alerts.alert_bad_record_mac; |
981 } catch (IOException ioe) { |
981 fatal(alertType, e.getMessage(), e); |
982 fatal(Alerts.alert_unexpected_message, ioe); |
982 } |
983 } |
983 |
984 |
984 // if (!inputRecord.decompress(c)) |
985 // plainText should never be null for TLS protocols |
985 // fatal(Alerts.alert_decompression_failure, |
986 HandshakeStatus hsStatus = null; |
986 // "decompression failure"); |
987 if (!isDTLS || plainText != null) { |
987 |
988 hsStatus = processInputRecord(plainText, appData, offset, length); |
988 |
989 } |
989 /* |
990 |
990 * Process the record. |
991 if (hsStatus == null) { |
991 */ |
992 hsStatus = getHSStatus(null); |
992 |
993 } |
993 synchronized (this) { |
994 |
994 switch (inputRecord.contentType()) { |
995 if (plainText == null) { |
995 case Record.ct_handshake: |
996 plainText = new Plaintext(); |
996 /* |
997 } |
997 * Handshake messages always go to a pending session |
998 plainText.handshakeStatus = hsStatus; |
998 * handshaker ... if there isn't one, create one. This |
999 |
999 * must work asynchronously, for renegotiation. |
1000 return plainText; |
1000 * |
1001 } |
1001 * NOTE that handshaking will either resume a session |
1002 |
1002 * which was in the cache (and which might have other |
1003 /* |
1003 * connections in it already), or else will start a new |
1004 * Process the record. |
1004 * session (new keys exchanged) with just this connection |
1005 */ |
1005 * in it. |
1006 private synchronized HandshakeStatus processInputRecord( |
1006 */ |
1007 Plaintext plainText, |
1007 initHandshaker(); |
1008 ByteBuffer[] appData, int offset, int length) throws IOException { |
1008 if (!handshaker.activated()) { |
1009 |
1009 // prior to handshaking, activate the handshake |
1010 HandshakeStatus hsStatus = null; |
1010 if (connectionState == cs_RENEGOTIATE) { |
1011 switch (plainText.contentType) { |
1011 // don't use SSLv2Hello when renegotiating |
1012 case Record.ct_handshake: |
1012 handshaker.activate(protocolVersion); |
1013 /* |
1013 } else { |
1014 * Handshake messages always go to a pending session |
1014 handshaker.activate(null); |
1015 * handshaker ... if there isn't one, create one. This |
1015 } |
1016 * must work asynchronously, for renegotiation. |
1017 * |
|
1018 * NOTE that handshaking will either resume a session |
|
1019 * which was in the cache (and which might have other |
|
1020 * connections in it already), or else will start a new |
|
1021 * session (new keys exchanged) with just this connection |
|
1022 * in it. |
|
1023 */ |
|
1024 initHandshaker(); |
|
1025 if (!handshaker.activated()) { |
|
1026 // prior to handshaking, activate the handshake |
|
1027 if (connectionState == cs_RENEGOTIATE) { |
|
1028 // don't use SSLv2Hello when renegotiating |
|
1029 handshaker.activate(protocolVersion); |
|
1030 } else { |
|
1031 handshaker.activate(null); |
|
1016 } |
1032 } |
1017 |
1033 } |
1018 /* |
1034 |
1019 * process the handshake record ... may contain just |
1035 /* |
1020 * a partial handshake message or multiple messages. |
1036 * process the handshake record ... may contain just |
1021 * |
1037 * a partial handshake message or multiple messages. |
1022 * The handshaker state machine will ensure that it's |
1038 * |
1023 * a finished message. |
1039 * The handshaker state machine will ensure that it's |
1024 */ |
1040 * a finished message. |
1025 handshaker.process_record(inputRecord, expectingFinished); |
1041 */ |
1026 expectingFinished = false; |
1042 handshaker.processRecord(plainText.fragment, expectingFinished); |
1027 |
1043 expectingFinished = false; |
1028 if (handshaker.invalidated) { |
1044 |
1029 handshaker = null; |
1045 if (handshaker.invalidated) { |
1030 receivedCCS = false; |
1046 finishHandshake(); |
1031 // if state is cs_RENEGOTIATE, revert it to cs_DATA |
1047 |
1032 if (connectionState == cs_RENEGOTIATE) { |
1048 // if state is cs_RENEGOTIATE, revert it to cs_DATA |
1033 connectionState = cs_DATA; |
1049 if (connectionState == cs_RENEGOTIATE) { |
1034 } |
|
1035 } else if (handshaker.isDone()) { |
|
1036 // reset the parameters for secure renegotiation. |
|
1037 secureRenegotiation = |
|
1038 handshaker.isSecureRenegotiation(); |
|
1039 clientVerifyData = handshaker.getClientVerifyData(); |
|
1040 serverVerifyData = handshaker.getServerVerifyData(); |
|
1041 |
|
1042 sess = handshaker.getSession(); |
|
1043 handshakeSession = null; |
|
1044 if (!writer.hasOutboundData()) { |
|
1045 hsStatus = HandshakeStatus.FINISHED; |
|
1046 } |
|
1047 handshaker = null; |
|
1048 connectionState = cs_DATA; |
1050 connectionState = cs_DATA; |
1049 receivedCCS = false; |
|
1050 |
|
1051 // No handshakeListeners here. That's a |
|
1052 // SSLSocket thing. |
|
1053 } else if (handshaker.taskOutstanding()) { |
|
1054 hsStatus = HandshakeStatus.NEED_TASK; |
|
1055 } |
1051 } |
1056 break; |
1052 } else if (handshaker.isDone()) { |
1057 |
1053 // reset the parameters for secure renegotiation. |
1058 case Record.ct_application_data: |
1054 secureRenegotiation = |
1059 // Pass this right back up to the application. |
1055 handshaker.isSecureRenegotiation(); |
1060 if ((connectionState != cs_DATA) |
1056 clientVerifyData = handshaker.getClientVerifyData(); |
1061 && (connectionState != cs_RENEGOTIATE) |
1057 serverVerifyData = handshaker.getServerVerifyData(); |
1062 && (connectionState != cs_CLOSED)) { |
1058 |
1063 throw new SSLProtocolException( |
1059 sess = handshaker.getSession(); |
1060 handshakeSession = null; |
|
1061 if (outputRecord.isEmpty()) { |
|
1062 hsStatus = finishHandshake(); |
|
1063 connectionState = cs_DATA; |
|
1064 } |
|
1065 |
|
1066 // No handshakeListeners here. That's a |
|
1067 // SSLSocket thing. |
|
1068 } else if (handshaker.taskOutstanding()) { |
|
1069 hsStatus = HandshakeStatus.NEED_TASK; |
|
1070 } |
|
1071 break; |
|
1072 |
|
1073 case Record.ct_application_data: |
|
1074 // Pass this right back up to the application. |
|
1075 if ((connectionState != cs_DATA) |
|
1076 && (connectionState != cs_RENEGOTIATE) |
|
1077 && (connectionState != cs_CLOSED)) { |
|
1078 throw new SSLProtocolException( |
|
1064 "Data received in non-data state: " + |
1079 "Data received in non-data state: " + |
1065 connectionState); |
1080 connectionState); |
1066 } |
1081 } |
1067 |
1082 |
1068 if (expectingFinished) { |
1083 if (expectingFinished) { |
1069 throw new SSLProtocolException |
1084 throw new SSLProtocolException |
1070 ("Expecting finished message, received data"); |
1085 ("Expecting finished message, received data"); |
1071 } |
1086 } |
1072 |
1087 |
1073 /* |
1088 if (!inboundDone) { |
1074 * Don't return data once the inbound side is |
1089 ByteBuffer fragment = plainText.fragment; |
1075 * closed. |
1090 int remains = fragment.remaining(); |
1076 */ |
1091 |
1077 if (!inboundDone) { |
1092 // Should have enough room in appData. |
1078 ea.scatter(decryptedBB.slice()); |
1093 for (int i = offset; |
1079 } |
1094 ((i < (offset + length)) && (remains > 0)); i++) { |
1080 break; |
1095 int amount = Math.min(appData[i].remaining(), remains); |
1081 |
1096 fragment.limit(fragment.position() + amount); |
1082 case Record.ct_alert: |
1097 appData[i].put(fragment); |
1083 recvAlert(); |
1098 remains -= amount; |
1084 break; |
|
1085 |
|
1086 case Record.ct_change_cipher_spec: |
|
1087 if ((connectionState != cs_HANDSHAKE |
|
1088 && connectionState != cs_RENEGOTIATE) |
|
1089 || !handshaker.sessionKeysCalculated() |
|
1090 || receivedCCS) { |
|
1091 // For the CCS message arriving in the wrong state |
|
1092 fatal(Alerts.alert_unexpected_message, |
|
1093 "illegal change cipher spec msg, conn state = " |
|
1094 + connectionState + ", handshake state = " |
|
1095 + handshaker.state); |
|
1096 } else if (inputRecord.available() != 1 |
|
1097 || inputRecord.read() != 1) { |
|
1098 // For structural/content issues with the CCS |
|
1099 fatal(Alerts.alert_unexpected_message, |
|
1100 "Malformed change cipher spec msg"); |
|
1101 } |
|
1102 |
|
1103 // Once we've received CCS, update the flag. |
|
1104 // If the remote endpoint sends it again in this handshake |
|
1105 // we won't process it. |
|
1106 receivedCCS = true; |
|
1107 |
|
1108 // |
|
1109 // The first message after a change_cipher_spec |
|
1110 // record MUST be a "Finished" handshake record, |
|
1111 // else it's a protocol violation. We force this |
|
1112 // to be checked by a minor tweak to the state |
|
1113 // machine. |
|
1114 // |
|
1115 changeReadCiphers(); |
|
1116 // next message MUST be a finished message |
|
1117 expectingFinished = true; |
|
1118 break; |
|
1119 |
|
1120 default: |
|
1121 // |
|
1122 // TLS requires that unrecognized records be ignored. |
|
1123 // |
|
1124 if (debug != null && Debug.isOn("ssl")) { |
|
1125 System.out.println(Thread.currentThread().getName() + |
|
1126 ", Received record type: " |
|
1127 + inputRecord.contentType()); |
|
1128 } |
|
1129 break; |
|
1130 } // switch |
|
1131 |
|
1132 /* |
|
1133 * We only need to check the sequence number state for |
|
1134 * non-handshaking record. |
|
1135 * |
|
1136 * Note that in order to maintain the handshake status |
|
1137 * properly, we check the sequence number after the last |
|
1138 * record reading process. As we request renegotiation |
|
1139 * or close the connection for wrapped sequence number |
|
1140 * when there is enough sequence number space left to |
|
1141 * handle a few more records, so the sequence number |
|
1142 * of the last record cannot be wrapped. |
|
1143 */ |
|
1144 hsStatus = getHSStatus(hsStatus); |
|
1145 if (connectionState < cs_ERROR && !isInboundDone() && |
|
1146 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { |
|
1147 if (checkSequenceNumber(readAuthenticator, |
|
1148 inputRecord.contentType())) { |
|
1149 hsStatus = getHSStatus(null); |
|
1150 } |
1099 } |
1151 } |
1100 } |
1152 } // synchronized (this) |
1101 |
1102 break; |
|
1103 |
|
1104 case Record.ct_alert: |
|
1105 recvAlert(plainText.fragment); |
|
1106 break; |
|
1107 |
|
1108 case Record.ct_change_cipher_spec: |
|
1109 if ((connectionState != cs_HANDSHAKE |
|
1110 && connectionState != cs_RENEGOTIATE)) { |
|
1111 // For the CCS message arriving in the wrong state |
|
1112 fatal(Alerts.alert_unexpected_message, |
|
1113 "illegal change cipher spec msg, conn state = " |
|
1114 + connectionState); |
|
1115 } else if (plainText.fragment.remaining() != 1 |
|
1116 || plainText.fragment.get() != 1) { |
|
1117 // For structural/content issues with the CCS |
|
1118 fatal(Alerts.alert_unexpected_message, |
|
1119 "Malformed change cipher spec msg"); |
|
1120 } |
|
1121 |
|
1122 // |
|
1123 // The first message after a change_cipher_spec |
|
1124 // record MUST be a "Finished" handshake record, |
|
1125 // else it's a protocol violation. We force this |
|
1126 // to be checked by a minor tweak to the state |
|
1127 // machine. |
|
1128 // |
|
1129 handshaker.receiveChangeCipherSpec(); |
|
1130 |
|
1131 CipherBox readCipher; |
|
1132 Authenticator readAuthenticator; |
|
1133 try { |
|
1134 readCipher = handshaker.newReadCipher(); |
|
1135 readAuthenticator = handshaker.newReadAuthenticator(); |
|
1136 } catch (GeneralSecurityException e) { |
|
1137 // can't happen |
|
1138 throw new SSLException("Algorithm missing: ", e); |
|
1139 } |
|
1140 inputRecord.changeReadCiphers(readAuthenticator, readCipher); |
|
1141 |
|
1142 // next message MUST be a finished message |
|
1143 expectingFinished = true; |
|
1144 break; |
|
1145 |
|
1146 default: |
|
1147 // |
|
1148 // TLS requires that unrecognized records be ignored. |
|
1149 // |
|
1150 if (debug != null && Debug.isOn("ssl")) { |
|
1151 System.out.println(Thread.currentThread().getName() + |
|
1152 ", Received record type: " + plainText.contentType); |
|
1153 } |
|
1154 break; |
|
1155 } // switch |
|
1156 |
|
1157 /* |
|
1158 * We only need to check the sequence number state for |
|
1159 * non-handshaking record. |
|
1160 * |
|
1161 * Note that in order to maintain the handshake status |
|
1162 * properly, we check the sequence number after the last |
|
1163 * record reading process. As we request renegotiation |
|
1164 * or close the connection for wrapped sequence number |
|
1165 * when there is enough sequence number space left to |
|
1166 * handle a few more records, so the sequence number |
|
1167 * of the last record cannot be wrapped. |
|
1168 */ |
|
1169 hsStatus = getHSStatus(hsStatus); |
|
1170 if (connectionState < cs_ERROR && !isInboundDone() && |
|
1171 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) && |
|
1172 (inputRecord.seqNumIsHuge())) { |
|
1173 /* |
|
1174 * Ask for renegotiation when need to renew sequence number. |
|
1175 * |
|
1176 * Don't bother to kickstart the renegotiation when the local is |
|
1177 * asking for it. |
|
1178 */ |
|
1179 if (debug != null && Debug.isOn("ssl")) { |
|
1180 System.out.println(Thread.currentThread().getName() + |
|
1181 ", request renegotiation " + |
|
1182 "to avoid sequence number overflow"); |
|
1183 } |
|
1184 |
|
1185 beginHandshake(); |
|
1186 |
|
1187 hsStatus = getHSStatus(null); |
|
1153 } |
1188 } |
1154 |
1189 |
1155 return hsStatus; |
1190 return hsStatus; |
1156 } |
1191 } |
1157 |
1192 |
1164 /** |
1199 /** |
1165 * Wraps a buffer. Does a variety of checks before grabbing |
1200 * Wraps a buffer. Does a variety of checks before grabbing |
1166 * the wrapLock, which blocks multiple wraps from occurring. |
1201 * the wrapLock, which blocks multiple wraps from occurring. |
1167 */ |
1202 */ |
1168 @Override |
1203 @Override |
1169 public SSLEngineResult wrap(ByteBuffer [] appData, |
1204 public SSLEngineResult wrap(ByteBuffer[] appData, |
1170 int offset, int length, ByteBuffer netData) throws SSLException { |
1205 int offset, int length, ByteBuffer netData) throws SSLException { |
1171 |
1206 |
1172 EngineArgs ea = new EngineArgs(appData, offset, length, netData); |
1207 // check engine parameters |
1208 checkEngineParas(netData, appData, offset, length, true); |
|
1173 |
1209 |
1174 /* |
1210 /* |
1175 * We can be smarter about using smaller buffer sizes later. |
1211 * We can be smarter about using smaller buffer sizes later. |
1176 * For now, force it to be large enough to handle any |
1212 * For now, force it to be large enough to handle any valid record. |
1177 * valid SSL/TLS record. |
1213 */ |
1178 */ |
1214 if (netData.remaining() < sess.getPacketBufferSize()) { |
1179 if (netData.remaining() < EngineOutputRecord.maxRecordSize) { |
|
1180 return new SSLEngineResult( |
1215 return new SSLEngineResult( |
1181 Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0); |
1216 Status.BUFFER_OVERFLOW, getHSStatus(null), 0, 0); |
1182 } |
1217 } |
1183 |
1218 |
1184 try { |
1219 try { |
1185 synchronized (wrapLock) { |
1220 synchronized (wrapLock) { |
1186 return writeAppRecord(ea); |
1221 return writeAppRecord(appData, offset, length, netData); |
1187 } |
1222 } |
1223 } catch (SSLProtocolException spe) { |
|
1224 // may be an unexpected handshake message |
|
1225 fatal(Alerts.alert_unexpected_message, spe.getMessage(), spe); |
|
1226 return null; // make compiler happy |
|
1188 } catch (Exception e) { |
1227 } catch (Exception e) { |
1189 ea.resetPos(); |
|
1190 |
|
1191 fatal(Alerts.alert_internal_error, |
1228 fatal(Alerts.alert_internal_error, |
1192 "problem wrapping app data", e); |
1229 "problem wrapping app data", e); |
1193 return null; // make compiler happy |
1230 return null; // make compiler happy |
1194 } finally { |
|
1195 /* |
|
1196 * Just in case something didn't reset limits properly. |
|
1197 */ |
|
1198 ea.resetLim(); |
|
1199 } |
1231 } |
1200 } |
1232 } |
1201 |
1233 |
1202 /* |
1234 /* |
1203 * Makes additional checks for unwrap, but this time more |
1235 * Makes additional checks for unwrap, but this time more |
1204 * specific to this packet and the current state of the machine. |
1236 * specific to this packet and the current state of the machine. |
1205 */ |
1237 */ |
1206 private SSLEngineResult writeAppRecord(EngineArgs ea) throws IOException { |
1238 private SSLEngineResult writeAppRecord(ByteBuffer[] appData, |
1239 int offset, int length, ByteBuffer netData) throws IOException { |
|
1207 |
1240 |
1208 Status status = null; |
1241 Status status = null; |
1209 HandshakeStatus hsStatus = null; |
1242 HandshakeStatus hsStatus = null; |
1210 |
1243 |
1211 /* |
1244 /* |
1214 checkTaskThrown(); |
1247 checkTaskThrown(); |
1215 |
1248 |
1216 /* |
1249 /* |
1217 * short circuit if we're closed/closing. |
1250 * short circuit if we're closed/closing. |
1218 */ |
1251 */ |
1219 if (writer.isOutboundDone()) { |
1252 if (isOutboundDone()) { |
1220 return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0); |
1253 return new SSLEngineResult(Status.CLOSED, getHSStatus(null), 0, 0); |
1221 } |
1254 } |
1222 |
1255 |
1223 /* |
1256 /* |
1224 * If we're still in cs_HANDSHAKE, make sure it's been |
1257 * If we're still in cs_HANDSHAKE, make sure it's been |
1225 * started. |
1258 * started. |
1226 */ |
1259 */ |
1227 synchronized (this) { |
1260 synchronized (this) { |
1228 if ((connectionState == cs_HANDSHAKE) || |
1261 if ((connectionState == cs_HANDSHAKE) || |
1229 (connectionState == cs_START)) { |
1262 (connectionState == cs_START)) { |
1263 |
|
1230 kickstartHandshake(); |
1264 kickstartHandshake(); |
1231 |
1265 |
1232 /* |
1266 /* |
1233 * If there's no HS data available to write, we can return |
1267 * If there's no HS data available to write, we can return |
1234 * without trying to wrap anything. |
1268 * without trying to wrap anything. |
1235 */ |
1269 */ |
1236 hsStatus = getHSStatus(null); |
1270 hsStatus = getHSStatus(null); |
1237 |
|
1238 if (hsStatus == HandshakeStatus.NEED_UNWRAP) { |
1271 if (hsStatus == HandshakeStatus.NEED_UNWRAP) { |
1239 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); |
1272 /* |
1273 * For DTLS, if the handshake state is |
|
1274 * HandshakeStatus.NEED_UNWRAP, a call to SSLEngine.wrap() |
|
1275 * means that the previous handshake packets (if delivered) |
|
1276 * get lost, and need retransmit the handshake messages. |
|
1277 */ |
|
1278 if (!isDTLS || !enableRetransmissions || |
|
1279 (handshaker == null) || outputRecord.firstMessage) { |
|
1280 |
|
1281 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); |
|
1282 } // otherwise, need retransmission |
|
1240 } |
1283 } |
1241 } |
1284 } |
1242 } |
1285 } |
1243 |
1286 |
1244 /* |
1287 /* |
1256 * doing any more wrapping, because we could be in the middle |
1299 * doing any more wrapping, because we could be in the middle |
1257 * of receiving a handshake message, for example, a finished |
1300 * of receiving a handshake message, for example, a finished |
1258 * message which would change the ciphers. |
1301 * message which would change the ciphers. |
1259 */ |
1302 */ |
1260 if (hsStatus == HandshakeStatus.NEED_TASK) { |
1303 if (hsStatus == HandshakeStatus.NEED_TASK) { |
1261 return new SSLEngineResult( |
1304 return new SSLEngineResult(Status.OK, hsStatus, 0, 0); |
1262 Status.OK, hsStatus, 0, 0); |
|
1263 } |
1305 } |
1264 |
1306 |
1265 /* |
1307 /* |
1266 * This will obtain any waiting outbound data, or will |
1308 * This will obtain any waiting outbound data, or will |
1267 * process the outbound appData. |
1309 * process the outbound appData. |
1268 */ |
1310 */ |
1311 int netPos = netData.position(); |
|
1312 int appRemains = 0; |
|
1313 for (int i = offset; i < offset + length; i++) { |
|
1314 if (appData[i] == null) { |
|
1315 throw new IllegalArgumentException( |
|
1316 "appData[" + i + "] == null"); |
|
1317 } |
|
1318 appRemains += appData[i].remaining(); |
|
1319 } |
|
1320 |
|
1321 Ciphertext ciphertext = null; |
|
1269 try { |
1322 try { |
1270 synchronized (writeLock) { |
1323 if (appRemains != 0) { |
1271 hsStatus = writeRecord(outputRecord, ea); |
1324 synchronized (writeLock) { |
1325 ciphertext = writeRecord(appData, offset, length, netData); |
|
1326 } |
|
1327 } else { |
|
1328 synchronized (writeLock) { |
|
1329 ciphertext = writeRecord(null, 0, 0, netData); |
|
1330 } |
|
1272 } |
1331 } |
1273 } catch (SSLException e) { |
1332 } catch (SSLException e) { |
1274 throw e; |
1333 throw e; |
1275 } catch (IOException e) { |
1334 } catch (IOException e) { |
1276 throw new SSLException("Write problems", e); |
1335 throw new SSLException("Write problems", e); |
1281 * Now check for the remaining cases. |
1340 * Now check for the remaining cases. |
1282 * |
1341 * |
1283 * status above should cover: NEED_WRAP/FINISHED |
1342 * status above should cover: NEED_WRAP/FINISHED |
1284 */ |
1343 */ |
1285 status = (isOutboundDone() ? Status.CLOSED : Status.OK); |
1344 status = (isOutboundDone() ? Status.CLOSED : Status.OK); |
1286 hsStatus = getHSStatus(hsStatus); |
1345 hsStatus = getHSStatus(ciphertext.handshakeStatus); |
1287 |
1346 |
1288 return new SSLEngineResult(status, hsStatus, |
1347 int deltaNet = netData.position() - netPos; |
1289 ea.deltaApp(), ea.deltaNet()); |
1348 int deltaApp = appRemains; |
1349 for (int i = offset; i < offset + length; i++) { |
|
1350 deltaApp -= appData[i].remaining(); |
|
1351 } |
|
1352 |
|
1353 return new SSLEngineResult( |
|
1354 status, hsStatus, deltaApp, deltaNet, ciphertext.recordSN); |
|
1290 } |
1355 } |
1291 |
1356 |
1292 /* |
1357 /* |
1293 * Central point to write/get all of the outgoing data. |
1358 * Central point to write/get all of the outgoing data. |
1294 */ |
1359 */ |
1295 private HandshakeStatus writeRecord(EngineOutputRecord eor, |
1360 private Ciphertext writeRecord(ByteBuffer[] appData, |
1296 EngineArgs ea) throws IOException { |
1361 int offset, int length, ByteBuffer netData) throws IOException { |
1297 |
1362 |
1298 // eventually compress as well. |
1363 Ciphertext ciphertext = null; |
1299 HandshakeStatus hsStatus = |
1364 try { |
1300 writer.writeRecord(eor, ea, writeAuthenticator, writeCipher); |
1365 // Acquire the buffered to-be-delivered records or retransmissions. |
1366 // |
|
1367 // May have buffered records, or need retransmission if handshaking. |
|
1368 if (!outputRecord.isEmpty() || (handshaker != null)) { |
|
1369 ciphertext = outputRecord.acquireCiphertext(netData); |
|
1370 } |
|
1371 |
|
1372 if ((ciphertext == null) && (appData != null)) { |
|
1373 ciphertext = outputRecord.encode( |
|
1374 appData, offset, length, netData); |
|
1375 } |
|
1376 } catch (SSLHandshakeException she) { |
|
1377 // may be record sequence number overflow |
|
1378 fatal(Alerts.alert_handshake_failure, she); |
|
1379 |
|
1380 return Ciphertext.CIPHERTEXT_NULL; // make the complier happy |
|
1381 } catch (IOException e) { |
|
1382 fatal(Alerts.alert_unexpected_message, e); |
|
1383 |
|
1384 return Ciphertext.CIPHERTEXT_NULL; // make the complier happy |
|
1385 } |
|
1386 |
|
1387 if (ciphertext == null) { |
|
1388 return Ciphertext.CIPHERTEXT_NULL; |
|
1389 } |
|
1390 |
|
1391 HandshakeStatus hsStatus = null; |
|
1392 Ciphertext.RecordType recordType = ciphertext.recordType; |
|
1393 if ((handshaker != null) && |
|
1394 (recordType.contentType == Record.ct_handshake) && |
|
1395 (recordType.handshakeType == HandshakeMessage.ht_finished) && |
|
1396 handshaker.isDone() && outputRecord.isEmpty()) { |
|
1397 |
|
1398 hsStatus = finishHandshake(); |
|
1399 connectionState = cs_DATA; |
|
1400 } // Otherwise, the followed call to getHSStatus() will help. |
|
1301 |
1401 |
1302 /* |
1402 /* |
1303 * We only need to check the sequence number state for |
1403 * We only need to check the sequence number state for |
1304 * non-handshaking record. |
1404 * non-handshaking record. |
1305 * |
1405 * |
1311 * handle a few more records, so the sequence number |
1411 * handle a few more records, so the sequence number |
1312 * of the last record cannot be wrapped. |
1412 * of the last record cannot be wrapped. |
1313 */ |
1413 */ |
1314 hsStatus = getHSStatus(hsStatus); |
1414 hsStatus = getHSStatus(hsStatus); |
1315 if (connectionState < cs_ERROR && !isOutboundDone() && |
1415 if (connectionState < cs_ERROR && !isOutboundDone() && |
1316 (hsStatus == HandshakeStatus.NOT_HANDSHAKING)) { |
1416 (hsStatus == HandshakeStatus.NOT_HANDSHAKING) && |
1317 if (checkSequenceNumber(writeAuthenticator, eor.contentType())) { |
1417 (outputRecord.seqNumIsHuge())) { |
1318 hsStatus = getHSStatus(null); |
|
1319 } |
|
1320 } |
|
1321 |
|
1322 /* |
|
1323 * turn off the flag of the first application record if we really |
|
1324 * consumed at least byte. |
|
1325 */ |
|
1326 if (isFirstAppOutputRecord && ea.deltaApp() > 0) { |
|
1327 isFirstAppOutputRecord = false; |
|
1328 } |
|
1329 |
|
1330 return hsStatus; |
|
1331 } |
|
1332 |
|
1333 /* |
|
1334 * Need to split the payload except the following cases: |
|
1335 * |
|
1336 * 1. protocol version is TLS 1.1 or later; |
|
1337 * 2. bulk cipher does not use CBC mode, including null bulk cipher suites. |
|
1338 * 3. the payload is the first application record of a freshly |
|
1339 * negotiated TLS session. |
|
1340 * 4. the CBC protection is disabled; |
|
1341 * |
|
1342 * More details, please refer to |
|
1343 * EngineOutputRecord.write(EngineArgs, MAC, CipherBox). |
|
1344 */ |
|
1345 boolean needToSplitPayload(CipherBox cipher, ProtocolVersion protocol) { |
|
1346 return (protocol.v <= ProtocolVersion.TLS10.v) && |
|
1347 cipher.isCBCMode() && !isFirstAppOutputRecord && |
|
1348 Record.enableCBCProtection; |
|
1349 } |
|
1350 |
|
1351 /* |
|
1352 * Non-application OutputRecords go through here. |
|
1353 */ |
|
1354 void writeRecord(EngineOutputRecord eor) throws IOException { |
|
1355 // eventually compress as well. |
|
1356 writer.writeRecord(eor, writeAuthenticator, writeCipher); |
|
1357 |
|
1358 /* |
|
1359 * Check the sequence number state |
|
1360 * |
|
1361 * Note that in order to maintain the connection I/O |
|
1362 * properly, we check the sequence number after the last |
|
1363 * record writing process. As we request renegotiation |
|
1364 * or close the connection for wrapped sequence number |
|
1365 * when there is enough sequence number space left to |
|
1366 * handle a few more records, so the sequence number |
|
1367 * of the last record cannot be wrapped. |
|
1368 */ |
|
1369 if ((connectionState < cs_ERROR) && !isOutboundDone()) { |
|
1370 checkSequenceNumber(writeAuthenticator, eor.contentType()); |
|
1371 } |
|
1372 } |
|
1373 |
|
1374 // |
|
1375 // Close code |
|
1376 // |
|
1377 |
|
1378 /** |
|
1379 * Check the sequence number state |
|
1380 * |
|
1381 * RFC 4346 states that, "Sequence numbers are of type uint64 and |
|
1382 * may not exceed 2^64-1. Sequence numbers do not wrap. If a TLS |
|
1383 * implementation would need to wrap a sequence number, it must |
|
1384 * renegotiate instead." |
|
1385 * |
|
1386 * Return true if the handshake status may be changed. |
|
1387 */ |
|
1388 private boolean checkSequenceNumber(Authenticator authenticator, byte type) |
|
1389 throws IOException { |
|
1390 |
|
1391 /* |
|
1392 * Don't bother to check the sequence number for error or |
|
1393 * closed connections, or NULL MAC |
|
1394 */ |
|
1395 if (connectionState >= cs_ERROR || authenticator == MAC.NULL) { |
|
1396 return false; |
|
1397 } |
|
1398 |
|
1399 /* |
|
1400 * Conservatively, close the connection immediately when the |
|
1401 * sequence number is close to overflow |
|
1402 */ |
|
1403 if (authenticator.seqNumOverflow()) { |
|
1404 /* |
1418 /* |
1405 * TLS protocols do not define a error alert for sequence |
1419 * Ask for renegotiation when need to renew sequence number. |
1406 * number overflow. We use handshake_failure error alert |
1420 * |
1407 * for handshaking and bad_record_mac for other records. |
1421 * Don't bother to kickstart the renegotiation when the local is |
1422 * asking for it. |
|
1408 */ |
1423 */ |
1409 if (debug != null && Debug.isOn("ssl")) { |
|
1410 System.out.println(Thread.currentThread().getName() + |
|
1411 ", sequence number extremely close to overflow " + |
|
1412 "(2^64-1 packets). Closing connection."); |
|
1413 } |
|
1414 |
|
1415 fatal(Alerts.alert_handshake_failure, "sequence number overflow"); |
|
1416 |
|
1417 return true; // make the compiler happy |
|
1418 } |
|
1419 |
|
1420 /* |
|
1421 * Ask for renegotiation when need to renew sequence number. |
|
1422 * |
|
1423 * Don't bother to kickstart the renegotiation when the local is |
|
1424 * asking for it. |
|
1425 */ |
|
1426 if ((type != Record.ct_handshake) && authenticator.seqNumIsHuge()) { |
|
1427 if (debug != null && Debug.isOn("ssl")) { |
1424 if (debug != null && Debug.isOn("ssl")) { |
1428 System.out.println(Thread.currentThread().getName() + |
1425 System.out.println(Thread.currentThread().getName() + |
1429 ", request renegotiation " + |
1426 ", request renegotiation " + |
1430 "to avoid sequence number overflow"); |
1427 "to avoid sequence number overflow"); |
1431 } |
1428 } |
1432 |
1429 |
1433 beginHandshake(); |
1430 beginHandshake(); |
1434 return true; |
1431 |
1435 } |
1432 hsStatus = getHSStatus(null); |
1436 |
1433 } |
1437 return false; |
1434 ciphertext.handshakeStatus = hsStatus; |
1438 } |
1435 |
1436 return ciphertext; |
|
1437 } |
|
1438 |
|
1439 private HandshakeStatus finishHandshake() { |
|
1440 handshaker = null; |
|
1441 inputRecord.setHandshakeHash(null); |
|
1442 outputRecord.setHandshakeHash(null); |
|
1443 connectionState = cs_DATA; |
|
1444 |
|
1445 return HandshakeStatus.FINISHED; |
|
1446 } |
|
1447 |
|
1448 // |
|
1449 // Close code |
|
1450 // |
|
1439 |
1451 |
1440 /** |
1452 /** |
1441 * Signals that no more outbound application data will be sent |
1453 * Signals that no more outbound application data will be sent |
1442 * on this <code>SSLEngine</code>. |
1454 * on this <code>SSLEngine</code>. |
1443 */ |
1455 */ |
1449 } |
1461 } |
1450 |
1462 |
1451 /* |
1463 /* |
1452 * Already closed, ignore |
1464 * Already closed, ignore |
1453 */ |
1465 */ |
1454 if (writer.isOutboundDone()) { |
1466 if (outboundDone) { |
1455 return; |
1467 return; |
1456 } |
1468 } |
1457 |
1469 |
1458 switch (connectionState) { |
1470 switch (connectionState) { |
1459 |
1471 |
1460 /* |
1472 /* |
1461 * If we haven't even started yet, don't bother reading inbound. |
1473 * If we haven't even started yet, don't bother reading inbound. |
1462 */ |
1474 */ |
1463 case cs_START: |
1475 case cs_START: |
1464 writer.closeOutbound(); |
1476 try { |
1477 outputRecord.close(); |
|
1478 } catch (IOException ioe) { |
|
1479 // ignore |
|
1480 } |
|
1481 outboundDone = true; |
|
1482 |
|
1483 try { |
|
1484 inputRecord.close(); |
|
1485 } catch (IOException ioe) { |
|
1486 // ignore |
|
1487 } |
|
1465 inboundDone = true; |
1488 inboundDone = true; |
1466 break; |
1489 break; |
1467 |
1490 |
1468 case cs_ERROR: |
1491 case cs_ERROR: |
1469 case cs_CLOSED: |
1492 case cs_CLOSED: |
1475 // case cs_HANDSHAKE: |
1498 // case cs_HANDSHAKE: |
1476 // case cs_DATA: |
1499 // case cs_DATA: |
1477 // case cs_RENEGOTIATE: |
1500 // case cs_RENEGOTIATE: |
1478 default: |
1501 default: |
1479 warning(Alerts.alert_close_notify); |
1502 warning(Alerts.alert_close_notify); |
1480 writer.closeOutbound(); |
1503 try { |
1504 outputRecord.close(); |
|
1505 } catch (IOException ioe) { |
|
1506 // ignore |
|
1507 } |
|
1508 outboundDone = true; |
|
1481 break; |
1509 break; |
1482 } |
1510 } |
1483 |
|
1484 // See comment in changeReadCiphers() |
|
1485 writeCipher.dispose(); |
|
1486 |
1511 |
1487 connectionState = cs_CLOSED; |
1512 connectionState = cs_CLOSED; |
1488 } |
1513 } |
1489 |
1514 |
1490 @Override |
1515 @Override |
1503 /** |
1528 /** |
1504 * Returns the outbound application data closure state |
1529 * Returns the outbound application data closure state |
1505 */ |
1530 */ |
1506 @Override |
1531 @Override |
1507 public boolean isOutboundDone() { |
1532 public boolean isOutboundDone() { |
1508 return writer.isOutboundDone(); |
1533 return outboundDone && outputRecord.isEmpty(); |
1509 } |
1534 } |
1510 |
1535 |
1511 /** |
1536 /** |
1512 * Signals that no more inbound network data will be sent |
1537 * Signals that no more inbound network data will be sent |
1513 * to this <code>SSLEngine</code>. |
1538 * to this <code>SSLEngine</code>. |
1525 if (inboundDone) { |
1550 if (inboundDone) { |
1526 return; |
1551 return; |
1527 } |
1552 } |
1528 |
1553 |
1529 closeOutboundInternal(); |
1554 closeOutboundInternal(); |
1555 |
|
1556 try { |
|
1557 inputRecord.close(); |
|
1558 } catch (IOException ioe) { |
|
1559 // ignore |
|
1560 } |
|
1530 inboundDone = true; |
1561 inboundDone = true; |
1531 |
|
1532 // See comment in changeReadCiphers() |
|
1533 readCipher.dispose(); |
|
1534 |
1562 |
1535 connectionState = cs_CLOSED; |
1563 connectionState = cs_CLOSED; |
1536 } |
1564 } |
1537 |
1565 |
1538 /* |
1566 /* |
1600 synchronized public SSLSession getHandshakeSession() { |
1628 synchronized public SSLSession getHandshakeSession() { |
1601 return handshakeSession; |
1629 return handshakeSession; |
1602 } |
1630 } |
1603 |
1631 |
1604 synchronized void setHandshakeSession(SSLSessionImpl session) { |
1632 synchronized void setHandshakeSession(SSLSessionImpl session) { |
1633 // update the fragment size, which may be negotiated during handshaking |
|
1634 inputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize()); |
|
1635 outputRecord.changeFragmentSize(session.getNegotiatedMaxFragSize()); |
|
1636 |
|
1605 handshakeSession = session; |
1637 handshakeSession = session; |
1606 } |
1638 } |
1607 |
1639 |
1608 /** |
1640 /** |
1609 * Returns a delegated <code>Runnable</code> task for |
1641 * Returns a delegated <code>Runnable</code> task for |
1699 * Ok, this engine's going down. |
1731 * Ok, this engine's going down. |
1700 */ |
1732 */ |
1701 int oldState = connectionState; |
1733 int oldState = connectionState; |
1702 connectionState = cs_ERROR; |
1734 connectionState = cs_ERROR; |
1703 |
1735 |
1736 try { |
|
1737 inputRecord.close(); |
|
1738 } catch (IOException ioe) { |
|
1739 // ignore |
|
1740 } |
|
1704 inboundDone = true; |
1741 inboundDone = true; |
1705 |
1742 |
1706 sess.invalidate(); |
1743 sess.invalidate(); |
1707 if (handshakeSession != null) { |
1744 if (handshakeSession != null) { |
1708 handshakeSession.invalidate(); |
1745 handshakeSession.invalidate(); |
1726 */ |
1763 */ |
1727 closeReason = |
1764 closeReason = |
1728 Alerts.getSSLException(description, cause, diagnostic); |
1765 Alerts.getSSLException(description, cause, diagnostic); |
1729 } |
1766 } |
1730 |
1767 |
1731 writer.closeOutbound(); |
1768 try { |
1769 outputRecord.close(); |
|
1770 } catch (IOException ioe) { |
|
1771 // ignore |
|
1772 } |
|
1773 outboundDone = true; |
|
1732 |
1774 |
1733 connectionState = cs_CLOSED; |
1775 connectionState = cs_CLOSED; |
1734 |
|
1735 // See comment in changeReadCiphers() |
|
1736 readCipher.dispose(); |
|
1737 writeCipher.dispose(); |
|
1738 |
1776 |
1739 if (cause instanceof RuntimeException) { |
1777 if (cause instanceof RuntimeException) { |
1740 throw (RuntimeException)cause; |
1778 throw (RuntimeException)cause; |
1741 } else { |
1779 } else { |
1742 throw closeReason; |
1780 throw closeReason; |
1745 |
1783 |
1746 /* |
1784 /* |
1747 * Process an incoming alert ... caller must already have synchronized |
1785 * Process an incoming alert ... caller must already have synchronized |
1748 * access to "this". |
1786 * access to "this". |
1749 */ |
1787 */ |
1750 private void recvAlert() throws IOException { |
1788 private void recvAlert(ByteBuffer fragment) throws IOException { |
1751 byte level = (byte)inputRecord.read(); |
1789 byte level = fragment.get(); |
1752 byte description = (byte)inputRecord.read(); |
1790 byte description = fragment.get(); |
1791 |
|
1753 if (description == -1) { // check for short message |
1792 if (description == -1) { // check for short message |
1754 fatal(Alerts.alert_illegal_parameter, "Short alert message"); |
1793 fatal(Alerts.alert_illegal_parameter, "Short alert message"); |
1755 } |
1794 } |
1756 |
1795 |
1757 if (debug != null && (Debug.isOn("record") || |
1796 if (debug != null && (Debug.isOn("record") || |
1811 return; |
1850 return; |
1812 } |
1851 } |
1813 |
1852 |
1814 // For initial handshaking, don't send alert message to peer if |
1853 // For initial handshaking, don't send alert message to peer if |
1815 // handshaker has not started. |
1854 // handshaker has not started. |
1816 if (connectionState == cs_HANDSHAKE && |
1855 // |
1817 (handshaker == null || !handshaker.started())) { |
1856 // Shall we send an fatal alter to terminate the connection gracefully? |
1857 if (connectionState <= cs_HANDSHAKE && |
|
1858 (handshaker == null || !handshaker.started() || |
|
1859 !handshaker.activated())) { |
|
1818 return; |
1860 return; |
1819 } |
1861 } |
1820 |
1862 |
1821 EngineOutputRecord r = new EngineOutputRecord(Record.ct_alert, this); |
|
1822 r.setVersion(protocolVersion); |
|
1823 |
|
1824 boolean useDebug = debug != null && Debug.isOn("ssl"); |
|
1825 if (useDebug) { |
|
1826 synchronized (System.out) { |
|
1827 System.out.print(Thread.currentThread().getName()); |
|
1828 System.out.print(", SEND " + protocolVersion + " ALERT: "); |
|
1829 if (level == Alerts.alert_fatal) { |
|
1830 System.out.print("fatal, "); |
|
1831 } else if (level == Alerts.alert_warning) { |
|
1832 System.out.print("warning, "); |
|
1833 } else { |
|
1834 System.out.print("<level = " + (0x0ff & level) + ">, "); |
|
1835 } |
|
1836 System.out.println("description = " |
|
1837 + Alerts.alertDescription(description)); |
|
1838 } |
|
1839 } |
|
1840 |
|
1841 r.write(level); |
|
1842 r.write(description); |
|
1843 try { |
1863 try { |
1844 writeRecord(r); |
1864 outputRecord.encodeAlert(level, description); |
1845 } catch (IOException e) { |
1865 } catch (IOException ioe) { |
1846 if (useDebug) { |
1866 // ignore |
1847 System.out.println(Thread.currentThread().getName() + |
|
1848 ", Exception sending alert: " + e); |
|
1849 } |
|
1850 } |
1867 } |
1851 } |
1868 } |
1852 |
1869 |
1853 |
1870 |
1854 // |
1871 // |
1892 * we will need to wait for the next handshake. |
1909 * we will need to wait for the next handshake. |
1893 */ |
1910 */ |
1894 @Override |
1911 @Override |
1895 synchronized public void setNeedClientAuth(boolean flag) { |
1912 synchronized public void setNeedClientAuth(boolean flag) { |
1896 doClientAuth = (flag ? |
1913 doClientAuth = (flag ? |
1897 SSLEngineImpl.clauth_required : SSLEngineImpl.clauth_none); |
1914 ClientAuthType.CLIENT_AUTH_REQUIRED : |
1915 ClientAuthType.CLIENT_AUTH_NONE); |
|
1898 |
1916 |
1899 if ((handshaker != null) && |
1917 if ((handshaker != null) && |
1900 (handshaker instanceof ServerHandshaker) && |
1918 (handshaker instanceof ServerHandshaker) && |
1901 !handshaker.activated()) { |
1919 !handshaker.activated()) { |
1902 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth); |
1920 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth); |
1903 } |
1921 } |
1904 } |
1922 } |
1905 |
1923 |
1906 @Override |
1924 @Override |
1907 synchronized public boolean getNeedClientAuth() { |
1925 synchronized public boolean getNeedClientAuth() { |
1908 return (doClientAuth == SSLEngineImpl.clauth_required); |
1926 return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUIRED); |
1909 } |
1927 } |
1910 |
1928 |
1911 /** |
1929 /** |
1912 * Sets the flag controlling whether a server mode engine |
1930 * Sets the flag controlling whether a server mode engine |
1913 * *REQUESTS* SSL client authentication. |
1931 * *REQUESTS* SSL client authentication. |
1917 * we will need to wait for the next handshake. |
1935 * we will need to wait for the next handshake. |
1918 */ |
1936 */ |
1919 @Override |
1937 @Override |
1920 synchronized public void setWantClientAuth(boolean flag) { |
1938 synchronized public void setWantClientAuth(boolean flag) { |
1921 doClientAuth = (flag ? |
1939 doClientAuth = (flag ? |
1922 SSLEngineImpl.clauth_requested : SSLEngineImpl.clauth_none); |
1940 ClientAuthType.CLIENT_AUTH_REQUESTED : |
1941 ClientAuthType.CLIENT_AUTH_NONE); |
|
1923 |
1942 |
1924 if ((handshaker != null) && |
1943 if ((handshaker != null) && |
1925 (handshaker instanceof ServerHandshaker) && |
1944 (handshaker instanceof ServerHandshaker) && |
1926 !handshaker.activated()) { |
1945 !handshaker.activated()) { |
1927 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth); |
1946 ((ServerHandshaker) handshaker).setClientAuth(doClientAuth); |
1928 } |
1947 } |
1929 } |
1948 } |
1930 |
1949 |
1931 @Override |
1950 @Override |
1932 synchronized public boolean getWantClientAuth() { |
1951 synchronized public boolean getWantClientAuth() { |
1933 return (doClientAuth == SSLEngineImpl.clauth_requested); |
1952 return (doClientAuth == ClientAuthType.CLIENT_AUTH_REQUESTED); |
1934 } |
1953 } |
1935 |
1954 |
1936 |
1955 |
1937 /** |
1956 /** |
1938 * Sets the flag controlling whether the engine is in SSL |
1957 * Sets the flag controlling whether the engine is in SSL |
1944 synchronized public void setUseClientMode(boolean flag) { |
1963 synchronized public void setUseClientMode(boolean flag) { |
1945 switch (connectionState) { |
1964 switch (connectionState) { |
1946 |
1965 |
1947 case cs_START: |
1966 case cs_START: |
1948 /* |
1967 /* |
1949 * If we need to change the engine mode and the enabled |
1968 * If we need to change the socket mode and the enabled |
1950 * protocols haven't specifically been set by the user, |
1969 * protocols and cipher suites haven't specifically been |
1951 * change them to the corresponding default ones. |
1970 * set by the user, change them to the corresponding |
1971 * default ones. |
|
1952 */ |
1972 */ |
1953 if (roleIsServer != (!flag) && |
1973 if (roleIsServer != (!flag)) { |
1954 sslContext.isDefaultProtocolList(enabledProtocols)) { |
1974 if (sslContext.isDefaultProtocolList(enabledProtocols)) { |
1955 enabledProtocols = sslContext.getDefaultProtocolList(!flag); |
1975 enabledProtocols = |
1976 sslContext.getDefaultProtocolList(!flag); |
|
1977 } |
|
1978 |
|
1979 if (sslContext.isDefaultCipherSuiteList(enabledCipherSuites)) { |
|
1980 enabledCipherSuites = |
|
1981 sslContext.getDefaultCipherSuiteList(!flag); |
|
1982 } |
|
1956 } |
1983 } |
1957 |
1984 |
1958 roleIsServer = !flag; |
1985 roleIsServer = !flag; |
1959 serverModeSet = true; |
1986 serverModeSet = true; |
1960 break; |
1987 break; |
1968 * have the streams. |
1995 * have the streams. |
1969 */ |
1996 */ |
1970 assert(handshaker != null); |
1997 assert(handshaker != null); |
1971 if (!handshaker.activated()) { |
1998 if (!handshaker.activated()) { |
1972 /* |
1999 /* |
1973 * If we need to change the engine mode and the enabled |
2000 * If we need to change the socket mode and the enabled |
1974 * protocols haven't specifically been set by the user, |
2001 * protocols and cipher suites haven't specifically been |
1975 * change them to the corresponding default ones. |
2002 * set by the user, change them to the corresponding |
2003 * default ones. |
|
1976 */ |
2004 */ |
1977 if (roleIsServer != (!flag) && |
2005 if (roleIsServer != (!flag)) { |
1978 sslContext.isDefaultProtocolList(enabledProtocols)) { |
2006 if (sslContext.isDefaultProtocolList(enabledProtocols)) { |
1979 enabledProtocols = sslContext.getDefaultProtocolList(!flag); |
2007 enabledProtocols = |
2008 sslContext.getDefaultProtocolList(!flag); |
|
2009 } |
|
2010 |
|
2011 if (sslContext.isDefaultCipherSuiteList( |
|
2012 enabledCipherSuites)) { |
|
2013 enabledCipherSuites = |
|
2014 sslContext.getDefaultCipherSuiteList(!flag); |
|
2015 } |
|
1980 } |
2016 } |
1981 |
2017 |
1982 roleIsServer = !flag; |
2018 roleIsServer = !flag; |
1983 connectionState = cs_START; |
2019 connectionState = cs_START; |
1984 initHandshaker(); |
2020 initHandshaker(); |
2100 params.setEndpointIdentificationAlgorithm(identificationProtocol); |
2136 params.setEndpointIdentificationAlgorithm(identificationProtocol); |
2101 params.setAlgorithmConstraints(algorithmConstraints); |
2137 params.setAlgorithmConstraints(algorithmConstraints); |
2102 params.setSNIMatchers(sniMatchers); |
2138 params.setSNIMatchers(sniMatchers); |
2103 params.setServerNames(serverNames); |
2139 params.setServerNames(serverNames); |
2104 params.setUseCipherSuitesOrder(preferLocalCipherSuites); |
2140 params.setUseCipherSuitesOrder(preferLocalCipherSuites); |
2141 params.setEnableRetransmissions(enableRetransmissions); |
|
2142 params.setMaximumPacketSize(maximumPacketSize); |
|
2105 |
2143 |
2106 return params; |
2144 return params; |
2107 } |
2145 } |
2108 |
2146 |
2109 /** |
2147 /** |
2115 |
2153 |
2116 // the super implementation does not handle the following parameters |
2154 // the super implementation does not handle the following parameters |
2117 identificationProtocol = params.getEndpointIdentificationAlgorithm(); |
2155 identificationProtocol = params.getEndpointIdentificationAlgorithm(); |
2118 algorithmConstraints = params.getAlgorithmConstraints(); |
2156 algorithmConstraints = params.getAlgorithmConstraints(); |
2119 preferLocalCipherSuites = params.getUseCipherSuitesOrder(); |
2157 preferLocalCipherSuites = params.getUseCipherSuitesOrder(); |
2158 enableRetransmissions = params.getEnableRetransmissions(); |
|
2159 maximumPacketSize = params.getMaximumPacketSize(); |
|
2160 |
|
2161 if (maximumPacketSize != 0) { |
|
2162 outputRecord.changePacketSize(maximumPacketSize); |
|
2163 } else { |
|
2164 // use the implicit maximum packet size. |
|
2165 maximumPacketSize = outputRecord.getMaxPacketSize(); |
|
2166 } |
|
2120 |
2167 |
2121 List<SNIServerName> sniNames = params.getServerNames(); |
2168 List<SNIServerName> sniNames = params.getServerNames(); |
2122 if (sniNames != null) { |
2169 if (sniNames != null) { |
2123 serverNames = sniNames; |
2170 serverNames = sniNames; |
2124 } |
2171 } |
2129 } |
2176 } |
2130 |
2177 |
2131 if ((handshaker != null) && !handshaker.started()) { |
2178 if ((handshaker != null) && !handshaker.started()) { |
2132 handshaker.setIdentificationProtocol(identificationProtocol); |
2179 handshaker.setIdentificationProtocol(identificationProtocol); |
2133 handshaker.setAlgorithmConstraints(algorithmConstraints); |
2180 handshaker.setAlgorithmConstraints(algorithmConstraints); |
2181 handshaker.setMaximumPacketSize(maximumPacketSize); |
|
2134 if (roleIsServer) { |
2182 if (roleIsServer) { |
2135 handshaker.setSNIMatchers(sniMatchers); |
2183 handshaker.setSNIMatchers(sniMatchers); |
2136 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites); |
2184 handshaker.setUseCipherSuitesOrder(preferLocalCipherSuites); |
2137 } else { |
2185 } else { |
2138 handshaker.setSNIServerNames(serverNames); |
2186 handshaker.setSNIServerNames(serverNames); |
2139 } |
2187 } |
2140 } |
2188 } |
2141 } |
|
2142 |
|
2143 /** |
|
2144 * Returns a boolean indicating whether the ChangeCipherSpec message |
|
2145 * has been received for this handshake. |
|
2146 */ |
|
2147 boolean receivedChangeCipherSpec() { |
|
2148 return receivedCCS; |
|
2149 } |
2189 } |
2150 |
2190 |
2151 /** |
2191 /** |
2152 * Returns a printable representation of this end of the connection. |
2192 * Returns a printable representation of this end of the connection. |
2153 */ |
2193 */ |
2160 retval.append("SSLEngine[hostname="); |
2200 retval.append("SSLEngine[hostname="); |
2161 String host = getPeerHost(); |
2201 String host = getPeerHost(); |
2162 retval.append((host == null) ? "null" : host); |
2202 retval.append((host == null) ? "null" : host); |
2163 retval.append(" port="); |
2203 retval.append(" port="); |
2164 retval.append(Integer.toString(getPeerPort())); |
2204 retval.append(Integer.toString(getPeerPort())); |
2205 retval.append(" role=" + (roleIsServer ? "Server" : "Client")); |
|
2165 retval.append("] "); |
2206 retval.append("] "); |
2166 retval.append(getSession().getCipherSuite()); |
2207 retval.append(getSession().getCipherSuite()); |
2167 retval.append("]"); |
2208 retval.append("]"); |
2168 |
2209 |
2169 return retval.toString(); |
2210 return retval.toString(); |