You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by at...@apache.org on 2005/09/22 23:20:17 UTC

svn commit: r291016 - in /portals/jetspeed-2/trunk/components: portal/src/java/org/apache/jetspeed/security/impl/ security/src/java/org/apache/jetspeed/security/spi/ security/src/java/org/apache/jetspeed/security/spi/impl/ security/src/test/JETSPEED-IN...

Author: ate
Date: Thu Sep 22 14:19:36 2005
New Revision: 291016

URL: http://svn.apache.org/viewcvs?rev=291016&view=rev
Log:
Implementation of http://issues.apache.org/jira/browse/JS2-359:
  Provide a more flexible and less strict default configuration of InternalPasswordCredentialInterceptors
Also added a lot of javadocs to make it easier for creating additional or extended interceptors.
Online documentation for all of this will be provided too shortly.

Added:
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/AbstractInternalPasswordCredentialInterceptorImpl.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/EncodePasswordOnFirstLoadInterceptor.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/InternalPasswordCredentialInterceptorsProxy.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/MaxPasswordAuthenticationFailuresInterceptor.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordExpirationInterceptor.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordHistoryInterceptor.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/ValidatePasswordOnLoadInterceptor.java   (with props)
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml   (with props)
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordCredentialProvider.xml
      - copied unchanged from r264640, portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/spcpv.xml
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.xml
      - copied, changed from r264640, portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/sipcshi.xml
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml   (with props)
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestCredentialPasswordEncoder.java
      - copied, changed from r264640, portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestDefaultInternalPasswordCredentialInterceptor.java
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.java
      - copied, changed from r264640, portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialStateHandlingInterceptor.java
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordHistoryInterceptor.java
      - copied, changed from r264640, portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialHistoryHandlingInterceptor.java
Removed:
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/defipci.xml
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/sipchhi.xml
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/sipcshi.xml
    portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/spcpv.xml
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestDefaultInternalPasswordCredentialInterceptor.java
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialHistoryHandlingInterceptor.java
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialStateHandlingInterceptor.java
Modified:
    portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/LoginValidationValveImpl.java
    portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/PasswordCredentialValveImpl.java
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/InternalPasswordCredentialInterceptor.java
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/DefaultCredentialHandler.java
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java
    portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/SimpleCredentialPasswordValidator.java
    portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordCredentialProvider.java

