]> source.dussan.org Git - archiva.git/blob
7b74b2c552cdba7a9cfb201e3b4028f6be3a375e
[archiva.git] /
1 package org.apache.archiva.redback.struts2.interceptor;
2
3 /*
4  * Licensed to the Apache Software Foundation (ASF) under one
5  * or more contributor license agreements.  See the NOTICE file
6  * distributed with this work for additional information
7  * regarding copyright ownership.  The ASF licenses this file
8  * to you under the Apache License, Version 2.0 (the
9  * "License"); you may not use this file except in compliance
10  * with the License.  You may obtain a copy of the License at
11  *
12  * http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing,
15  * software distributed under the License is distributed on an
16  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17  * KIND, either express or implied.  See the License for the
18  * specific language governing permissions and limitations
19  * under the License.
20  */
21
22 import java.util.Calendar;
23 import java.util.Map;
24
25 import javax.inject.Inject;
26 import javax.servlet.http.HttpServletRequest;
27
28 import org.apache.archiva.redback.configuration.UserConfiguration;
29 import org.apache.archiva.redback.users.UserManager;
30 import org.apache.struts2.ServletActionContext;
31 import org.apache.archiva.redback.policy.UserSecurityPolicy;
32 import org.apache.archiva.redback.system.DefaultSecuritySession;
33 import org.apache.archiva.redback.system.SecuritySession;
34 import org.apache.archiva.redback.system.SecuritySystem;
35 import org.apache.archiva.redback.system.SecuritySystemConstants;
36 import org.apache.archiva.redback.users.User;
37 import org.slf4j.Logger;
38 import org.slf4j.LoggerFactory;
39
40 import com.opensymphony.xwork2.ActionContext;
41 import com.opensymphony.xwork2.ActionInvocation;
42 import com.opensymphony.xwork2.interceptor.Interceptor;
43 import org.springframework.context.annotation.Scope;
44 import org.springframework.stereotype.Controller;
45
46 /**
47  * Interceptor to force the user to perform actions, when required.
48  *
49  * @author Edwin Punzalan
50  */
51 @Controller( "redbackPolicyEnforcementInterceptor" )
52 @Scope( "prototype" )
53 public class PolicyEnforcementInterceptor
54     implements Interceptor
55 {
56     private Logger log = LoggerFactory.getLogger( PolicyEnforcementInterceptor.class );
57     
58     private static final String SECURITY_USER_MUST_CHANGE_PASSWORD = "security-must-change-password";
59
60     /**
61      *
62      */
63     @Inject
64     private UserConfiguration config;
65
66     /**
67      *
68      */
69     @Inject
70     protected SecuritySystem securitySystem;
71
72     public void destroy()
73     {
74         //ignore
75     }
76
77     public void init()
78     {
79         //ignore
80     }
81
82     /**
83      * 1) validate that the user doesn't have to change their password, if they do then re-route accordingly
84      *
85      * @param actionInvocation
86      * @return
87      * @throws Exception
88      */
89     @SuppressWarnings("unchecked")
90     public String intercept( ActionInvocation actionInvocation )
91         throws Exception
92     {
93
94         if ( config.getBoolean( "security.policy.strict.enforcement.enabled" ) )
95         {
96             log.debug( "Enforcement: enforcing per click security policies." );
97
98
99             ActionContext context = ActionContext.getContext();
100
101             SecuritySession securitySession = null;
102
103             try
104             {
105                 securitySession = (SecuritySession) context.getSession().get( SecuritySystemConstants.SECURITY_SESSION_KEY );
106             }
107             catch (IllegalStateException e)
108             {
109                 log.debug("Could not get security session as the session was invalid", e);
110             }
111
112             UserSecurityPolicy policy = securitySystem.getPolicy();            
113             
114             if ( securitySession != null )
115             {
116                 UserManager userManager = securitySystem.getUserManager();
117                 User user = userManager.findUser( securitySession.getUser().getPrincipal() );
118                 securitySession = new DefaultSecuritySession( securitySession.getAuthenticationResult(), user );
119                 context.getSession().put( SecuritySystemConstants.SECURITY_SESSION_KEY, securitySession ); 
120             }
121             else
122             {
123                 log.debug( "Enforcement: no user security session detected, skipping enforcement" );
124                 return actionInvocation.invoke();
125             }
126
127             if ( checkForcePasswordChange( securitySession, actionInvocation ) )
128             {
129                 Map<String, Object> session = ServletActionContext.getContext().getSession();
130                 HttpServletRequest request = ServletActionContext.getRequest();
131                 
132                 String queryString = request.getQueryString();
133                 String targetUrl = request.getRequestURL() + ( queryString==null ? "" : "?" + queryString );
134                 
135                 session.put( "targetUrl", targetUrl  );
136  
137                 log.info( "storing targetUrl : {}", targetUrl );
138                 
139                 return SECURITY_USER_MUST_CHANGE_PASSWORD;
140             }
141             
142             if ( config.getBoolean( "security.policy.password.expiration.enabled" ) )
143             {
144                 log.debug( "checking password expiration notification" );
145                 
146                 UserManager userManager = securitySystem.getUserManager();
147                 User user = userManager.findUser( securitySession.getUser().getPrincipal() );             
148                 
149                 Calendar expirationNotifyDate = Calendar.getInstance();
150                 expirationNotifyDate.setTime( user.getLastPasswordChange() );
151                 // add on the total days to expire minus the notification days
152                 expirationNotifyDate.add( Calendar.DAY_OF_MONTH, policy.getPasswordExpirationDays() - config.getInt( "security.policy.password.expiration.notify.days" ) );
153                 
154                 Calendar now = Calendar.getInstance();
155
156                 if ( now.after( expirationNotifyDate ) )
157                 {
158                     log.debug( "setting password expiration notification" );
159                     
160                     Calendar expirationDate = Calendar.getInstance();
161                     expirationDate.setTime( user.getLastPasswordChange() );
162                     expirationDate.add( Calendar.DAY_OF_MONTH, policy.getPasswordExpirationDays() );
163                     Map<String, Object> session = ServletActionContext.getContext().getSession();
164                     session.put( "passwordExpirationNotification", expirationDate.getTime().toString() );
165                 }                                
166             }
167             
168             return actionInvocation.invoke();
169         }
170         else
171         {
172             log.debug( "Enforcement: not processing per click security policies." );
173             return actionInvocation.invoke();
174         }
175     }
176
177     private boolean checkForcePasswordChange( SecuritySession securitySession, ActionInvocation actionInvocation )
178     {
179         /*
180          * FIXME: something less 'hackish'
181          * 
182          * these two classes should not be subject to this enforcement policy and this
183          * ideally should be governed by the interceptor stacks but that just didn't work
184          * when I was trying to solve the problem that way, psquad32 recommended I just
185          * find a way to get around this interceptor in the particular case I needed to and use
186          * "One stack to rule them all  
187          */
188         if ( "org.apache.archiva.redback.struts2.action.PasswordAction".equals( actionInvocation.getAction().getClass().getName() ) )
189         {
190             log.debug( "Enforcement: skipping force password check on password action" );
191             return false;
192         }
193
194         if ( "org.apache.archiva.redback.struts2.action.LoginAction".equals( actionInvocation.getAction().getClass().getName() ) )
195         {
196             log.debug( "Enforcement: skipping force password check on login action" );
197             return false;
198         }
199         
200         if ( "org.apache.archiva.redback.struts2.action.LogoutAction".equals( actionInvocation.getAction().getClass().getName() ) )
201         {
202             log.debug( "Enforcement: skipping force password check on logout action" );
203             return false;
204         }
205
206         if ( config.getBoolean( "security.policy.strict.force.password.change.enabled" ) )
207         {
208             log.debug( "Enforcement: checking active user password change enabled" );
209
210             if ( securitySession.getUser().isPasswordChangeRequired() )
211             {
212                 log.info( "Enforcement: User must change password - forwarding to change password page." );
213
214                 return true;
215             }
216             else
217             {
218                 log.debug( "Enforcement: User doesn't need to change password." );                
219             }
220         }
221         return false;
222     }
223
224 }