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
    3    * or more contributor license agreements.  See the NOTICE file
    4    * distributed with this work for additional information
    5    * regarding copyright ownership.  The ASF licenses this file
    6    * to you under the Apache License, Version 2.0 (the
    7    * "License"); you may not use this file except in compliance
    8    * with the License.  You may obtain a copy of the License at
    9    *
   10    *  http://www.apache.org/licenses/LICENSE-2.0
   11    *
   12    * Unless required by applicable law or agreed to in writing,
   13    * software distributed under the License is distributed on an
   14    * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
   15    * KIND, either express or implied.  See the License for the
   16    * specific language governing permissions and limitations
   17    * under the License.
   18    */
   19   
   20   
   21   package org.apache.geronimo.security.realm.providers;
   22   
   23   import java.io.InputStream;
   24   import java.net.URI;
   25   import java.util.Arrays;
   26   import java.util.Collections;
   27   import java.util.HashSet;
   28   import java.util.List;
   29   import java.util.Map;
   30   import java.util.Properties;
   31   import java.util.Set;
   32   import java.util.regex.Matcher;
   33   import java.util.regex.Pattern;
   34   
   35   import javax.security.auth.DestroyFailedException;
   36   import javax.security.auth.Subject;
   37   import javax.security.auth.callback.Callback;
   38   import javax.security.auth.callback.CallbackHandler;
   39   import javax.security.auth.callback.NameCallback;
   40   import javax.security.auth.callback.UnsupportedCallbackException;
   41   import javax.security.auth.login.LoginException;
   42   import javax.security.auth.spi.LoginModule;
   43   
   44   import org.slf4j.Logger;
   45   import org.slf4j.LoggerFactory;
   46   import org.apache.geronimo.common.GeronimoSecurityException;
   47   import org.apache.geronimo.security.jaas.JaasLoginModuleUse;
   48   import org.apache.geronimo.security.jaas.NamedUsernamePasswordCredential;
   49   import org.apache.geronimo.security.jaas.WrappingLoginModule;
   50   import org.apache.geronimo.system.serverinfo.ServerInfo;
   51   
   52   /**
   53    * GeronimoPropertiesFileMappedPasswordCredentialLoginModule adds NamedUsernamePasswordCredentials to the Subject.
   54    * The NamedUsernamePasswordCredential are specified in a properties file specified in the options. Each line of the
   55    * properties file is of the form:
   56    *
   57    * username=credentials
   58    *
   59    * where credentials is a comma-separated list of credentials and a credential is of the form
   60    * name:username=password
   61    *
   62    * Thus a typical line would be:
   63    *
   64    * whee=foo:bar=baz,foo2:bar2=baz2
   65    *
   66    * This login module does not check credentials so it should never be able to cause a login to succeed.
   67    * Therefore the lifecycle methods must return false to indicate success or throw a LoginException to indicate failure.
   68    *
   69    * @version $Rev: 653740 $ $Date: 2008-05-06 03:44:18 -0700 (Tue, 06 May 2008) $
   70    */
   71   public class GeronimoPropertiesFileMappedPasswordCredentialLoginModule implements LoginModule {
   72   
   73       private static final Logger log = LoggerFactory.getLogger(GeronimoPropertiesFileMappedPasswordCredentialLoginModule.class);
   74       public final static String CREDENTIALS_URI = "credentialsURI";
   75       public final static List<String> supportedOptions = Collections.unmodifiableList(Arrays.asList(CREDENTIALS_URI));
   76       private final static Pattern pattern = Pattern.compile("([^:,=]*):([^:,=]*)=([^:,=]*)");
   77   
   78       private final Set<NamedUsernamePasswordCredential> passwordCredentials = new HashSet<NamedUsernamePasswordCredential>();
   79       private final Properties credentials = new Properties();
   80       private String userName;
   81   
   82       private Subject subject;
   83       private CallbackHandler callbackHandler;
   84   
   85       public void initialize(Subject subject, CallbackHandler callbackHandler, Map sharedState, Map options) {
   86           this.subject = subject;
   87           this.callbackHandler = callbackHandler;
   88           for(Object option: options.keySet()) {
   89               if(!supportedOptions.contains(option) && !JaasLoginModuleUse.supportedOptions.contains(option)
   90                       && !WrappingLoginModule.supportedOptions.contains(option)) {
   91                   log.warn("Ignoring option: "+option+". Not supported.");
   92               }
   93           }
   94           try {
   95               ServerInfo serverInfo = (ServerInfo) options.get(JaasLoginModuleUse.SERVERINFO_LM_OPTION);
   96               final String credentials = (String) options.get(CREDENTIALS_URI);
   97               if (credentials == null) {
   98                   throw new IllegalArgumentException(CREDENTIALS_URI + " must be provided!");
   99               }
  100               URI usersURI = new URI(credentials);
  101               loadProperties(serverInfo, usersURI);
  102           } catch (Exception e) {
  103               log.error("Initialization failed", e);
  104               throw new IllegalArgumentException("Unable to configure properties file login module: " + e.getMessage(), e);
  105           }
  106       }
  107   
  108       private void loadProperties(ServerInfo serverInfo, URI credentialsURI) throws GeronimoSecurityException {
  109           try {
  110               URI userFile = serverInfo.resolveServer(credentialsURI);
  111               InputStream stream = userFile.toURL().openStream();
  112               credentials.load(stream);
  113               stream.close();
  114           } catch (Exception e) {
  115               log.error("Properties File Login Module - data load failed", e);
  116               throw new GeronimoSecurityException(e);
  117           }
  118       }
  119   
  120       public boolean login() throws LoginException {
  121           Callback[] callbacks = new Callback[1];
  122           callbacks[0] = new NameCallback("User name");
  123           try {
  124               callbackHandler.handle(callbacks);
  125           } catch (java.io.IOException e) {
  126               throw (LoginException) new LoginException("Unlikely IOException").initCause(e);
  127           } catch (UnsupportedCallbackException e) {
  128               throw (LoginException) new LoginException("Unlikely UnsupportedCallbackException").initCause(e);
  129           }
  130           userName = ((NameCallback) callbacks[0]).getName();
  131           return false;
  132       }
  133   
  134       void parseCredentials(String unparsedCredentials, Set<NamedUsernamePasswordCredential> passwordCredentials) {
  135           Matcher matcher = pattern.matcher(unparsedCredentials);
  136           while (matcher.find()) {
  137               String credentialName = matcher.group(1);
  138               String credentialUser = matcher.group(2);
  139               String credentialPassword = matcher.group(3);
  140               NamedUsernamePasswordCredential credential = new NamedUsernamePasswordCredential(credentialUser, credentialPassword.toCharArray(), credentialName);
  141               passwordCredentials.add(credential);
  142           }
  143       }
  144   
  145       public boolean commit() throws LoginException {
  146           String unparsedCredentials = credentials.getProperty(userName);
  147           if (unparsedCredentials != null) {
  148               parseCredentials(unparsedCredentials, passwordCredentials);
  149           }
  150           subject.getPrivateCredentials().addAll(passwordCredentials);
  151           
  152           userName = null;
  153           return false;
  154       }
  155   
  156       public boolean abort() throws LoginException {
  157           userName = null;
  158           for(NamedUsernamePasswordCredential credential : passwordCredentials) {
  159               try{
  160                   credential.destroy();
  161               } catch (DestroyFailedException e) {
  162                   // do nothing
  163               }
  164           }
  165           passwordCredentials.clear();
  166           return false;
  167       }
  168   
  169       public boolean logout() throws LoginException {
  170           if(!subject.isReadOnly()) {
  171               subject.getPrivateCredentials().removeAll(passwordCredentials);
  172           }
  173           userName = null;
  174           for(NamedUsernamePasswordCredential credential : passwordCredentials) {
  175               try{
  176                   credential.destroy();
  177               } catch (DestroyFailedException e) {
  178                   // do nothing
  179               }
  180           }
  181           passwordCredentials.clear();
  182           return false;
  183       }
  184   }

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