package org.bouncycastle.test.est;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.InetSocketAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.security.Key;
import java.security.KeyFactory;
import java.security.KeyStore;
import java.security.PrivateKey;
import java.security.SecureRandom;
import java.security.cert.Certificate;
import java.security.cert.CertificateFactory;
import java.security.spec.PKCS8EncodedKeySpec;
import java.util.List;
import java.util.Random;
import java.util.concurrent.CountDownLatch;
import java.util.concurrent.TimeUnit;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.security.cert.X509Certificate;
import org.bouncycastle.cert.X509CertificateHolder;
import org.bouncycastle.util.io.pem.PemReader;
/**
* Accept a connection and responds with a pre baked message.
*/
public class HttpResponder
implements Runnable
{
private CountDownLatch finished = new CountDownLatch(1);
private CountDownLatch ready = new CountDownLatch(1);
private CountDownLatch close = new CountDownLatch(1);
private int port;
private byte[] response;
private String tlsProtocol = null;
ServerSocket serverSocket = null;
List<String> lineBuffer = null;
private String[] cipherSuites;
Object[] creds = null;
public HttpResponder(byte[] response, List<String> lineBuffer)
{
this.response = response;
this.lineBuffer = lineBuffer;
}
public HttpResponder(byte[] response)
{
this.response = response;
}
public HttpResponder(List<String> lineBuffer)
{
this.lineBuffer = lineBuffer;
}
public HttpResponder()
{
}
public void run()
{
Random rand = new Random();
Socket sock = null;
try
{
int t = 10;
for (; t >= 0; t--)
{
port = 8000 + rand.nextInt(1000);
KeyStore ks = KeyStore.getInstance("JKS");
ks.load(null, "password".toCharArray());
if (creds == null)
{
creds = readCertAndKey(ESTServerUtils.makeRelativeToServerHome("estCA/private/estservercertandkey.pem"));
ks.setKeyEntry("server", KeyFactory.getInstance("EC").generatePrivate(((PKCS8EncodedKeySpec)creds[1])), "password".toCharArray(), new Certificate[]{(Certificate)creds[0]});
}
else
{
ks.setKeyEntry("server", (Key)creds[1], "password".toCharArray(), new Certificate[]{(Certificate)creds[0]});
}
KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance(KeyManagerFactory.getDefaultAlgorithm());
keyManagerFactory.init(ks, "password".toCharArray());
SSLContext sslContext = SSLContext.getInstance("TLS");
sslContext.init(keyManagerFactory.getKeyManagers(), null, new SecureRandom());
SSLServerSocketFactory fact = sslContext.getServerSocketFactory();
serverSocket = sslContext.getServerSocketFactory().createServerSocket();
// for (String s : ((SSLServerSocket)serverSocket).getSupportedCipherSuites())
// {
// if (s.contains("_DES"))
// {
// System.out.println(s);
// }
// }
if (cipherSuites != null)
{
((SSLServerSocket)serverSocket).setEnabledCipherSuites(cipherSuites);
}
if (tlsProtocol != null)
{
((SSLServerSocket)serverSocket).setEnabledProtocols(new String[]{tlsProtocol});
}
try
{
serverSocket.bind(new InetSocketAddress(port));
}
catch (IOException ioex)
{
continue;
}
break;
}
if (t <= 0)
{
throw new RuntimeException("Could not open test server socket.");
}
ready.countDown();
sock = serverSocket.accept();
if (lineBuffer != null)
{
BufferedReader bin = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String line = null;
while ((line = bin.readLine()) != null && line.length() > 0)
{
lineBuffer.add(line);
}
}
if (response != null)
{
OutputStream os = sock.getOutputStream();
os.write(response);
os.flush();
close.await(60, TimeUnit.SECONDS);
os.close();
sock.close();
}
}
catch (InterruptedException ie)
{
try
{
sock.close();
}
catch (IOException e)
{
e.printStackTrace();
}
}
catch (Exception e)
{
e.printStackTrace();
}
finally
{
try
{
serverSocket.close();
}
catch (IOException e)
{
e.printStackTrace();
}
finished.countDown();
}
}
public int open(byte[] response)
throws Exception
{
this.response = response;
Thread t = new Thread(this);
t.setPriority(Thread.MIN_PRIORITY);
t.start();
ready.await(5, TimeUnit.SECONDS);
return port;
}
public void close()
{
close.countDown();
}
public String[] getSupportedCipherSuites()
{
return ((SSLServerSocket)serverSocket).getSupportedCipherSuites();
}
public String[] getEnabledSuites()
{
return ((SSLServerSocket)serverSocket).getEnabledCipherSuites();
}
public void setCipherSuites(String[] cipherSuites)
{
this.cipherSuites = cipherSuites;
}
public CountDownLatch getFinished()
{
return finished;
}
public HttpResponder withTlsProtocol(String prot)
{
this.tlsProtocol = prot;
return this;
}
public Object[] readCertAndKey(File path)
throws Exception
{
Object[] out = new Object[2];
FileReader fr = new FileReader(path);
PemReader reader = new PemReader(fr);
out[0] = toJavaX509Certificate(new X509CertificateHolder(reader.readPemObject().getContent()));
out[1] = new PKCS8EncodedKeySpec(reader.readPemObject().getContent());
reader.close();
fr.close();
return out;
}
public HttpResponder withCreds(java.security.cert.X509Certificate cert, PrivateKey aPrivate)
{
this.creds = new Object[]{cert, aPrivate};
return this;
}
public java.security.cert.X509Certificate toJavaX509Certificate(Object o)
throws Exception
{
CertificateFactory fac = CertificateFactory.getInstance("X509");
if (o instanceof X509CertificateHolder)
{
return (java.security.cert.X509Certificate)fac.generateCertificate(new ByteArrayInputStream(((X509CertificateHolder)o).getEncoded()));
}
else if (o instanceof X509Certificate)
{
return (java.security.cert.X509Certificate)fac.generateCertificate(new ByteArrayInputStream(((X509Certificate)o).getEncoded()));
}
else if (o instanceof java.security.cert.X509Certificate)
{
return (java.security.cert.X509Certificate)o;
}
throw new IllegalArgumentException("Object not X509CertificateHolder, javax..X509Certificate or java...X509Certificate");
}
}