Methods Summary |
---|
public void | beginHandshake()Starts the handshake.
if (engine_was_closed) {
throw new SSLException("Engine has already been closed.");
}
if (!peer_mode_was_set) {
throw new IllegalStateException("Client/Server mode was not set");
}
if (!handshake_started) {
handshake_started = true;
if (getUseClientMode()) {
handshakeProtocol = new ClientHandshakeImpl(this);
} else {
handshakeProtocol = new ServerHandshakeImpl(this);
}
appData = new SSLEngineAppData();
alertProtocol = new AlertProtocol();
recProtIS = new SSLBufferedInput();
recordProtocol = new SSLRecordProtocol(handshakeProtocol,
alertProtocol, recProtIS, appData);
}
handshakeProtocol.start();
|
public void | closeInbound()Closes inbound operations of this engine
if (logger != null) {
logger.println("closeInbound() "+isInboundDone);
}
if (isInboundDone) {
return;
}
isInboundDone = true;
engine_was_closed = true;
if (handshake_started) {
if (!close_notify_was_received) {
if (session != null) {
session.invalidate();
}
alertProtocol.alert(AlertProtocol.FATAL,
AlertProtocol.INTERNAL_ERROR);
throw new SSLException("Inbound is closed before close_notify "
+ "alert has been received.");
}
} else {
// engine is closing before initial handshake has been made
shutdown();
}
|
public void | closeOutbound()Closes outbound operations of this engine
if (logger != null) {
logger.println("closeOutbound() "+isOutboundDone);
}
if (isOutboundDone) {
return;
}
isOutboundDone = true;
if (handshake_started) {
// initial handshake had been started
alertProtocol.alert(AlertProtocol.WARNING,
AlertProtocol.CLOSE_NOTIFY);
close_notify_was_sent = true;
} else {
// engine is closing before initial handshake has been made
shutdown();
}
engine_was_closed = true;
|
public java.lang.Runnable | getDelegatedTask()Returns handshake's delegated tasks to be run
return handshakeProtocol.getTask();
|
public boolean | getEnableSessionCreation()This method works according to the specification of implemented class.
return sslParameters.getEnableSessionCreation();
|
public java.lang.String[] | getEnabledCipherSuites()This method works according to the specification of implemented class.
return sslParameters.getEnabledCipherSuites();
|
public java.lang.String[] | getEnabledProtocols()This method works according to the specification of implemented class.
return sslParameters.getEnabledProtocols();
|
private javax.net.ssl.SSLEngineResult$Status | getEngineStatus()
return (engine_was_closed)
? SSLEngineResult.Status.CLOSED
: SSLEngineResult.Status.OK;
|
public javax.net.ssl.SSLEngineResult$HandshakeStatus | getHandshakeStatus()This method works according to the specification of implemented class.
if (!handshake_started || engine_was_shutteddown) {
// initial handshake has not been started yet
return SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING;
}
if (alertProtocol.hasAlert()) {
// need to send an alert
return SSLEngineResult.HandshakeStatus.NEED_WRAP;
}
if (close_notify_was_sent && !close_notify_was_received) {
// waiting for "close_notify" response
return SSLEngineResult.HandshakeStatus.NEED_UNWRAP;
}
return handshakeProtocol.getStatus();
|
public boolean | getNeedClientAuth()This method works according to the specification of implemented class.
return sslParameters.getNeedClientAuth();
|
public javax.net.ssl.SSLSession | getSession()This method works according to the specification of implemented class.
if (session != null) {
return session;
} else {
return SSLSessionImpl.NULL_SESSION;
}
|
public java.lang.String[] | getSupportedCipherSuites()Returns names of supported cipher suites.
return CipherSuite.getSupportedCipherSuiteNames();
|
public java.lang.String[] | getSupportedProtocols()This method works according to the specification of implemented class.
return (String[]) ProtocolVersion.supportedProtocols.clone();
|
public boolean | getUseClientMode()This method works according to the specification of implemented class.
return sslParameters.getUseClientMode();
|
public boolean | getWantClientAuth()This method works according to the specification of implemented class.
return sslParameters.getWantClientAuth();
|
public boolean | isInboundDone()This method works according to the specification of implemented class.
return isInboundDone || engine_was_closed;
|
public boolean | isOutboundDone()This method works according to the specification of implemented class.
return isOutboundDone;
|
public void | setEnableSessionCreation(boolean flag)This method works according to the specification of implemented class.
sslParameters.setEnableSessionCreation(flag);
|
public void | setEnabledCipherSuites(java.lang.String[] suites)This method works according to the specification of implemented class.
sslParameters.setEnabledCipherSuites(suites);
|
public void | setEnabledProtocols(java.lang.String[] protocols)This method works according to the specification of implemented class.
sslParameters.setEnabledProtocols(protocols);
|
public void | setNeedClientAuth(boolean need)This method works according to the specification of implemented class.
sslParameters.setNeedClientAuth(need);
|
public void | setUseClientMode(boolean mode)This method works according to the specification of implemented class.
if (handshake_started) {
throw new IllegalArgumentException(
"Could not change the mode after the initial handshake has begun.");
}
sslParameters.setUseClientMode(mode);
peer_mode_was_set = true;
|
public void | setWantClientAuth(boolean want)This method works according to the specification of implemented class.
sslParameters.setWantClientAuth(want);
|
private void | shutdown()
engine_was_closed = true;
engine_was_shutteddown = true;
isOutboundDone = true;
isInboundDone = true;
if (handshake_started) {
alertProtocol.shutdown();
alertProtocol = null;
handshakeProtocol.shutdown();
handshakeProtocol = null;
recordProtocol.shutdown();
recordProtocol = null;
}
|
public javax.net.ssl.SSLEngineResult | unwrap(java.nio.ByteBuffer src, java.nio.ByteBuffer[] dsts, int offset, int length)Decodes one complete SSL/TLS record provided in the source buffer.
If decoded record contained application data, this data will
be placed in the destination buffers.
For more information about TLS record fragmentation see
TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
if (engine_was_shutteddown) {
return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
}
if ((src == null) || (dsts == null)) {
throw new IllegalStateException(
"Some of the input parameters are null");
}
if (!handshake_started) {
beginHandshake();
}
SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
// If is is initial handshake or connection closure stage,
// check if this call was made in spite of handshake status
if ((session == null || engine_was_closed) && (
handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_WRAP) ||
handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_TASK))) {
return new SSLEngineResult(
getEngineStatus(), handshakeStatus, 0, 0);
}
if (src.remaining() < recordProtocol.getMinRecordSize()) {
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_UNDERFLOW,
getHandshakeStatus(), 0, 0);
}
try {
src.mark();
// check the destination buffers and count their capacity
int capacity = 0;
for (int i=offset; i<offset+length; i++) {
if (dsts[i] == null) {
throw new IllegalStateException(
"Some of the input parameters are null");
}
if (dsts[i].isReadOnly()) {
throw new ReadOnlyBufferException();
}
capacity += dsts[i].remaining();
}
if (capacity < recordProtocol.getDataSize(src.remaining())) {
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_OVERFLOW,
getHandshakeStatus(), 0, 0);
}
recProtIS.setSourceBuffer(src);
// unwrap the record contained in source buffer, pass it
// to appropriate client protocol (alert, handshake, or app)
// and retrieve the type of unwrapped data
int type = recordProtocol.unwrap();
// process the data and return the result
switch (type) {
case ContentType.HANDSHAKE:
case ContentType.CHANGE_CIPHER_SPEC:
if (handshakeProtocol.getStatus().equals(
SSLEngineResult.HandshakeStatus.FINISHED)) {
session = recordProtocol.getSession();
}
break;
case ContentType.APPLICATION_DATA:
break;
case ContentType.ALERT:
if (alertProtocol.isFatalAlert()) {
alertProtocol.setProcessed();
if (session != null) {
session.invalidate();
}
String description = "Fatal alert received "
+ alertProtocol.getAlertDescription();
shutdown();
throw new SSLException(description);
} else {
if (logger != null) {
logger.println("Warning allert has been received: "
+ alertProtocol.getAlertDescription());
}
switch(alertProtocol.getDescriptionCode()) {
case AlertProtocol.CLOSE_NOTIFY:
alertProtocol.setProcessed();
close_notify_was_received = true;
if (!close_notify_was_sent) {
closeOutbound();
closeInbound();
} else {
closeInbound();
shutdown();
}
break;
case AlertProtocol.NO_RENEGOTIATION:
alertProtocol.setProcessed();
if (session == null) {
// message received during the initial
// handshake
throw new AlertException(
AlertProtocol.HANDSHAKE_FAILURE,
new SSLHandshakeException(
"Received no_renegotiation "
+ "during the initial handshake"));
} else {
// just stop the handshake
handshakeProtocol.stop();
}
break;
default:
alertProtocol.setProcessed();
}
}
break;
}
return new SSLEngineResult(getEngineStatus(), getHandshakeStatus(),
recProtIS.consumed(),
// place the app. data (if any) into the dest. buffers
// and get the number of produced bytes:
appData.placeTo(dsts, offset, length));
} catch (BufferUnderflowException e) {
// there was not enought data ource buffer to make complete packet
src.reset();
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_UNDERFLOW,
getHandshakeStatus(), 0, 0);
} catch (AlertException e) {
// fatal alert occured
alertProtocol.alert(AlertProtocol.FATAL, e.getDescriptionCode());
engine_was_closed = true;
src.reset();
if (session != null) {
session.invalidate();
}
// shutdown work will be made after the alert will be sent
// to another peer (by wrap method)
throw e.getReason();
} catch (SSLException e) {
throw e;
} catch (IOException e) {
alertProtocol.alert(AlertProtocol.FATAL,
AlertProtocol.INTERNAL_ERROR);
engine_was_closed = true;
// shutdown work will be made after the alert will be sent
// to another peer (by wrap method)
throw new SSLException(e.getMessage());
}
|
public javax.net.ssl.SSLEngineResult | wrap(java.nio.ByteBuffer[] srcs, int offset, int len, java.nio.ByteBuffer dst)Encodes the application data into SSL/TLS record. If handshake status
of the engine differs from NOT_HANDSHAKING the operation can work
without consuming of the source data.
For more information about TLS record fragmentation see
TLS v 1 specification (http://www.ietf.org/rfc/rfc2246.txt) p 6.2.
if (engine_was_shutteddown) {
return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING, 0, 0);
}
if ((srcs == null) || (dst == null)) {
throw new IllegalStateException(
"Some of the input parameters are null");
}
if (dst.isReadOnly()) {
throw new ReadOnlyBufferException();
}
if (!handshake_started) {
beginHandshake();
}
SSLEngineResult.HandshakeStatus handshakeStatus = getHandshakeStatus();
// If it is an initial handshake or connection closure stage,
// check if this call was made in spite of handshake status
if ((session == null || engine_was_closed) && (
handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_UNWRAP) ||
handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_TASK))) {
return new SSLEngineResult(
getEngineStatus(), handshakeStatus, 0, 0);
}
int capacity = dst.remaining();
int produced = 0;
if (alertProtocol.hasAlert()) {
// we have an alert to be sent
if (capacity < recordProtocol.getRecordSize(2)) {
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_OVERFLOW,
handshakeStatus, 0, 0);
}
byte[] alert_data = alertProtocol.wrap();
// place the alert record into destination
dst.put(alert_data);
if (alertProtocol.isFatalAlert()) {
alertProtocol.setProcessed();
if (session != null) {
session.invalidate();
}
// fatal alert has been sent, so shut down the engine
shutdown();
return new SSLEngineResult(
SSLEngineResult.Status.CLOSED,
SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
0, alert_data.length);
} else {
alertProtocol.setProcessed();
// check if the works on this engine have been done
if (close_notify_was_sent && close_notify_was_received) {
shutdown();
return new SSLEngineResult(SSLEngineResult.Status.CLOSED,
SSLEngineResult.HandshakeStatus.NOT_HANDSHAKING,
0, alert_data.length);
}
return new SSLEngineResult(
getEngineStatus(),
getHandshakeStatus(),
0, alert_data.length);
}
}
if (capacity < recordProtocol.getMinRecordSize()) {
if (logger != null) {
logger.println("Capacity of the destination("
+capacity+") < MIN_PACKET_SIZE("
+recordProtocol.getMinRecordSize()+")");
}
return new SSLEngineResult(SSLEngineResult.Status.BUFFER_OVERFLOW,
handshakeStatus, 0, 0);
}
try {
if (!handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.NEED_WRAP)) {
// so we wraps application data
dataStream.setSourceBuffers(srcs, offset, len);
if ((capacity < SSLRecordProtocol.MAX_SSL_PACKET_SIZE) &&
(capacity < recordProtocol.getRecordSize(
dataStream.available()))) {
if (logger != null) {
logger.println("The destination buffer("
+capacity+") can not take the resulting packet("
+ recordProtocol.getRecordSize(
dataStream.available())+")");
}
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_OVERFLOW,
handshakeStatus, 0, 0);
}
if (remaining_wrapped_data == null) {
remaining_wrapped_data =
recordProtocol.wrap(ContentType.APPLICATION_DATA,
dataStream);
}
if (capacity < remaining_wrapped_data.length) {
// It should newer happen because we checked the destination
// buffer size, but there is a possibility
// (if dest buffer was filled outside)
// so we just remember the data into remaining_wrapped_data
// and will enclose it during the the next call
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_OVERFLOW,
handshakeStatus, dataStream.consumed(), 0);
} else {
dst.put(remaining_wrapped_data);
produced = remaining_wrapped_data.length;
remaining_wrapped_data = null;
return new SSLEngineResult(getEngineStatus(),
handshakeStatus, dataStream.consumed(), produced);
}
} else {
if (remaining_hsh_data == null) {
remaining_hsh_data = handshakeProtocol.wrap();
}
if (capacity < remaining_hsh_data.length) {
// It should newer happen because we checked the destination
// buffer size, but there is a possibility
// (if dest buffer was filled outside)
// so we just remember the data into remaining_hsh_data
// and will enclose it during the the next call
return new SSLEngineResult(
SSLEngineResult.Status.BUFFER_OVERFLOW,
handshakeStatus, 0, 0);
} else {
dst.put(remaining_hsh_data);
produced = remaining_hsh_data.length;
remaining_hsh_data = null;
handshakeStatus = handshakeProtocol.getStatus();
if (handshakeStatus.equals(
SSLEngineResult.HandshakeStatus.FINISHED)) {
session = recordProtocol.getSession();
}
}
return new SSLEngineResult(
getEngineStatus(), getHandshakeStatus(), 0, produced);
}
} catch (AlertException e) {
// fatal alert occured
alertProtocol.alert(AlertProtocol.FATAL, e.getDescriptionCode());
engine_was_closed = true;
if (session != null) {
session.invalidate();
}
// shutdown work will be made after the alert will be sent
// to another peer (by wrap method)
throw e.getReason();
}
|