Skip to content

Commit

Permalink
adding detailed output (#6)
Browse files Browse the repository at this point in the history
  • Loading branch information
jtgasper3 authored and SavvasMisaghMoayyed committed May 11, 2018
1 parent f987d22 commit df2ae75
Show file tree
Hide file tree
Showing 3 changed files with 182 additions and 10 deletions.
30 changes: 29 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ mvn clean package
- Run:

```
java -jar <jar-file-name> <https://address.server.edu> [timeout]
java -jar <jar-file-name> [--detailed] <https://address.server.edu> [timeout]
```

## Sample
Expand Down Expand Up @@ -72,3 +72,31 @@ Caused by: sun.security.provider.certpath.SunCertPathBuilderException: unable to
... 18 more
```

### Detailed (--forced) Dump

```
INFO - Received host address https://expired.badssl.com/
INFO - Setting connection timeout to 5 second(s).
INFO - HTTPS Connection: setting custom handler
INFO - Trying to connect to https://expired.badssl.com/
INFO - Response status code received 200
INFO - Detected Truststore: SunJSSE
INFO - Trusted issuers found: 104
INFO - Server provided certs:
INFO - subject: CN=*.badssl.com, OU=PositiveSSL Wildcard, OU=Domain Control Validated
INFO - issuer: CN=COMODO RSA Domain Validation Secure Server CA, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
INFO - expiration: Wed Apr 08 17:00:00 PDT 2015 - Sun Apr 12 16:59:59 PDT 2015 (invalid)
INFO - trust anchor not matched in trust store (which is expected of the host certificate that is part of a chain)
INFO - ---
INFO - subject: CN=COMODO RSA Domain Validation Secure Server CA, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
INFO - issuer: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
INFO - expiration: Tue Feb 11 16:00:00 PST 2014 - Sun Feb 11 15:59:59 PST 2029 (valid)
INFO - trust anchor matched found: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
INFO - ---
INFO - subject: CN=COMODO RSA Certification Authority, O=COMODO CA Limited, L=Salford, ST=Greater Manchester, C=GB
INFO - issuer: CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE
INFO - expiration: Tue May 30 03:48:38 PDT 2000 - Sat May 30 03:48:38 PDT 2020 (valid)
INFO - trust anchor matched found: CN=AddTrust External CA Root, OU=AddTrust External TTP Network, O=AddTrust AB, C=SE
INFO - ---
INFO - Completed. See the info above for details.
```
10 changes: 9 additions & 1 deletion pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
<modelVersion>4.0.0</modelVersion>
<groupId>net.unicon</groupId>
<artifactId>java-keystore-test</artifactId>
<version>0.0.1</version>
<version>0.1.0</version>
<name>Java keystore test</name>
<packaging>jar</packaging>
<description>Java CLI utility to execute outbound HTTPS calls.</description>
Expand All @@ -28,6 +28,14 @@
</execution>
</executions>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-compiler-plugin</artifactId>
<configuration>
<source>1.6</source>
<target>1.6</target>
</configuration>
</plugin>
</plugins>
</build>
</project>
152 changes: 144 additions & 8 deletions src/main/java/net/unicon/Test.java
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
import org.springframework.boot.ApplicationRunner;
import org.springframework.boot.SpringApplication;

import javax.net.ssl.*;
import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
Expand All @@ -14,11 +15,15 @@
import java.net.Proxy;
import java.net.Proxy.Type;
import java.net.InetSocketAddress;


import java.security.*;
import java.security.cert.*;
import java.security.cert.Certificate;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

public class Test implements ApplicationRunner {
String USAGE = "Usage: java Test [--proxy=<http://proxy.example.com:port>] <https://address.server.edu> [timeout]";
String USAGE = "Usage: java Test [--proxy=<http://proxy.example.com:port>] [--forced] <https://address.server.edu> [timeout]";
protected final Logger logger = LoggerFactory.getLogger(this.getClass());

public static void main(String[] args) throws Exception {
Expand All @@ -27,7 +32,7 @@ public static void main(String[] args) throws Exception {

public void run(ApplicationArguments args) throws Exception {
System.setProperty("java.net.preferIPv4Stack", "true");

URLConnection conn = null;
try {
if (args.getNonOptionArgs().size() != 1 && args.getNonOptionArgs().size() != 2) {
logger.warn(USAGE);
Expand All @@ -36,7 +41,7 @@ public void run(ApplicationArguments args) throws Exception {

logger.info("Received host address " + args.getNonOptionArgs().get(0));
URL constructedUrl = new URL(args.getNonOptionArgs().get(0));
URLConnection conn;

if (args.containsOption("proxy")) {
if (args.getOptionValues("proxy").size() != 1) {
logger.warn(USAGE);
Expand All @@ -54,8 +59,14 @@ public void run(ApplicationArguments args) throws Exception {
} else {
conn.setConnectTimeout(5000);
}

logger.info("Setting connection timeout to " + conn.getConnectTimeout() / 1000 + " second(s).");

if (conn instanceof HttpsURLConnection && args.containsOption("forced")) {
((HttpsURLConnection) conn).setSSLSocketFactory(getSSLContext().getSocketFactory());
logger.info("HTTPS Connection: setting custom handler");
}

logger.info("Trying to connect to " + args.getNonOptionArgs().get(0));
InputStreamReader reader = new InputStreamReader(conn.getInputStream(), "UTF-8");
BufferedReader in = new BufferedReader(reader);
Expand All @@ -67,18 +78,143 @@ public void run(ApplicationArguments args) throws Exception {
logger.info("Response status code received " + code);
}



if (args.containsOption("forced")) {
connectionReport(conn);
logger.info("Completed. See the info above for details.");
} else{
logger.info("Great! It worked.");
}

in.close();
reader.close();

logger.info("Great! It worked.");

} catch (Exception e) {
logger.info("Could not connect to the host address " + args.getNonOptionArgs().get(0));
logger.info("The error is: " + e.getMessage());
logger.info("Here are the details:");
logger.info("Here are the exception details:");
logger.error(e.getMessage(), e);
logger.info("Run again with '--forced'.");
throw new RuntimeException(e);
}
}

protected void connectionReport(URLConnection connection) {
if (!(connection instanceof HttpsURLConnection)) {
logger.info("This is not an HTTPS-based connection.");
return;
}

X509TrustManager[] trustManagers = getSystemTrustManagers();
HttpsURLConnection httpsConnection = (HttpsURLConnection)connection;
Certificate[] certificates;

try {
certificates = httpsConnection.getServerCertificates();
} catch (SSLPeerUnverifiedException e) {
logger.error(e.getMessage(), e);
throw new RuntimeException(e);
}

X509Certificate[] serverCertificates = Arrays.copyOf(certificates, certificates.length, X509Certificate[].class);

logger.info("Server provided certs: ");
for (X509Certificate certificate : serverCertificates) {

String validity;
try {
certificate.checkValidity();
validity = "valid";
} catch (CertificateExpiredException e) {
validity = "invalid";
} catch (CertificateNotYetValidException e) {
validity = "invalid";
}

logger.info(" subject: {}", certificate.getSubjectDN().getName());
logger.info(" issuer: {}", certificate.getIssuerDN().getName());
logger.info(" expiration: {} - {} ({})", certificate.getNotBefore(), certificate.getNotAfter(), validity);
logger.info(" trust anchor {}", checkTrustedCertStatus(certificate, trustManagers));
logger.info("---");
}
}

protected X509TrustManager[] getSystemTrustManagers() {
TrustManagerFactory trustManagerFactory = null;
try {
trustManagerFactory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
trustManagerFactory.init((KeyStore)null);
} catch (NoSuchAlgorithmException e) {

} catch (KeyStoreException e) {

}

logger.info("Detected Truststore: {}", trustManagerFactory.getProvider().getName());
List<X509TrustManager> x509TrustManagers = new ArrayList<X509TrustManager>();

for (TrustManager trustManager : trustManagerFactory.getTrustManagers()) {
if (trustManager instanceof X509TrustManager) {
X509TrustManager x509TrustManager = (X509TrustManager)trustManager;
logger.info(" Trusted issuers found: " + x509TrustManager.getAcceptedIssuers().length);

x509TrustManagers.add(x509TrustManager);
}
}

return x509TrustManagers.toArray(new X509TrustManager[]{});
}
protected String checkTrustedCertStatus(X509Certificate certificate, X509TrustManager[] trustManagers) {

for (X509TrustManager trustManager : trustManagers) {
for (X509Certificate trustedCert : trustManager.getAcceptedIssuers()) {
try {
certificate.verify(trustedCert.getPublicKey());
return "matched found: " + trustedCert.getIssuerDN().getName();

} catch (CertificateException e) {
logger.trace("{}: {}", trustedCert.getIssuerDN().getName(), e.getMessage());
} catch (NoSuchAlgorithmException e) {
logger.trace("{}: {}", trustedCert.getIssuerDN().getName(), e.getMessage());
} catch (InvalidKeyException e) {
logger.trace("{}: {}", trustedCert.getIssuerDN().getName(), e.getMessage());
} catch (NoSuchProviderException e) {
logger.trace("{}: {}", trustedCert.getIssuerDN().getName(), e.getMessage());
} catch (SignatureException e) {
logger.trace("{}: {}", trustedCert.getIssuerDN().getName(), e.getMessage());
}
}
}

return "not matched in trust store (which is expected of the host certificate that is part of a chain)";
}

protected SSLContext getSSLContext() {
try {
SSLContext sslCtx = SSLContext.getInstance("TLS");
sslCtx.init(null, new TrustManager[]{ new X509TrustManager() {

private X509Certificate[] accepted;

@Override
public void checkClientTrusted(X509Certificate[] xcs, String string) throws CertificateException {
}

@Override
public void checkServerTrusted(X509Certificate[] xcs, String string) throws CertificateException {
accepted = xcs;
}

@Override
public X509Certificate[] getAcceptedIssuers() {
return accepted;
}
}}, null);

return sslCtx;
} catch (Exception e) {
throw new RuntimeException(e);
}
}
}

0 comments on commit df2ae75

Please sign in to comment.