KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > mortbay > http > ClientCertAuthenticator


1 // ========================================================================
2
// $Id: ClientCertAuthenticator.java,v 1.15 2006/02/28 12:45:01 gregwilkins Exp $
3
// Copyright 2002-2004 Mort Bay Consulting Pty. Ltd.
4
// ------------------------------------------------------------------------
5
// Licensed under the Apache License, Version 2.0 (the "License");
6
// you may not use this file except in compliance with the License.
7
// You may obtain a copy of the License at
8
// http://www.apache.org/licenses/LICENSE-2.0
9
// Unless required by applicable law or agreed to in writing, software
10
// distributed under the License is distributed on an "AS IS" BASIS,
11
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
// See the License for the specific language governing permissions and
13
// limitations under the License.
14
// ========================================================================
15

16 package org.mortbay.http;
17
18 import java.io.IOException JavaDoc;
19 import java.security.Principal JavaDoc;
20
21 import javax.net.ssl.SSLSocket;
22
23 import org.apache.commons.logging.Log;
24 import org.mortbay.log.LogFactory;
25
26 /* ------------------------------------------------------------ */
27 /** Client Certificate Authenticator.
28  * This Authenticator uses a client certificate to authenticate the user.
29  * Each client certificate supplied is tried against the realm using the
30  * Principal name as the username and a string representation of the
31  * certificate as the credential.
32  * @version $Id: ClientCertAuthenticator.java,v 1.15 2006/02/28 12:45:01 gregwilkins Exp $
33  * @author Greg Wilkins (gregw)
34  */

35 public class ClientCertAuthenticator implements Authenticator
36 {
37     private static Log log = LogFactory.getLog(ClientCertAuthenticator.class);
38
39     private int _maxHandShakeSeconds =60;
40     
41     /* ------------------------------------------------------------ */
42     public ClientCertAuthenticator()
43     {
44         log.warn("Client Cert Authentication is EXPERIMENTAL");
45     }
46     
47     /* ------------------------------------------------------------ */
48     public int getMaxHandShakeSeconds()
49     {
50         return _maxHandShakeSeconds;
51     }
52     
53     /* ------------------------------------------------------------ */
54     /**
55      * @param maxHandShakeSeconds Maximum time to wait for SSL handshake if
56      * Client certification is required.
57      */

58     public void setMaxHandShakeSeconds(int maxHandShakeSeconds)
59     {
60         _maxHandShakeSeconds = maxHandShakeSeconds;
61     }
62     
63     /* ------------------------------------------------------------ */
64     /**
65      * @return UserPrinciple if authenticated or null if not. If
66      * Authentication fails, then the authenticator may have committed
67      * the response as an auth challenge or redirect.
68      * @exception IOException
69      */

70     public Principal JavaDoc authenticate(UserRealm realm,
71                                   String JavaDoc pathInContext,
72                                   HttpRequest request,
73                                   HttpResponse response)
74         throws IOException JavaDoc
75     {
76         java.security.cert.X509Certificate JavaDoc[] certs =
77             (java.security.cert.X509Certificate JavaDoc[])
78             request.getAttribute("javax.servlet.request.X509Certificate");
79             
80         if (response!=null && (certs==null || certs.length==0 || certs[0]==null))
81         {
82             // No certs available so lets try and force the issue
83

84             // Get the SSLSocket
85
Object JavaDoc s = HttpConnection.getHttpConnection().getConnection();
86             if (!(s instanceof SSLSocket))
87                 return null;
88             SSLSocket socket = (SSLSocket)s;
89             
90             if (!socket.getNeedClientAuth())
91             {
92                 // Need to re-handshake
93
socket.setNeedClientAuth(true);
94                 socket.startHandshake();
95
96                 // Need to wait here - but not forever. The Handshake
97
// Listener API does not look like a good option to
98
// avoid waiting forever. So we will take a slightly
99
// busy timelimited approach. For now:
100
for (int i=(_maxHandShakeSeconds*4);i-->0;)
101                 {
102                     certs = (java.security.cert.X509Certificate JavaDoc[])
103                         request.getAttribute("javax.servlet.request.X509Certificate");
104                     if (certs!=null && certs.length>0 && certs[0]!=null)
105                         break;
106                     try{Thread.sleep(250);} catch (Exception JavaDoc e) {break;}
107                 }
108             }
109         }
110
111         if (certs==null || certs.length==0 || certs[0]==null)
112             return null;
113         
114         Principal JavaDoc principal = certs[0].getSubjectDN();
115         if (principal==null)
116             principal=certs[0].getIssuerDN();
117         String JavaDoc username=principal==null?"clientcert":principal.getName();
118         
119         Principal JavaDoc user = realm.authenticate(username,certs,request);
120         
121         request.setAuthType(SecurityConstraint.__CERT_AUTH);
122         if (user!=null)
123             request.setAuthUser(user.getName());
124         request.setUserPrincipal(user);
125         return user;
126     }
127     
128     /* ------------------------------------------------------------ */
129     public String JavaDoc getAuthMethod()
130     {
131         return SecurityConstraint.__CERT_AUTH;
132     }
133
134 }
135
Popular Tags