Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
  /*
  * JBoss, Home of Professional Open Source
  * Copyright 2005, JBoss Inc., and individual contributors as indicated
  * by the @authors tag. See the copyright.txt in the distribution for a
  * full listing of individual contributors.
  *
  * This is free software; you can redistribute it and/or modify it
  * under the terms of the GNU Lesser General Public License as
  * published by the Free Software Foundation; either version 2.1 of
 * the License, or (at your option) any later version.
 *
 * This software is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this software; if not, write to the Free
 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
 */
 package org.jboss.security.auth.spi;
 
 import java.util.Map;
 
 
Base Login Module that uses X509Certificates as credentials for authentication. This login module uses X509Certificates as a credential. It takes the cert as an object and checks to see if the alias in the truststore/keystore contains the same certificate. Subclasses of this module should implement the getRoleSets() method defined by AbstractServerLoginModule. Much of this module was patterned after the UserNamePasswordLoginModule.

Author(s):
Jason Essington
Scott.Stark@jboss.org
Version:
$Revision: 73520 $
 
 {
   
A principal derived from the certificate alias
 
    private Principal identity;
   
The client certificate
 
    private X509Certificate credential;
   
The SecurityDomain to obtain the KeyStore/TrustStore from
 
    private SecurityDomain domain = null;
   
An option certificate verifier
 
    private X509CertificateVerifier verifier;
   
The trace level log flag
 
    private boolean trace;

   
Override the super version to pickup the following options after first calling the super method. option: securityDomain - the name of the SecurityDomain to obtain the trust and keystore from. option: verifier - the class name of the X509CertificateVerifier to use for verification of the login certificate

Parameters:
subject the Subject to update after a successful login.
callbackHandler the CallbackHandler that will be used to obtain the the user identity and credentials.
sharedState a Map shared between all configured login module instances
options the parameters passed to the login module.
See also:
org.jboss.security.SecurityDomain
org.jboss.security.auth.certs.X509CertificateVerifier
 
    public void initialize(Subject subjectCallbackHandler callbackHandler,
       Map<String,?> sharedStateMap<String,?> options)
    {
       super.initialize(subjectcallbackHandlersharedStateoptions);
        = .isTraceEnabled();
 
       // Get the security domain and default to "other"
      String sd = (Stringoptions.get("securityDomain");
      if (sd == null)
         sd = "java:/jaas/other";
      if )
         .trace("securityDomain=" + sd);
      try
      {
         Object tempDomain = new InitialContext().lookup(sd);
         if (tempDomain instanceof SecurityDomain)
         {
             = (SecurityDomaintempDomain;
            if )
            {
               if ( != null)
                  .trace("found domain: " + .getClass().getName());
               else
                  .trace("the domain " + sd + " is null!");
            }
         }
         else
         {
            .error("The domain " + sd + " is not a SecurityDomain. All authentication using this module will fail!");
         }
      }
      catch (NamingException e)
      {
         .error("Unable to find the securityDomain named: " + sde);
      }
      String option = (Stringoptions.get("verifier");
      ifoption != null )
      {
         try
         {
            ClassLoader loader = SecurityActions.getContextClassLoader();
            Class<?> verifierClass = loader.loadClass(option);
             = (X509CertificateVerifierverifierClass.newInstance();
         }
         catch(Throwable e)
         {
            if )
               .trace("Failed to create X509CertificateVerifier"e);
            IllegalArgumentException ex = new IllegalArgumentException("Invalid verifier: "+option);
            ex.initCause(e);
         }
      }
      if )
         .trace("exit: initialize(Subject, CallbackHandler, Map, Map)");
   }

   
Perform the authentication of the username and password.
   @SuppressWarnings("unchecked")
   public boolean login() throws LoginException
   {
      if )
         .trace("enter: login()");
      // See if shared credentials exist
      if (super.login() == true)
      {
         // Setup our view of the user
         Object username = .get("javax.security.auth.login.name");
         ifusername instanceof Principal )
             = (Principalusername;
         else
         {
            String name = username.toString();
            try
            {
                = createIdentity(name);
            }
            catch(Exception e)
            {
               .debug("Failed to create principal"e);
               throw new LoginException("Failed to create principal: "e.getMessage());
            }
         }
         Object password = .get("javax.security.auth.login.password");
         if (password instanceof X509Certificate)
             = (X509Certificatepassword;
         else if (password != null)
         {
            .debug("javax.security.auth.login.password is not X509Certificate");
            super. = false;
            return false;
         }
         return true;
      }
      super. = false;
      Object[] info = getAliasAndCert();
      String alias = (Stringinfo[0];
       = (X509Certificateinfo[1];
      if (alias == null &&  == null)
      {
          = ;
         super..trace("Authenticating as unauthenticatedIdentity=" + );
      }
      if ( == null)
      {
         try
         {
             = createIdentity(alias);
         }
         catch(Exception e)
         {
            .debug("Failed to create identity for alias:"+aliase);
         }
         if (!validateCredential(alias))
         {
            .debug("Bad credential for alias=" + alias);
            throw new FailedLoginException("Supplied Credential did not match existing credential for " + alias);
         }
      }
      if (getUseFirstPass() == true)
      {
         // Add authentication info to shared state map
         .put("javax.security.auth.login.name"alias);
         .put("javax.security.auth.login.password");
      }
      super. = true;
      if )
      {
         .trace("User '" +  + "' authenticated, loginOk=" + );
         .debug("exit: login()");
      }
      return true;
   }

   
Override to add the X509Certificate to the public credentials

   public boolean commit() throws LoginException
   {
      boolean ok = super.commit();
      ifok == true )
      {
         // Add the cert to the public credentials
         if ( != null)
         {
            .getPublicCredentials().add();
         }
      }
      return ok;
   }

   
