├── .travis.yml
├── .gitattributes
├── .editorconfig
├── .gitignore
├── src
├── test
│ └── java
│ │ ├── SSLPokeIgnoreRevocationTest.java
│ │ ├── SSLPokeClientProtocolTest.java
│ │ └── SSLPokeTest.java
└── main
│ └── java
│ └── SSLPoke.java
├── .github
└── workflows
│ ├── maven-ci.yml
│ └── maven-release.yml
├── doc
└── java11systemPropertyNames.txt
├── pom.xml
├── README.md
└── LICENSE
/.travis.yml:
--------------------------------------------------------------------------------
1 | language: java
2 | jdk: oraclejdk8
3 | after_success:
4 | - mvn coveralls:report
5 |
--------------------------------------------------------------------------------
/.gitattributes:
--------------------------------------------------------------------------------
1 | # When shell scripts end in CRLF, bash gives a cryptic error message
2 | *.sh text eol=lf
3 |
--------------------------------------------------------------------------------
/.editorconfig:
--------------------------------------------------------------------------------
1 | # Editor configuration, see http://editorconfig.org
2 | root = true
3 |
4 | [*]
5 | charset = utf-8
6 | indent_style = space
7 | indent_size = 4
8 | insert_final_newline = true
9 | trim_trailing_whitespace = true
10 |
11 | [*.md]
12 | max_line_length = off
13 | trim_trailing_whitespace = false
14 |
15 | [*.yml]
16 | indent_size = 2
17 |
18 | [*.sh]
19 | end_of_line = lf
20 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | #
2 | # Standard Maven .gitignore
3 | #
4 | target/
5 | pom.xml.tag
6 | pom.xml.releaseBackup
7 | pom.xml.versionsBackup
8 | pom.xml.next
9 | release.properties
10 | dependency-reduced-pom.xml
11 | buildNumber.properties
12 | .mvn/timing.properties
13 |
14 | #
15 | # IntelliJ
16 | #
17 | *.iml
18 | .idea/*
19 | !.idea/runConfigurations/
20 |
21 | #
22 | # Visual Studio Code
23 | #
24 | .settings/
25 | .classpath
26 | .project
27 | .vscode/
28 |
29 | # secrets
30 | *.p12
31 | *.jks
32 |
--------------------------------------------------------------------------------
/src/test/java/SSLPokeIgnoreRevocationTest.java:
--------------------------------------------------------------------------------
1 | import static org.junit.jupiter.api.Assertions.assertNotNull;
2 |
3 | import java.io.IOException;
4 | import java.net.UnknownHostException;
5 |
6 | import org.junit.jupiter.api.Test;
7 | import org.junitpioneer.jupiter.ClearSystemProperty;
8 |
9 | /**
10 | * Unit test.
11 | */
12 | @ClearSystemProperty(key = "com.sun.net.ssl.checkRevocation")
13 | @ClearSystemProperty(key = "com.sun.security.enableCRLDP")
14 | public class SSLPokeIgnoreRevocationTest {
15 |
16 | @Test
17 | public void ignoreRevocation() throws UnknownHostException, IOException {
18 | assertNotNull(SSLPoke.connect("revoked-rsa-dv.ssl.com", 443));
19 | }
20 |
21 | }
22 |
--------------------------------------------------------------------------------
/src/test/java/SSLPokeClientProtocolTest.java:
--------------------------------------------------------------------------------
1 | import static org.junit.jupiter.api.Assertions.assertThrows;
2 |
3 | import java.io.IOException;
4 | import java.net.UnknownHostException;
5 |
6 | import org.junit.jupiter.api.Test;
7 | import org.junitpioneer.jupiter.ClearSystemProperty;
8 | import org.junitpioneer.jupiter.SetSystemProperty;
9 |
10 | /**
11 | * Unit test.
12 | */
13 | @ClearSystemProperty(key = "com.sun.net.ssl.checkRevocation")
14 | @ClearSystemProperty(key = "com.sun.security.enableCRLDP")
15 | public class SSLPokeClientProtocolTest {
16 |
17 | @Test
18 | @SetSystemProperty(key = "jdk.tls.client.protocols", value = "SSLv3")
19 | public void sslV3() throws UnknownHostException, IOException {
20 | assertThrows(javax.net.ssl.SSLHandshakeException.class,
21 | () -> SSLPoke.connect("www.badssl.com", 443));
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/.github/workflows/maven-ci.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Java CI with Maven
5 |
6 | on:
7 | push:
8 | branches: [ main ]
9 | pull_request:
10 | branches: [ main ]
11 |
12 | jobs:
13 | build:
14 | runs-on: ubuntu-latest
15 |
16 | steps:
17 | - uses: actions/checkout@v5
18 |
19 | - name: Set up JDK 8
20 | uses: actions/setup-java@v5
21 | with:
22 | java-version: "8"
23 | distribution: "zulu"
24 | cache: maven
25 |
26 | - name: Build with Maven
27 | run: mvn --batch-mode package
28 |
29 | - name: Upload artifacts
30 | uses: actions/upload-artifact@v5
31 | with:
32 | name: package
33 | path: target/*.jar
34 |
--------------------------------------------------------------------------------
/.github/workflows/maven-release.yml:
--------------------------------------------------------------------------------
1 | # This workflow will build a Java project with Maven
2 | # For more information see: https://help.github.com/actions/language-and-framework-guides/building-and-testing-java-with-maven
3 |
4 | name: Publish package on new release
5 |
6 | on:
7 | release:
8 | types: [created]
9 |
10 | jobs:
11 | build:
12 | runs-on: ubuntu-latest
13 |
14 | steps:
15 | - uses: actions/checkout@v3
16 |
17 | - name: Set up JDK 8
18 | uses: actions/setup-java@v3
19 | with:
20 | java-version: '8'
21 | distribution: 'zulu'
22 | cache: 'maven'
23 |
24 | - name: Publish package
25 | run: mvn --batch-mode deploy
26 | env:
27 | GITHUB_TOKEN: ${{ github.token }} # GITHUB_TOKEN is the default env for the password
28 |
29 | - name: Upload binaries to release
30 | uses: svenstaro/upload-release-action@v2
31 | with:
32 | file: target/*.jar
33 | overwrite: true
34 | file_glob: true
35 |
--------------------------------------------------------------------------------
/doc/java11systemPropertyNames.txt:
--------------------------------------------------------------------------------
1 | "com.sun.net.ssl.checkRevocation",
2 | "https.cipherSuites",
3 | "https.protocols",
4 | "https.proxyHost",
5 | "https.proxyPort",
6 | "java.protocol.handler.pkgs",
7 | "javax.net.ssl.keyStore",
8 | "javax.net.ssl.keyStorePassword",
9 | "javax.net.ssl.keyStoreProvider",
10 | "javax.net.ssl.keyStoreType",
11 | "javax.net.ssl.sessionCacheSize",
12 | "javax.net.ssl.trustStore",
13 | "javax.net.ssl.trustStorePassword",
14 | "javax.net.ssl.trustStoreProvider",
15 | "javax.net.ssl.trustStoreType",
16 | "jdk.tls.acknowledgeCloseNotify",
17 | "jdk.tls.allowUnsafeServerCertChange",
18 | "jdk.tls.client.cipherSuites",
19 | "jdk.tls.client.disableExtensions",
20 | "jdk.tls.client.protocols",
21 | "jdk.tls.client.SignatureSchemes",
22 | "jdk.tls.ephemeralDHKeySize",
23 | "jdk.tls.maxCertificateChainLength",
24 | "jdk.tls.maxHandshakeMessageSize",
25 | "jdk.tls.namedGroups",
26 | "jdk.tls.server.cipherSuites",
27 | "jdk.tls.server.disableExtensions",
28 | "jdk.tls.server.protocols",
29 | "jdk.tls.server.SignatureSchemes",
30 | "jsse.enableFFDHE",
31 | "jsse.enableMFLNExtension",
32 | "jsse.enableSNIExtension",
33 | "jsse.SSLEngine.acceptLargeFragments",
34 | "sun.security.ssl.allowLegacyHelloMessages",
35 | "sun.security.ssl.allowUnsafeRenegotiation",
36 |
--------------------------------------------------------------------------------
/src/test/java/SSLPokeTest.java:
--------------------------------------------------------------------------------
1 | import static org.junit.jupiter.api.Assertions.assertEquals;
2 | import static org.junit.jupiter.api.Assertions.assertNotNull;
3 | import static org.junit.jupiter.api.Assertions.assertThrows;
4 | import static org.junit.jupiter.api.Assertions.assertTrue;
5 |
6 | import java.io.IOException;
7 | import java.net.UnknownHostException;
8 |
9 | import org.junit.jupiter.api.Test;
10 | import org.junitpioneer.jupiter.SetSystemProperty;
11 |
12 | /**
13 | * Unit test.
14 | */
15 | @SetSystemProperty(key = "com.sun.net.ssl.checkRevocation", value = "true")
16 | @SetSystemProperty(key = "com.sun.security.enableCRLDP", value = "true")
17 | public class SSLPokeTest {
18 | @Test
19 | public void certificateWithCrlDp() throws UnknownHostException, IOException {
20 | Object result = SSLPoke.connect("www.microsoft.com", 443);
21 | assertNotNull(result);
22 | }
23 |
24 | @Test
25 | public void unknownHost() throws UnknownHostException, IOException {
26 | assertThrows(java.net.UnknownHostException.class,
27 | () -> SSLPoke.connect("host.invalid", 443));
28 | }
29 |
30 | @Test
31 | public void expired() throws UnknownHostException, IOException {
32 | assertThrows(javax.net.ssl.SSLHandshakeException.class,
33 | () -> SSLPoke.connect("expired.badssl.com", 443));
34 |
35 | }
36 |
37 | @Test
38 | public void wrongHost() throws UnknownHostException, IOException {
39 | assertThrows(javax.net.ssl.SSLHandshakeException.class,
40 | () -> SSLPoke.connect("wrong.host.badssl.com", 443));
41 | }
42 |
43 | @Test
44 | public void selfSigned() throws UnknownHostException, IOException {
45 | assertThrows(javax.net.ssl.SSLHandshakeException.class,
46 | () -> SSLPoke.connect("self-signed.badssl.com", 443));
47 | }
48 |
49 | @Test
50 | public void untrustedRoot() throws UnknownHostException, IOException {
51 | assertThrows(javax.net.ssl.SSLHandshakeException.class,
52 | () -> SSLPoke.connect("untrusted-root.badssl.com", 443));
53 | }
54 |
55 | @Test
56 | public void revoked() throws UnknownHostException, IOException {
57 | assertEquals("true", System.getProperty("com.sun.net.ssl.checkRevocation"));
58 | assertEquals("true", System.getProperty("com.sun.security.enableCRLDP"));
59 | Exception exception = assertThrows(javax.net.ssl.SSLHandshakeException.class,
60 | () -> SSLPoke.connect("revoked-rsa-dv.ssl.com", 443));
61 | assertTrue(exception.getMessage().contains("Certificate has been revoked"));
62 | }
63 |
64 | }
65 |
--------------------------------------------------------------------------------
/pom.xml:
--------------------------------------------------------------------------------
1 |
4 | 4.0.0
5 | de.norbertklasen.security
6 | sslpoke
7 | 1.1.1
8 |
9 | 1.8
10 | 1.8
11 | UTF-8
12 |
13 |
14 |
15 | org.junit.jupiter
16 | junit-jupiter-api
17 | 5.6.2
18 | test
19 |
20 |
21 | org.junit.jupiter
22 | junit-jupiter-engine
23 | 5.6.2
24 | test
25 |
26 |
27 | org.junit-pioneer
28 | junit-pioneer
29 | 0.5.6
30 | test
31 |
32 |
33 |
34 |
35 |
36 |
37 | org.apache.maven.plugins
38 | maven-checkstyle-plugin
39 | 3.0.0
40 |
41 |
42 | com.puppycrawl.tools
43 | checkstyle
44 | 8.29
45 |
46 |
47 | com.github.ngeor
48 | checkstyle-rules
49 | 1.1.0
50 |
51 |
52 |
53 | com/github/ngeor/checkstyle.xml
54 | true
55 |
56 |
57 |
58 |
59 |
60 |
61 | org.apache.maven.plugins
62 | maven-checkstyle-plugin
63 |
64 |
65 |
69 |
70 | org.jacoco
71 | jacoco-maven-plugin
72 | 0.8.1
73 |
74 |
75 | org.apache.maven.plugins
76 | maven-jar-plugin
77 | 3.2.0
78 |
79 |
80 |
81 | true
82 | SSLPoke
83 |
84 |
85 |
86 |
87 |
88 | maven-surefire-plugin
89 | 2.22.2
90 |
91 | false
92 | 4
93 |
94 |
95 |
96 | maven-failsafe-plugin
97 | 2.22.2
98 |
99 |
100 |
101 |
102 |
103 |
104 | org.apache.maven.plugins
105 | maven-javadoc-plugin
106 | 3.0.0
107 |
108 |
109 | org.apache.maven.plugins
110 | maven-checkstyle-plugin
111 |
112 | com/github/ngeor/checkstyle.xml
113 | true
114 |
115 |
116 |
117 |
118 |
119 |
120 |
125 |
126 | jacoco
127 |
128 |
129 | env.TRAVIS
130 |
131 |
132 |
133 |
134 |
135 | org.jacoco
136 | jacoco-maven-plugin
137 |
138 |
139 | prepare-agent
140 | validate
141 |
142 | prepare-agent
143 |
144 |
145 |
146 | report
147 | test
148 |
149 | report
150 |
151 |
152 |
153 |
154 |
155 |
156 |
157 |
158 |
163 |
164 | travis
165 |
166 |
167 | env.TRAVIS
168 |
169 |
170 |
171 |
172 |
173 | org.apache.maven.plugins
174 | maven-checkstyle-plugin
175 |
176 |
177 | checkstyle
178 | test
179 |
180 | check
181 |
182 |
183 |
184 |
185 |
186 | org.eluder.coveralls
187 | coveralls-maven-plugin
188 | 4.3.0
189 |
190 |
191 |
192 |
193 |
194 |
195 | https://github.com/klasen/sslpoke
196 |
197 |
198 |
199 | https://github.com/klasen/sslpoke/issues
200 | GitHub
201 |
202 |
203 |
204 |
205 | github
206 | https://maven.pkg.github.com/klasen/sslpoke
207 |
208 | true
209 |
210 |
211 | true
212 |
213 |
214 |
215 |
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # SSLPoke
2 |
3 | 
4 |
5 | Test establishment of a TLS connection to a host with Java.
6 |
7 | This version has been enhanced to print all known system and security properties relevant to TLS and HTTPS.
8 |
9 | ## Usage
10 |
11 | Positive test:
12 |
13 | ```sh
14 | java -jar sslpoke.jar www.github.com 443
15 | ```
16 |
17 | You should get this:
18 |
19 | ```log
20 | connecting to www.github.com:443 with the following system and security properties:
21 | java.version: System: 1.8.0_251
22 | java.vendor: System: Oracle Corporation
23 | policy.allowSystemProperty: Security: true
24 | java.security.policy:
25 | CertPathValidator.PKIX:
26 | cert.provider.x509v1:
27 | java.protocol.handler.pkgs:
28 | security.provider.1: Security: sun.security.provider.Sun
29 | ssl.ServerSocketFactory.provider:
30 | ssl.SocketFactory.provider:
31 | jdk.tls.client.protocols:
32 | jdk.tls.disabledAlgorithms: Security: SSLv3, RC4, DES, MD5withRSA, DH keySize < 1024, EC keySize < 224, 3DES_EDE_CBC, anon, NULL
33 | jdk.tls.legacyAlgorithms: Security: K_NULL, C_NULL, M_NULL, DH_anon, ECDH_anon, RC4_128, RC4_40, DES_CBC, DES40_CBC, 3DES_EDE_CBC
34 | jdk.tls.ephemeralDHKeySize:
35 | jsse.enableSNIExtension:
36 | https.cipherSuites:
37 | https.protocols:
38 | sun.security.ssl.allowUnsafeRenegotiation:
39 | sun.security.ssl.allowLegacyHelloMessages:
40 | keystore.type: Security: jks
41 | keystore.type.compat: Security: true
42 | javax.net.ssl.trustStore:
43 | javax.net.ssl.trustStorePassword:
44 | javax.net.ssl.trustStoreType:
45 | javax.net.ssl.keyStore:
46 | javax.net.ssl.keyStorePassword:
47 | javax.net.ssl.keyStoreType:
48 | CertPathValidator.PKIX:
49 | jdk.certpath.disabledAlgorithms: Security: MD2, MD5, SHA1 jdkCA & usage TLSServer, RSA keySize < 1024, DSA keySize < 1024, EC keySize < 224
50 | com.sun.net.ssl.checkRevocation:
51 | com.sun.security.enableCRLDP:
52 | com.sun.security.crl.timeout:
53 | sun.security.certpath.ldap.cache.lifetime:
54 | com.sun.security.enableAIAcaIssuers:
55 | ocsp.enable:
56 | ocsp.responderURL:
57 | ocsp.responderCertSubjectName:
58 | ocsp.responderCertIssuerName:
59 | ocsp.responderCertSerialNumber:
60 | http.nonProxyHosts:
61 | https.protocols:
62 | https.proxyHost:
63 | https.proxyPort:
64 | java.security.debug:
65 | javax.net.debug:
66 |
67 | Successfully connected.
68 | Protocol: TLSv1.2
69 | Cipher suite: TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
70 | ```
71 |
72 | Negative tests (courtesy of [badssl.com](https://badssl.com)):
73 |
74 | ```
75 | java -jar sslpoke.jar expired.badssl.com 443
76 | java -jar sslpoke.jar wrong.host.badssl.com 443
77 | java -jar sslpoke.jar self-signed.badssl.com 443
78 | java -jar sslpoke.jar untrusted-root.badssl.com 443
79 | java -jar sslpoke.jar revoked.badssl.com 443
80 | java -jar sslpoke.jar cbc.badssl.com 443
81 | java -jar sslpoke.jar rc4-md5.badssl.com 443
82 | java -jar sslpoke.jar rc4.badssl.com 443
83 | java -jar sslpoke.jar 3des.badssl.com 443
84 | java -jar sslpoke.jar null.badssl.com 443
85 | java -jar sslpoke.jar tls-v1-0.badssl.com 1010
86 | java -jar sslpoke.jar tls-v1-1.badssl.com 1011
87 | java -jar sslpoke.jar tls-v1-2.badssl.com 1012
88 | ```
89 |
90 | Which should get you an error like this:
91 |
92 | ```log
93 | [...]
94 | Connection failed.
95 | javax.net.ssl.SSLHandshakeException: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
96 | at sun.security.ssl.Alerts.getSSLException(Unknown Source)
97 | at sun.security.ssl.SSLSocketImpl.fatal(Unknown Source)
98 | at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
99 | at sun.security.ssl.Handshaker.fatalSE(Unknown Source)
100 | at sun.security.ssl.ClientHandshaker.serverCertificate(Unknown Source)
101 | at sun.security.ssl.ClientHandshaker.processMessage(Unknown Source)
102 | at sun.security.ssl.Handshaker.processLoop(Unknown Source)
103 | at sun.security.ssl.Handshaker.process_record(Unknown Source)
104 | at sun.security.ssl.SSLSocketImpl.readRecord(Unknown Source)
105 | at sun.security.ssl.SSLSocketImpl.performInitialHandshake(Unknown Source)
106 | at sun.security.ssl.SSLSocketImpl.writeRecord(Unknown Source)
107 | at sun.security.ssl.AppOutputStream.write(Unknown Source)
108 | at sun.security.ssl.AppOutputStream.write(Unknown Source)
109 | at SSLPoke.connect(SSLPoke.java:51)
110 | at SSLPoke.main(SSLPoke.java:84)
111 | Caused by: sun.security.validator.ValidatorException: PKIX path validation failed: java.security.cert.CertPathValidatorException: validity check failed
112 | at sun.security.validator.PKIXValidator.doValidate(Unknown Source)
113 | at sun.security.validator.PKIXValidator.engineValidate(Unknown Source)
114 | at sun.security.validator.Validator.validate(Unknown Source)
115 | at sun.security.ssl.X509TrustManagerImpl.validate(Unknown Source)
116 | at sun.security.ssl.X509TrustManagerImpl.checkTrusted(Unknown Source)
117 | at sun.security.ssl.X509TrustManagerImpl.checkServerTrusted(Unknown Source)
118 | ... 11 more
119 | Caused by: java.security.cert.CertPathValidatorException: validity check failed
120 | at sun.security.provider.certpath.PKIXMasterCertPathValidator.validate(Unknown Source)
121 | at sun.security.provider.certpath.PKIXCertPathValidator.validate(Unknown Source)
122 | at sun.security.provider.certpath.PKIXCertPathValidator.validate(Unknown Source)
123 | at sun.security.provider.certpath.PKIXCertPathValidator.engineValidate(Unknown Source)
124 | at java.security.cert.CertPathValidator.validate(Unknown Source)
125 | ... 17 more
126 | Caused by: java.security.cert.CertificateExpiredException: NotAfter: Mon Apr 13 01:59:59 CEST 2015
127 | at sun.security.x509.CertificateValidity.valid(Unknown Source)
128 | at sun.security.x509.X509CertImpl.checkValidity(Unknown Source)
129 | at sun.security.provider.certpath.BasicChecker.verifyValidity(Unknown Source)
130 | at sun.security.provider.certpath.BasicChecker.check(Unknown Source)
131 | ... 22 more
132 | ```
133 |
134 | ## Java Properties
135 |
136 | The properties that influence the network, TLS protocol, certificate verification and debugging behavior of a JVM are described in:
137 |
138 | - Java Secure Socket Extension (JSSE) Reference Guide ([Java 8](https://docs.oracle.com/javase/8/docs/technotes/guides/security/jsse/JSSERefGuide.html#InstallationAndCustomization), [Java 11](https://docs.oracle.com/en/java/javase/11/security/java-secure-socket-extension-jsse-reference-guide.html#GUID-93DEEE16-0B70-40E5-BBE7-55C3FD432345))
139 | - [Java PKI Programmer's Guide](https://docs.oracle.com/javase/8/docs/technotes/guides/security/certpath/CertPathProgGuide.html)
140 | - [Networking Properties](https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html)
141 | - [Additional information on Oracle's JDK and JRE Cryptographic Algorithms](https://www.java.com/en/configure_crypto.html)
142 | - [Oracle JRE and JDK Cryptographic Roadmap](https://www.java.com/en/jre-jdk-cryptoroadmap.html)
143 |
144 | So far, I've come across the following parameters that seem relevant:
145 |
146 | - Policy
147 | - policy.allowSystemProperty
148 | - java.security.policy
149 | - Implementation
150 | - cert.provider.x509v1
151 | - java.protocol.handler.pkgs
152 | - security.provider.1
153 | - ssl.ServerSocketFactory.provider
154 | - ssl.SocketFactory.provider
155 | - Protocol
156 | - jdk.tls.client.protocols
157 | - jdk.tls.disabledAlgorithms
158 | - jdk.tls.legacyAlgorithms
159 | - jdk.tls.ephemeralDHKeySize
160 | - jsse.enableSNIExtension
161 | - https.cipherSuites
162 | - https.protocols
163 | - sun.security.ssl.allowUnsafeRenegotiation
164 | - sun.security.ssl.allowLegacyHelloMessages
165 | - Stores
166 | - keystore.type ()
167 | - keystore.type.compat ()
168 | - javax.net.ssl.trustStore
169 | - javax.net.ssl.trustStorePassword
170 | - javax.net.ssl.trustStoreType
171 | - javax.net.ssl.keyStore
172 | - javax.net.ssl.keyStorePassword
173 | - javax.net.ssl.keyStoreType
174 | - Certificate path validation
175 | - CertPathValidator.PKIX
176 | - jdk.certpath.disabledAlgorithms
177 | - jdk.security.caDistrustPolicies
178 | - com.sun.net.ssl.checkRevocation
179 | - com.sun.security.enableCRLDP
180 | - com.sun.security.crl.timeout
181 | - sun.security.certpath.ldap.cache.lifetime
182 | - com.sun.security.enableAIAcaIssuers
183 | - ocsp.enable
184 | - ocsp.responderURL
185 | - ocsp.responderCertSubjectName
186 | - ocsp.responderCertIssuerName
187 | - ocsp.responderCertSerialNumber
188 |
189 | - Proxy
190 | - http.nonProxyHosts
191 | - https.protocols
192 | - https.proxyHost
193 | - https.proxyPort
194 |
195 | ## Troubleshooting
196 |
197 | To get more detailed logs, set the following properties:
198 |
199 | - showSettings
200 | -
201 | - suggested option: `-XshowSettings:security:all`
202 | - java.security.debug
203 | -
204 | -
205 | - suggested option: `-Djavax.net.debug=ssl,trustmanager,handshake`
206 | - javax.net.debug
207 | -
208 | - suggested option: `-Djava.security.debug=properties,certpath`
209 |
210 | Combined:
211 | ```sh
212 | -XshowSettings:security:all -Djavax.net.debug=ssl,trustmanager,handshake -Djava.security.debug=properties,certpath
213 | ```
214 |
215 | ## Servers
216 |
217 | To see the protocols and ciphers supported by the server you are trying to connect to you can use tools such as [Qualys SSL Labs](https://www.ssllabs.com/ssltest/) if the server is publicly available or [sslscan](https://www.ssllabs.com/ssltest/) if you are in a private network.
218 |
219 | ## Credits
220 |
221 | - Atlassian for the [base code](https://confluence.atlassian.com/display/JIRA052/Connecting+to+SSL+services)
222 | - @4ndrej for
223 |
--------------------------------------------------------------------------------
/src/main/java/SSLPoke.java:
--------------------------------------------------------------------------------
1 | import java.io.IOException;
2 | import java.io.InputStream;
3 | import java.io.OutputStream;
4 | import java.net.UnknownHostException;
5 | import java.util.ArrayList;
6 | import java.util.List;
7 |
8 | import javax.net.ssl.SNIHostName;
9 | import javax.net.ssl.SNIServerName;
10 | import javax.net.ssl.SSLParameters;
11 | import javax.net.ssl.SSLSession;
12 | import javax.net.ssl.SSLSocket;
13 | import javax.net.ssl.SSLSocketFactory;
14 |
15 | /**
16 | * Test establishment of a HTTPS (TLS) connection to a host and port
17 | *
18 | * @see https://gist.github.com/4ndrej/4547029
19 | */
20 | public class SSLPoke {
21 | // https://docs.oracle.com/en/java/javase/11/security/java-secure-socket-extension-jsse-reference-guide.html#GUID-A41282C3-19A3-400A-A40F-86F4DA22ABA9
22 | final static String[] securityPropertyNames = {
23 | "cert.provider.x509v1",
24 | "com.sun.CORBA.ORBIorTypeCheckRegistryFilter",
25 | "crypto.policy",
26 | "fips.keystore.type",
27 | "fips.provider.1",
28 | "fips.provider.2",
29 | "fips.provider.3",
30 | "fips.provider.4",
31 | "jceks.key.serialFilter",
32 | "jdk.certpath.disabledAlgorithms",
33 | "jdk.disabled.namedCurves",
34 | "jdk.includeInExceptions",
35 | "jdk.io.permissionsUseCanonicalPath",
36 | "jdk.jar.disabledAlgorithms",
37 | "jdk.jceks.iterationCount",
38 | "jdk.jndi.object.factoriesFilter",
39 | "jdk.sasl.disabledMechanisms",
40 | "jdk.security.allowNonCaAnchor",
41 | "jdk.security.caDistrustPolicies",
42 | "jdk.security.krb5.default.initiate.credential",
43 | "jdk.security.legacyAlgorithms",
44 | "jdk.security.provider.preferred",
45 | "jdk.serialFilter",
46 | "jdk.tls.alpnCharset",
47 | "jdk.tls.disabledAlgorithms",
48 | "jdk.tls.keyLimits",
49 | "jdk.tls.legacyAlgorithms",
50 | "jdk.tls.server.defaultDHEParameters",
51 | "jdk.xml.dsig.secureValidationPolicy",
52 | "keystore.pkcs12.certPbeIterationCount",
53 | "keystore.pkcs12.certProtectionAlgorithm",
54 | "keystore.pkcs12.keyPbeIterationCount",
55 | "keystore.pkcs12.keyProtectionAlgorithm",
56 | "keystore.pkcs12.macAlgorithm",
57 | "keystore.pkcs12.macIterationCount",
58 | "keystore.type",
59 | "keystore.type.compat",
60 | "krb5.kdc.bad.policy",
61 | "login.config.url.1",
62 | "login.configuration.provider",
63 | "networkaddress.cache.negative.ttl",
64 | "networkaddress.cache.ttl",
65 | "ocsp.enable",
66 | "package.access",
67 | "package.definition",
68 | "policy.allowSystemProperty",
69 | "policy.expandProperties",
70 | "policy.ignoreIdentityScope",
71 | "policy.provider",
72 | "policy.url.1",
73 | "policy.url.2",
74 | "securerandom.drbg.config",
75 | "securerandom.source",
76 | "securerandom.strongAlgorithms",
77 | "security.overridePropertiesFile",
78 | "security.provider.1",
79 | "security.provider.10",
80 | "security.provider.11",
81 | "security.provider.12",
82 | "security.provider.2",
83 | "security.provider.3",
84 | "security.provider.4",
85 | "security.provider.5",
86 | "security.provider.6",
87 | "security.provider.7",
88 | "security.provider.8",
89 | "security.provider.9",
90 | "security.useSystemPropertiesFile",
91 | "ssl.KeyManagerFactory.algorithm",
92 | "ssl.ServerSocketFactory.provider",
93 | "ssl.SocketFactory.provider",
94 | "ssl.TrustManagerFactory.algorithm",
95 | "sun.rmi.registry.registryFilter",
96 | "sun.rmi.transport.dgcFilter",
97 | "sun.security.krb5.disableReferrals",
98 | "sun.security.krb5.maxReferrals",
99 | };
100 |
101 | final static String[] systemPropertyNames = {
102 | "java.vendor",
103 | "java.version",
104 | "java.security.debug",
105 | "javax.net.debug",
106 | // https://docs.oracle.com/en/java/javase/11/security/permissions-jdk1.html#GUID-BFF84712-05CF-4C1E-926F-411FDF83AE32
107 | "java.security.policy",
108 | // system proxy
109 | "http_proxy",
110 | "https_proxy",
111 | "no_proxy",
112 | // https://docs.oracle.com/en/java/javase/11/security/java-secure-socket-extension-jsse-reference-guide.html#GUID-A41282C3-19A3-400A-A40F-86F4DA22ABA9
113 | "com.sun.net.ssl.checkRevocation",
114 | "https.cipherSuites",
115 | "https.protocols",
116 | "https.proxyHost",
117 | "https.proxyPort",
118 | "http.nonProxyHosts", // https://docs.oracle.com/javase/8/docs/api/java/net/doc-files/net-properties.html
119 | "java.protocol.handler.pkgs",
120 | "javax.net.ssl.keyStore",
121 | "javax.net.ssl.keyStorePassword",
122 | "javax.net.ssl.keyStoreProvider",
123 | "javax.net.ssl.keyStoreType",
124 | "javax.net.ssl.sessionCacheSize",
125 | "javax.net.ssl.trustStore",
126 | "javax.net.ssl.trustStorePassword",
127 | "javax.net.ssl.trustStoreProvider",
128 | "javax.net.ssl.trustStoreType",
129 | "jdk.tls.acknowledgeCloseNotify",
130 | "jdk.tls.allowUnsafeServerCertChange",
131 | "jdk.tls.client.cipherSuites",
132 | "jdk.tls.client.disableExtensions",
133 | "jdk.tls.client.protocols",
134 | "jdk.tls.client.SignatureSchemes",
135 | "jdk.tls.ephemeralDHKeySize",
136 | "jdk.tls.maxCertificateChainLength",
137 | "jdk.tls.maxHandshakeMessageSize",
138 | "jdk.tls.namedGroups",
139 | "jdk.tls.server.cipherSuites",
140 | "jdk.tls.server.disableExtensions",
141 | "jdk.tls.server.protocols",
142 | "jdk.tls.server.SignatureSchemes",
143 | "jsse.enableFFDHE",
144 | "jsse.enableMFLNExtension",
145 | "jsse.enableSNIExtension",
146 | "jsse.SSLEngine.acceptLargeFragments",
147 | "sun.security.ssl.allowLegacyHelloMessages",
148 | "sun.security.ssl.allowUnsafeRenegotiation",
149 | // https://docs.oracle.com/en/java/javase/11/security/java-pki-programmers-guide.html#GUID-FF62B0E3-E57A-4F40-970A-0481AF750CCD
150 | "sun.security.certpath.ldap.cache.lifetime",
151 | // https://docs.oracle.com/en/java/javase/11/security/java-pki-programmers-guide.html#GUID-EB250086-0AC1-4D60-AE2A-FC7461374746
152 | "com.sun.security.crl.timeout",
153 | "com.sun.security.enableAIAcaIssuers",
154 | "com.sun.security.enableCRLDP",
155 | // https://www.oracle.com/java/technologies/javase/8u271-relnotes.html#JDK-8237990
156 | "jdk.jndi.ldap.mechsAllowedToSendCredentials",
157 | // https://www.oracle.com/java/technologies/javase/8u181-relnotes.html
158 | "com.sun.jndi.ldap.object.disableEndpointIdentification",
159 | };
160 |
161 | static SSLSession connect(final String host, final int port) throws UnknownHostException, IOException {
162 | SSLSocketFactory sslsocketfactory = (SSLSocketFactory) SSLSocketFactory.getDefault();
163 | SSLSocket sslsocket = (SSLSocket) sslsocketfactory.createSocket(host, port);
164 |
165 | SSLParameters sslparams = new SSLParameters();
166 | sslsocket.setSSLParameters(sslparams);
167 |
168 | sslparams.setEndpointIdentificationAlgorithm("HTTPS");
169 |
170 | // Sets Server Name Indication (SNI) parameter.
171 | final SNIHostName serverName = new SNIHostName(host);
172 | final List serverNames = new ArrayList<>(1);
173 | serverNames.add(serverName);
174 | sslparams.setServerNames(serverNames);
175 |
176 | InputStream in = sslsocket.getInputStream();
177 | OutputStream out = sslsocket.getOutputStream();
178 |
179 | // Write a test byte to get a reaction :)
180 | out.write(1);
181 |
182 | while (in.available() > 0) {
183 | System.out.print(in.read());
184 | }
185 |
186 | return sslsocket.getSession();
187 | }
188 |
189 | public static void main(final String[] args) {
190 | if (args.length != 2) {
191 | System.out.println("Usage: " + SSLPoke.class.getName() + " ");
192 | System.exit(1);
193 | }
194 | final String host = args[0];
195 | final Integer port = Integer.parseInt(args[1]);
196 |
197 | // System.setProperty("java.security.debug", "certpath");
198 | // System.setProperty("javax.net.debug", "ssl");
199 | // System.setProperty("com.sun.net.ssl.checkRevocation", "true");
200 | // System.setProperty("com.sun.security.enableCRLDP", "true");
201 |
202 | System.out.println("connecting to " + host + ":" + port);
203 |
204 | System.out.println("System properties:");
205 | for (int i = 0; i < systemPropertyNames.length; i++) {
206 | final String value = System.getProperty(systemPropertyNames[i]);
207 | if (value != null) {
208 | System.out.println(systemPropertyNames[i] + ": " + value);
209 | }
210 | }
211 |
212 | // dump all system properties
213 | // Properties systemProperties = System.getProperties();
214 | // for (Entry