package org.bouncycastle.test.est.examples; import java.io.File; import java.security.Provider; import java.security.Security; import java.security.cert.TrustAnchor; import java.util.Set; import javax.net.ssl.SSLSession; import javax.net.ssl.X509TrustManager; import org.bouncycastle.cert.X509CertificateHolder; import org.bouncycastle.est.CACertsResponse; import org.bouncycastle.est.ESTService; import org.bouncycastle.est.jcajce.JcaJceUtils; import org.bouncycastle.est.jcajce.JsseDefaultHostnameAuthorizer; import org.bouncycastle.est.jcajce.JsseESTServiceBuilder; import org.bouncycastle.jce.provider.BouncyCastleProvider; /** * CaCertsExample gives examples of fetching CA certs. */ public class CaCertsExample { public CaCertsExample(String[] args) throws Exception { if (args.length == 0) { printArguments(); System.exit(1); } Security.addProvider(new BouncyCastleProvider()); File trustAnchorFile = null; String serverRootUrl = null; boolean printTLSCerts = false; String tlsVersion = "TLS"; String tlsProvider = "SunJSSE"; String tlsProviderClass = null; boolean noNameVerifier = false; String label = null; int timeout = 0; String suffixList = null; try { for (int t = 0; t < args.length; t++) { String arg = args[t]; if (arg.equals("-t")) { trustAnchorFile = ExampleUtils.nextArgAsFile("Trust Anchor File", args, t); t += 1; } else if (arg.equals("-u")) { serverRootUrl = ExampleUtils.nextArgAsString("Server Hostname", args, t); t += 1; } else if (arg.equals("--printTLS")) { printTLSCerts = true; } else if (arg.equals("--tls")) { tlsVersion = ExampleUtils.nextArgAsString("TLS version", args, t); t += 1; } else if (arg.equals("--tlsProvider")) { tlsProvider = ExampleUtils.nextArgAsString("TLS Provider", args, t); t += 1; tlsProviderClass = ExampleUtils.nextArgAsString("TLS Provider Class", args, t); t += 1; } else if (arg.equals("--to")) { timeout = ExampleUtils.nextArgAsInteger("Timeout", args, t); t += 1; } else if (arg.equals("--no-name-verifier")) { noNameVerifier = true; } else if (arg.equals("--label")) { label = ExampleUtils.nextArgAsString("CA Label", args, t); t += 1; } else if (arg.equals("--sl")) { suffixList = ExampleUtils.nextArgAsString("Suffix List", args, t); t += 1; } else { throw new IllegalArgumentException("Unknown argument " + arg); } } } catch (IllegalArgumentException ilex) { System.err.println(ilex.getMessage()); printArguments(); System.exit(1); } if (serverRootUrl == null) { System.err.println("Server url (-u) must be defined."); System.exit(-1); } if (suffixList == null) { System.err.println("Known Suffix List (--sl) must be defined."); System.exit(-1); } // // Read the trust anchor. // Set<TrustAnchor> trustAnchors = null; if (trustAnchorFile != null) { trustAnchors = ExampleUtils.toTrustAnchor(ExampleUtils.readPemCertificates(trustAnchorFile)); } if (tlsProviderClass != null) { Security.addProvider((Provider)Class.forName(tlsProviderClass).newInstance()); } //SSLSocketFactoryCreatorBuilder sfcb = null; // // Make est client builder // X509TrustManager[] trustManagers = null; JsseESTServiceBuilder builder = null; if (trustAnchors != null && !trustAnchors.isEmpty()) { trustManagers = JcaJceUtils.getCertPathTrustManager(trustAnchors, null); } else { // In this case we do not have trust anchors so create a builder for a client talking to an untrusted server. trustManagers = new X509TrustManager[]{JcaJceUtils.getTrustAllTrustManager()}; } builder = new JsseESTServiceBuilder(serverRootUrl, trustManagers); if (noNameVerifier) { builder.withHostNameAuthorizer(null); } else { builder.withHostNameAuthorizer(new JsseDefaultHostnameAuthorizer(SuffixList.loadSuffixes(suffixList))); } builder.withTimeout(timeout); builder.withLabel(label); builder.withTLSVersion(tlsVersion); builder.withProvider(tlsProvider); // // Make a client. // ESTService estService = builder.build(); CACertsResponse caCertsResponse = estService.getCACerts(); // // We must check the response is trusted. If it is not trusted we have fetched the CAs // without verifying the source using a trust anchor. At this point an out of band 'ie user' must // accept the CA certs returned. // This is congruent with <https://tools.ietf.org/html/rfc7030#section-4.1.1> Bootstrapping. // javax.security.cert.X509Certificate[] certs = ((SSLSession)caCertsResponse.getSession()).getPeerCertificateChain(); if (!caCertsResponse.isTrusted()) { System.out.println(); for (javax.security.cert.X509Certificate cert : certs) { // // Limited the amount of information for the sake of the example. // The default too string prints everything and is hard to follow. // It is at this point developers should present users with enough information to make an informed // decision. // System.out.println("Subject: " + cert.getSubjectDN()); System.out.println("Issuer: " + cert.getIssuerDN()); System.out.println("Serial Number: " + cert.getSerialNumber()); System.out.println("Not Before: " + cert.getNotBefore()); System.out.println("Not After: " + cert.getNotAfter()); System.out.println("Signature Algorithm: " + cert.getSigAlgName()); System.out.println(); System.out.println(cert.toString()); } System.out.println("As part of the TLS handshake, the server tendered to us these certificates."); if (!ExampleUtils.userSaysYes("Do you accept these certificates (y,n) ?")) { System.exit(0); } System.out.println(); System.out.println("The untrusted server tendered to us these certificates as CA certs"); for (X509CertificateHolder holder : ESTService.storeToArray(caCertsResponse.getCertificateStore())) { // // Limited the amount of information for the sake of the example. // The default too string prints everything and is hard to follow. // It is at this point developers should present users with enough information to make an informed // decision. // System.out.println("Subject: " + holder.getSubject()); System.out.println("Issuer: " + holder.getIssuer()); System.out.println("Serial Number: " + holder.getSerialNumber()); System.out.println("Not Before: " + holder.getNotBefore()); System.out.println("Not After: " + holder.getNotAfter()); System.out.println("Signature Algorithm: " + holder.getSignatureAlgorithm()); System.out.println(); System.out.println(ExampleUtils.toJavaX509Certificate(holder)); } if (!ExampleUtils.userSaysYes("Do you accept these certificates (y,n) ?")) { System.exit(0); } } System.out.println("Fetched CA Certs:\n\n"); for (X509CertificateHolder holder : ESTService.storeToArray(caCertsResponse.getCertificateStore())) { System.out.println(ExampleUtils.toPem(holder)); } if (printTLSCerts) { System.out.println("\n TLS Certificates"); System.out.println(); for (javax.security.cert.X509Certificate cert : certs) { System.out.println(ExampleUtils.toPem(new X509CertificateHolder(cert.getEncoded()))); } } } public static void main(String[] args) throws Exception { try { new CaCertsExample(args); } catch (Exception ex) { System.out.println("\n\n-----------------"); System.out.println(ex.getMessage()); System.out.println("-----------------\n\n"); throw ex; } } public void printArguments() { System.out.println("-t <file> Trust anchor file. (PEM)"); System.out.println("-u <url> Server Hostname."); System.out.println("--printTLS <url> Print TLS certificates as PEM format"); System.out.println("--tls <version> Use this TLS version when creating socket factory, Eg TLSv1.2"); System.out.println("--tlsProvider <provider> <class> The JSSE Provider."); System.out.println("--to <milliseconds> Timeout in milliseconds."); System.out.println("--no-name-verifier No hostname verifier."); System.out.println("--label <ca label> CA Label."); System.out.println("--sl <file> List of known suffixes."); } }