001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: /**
019: * @author Alexander Y. Kleymenov
020: * @version $Revision$
021: */package org.apache.harmony.xnet.provider.jsse;
022:
023: import org.apache.harmony.xnet.provider.jsse.AlertException;
024: import org.apache.harmony.xnet.provider.jsse.SSLSessionImpl;
025: import org.apache.harmony.xnet.provider.jsse.SSLEngineDataStream;
026:
027: import java.io.IOException;
028: import java.nio.BufferUnderflowException;
029: import java.nio.ByteBuffer;
030: import java.nio.ReadOnlyBufferException;
031: import javax.net.ssl.SSLEngine;
032: import javax.net.ssl.SSLHandshakeException;
033: import javax.net.ssl.SSLEngineResult;
034: import javax.net.ssl.SSLException;
035: import javax.net.ssl.SSLSession;
036:
037: /**
038: * Implementation of SSLEngine.
039: * @see javax.net.ssl.SSLEngine class documentation for more information.
040: */
041: public class SSLEngineImpl extends SSLEngine {
042:
043: // indicates if peer mode was set
044: private boolean peer_mode_was_set = false;
045: // indicates if handshake has been started
046: private boolean handshake_started = false;
047: // indicates if inbound operations finished
048: private boolean isInboundDone = false;
049: // indicates if outbound operations finished
050: private boolean isOutboundDone = false;
051: // indicates if close_notify alert had been sent to another peer
052: private boolean close_notify_was_sent = false;
053: // indicates if close_notify alert had been received from another peer
054: private boolean close_notify_was_received = false;
055: // indicates if engine was closed (it means that
056: // all the works on it are done, except (probably) some finalizing work)
057: private boolean engine_was_closed = false;
058: // indicates if engine was shutted down (it means that
059: // all cleaning work had been done and the engine is not operable)
060: private boolean engine_was_shutteddown = false;
061:
062: // record protocol to be used
063: protected SSLRecordProtocol recordProtocol;
064: // input stream for record protocol
065: private SSLBufferedInput recProtIS;
066: // handshake protocol to be used
067: private HandshakeProtocol handshakeProtocol;
068: // alert protocol to be used
069: private AlertProtocol alertProtocol;
070: // place where application data will be stored
071: private SSLEngineAppData appData;
072: // outcoming application data stream
073: private SSLEngineDataStream dataStream = new SSLEngineDataStream();
074: // active session object
075: private SSLSessionImpl session;
076:
077: // peer configuration parameters
078: protected SSLParameters sslParameters;
079:
080: // in case of emergency situations when data could not be
081: // placed in destination buffers it will be stored in this
082: // fields
083: private byte[] remaining_wrapped_data = null;
084: private byte[] remaining_hsh_data = null;
085:
086: // logger
087: private Logger.Stream logger = Logger.getStream("engine");
088:
089: /**
090: * Ctor
091: * @param sslParameters: SSLParameters
092: */
093: protected SSLEngineImpl(SSLParameters sslParameters) {
094: super ();
095: this .sslParameters = sslParameters;
096: }
097:
098: /**
099: * Ctor
100: * @param host: String
101: * @param port: int
102: * @param sslParameters: SSLParameters
103: */
104: protected SSLEngineImpl(String host, int port,
105: SSLParameters sslParameters) {
106: super (host, port);
107: this .sslParameters = sslParameters;
108: }
109:
110: /**
111: * Starts the handshake.
112: * @throws SSLException
113: * @see javax.net.ssl.SSLEngine#beginHandshake() method documentation
114: * for more information
115: */
116: public void beginHandshake() throws SSLException {
117: if (engine_was_closed) {
118: throw new SSLException("Engine has already been closed.");
119: }
120: if (!peer_mode_was_set) {
121: throw new IllegalStateException(
122: "Client/Server mode was not set");
123: }
124: if (!handshake_started) {
125: handshake_started = true;
126: if (getUseClientMode()) {
127: handshakeProtocol = new ClientHandshakeImpl(this );
128: } else {
129: handshakeProtocol = new ServerHandshakeImpl(this );
130: }
131: appData = new SSLEngineAppData();
132: alertProtocol = new AlertProtocol();
133: recProtIS = new SSLBufferedInput();
134: recordProtocol = new SSLRecordProtocol(handshakeProtocol,
135: alertProtocol, recProtIS, appData);
136: }
137: handshakeProtocol.start();
138: }
139:
140: /**
141: * Closes inbound operations of this engine
142: * @throws SSLException
143: * @see javax.net.ssl.SSLEngine#closeInbound() method documentation
144: * for more information
145: */
146: public void closeInbound() throws SSLException {
147: if (logger != null) {
148: logger.println("closeInbound() " + isInboundDone);
149: }
150: if (isInboundDone) {
151: return;
152: }
153: isInboundDone = true;
154: engine_was_closed = true;
155: if (handshake_started) {
156: if (!close_notify_was_received) {
157: if (session != null) {
158: session.invalidate();
159: }
160: alertProtocol.alert(AlertProtocol.FATAL,
161: AlertProtocol.INTERNAL_ERROR);
162: throw new SSLException(
163: "Inbound is closed before close_notify "
164: + "alert has been received.");
165: }
166: } else {
167: // engine is closing before initial handshake has been made
168: shutdown();
169: }
170: }
171:
172: /**
173: * Closes outbound operations of this engine
174: * @see javax.net.ssl.SSLEngine#closeOutbound() method documentation
175: * for more information
176: */
177: public void closeOutbound() {
178: if (logger != null) {
179: logger.println("closeOutbound() " + isOutboundDone);
180: }
181: if (isOutboundDone) {
182: return;
183: }
184: isOutboundDone = true;
185: if (handshake_started) {
186: // initial handshake had been started
187: alertProtocol.alert(AlertProtocol.WARNING,
188: AlertProtocol.CLOSE_NOTIFY);
189: close_notify_was_sent = true;
190: } else {
191: // engine is closing before initial handshake has been made
192: shutdown();
193: }
194: engine_was_closed = true;
195: }
196:
197: /**
198: * Returns handshake's delegated tasks to be run
199: * @return the delegated task to be executed.
200: * @see javax.net.ssl.SSLEngine#getDelegatedTask() method documentation
201: * for more information
202: */
203: public Runnable getDelegatedTask() {
204: return handshakeProtocol.getTask();
205: }
206:
207: /**
208: * Returns names of supported cipher suites.
209: * @return array of strings containing the names of supported cipher suites
210: * @see javax.net.ssl.SSLEngine#getSupportedCipherSuites() method
211: * documentation for more information
212: */
213: public String[] getSupportedCipherSuites() {
214: return CipherSuite.getSupportedCipherSuiteNames();
215: }
216:
217: // --------------- SSLParameters based methods ---------------------
218:
219: /**
220: * This method works according to the specification of implemented class.
221: * @see javax.net.ssl.SSLEngine#getEnabledCipherSuites() method
222: * documentation for more information
223: */
224: public String[] getEnabledCipherSuites() {
225: return sslParameters.getEnabledCipherSuites();
226: }
227:
228: /**
229: * This method works according to the specification of implemented class.
230: * @see javax.net.ssl.SSLEngine#setEnabledCipherSuites(String) method
231: * documentation for more information
232: */
233: public void setEnabledCipherSuites(String[] suites) {
234: sslParameters.setEnabledCipherSuites(suites);
235: }
236:
237: /**
238: * This method works according to the specification of implemented class.
239: * @see javax.net.ssl.SSLEngine#getSupportedProtocols() method
240: * documentation for more information
241: */
242: public String[] getSupportedProtocols() {
243: return (String[]) ProtocolVersion.supportedProtocols.clone();
244: }
245:
246: /**
247: * This method works according to the specification of implemented class.
248: * @see javax.net.ssl.SSLEngine#getEnabledProtocols() method
249: * documentation for more information
250: */
251: public String[] getEnabledProtocols() {
252: return sslParameters.getEnabledProtocols();
253: }
254:
255: /**
256: * This method works according to the specification of implemented class.
257: * @see javax.net.ssl.SSLEngine#setEnabledProtocols(String) method
258: * documentation for more information
259: */
260: public void setEnabledProtocols(String[] protocols) {
261: sslParameters.setEnabledProtocols(protocols);
262: }
263:
264: /**
265: * This method works according to the specification of implemented class.
266: * @see javax.net.ssl.SSLEngine#setUseClientMode(boolean) method
267: * documentation for more information
268: */
269: public void setUseClientMode(boolean mode) {
270: if (handshake_started) {
271: throw new IllegalArgumentException(
272: "Could not change the mode after the initial handshake has begun.");
273: }
274: sslParameters.setUseClientMode(mode);
275: peer_mode_was_set = true;
276: }
277:
278: /**
279: * This method works according to the specification of implemented class.
280: * @see javax.net.ssl.SSLEngine#getUseClientMode() method
281: * documentation for more information
282: */
283: public boolean getUseClientMode() {
284: return sslParameters.getUseClientMode();
285: }
286:
287: /**
288: * This method works according to the specification of implemented class.
289: * @see javax.net.ssl.SSLEngine#setNeedClientAuth(boolean) method
290: * documentation for more information
291: */
292: public void setNeedClientAuth(boolean need) {
293: sslParameters.setNeedClientAuth(need);
294: }
295:
296: /**
297: * This method works according to the specification of implemented class.
298: * @see javax.net.ssl.SSLEngine#getNeedClientAuth() method
299: * documentation for more information
300: */
301: public boolean getNeedClientAuth() {
302: return sslParameters.getNeedClientAuth();
303: }
304:
305: /**
306: * This method works according to the specification of implemented class.
307: * @see javax.net.ssl.SSLEngine#setWantClientAuth(boolean) method
308: * documentation for more information
309: */
310: public void setWantClientAuth(boolean want) {
311: sslParameters.setWantClientAuth(want);
312: }
313:
314: /**
315: * This method works according to the specification of implemented class.
316: * @see javax.net.ssl.SSLEngine#getWantClientAuth() method
317: * documentation for more information
318: */
319: public boolean getWantClientAuth() {
320: return sslParameters.getWantClientAuth();
321: }
322:
323: /**
324: * This method works according to the specification of implemented class.
325: * @see javax.net.ssl.SSLEngine#setEnableSessionCreation(boolean) method
326: * documentation for more information
327: */
328: public void setEnableSessionCreation(boolean flag) {
329: sslParameters.setEnableSessionCreation(flag);
330: }
331:
332: /**
333: * This method works according to the specification of implemented class.
334: * @see javax.net.ssl.SSLEngine#getEnableSessionCreation() method
335: * documentation for more information
336: */
337: public boolean getEnableSessionCreation() {
338: return sslParameters.getEnableSessionCreation();
339: }
340:
341: // -----------------------------------------------------------------
342:
343: /**
344: * This method works according to the specification of implemented class.
345: * @see javax.net.ssl.SSLEngine#getHandshakeStatus() method
346: * documentation for more information
347: */
348: public SSLEngineResult.HandshakeStatus getHandshakeStatus() {
349: if (!handshake_started || engine_was_shutteddown) {
350: // initial handshake has not been started yet
351: return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
352: }
353: if (alertProtocol.hasAlert()) {
354: // need to send an alert
355: return SSLEngineResult.HandshakeStatus.NEED_WRAP;
356: }
357: if (close_notify_was_sent && !close_notify_was_received) {
358: // waiting for "close_notify" response
359: return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
360: }
361: return handshakeProtocol.getStatus();
362: }
363:
364: /**
365: * This method works according to the specification of implemented class.
366: * @see javax.net.ssl.SSLEngine#getSession() method
367: * documentation for more information
368: */
369: public SSLSession getSession() {
370: if (session != null) {
371: return session;
372: } else {
373: return SSLSessionImpl.NULL_SESSION;
374: }
375: }
376:
377: /**
378: * This method works according to the specification of implemented class.
379: * @see javax.net.ssl.SSLEngine#isInboundDone() method
380: * documentation for more information
381: */
382: public boolean isInboundDone() {
383: return isInboundDone || engine_was_closed;
384: }
385:
386: /**
387: * This method works according to the specification of implemented class.
388: * @see javax.net.ssl.SSLEngine#isOutboundDone() method
389: * documentation for more information
390: */
391: public boolean isOutboundDone() {
392: return isOutboundDone;
393: }
394:
395: /**
396: * Decodes one complete SSL/TLS record provided in the source buffer.
397: * If decoded record contained application data, this data will
398: * be placed in the destination buffers.
399: * For more information about TLS record fragmentation see
400: * TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
401: * @param src source buffer containing SSL/TLS record.
402: * @param dsts destination buffers to place received application data.
403: * @see javax.net.ssl.SSLEngine#unwrap(ByteBuffer,ByteBuffer[],int,int)
404: * method documentation for more information
405: */
406: public SSLEngineResult unwrap(ByteBuffer src, ByteBuffer[] dsts,
407: int offset, int length) throws SSLException {
408: if (engine_was_shutteddown) {
409: return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
410: SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0,
411: 0);
412: }
413: if ((src == null) || (dsts == null)) {
414: throw new IllegalStateException(
415: "Some of the input parameters are null");
416: }
417:
418: if (!handshake_started) {
419: beginHandshake();
420: }
421:
422: SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
423: // If is is initial handshake or connection closure stage,
424: // check if this call was made in spite of handshake status
425: if ((session == null || engine_was_closed)
426: && (handshakeStatus
427: .equals(SSLEngineResult.HandshakeStatus.NEED_WRAP) || handshakeStatus
428: .equals(SSLEngineResult.HandshakeStatus.NEED_TASK))) {
429: return new SSLEngineResult(getEngineStatus(),
430: handshakeStatus, 0, 0);
431: }
432:
433: if (src.remaining() < recordProtocol.getMinRecordSize()) {
434: return new SSLEngineResult(
435: SSLEngineResult.Status.BUFFER_UNDERFLOW,
436: getHandshakeStatus(), 0, 0);
437: }
438:
439: try {
440: src.mark();
441: // check the destination buffers and count their capacity
442: int capacity = 0;
443: for (int i = offset; i < offset + length; i++) {
444: if (dsts[i] == null) {
445: throw new IllegalStateException(
446: "Some of the input parameters are null");
447: }
448: if (dsts[i].isReadOnly()) {
449: throw new ReadOnlyBufferException();
450: }
451: capacity += dsts[i].remaining();
452: }
453: if (capacity < recordProtocol.getDataSize(src.remaining())) {
454: return new SSLEngineResult(
455: SSLEngineResult.Status.BUFFER_OVERFLOW,
456: getHandshakeStatus(), 0, 0);
457: }
458: recProtIS.setSourceBuffer(src);
459: // unwrap the record contained in source buffer, pass it
460: // to appropriate client protocol (alert, handshake, or app)
461: // and retrieve the type of unwrapped data
462: int type = recordProtocol.unwrap();
463: // process the data and return the result
464: switch (type) {
465: case ContentType.HANDSHAKE:
466: case ContentType.CHANGE_CIPHER_SPEC:
467: if (handshakeProtocol.getStatus().equals(
468: SSLEngineResult.HandshakeStatus.FINISHED)) {
469: session = recordProtocol.getSession();
470: }
471: break;
472: case ContentType.APPLICATION_DATA:
473: break;
474: case ContentType.ALERT:
475: if (alertProtocol.isFatalAlert()) {
476: alertProtocol.setProcessed();
477: if (session != null) {
478: session.invalidate();
479: }
480: String description = "Fatal alert received "
481: + alertProtocol.getAlertDescription();
482: shutdown();
483: throw new SSLException(description);
484: } else {
485: if (logger != null) {
486: logger
487: .println("Warning allert has been received: "
488: + alertProtocol
489: .getAlertDescription());
490: }
491: switch (alertProtocol.getDescriptionCode()) {
492: case AlertProtocol.CLOSE_NOTIFY:
493: alertProtocol.setProcessed();
494: close_notify_was_received = true;
495: if (!close_notify_was_sent) {
496: closeOutbound();
497: closeInbound();
498: } else {
499: closeInbound();
500: shutdown();
501: }
502: break;
503: case AlertProtocol.NO_RENEGOTIATION:
504: alertProtocol.setProcessed();
505: if (session == null) {
506: // message received during the initial
507: // handshake
508: throw new AlertException(
509: AlertProtocol.HANDSHAKE_FAILURE,
510: new SSLHandshakeException(
511: "Received no_renegotiation "
512: + "during the initial handshake"));
513: } else {
514: // just stop the handshake
515: handshakeProtocol.stop();
516: }
517: break;
518: default:
519: alertProtocol.setProcessed();
520: }
521: }
522: break;
523: }
524: return new SSLEngineResult(getEngineStatus(),
525: getHandshakeStatus(), recProtIS.consumed(),
526: // place the app. data (if any) into the dest. buffers
527: // and get the number of produced bytes:
528: appData.placeTo(dsts, offset, length));
529: } catch (BufferUnderflowException e) {
530: // there was not enought data ource buffer to make complete packet
531: src.reset();
532: return new SSLEngineResult(
533: SSLEngineResult.Status.BUFFER_UNDERFLOW,
534: getHandshakeStatus(), 0, 0);
535: } catch (AlertException e) {
536: // fatal alert occured
537: alertProtocol.alert(AlertProtocol.FATAL, e
538: .getDescriptionCode());
539: engine_was_closed = true;
540: src.reset();
541: if (session != null) {
542: session.invalidate();
543: }
544: // shutdown work will be made after the alert will be sent
545: // to another peer (by wrap method)
546: throw e.getReason();
547: } catch (SSLException e) {
548: throw e;
549: } catch (IOException e) {
550: alertProtocol.alert(AlertProtocol.FATAL,
551: AlertProtocol.INTERNAL_ERROR);
552: engine_was_closed = true;
553: // shutdown work will be made after the alert will be sent
554: // to another peer (by wrap method)
555: throw new SSLException(e.getMessage());
556: }
557: }
558:
559: /**
560: * Encodes the application data into SSL/TLS record. If handshake status
561: * of the engine differs from NOT_HANDSHAKING the operation can work
562: * without consuming of the source data.
563: * For more information about TLS record fragmentation see
564: * TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
565: * @param srcs the source buffers with application data to be encoded
566: * into SSL/TLS record.
567: * @param offset the offset in the destination buffers array pointing to
568: * the first buffer with the source data.
569: * @param len specifies the maximum number of buffers to be procesed.
570: * @param dst the destination buffer where encoded data will be placed.
571: * @see javax.net.ssl.SSLEngine#wrap(ByteBuffer[],int,int,ByteBuffer) method
572: * documentation for more information
573: */
574: public SSLEngineResult wrap(ByteBuffer[] srcs, int offset, int len,
575: ByteBuffer dst) throws SSLException {
576: if (engine_was_shutteddown) {
577: return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
578: SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0,
579: 0);
580: }
581: if ((srcs == null) || (dst == null)) {
582: throw new IllegalStateException(
583: "Some of the input parameters are null");
584: }
585: if (dst.isReadOnly()) {
586: throw new ReadOnlyBufferException();
587: }
588:
589: if (!handshake_started) {
590: beginHandshake();
591: }
592:
593: SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
594: // If it is an initial handshake or connection closure stage,
595: // check if this call was made in spite of handshake status
596: if ((session == null || engine_was_closed)
597: && (handshakeStatus
598: .equals(SSLEngineResult.HandshakeStatus.NEED_UNWRAP) || handshakeStatus
599: .equals(SSLEngineResult.HandshakeStatus.NEED_TASK))) {
600: return new SSLEngineResult(getEngineStatus(),
601: handshakeStatus, 0, 0);
602: }
603:
604: int capacity = dst.remaining();
605: int produced = 0;
606:
607: if (alertProtocol.hasAlert()) {
608: // we have an alert to be sent
609: if (capacity < recordProtocol.getRecordSize(2)) {
610: return new SSLEngineResult(
611: SSLEngineResult.Status.BUFFER_OVERFLOW,
612: handshakeStatus, 0, 0);
613: }
614: byte[] alert_data = alertProtocol.wrap();
615: // place the alert record into destination
616: dst.put(alert_data);
617: if (alertProtocol.isFatalAlert()) {
618: alertProtocol.setProcessed();
619: if (session != null) {
620: session.invalidate();
621: }
622: // fatal alert has been sent, so shut down the engine
623: shutdown();
624: return new SSLEngineResult(
625: SSLEngineResult.Status.CLOSED,
626: SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
627: 0, alert_data.length);
628: } else {
629: alertProtocol.setProcessed();
630: // check if the works on this engine have been done
631: if (close_notify_was_sent && close_notify_was_received) {
632: shutdown();
633: return new SSLEngineResult(
634: SSLEngineResult.Status.CLOSED,
635: SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
636: 0, alert_data.length);
637: }
638: return new SSLEngineResult(getEngineStatus(),
639: getHandshakeStatus(), 0, alert_data.length);
640: }
641: }
642:
643: if (capacity < recordProtocol.getMinRecordSize()) {
644: if (logger != null) {
645: logger.println("Capacity of the destination("
646: + capacity + ") < MIN_PACKET_SIZE("
647: + recordProtocol.getMinRecordSize() + ")");
648: }
649: return new SSLEngineResult(
650: SSLEngineResult.Status.BUFFER_OVERFLOW,
651: handshakeStatus, 0, 0);
652: }
653:
654: try {
655: if (!handshakeStatus
656: .equals(SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
657: // so we wraps application data
658: dataStream.setSourceBuffers(srcs, offset, len);
659: if ((capacity < SSLRecordProtocol.MAX_SSL_PACKET_SIZE)
660: && (capacity < recordProtocol
661: .getRecordSize(dataStream.available()))) {
662: if (logger != null) {
663: logger
664: .println("The destination buffer("
665: + capacity
666: + ") can not take the resulting packet("
667: + recordProtocol
668: .getRecordSize(dataStream
669: .available())
670: + ")");
671: }
672: return new SSLEngineResult(
673: SSLEngineResult.Status.BUFFER_OVERFLOW,
674: handshakeStatus, 0, 0);
675: }
676: if (remaining_wrapped_data == null) {
677: remaining_wrapped_data = recordProtocol.wrap(
678: ContentType.APPLICATION_DATA, dataStream);
679: }
680: if (capacity < remaining_wrapped_data.length) {
681: // It should newer happen because we checked the destination
682: // buffer size, but there is a possibility
683: // (if dest buffer was filled outside)
684: // so we just remember the data into remaining_wrapped_data
685: // and will enclose it during the the next call
686: return new SSLEngineResult(
687: SSLEngineResult.Status.BUFFER_OVERFLOW,
688: handshakeStatus, dataStream.consumed(), 0);
689: } else {
690: dst.put(remaining_wrapped_data);
691: produced = remaining_wrapped_data.length;
692: remaining_wrapped_data = null;
693: return new SSLEngineResult(getEngineStatus(),
694: handshakeStatus, dataStream.consumed(),
695: produced);
696: }
697: } else {
698: if (remaining_hsh_data == null) {
699: remaining_hsh_data = handshakeProtocol.wrap();
700: }
701: if (capacity < remaining_hsh_data.length) {
702: // It should newer happen because we checked the destination
703: // buffer size, but there is a possibility
704: // (if dest buffer was filled outside)
705: // so we just remember the data into remaining_hsh_data
706: // and will enclose it during the the next call
707: return new SSLEngineResult(
708: SSLEngineResult.Status.BUFFER_OVERFLOW,
709: handshakeStatus, 0, 0);
710: } else {
711: dst.put(remaining_hsh_data);
712: produced = remaining_hsh_data.length;
713: remaining_hsh_data = null;
714:
715: handshakeStatus = handshakeProtocol.getStatus();
716: if (handshakeStatus
717: .equals(SSLEngineResult.HandshakeStatus.FINISHED)) {
718: session = recordProtocol.getSession();
719: }
720: }
721: return new SSLEngineResult(getEngineStatus(),
722: getHandshakeStatus(), 0, produced);
723: }
724: } catch (AlertException e) {
725: // fatal alert occured
726: alertProtocol.alert(AlertProtocol.FATAL, e
727: .getDescriptionCode());
728: engine_was_closed = true;
729: if (session != null) {
730: session.invalidate();
731: }
732: // shutdown work will be made after the alert will be sent
733: // to another peer (by wrap method)
734: throw e.getReason();
735: }
736: }
737:
738: // Shutdownes the engine and makes all cleanup work.
739: private void shutdown() {
740: engine_was_closed = true;
741: engine_was_shutteddown = true;
742: isOutboundDone = true;
743: isInboundDone = true;
744: if (handshake_started) {
745: alertProtocol.shutdown();
746: alertProtocol = null;
747: handshakeProtocol.shutdown();
748: handshakeProtocol = null;
749: recordProtocol.shutdown();
750: recordProtocol = null;
751: }
752: }
753:
754: private SSLEngineResult.Status getEngineStatus() {
755: return (engine_was_closed) ? SSLEngineResult.Status.CLOSED
756: : SSLEngineResult.Status.OK;
757: }
758: }
|