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"); } }