Modified: portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/LoginValidationValveImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/LoginValidationValveImpl.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/LoginValidationValveImpl.java (original)
+++ portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/LoginValidationValveImpl.java Thu Sep 22 14:19:36 2005
@@ -40,11 +40,25 @@
 {
     private static final Log log = LogFactory.getLog(LoginValidationValveImpl.class);
     
-    // This value should be in sync with that of InternalPasswordCredentialStateHandlingInterceptor (if used)
-    // to make any sense.
-    // Providing value < 2 will disable the LoginConstants.ERROR_FINAL_LOGIN_ATTEMPT warning 
     private int maxNumberOfAuthenticationFailures;
     
+    /**
+     * Creates a LoginValidationValveImpl instance which doesn't evaluate the maxNumberOfAuthenticationFailures 
+     * for LoginConstant.ERROR_FINAL_LOGIN_ATTEMPT error reporting.
+     */
+    public LoginValidationValveImpl()
+    {
+    }
+
+    /**
+     * <p>
+     * Creates a LoginValidationValveImpl instance which can evaluate {@link PasswordCredential#getAuthenticationFailures()}
+     * to determine if a user only has one login attempt available before the maxNumberOfAuthenticationFailures parameter
+     * value is reached and the credential will be disabled.</p>
+     * <p>
+     * The provided maxNumberOfAuthenticationFailures value should be equal to the value configured for the
+     * MaxPasswordAuthenticationFailuresInterceptor (and > 2 to be useful).</p>
+     */
     public LoginValidationValveImpl(int maxNumberOfAuthenticationFailures)
     {
         this.maxNumberOfAuthenticationFailures = maxNumberOfAuthenticationFailures;

Modified: portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/PasswordCredentialValveImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/PasswordCredentialValveImpl.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/PasswordCredentialValveImpl.java (original)
+++ portals/jetspeed-2/trunk/components/portal/src/java/org/apache/jetspeed/security/impl/PasswordCredentialValveImpl.java Thu Sep 22 14:19:36 2005
@@ -45,6 +45,22 @@
     //private PageManager pageManager;
     private int[] expirationWarningDays;
     
+    /**
+     * Create a PasswordCredentialValveImpl which only checks and handles PasswordCredential.isUpdateRequired().
+     *
+     */
+    public PasswordCredentialValveImpl()
+    {     
+        expirationWarningDays = new int[]{};
+    }
+    
+    /**
+     * <p>
+     * Creates a PasswordCredentialValveImpl which, besides checking and handling PasswordCredential.isUpdateRequired(),
+     * also provides a warning when a password is about to be expired according to the provided list of
+     * expirationWarningDays.</p>
+     * @param expirationWarningDays the list of days before password expiration when a warning should be presented 
+     */
     public PasswordCredentialValveImpl(List expirationWarningDays)
     {
         if ( expirationWarningDays != null )

Modified: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/InternalPasswordCredentialInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/InternalPasswordCredentialInterceptor.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/InternalPasswordCredentialInterceptor.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/InternalPasswordCredentialInterceptor.java Thu Sep 22 14:19:36 2005
@@ -22,7 +22,8 @@
 
 /**
  * <p>
- * InternalPasswordCredentialInterceptor
+ * Callback component interface used by {@link org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler DefaultCredentialHandler} 
+ * allowing injecting custom logic on certain events of the {@link InternalCredential}.
  * </p>
  * 
  * @author <a href="mailto:ate@apache.org">Ate Douma</a>
@@ -30,8 +31,89 @@
  */
 public interface InternalPasswordCredentialInterceptor
 {
+    /**
+     * <p>
+     * Invoked after a password credential is loaded from the persistent store.</p>
+     * <p>
+     * If true is returned the credential is expected to be updated and its changes will be stored again.</p>
+     * <p>
+     * A thrown SecurityException will be logged as an error and result in the credential to be ignored 
+     * as if not existing (like for authentication).</p>
+     * 
+     * @param pcProvider provides callback access to for instance the configured {@link CredentialPasswordEncoder} and
+     * {@link CredentialPasswordValidator}
+     * @param userName the name of the principal to which the credential belongs
+     * @param credential the credential just loaded from the persistent store
+     * @return true if the credential is updated
+     * @throws SecurityException
+     * @see org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler#getPasswordCredential(InternalUserPrincipal, String)
+     * @see org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler#setPasswordExpiration(String, java.sql.Date)
+     */
     boolean afterLoad(PasswordCredentialProvider pcProvider, String userName, InternalCredential credential) throws SecurityException;
+
+    /**
+     * <p>
+     * Invoked during authentication after the provided password is compared against the one retrieved from
+     * the InternalCredential.</p>
+     * <p>
+     * If true is returned, the credential is expected to be updated and its {@link InternalCredential#isEnabled() enabled}
+     * and {@link InternalCredential#isExpired() expired} flags will checked if the credential is (still) valid.</p>
+     * <p>
+     * Note: the enabled and expired flags are <em>only</em> checked if this method returns true.</p>
+     * <p>
+     * A thrown SecurityException will be passed on to the authentication requestor.</p>
+     *  
+     * @param internalUser the user to which the credential belongs
+     * @param userName the name of the principal to which the credential belongs
+     * @param credential the credential of the user
+     * @param authenticated true if the provided password matches the value of the credential
+     * @return true if the credential is updated
+     * @throws SecurityException
+     * @see org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler#authenticate(String, String)
+     */
     boolean afterAuthenticated(InternalUserPrincipal internalUser, String userName, InternalCredential credential, boolean authenticated) throws SecurityException;
+
+    /**
+     * <p>
+     * Invoked when the first password credential is to be saved for a user.</p>
+     * <p>
+     * This callback method can be used to set default values like the {@link InternalCredential#getExpirationDate() expiration date}.</p>
+     * <p>
+     * A thrown SecurityException is passed on to the new password requestor.</p>
+     * 
+     * @param internalUser the user to which the credential belongs
+     * @param credentials the collection of credentials which will set on the user after (already contains the new credential)
+     * @param userName the name of the principal to which the credential belongs
+     * @param credential the credential of the user
+     * @param password the new password value (already set on the new credential)
+     * @throws SecurityException
+     * @see org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler#setPassword(String, String, String)
+     */
     void beforeCreate(InternalUserPrincipal internalUser, Collection credentials, String userName, InternalCredential credential, String password) throws SecurityException;
+
+    /**
+     * <p>
+     * Invoked when a new password value is to be saved for a user.</p>
+     * <p>
+     * The new password value is <em>not</em> yet set on the provided credential when this callback is invoked. This allows
+     * custom history maintenance and/or auditing to be performed.</p>
+     * <p>
+     * The provided authenticated flag can be used to differentiate between a new password value set directly by a user
+     * itself or through an administrative interface.</p>
+     * <p>
+     * After this callback is invoked, the specified password value will be set, as well as a reset of the
+     * {@link InternalCredential#isUpdateRequired() updateRequired} flag, before the credential is saved.</p>
+     * <p>
+     * A thrown SecurityException is passed on to the set password requestor.</p>
+     * 
+     * @param internalUser the user to which the credential belongs
+     * @param credentials the collection of credentials which will set on the user after (already contains the new credential)
+     * @param userName the name of the principal to which the credential belongs
+     * @param credential the credential of the user
+     * @param password the new password value (already set on the new credential)
+     * @param authenticated true if the new password value is provided by the user directly
+     * @throws SecurityException
+     * @see org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler#setPassword(String, String, String)
+     */
     void beforeSetPassword(InternalUserPrincipal internalUser, Collection credentials, String userName, InternalCredential credential, String password, boolean authenticated) throws SecurityException;
 }

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/AbstractInternalPasswordCredentialInterceptorImpl.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/AbstractInternalPasswordCredentialInterceptorImpl.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/AbstractInternalPasswordCredentialInterceptorImpl.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/AbstractInternalPasswordCredentialInterceptorImpl.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,71 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import java.util.Collection;
+
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.om.InternalUserPrincipal;
+import org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor;
+import org.apache.jetspeed.security.spi.PasswordCredentialProvider;
+
+/**
+ * <p>
+ * Base class providing default empty behavior for a {@link InternalPasswordCredentialInterceptor}
+ * implementation.
+ * </p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public abstract class AbstractInternalPasswordCredentialInterceptorImpl implements InternalPasswordCredentialInterceptor
+{
+    /**
+     * @return false
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterLoad(org.apache.jetspeed.security.spi.PasswordCredentialProvider, java.lang.String, org.apache.jetspeed.security.om.InternalCredential)
+     */
+    public boolean afterLoad(PasswordCredentialProvider pcProvider, String userName, InternalCredential credential)
+            throws SecurityException
+    {
+        return false;
+    }
+
+    /**
+     * @return false
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterAuthenticated(org.apache.jetspeed.security.om.InternalUserPrincipal, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, boolean)
+     */
+    public boolean afterAuthenticated(InternalUserPrincipal internalUser, String userName,
+            InternalCredential credential, boolean authenticated) throws SecurityException
+    {
+        return false;
+    }
+
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeCreate(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, InternalCredential, java.lang.String)
+     */
+    public void beforeCreate(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password) throws SecurityException
+    {
+    }
+
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeSetPassword(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, java.lang.String, boolean)
+     */
+    public void beforeSetPassword(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password, boolean authenticated) throws SecurityException
+    {
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/AbstractInternalPasswordCredentialInterceptorImpl.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/DefaultCredentialHandler.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/DefaultCredentialHandler.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/DefaultCredentialHandler.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/DefaultCredentialHandler.java Thu Sep 22 14:19:36 2005
@@ -223,6 +223,7 @@
         {
             credential.setValue(newPassword);
             credential.setEncoded(encoded);
+            credential.setUpdateRequired(false);
         }
                 
         internalUser.setModifiedDate(new Timestamp(new Date().getTime()));

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/EncodePasswordOnFirstLoadInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/EncodePasswordOnFirstLoadInterceptor.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/EncodePasswordOnFirstLoadInterceptor.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/EncodePasswordOnFirstLoadInterceptor.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,50 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.spi.PasswordCredentialProvider;
+
+/**
+ * <p>
+ * Encodes (encrypts) an {@link InternalCredential} password using the configured {@link PasswordCredentialProvider#getEncoder() encoder}
+ * if it is loaded unencoded from the persistent store.</p>
+ * <p>
+ * This interceptor is useful when credentials need to be preset in the persistent store (like through scripts) or
+ * migrated unencoded from a different storage.</p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class EncodePasswordOnFirstLoadInterceptor extends AbstractInternalPasswordCredentialInterceptorImpl
+{
+    /**
+     * @return true if now encoded
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterLoad(org.apache.jetspeed.security.spi.PasswordCredentialProvider, java.lang.String, org.apache.jetspeed.security.om.InternalCredential)
+     */
+    public boolean afterLoad(PasswordCredentialProvider pcProvider, String userName, InternalCredential credential)
+            throws SecurityException
+    {
+        boolean updated = false;
+        if (!credential.isEncoded() && pcProvider.getEncoder() != null )
+        {
+            credential.setValue(pcProvider.getEncoder().encode(userName,credential.getValue()));
+            credential.setEncoded(true);
+            updated = true;
+        }
+        return updated;
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/EncodePasswordOnFirstLoadInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/InternalPasswordCredentialInterceptorsProxy.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/InternalPasswordCredentialInterceptorsProxy.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/InternalPasswordCredentialInterceptorsProxy.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/InternalPasswordCredentialInterceptorsProxy.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,111 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import java.util.Collection;
+import java.util.List;
+
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.om.InternalUserPrincipal;
+import org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor;
+import org.apache.jetspeed.security.spi.PasswordCredentialProvider;
+
+/**
+ * <p>
+ * Provides a wrapper around a list of interceptors so multiple interceptors can
+ * be used with the {@link DefaultCredentialHandler}.
+ * Each interceptor will be invoked sequentially.
+ * </p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class InternalPasswordCredentialInterceptorsProxy implements InternalPasswordCredentialInterceptor
+{
+    private InternalPasswordCredentialInterceptor[] interceptors;
+
+    public InternalPasswordCredentialInterceptorsProxy(List interceptors)
+    {
+        this.interceptors = (InternalPasswordCredentialInterceptor[]) interceptors
+                .toArray(new InternalPasswordCredentialInterceptor[interceptors.size()]);
+    }
+
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterLoad(org.apache.jetspeed.security.spi.PasswordCredentialProvider, java.lang.String, org.apache.jetspeed.security.om.InternalCredential)
+     */
+    public boolean afterLoad(PasswordCredentialProvider pcProvider, String userName, InternalCredential credential)
+            throws SecurityException
+    {
+        boolean updated = false;
+        for (int i = 0; i < interceptors.length; i++)
+        {
+            if (interceptors[i] != null && interceptors[i].afterLoad(pcProvider, userName, credential))
+            {
+                updated = true;
+            }
+        }
+        return updated;
+    }
+
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterAuthenticated(org.apache.jetspeed.security.om.InternalUserPrincipal, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, boolean)
+     */
+    public boolean afterAuthenticated(InternalUserPrincipal internalUser, String userName,
+            InternalCredential credential, boolean authenticated) throws SecurityException
+    {
+        boolean updated = false;
+        for (int i = 0; i < interceptors.length; i++)
+        {
+            if (interceptors[i] != null
+                    && interceptors[i].afterAuthenticated(internalUser, userName, credential, authenticated))
+            {
+                updated = true;
+            }
+        }
+        return updated;
+    }
+
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeCreate(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, InternalCredential, java.lang.String)
+     */
+    public void beforeCreate(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password) throws SecurityException
+    {
+        for (int i = 0; i < interceptors.length; i++)
+        {
+            if (interceptors[i] != null)
+            {
+                interceptors[i].beforeCreate(internalUser, credentials, userName, credential, password);
+            }
+        }
+    }
+
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeSetPassword(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, java.lang.String, boolean)
+     */
+    public void beforeSetPassword(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password, boolean authenticated) throws SecurityException
+    {
+        for (int i = 0; i < interceptors.length; i++)
+        {
+            if (interceptors[i] != null)
+            {
+                interceptors[i].beforeSetPassword(internalUser, credentials, userName, credential, password,
+                        authenticated);
+            }
+        }
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/InternalPasswordCredentialInterceptorsProxy.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/LdapCredentialHandler.java Thu Sep 22 14:19:36 2005
@@ -14,6 +14,7 @@
  */
 package org.apache.jetspeed.security.spi.impl;
 
+import java.sql.Date;
 import java.util.HashSet;
 import java.util.Set;
 
@@ -142,6 +143,15 @@
     public void setPasswordUpdateRequired(String userName, boolean updateRequired) throws SecurityException
     {
         // TODO Implement this.
+    }    
+
+    /**
+     * @see org.apache.jetspeed.security.spi.CredentialHandler#setPasswordExpiration(java.lang.String, java.sql.Date)
+     */
+    public void setPasswordExpiration(String userName, Date expirationDate) throws SecurityException
+    {
+        // TODO Implement this
+        
     }
 
     /**

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/MaxPasswordAuthenticationFailuresInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/MaxPasswordAuthenticationFailuresInterceptor.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/MaxPasswordAuthenticationFailuresInterceptor.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/MaxPasswordAuthenticationFailuresInterceptor.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,95 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import java.util.Collection;
+
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.om.InternalUserPrincipal;
+
+/**
+ * <p>
+ * Enforces a {@link #MaxPasswordAuthenticationFailuresInterceptor(int) maximum number of times} a user may provide an invalid password.
+ * Once the maximum number of invalid authentications is reached, the credential is disabled.</p>
+ * <p>
+ * Note: the current count is <em>not</em> reset on valid authentication by this interceptor.
+ * This is done by the {@link DefaultCredentialHandler} which invokes the interceptor(s) after authentication
+ * and no interceptor {@link #afterAuthenticated(InternalUserPrincipal, String, InternalCredential, boolean) afterAuthenicated} 
+ * method returns true.</p>
+ * <p>
+ * But, this interceptor <em>does</em> (re)sets the count on creation and on change of the password.</p>
+ * <p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class MaxPasswordAuthenticationFailuresInterceptor extends AbstractInternalPasswordCredentialInterceptorImpl
+{
+    private int maxNumberOfAuthenticationFailures;
+    
+    /**
+     * <p>
+     * Configure the maximum number of invalid authentications allowed in a row.</p>
+     * <p>
+     * A value of zero (0) disables the check</p>
+     */
+    public MaxPasswordAuthenticationFailuresInterceptor(int maxNumberOfAuthenticationFailures)
+    {
+        this.maxNumberOfAuthenticationFailures = maxNumberOfAuthenticationFailures;
+    }
+    
+    /**
+     * Checks the current count of authentication failures when the credential is not expired and authentication failed.
+     * @return true if the maximum number of invalid authentications is reached and the credential is disabled.
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterAuthenticated(org.apache.jetspeed.security.om.InternalUserPrincipal, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, boolean)
+     */
+    public boolean afterAuthenticated(InternalUserPrincipal internalUser, String userName,
+            InternalCredential credential, boolean authenticated) throws SecurityException
+    {
+        boolean update = false;
+        if ( !credential.isExpired() && !authenticated && maxNumberOfAuthenticationFailures > 0 )
+        {
+            int authenticationFailures = credential.getAuthenticationFailures()+1;
+            credential.setAuthenticationFailures(authenticationFailures);
+            if (authenticationFailures >= maxNumberOfAuthenticationFailures)
+            {
+                credential.setEnabled(false);
+            }
+            update = true;
+        }
+        return update;
+    }
+    
+    /**
+     * Sets the count of invalid authentications to zero (0).
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeCreate(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, InternalCredential, java.lang.String)
+     */
+    public void beforeCreate(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password) throws SecurityException
+    {
+        credential.setAuthenticationFailures(0);
+    }
+    
+    /**
+     * Resets the count of invalid authentications to zero (0).
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeSetPassword(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, java.lang.String, boolean)
+     */
+    public void beforeSetPassword(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password, boolean authenticated) throws SecurityException
+    {
+        credential.setAuthenticationFailures(0);
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/MaxPasswordAuthenticationFailuresInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordExpirationInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordExpirationInterceptor.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordExpirationInterceptor.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordExpirationInterceptor.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,126 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import java.sql.Date;
+import java.util.Collection;
+
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.om.InternalUserPrincipal;
+import org.apache.jetspeed.security.spi.PasswordCredentialProvider;
+
+/**
+ * <p>
+ * Enforces a maximum lifespan for a password credential.</p>
+ * When {@link #afterAuthenticated(InternalUserPrincipal, String, InternalCredential, boolean) on authentication}
+ * a password its expiration date is reached, its expired flag is set.
+ * The {@link DefaultCredentialHandler} then will fail the authentication and subsequent authentications
+ * will fail immediately.</p>
+ * <p>
+ * To ensure proper expiration handling, an empty (null) expiration date will be automatically
+ * filled in when the credential is loaded from the persistent store using the {@link #PasswordExpirationInterceptor(int) configured} 
+ * max lifespan in days.</p>
+ * <p>
+ * When a password credential is {@link #beforeCreate(InternalUserPrincipal, Collection, String, InternalCredential, String) created}
+ * or a password is {@link #beforeSetPassword(InternalUserPrincipal, Collection, String, InternalCredential, String, boolean) updated}
+ * a new future expiration date is calculated.</p>
+ * <p>
+ * An existing or already provided higher expiration date will be preserved though. 
+ * This allows to (pre)set a (very) high expiration date, like with {@link InternalCredential#MAX_DATE},
+ * for credentials which shouldn't expire.</p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class PasswordExpirationInterceptor extends AbstractInternalPasswordCredentialInterceptorImpl
+{
+    private long maxLifeSpanInMillis;
+    
+    /**
+     * @param maxLifeSpanInDays default lifespan of password credentials in days
+     */
+    public PasswordExpirationInterceptor(int maxLifeSpanInDays)
+    {
+        this.maxLifeSpanInMillis = (long)(maxLifeSpanInDays) * 1000*60*60*24;
+    }
+    
+    /**
+     * @return true when the password credential is now expired
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterAuthenticated(org.apache.jetspeed.security.om.InternalUserPrincipal, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, boolean)
+     */
+    public boolean afterAuthenticated(InternalUserPrincipal internalUser, String userName,
+            InternalCredential credential, boolean authenticated) throws SecurityException
+    {
+        boolean update = false;
+        if ( !credential.isExpired() )
+        {
+            long expirationTime = credential.getExpirationDate().getTime();
+            long currentTime     = new java.util.Date().getTime();
+            if (expirationTime <= currentTime)
+            {
+                credential.setExpired(true);
+                update = true;
+            }
+        }
+        return update;
+    }
+    
+    /**
+     * @return true when a new default expiration date is set
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterLoad(org.apache.jetspeed.security.spi.PasswordCredentialProvider, java.lang.String, org.apache.jetspeed.security.om.InternalCredential)
+     */
+    public boolean afterLoad(PasswordCredentialProvider pcProvider, String userName, InternalCredential credential)
+            throws SecurityException
+    {
+        boolean update = false;
+        if ( credential.getExpirationDate() == null )
+        {
+            credential.setExpirationDate(new Date(new java.util.Date().getTime()+maxLifeSpanInMillis));
+            update = true;
+        }
+        return update;
+    }
+    
+    /**
+     * Calculates and sets the default expiration date and the expired flag to false 
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeCreate(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, InternalCredential, java.lang.String)
+     */
+    public void beforeCreate(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password) throws SecurityException
+    {
+        setExpiration(credential);
+    }
+    
+    /**
+     * Sets a new expiration date if a higher expiration date isn't set already and resets the expired flag
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeSetPassword(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, java.lang.String, boolean)
+     */
+    public void beforeSetPassword(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password, boolean authenticated) throws SecurityException
+    {
+        setExpiration(credential);
+    }
+    
+    protected void setExpiration(InternalCredential credential)
+    {
+        Date nextExpirationDate = new Date(new java.util.Date().getTime()+maxLifeSpanInMillis);
+        if ( credential.getExpirationDate() == null || credential.getExpirationDate().before(nextExpirationDate))
+        {
+            credential.setExpirationDate(nextExpirationDate);
+        }
+        credential.setExpired(false);
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordExpirationInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordHistoryInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordHistoryInterceptor.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordHistoryInterceptor.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordHistoryInterceptor.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,132 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import java.sql.Timestamp;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Date;
+import java.util.Iterator;
+
+import org.apache.jetspeed.security.PasswordAlreadyUsedException;
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.om.InternalUserPrincipal;
+import org.apache.jetspeed.security.om.impl.InternalCredentialImpl;
+
+/**
+ * <p>
+ * Maintains a configurable FIFO stack of used password credentials for a principal.
+ * It also requires a unique password (with regards to the values currently in the stack) when 
+ * a password is changed directly by the user itself.</p>
+ * <p>
+ * The historical passwords are maintained as {@link InternalCredential} instances with as {@link InternalCredential#getClassname() classname}
+ *  value {@link #HISTORICAL_PASSWORD_CREDENTIAL} to distinguish them from the current password credential.</p>
+ * <p>
+ * <em>Implementation Note:</em><br>
+ * When a new password is about to be saved, a new <em>copy</em> of the current credential is saved as
+ * a historic password credential. This means that the current password credential <em>instance</em>,
+ * and thus also its {@link InternalCredential#getCredentialId() key}, remains the same.</p>
+ * <p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class PasswordHistoryInterceptor extends AbstractInternalPasswordCredentialInterceptorImpl
+{
+    private int historySize;
+    
+    /**
+     * Value used for {@link InternalCredential#getClassname()} to distinguish from current password credentials
+     */
+    public static String HISTORICAL_PASSWORD_CREDENTIAL = "org.apache.jetspeed.security.spi.impl.HistoricalPasswordCredentialImpl";
+    
+    private static final Comparator internalCredentialCreationDateComparator =
+        new Comparator()
+        {
+            public int compare(Object obj1, Object obj2)
+            {
+                return ((InternalCredential)obj2).getCreationDate().compareTo(((InternalCredential)obj1).getCreationDate());
+            }
+        };
+    
+    /**
+     * @param historySize stack size maintained for historical passwords
+     */
+    public PasswordHistoryInterceptor(int historySize)
+    {
+        this.historySize = historySize;
+    }
+    
+    /**
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#beforeSetPassword(org.apache.jetspeed.security.om.InternalUserPrincipal, java.util.Collection, java.lang.String, org.apache.jetspeed.security.om.InternalCredential, java.lang.String, boolean)
+     */
+    public void beforeSetPassword(InternalUserPrincipal internalUser, Collection credentials, String userName,
+            InternalCredential credential, String password, boolean authenticated) throws SecurityException
+    {
+        Collection internalCredentials = internalUser.getCredentials();
+        ArrayList historicalPasswordCredentials = new ArrayList();
+        if ( internalCredentials != null )
+        {
+            InternalCredential currCredential;
+            Iterator iter = internalCredentials.iterator();
+            
+            while (iter.hasNext())
+            {
+                currCredential = (InternalCredential) iter.next();
+                if (currCredential.getType() == InternalCredential.PRIVATE )
+                {
+                    if ((null != currCredential.getClassname())
+                            && (currCredential.getClassname().equals(HISTORICAL_PASSWORD_CREDENTIAL)))
+                    {
+                        historicalPasswordCredentials.add(currCredential);
+                    }
+                }
+            }
+        }
+        if (historicalPasswordCredentials.size() > 1)
+        {
+            Collections.sort(historicalPasswordCredentials,internalCredentialCreationDateComparator);
+        }
+        
+        int historyCount = historyCount = historicalPasswordCredentials.size();
+        InternalCredential historicalPasswordCredential;
+        if ( authenticated )
+        {
+            // check password already used
+            for ( int i = 0; i < historyCount && i < historySize; i++ )
+            {
+                historicalPasswordCredential = (InternalCredential)historicalPasswordCredentials.get(i);
+                if ( historicalPasswordCredential.getValue() != null &&
+                        historicalPasswordCredential.getValue().equals(password) )
+                {
+                    throw new PasswordAlreadyUsedException();
+                }
+            }
+        }
+
+        for ( int i = historySize-1; i < historyCount; i++ )
+        {
+            credentials.remove(historicalPasswordCredentials.get(i));
+        }
+        historicalPasswordCredential = new InternalCredentialImpl(credential,HISTORICAL_PASSWORD_CREDENTIAL);
+        credentials.add(historicalPasswordCredential);
+        
+        // fake update to current InternalCredential as being an insert of a new one
+        credential.setCreationDate(new Timestamp(new Date().getTime()));
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/PasswordHistoryInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/SimpleCredentialPasswordValidator.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/SimpleCredentialPasswordValidator.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/SimpleCredentialPasswordValidator.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/SimpleCredentialPasswordValidator.java Thu Sep 22 14:19:36 2005
@@ -47,6 +47,10 @@
     public void validate(String clearTextPassword) throws SecurityException
     {
         int digits = 0;
+        if ( clearTextPassword == null )
+        {
+            clearTextPassword = "";
+        }
         char[] pwd = clearTextPassword.toCharArray();
 
         if ( minPasswordLength > 0 && pwd.length < minPasswordLength )

Added: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/ValidatePasswordOnLoadInterceptor.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/ValidatePasswordOnLoadInterceptor.java?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/ValidatePasswordOnLoadInterceptor.java (added)
+++ portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/ValidatePasswordOnLoadInterceptor.java Thu Sep 22 14:19:36 2005
@@ -0,0 +1,64 @@
+/* Copyright 2004 Apache Software Foundation
+*
+* Licensed under the Apache License, Version 2.0 (the "License");
+* you may not use this file except in compliance with the License.
+* You may obtain a copy of the License at
+*
+*     http://www.apache.org/licenses/LICENSE-2.0
+*
+* Unless required by applicable law or agreed to in writing, software
+* distributed under the License is distributed on an "AS IS" BASIS,
+* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+* See the License for the specific language governing permissions and
+* limitations under the License.
+*/
+package org.apache.jetspeed.security.spi.impl;
+
+import org.apache.commons.logging.Log;
+import org.apache.commons.logging.LogFactory;
+import org.apache.jetspeed.security.SecurityException;
+import org.apache.jetspeed.security.om.InternalCredential;
+import org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor;
+import org.apache.jetspeed.security.spi.PasswordCredentialProvider;
+
+/**
+ * <p>
+ * Checks if a (pre)set password in the persitent store is valid according to the configured
+ * {@link PasswordCredentialProvider#getValidator() validator} when loaded from the persistent store.</p>
+ * <p>
+ * If the password checks out to be invalid, an error is logged and the credential is flagged to be 
+ * {@link InternalCredential#isUpdateRequired() updateRequired}.</p>
+ * 
+ * @author <a href="mailto:ate@douma.nu">Ate Douma</a>
+ * @version $Id$
+ */
+public class ValidatePasswordOnLoadInterceptor extends AbstractInternalPasswordCredentialInterceptorImpl
+{
+    private static final Log log = LogFactory.getLog(InternalPasswordCredentialInterceptor.class);
+    
+    /**
+     * @return true is the password was invalid and update is required
+     * @see org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor#afterLoad(org.apache.jetspeed.security.spi.PasswordCredentialProvider, java.lang.String, org.apache.jetspeed.security.om.InternalCredential)
+     */
+    public boolean afterLoad(PasswordCredentialProvider pcProvider, String userName, InternalCredential credential)
+            throws SecurityException
+    {
+        boolean updated = false;
+        if (!credential.isEncoded() && pcProvider.getValidator() != null )
+        {
+            try
+            {
+                pcProvider.getValidator().validate(credential.getValue());
+            }
+            catch (SecurityException e)
+            {
+                log.error("Loaded password for user "+userName+" is invalid. The user will be required to change it.");
+                // persitent store contains an invalid password
+                // allow login (assuming the user knows the invalid value) but enforce an update
+                credential.setUpdateRequired(true);
+                updated = true;
+            }
+        }
+        return updated;
+    }
+}

Propchange: portals/jetspeed-2/trunk/components/security/src/java/org/apache/jetspeed/security/spi/impl/ValidatePasswordOnLoadInterceptor.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml (added)
+++ portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml Thu Sep 22 14:19:36 2005
@@ -0,0 +1,40 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<!--
+Copyright 2004 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans>
+ <!-- MessageDigestCredentialPasswordEncoder usage -->
+  <bean id="org.apache.jetspeed.security.spi.CredentialPasswordEncoder" 
+       class="org.apache.jetspeed.security.spi.impl.MessageDigestCredentialPasswordEncoder">
+       <constructor-arg index="0"><value>SHA-1</value></constructor-arg>       
+  </bean>       
+
+  <bean id="org.apache.jetspeed.security.spi.PasswordCredentialProvider" 
+       class="org.apache.jetspeed.security.spi.impl.DefaultPasswordCredentialProvider">
+       <constructor-arg index="0"><null/></constructor-arg> <!-- no validator -->       
+       <constructor-arg index="1"><ref bean="org.apache.jetspeed.security.spi.CredentialPasswordEncoder"/></constructor-arg>       
+  </bean>       
+
+  <!-- Security SPI: CredentialHandler -->
+  <bean id="org.apache.jetspeed.security.spi.CredentialHandler" 
+       class="org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler"
+  >       
+       <constructor-arg index="0"><ref bean="org.apache.jetspeed.security.spi.SecurityAccess"/></constructor-arg>       
+       <constructor-arg index="1"><ref bean="org.apache.jetspeed.security.spi.PasswordCredentialProvider"/></constructor-arg>       
+       <constructor-arg index="2"><null/></constructor-arg> <!-- no interceptors -->       
+  </bean>
+  
+</beans>

Propchange: portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.xml (from r264640, portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/sipcshi.xml)
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.xml?p2=portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.xml&p1=portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/sipcshi.xml&r1=264640&r2=291016&rev=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/sipcshi.xml (original)
+++ portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.xml Thu Sep 22 14:19:36 2005
@@ -16,18 +16,28 @@
 limitations under the License.
 -->
 <beans>
- <!-- MessageDigestCredentialPasswordEncoder usage -->
-  <bean id="org.apache.jetspeed.security.spi.CredentialPasswordValidator" 
-       class="org.apache.jetspeed.security.spi.impl.DefaultCredentialPasswordValidator"/>
-
-  <bean id="org.apache.jetspeed.security.spi.CredentialPasswordEncoder" 
-       class="org.apache.jetspeed.security.spi.impl.MessageDigestCredentialPasswordEncoder">
-       <constructor-arg index="0"><value>SHA-1</value></constructor-arg>       
-  </bean>       
+  <bean id="org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor"
+       class="org.apache.jetspeed.security.spi.impl.InternalPasswordCredentialInterceptorsProxy">
+       <constructor-arg index="0">
+         <list>
+           <bean class="org.apache.jetspeed.security.spi.impl.PasswordExpirationInterceptor">
+             <constructor-arg index="0"><value>60</value></constructor-arg>       
+           </bean>        
+           <bean class="org.apache.jetspeed.security.spi.impl.MaxPasswordAuthenticationFailuresInterceptor">
+             <constructor-arg index="0"><value>3</value></constructor-arg>       
+           </bean>
+         </list>
+       </constructor-arg>
+  </bean>
 
   <bean id="org.apache.jetspeed.security.spi.PasswordCredentialProvider" 
-       class="org.apache.jetspeed.security.spi.impl.DefaultPasswordCredentialProvider">
-       <constructor-arg index="0"><ref bean="org.apache.jetspeed.security.spi.CredentialPasswordValidator"/></constructor-arg>       
-       <constructor-arg index="1"><ref bean="org.apache.jetspeed.security.spi.CredentialPasswordEncoder"/></constructor-arg>       
-  </bean>       
+       class="org.apache.jetspeed.security.spi.impl.DefaultPasswordCredentialProvider"/>
+
+  <!-- Security SPI: CredentialHandler -->
+  <bean id="org.apache.jetspeed.security.spi.CredentialHandler" 
+       class="org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler">       
+       <constructor-arg index="0"><ref bean="org.apache.jetspeed.security.spi.SecurityAccess"/></constructor-arg>       
+       <constructor-arg index="1"><ref bean="org.apache.jetspeed.security.spi.PasswordCredentialProvider"/></constructor-arg>       
+       <constructor-arg index="2"><ref bean="org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor"/></constructor-arg>       
+  </bean>
 </beans>

Added: portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml?rev=291016&view=auto
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml (added)
+++ portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml Thu Sep 22 14:19:36 2005
@@ -0,0 +1,44 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE beans PUBLIC "-//SPRING//DTD BEAN//EN" "http://www.springframework.org/dtd/spring-beans.dtd">
+<!--
+Copyright 2004 The Apache Software Foundation
+
+Licensed under the Apache License, Version 2.0 (the "License");
+you may not use this file except in compliance with the License.
+You may obtain a copy of the License at
+
+    http://www.apache.org/licenses/LICENSE-2.0
+
+Unless required by applicable law or agreed to in writing, software
+distributed under the License is distributed on an "AS IS" BASIS,
+WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+See the License for the specific language governing permissions and
+limitations under the License.
+-->
+<beans>
+  <bean id="org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor"
+       class="org.apache.jetspeed.security.spi.impl.InternalPasswordCredentialInterceptorsProxy">
+       <constructor-arg index="0">
+         <list>
+           <bean class="org.apache.jetspeed.security.spi.impl.PasswordHistoryInterceptor">
+             <constructor-arg index="0"><value>3</value></constructor-arg>       
+           </bean>
+         </list>
+       </constructor-arg>
+  </bean>
+
+  <bean id="org.apache.jetspeed.security.spi.PasswordCredentialProvider" 
+       class="org.apache.jetspeed.security.spi.impl.DefaultPasswordCredentialProvider">
+       <constructor-arg index="0"><null/></constructor-arg>       
+       <constructor-arg index="1"><null/></constructor-arg>       
+  </bean>       
+
+  <!-- Security SPI: CredentialHandler -->
+  <bean id="org.apache.jetspeed.security.spi.CredentialHandler" 
+       class="org.apache.jetspeed.security.spi.impl.DefaultCredentialHandler">       
+       <constructor-arg index="0"><ref bean="org.apache.jetspeed.security.spi.SecurityAccess"/></constructor-arg>       
+       <constructor-arg index="1"><ref bean="org.apache.jetspeed.security.spi.PasswordCredentialProvider"/></constructor-arg>       
+       <constructor-arg index="2"><ref bean="org.apache.jetspeed.security.spi.InternalPasswordCredentialInterceptor"/></constructor-arg>       
+  </bean>
+  
+</beans>

Propchange: portals/jetspeed-2/trunk/components/security/src/test/JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml
------------------------------------------------------------------------------
    svn:eol-style = native

Copied: portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestCredentialPasswordEncoder.java (from r264640, portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestDefaultInternalPasswordCredentialInterceptor.java)
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestCredentialPasswordEncoder.java?p2=portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestCredentialPasswordEncoder.java&p1=portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestDefaultInternalPasswordCredentialInterceptor.java&r1=264640&r2=291016&rev=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestDefaultInternalPasswordCredentialInterceptor.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestCredentialPasswordEncoder.java Thu Sep 22 14:19:36 2005
@@ -36,7 +36,7 @@
  * @author <a href="mailto:ate@apache.org">Ate Douma</a>
  * @version $Id$
  */
-public class TestDefaultInternalPasswordCredentialInterceptor extends AbstractSecurityTestcase
+public class TestCredentialPasswordEncoder extends AbstractSecurityTestcase
 {
     protected void setUp() throws Exception
     {
@@ -54,7 +54,7 @@
 
     public static Test suite()
     {
-        return new TestSuite(TestDefaultInternalPasswordCredentialInterceptor.class);
+        return new TestSuite(TestCredentialPasswordEncoder.class);
     }
 
     public void testEncodedPassword() throws Exception
@@ -91,7 +91,7 @@
     {
         String[] confs = super.getConfigurations();
         List confList = new ArrayList(Arrays.asList(confs));
-        confList.add("JETSPEED-INF/spring/defipci.xml");
+        confList.add("JETSPEED-INF/spring/TestCredentialPasswordEncoder.xml");
         return (String[])confList.toArray(new String[1]);
     }    
 }

Modified: portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordCredentialProvider.java
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordCredentialProvider.java?rev=291016&r1=291015&r2=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordCredentialProvider.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordCredentialProvider.java Thu Sep 22 14:19:36 2005
@@ -154,7 +154,7 @@
     {
         String[] confs = super.getConfigurations();
         List confList = new ArrayList(Arrays.asList(confs));
-        confList.add("JETSPEED-INF/spring/spcpv.xml");
+        confList.add("JETSPEED-INF/spring/TestPasswordCredentialProvider.xml");
         return (String[]) confList.toArray(new String[1]);
     }    
 }

Copied: portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.java (from r264640, portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialStateHandlingInterceptor.java)
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.java?p2=portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.java&p1=portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialStateHandlingInterceptor.java&r1=264640&r2=291016&rev=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialStateHandlingInterceptor.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.java Thu Sep 22 14:19:36 2005
@@ -34,7 +34,7 @@
  * @author <a href="mailto:ate@apache.org">Ate Douma</a>
  * @version $Id$
  */
-public class TestInternalPasswordCredentialStateHandlingInterceptor extends AbstractSecurityTestcase
+public class TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor extends AbstractSecurityTestcase
 {
     private InternalUserPrincipal internalUser;
     private InternalCredential credential;
@@ -55,10 +55,10 @@
 
     public static Test suite()
     {
-        return new TestSuite(TestInternalPasswordCredentialStateHandlingInterceptor.class);
+        return new TestSuite(TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.class);
     }
 
-    public void testExpired() throws Exception
+    public void testExpirationAndMaxAuthenticationFailures() throws Exception
     {
         assertTrue("should be allowed to authenticate",ums.authenticate("testcred","password"));
         credential.setExpirationDate(new Date(new java.util.Date().getTime()));
@@ -102,7 +102,7 @@
     {
         String[] confs = super.getConfigurations();
         List confList = new ArrayList(Arrays.asList(confs));
-        confList.add("JETSPEED-INF/spring/sipcshi.xml");
+        confList.add("JETSPEED-INF/spring/TestPasswordExpirationAndMaxAuthenticationFailuresInterceptor.xml");
         return (String[])confList.toArray(new String[1]);
     }    
 }

Copied: portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordHistoryInterceptor.java (from r264640, portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialHistoryHandlingInterceptor.java)
URL: http://svn.apache.org/viewcvs/portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordHistoryInterceptor.java?p2=portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordHistoryInterceptor.java&p1=portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialHistoryHandlingInterceptor.java&r1=264640&r2=291016&rev=291016&view=diff
==============================================================================
--- portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestInternalPasswordCredentialHistoryHandlingInterceptor.java (original)
+++ portals/jetspeed-2/trunk/components/security/src/test/org/apache/jetspeed/security/spi/TestPasswordHistoryInterceptor.java Thu Sep 22 14:19:36 2005
@@ -22,8 +22,6 @@
 import junit.framework.TestSuite;
 
 import org.apache.jetspeed.security.SecurityException;
-import org.apache.jetspeed.security.om.InternalUserPrincipal;
-import org.apache.jetspeed.security.om.impl.InternalCredentialImpl;
 import org.apache.jetspeed.security.util.test.AbstractSecurityTestcase;
 
 /**
@@ -34,11 +32,8 @@
  * @author <a href="mailto:ate@apache.org">Ate Douma</a>
  * @version $Id$
  */
-public class TestInternalPasswordCredentialHistoryHandlingInterceptor extends AbstractSecurityTestcase
+public class TestPasswordHistoryInterceptor extends AbstractSecurityTestcase
 {
-    private InternalUserPrincipal internalUser;
-    private InternalCredentialImpl credential;
-    
     protected void setUp() throws Exception
     {
         super.setUp(); 
@@ -55,7 +50,7 @@
 
     public static Test suite()
     {
-        return new TestSuite(TestInternalPasswordCredentialHistoryHandlingInterceptor.class);
+        return new TestSuite(TestPasswordHistoryInterceptor.class);
     }
 
     public void testPasswordHistory() throws Exception
@@ -103,7 +98,7 @@
     {
         String[] confs = super.getConfigurations();
         List confList = new ArrayList(Arrays.asList(confs));
-        confList.add("JETSPEED-INF/spring/sipchhi.xml");
+        confList.add("JETSPEED-INF/spring/TestPasswordHistoryInterceptor.xml");
         return (String[])confList.toArray(new String[1]);
     }    
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org