Merge pull request #118 from owncloud/loggingtool
[pub/Android/ownCloud.git] / src / com / owncloud / android / network / AdvancedX509TrustManager.java
1 /* ownCloud Android client application
2 * Copyright (C) 2012-2013 ownCloud Inc.
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 2 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 com.owncloud.android.Log_OC;
36
37 import android.util.Log;
38
39 /**
40 * @author David A. Velasco
41 */
42 public class AdvancedX509TrustManager implements X509TrustManager {
43
44 private static final String TAG = AdvancedX509TrustManager.class.getSimpleName();
45
46 private X509TrustManager mStandardTrustManager = null;
47 private KeyStore mKnownServersKeyStore;
48
49 /**
50 * Constructor for AdvancedX509TrustManager
51 *
52 * @param knownServersCertStore Local certificates store with server certificates explicitly trusted by the user.
53 * @throws CertStoreException When no default X509TrustManager instance was found in the system.
54 */
55 public AdvancedX509TrustManager(KeyStore knownServersKeyStore)
56 throws NoSuchAlgorithmException, KeyStoreException, CertStoreException {
57 super();
58 TrustManagerFactory factory = TrustManagerFactory
59 .getInstance(TrustManagerFactory.getDefaultAlgorithm());
60 factory.init((KeyStore)null);
61 mStandardTrustManager = findX509TrustManager(factory);
62
63 mKnownServersKeyStore = knownServersKeyStore;
64 }
65
66
67 /**
68 * Locates the first X509TrustManager provided by a given TrustManagerFactory
69 * @param factory TrustManagerFactory to inspect in the search for a X509TrustManager
70 * @return The first X509TrustManager found in factory.
71 * @throws CertStoreException When no X509TrustManager instance was found in factory
72 */
73 private X509TrustManager findX509TrustManager(TrustManagerFactory factory) throws CertStoreException {
74 TrustManager tms[] = factory.getTrustManagers();
75 for (int i = 0; i < tms.length; i++) {
76 if (tms[i] instanceof X509TrustManager) {
77 return (X509TrustManager) tms[i];
78 }
79 }
80 return null;
81 }
82
83
84 /**
85 * @see javax.net.ssl.X509TrustManager#checkClientTrusted(X509Certificate[],
86 * String authType)
87 */
88 public void checkClientTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
89 mStandardTrustManager.checkClientTrusted(certificates, authType);
90 }
91
92
93 /**
94 * @see javax.net.ssl.X509TrustManager#checkServerTrusted(X509Certificate[],
95 * String authType)
96 */
97 public void checkServerTrusted(X509Certificate[] certificates, String authType) throws CertificateException {
98 if (!isKnownServer(certificates[0])) {
99 CertificateCombinedException result = new CertificateCombinedException(certificates[0]);
100 try {
101 certificates[0].checkValidity();
102 } catch (CertificateExpiredException c) {
103 result.setCertificateExpiredException(c);
104
105 } catch (CertificateNotYetValidException c) {
106 result.setCertificateNotYetException(c);
107 }
108
109 try {
110 mStandardTrustManager.checkServerTrusted(certificates, authType);
111 } catch (CertificateException c) {
112 Throwable cause = c.getCause();
113 Throwable previousCause = null;
114 while (cause != null && cause != previousCause && !(cause instanceof CertPathValidatorException)) { // getCause() is not funny
115 previousCause = cause;
116 cause = cause.getCause();
117 }
118 if (cause != null && cause instanceof CertPathValidatorException) {
119 result.setCertPathValidatorException((CertPathValidatorException)cause);
120 } else {
121 result.setOtherCertificateException(c);
122 }
123 }
124
125 if (result.isException())
126 throw result;
127
128 }
129 }
130
131
132 /**
133 * @see javax.net.ssl.X509TrustManager#getAcceptedIssuers()
134 */
135 public X509Certificate[] getAcceptedIssuers() {
136 return mStandardTrustManager.getAcceptedIssuers();
137 }
138
139
140 public boolean isKnownServer(X509Certificate cert) {
141 try {
142 return (mKnownServersKeyStore.getCertificateAlias(cert) != null);
143 } catch (KeyStoreException e) {
144 Log_OC.d(TAG, "Fail while checking certificate in the known-servers store");
145 return false;
146 }
147 }
148
149 }