Fixed crash when the device is turned while the warning dialog about server certifica...
[pub/Android/ownCloud.git] / src / com / owncloud / android / network / AdvancedX509TrustManager.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012 Bartek Przybylski
3 *
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License as published by
6 * the Free Software Foundation, either version 3 of the License, or
7 * (at your option) any later version.
8 *
9 * This program is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 * GNU General Public License for more details.
13 *
14 * You should have received a copy of the GNU General Public License
15 * along with this program. If not, see <http://www.gnu.org/licenses/>.
16 *
17 */
18
19 package com.owncloud.android.network;
20
21 import java.security.KeyStore;
22 import java.security.KeyStoreException;
23 import java.security.NoSuchAlgorithmException;
24 import java.security.cert.CertPathValidatorException;
25 import java.security.cert.CertStoreException;
26 import java.security.cert.CertificateException;
27 import java.security.cert.CertificateExpiredException;
28 import java.security.cert.CertificateNotYetValidException;
29 import java.security.cert.X509Certificate;
30
31 import javax.net.ssl.TrustManager;
32 import javax.net.ssl.TrustManagerFactory;
33 import javax.net.ssl.X509TrustManager;
34
35 import android.util.Log;
36
37 /**
38 * @author David A. Velasco
39 */
40 public class AdvancedX509TrustManager implements X509TrustManager {
41
42 private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
43
44 private X509TrustManager mStandardTrustManager = null;
45 private KeyStore mKnownServersKeyStore;
46
47 /**
48 * Constructor for AdvancedX509TrustManager
49 *
50 * @param knownServersCertStore Local certificates store with server certificates explicitly trusted by the user.
51 * @throws CertStoreException When no default X509TrustManager instance was found in the system.
52 */
53 public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
54 throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
55 super();
56 TrustManagerFactory factory = TrustManagerFactory
57 .getInstance(TrustManagerFactory.getDefaultAlgorithm());
58 factory.init((KeyStore)null);
59 mStandardTrustManager = findX509TrustManager(factory);
60
61 mKnownServersKeyStore = knownServersKeyStore;
62 }
63
64
65 /**
66 * Locates the first X509TrustManager provided by a given TrustManagerFactory
67 * @param factory TrustManagerFactory to inspect in the search for a X509TrustManager
68 * @return The first X509TrustManager found in factory.
69 * @throws CertStoreException When no X509TrustManager instance was found in factory
70 */
71 private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
72 TrustManager tms[] = factory.getTrustManagers();
73 for (int i = 0; i < tms.length; i++) {
74 if (tms[i] instanceof X509TrustManager) {
75 return (X509TrustManager) tms[i];
76 }
77 }
78 return null;
79 }
80
81
82 /**
83 * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
84 * String authType)
85 */
86 public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
87 mStandardTrustManager.checkClientTrusted(certificates, authType);
88 }
89
90
91 /**
92 * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
93 * String authType)
94 */
95 public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
96 if (!isKnownServer(certificates[0])) {
97 CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
98 try {
99 certificates[0].checkValidity();
100 } catch (CertificateExpiredException c) {
101 result.setCertificateExpiredException(c);
102
103 } catch (CertificateNotYetValidException c) {
104 result.setCertificateNotYetException(c);
105 }
106
107 try {
108 mStandardTrustManager.checkServerTrusted(certificates, authType);
109 } catch (CertificateException c) {
110 Throwable cause = c.getCause();
111 Throwable previousCause = null;
112 while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) { // getCause() is not funny
113 previousCause = cause;
114 cause = cause.getCause();
115 }
116 if (cause != null && cause instanceof CertPathValidatorException) {
117 result.setCertPathValidatorException((CertPathValidatorException)cause);
118 } else {
119 result.setOtherCertificateException(c);
120 }
121 }
122
123 if (result.isException())
124 throw result;
125
126 }
127 }
128
129
130 /**
131 * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
132 */
133 public X509Certificate[] getAcceptedIssuers() {
134 return mStandardTrustManager.getAcceptedIssuers();
135 }
136
137
138 public boolean isKnownServer(X509Certificate cert) {
139 try {
140 return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
141 } catch (KeyStoreException e) {
142 Log.d(TAG, "Fail while checking certificate in the known-servers store");
143 return false;
144 }
145 }
146
147 }