Browse Source

Use HostChecker in CertificateManager.

pull/809/head
Chris Smith 7 years ago
parent
commit
490c38cdfc
1 changed files with 10 additions and 82 deletions
  1. 10
    82
      src/main/java/com/dmdirc/tls/CertificateManager.java

+ 10
- 82
src/main/java/com/dmdirc/tls/CertificateManager.java View File

@@ -17,13 +17,12 @@
17 17
 
18 18
 package com.dmdirc.tls;
19 19
 
20
+import com.dmdirc.config.provider.AggregateConfigProvider;
21
+import com.dmdirc.config.provider.ConfigProvider;
20 22
 import com.dmdirc.events.ServerCertificateProblemEncounteredEvent;
21 23
 import com.dmdirc.events.ServerCertificateProblemResolvedEvent;
22
-import com.dmdirc.interfaces.Connection;
23 24
 import com.dmdirc.events.eventbus.EventBus;
24
-import com.dmdirc.config.provider.AggregateConfigProvider;
25
-import com.dmdirc.config.provider.ConfigProvider;
26
-
25
+import com.dmdirc.interfaces.Connection;
27 26
 import java.io.FileInputStream;
28 27
 import java.io.FileNotFoundException;
29 28
 import java.io.IOException;
@@ -32,7 +31,6 @@ import java.security.InvalidAlgorithmParameterException;
32 31
 import java.security.KeyStore;
33 32
 import java.security.KeyStoreException;
34 33
 import java.security.cert.CertificateException;
35
-import java.security.cert.CertificateParsingException;
36 34
 import java.security.cert.PKIXParameters;
37 35
 import java.security.cert.TrustAnchor;
38 36
 import java.security.cert.X509Certificate;
@@ -47,14 +45,12 @@ import java.util.Map;
47 45
 import java.util.Set;
48 46
 import java.util.concurrent.Semaphore;
49 47
 import java.util.stream.Collectors;
50
-
51 48
 import javax.naming.InvalidNameException;
52 49
 import javax.naming.ldap.LdapName;
53 50
 import javax.naming.ldap.Rdn;
54 51
 import javax.net.ssl.KeyManager;
55 52
 import javax.net.ssl.KeyManagerFactory;
56 53
 import javax.net.ssl.X509TrustManager;
57
-
58 54
 import org.slf4j.Logger;
59 55
 import org.slf4j.LoggerFactory;
60 56
 
@@ -90,6 +86,8 @@ public class CertificateManager implements X509TrustManager {
90 86
     private final ConfigProvider userSettings;
91 87
     /** Locator to use to find a system keystore. */
92 88
     private final KeyStoreLocator keyStoreLocator;
89
+    /** Checker to use for hostnames. */
90
+    private final CertificateHostChecker hostChecker;
93 91
 
94 92
     /**
95 93
      * Creates a new certificate manager for a client connecting to the specified server.
@@ -111,6 +109,7 @@ public class CertificateManager implements X509TrustManager {
111 109
         this.userSettings = userSettings;
112 110
         this.eventBus = eventBus;
113 111
         this.keyStoreLocator = new KeyStoreLocator();
112
+        this.hostChecker = new CertificateHostChecker();
114 113
 
115 114
         loadTrustedCAs();
116 115
     }
@@ -206,74 +205,16 @@ public class CertificateManager implements X509TrustManager {
206 205
         return TrustResult.UNTRUSTED_GENERAL;
207 206
     }
208 207
 
209
-    /**
210
-     * Determines whether the given certificate has a valid CN or alternate name for this server's
211
-     * hostname.
212
-     *
213
-     * @param certificate The certificate to be validated
214
-     *
215
-     * @return True if the certificate is valid for this server's host, false otherwise
216
-     */
217
-    public boolean isValidHost(final X509Certificate certificate) {
218
-        final Map<String, String> fields = getDNFieldsFromCert(certificate);
219
-        if (fields.containsKey("CN") && isMatchingServerName(fields.get("CN"))) {
220
-            return true;
221
-        }
222
-
223
-        try {
224
-            if (certificate.getSubjectAlternativeNames() != null) {
225
-                for (List<?> entry : certificate.getSubjectAlternativeNames()) {
226
-                    final int type = (Integer) entry.get(0);
227
-
228
-                    // DNS or IP
229
-                    if ((type == 2 || type == 7) && isMatchingServerName((String) entry.get(1))) {
230
-                        return true;
231
-                    }
232
-                }
233
-            }
234
-        } catch (CertificateParsingException ex) {
235
-            return false;
236
-        }
237
-
238
-        return false;
239
-    }
240
-
241
-    /**
242
-     * Checks whether the specified target matches the server name this certificate manager was
243
-     * initialised with.
244
-     *
245
-     * Target names may contain wildcards per RFC2818.
246
-     *
247
-     * @since 0.6.5
248
-     * @param target The target to compare to our server name
249
-     *
250
-     * @return True if the target matches, false otherwise
251
-     */
252
-    protected boolean isMatchingServerName(final String target) {
253
-        final String[] targetParts = target.split("\\.");
254
-        final String[] serverParts = serverName.split("\\.");
255
-
256
-        if (targetParts.length != serverParts.length) {
257
-            // Fail fast if they don't match
258
-            return false;
259
-        }
260
-
261
-        for (int i = 0; i < serverParts.length; i++) {
262
-            if (!serverParts[i].matches("\\Q" + targetParts[i].replace("*", "\\E.*\\Q") + "\\E")) {
263
-                return false;
264
-            }
265
-        }
266
-
267
-        return true;
268
-    }
269
-
270 208
     @Override
271 209
     public void checkServerTrusted(final X509Certificate[] chain, final String authType)
272 210
             throws CertificateException {
273 211
         this.chain = Arrays.copyOf(chain, chain.length);
274 212
         problems.clear();
275 213
 
276
-        checkHost(chain);
214
+        if (!hostChecker.isValidFor(chain[0], serverName)) {
215
+            problems.add(new CertificateDoesntMatchHostException(
216
+                    "Certificate was not issued to " + serverName));
217
+        }
277 218
 
278 219
         if (checkIssuer(chain)) {
279 220
             problems.clear();
@@ -343,19 +284,6 @@ public class CertificateManager implements X509TrustManager {
343 284
         return manual;
344 285
     }
345 286
 
346
-    /**
347
-     * Checks that the host of the leaf certificate is the same as the server we are connected to.
348
-     *
349
-     * @param chain The chain of certificates to check.
350
-     */
351
-    private void checkHost(final X509Certificate... chain) {
352
-        // Check that the cert is issued to the correct host
353
-        if (!isValidHost(chain[0])) {
354
-            problems.add(new CertificateDoesntMatchHostException(
355
-                    "Certificate was not issued to " + serverName));
356
-        }
357
-    }
358
-
359 287
     /**
360 288
      * Gets the chain of certificates currently being validated, if any.
361 289
      *

Loading…
Cancel
Save