Home » geronimo-2.2-source-release » org.apache.geronimo.security.realm.providers » [javadoc | source]

    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   
   18   package org.apache.geronimo.security.realm.providers;
   19   
   20   import java.io.IOException;
   21   import java.security.Principal;
   22   import java.security.cert.Certificate;
   23   import java.security.cert.X509Certificate;
   24   import java.util.Arrays;
   25   import java.util.Collections;
   26   import java.util.HashSet;
   27   import java.util.List;
   28   import java.util.Map;
   29   import java.util.Set;
   30   import javax.security.auth.Subject;
   31   import javax.security.auth.callback.Callback;
   32   import javax.security.auth.callback.CallbackHandler;
   33   import javax.security.auth.callback.UnsupportedCallbackException;
   34   import javax.security.auth.login.FailedLoginException;
   35   import javax.security.auth.login.LoginException;
   36   import javax.security.auth.spi.LoginModule;
   37   import javax.security.auth.x500.X500Principal;
   38   
   39   import org.slf4j.Logger;
   40   import org.slf4j.LoggerFactory;
   41   import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
   42   import org.apache.geronimo.security.jaas.WrappingLoginModule;
   43   
   44   /**
   45    * An example LoginModule that authenticates based on a client certificate.
   46    * Authentication is provided by the SSL layer supplying the client certificate.
   47    * All we check is that it is present. Expects
   48    * to be run by a GenericSecurityRealm (doesn't work on its own).
   49    *
   50    * This login module checks security credentials so the lifecycle methods must return true to indicate success
   51    * or throw LoginException to indicate failure.
   52    *
   53    * @version $Rev: 653740 $ $Date: 2008-05-06 03:44:18 -0700 (Tue, 06 May 2008) $
   54    */
   55   public class CertificateChainLoginModule implements LoginModule {
   56       private static final Logger log = LoggerFactory.getLogger(CertificateChainLoginModule.class);
   57   
   58       // Note: If this LoginModule supports any options, the Collections.EMPTY_LIST in the following should be
   59       // replaced with the list of supported options for e.g. Arrays.asList(option1, option2, ...) etc.
   60       public final static List<String> supportedOptions = Collections.unmodifiableList(Collections.EMPTY_LIST);
   61       private Subject subject;
   62       private CallbackHandler handler;
   63       private X500Principal principal;
   64       private boolean loginSucceeded;
   65       private final Set<Principal> allPrincipals = new HashSet<Principal>();
   66   
   67       public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
   68           this.subject = subject;
   69           this.handler = callbackHandler;
   70           for(Object option: options.keySet()) {
   71               if(!supportedOptions.contains(option) && !JaasLoginModuleUse.supportedOptions.contains(option)
   72                       && !WrappingLoginModule.supportedOptions.contains(option)) {
   73                   log.warn("Ignoring option: "+option+". Not supported.");
   74               }
   75           }
   76       }
   77   
   78       /**
   79        * This LoginModule is not to be ignored.  So, this method should never return false.
   80        * @return true if authentication succeeds, or throw a LoginException such as FailedLoginException
   81        *         if authentication fails
   82        */
   83       public boolean login() throws LoginException {
   84           loginSucceeded = false;
   85           Callback[] callbacks = new Callback[1];
   86   
   87           callbacks[0] = new CertificateChainCallback();
   88           try {
   89               handler.handle(callbacks);
   90           } catch (IOException ioe) {
   91               throw (LoginException) new LoginException().initCause(ioe);
   92           } catch (UnsupportedCallbackException uce) {
   93               throw (LoginException) new LoginException().initCause(uce);
   94           }
   95           assert callbacks.length == 1;
   96           Certificate[] certificateChain = ((CertificateChainCallback)callbacks[0]).getCertificateChain();
   97           if (certificateChain == null || certificateChain.length == 0) {
   98               throw new FailedLoginException();
   99           }
  100           if (!(certificateChain[0] instanceof X509Certificate)) {
  101               throw new FailedLoginException();
  102           }
  103           //TODO actually validate chain
  104           principal = ((X509Certificate)certificateChain[0]).getSubjectX500Principal();
  105   
  106           loginSucceeded = true;
  107           return true;
  108       }
  109   
  110       /*
  111        * @exception LoginException if login succeeded but commit failed.
  112        *
  113        * @return true if login succeeded and commit succeeded, or false if login failed but commit succeeded.
  114        */
  115       public boolean commit() throws LoginException {
  116           if(loginSucceeded) {
  117               allPrincipals.add(principal);
  118               allPrincipals.add(new GeronimoUserPrincipal(principal.getName()));
  119               subject.getPrincipals().addAll(allPrincipals);
  120           }
  121           // Clear out the private state
  122           principal = null;
  123           
  124           return loginSucceeded;
  125       }
  126   
  127       public boolean abort() throws LoginException {
  128           if(loginSucceeded) {
  129               // Clear out the private state
  130               principal = null;
  131               allPrincipals.clear();
  132           }
  133           return loginSucceeded;
  134       }
  135   
  136       public boolean logout() throws LoginException {
  137           // Clear out the private state
  138           loginSucceeded = false;
  139           principal = null;
  140           if(!subject.isReadOnly()) {
  141               // Remove principals added by this LoginModule
  142               subject.getPrincipals().removeAll(allPrincipals);
  143           }
  144           allPrincipals.clear();
  145           return true;
  146       }
  147   
  148   }

Home » geronimo-2.2-source-release » org.apache.geronimo.security.realm.providers » [javadoc | source]