blob: 5accd5c7dcfa28ad36eb873f995e1931f9fcf794 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one or more
* contributor license agreements. See the NOTICE file distributed with
* this work for additional information regarding copyright ownership.
* The ASF licenses this file to You under the Apache License, Version 2.0
* (the "License"); you may not use this file except in compliance with
* the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.harmony.xnet.provider.jsse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.Arrays;
import javax.net.ssl.HandshakeCompletedEvent;
import javax.net.ssl.HandshakeCompletedListener;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLSocket;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;
/**
* SSLSocketImplTest
*/
public class SSLSocketFunctionalTest extends TestCase {
/**
* The cipher suites used for functionality testing.
*/
private String[] cipher_suites = {
"RSA_WITH_RC4_128_MD5",
"RSA_WITH_DES_CBC_SHA",
"DH_anon_EXPORT_WITH_DES40_CBC_SHA"
};
// turn on/off the debug logging
private boolean doLog = false;
/**
* Sets up the test case.
*/
@Override
public void setUp() throws Exception {
if (doLog) {
System.out.println("========================");
System.out.println("====== Running the test: " + getName());
System.out.println("========================");
}
}
public void testContextInitialized2() throws Throwable {
doTestSelfInteraction(JSSETestData.getContext());
}
public void doTestInteraction(SSLContext context, SSLContext ctx_other)
throws Throwable {
SSLContext ctx1, ctx2;
ctx1 = context;
ctx2 = ctx_other;
int k = 1;
SSLServerSocket ssocket = (SSLServerSocket) ctx1
.getServerSocketFactory().createServerSocket(0);
ssocket.setUseClientMode(false);
ssocket.setEnabledCipherSuites(
((k & 1) > 0)
? new String[] { "TLS_" + cipher_suites[0] }
: new String[] { "SSL_" + cipher_suites[0] });
SSLSocket csocket = (SSLSocket) ctx2
.getSocketFactory().createSocket("localhost",
ssocket.getLocalPort());
csocket.setEnabledProtocols(new String[] { "TLSv1" });
csocket.setUseClientMode(true);
csocket.setEnabledCipherSuites(
(((k & 2) >> 1) > 0)
? new String[] { "TLS_" + cipher_suites[0] }
: new String[] { "SSL_" + cipher_suites[0] });
doTest(ssocket, csocket);
}
public void _doTestInteraction(SSLContext context, SSLContext ctx_other)
throws Throwable {
for (int i = 0; i < cipher_suites.length; i++) {
if (doLog) {
System.out.println("======== Checking the work on cipher: "
+ cipher_suites[i]);
}
SSLContext ctx1, ctx2;
// k: 00, 01, 10, 11;
// where 1 means implementation under the test,
// 0 - another implementation to interract with
for (int k = 0; k < 4; k++) {
if (doLog) {
System.out.println("======== " + (k & 1) + " " + ((k & 2) >> 1));
}
ctx1 = ((k & 1) > 0) ? context : ctx_other;
ctx2 = (((k & 2) >> 1) > 0) ? context : ctx_other;
SSLServerSocket ssocket = (SSLServerSocket) ctx1
.getServerSocketFactory().createServerSocket(0);
ssocket.setUseClientMode(false);
ssocket.setEnabledCipherSuites(
((k & 1) > 0)
? new String[] { "TLS_" + cipher_suites[i] }
: new String[] { "SSL_" + cipher_suites[i] });
SSLSocket csocket = (SSLSocket) ctx2
.getSocketFactory().createSocket("localhost",
ssocket.getLocalPort());
csocket.setEnabledProtocols(new String[] { "TLSv1" });
csocket.setUseClientMode(true);
csocket.setEnabledCipherSuites(
(((k & 2) >> 1) > 0)
? new String[] { "TLS_" + cipher_suites[i] }
: new String[] { "SSL_" + cipher_suites[i] });
doTest(ssocket, csocket);
}
}
}
/**
* Tests the interaction with other implementation.
*/
public void doTestSelfInteraction(SSLContext context)
throws Throwable {
String[] protocols = { "SSLv3", "TLSv1" };
for (int i = 0; i < cipher_suites.length; i++) {
for (int j = 0; j < 2; j++) {
if (doLog) {
System.out.println("======= " + cipher_suites[i]);
}
SSLServerSocket ssocket = (SSLServerSocket) context
.getServerSocketFactory().createServerSocket(0);
ssocket.setUseClientMode(false);
ssocket.setEnabledProtocols(new String[] { protocols[j] });
ssocket.setEnabledCipherSuites(
new String[] { "TLS_" + cipher_suites[i] });
SSLSocket csocket = (SSLSocket) context
.getSocketFactory().createSocket("localhost",
ssocket.getLocalPort());
csocket.setEnabledProtocols(new String[] { protocols[j] });
csocket.setUseClientMode(true);
csocket.setEnabledCipherSuites(
new String[] { "TLS_" + cipher_suites[i] });
doTest(ssocket, csocket);
}
}
}
private static class HandshakeListener
implements HandshakeCompletedListener {
boolean compleated = false;
public void handshakeCompleted(HandshakeCompletedEvent event) {
compleated = true;
}
}
/**
* Performs SSL connection between the sockets
*
* @return
*/
public void doTest(SSLServerSocket ssocket, SSLSocket csocket)
throws Throwable {
final String server_message = "Hello from SSL Server Socket!";
final String client_message = "Hello from SSL Socket!";
Thread server = null;
Thread client = null;
final Throwable[] throwed = new Throwable[1];
try {
final SSLServerSocket ss = ssocket;
final SSLSocket s = csocket;
server = new Thread() {
@Override
public void run() {
InputStream is = null;
OutputStream os = null;
SSLSocket s = null;
try {
s = (SSLSocket) ss.accept();
if (doLog) {
System.out.println("Socket accepted: " + s);
}
is = s.getInputStream();
os = s.getOutputStream();
// send the message to the client
os.write(server_message.getBytes());
// read the response
byte[] buff = new byte[client_message.length()];
int len = is.read(buff);
if (doLog) {
System.out.println("Received message of length "
+ len + ": '" + new String(buff, 0, len) + "'");
}
assertTrue("Read message does not equal to expected",
Arrays.equals(client_message.getBytes(), buff));
os.write(-1);
assertEquals("Read data differs from expected",
255, is.read());
if (doLog) {
System.out.println("Server is closed: "
+ s.isClosed());
}
assertEquals("Returned value should be -1",
// initiate an exchange of closure alerts
-1, is.read());
if (doLog) {
System.out.println("Server is closed: "
+ s.isClosed());
}
assertEquals("Returned value should be -1",
// initiate an exchange of closure alerts
-1, is.read());
} catch (Throwable e) {
synchronized (throwed) {
if (doLog) {
e.printStackTrace();
}
if (throwed[0] == null) {
throwed[0] = e;
}
}
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException ex) {
}
try {
if (os != null) {
os.close();
}
} catch (IOException ex) {
}
try {
if (s != null) {
s.close();
}
} catch (IOException ex) {
}
}
}
};
client = new Thread() {
@Override
public void run() {
InputStream is = null;
OutputStream os = null;
try {
assertTrue("Client was not connected", s.isConnected());
if (doLog) {
System.out.println("Client connected");
}
is = s.getInputStream();
os = s.getOutputStream();
s.startHandshake();
if (doLog) {
System.out.println("Client: HS was done");
}
// read the message from the server
byte[] buff = new byte[server_message.length()];
int len = is.read(buff);
if (doLog) {
System.out.println("Received message of length "
+ len + ": '" + new String(buff, 0, len) + "'");
}
assertTrue("Read message does not equal to expected",
Arrays.equals(server_message.getBytes(), buff));
// send the response
buff = (" " + client_message + " ").getBytes();
os.write(buff, 1, buff.length - 2);
assertEquals("Read data differs from expected",
255, is.read());
os.write(-1);
if (doLog) {
System.out.println("\n======== Closing ========");
}
if (doLog) {
System.out.println("Client is closed: "
+ s.isClosed());
}
s.close();
if (doLog) {
System.out.println("Client is closed: "
+ s.isClosed());
}
} catch (Throwable e) {
synchronized (throwed) {
if (doLog) {
e.printStackTrace();
}
if (throwed[0] == null) {
throwed[0] = e;
}
}
} finally {
try {
if (is != null) {
is.close();
}
} catch (IOException ex) {
}
try {
if (os != null) {
os.close();
}
} catch (IOException ex) {
}
try {
if (s != null) {
s.close();
}
} catch (IOException ex) {
}
}
}
};
server.start();
client.start();
while (server.isAlive() || client.isAlive()) {
if (throwed[0] != null) {
throw throwed[0];
}
try {
Thread.sleep(500);
} catch (Exception e) {
}
}
} finally {
if (server != null) {
server.stop();
}
if (client != null) {
client.stop();
}
}
if (throwed[0] != null) {
throw throwed[0];
}
}
public static Test suite() {
return new TestSuite(SSLSocketFunctionalTest.class);
}
}