CombiningTrustManager.java

 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}