View Javadoc

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  package org.apache.jetspeed.security.impl;
18  
19  import java.util.Arrays;
20  import java.util.List;
21  
22  import javax.security.auth.Subject;
23  
24  import org.apache.commons.logging.Log;
25  import org.apache.commons.logging.LogFactory;
26  import org.apache.jetspeed.pipeline.PipelineException;
27  import org.apache.jetspeed.pipeline.valve.AbstractValve;
28  import org.apache.jetspeed.pipeline.valve.PageProfilerValve;
29  import org.apache.jetspeed.pipeline.valve.ValveContext;
30  import org.apache.jetspeed.profiler.ProfileLocator;
31  import org.apache.jetspeed.request.RequestContext;
32  import org.apache.jetspeed.security.PasswordCredential;
33  import org.apache.jetspeed.security.SecurityHelper;
34  
35  /***
36   * PasswordCredentialValve
37   *
38   * @author <a href="mailto:ate@apache.org">Ate Douma</a>
39   * @version $Id: PasswordCredentialValveImpl.java 516448 2007-03-09 16:25:47Z ate $
40   */
41  public class PasswordCredentialValveImpl extends AbstractValve implements org.apache.jetspeed.pipeline.valve.PasswordCredentialValve
42  {
43      private static final Log log = LogFactory.getLog(PasswordCredentialValveImpl.class);
44      
45      private static final String CHECKED_KEY = PasswordCredentialValveImpl.class.getName() + ".checked";
46      //private PageManager pageManager;
47      private int[] expirationWarningDays;
48      
49      /***
50       * Create a PasswordCredentialValveImpl which only checks and handles PasswordCredential.isUpdateRequired().
51       *
52       */
53      public PasswordCredentialValveImpl()
54      {     
55          expirationWarningDays = new int[]{};
56      }
57      
58      /***
59       * <p>
60       * Creates a PasswordCredentialValveImpl which, besides checking and handling PasswordCredential.isUpdateRequired(),
61       * also provides a warning when a password is about to be expired according to the provided list of
62       * expirationWarningDays.</p>
63       * @param expirationWarningDays the list of days before password expiration when a warning should be presented 
64       */
65      public PasswordCredentialValveImpl(List expirationWarningDays)
66      {
67          if ( expirationWarningDays != null )
68          {
69              this.expirationWarningDays = new int[expirationWarningDays.size()];
70              for ( int i = 0; i < this.expirationWarningDays.length; i++ )
71              {
72                  this.expirationWarningDays[i] = Integer.parseInt((String)expirationWarningDays.get(i));
73              }
74              Arrays.sort(this.expirationWarningDays);
75          }
76          else
77          {
78              this.expirationWarningDays = new int[0];
79          }
80      }
81  
82      /***
83       * @see org.apache.jetspeed.pipeline.valve.Valve#invoke(org.apache.jetspeed.request.RequestContext, org.apache.jetspeed.pipeline.valve.ValveContext)
84       */
85      public void invoke(RequestContext request, ValveContext context) throws PipelineException
86      {
87          try
88          {
89              if ( request.getRequest().getUserPrincipal() != null )
90              {
91                  Subject subject = request.getSubject();
92                  PasswordCredential pwdCredential = SecurityHelper.getPasswordCredential(subject);
93                  Integer passwordDaysValid = null;
94                  
95                  // check for an existing password credential
96                  if ( pwdCredential != null )
97                  {
98                      if ( pwdCredential.isUpdateRequired() )
99                      {
100                         passwordDaysValid = new Integer(0); // required change
101                     }
102                     if ( request.getSessionAttribute(CHECKED_KEY) == null  )
103                     {
104                         request.setSessionAttribute(CHECKED_KEY,Boolean.TRUE);
105                         if ( pwdCredential.getPreviousAuthenticationDate() != null && 
106                                 pwdCredential.getLastAuthenticationDate() != null &&
107                                 pwdCredential.getExpirationDate() != null )
108                         {
109                             long expirationTime = pwdCredential.getExpirationDate().getTime();
110                             long lastAuthTime = pwdCredential.getLastAuthenticationDate().getTime();
111                             int lastAuthDaysBeforeExpiration = (int)((expirationTime-lastAuthTime)/(24*60*60*1000));
112                             if (  lastAuthDaysBeforeExpiration < 1 )
113                             {
114                                 passwordDaysValid = new Integer(1);
115                             }
116                             else if (expirationWarningDays.length > 0)
117                             {
118                                 long prevAuthTime = Long.MIN_VALUE;
119                                 if (pwdCredential.getPreviousAuthenticationDate() != null )
120                                 {
121                                     prevAuthTime = pwdCredential.getPreviousAuthenticationDate().getTime();
122                                 }
123                                 int prevAuthDaysBeforeExpiration = (int)((expirationTime-prevAuthTime)/(24*60*60*1000));
124                                 if ( prevAuthDaysBeforeExpiration > lastAuthDaysBeforeExpiration )
125                                 {
126                                     for ( int i = 0; i < expirationWarningDays.length; i++ )
127                                     {
128                                         int daysBefore = expirationWarningDays[i]-1;
129                                         if ( lastAuthDaysBeforeExpiration == daysBefore ||
130                                                 (lastAuthDaysBeforeExpiration < daysBefore &&
131                                                         prevAuthDaysBeforeExpiration > daysBefore ) )
132                                         {
133                                             passwordDaysValid = new Integer(lastAuthDaysBeforeExpiration+1);
134                                             break;
135                                         }
136                                     }
137                                 }
138                             }
139                         }
140                     }
141                 }
142                 if ( passwordDaysValid != null )
143                 {
144                     // enforce the SECURITY_LOCATOR to be used to redirect to a change password portlet page
145                     request.setAttribute(PageProfilerValve.PROFILE_LOCATOR_REQUEST_ATTR_KEY,ProfileLocator.SECURITY_LOCATOR);
146                     // inform the change password portlet why it is invoked
147                     request.setAttribute(PasswordCredential.PASSWORD_CREDENTIAL_DAYS_VALID_REQUEST_ATTR_KEY, passwordDaysValid);
148                 }
149             }
150             context.invokeNext(request);
151         }
152         catch (Exception e)
153         {
154             log.error("Exception in request pipeline: " + e.getMessage(), e);
155             throw new PipelineException(e.toString(), e);
156         }
157     }
158 
159     public String toString()
160     {
161         return "PasswordCredentialValve";
162     }
163 
164 }