View Javadoc
1   /*
2    * Copyright (c) 2002-2021, City of Paris
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions
7    * are met:
8    *
9    *  1. Redistributions of source code must retain the above copyright notice
10   *     and the following disclaimer.
11   *
12   *  2. Redistributions in binary form must reproduce the above copyright notice
13   *     and the following disclaimer in the documentation and/or other materials
14   *     provided with the distribution.
15   *
16   *  3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
17   *     contributors may be used to endorse or promote products derived from
18   *     this software without specific prior written permission.
19   *
20   * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
21   * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
22   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
23   * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
24   * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
25   * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
26   * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
27   * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
28   * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
29   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
30   * POSSIBILITY OF SUCH DAMAGE.
31   *
32   * License 1.0
33   */
34  package fr.paris.lutece.plugins.mylutece.util;
35  
36  import fr.paris.lutece.plugins.mylutece.service.IUserParameterService;
37  import fr.paris.lutece.portal.service.datastore.DatastoreService;
38  import fr.paris.lutece.portal.service.i18n.I18nService;
39  import fr.paris.lutece.portal.service.message.AdminMessage;
40  import fr.paris.lutece.portal.service.message.AdminMessageService;
41  import fr.paris.lutece.portal.service.plugin.Plugin;
42  import fr.paris.lutece.portal.service.util.AppPathService;
43  import fr.paris.lutece.portal.service.util.AppPropertiesService;
44  import fr.paris.lutece.portal.service.util.CryptoService;
45  import fr.paris.lutece.util.ReferenceItem;
46  import fr.paris.lutece.util.date.DateUtil;
47  import fr.paris.lutece.util.password.PasswordUtil;
48  import fr.paris.lutece.util.url.UrlItem;
49  
50  import org.apache.commons.lang3.StringUtils;
51  
52  import java.sql.Timestamp;
53  
54  import java.util.Calendar;
55  import java.util.Date;
56  import java.util.GregorianCalendar;
57  import java.util.List;
58  import java.util.Locale;
59  import java.util.Map;
60  
61  import javax.servlet.http.HttpServletRequest;
62  
63  /**
64   * Util for security parameters
65   *
66   */
67  public class SecurityUtils
68  {
69      // MARKS
70      private static final String MARK_FORCE_CHANGE_PASSWORD_REINIT = "force_change_password_reinit";
71      private static final String MARK_PASSWORD_MINIMUM_LENGTH = "password_minimum_length";
72      private static final String MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE = "password_format_upper_lower_case";
73      private static final String MARK_PASSWORD_FORMAT_NUMERO = "password_format_numero";
74      private static final String MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "password_format_special_characters";
75      private static final String MARK_PASSWORD_DURATION = "password_duration";
76      private static final String MARK_PASSWORD_HISTORY_SIZE = "password_history_size";
77      private static final String MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE = "maximum_number_password_change";
78      private static final String MARK_TSW_SIZE_PASSWORD_CHANGE = "tsw_size_password_change";
79      private static final String MARK_USE_ADVANCED_SECURITY_PARAMETERS = "use_advanced_security_parameters";
80      private static final String MARK_ENABLE_PASSWORD_ENCRYPTION = "enable_password_encryption";
81      private static final String MARK_ENCRYPTION_ALGORITHM = "encryption_algorithm";
82      private static final String MARK_ACCOUNT_LIFE_TIME = "account_life_time";
83      private static final String MARK_TIME_BEFORE_ALERT_ACCOUNT = "time_before_alert_account";
84      private static final String MARK_NB_ALERT_ACCOUNT = "nb_alert_account";
85      private static final String MARK_TIME_BETWEEN_ALERTS_ACCOUNT = "time_between_alerts_account";
86      private static final String MARK_ACCESS_FAILURES_MAX = "access_failures_max";
87      private static final String MARK_ACCESS_FAILURES_INTERVAL = "access_failures_interval";
88      private static final String MARK_BANNED_DOMAIN_NAMES = "banned_domain_names";
89      private static final String MARK_ACCESS_FAILURES_CAPTCHA = "access_failures_captcha";
90      private static final String MARK_ENABLE_UNBLOCK_IP = "enable_unblock_ip";
91      private static final String MARK_ENABLE_TOKEN_LOGIN = "enable_token_login";
92      private static final String MARK_NOTIFY_USER_PASSWORD_EXPIRED = "notify_user_password_expired";
93  
94      // PARAMETERS
95      private static final String PARAMETER_DATE_LOGIN = "date_login";
96      private static final String PARAMETER_IP = "ip";
97      private static final String PARAMETER_INTERVAL = "interval";
98      private static final String PARAMETER_KEY = "key";
99  
100     // MESSAGES
101     private static final String MESSAGE_MINIMUM_PASSWORD_LENGTH = "mylutece.message.password.minimumPasswordLength";
102     private static final String MESSAGE_PASSWORD_FORMAT = "mylutece.message.password.format";
103     private static final String MESSAGE_PASSWORD_FORMAT_UPPER_LOWER_CASE = "mylutece.message.password.formatUpperLowerCase";
104     private static final String MESSAGE_PASSWORD_FORMAT_NUMERO = "mylutece.message.password.formatNumero";
105     private static final String MESSAGE_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "mylutece.message.password.formatSpecialCharacters";
106 
107     // ERROR
108     private static final String ERROR_PASSWORD_MINIMUM_LENGTH = "password_minimum_length";
109     private static final String ERROR_PASSWORD_WRONG_FORMAT = "password_format";
110     private static final String ERROR_PASSWORD_ALREADY_USED = "password_already_used";
111     private static final String ERROR_MAX_PASSWORD_CHANGE = "max_password_change";
112 
113     // PROPERTIES
114     private static final String PROPERTY_DEFAULT_PASSWORD_MINIMAL_LENGTH = "security.defaultValues.passwordMinimalLength";
115     private static final String PROPERTY_DEFAULT_MAXIMUM_NUMBER_PASSWORD_CHANGE = "security.defaultValues.maximumPasswordChange";
116     private static final String PROPERTY_DEFAULT_TSW_SIZE_PASSWORD_CHANGE = "security.defaultValues.maximumPasswordChangeTSWSize";
117     private static final String PROPERTY_DEFAULT_HISTORY_SIZE = "security.defaultValues.passwordHistorySize";
118     private static final String PROPERTY_DEFAULT_PASSWORD_DURATION = "security.defaultValues.passwordDuration";
119     private static final String PROPERTY_DEFAULT_ENCRYPTION_ALGORITHM = "security.defaultValues.algorithm";
120     private static final String JSP_URL_RESET_CONNECTION_LOG = "jsp/site/plugins/mylutece/DoResetConnectionLog.jsp";
121     private static final String CONSTANT_DEFAULT_ENCRYPTION_ALGORITHM = "SHA-256";
122     private static final String SEMICOLON = ";";
123     private static final String CONSTANT_UNDERSCORE = "_";
124 
125     /**
126      * Loads a model with base security parameters
127      * 
128      * @param parameterService
129      *            The parameter service to use
130      * @param model
131      *            The base model to load
132      * @param plugin
133      *            The plugin
134      * @return The model loaded with security parameters
135      */
136     public static Map<String, Object> checkSecurityParameters( IUserParameterService parameterService, Map<String, Object> model, Plugin plugin )
137     {
138         boolean bUseAdvancedParameters = getBooleanSecurityParameter( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS );
139         model.put( MARK_ENABLE_PASSWORD_ENCRYPTION, getBooleanSecurityParameter( parameterService, plugin, MARK_ENABLE_PASSWORD_ENCRYPTION ) );
140         model.put( MARK_ENCRYPTION_ALGORITHM, parameterService.getEncryptionAlgorithm( plugin ) );
141         model.put( MARK_FORCE_CHANGE_PASSWORD_REINIT, isChangePasswordForceAfterReinitActivated( parameterService, plugin ) );
142         model.put( MARK_PASSWORD_MINIMUM_LENGTH, getMinimumPasswordLength( parameterService, plugin ) );
143         model.put( MARK_USE_ADVANCED_SECURITY_PARAMETERS, bUseAdvancedParameters );
144 
145         if ( bUseAdvancedParameters )
146         {
147             model.put( MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, isPasswordFormatUpperLowerCaseUsed( parameterService, plugin ) );
148             model.put( MARK_PASSWORD_FORMAT_NUMERO, isPasswordFormatNumeroUsed( parameterService, plugin ) );
149             model.put( MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, isPasswordFormatSpecialCharactersUsed( parameterService, plugin ) );
150             model.put( MARK_PASSWORD_DURATION, getPasswordDuration( parameterService, plugin ) );
151             model.put( MARK_PASSWORD_HISTORY_SIZE, getPasswordHistorySize( parameterService, plugin ) );
152             model.put( MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, getMaximumNumberPasswordChange( parameterService, plugin ) );
153             model.put( MARK_TSW_SIZE_PASSWORD_CHANGE, getTSWSizePasswordChange( parameterService, plugin ) );
154             model.put( MARK_NOTIFY_USER_PASSWORD_EXPIRED, getBooleanSecurityParameter( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED ) );
155         }
156 
157         model.put( MARK_ACCOUNT_LIFE_TIME, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCOUNT_LIFE_TIME ) );
158 
159         model.put( MARK_TIME_BEFORE_ALERT_ACCOUNT, getIntegerSecurityParameter( parameterService, plugin, MARK_TIME_BEFORE_ALERT_ACCOUNT ) );
160 
161         model.put( MARK_NB_ALERT_ACCOUNT, getIntegerSecurityParameter( parameterService, plugin, MARK_NB_ALERT_ACCOUNT ) );
162 
163         model.put( MARK_TIME_BETWEEN_ALERTS_ACCOUNT, getIntegerSecurityParameter( parameterService, plugin, MARK_TIME_BETWEEN_ALERTS_ACCOUNT ) );
164 
165         model.put( MARK_ACCESS_FAILURES_MAX, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCESS_FAILURES_MAX ) );
166         model.put( MARK_ACCESS_FAILURES_INTERVAL, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCESS_FAILURES_INTERVAL ) );
167         model.put( MARK_ACCESS_FAILURES_CAPTCHA, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCESS_FAILURES_CAPTCHA ) );
168         model.put( MARK_ENABLE_UNBLOCK_IP, getBooleanSecurityParameter( parameterService, plugin, MARK_ENABLE_UNBLOCK_IP ) );
169         model.put( MARK_ENABLE_TOKEN_LOGIN, getBooleanSecurityParameter( parameterService, plugin, MARK_ENABLE_TOKEN_LOGIN ) );
170 
171         return model;
172     }
173 
174     /**
175      * Update security parameters from request parameters
176      * 
177      * @param parameterService
178      *            Parameter service
179      * @param request
180      *            Request to get the parameter from
181      * @param plugin
182      *            The plugin
183      */
184     public static void updateSecurityParameters( IUserParameterService parameterService, HttpServletRequest request, Plugin plugin )
185     {
186         updateParameterValue( parameterService, plugin, MARK_FORCE_CHANGE_PASSWORD_REINIT, request.getParameter( MARK_FORCE_CHANGE_PASSWORD_REINIT ) );
187         updateParameterValue( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH, request.getParameter( MARK_PASSWORD_MINIMUM_LENGTH ) );
188 
189         if ( getBooleanSecurityParameter( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS ) )
190         {
191             updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE,
192                     request.getParameter( MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE ) );
193             updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO, request.getParameter( MARK_PASSWORD_FORMAT_NUMERO ) );
194             updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS,
195                     request.getParameter( MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS ) );
196             updateParameterValue( parameterService, plugin, MARK_PASSWORD_DURATION, request.getParameter( MARK_PASSWORD_DURATION ) );
197             updateParameterValue( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE, request.getParameter( MARK_PASSWORD_HISTORY_SIZE ) );
198             updateParameterValue( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, request.getParameter( MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE ) );
199             updateParameterValue( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE, request.getParameter( MARK_TSW_SIZE_PASSWORD_CHANGE ) );
200             updateParameterValue( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED, request.getParameter( MARK_NOTIFY_USER_PASSWORD_EXPIRED ) );
201         }
202 
203         // Time of life of accounts
204         updateParameterValue( parameterService, plugin, MARK_ACCOUNT_LIFE_TIME, request.getParameter( MARK_ACCOUNT_LIFE_TIME ) );
205 
206         // Time before the first alert when an account will expire
207         updateParameterValue( parameterService, plugin, MARK_TIME_BEFORE_ALERT_ACCOUNT, request.getParameter( MARK_TIME_BEFORE_ALERT_ACCOUNT ) );
208 
209         // Number of alerts sent to a user when his account will expire
210         updateParameterValue( parameterService, plugin, MARK_NB_ALERT_ACCOUNT, request.getParameter( MARK_NB_ALERT_ACCOUNT ) );
211 
212         // Time between alerts
213         updateParameterValue( parameterService, plugin, MARK_TIME_BETWEEN_ALERTS_ACCOUNT, request.getParameter( MARK_TIME_BETWEEN_ALERTS_ACCOUNT ) );
214 
215         updateParameterValue( parameterService, plugin, MARK_ACCESS_FAILURES_MAX, request.getParameter( MARK_ACCESS_FAILURES_MAX ) );
216 
217         updateParameterValue( parameterService, plugin, MARK_ACCESS_FAILURES_INTERVAL, request.getParameter( MARK_ACCESS_FAILURES_INTERVAL ) );
218         updateParameterValue( parameterService, plugin, MARK_ACCESS_FAILURES_CAPTCHA, request.getParameter( MARK_ACCESS_FAILURES_CAPTCHA ) );
219         updateParameterValue( parameterService, plugin, MARK_ENABLE_UNBLOCK_IP, request.getParameter( MARK_ENABLE_UNBLOCK_IP ) );
220         updateParameterValue( parameterService, plugin, MARK_ENABLE_TOKEN_LOGIN, request.getParameter( MARK_ENABLE_TOKEN_LOGIN ) );
221 
222     }
223 
224     /**
225      * Check whether a user must change his new password after a password reset by mail.
226      * 
227      * @param parameterService
228      *            Parameter service to get parameters from.
229      * @param plugin
230      *            The plugin
231      * @return true if the user must, false otherwise
232      */
233     private static int getMinimumPasswordLength( IUserParameterService parameterService, Plugin plugin )
234     {
235         return getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
236     }
237 
238     /**
239      * Check whether a user must change his new password after a password reset by mail.
240      * 
241      * @param parameterService
242      *            Parameter service to get parameters from.
243      * @param plugin
244      *            The plugin
245      * @return true if the user must, false otherwise
246      */
247     private static boolean isChangePasswordForceAfterReinitActivated( IUserParameterService parameterService, Plugin plugin )
248     {
249         Boolean bIsChecked = Boolean.valueOf( parameterService.findByKey( MARK_FORCE_CHANGE_PASSWORD_REINIT, plugin ).isChecked( ) );
250 
251         return bIsChecked.booleanValue( );
252     }
253 
254     /**
255      * Check whether a password is long enough.
256      * 
257      * @param strPassword
258      *            Password to check
259      * @param parameterService
260      *            Parameter service to get parameters from.
261      * @param plugin
262      *            The plugin
263      * @return true is the password is too short, or false if the password correct or if the password's minimum length is disabled.
264      */
265     protected static boolean checkUserPasswordMinimumLength( String strPassword, IUserParameterService parameterService, Plugin plugin )
266     {
267         int nMinimumLength = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
268 
269         return !( ( nMinimumLength > 0 ) && ( strPassword.length( ) < nMinimumLength ) );
270     }
271 
272     /**
273      * Get the admin message telling the password length is too short.
274      * 
275      * @param request
276      *            The request
277      * @param parameterService
278      *            Parameter service to get parameters from.
279      * @param plugin
280      *            The plugin
281      * @return The URL of the admin message indicating that the entered password is too short.
282      */
283     protected static String getMessagePasswordMinimumLength( HttpServletRequest request, IUserParameterService parameterService, Plugin plugin )
284     {
285         Object [ ] param = {
286                 parameterService.findByKey( MARK_PASSWORD_MINIMUM_LENGTH, plugin ).getName( )
287         };
288 
289         return AdminMessageService.getMessageUrl( request, MESSAGE_MINIMUM_PASSWORD_LENGTH, param, AdminMessage.TYPE_STOP );
290     }
291 
292     /**
293      * Get the parameter indicating that a password must contain upper and lower case.
294      * 
295      * @param parameterService
296      *            Parameter service to get parameters from.
297      * @param plugin
298      *            The plugin
299      * @return True if passwords must contain must contain upper and lower case.
300      */
301     protected static boolean isPasswordFormatUpperLowerCaseUsed( IUserParameterService parameterService, Plugin plugin )
302     {
303         return getBooleanSecurityParameter( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE );
304     }
305 
306     /**
307      * Get the parameter indicating that a password must contain a numero
308      * 
309      * @param parameterService
310      *            Parameter service to get parameters from.
311      * @param plugin
312      *            The plugin
313      * @return True if passwords must contain must contain a numero
314      */
315     protected static boolean isPasswordFormatNumeroUsed( IUserParameterService parameterService, Plugin plugin )
316     {
317         return getBooleanSecurityParameter( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO );
318     }
319 
320     /**
321      * Get the parameter indicating that a password must contain a numero
322      * 
323      * @param parameterService
324      *            Parameter service to get parameters from.
325      * @param plugin
326      *            The plugin
327      * @return True if passwords must contain must contain a numero
328      */
329     protected static boolean isPasswordFormatSpecialCharactersUsed( IUserParameterService parameterService, Plugin plugin )
330     {
331         return getBooleanSecurityParameter( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS );
332     }
333 
334     /**
335      * Get the password duration
336      * 
337      * @param parameterService
338      *            Parameter service to get parameters from.
339      * @param plugin
340      *            The plugin
341      * @return The password duration, or 0 if no value or an incorrect value is specified
342      */
343     public static int getPasswordDuration( IUserParameterService parameterService, Plugin plugin )
344     {
345         return getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_DURATION );
346     }
347 
348     /**
349      * Get the password history size
350      * 
351      * @param parameterService
352      *            Parameter service to get parameters from.
353      * @param plugin
354      *            The plugin
355      * @return The password history size, or 0 if no value or an incorrect value is specified
356      */
357     public static int getPasswordHistorySize( IUserParameterService parameterService, Plugin plugin )
358     {
359         return getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE );
360     }
361 
362     /**
363      * Get the size of the time sliding window of passwor change
364      * 
365      * @param parameterService
366      *            Parameter service to get parameters from.
367      * @param plugin
368      *            The plugin
369      * @return the size of the time sliding window of passwor change, or 0 if none is specified
370      */
371     public static int getTSWSizePasswordChange( IUserParameterService parameterService, Plugin plugin )
372     {
373         return getIntegerSecurityParameter( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE );
374     }
375 
376     /**
377      * Get the parameter indicating that a password must contain numbers.
378      * 
379      * @param parameterService
380      *            Parameter service to get parameters from.
381      * @param plugin
382      *            The plugin
383      * @return True if passwords must contain numbers, false otherwise
384      */
385     public static boolean isAdvancedSecurityParametersUsed( IUserParameterService parameterService, Plugin plugin )
386     {
387         return getBooleanSecurityParameter( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS );
388     }
389 
390     /**
391      * Get the maximum number of time a user can change his password in a given period
392      * 
393      * @param parameterService
394      *            Parameter service to get parameters from.
395      * @param plugin
396      *            The plugin
397      * @return The the maximum number of time a user can change his password in a given period, or 0 if no value or an incorrect value is specified
398      */
399     public static int getMaximumNumberPasswordChange( IUserParameterService parameterService, Plugin plugin )
400     {
401         return getIntegerSecurityParameter( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE );
402     }
403 
404     /**
405      * Get the integer value of a security parameter
406      * 
407      * @param parameterService
408      *            Parameter service to use
409      * @param plugin
410      *            The plugin
411      * @param strParameterkey
412      *            Key of the security parameter to get
413      * @return The integer value of the security parameter
414      */
415     public static int getIntegerSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
416     {
417         ReferenceItem refItem = parameterService.findByKey( strParameterkey, plugin );
418 
419         if ( ( refItem == null ) || StringUtils.isEmpty( refItem.getName( ) ) )
420         {
421             return 0;
422         }
423 
424         try
425         {
426             int nValue = Integer.parseInt( refItem.getName( ) );
427 
428             return nValue;
429         }
430         catch( NumberFormatException e )
431         {
432             return 0;
433         }
434     }
435 
436     /**
437      * Get the boolean value of a security parameter
438      * 
439      * @param parameterService
440      *            Parameter service to use
441      * @param plugin
442      *            The plugin
443      * @param strParameterkey
444      *            Key of the security parameter to get
445      * @return The boolean value of the security parameter
446      */
447     public static boolean getBooleanSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
448     {
449         ReferenceItem refItem = parameterService.findByKey( strParameterkey, plugin );
450 
451         return ( refItem == null ) ? false : refItem.isChecked( );
452     }
453 
454     /**
455      * Get the value of a security parameter
456      * 
457      * @param parameterService
458      *            Parameter service to use
459      * @param plugin
460      *            The plugin
461      * @param strParameterkey
462      *            Key of the security parameter to get
463      * @return The value of the security parameter
464      */
465     public static String getSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
466     {
467         ReferenceItem refItem = parameterService.findByKey( strParameterkey, plugin );
468 
469         return ( refItem == null ) ? null : refItem.getName( );
470     }
471 
472     /**
473      * Get the large value of a security parameter.
474      * 
475      * @param parameterService
476      *            Parameter service to use
477      * @param plugin
478      *            The plugin
479      * @param strParameterkey
480      *            Key of the security parameter to get
481      * @return The value of the security parameter
482      */
483     public static String getLargeSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
484     {
485         return DatastoreService.getDataValue( plugin.getName( ) + CONSTANT_UNDERSCORE + strParameterkey, StringUtils.EMPTY );
486     }
487 
488     /**
489      * Gets the admin message saying that the password does not match the required format
490      * 
491      * @param request
492      *            The request
493      * @param parameterService
494      *            Parameter service to use
495      * @param plugin
496      *            The plugin
497      * @return the url of the admin message saying that the password does not match the required format
498      */
499     protected static String getMessageBackPasswordFormat( HttpServletRequest request, IUserParameterService parameterService, Plugin plugin )
500     {
501         Object [ ] param = {
502                 getMessagePasswordFormat( parameterService, request.getLocale( ), plugin )
503         };
504 
505         return AdminMessageService.getMessageUrl( request, MESSAGE_PASSWORD_FORMAT, param, AdminMessage.TYPE_STOP );
506     }
507 
508     /**
509      * Gets the password message format required format
510      * 
511      * @param locale
512      *            the locale
513      * @param parameterService
514      *            Parameter service to use
515      * @param plugin
516      *            The plugin
517      * @return the url of the admin message saying that the password does not match the required format
518      */
519     public static String getMessageFrontPasswordFormat( Locale locale, IUserParameterService parameterService, Plugin plugin )
520     {
521         Object [ ] param = {
522                 getMessagePasswordFormat( parameterService, locale, plugin )
523         };
524 
525         return I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT, param, locale );
526     }
527 
528     /**
529      * The password format message
530      * 
531      * @param parameterService
532      *            Parameter service to use
533      * @param plugin
534      *            The plugin
535      * @param locale
536      *            the locale
537      * @return
538      */
539     private static String getMessagePasswordFormat( IUserParameterService parameterService, Locale locale, Plugin plugin )
540     {
541         StringBuffer strParam = new StringBuffer( );
542         boolean bUserPasswordFormatUpperLowerCase = isPasswordFormatUpperLowerCaseUsed( parameterService, plugin );
543         boolean bUserPasswordFormatNumero = isPasswordFormatNumeroUsed( parameterService, plugin );
544         boolean bUserPasswordFormatSpecialCaracters = isPasswordFormatSpecialCharactersUsed( parameterService, plugin );
545 
546         // Add Message Upper Lower Case
547         if ( bUserPasswordFormatUpperLowerCase )
548         {
549             strParam.append( I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT_UPPER_LOWER_CASE, locale ) );
550         }
551 
552         // Add Message Numero
553         if ( bUserPasswordFormatNumero )
554         {
555             if ( bUserPasswordFormatUpperLowerCase )
556             {
557                 strParam.append( ", " );
558             }
559 
560             strParam.append( I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT_NUMERO, locale ) );
561         }
562 
563         // Add Message Special Characters
564         if ( bUserPasswordFormatSpecialCaracters )
565         {
566             if ( bUserPasswordFormatUpperLowerCase || bUserPasswordFormatNumero )
567             {
568                 strParam.append( ", " );
569             }
570 
571             strParam.append( I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT_SPECIAL_CHARACTERS, locale ) );
572         }
573 
574         return strParam.toString( );
575     }
576 
577     /**
578      * Updates a parameter from its key with a new value.
579      * 
580      * @param parameterService
581      *            Parameter service to use
582      * @param plugin
583      *            The plugin
584      * @param strKey
585      *            The key of the parameter to update
586      * @param strValue
587      *            The new value of the parameter
588      */
589     public static void updateParameterValue( IUserParameterService parameterService, Plugin plugin, String strKey, String strValue )
590     {
591         ReferenceItem userParam = new ReferenceItem( );
592         userParam.setCode( strKey );
593         strValue = ( strValue == null ) ? StringUtils.EMPTY : strValue;
594         userParam.setName( strValue );
595         parameterService.update( userParam, plugin );
596     }
597 
598     /**
599      * Updates a parameter from its key with a new value. The value should be a large value, from exemple a String from a text area.
600      * 
601      * @param parameterService
602      *            Parameter service to use
603      * @param plugin
604      *            The plugin
605      * @param strKey
606      *            The key of the parameter to update
607      * @param strValue
608      *            The new value of the parameter
609      */
610     public static void updateLargeParameterValue( IUserParameterService parameterService, Plugin plugin, String strKey, String strValue )
611     {
612         DatastoreService.setDataValue( plugin.getName( ) + CONSTANT_UNDERSCORE + strKey, strValue );
613     }
614 
615     /**
616      * Enable advanced security parameters
617      * 
618      * @param parameterService
619      *            Parameter service to use
620      * @param plugin
621      *            The plugin
622      */
623     public static void useAdvancedSecurityParameters( IUserParameterService parameterService, Plugin plugin )
624     {
625         updateParameterValue( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS, Boolean.TRUE.toString( ) );
626         updateParameterValue( parameterService, plugin, MARK_FORCE_CHANGE_PASSWORD_REINIT, Boolean.TRUE.toString( ) );
627         updateParameterValue( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE,
628                 AppPropertiesService.getProperty( PROPERTY_DEFAULT_MAXIMUM_NUMBER_PASSWORD_CHANGE ) );
629         updateParameterValue( parameterService, plugin, MARK_PASSWORD_DURATION, AppPropertiesService.getProperty( PROPERTY_DEFAULT_PASSWORD_DURATION ) );
630         updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, Boolean.TRUE.toString( ) );
631         updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO, Boolean.TRUE.toString( ) );
632         updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, Boolean.TRUE.toString( ) );
633         updateParameterValue( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE, AppPropertiesService.getProperty( PROPERTY_DEFAULT_HISTORY_SIZE ) );
634         updateParameterValue( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE,
635                 AppPropertiesService.getProperty( PROPERTY_DEFAULT_TSW_SIZE_PASSWORD_CHANGE ) );
636 
637         int nMinPwdLength = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
638 
639         if ( nMinPwdLength <= 0 )
640         {
641             updateParameterValue( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH,
642                     AppPropertiesService.getProperty( PROPERTY_DEFAULT_PASSWORD_MINIMAL_LENGTH ) );
643         }
644 
645         updateParameterValue( parameterService, plugin, MARK_ENABLE_PASSWORD_ENCRYPTION, Boolean.TRUE.toString( ) );
646         updateParameterValue( parameterService, plugin, MARK_ENCRYPTION_ALGORITHM,
647                 AppPropertiesService.getProperty( PROPERTY_DEFAULT_ENCRYPTION_ALGORITHM, CONSTANT_DEFAULT_ENCRYPTION_ALGORITHM ) );
648         updateParameterValue( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED, Boolean.TRUE.toString( ) );
649     }
650 
651     /**
652      * Remove the advanced security parameters
653      * 
654      * @param parameterService
655      *            Parameter service to use
656      * @param plugin
657      *            The plugin
658      */
659     public static void removeAdvancedSecurityParameters( IUserParameterService parameterService, Plugin plugin )
660     {
661         updateParameterValue( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS, StringUtils.EMPTY );
662         updateParameterValue( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, StringUtils.EMPTY );
663         updateParameterValue( parameterService, plugin, MARK_PASSWORD_DURATION, StringUtils.EMPTY );
664         updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, StringUtils.EMPTY );
665         updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO, StringUtils.EMPTY );
666         updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, StringUtils.EMPTY );
667         updateParameterValue( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE, StringUtils.EMPTY );
668         updateParameterValue( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE, StringUtils.EMPTY );
669         updateParameterValue( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED, StringUtils.EMPTY );
670     }
671 
672     /**
673      * Get the current maximum valid date of a password from the parameter service.
674      * 
675      * @param parameterService
676      *            Parameter service to use
677      * @param plugin
678      *            The plugin
679      * @return The maximum valid date of a password
680      */
681     public static Timestamp getPasswordMaxValidDate( IUserParameterService parameterService, Plugin plugin )
682     {
683         int nbDayPasswordValid = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_DURATION );
684 
685         if ( nbDayPasswordValid <= 0 )
686         {
687             return null;
688         }
689 
690         return PasswordUtil.getPasswordMaxValidDate( nbDayPasswordValid );
691     }
692 
693     /**
694      * Compute the maximum valid date of an account with the current time and the parameters in the database.
695      * 
696      * @param parameterService
697      *            Parameter service to use
698      * @param plugin
699      *            The plugin
700      * @return The maximum valid date of an account
701      */
702     public static Timestamp getAccountMaxValidDate( IUserParameterService parameterService, Plugin plugin )
703     {
704         int nbDaysPasswordValid = getIntegerSecurityParameter( parameterService, plugin, MARK_ACCOUNT_LIFE_TIME );
705 
706         if ( nbDaysPasswordValid <= 0 )
707         {
708             return null;
709         }
710 
711         Calendar calendare = new GregorianCalendar( Locale.getDefault( ) );
712         calendare.add( Calendar.DAY_OF_MONTH, nbDaysPasswordValid );
713 
714         return new Timestamp( calendare.getTimeInMillis( ) );
715     }
716 
717     /**
718      * Test a password validity
719      * 
720      * @param parameterService
721      *            Paramter service to use
722      * @param plugin
723      *            The plugin
724      * @param strPassword
725      *            The password to test validity
726      * @param nUserId
727      *            The id of the user
728      * @return Returns null if the password is correct, or a code depending on the error found. Errors can be 'password_minimum_length' if the password is too
729      *         short, or 'password_format' if the format of the password is not correct.
730      */
731     public static String checkPasswordForFrontOffice( IUserParameterService parameterService, Plugin plugin, String strPassword, int nUserId )
732     {
733         // Check minimum length password
734         if ( !( SecurityUtils.checkUserPasswordMinimumLength( strPassword, parameterService, plugin ) ) )
735         {
736             return ERROR_PASSWORD_MINIMUM_LENGTH;
737         }
738 
739         // Check password format
740         if ( !( SecurityUtils.checkPasswordFormat( strPassword, parameterService, plugin ) ) )
741         {
742             return ERROR_PASSWORD_WRONG_FORMAT;
743         }
744 
745         // Check password history
746         if ( nUserId > 0 )
747         {
748             int nPasswordHistorySize = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE );
749 
750             if ( nPasswordHistorySize > 0 )
751             {
752                 String strEncryptedPassword = buildPassword( parameterService, plugin, strPassword );
753                 List<String> passwordHistory = parameterService.selectUserPasswordHistory( nUserId, plugin );
754 
755                 if ( nPasswordHistorySize < passwordHistory.size( ) )
756                 {
757                     passwordHistory = passwordHistory.subList( 0, nPasswordHistorySize );
758                 }
759 
760                 if ( passwordHistory.contains( strEncryptedPassword ) )
761                 {
762                     return ERROR_PASSWORD_ALREADY_USED;
763                 }
764             }
765 
766             int nTSWSizePasswordChange = getIntegerSecurityParameter( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE );
767             int nMaximumNumberPasswordChange = getIntegerSecurityParameter( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE );
768 
769             if ( nMaximumNumberPasswordChange > 0 )
770             {
771                 Timestamp minDate = null;
772 
773                 if ( nTSWSizePasswordChange > 0 )
774                 {
775                     minDate = new Timestamp( new java.util.Date( ).getTime( ) - DateUtil.convertDaysInMiliseconds( nTSWSizePasswordChange ) );
776                 }
777                 else
778                 {
779                     minDate = new Timestamp( 0 );
780                 }
781 
782                 if ( parameterService.countUserPasswordHistoryFromDate( minDate, nUserId, plugin ) >= nMaximumNumberPasswordChange )
783                 {
784                     return ERROR_MAX_PASSWORD_CHANGE;
785                 }
786             }
787         }
788 
789         return null;
790     }
791 
792     /**
793      * Test a password validity
794      * 
795      * @param parameterService
796      *            Parameter service to use
797      * @param plugin
798      *            The plugin
799      * @param strPassword
800      *            Password to check
801      * @param request
802      *            The request
803      * @return Returns null if the password is correct, or an admin message describing the error
804      */
805     public static String checkPasswordForBackOffice( IUserParameterService parameterService, Plugin plugin, String strPassword, HttpServletRequest request )
806     {
807         if ( !SecurityUtils.checkUserPasswordMinimumLength( strPassword, parameterService, plugin ) )
808         {
809             return SecurityUtils.getMessagePasswordMinimumLength( request, parameterService, plugin );
810         }
811 
812         if ( !SecurityUtils.checkPasswordFormat( strPassword, parameterService, plugin ) )
813         {
814             return SecurityUtils.getMessageBackPasswordFormat( request, parameterService, plugin );
815         }
816 
817         return null;
818     }
819 
820     /**
821      * Build the password depending of the encryption. If the encryption is enable, then it returns the password encrypted, otherwise it just returns the
822      * password given in parameter.
823      * 
824      * @param parameterService
825      *            The parameter service to use
826      * @param plugin
827      *            The plugin
828      * @param strUserPassword
829      *            the password
830      * @return the password encrypted or not
831      */
832     public static String buildPassword( IUserParameterService parameterService, Plugin plugin, String strUserPassword )
833     {
834         // Check if there is an encryption algorithm
835         String strPassword = strUserPassword;
836 
837         if ( parameterService.isPasswordEncrypted( plugin ) )
838         {
839             String strAlgorithm = parameterService.getEncryptionAlgorithm( plugin );
840             strPassword = CryptoService.encrypt( strUserPassword, strAlgorithm );
841         }
842 
843         return strPassword;
844     }
845 
846     /**
847      * Generate a new random password
848      * 
849      * @param parameterService
850      *            The parameter service to use
851      * @return the new password
852      */
853     public static String makePassword( IUserParameterService parameterService, Plugin plugin )
854     {
855         int nMinimumLength = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
856 
857         return PasswordUtil.makePassword( nMinimumLength, isPasswordFormatUpperLowerCaseUsed( parameterService, plugin ),
858                 isPasswordFormatNumeroUsed( parameterService, plugin ), isPasswordFormatSpecialCharactersUsed( parameterService, plugin ) );
859     }
860 
861     /**
862      * Get an array containing banned domain names for email adresses
863      * 
864      * @param parameterService
865      *            Parameter service
866      * @param plugin
867      *            The plugin
868      * @return An array containing banned domain names for email adresses
869      */
870     public static String [ ] getBannedDomainNames( IUserParameterService parameterService, Plugin plugin )
871     {
872         String strDomainNames = SecurityUtils.getLargeSecurityParameter( parameterService, plugin, MARK_BANNED_DOMAIN_NAMES );
873 
874         if ( StringUtils.isNotBlank( strDomainNames ) )
875         {
876             return strDomainNames.split( SEMICOLON );
877         }
878 
879         return null;
880     }
881 
882     /**
883      * Build an url to reset connection logs for an IP and a given user. Data is read from the request.
884      * 
885      * @param nInterval
886      *            Interval of time to reset
887      * @param request
888      *            The request
889      * @return The url to reset connection logs.
890      */
891     public static String buildResetConnectionLogUrl( int nInterval, HttpServletRequest request )
892     {
893         UrlItem url = new UrlItem( AppPathService.getBaseUrl( request ) + JSP_URL_RESET_CONNECTION_LOG );
894         String strIp = request.getRemoteAddr( );
895         String strDate = Long.toString( new Date( ).getTime( ) );
896         String strInterval = Integer.toString( nInterval );
897         url.addParameter( PARAMETER_IP, strIp );
898         url.addParameter( PARAMETER_DATE_LOGIN, strDate );
899         url.addParameter( PARAMETER_INTERVAL, strInterval );
900 
901         String strCryptoKey = CryptoService.getCryptoKey( );
902         url.addParameter( PARAMETER_KEY, CryptoService.encrypt( strIp + strDate + strInterval + strCryptoKey,
903                 AppPropertiesService.getProperty( PROPERTY_DEFAULT_ENCRYPTION_ALGORITHM, CONSTANT_DEFAULT_ENCRYPTION_ALGORITHM ) ) );
904 
905         return url.getUrl( );
906     }
907 
908     /**
909      * Check the format of the password from the entered parameters. The password may have to contain upper and lower case letters, numbers and special
910      * characters.
911      * 
912      * @param strPassword
913      *            The password to check
914      * @param parameterService
915      *            Parameter service to get parameters from.
916      * @param plugin
917      *            The plugin
918      * @return True if the giver parameter respect the parametered format, false if he violate one or more rules.
919      */
920     protected static boolean checkPasswordFormat( String strPassword, IUserParameterService parameterService, Plugin plugin )
921     {
922         boolean bPasswordFormat = isPasswordFormatNumeroUsed( parameterService, plugin ) || isPasswordFormatSpecialCharactersUsed( parameterService, plugin )
923                 || isPasswordFormatUpperLowerCaseUsed( parameterService, plugin );
924 
925         return bPasswordFormat ? PasswordUtil.checkPasswordFormat( strPassword, isPasswordFormatUpperLowerCaseUsed( parameterService, plugin ),
926                 isPasswordFormatNumeroUsed( parameterService, plugin ), isPasswordFormatSpecialCharactersUsed( parameterService, plugin ) ) : true;
927     }
928 }