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