View Javadoc

1   // ========================================================================
2   // Copyright 2002-2005 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // Licensed under the Apache License, Version 2.0 (the "License");
5   // you may not use this file except in compliance with the License.
6   // You may obtain a copy of the License at 
7   // http://www.apache.org/licenses/LICENSE-2.0
8   // Unless required by applicable law or agreed to in writing, software
9   // distributed under the License is distributed on an "AS IS" BASIS,
10  // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
11  // See the License for the specific language governing permissions and
12  // limitations under the License.
13  // ========================================================================
14  
15  package org.mortbay.jetty.security;
16  
17  import java.io.IOException;
18  import java.security.Principal;
19  
20  import javax.servlet.http.HttpServletResponse;
21  
22  import org.mortbay.jetty.Request;
23  import org.mortbay.jetty.Response;
24  
25  /* ------------------------------------------------------------ */
26  /** Client Certificate Authenticator.
27   * This Authenticator uses a client certificate to authenticate the user.
28   * Each client certificate supplied is tried against the realm using the
29   * Principal name as the username and a string representation of the
30   * certificate as the credential.
31   * @author Greg Wilkins (gregw)
32   */
33  public class ClientCertAuthenticator implements Authenticator
34  {
35      private int _maxHandShakeSeconds =60;
36      
37      /* ------------------------------------------------------------ */
38      public ClientCertAuthenticator()
39      {
40      }
41      
42      /* ------------------------------------------------------------ */
43      public int getMaxHandShakeSeconds()
44      {
45          return _maxHandShakeSeconds;
46      }
47      
48      /* ------------------------------------------------------------ */
49      /** 
50       * @param maxHandShakeSeconds Maximum time to wait for SSL handshake if
51       * Client certification is required.
52       */
53      public void setMaxHandShakeSeconds(int maxHandShakeSeconds)
54      {
55          _maxHandShakeSeconds = maxHandShakeSeconds;
56      }
57      
58      /* ------------------------------------------------------------ */
59      /** 
60       * @return UserPrinciple if authenticated or null if not. If
61       * Authentication fails, then the authenticator may have committed
62       * the response as an auth challenge or redirect.
63       * @exception IOException 
64       */
65      public Principal authenticate(UserRealm realm,
66              String pathInContext,
67              Request request,
68              Response response)
69          throws IOException
70      {
71          java.security.cert.X509Certificate[] certs =
72              (java.security.cert.X509Certificate[])
73              request.getAttribute("javax.servlet.request.X509Certificate");
74              
75          // Need certificates.
76          if (certs==null || certs.length==0 || certs[0]==null)
77          {
78              if (response != null)
79                  response.sendError(HttpServletResponse.SC_FORBIDDEN,"A client certificate is required for accessing this web application but the server's listener is not configured for mutual authentication (or the client did not provide a certificate).");
80              return null;
81          }
82          
83          Principal principal = certs[0].getSubjectDN();
84          if (principal==null)
85              principal=certs[0].getIssuerDN();
86          String username=principal==null?"clientcert":principal.getName();
87          
88          Principal user = realm.authenticate(username,certs,request);
89          if (user == null)
90          {
91              if (response != null)
92                  response.sendError(HttpServletResponse.SC_FORBIDDEN,"The provided client certificate does not correspond to a trusted user.");
93              return null;
94          }
95          
96          request.setAuthType(Constraint.__CERT_AUTH);
97          request.setUserPrincipal(user);                
98          return user;
99      }
100     
101     /* ------------------------------------------------------------ */
102     public String getAuthMethod()
103     {
104         return Constraint.__CERT_AUTH;
105     }
106 
107 }