|
@@ -285,24 +285,55 @@ public class CertificateManager implements X509TrustManager {
|
285
|
285
|
@Override
|
286
|
286
|
public void checkServerTrusted(final X509Certificate[] chain, final String authType)
|
287
|
287
|
throws CertificateException {
|
288
|
|
- this.chain = chain;
|
|
288
|
+ this.chain = Arrays.copyOf(chain, chain.length);
|
289
|
289
|
problems.clear();
|
290
|
290
|
|
291
|
|
- boolean verified = false;
|
292
|
|
- boolean manual = false;
|
|
291
|
+ checkHost(chain);
|
293
|
292
|
|
294
|
|
- if (checkHost) {
|
295
|
|
- // Check that the cert is issued to the correct host
|
296
|
|
- verified = isValidHost(chain[0]);
|
|
293
|
+ if (checkIssuer(chain)) {
|
|
294
|
+ problems.clear();
|
|
295
|
+ }
|
297
|
296
|
|
298
|
|
- if (!verified) {
|
299
|
|
- problems.add(new CertificateDoesntMatchHostException(
|
300
|
|
- "Certificate was not issued to " + serverName));
|
|
297
|
+ if (!problems.isEmpty()) {
|
|
298
|
+ eventBus.publishAsync(new ServerCertificateProblemEncounteredEvent(connection, this,
|
|
299
|
+ Arrays.asList(chain), problems));
|
|
300
|
+
|
|
301
|
+ try {
|
|
302
|
+ actionSem.acquire();
|
|
303
|
+ } catch (InterruptedException ie) {
|
|
304
|
+ throw new CertificateException("Thread aborted", ie);
|
|
305
|
+ } finally {
|
|
306
|
+ problems.clear();
|
|
307
|
+ eventBus.publishAsync(new ServerCertificateProblemResolvedEvent(connection, this));
|
301
|
308
|
}
|
302
|
309
|
|
303
|
|
- verified = false;
|
|
310
|
+ switch (action) {
|
|
311
|
+ case DISCONNECT:
|
|
312
|
+ throw new CertificateException("Not trusted");
|
|
313
|
+ case IGNORE_PERMANENTLY:
|
|
314
|
+ final List<String> list = new ArrayList<>(config
|
|
315
|
+ .getOptionList("ssl", "trusted"));
|
|
316
|
+ list.add(Base64.getEncoder().encodeToString(chain[0].getSignature()));
|
|
317
|
+ userSettings.setOption("ssl", "trusted", list);
|
|
318
|
+ break;
|
|
319
|
+ case IGNORE_TEMPORARILY:
|
|
320
|
+ // Do nothing, continue connecting
|
|
321
|
+ break;
|
|
322
|
+ }
|
304
|
323
|
}
|
|
324
|
+ }
|
305
|
325
|
|
|
326
|
+ /**
|
|
327
|
+ * Checks that some issuer in the certificate chain is trusted, either by the global CA list,
|
|
328
|
+ * or manually by the user.
|
|
329
|
+ *
|
|
330
|
+ * @param chain The chain of certificates to check.
|
|
331
|
+ * @return True if the certificate is trusted manually, false otherwise (i.e., trusted globally
|
|
332
|
+ * OR untrusted).
|
|
333
|
+ */
|
|
334
|
+ private boolean checkIssuer(final X509Certificate... chain) {
|
|
335
|
+ boolean manual = false;
|
|
336
|
+ boolean verified = false;
|
306
|
337
|
for (X509Certificate cert : chain) {
|
307
|
338
|
final TrustResult trustResult = isTrusted(cert);
|
308
|
339
|
|
|
@@ -317,7 +348,6 @@ public class CertificateManager implements X509TrustManager {
|
317
|
348
|
|
318
|
349
|
if (checkIssuer) {
|
319
|
350
|
// Check that we trust an issuer
|
320
|
|
-
|
321
|
351
|
verified |= trustResult.isTrusted();
|
322
|
352
|
}
|
323
|
353
|
|
|
@@ -329,38 +359,22 @@ public class CertificateManager implements X509TrustManager {
|
329
|
359
|
if (!verified && checkIssuer) {
|
330
|
360
|
problems.add(new CertificateNotTrustedException("Issuer is not trusted"));
|
331
|
361
|
}
|
|
362
|
+ return manual;
|
|
363
|
+ }
|
332
|
364
|
|
333
|
|
- if (!problems.isEmpty() && !manual) {
|
334
|
|
- eventBus.publishAsync(new ServerCertificateProblemEncounteredEvent(
|
335
|
|
- connection, this, Arrays.asList(chain), problems));
|
336
|
|
-
|
337
|
|
- try {
|
338
|
|
- actionSem.acquire();
|
339
|
|
- } catch (InterruptedException ie) {
|
340
|
|
- throw new CertificateException("Thread aborted", ie);
|
341
|
|
- } finally {
|
342
|
|
- problems.clear();
|
343
|
|
-
|
344
|
|
- eventBus.publishAsync(new ServerCertificateProblemResolvedEvent(connection, this));
|
345
|
|
- }
|
346
|
|
-
|
347
|
|
- switch (action) {
|
348
|
|
- case DISCONNECT:
|
349
|
|
- throw new CertificateException("Not trusted");
|
350
|
|
- case IGNORE_PERMANENTLY:
|
351
|
|
- final List<String> list = new ArrayList<>(config
|
352
|
|
- .getOptionList("ssl", "trusted"));
|
353
|
|
- list.add(Base64.getEncoder().encodeToString(chain[0].getSignature()));
|
354
|
|
- userSettings.setOption("ssl", "trusted", list);
|
355
|
|
- break;
|
356
|
|
- case IGNORE_TEMPORARILY:
|
357
|
|
- // Do nothing, continue connecting
|
358
|
|
- break;
|
|
365
|
+ /**
|
|
366
|
+ * Checks that the host of the leaf certificate is the same as the server we are connected to.
|
|
367
|
+ *
|
|
368
|
+ * @param chain The chain of certificates to check.
|
|
369
|
+ */
|
|
370
|
+ private void checkHost(final X509Certificate... chain) {
|
|
371
|
+ if (checkHost) {
|
|
372
|
+ // Check that the cert is issued to the correct host
|
|
373
|
+ if (!isValidHost(chain[0])) {
|
|
374
|
+ problems.add(new CertificateDoesntMatchHostException(
|
|
375
|
+ "Certificate was not issued to " + serverName));
|
359
|
376
|
}
|
360
|
377
|
}
|
361
|
|
- if (manual) {
|
362
|
|
- problems.clear();
|
363
|
|
- }
|
364
|
378
|
}
|
365
|
379
|
|
366
|
380
|
/**
|
|
@@ -429,4 +443,4 @@ public class CertificateManager implements X509TrustManager {
|
429
|
443
|
return globalTrustedCAs.toArray(new X509Certificate[globalTrustedCAs.size()]);
|
430
|
444
|
}
|
431
|
445
|
|
432
|
|
-}
|
|
446
|
+}
|