1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 package org.archive.httpclient;
24
25 import java.security.KeyStore;
26 import java.security.KeyStoreException;
27 import java.security.NoSuchAlgorithmException;
28 import java.security.cert.CertificateException;
29 import java.security.cert.X509Certificate;
30 import java.util.Arrays;
31 import java.util.List;
32 import java.util.logging.Logger;
33
34 import javax.net.ssl.TrustManager;
35 import javax.net.ssl.TrustManagerFactory;
36 import javax.net.ssl.X509TrustManager;
37
38 /***
39 * A configurable trust manager built on X509TrustManager.
40 *
41 * If set to 'open' trust, the default, will get us into sites for whom we do
42 * not have the CA or any of intermediary CAs that go to make up the cert chain
43 * of trust. Will also get us past selfsigned and expired certs. 'loose'
44 * trust will get us into sites w/ valid certs even if they are just
45 * selfsigned. 'normal' is any valid cert not including selfsigned. 'strict'
46 * means cert must be valid and the cert DN must match server name.
47 *
48 * <p>Based on pointers in
49 * <a href="http://jakarta.apache.org/commons/httpclient/sslguide.html">SSL
50 * Guide</a>,
51 * and readings done in <a
52 * href="http://java.sun.com/j2se/1.4.2/docs/guide/security/jsse/JSSERefGuide.html#Introduction">JSSE
53 * Guide</a>.
54 *
55 * <p>TODO: Move to an ssl subpackage when we have other classes other than
56 * just this one.
57 *
58 * @author stack
59 * @version $Id: ConfigurableX509TrustManager.java 4232 2006-05-15 21:52:30Z stack-sf $
60 */
61 public class ConfigurableX509TrustManager implements X509TrustManager
62 {
63 /***
64 * Logging instance.
65 */
66 protected static Logger logger = Logger.getLogger(
67 "org.archive.httpclient.ConfigurableX509TrustManager");
68
69 /***
70 * Trust anything given us.
71 *
72 * Default setting.
73 *
74 * <p>See <a href="http://javaalmanac.com/egs/javax.net.ssl/TrustAll.html">
75 * e502. Disabling Certificate Validation in an HTTPS Connection</a> from
76 * the java almanac for how to trust all.
77 */
78 public final static String OPEN = "open";
79
80 /***
81 * Trust any valid cert including self-signed certificates.
82 */
83 public final static String LOOSE = "loose";
84
85 /***
86 * Normal jsse behavior.
87 *
88 * Seemingly any certificate that supplies valid chain of trust.
89 */
90 public final static String NORMAL = "normal";
91
92 /***
93 * Strict trust.
94 *
95 * Ensure server has same name as cert DN.
96 */
97 public final static String STRICT = "strict";
98
99 /***
100 * All the levels of trust as an array from babe-in-the-wood to strict.
101 */
102 public static String [] LEVELS_AS_ARRAY = {OPEN, LOOSE, NORMAL, STRICT};
103
104 /***
105 * Levels as a list.
106 */
107 private static List LEVELS = Arrays.asList(LEVELS_AS_ARRAY);
108
109 /***
110 * Default setting for trust level.
111 */
112 public final static String DEFAULT = OPEN;
113
114 /***
115 * Trust level.
116 */
117 private String trustLevel = DEFAULT;
118
119
120 /***
121 * An instance of the SUNX509TrustManager that we adapt variously
122 * depending upon passed configuration.
123 *
124 * We have it do all the work we don't want to.
125 */
126 private X509TrustManager standardTrustManager = null;
127
128
129 public ConfigurableX509TrustManager()
130 throws NoSuchAlgorithmException, KeyStoreException {
131 this(DEFAULT);
132 }
133
134 /***
135 * Constructor.
136 *
137 * @param level Level of trust to effect.
138 *
139 * @throws NoSuchAlgorithmException
140 * @throws KeyStoreException
141 */
142 public ConfigurableX509TrustManager(String level)
143 throws NoSuchAlgorithmException, KeyStoreException {
144 super();
145 TrustManagerFactory factory = TrustManagerFactory.
146 getInstance(TrustManagerFactory.getDefaultAlgorithm());
147
148
149
150
151
152
153 factory.init((KeyStore)null);
154 TrustManager[] trustmanagers = factory.getTrustManagers();
155 if (trustmanagers.length == 0) {
156 throw new NoSuchAlgorithmException(TrustManagerFactory.
157 getDefaultAlgorithm() + " trust manager not supported");
158 }
159 this.standardTrustManager = (X509TrustManager)trustmanagers[0];
160
161 this.trustLevel =
162 (LEVELS.contains(level.toLowerCase()))? level: DEFAULT;
163 }
164
165 public void checkClientTrusted(X509Certificate[] certificates, String type)
166 throws CertificateException {
167 if (this.trustLevel.equals(OPEN)) {
168 return;
169 }
170
171 this.standardTrustManager.checkClientTrusted(certificates, type);
172 }
173
174 public void checkServerTrusted(X509Certificate[] certificates, String type)
175 throws CertificateException {
176 if (this.trustLevel.equals(OPEN)) {
177 return;
178 }
179
180 try {
181 this.standardTrustManager.checkServerTrusted(certificates, type);
182 if (this.trustLevel.equals(STRICT)) {
183 logger.severe(STRICT + " not implemented.");
184 }
185 } catch (CertificateException e) {
186 if (this.trustLevel.equals(LOOSE) &&
187 certificates != null && certificates.length == 1)
188 {
189
190
191 X509Certificate certificate = certificates[0];
192 certificate.checkValidity();
193 } else {
194
195 throw e;
196 }
197 }
198 }
199
200 public X509Certificate[] getAcceptedIssuers() {
201 return this.standardTrustManager.getAcceptedIssuers();
202 }
203 }