1package eu.siacs.conversations.crypto;
2
3import android.util.Log;
4
5import com.google.common.collect.ImmutableList;
6
7import java.security.KeyStoreException;
8import java.security.NoSuchAlgorithmException;
9import java.security.cert.CertificateException;
10import java.security.cert.X509Certificate;
11import java.util.Arrays;
12import java.util.Iterator;
13import java.util.List;
14
15import javax.net.ssl.X509TrustManager;
16
17import eu.siacs.conversations.Config;
18
19public class CombiningTrustManager implements X509TrustManager {
20
21 private final List<X509TrustManager> trustManagers;
22
23 private CombiningTrustManager(final List<X509TrustManager> trustManagers) {
24 this.trustManagers = trustManagers;
25 }
26
27 @Override
28 public void checkClientTrusted(final X509Certificate[] chain, final String authType)
29 throws CertificateException {
30 for (final Iterator<X509TrustManager> iterator = this.trustManagers.iterator();
31 iterator.hasNext(); ) {
32 final X509TrustManager trustManager = iterator.next();
33 try {
34 trustManager.checkClientTrusted(chain, authType);
35 } catch (final CertificateException certificateException) {
36 if (iterator.hasNext()) {
37 continue;
38 }
39 throw certificateException;
40 }
41 }
42 }
43
44 @Override
45 public void checkServerTrusted(final X509Certificate[] chain, final String authType)
46 throws CertificateException {
47 Log.d(
48 Config.LOGTAG,
49 CombiningTrustManager.class.getSimpleName()
50 + " is configured with "
51 + this.trustManagers.size()
52 + " TrustManagers");
53 int i = 0;
54 for (final Iterator<X509TrustManager> iterator = this.trustManagers.iterator();
55 iterator.hasNext(); ) {
56 final X509TrustManager trustManager = iterator.next();
57 try {
58 trustManager.checkServerTrusted(chain, authType);
59 Log.d(
60 Config.LOGTAG,
61 "certificate check passed on " + trustManager.getClass().getName()+". chain length was "+chain.length);
62 return;
63 } catch (final CertificateException certificateException) {
64 Log.d(
65 Config.LOGTAG,
66 "failed to verify in [" + i + "]/" + trustManager.getClass().getName(),
67 certificateException);
68 if (iterator.hasNext()) {
69 continue;
70 }
71 throw certificateException;
72 } finally {
73 ++i;
74 }
75 }
76 }
77
78 @Override
79 public X509Certificate[] getAcceptedIssuers() {
80 final ImmutableList.Builder<X509Certificate> certificates = ImmutableList.builder();
81 for (final X509TrustManager trustManager : this.trustManagers) {
82 for (final X509Certificate certificate : trustManager.getAcceptedIssuers()) {
83 certificates.add(certificate);
84 }
85 }
86 return certificates.build().toArray(new X509Certificate[0]);
87 }
88
89 public static X509TrustManager combineWithDefault(final X509TrustManager... trustManagers)
90 throws NoSuchAlgorithmException, KeyStoreException {
91 final ImmutableList.Builder<X509TrustManager> builder = ImmutableList.builder();
92 builder.addAll(Arrays.asList(trustManagers));
93 builder.add(TrustManagers.createDefaultTrustManager());
94 return new CombiningTrustManager(builder.build());
95 }
96}