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 }