in modules/x-net/src/main/java/org/apache/harmony/xnet/provider/jsse/ClientHandshakeImpl.java [140:319]
public void unwrap(byte[] bytes) {
if (this.delegatedTaskErr != null) {
Exception e = this.delegatedTaskErr;
this.delegatedTaskErr = null;
this.fatalAlert(AlertProtocol.HANDSHAKE_FAILURE, "Error in delegated task", e);
}
int handshakeType;
io_stream.append(bytes);
while (io_stream.available() > 0) {
io_stream.mark();
int length;
try {
handshakeType = io_stream.read();
length = io_stream.readUint24();
if (io_stream.available() < length) {
io_stream.reset();
return;
}
switch (handshakeType) {
case 0: // HELLO_REQUEST
// we don't need to take this message into account
// during FINISH message verification, so remove it
io_stream.removeFromMarkedPosition();
if (clientHello != null
&& (clientFinished == null || serverFinished == null)) {
//currently negotiating - ignore
break;
}
// renegotiate
if (session.isValid()) {
session = (SSLSessionImpl) session.clone();
isResuming = true;
startSession();
} else {
// if SSLSession is invalidated (e.g. timeout limit is
// exceeded) connection can't resume the session.
renegotiateNewSession();
}
break;
case 2: // SERVER_HELLO
if (clientHello == null || serverHello != null) {
unexpectedMessage();
return;
}
serverHello = new ServerHello(io_stream, length);
//check protocol version
ProtocolVersion servProt = ProtocolVersion
.getByVersion(serverHello.server_version);
String[] enabled = parameters.getEnabledProtocols();
find: {
for (int i = 0; i < enabled.length; i++) {
if (servProt.equals(ProtocolVersion
.getByName(enabled[i]))) {
break find;
}
}
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"Bad server hello protocol version");
}
// check compression method
if (serverHello.compression_method != 0) {
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"Bad server hello compression method");
}
//check cipher_suite
CipherSuite[] enabledSuites = parameters.enabledCipherSuites;
find: {
for (int i = 0; i < enabledSuites.length; i++) {
if (serverHello.cipher_suite
.equals(enabledSuites[i])) {
break find;
}
}
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"Bad server hello cipher suite");
}
if (isResuming) {
if (serverHello.session_id.length == 0) {
// server is not willing to establish the new connection
// using specified session
isResuming = false;
} else if (!Arrays.equals(serverHello.session_id, clientHello.session_id)) {
isResuming = false;
} else if (!session.protocol.equals(servProt)) {
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"Bad server hello protocol version");
} else if (!session.cipherSuite
.equals(serverHello.cipher_suite)) {
fatalAlert(AlertProtocol.HANDSHAKE_FAILURE,
"Bad server hello cipher suite");
}
if (serverHello.server_version[1] == 1) {
computerReferenceVerifyDataTLS("server finished");
} else {
computerReferenceVerifyDataSSLv3(SSLv3Constants.server);
}
}
session.protocol = servProt;
recordProtocol.setVersion(session.protocol.version);
session.cipherSuite = serverHello.cipher_suite;
session.id = serverHello.session_id.clone();
session.serverRandom = serverHello.random;
break;
case 11: // CERTIFICATE
if (serverHello == null || serverKeyExchange != null
|| serverCert != null || isResuming) {
unexpectedMessage();
return;
}
serverCert = new CertificateMessage(io_stream, length);
break;
case 12: // SERVER_KEY_EXCHANGE
if (serverHello == null || serverKeyExchange != null
|| isResuming) {
unexpectedMessage();
return;
}
serverKeyExchange = new ServerKeyExchange(io_stream,
length, session.cipherSuite.keyExchange);
break;
case 13: // CERTIFICATE_REQUEST
if (serverCert == null || certificateRequest != null
|| session.cipherSuite.isAnonymous() || isResuming) {
unexpectedMessage();
return;
}
certificateRequest = new CertificateRequest(io_stream,
length);
break;
case 14: // SERVER_HELLO_DONE
if (serverHello == null || serverHelloDone != null
|| isResuming) {
unexpectedMessage();
return;
}
serverHelloDone = new ServerHelloDone(io_stream, length);
if (this.nonBlocking) {
delegatedTasks.add(new DelegatedTask(new PrivilegedExceptionAction<Void>() {
public Void run() throws Exception {
processServerHelloDone();
return null;
}
}, this, AccessController.getContext()));
return;
}
processServerHelloDone();
break;
case 20: // FINISHED
if (!changeCipherSpecReceived) {
unexpectedMessage();
return;
}
serverFinished = new Finished(io_stream, length);
verifyFinished(serverFinished.getData());
session.lastAccessedTime = System.currentTimeMillis();
parameters.getClientSessionContext().putSession(session);
if (isResuming) {
sendChangeCipherSpec();
} else {
session.lastAccessedTime = System.currentTimeMillis();
status = FINISHED;
}
// XXX there is no cleanup work
break;
default:
unexpectedMessage();
return;
}
} catch (IOException e) {
// io stream dosn't contain complete handshake message
io_stream.reset();
return;
}
}
}