Subclasses need to override this to provide the roles for authorization

   protected Group[] getRoleSets() throws LoginException
   {
      return new Group[0];
   }
   protected Principal getIdentity()
   {
      return ;
   }
   protected Object getCredentials()
   {
      return ;
   }
   protected String getUsername()
   {
      String username = null;
      if (getIdentity() != null)
         username = getIdentity().getName();
      return username;
   }
   protected Object[] getAliasAndCert() throws LoginException
   {
      if )
         .trace("enter: getAliasAndCert()");
      Object[] info = { nullnull };
      // prompt for a username and password
      if ( == null)
      {
         throw new LoginException("Error: no CallbackHandler available to collect authentication information");
      }
      NameCallback nc = new NameCallback("Alias: ");
      ObjectCallback oc = new ObjectCallback("Certificate: ");
      Callback[] callbacks = { ncoc };
      String alias = null;
      X509Certificate cert = null;
      X509Certificate[] certChain;
      try
      {
         .handle(callbacks);
         alias = nc.getName();
         Object tmpCert = oc.getCredential();
         if (tmpCert != null)
         {
            if (tmpCert instanceof X509Certificate)
            {
               cert = (X509CertificatetmpCert;
               if )
                  .trace("found cert " + cert.getSerialNumber().toString(16) + ":" + cert.getSubjectDN().getName());
            }
            else iftmpCert instanceof X509Certificate[] )
            {
               certChain = (X509Certificate[]) tmpCert;
               ifcertChain.length > 0 )
                  cert = certChain[0];
            }
            else
            {
               String msg = "Don't know how to obtain X509Certificate from: "
                  +tmpCert.getClass();
               .warn(msg);
               throw new LoginException(msg);
            }
         }
         else
         {
            .warn("CallbackHandler did not provide a certificate");
         }
      }
      catch (IOException e)
      {
         .debug("Failed to invoke callback"e);
         throw new LoginException("Failed to invoke callback: "+e.toString());
      }
      catch (UnsupportedCallbackException uce)
      {
         throw new LoginException("CallbackHandler does not support: "
            + uce.getCallback());
      }
      info[0] = alias;
      info[1] = cert;
      if )
         .trace("exit: getAliasAndCert()");
      return info;
   }
   protected boolean validateCredential(String aliasX509Certificate cert)
   {
      if )
         .trace("enter: validateCredentail(String, X509Certificate)");
      boolean isValid = false;
      // if we don't have a trust store, we'll just use the key store.
      KeyStore keyStore = null;
      KeyStore trustStore = null;
      if != null )
      {
         keyStore = .getKeyStore();
         trustStore = .getTrustStore();
      }
      iftrustStore == null )
         trustStore = keyStore;
      if != null )
      {
         // Have the verifier validate the cert
         if )
            .trace("Validating cert using: "+);
         isValid = .verify(certaliaskeyStoretrustStore);
      }
      else if (keyStore != null && cert != null)
      {
         // Look for the cert in the keystore using the alias
         X509Certificate storeCert = null;
         try
         {
            storeCert = (X509CertificatekeyStore.getCertificate(alias);
            if )
            {
               StringBuffer buf = new StringBuffer("\n\tSupplied Credential: ");
               buf.append(cert.getSerialNumber().toString(16));
               buf.append("\n\t\t");
               buf.append(cert.getSubjectDN().getName());
               buf.append("\n\n\tExisting Credential: ");
               ifstoreCert != null )
               {
                  buf.append(storeCert.getSerialNumber().toString(16));
                  buf.append("\n\t\t");
                  buf.append(storeCert.getSubjectDN().getName());
                  buf.append("\n");
               }
               else
               {
                  ArrayList<Stringaliases = new ArrayList<String>();
                  Enumeration<Stringen = keyStore.aliases();
                  while (en.hasMoreElements())
                  {
                     aliases.add(en.nextElement());
                  }
                  buf.append("No match for alias: "+alias+", we have aliases " + aliases);
               }
               .trace(buf.toString());
            }
         }
         catch (KeyStoreException e)
         {
            .warn("failed to find the certificate for " + aliase);
         }
         // Ensure that the two certs are equal
         if (cert.equals(storeCert))
            isValid = true;
      }
      else
      {
         .warn("Domain, KeyStore, or cert is null. Unable to validate the certificate.");
      }
      if )
      {
         .trace("The supplied certificate "
               + (isValid ? "matched" : "DID NOT match")
               + " the certificate in the keystore.");
         .trace("exit: validateCredentail(String, X509Certificate)");
      }
      return isValid;
   }
New to GrepCode? Check out our FAQ X