Переглянути джерело

Use HostChecker in CertificateManager.

pull/809/head
Chris Smith 7 роки тому
джерело
коміт
490c38cdfc
1 змінених файлів з 10 додано та 82 видалено
  1. 10
    82
      src/main/java/com/dmdirc/tls/CertificateManager.java

+ 10
- 82
src/main/java/com/dmdirc/tls/CertificateManager.java Переглянути файл

17
 
17
 
18
 package com.dmdirc.tls;
18
 package com.dmdirc.tls;
19
 
19
 
20
+import com.dmdirc.config.provider.AggregateConfigProvider;
21
+import com.dmdirc.config.provider.ConfigProvider;
20
 import com.dmdirc.events.ServerCertificateProblemEncounteredEvent;
22
 import com.dmdirc.events.ServerCertificateProblemEncounteredEvent;
21
 import com.dmdirc.events.ServerCertificateProblemResolvedEvent;
23
 import com.dmdirc.events.ServerCertificateProblemResolvedEvent;
22
-import com.dmdirc.interfaces.Connection;
23
 import com.dmdirc.events.eventbus.EventBus;
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
 import java.io.FileInputStream;
26
 import java.io.FileInputStream;
28
 import java.io.FileNotFoundException;
27
 import java.io.FileNotFoundException;
29
 import java.io.IOException;
28
 import java.io.IOException;
32
 import java.security.KeyStore;
31
 import java.security.KeyStore;
33
 import java.security.KeyStoreException;
32
 import java.security.KeyStoreException;
34
 import java.security.cert.CertificateException;
33
 import java.security.cert.CertificateException;
35
-import java.security.cert.CertificateParsingException;
36
 import java.security.cert.PKIXParameters;
34
 import java.security.cert.PKIXParameters;
37
 import java.security.cert.TrustAnchor;
35
 import java.security.cert.TrustAnchor;
38
 import java.security.cert.X509Certificate;
36
 import java.security.cert.X509Certificate;
47
 import java.util.Set;
45
 import java.util.Set;
48
 import java.util.concurrent.Semaphore;
46
 import java.util.concurrent.Semaphore;
49
 import java.util.stream.Collectors;
47
 import java.util.stream.Collectors;
50
-
51
 import javax.naming.InvalidNameException;
48
 import javax.naming.InvalidNameException;
52
 import javax.naming.ldap.LdapName;
49
 import javax.naming.ldap.LdapName;
53
 import javax.naming.ldap.Rdn;
50
 import javax.naming.ldap.Rdn;
54
 import javax.net.ssl.KeyManager;
51
 import javax.net.ssl.KeyManager;
55
 import javax.net.ssl.KeyManagerFactory;
52
 import javax.net.ssl.KeyManagerFactory;
56
 import javax.net.ssl.X509TrustManager;
53
 import javax.net.ssl.X509TrustManager;
57
-
58
 import org.slf4j.Logger;
54
 import org.slf4j.Logger;
59
 import org.slf4j.LoggerFactory;
55
 import org.slf4j.LoggerFactory;
60
 
56
 
90
     private final ConfigProvider userSettings;
86
     private final ConfigProvider userSettings;
91
     /** Locator to use to find a system keystore. */
87
     /** Locator to use to find a system keystore. */
92
     private final KeyStoreLocator keyStoreLocator;
88
     private final KeyStoreLocator keyStoreLocator;
89
+    /** Checker to use for hostnames. */
90
+    private final CertificateHostChecker hostChecker;
93
 
91
 
94
     /**
92
     /**
95
      * Creates a new certificate manager for a client connecting to the specified server.
93
      * Creates a new certificate manager for a client connecting to the specified server.
111
         this.userSettings = userSettings;
109
         this.userSettings = userSettings;
112
         this.eventBus = eventBus;
110
         this.eventBus = eventBus;
113
         this.keyStoreLocator = new KeyStoreLocator();
111
         this.keyStoreLocator = new KeyStoreLocator();
112
+        this.hostChecker = new CertificateHostChecker();
114
 
113
 
115
         loadTrustedCAs();
114
         loadTrustedCAs();
116
     }
115
     }
206
         return TrustResult.UNTRUSTED_GENERAL;
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
     @Override
208
     @Override
271
     public void checkServerTrusted(final X509Certificate[] chain, final String authType)
209
     public void checkServerTrusted(final X509Certificate[] chain, final String authType)
272
             throws CertificateException {
210
             throws CertificateException {
273
         this.chain = Arrays.copyOf(chain, chain.length);
211
         this.chain = Arrays.copyOf(chain, chain.length);
274
         problems.clear();
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
         if (checkIssuer(chain)) {
219
         if (checkIssuer(chain)) {
279
             problems.clear();
220
             problems.clear();
343
         return manual;
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
      * Gets the chain of certificates currently being validated, if any.
288
      * Gets the chain of certificates currently being validated, if any.
361
      *
289
      *

Завантаження…
Відмінити
Зберегти