1package eu.siacs.conversations.crypto;
2
3import android.annotation.SuppressLint;
4import android.util.Log;
5import com.google.common.collect.ImmutableList;
6import eu.siacs.conversations.Config;
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;
14import javax.net.ssl.X509TrustManager;
15
16@SuppressLint("CustomX509TrustManager")
17public final class CombiningTrustManager implements X509TrustManager {
18
19 private final List<X509TrustManager> trustManagers;
20
21 private CombiningTrustManager(final List<X509TrustManager> trustManagers) {
22 this.trustManagers = trustManagers;
23 }
24
25 @Override
26 public void checkClientTrusted(final X509Certificate[] chain, final String authType)
27 throws CertificateException {
28 for (final Iterator<X509TrustManager> iterator = this.trustManagers.iterator();
29 iterator.hasNext(); ) {
30 final X509TrustManager trustManager = iterator.next();
31 try {
32 trustManager.checkClientTrusted(chain, authType);
33 return;
34 } catch (final CertificateException certificateException) {
35 if (iterator.hasNext()) {
36 continue;
37 }
38 throw certificateException;
39 }
40 }
41 throw new CertificateException("No trust managers configured");
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 for (final Iterator<X509TrustManager> iterator = this.trustManagers.iterator();
54 iterator.hasNext(); ) {
55 final X509TrustManager trustManager = iterator.next();
56 try {
57 trustManager.checkServerTrusted(chain, authType);
58 return;
59 } catch (final CertificateException certificateException) {
60 if (iterator.hasNext()) {
61 continue;
62 }
63 throw certificateException;
64 }
65 }
66 throw new CertificateException("No trust managers configured");
67 }
68
69 @Override
70 public X509Certificate[] getAcceptedIssuers() {
71 final ImmutableList.Builder<X509Certificate> certificates = ImmutableList.builder();
72 for (final X509TrustManager trustManager : this.trustManagers) {
73 for (final X509Certificate certificate : trustManager.getAcceptedIssuers()) {
74 certificates.add(certificate);
75 }
76 }
77 return certificates.build().toArray(new X509Certificate[0]);
78 }
79
80 public static X509TrustManager combineWithDefault(final X509TrustManager... trustManagers)
81 throws NoSuchAlgorithmException, KeyStoreException {
82 final ImmutableList.Builder<X509TrustManager> builder = ImmutableList.builder();
83 builder.addAll(Arrays.asList(trustManagers));
84 builder.add(TrustManagers.createDefaultTrustManager());
85 return new CombiningTrustManager(builder.build());
86 }
87}