1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.security.authentication;
15
16 import java.io.InputStream;
17 import java.security.KeyStore;
18 import java.security.Principal;
19 import java.security.cert.CRL;
20 import java.security.cert.X509Certificate;
21 import java.util.Collection;
22
23 import javax.servlet.ServletRequest;
24 import javax.servlet.ServletResponse;
25 import javax.servlet.http.HttpServletRequest;
26 import javax.servlet.http.HttpServletResponse;
27
28 import org.eclipse.jetty.http.security.Constraint;
29 import org.eclipse.jetty.http.security.Password;
30 import org.eclipse.jetty.security.ServerAuthException;
31 import org.eclipse.jetty.security.UserAuthentication;
32 import org.eclipse.jetty.server.Authentication;
33 import org.eclipse.jetty.server.Authentication.User;
34 import org.eclipse.jetty.server.UserIdentity;
35 import org.eclipse.jetty.util.B64Code;
36 import org.eclipse.jetty.util.security.CertificateUtils;
37 import org.eclipse.jetty.util.security.CertificateValidator;
38
39
40
41
42 public class ClientCertAuthenticator extends LoginAuthenticator
43 {
44
45 private static final String PASSWORD_PROPERTY = "org.eclipse.jetty.ssl.password";
46
47
48 private String _trustStorePath;
49
50 private String _trustStoreProvider;
51
52 private String _trustStoreType = "JKS";
53
54 private transient Password _trustStorePassword;
55
56
57 private boolean _validateCerts;
58
59 private String _crlPath;
60
61 private int _maxCertPathLength = -1;
62
63 private boolean _enableCRLDP = false;
64
65 private boolean _enableOCSP = false;
66
67 private String _ocspResponderURL;
68
69 public ClientCertAuthenticator()
70 {
71 super();
72 }
73
74 public String getAuthMethod()
75 {
76 return Constraint.__CERT_AUTH;
77 }
78
79
80
81
82
83 public Authentication validateRequest(ServletRequest req, ServletResponse res, boolean mandatory) throws ServerAuthException
84 {
85 if (!mandatory)
86 return _deferred;
87
88 HttpServletRequest request = (HttpServletRequest)req;
89 HttpServletResponse response = (HttpServletResponse)res;
90 X509Certificate[] certs = (X509Certificate[]) request.getAttribute("javax.servlet.request.X509Certificate");
91
92 try
93 {
94
95 if (certs != null && certs.length > 0)
96 {
97
98 if (_validateCerts)
99 {
100 KeyStore trustStore = getKeyStore(null,
101 _trustStorePath, _trustStoreType, _trustStoreProvider,
102 _trustStorePassword == null ? null :_trustStorePassword.toString());
103 Collection<? extends CRL> crls = loadCRL(_crlPath);
104 CertificateValidator validator = new CertificateValidator(trustStore, crls);
105 validator.validate(certs);
106 }
107
108 for (X509Certificate cert: certs)
109 {
110 if (cert==null)
111 continue;
112
113 Principal principal = cert.getSubjectDN();
114 if (principal == null) principal = cert.getIssuerDN();
115 final String username = principal == null ? "clientcert" : principal.getName();
116
117 final char[] credential = B64Code.encode(cert.getSignature());
118
119 UserIdentity user = _loginService.login(username,credential);
120 if (user!=null)
121 {
122 renewSessionOnAuthentication(request,response);
123 return new UserAuthentication(getAuthMethod(),user);
124 }
125 }
126 }
127
128 if (!_deferred.isDeferred(response))
129 {
130 response.sendError(HttpServletResponse.SC_FORBIDDEN);
131 return Authentication.SEND_FAILURE;
132 }
133
134 return Authentication.UNAUTHENTICATED;
135 }
136 catch (Exception e)
137 {
138 throw new ServerAuthException(e.getMessage());
139 }
140 }
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158 protected KeyStore getKeyStore(InputStream storeStream, String storePath, String storeType, String storeProvider, String storePassword) throws Exception
159 {
160 return CertificateUtils.getKeyStore(storeStream, storePath, storeType, storeProvider, storePassword);
161 }
162
163
164
165
166
167
168
169
170
171
172
173
174
175 protected Collection<? extends CRL> loadCRL(String crlPath) throws Exception
176 {
177 return CertificateUtils.loadCRL(crlPath);
178 }
179
180 public boolean secureResponse(ServletRequest req, ServletResponse res, boolean mandatory, User validatedUser) throws ServerAuthException
181 {
182 return true;
183 }
184
185
186
187
188
189 public boolean isValidateCerts()
190 {
191 return _validateCerts;
192 }
193
194
195
196
197
198
199 public void setValidateCerts(boolean validateCerts)
200 {
201 _validateCerts = validateCerts;
202 }
203
204
205
206
207
208 public String getTrustStore()
209 {
210 return _trustStorePath;
211 }
212
213
214
215
216
217
218 public void setTrustStore(String trustStorePath)
219 {
220 _trustStorePath = trustStorePath;
221 }
222
223
224
225
226
227 public String getTrustStoreProvider()
228 {
229 return _trustStoreProvider;
230 }
231
232
233
234
235
236
237 public void setTrustStoreProvider(String trustStoreProvider)
238 {
239 _trustStoreProvider = trustStoreProvider;
240 }
241
242
243
244
245
246 public String getTrustStoreType()
247 {
248 return _trustStoreType;
249 }
250
251
252
253
254
255
256 public void setTrustStoreType(String trustStoreType)
257 {
258 _trustStoreType = trustStoreType;
259 }
260
261
262
263
264
265
266 public void setTrustStorePassword(String password)
267 {
268 _trustStorePassword = Password.getPassword(PASSWORD_PROPERTY,password,null);
269 }
270
271
272
273
274
275 public String getCrlPath()
276 {
277 return _crlPath;
278 }
279
280
281
282
283
284 public void setCrlPath(String crlPath)
285 {
286 _crlPath = crlPath;
287 }
288
289
290
291
292
293 public int getMaxCertPathLength()
294 {
295 return _maxCertPathLength;
296 }
297
298
299
300
301
302
303
304 public void setMaxCertPathLength(int maxCertPathLength)
305 {
306 _maxCertPathLength = maxCertPathLength;
307 }
308
309
310
311
312
313 public boolean isEnableCRLDP()
314 {
315 return _enableCRLDP;
316 }
317
318
319
320
321
322 public void setEnableCRLDP(boolean enableCRLDP)
323 {
324 _enableCRLDP = enableCRLDP;
325 }
326
327
328
329
330
331 public boolean isEnableOCSP()
332 {
333 return _enableOCSP;
334 }
335
336
337
338
339
340 public void setEnableOCSP(boolean enableOCSP)
341 {
342 _enableOCSP = enableOCSP;
343 }
344
345
346
347
348
349 public String getOcspResponderURL()
350 {
351 return _ocspResponderURL;
352 }
353
354
355
356
357
358 public void setOcspResponderURL(String ocspResponderURL)
359 {
360 _ocspResponderURL = ocspResponderURL;
361 }
362 }