//2012-03-22 johnpfeiffer modified version of http://blogs.sun.com/andreas/resource/InstallCert.java
// Original found in /etc/java-6-sun/security/cacerts C:\Program Files\Java\jdk1.7.0_03\jre\lib\security\cacerts
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.security.KeyStore;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLException;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509TrustManager;
public class InstallCert
{
String host;
int port;
char[] keystorePassphrase;
KeyStore ks;
public static void main(String[] args) throws Exception
{
CommandLineParameterRequirements required = new CommandLineParameterRequirements( 3 , "version 0.2 Usage: java -jar InstallCert [host] [port] [keystorekeystorePassphrase] \nExample: java -jar server.com 443 changeit" );
if( ! required.isValid( args , System.out ) )
{ System.exit( 1 );
}
InstallCert ic = new InstallCert();
ic.host = args[0];
ic.port = Integer.parseInt( args[1] );
ic.keystorePassphrase = args[2].toCharArray();
String javaHome = System.getProperty( "java.home" );
String fileSeparator = System.getProperty( "file.separator" );
String workingDirectory = javaHome + fileSeparator + "lib" + fileSeparator + "security" + fileSeparator;
String sourceFile = "cacerts";
File source = new File( workingDirectory + fileSeparator + sourceFile );
System.out.println( "DEBUG: Loading existing KeyStore " + source + " ..." );
ic.loadKeystore( source );
X509Certificate[] chain = ic.getChain();
if (chain == null)
{ System.err.println( "Could not obtain server certificate chain" );
return;
}else
{
ic.displayChain( chain );
// Get User Selection of which cert from the Chain to Save
BufferedReader reader = new BufferedReader( new InputStreamReader( System.in ) );
System.out.println( "Enter certificate to add to trusted keystore or 'q' to quit: [1]" );
String line = reader.readLine().trim();
int choice;
try {
choice = (line.length() == 0) ? 0 : Integer.parseInt(line) - 1;
}catch (NumberFormatException e)
{ System.out.println( "KeyStore not changed" );
return;
}
X509Certificate cert = chain[choice];
String alias = ic.host + "-" + (choice + 1);
ic.ks.setCertificateEntry( alias, cert );
String outputFile = "jssecacerts";
File target = new File( workingDirectory + fileSeparator + outputFile );
OutputStream out = new FileOutputStream( target );
ic.ks.store( out , ic.keystorePassphrase );
out.close();
System.out.println( cert );
System.out.println( "DEBUG: Added certificate to keystore " + target + " using alias " + alias );
}
} //end main
private void loadKeystore( File f )
{
try{
InputStream in = new FileInputStream( f );
ks = KeyStore.getInstance( KeyStore.getDefaultType() );
ks.load( in , keystorePassphrase );
in.close();
}catch( Exception e )
{ e.printStackTrace();
System.exit( 1 );
}
}
private X509Certificate[] getChain()
{
X509Certificate[] chain = null;
try{
SSLContext context = SSLContext.getInstance( "TLS" );
TrustManagerFactory tmf = TrustManagerFactory.getInstance( TrustManagerFactory.getDefaultAlgorithm() );
tmf.init( ks );
X509TrustManager defaultTrustManager = (X509TrustManager)tmf.getTrustManagers()[0];
SavingTrustManager tm = new SavingTrustManager(defaultTrustManager);
context.init( null, new TrustManager[] {tm}, null );
SSLSocketFactory factory = context.getSocketFactory();
System.out.println( "DEBUG: Opening connection to " + host + ":" + port + " ..." );
SSLSocket socket = (SSLSocket)factory.createSocket( host , port );
socket.setSoTimeout( 10000 );
try{
System.out.println( "DEBUG: Starting SSL handshake ..." );
socket.startHandshake();
socket.close();
// System.out.println( "No errors, certificate is already trusted" );
} catch( SSLException e )
{ e.printStackTrace(System.out);
}
chain = tm.chain;
}catch( Exception e )
{ e.printStackTrace();
}
return chain;
}
private void displayChain( X509Certificate[] chain ) throws Exception
{
MessageDigest sha1 = null;
MessageDigest md5 = null;
System.out.println( "Server sent " + chain.length + " certificate(s):" );
try{
sha1 = MessageDigest.getInstance( "SHA1" );
md5 = MessageDigest.getInstance( "MD5" );
}catch( NoSuchAlgorithmException nsa )
{ nsa.printStackTrace();
}
for (int i = 0; i < chain.length; i++)
{
X509Certificate cert = chain[i];
System.out.println( " " + (i + 1) + " Subject " + cert.getSubjectDN() );
System.out.println( " Issuer " + cert.getIssuerDN() );
sha1.update( cert.getEncoded() );
System.out.println( " sha1 " + toHexString( sha1.digest() ) );
md5.update(cert.getEncoded());
System.out.println( " md5 " + toHexString( md5.digest() ) );
}
}
private static final char[] HEXDIGITS = "0123456789abcdef".toCharArray();
private static String toHexString(byte[] bytes)
{
StringBuilder sb = new StringBuilder(bytes.length * 3);
for (int b : bytes)
{
b &= 0xff;
sb.append(HEXDIGITS[b >> 4]);
sb.append(HEXDIGITS[b & 15]);
sb.append(' ');
}
return sb.toString();
}
private static class SavingTrustManager implements X509TrustManager
{
private final X509TrustManager tm;
private X509Certificate[] chain;
SavingTrustManager(X509TrustManager tm)
{
this.tm = tm;
}
public X509Certificate[] getAcceptedIssuers()
{
throw new UnsupportedOperationException();
}
public void checkClientTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
throw new UnsupportedOperationException();
}
public void checkServerTrusted(X509Certificate[] chain, String authType)
throws CertificateException
{
this.chain = chain;
tm.checkServerTrusted(chain, authType);
}
}
} //end class