SecurityUtils.java
/*
* Copyright (c) 2002-2021, City of Paris
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright notice
* and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright notice
* and the following disclaimer in the documentation and/or other materials
* provided with the distribution.
*
* 3. Neither the name of 'Mairie de Paris' nor 'Lutece' nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT HOLDERS OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*
* License 1.0
*/
package fr.paris.lutece.plugins.mylutece.util;
import fr.paris.lutece.plugins.mylutece.service.IUserParameterService;
import fr.paris.lutece.portal.service.datastore.DatastoreService;
import fr.paris.lutece.portal.service.i18n.I18nService;
import fr.paris.lutece.portal.service.message.AdminMessage;
import fr.paris.lutece.portal.service.message.AdminMessageService;
import fr.paris.lutece.portal.service.plugin.Plugin;
import fr.paris.lutece.portal.service.util.AppPathService;
import fr.paris.lutece.portal.service.util.AppPropertiesService;
import fr.paris.lutece.portal.service.util.CryptoService;
import fr.paris.lutece.util.ReferenceItem;
import fr.paris.lutece.util.date.DateUtil;
import fr.paris.lutece.util.password.PasswordUtil;
import fr.paris.lutece.util.url.UrlItem;
import org.apache.commons.lang3.StringUtils;
import java.sql.Timestamp;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import javax.servlet.http.HttpServletRequest;
/**
* Util for security parameters
*
*/
public class SecurityUtils
{
// MARKS
private static final String MARK_FORCE_CHANGE_PASSWORD_REINIT = "force_change_password_reinit";
private static final String MARK_PASSWORD_MINIMUM_LENGTH = "password_minimum_length";
private static final String MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE = "password_format_upper_lower_case";
private static final String MARK_PASSWORD_FORMAT_NUMERO = "password_format_numero";
private static final String MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "password_format_special_characters";
private static final String MARK_PASSWORD_DURATION = "password_duration";
private static final String MARK_PASSWORD_HISTORY_SIZE = "password_history_size";
private static final String MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE = "maximum_number_password_change";
private static final String MARK_TSW_SIZE_PASSWORD_CHANGE = "tsw_size_password_change";
private static final String MARK_USE_ADVANCED_SECURITY_PARAMETERS = "use_advanced_security_parameters";
private static final String MARK_ENABLE_PASSWORD_ENCRYPTION = "enable_password_encryption";
private static final String MARK_ENCRYPTION_ALGORITHM = "encryption_algorithm";
private static final String MARK_ACCOUNT_LIFE_TIME = "account_life_time";
private static final String MARK_TIME_BEFORE_ALERT_ACCOUNT = "time_before_alert_account";
private static final String MARK_NB_ALERT_ACCOUNT = "nb_alert_account";
private static final String MARK_TIME_BETWEEN_ALERTS_ACCOUNT = "time_between_alerts_account";
private static final String MARK_ACCESS_FAILURES_MAX = "access_failures_max";
private static final String MARK_ACCESS_FAILURES_INTERVAL = "access_failures_interval";
private static final String MARK_BANNED_DOMAIN_NAMES = "banned_domain_names";
private static final String MARK_ACCESS_FAILURES_CAPTCHA = "access_failures_captcha";
private static final String MARK_ENABLE_UNBLOCK_IP = "enable_unblock_ip";
private static final String MARK_ENABLE_TOKEN_LOGIN = "enable_token_login";
private static final String MARK_NOTIFY_USER_PASSWORD_EXPIRED = "notify_user_password_expired";
// PARAMETERS
private static final String PARAMETER_DATE_LOGIN = "date_login";
private static final String PARAMETER_IP = "ip";
private static final String PARAMETER_INTERVAL = "interval";
private static final String PARAMETER_KEY = "key";
// MESSAGES
private static final String MESSAGE_MINIMUM_PASSWORD_LENGTH = "mylutece.message.password.minimumPasswordLength";
private static final String MESSAGE_PASSWORD_FORMAT = "mylutece.message.password.format";
private static final String MESSAGE_PASSWORD_FORMAT_UPPER_LOWER_CASE = "mylutece.message.password.formatUpperLowerCase";
private static final String MESSAGE_PASSWORD_FORMAT_NUMERO = "mylutece.message.password.formatNumero";
private static final String MESSAGE_PASSWORD_FORMAT_SPECIAL_CHARACTERS = "mylutece.message.password.formatSpecialCharacters";
// ERROR
private static final String ERROR_PASSWORD_MINIMUM_LENGTH = "password_minimum_length";
private static final String ERROR_PASSWORD_WRONG_FORMAT = "password_format";
private static final String ERROR_PASSWORD_ALREADY_USED = "password_already_used";
private static final String ERROR_MAX_PASSWORD_CHANGE = "max_password_change";
// PROPERTIES
private static final String PROPERTY_DEFAULT_PASSWORD_MINIMAL_LENGTH = "security.defaultValues.passwordMinimalLength";
private static final String PROPERTY_DEFAULT_MAXIMUM_NUMBER_PASSWORD_CHANGE = "security.defaultValues.maximumPasswordChange";
private static final String PROPERTY_DEFAULT_TSW_SIZE_PASSWORD_CHANGE = "security.defaultValues.maximumPasswordChangeTSWSize";
private static final String PROPERTY_DEFAULT_HISTORY_SIZE = "security.defaultValues.passwordHistorySize";
private static final String PROPERTY_DEFAULT_PASSWORD_DURATION = "security.defaultValues.passwordDuration";
private static final String PROPERTY_DEFAULT_ENCRYPTION_ALGORITHM = "security.defaultValues.algorithm";
private static final String JSP_URL_RESET_CONNECTION_LOG = "jsp/site/plugins/mylutece/DoResetConnectionLog.jsp";
private static final String CONSTANT_DEFAULT_ENCRYPTION_ALGORITHM = "SHA-256";
private static final String SEMICOLON = ";";
private static final String CONSTANT_UNDERSCORE = "_";
/**
* Loads a model with base security parameters
*
* @param parameterService
* The parameter service to use
* @param model
* The base model to load
* @param plugin
* The plugin
* @return The model loaded with security parameters
*/
public static Map<String, Object> checkSecurityParameters( IUserParameterService parameterService, Map<String, Object> model, Plugin plugin )
{
boolean bUseAdvancedParameters = getBooleanSecurityParameter( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS );
model.put( MARK_ENABLE_PASSWORD_ENCRYPTION, getBooleanSecurityParameter( parameterService, plugin, MARK_ENABLE_PASSWORD_ENCRYPTION ) );
model.put( MARK_ENCRYPTION_ALGORITHM, parameterService.getEncryptionAlgorithm( plugin ) );
model.put( MARK_FORCE_CHANGE_PASSWORD_REINIT, isChangePasswordForceAfterReinitActivated( parameterService, plugin ) );
model.put( MARK_PASSWORD_MINIMUM_LENGTH, getMinimumPasswordLength( parameterService, plugin ) );
model.put( MARK_USE_ADVANCED_SECURITY_PARAMETERS, bUseAdvancedParameters );
if ( bUseAdvancedParameters )
{
model.put( MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, isPasswordFormatUpperLowerCaseUsed( parameterService, plugin ) );
model.put( MARK_PASSWORD_FORMAT_NUMERO, isPasswordFormatNumeroUsed( parameterService, plugin ) );
model.put( MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, isPasswordFormatSpecialCharactersUsed( parameterService, plugin ) );
model.put( MARK_PASSWORD_DURATION, getPasswordDuration( parameterService, plugin ) );
model.put( MARK_PASSWORD_HISTORY_SIZE, getPasswordHistorySize( parameterService, plugin ) );
model.put( MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, getMaximumNumberPasswordChange( parameterService, plugin ) );
model.put( MARK_TSW_SIZE_PASSWORD_CHANGE, getTSWSizePasswordChange( parameterService, plugin ) );
model.put( MARK_NOTIFY_USER_PASSWORD_EXPIRED, getBooleanSecurityParameter( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED ) );
}
model.put( MARK_ACCOUNT_LIFE_TIME, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCOUNT_LIFE_TIME ) );
model.put( MARK_TIME_BEFORE_ALERT_ACCOUNT, getIntegerSecurityParameter( parameterService, plugin, MARK_TIME_BEFORE_ALERT_ACCOUNT ) );
model.put( MARK_NB_ALERT_ACCOUNT, getIntegerSecurityParameter( parameterService, plugin, MARK_NB_ALERT_ACCOUNT ) );
model.put( MARK_TIME_BETWEEN_ALERTS_ACCOUNT, getIntegerSecurityParameter( parameterService, plugin, MARK_TIME_BETWEEN_ALERTS_ACCOUNT ) );
model.put( MARK_ACCESS_FAILURES_MAX, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCESS_FAILURES_MAX ) );
model.put( MARK_ACCESS_FAILURES_INTERVAL, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCESS_FAILURES_INTERVAL ) );
model.put( MARK_ACCESS_FAILURES_CAPTCHA, getIntegerSecurityParameter( parameterService, plugin, MARK_ACCESS_FAILURES_CAPTCHA ) );
model.put( MARK_ENABLE_UNBLOCK_IP, getBooleanSecurityParameter( parameterService, plugin, MARK_ENABLE_UNBLOCK_IP ) );
model.put( MARK_ENABLE_TOKEN_LOGIN, getBooleanSecurityParameter( parameterService, plugin, MARK_ENABLE_TOKEN_LOGIN ) );
return model;
}
/**
* Update security parameters from request parameters
*
* @param parameterService
* Parameter service
* @param request
* Request to get the parameter from
* @param plugin
* The plugin
*/
public static void updateSecurityParameters( IUserParameterService parameterService, HttpServletRequest request, Plugin plugin )
{
updateParameterValue( parameterService, plugin, MARK_FORCE_CHANGE_PASSWORD_REINIT, request.getParameter( MARK_FORCE_CHANGE_PASSWORD_REINIT ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH, request.getParameter( MARK_PASSWORD_MINIMUM_LENGTH ) );
if ( getBooleanSecurityParameter( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS ) )
{
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE,
request.getParameter( MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO, request.getParameter( MARK_PASSWORD_FORMAT_NUMERO ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS,
request.getParameter( MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_DURATION, request.getParameter( MARK_PASSWORD_DURATION ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE, request.getParameter( MARK_PASSWORD_HISTORY_SIZE ) );
updateParameterValue( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, request.getParameter( MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE ) );
updateParameterValue( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE, request.getParameter( MARK_TSW_SIZE_PASSWORD_CHANGE ) );
updateParameterValue( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED, request.getParameter( MARK_NOTIFY_USER_PASSWORD_EXPIRED ) );
}
// Time of life of accounts
updateParameterValue( parameterService, plugin, MARK_ACCOUNT_LIFE_TIME, request.getParameter( MARK_ACCOUNT_LIFE_TIME ) );
// Time before the first alert when an account will expire
updateParameterValue( parameterService, plugin, MARK_TIME_BEFORE_ALERT_ACCOUNT, request.getParameter( MARK_TIME_BEFORE_ALERT_ACCOUNT ) );
// Number of alerts sent to a user when his account will expire
updateParameterValue( parameterService, plugin, MARK_NB_ALERT_ACCOUNT, request.getParameter( MARK_NB_ALERT_ACCOUNT ) );
// Time between alerts
updateParameterValue( parameterService, plugin, MARK_TIME_BETWEEN_ALERTS_ACCOUNT, request.getParameter( MARK_TIME_BETWEEN_ALERTS_ACCOUNT ) );
updateParameterValue( parameterService, plugin, MARK_ACCESS_FAILURES_MAX, request.getParameter( MARK_ACCESS_FAILURES_MAX ) );
updateParameterValue( parameterService, plugin, MARK_ACCESS_FAILURES_INTERVAL, request.getParameter( MARK_ACCESS_FAILURES_INTERVAL ) );
updateParameterValue( parameterService, plugin, MARK_ACCESS_FAILURES_CAPTCHA, request.getParameter( MARK_ACCESS_FAILURES_CAPTCHA ) );
updateParameterValue( parameterService, plugin, MARK_ENABLE_UNBLOCK_IP, request.getParameter( MARK_ENABLE_UNBLOCK_IP ) );
updateParameterValue( parameterService, plugin, MARK_ENABLE_TOKEN_LOGIN, request.getParameter( MARK_ENABLE_TOKEN_LOGIN ) );
}
/**
* Check whether a user must change his new password after a password reset by mail.
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return true if the user must, false otherwise
*/
private static int getMinimumPasswordLength( IUserParameterService parameterService, Plugin plugin )
{
return getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
}
/**
* Check whether a user must change his new password after a password reset by mail.
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return true if the user must, false otherwise
*/
private static boolean isChangePasswordForceAfterReinitActivated( IUserParameterService parameterService, Plugin plugin )
{
Boolean bIsChecked = Boolean.valueOf( parameterService.findByKey( MARK_FORCE_CHANGE_PASSWORD_REINIT, plugin ).isChecked( ) );
return bIsChecked.booleanValue( );
}
/**
* Check whether a password is long enough.
*
* @param strPassword
* Password to check
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return true is the password is too short, or false if the password correct or if the password's minimum length is disabled.
*/
protected static boolean checkUserPasswordMinimumLength( String strPassword, IUserParameterService parameterService, Plugin plugin )
{
int nMinimumLength = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
return !( ( nMinimumLength > 0 ) && ( strPassword.length( ) < nMinimumLength ) );
}
/**
* Get the admin message telling the password length is too short.
*
* @param request
* The request
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return The URL of the admin message indicating that the entered password is too short.
*/
protected static String getMessagePasswordMinimumLength( HttpServletRequest request, IUserParameterService parameterService, Plugin plugin )
{
Object [ ] param = {
parameterService.findByKey( MARK_PASSWORD_MINIMUM_LENGTH, plugin ).getName( )
};
return AdminMessageService.getMessageUrl( request, MESSAGE_MINIMUM_PASSWORD_LENGTH, param, AdminMessage.TYPE_STOP );
}
/**
* Get the parameter indicating that a password must contain upper and lower case.
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return True if passwords must contain must contain upper and lower case.
*/
protected static boolean isPasswordFormatUpperLowerCaseUsed( IUserParameterService parameterService, Plugin plugin )
{
return getBooleanSecurityParameter( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE );
}
/**
* Get the parameter indicating that a password must contain a numero
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return True if passwords must contain must contain a numero
*/
protected static boolean isPasswordFormatNumeroUsed( IUserParameterService parameterService, Plugin plugin )
{
return getBooleanSecurityParameter( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO );
}
/**
* Get the parameter indicating that a password must contain a numero
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return True if passwords must contain must contain a numero
*/
protected static boolean isPasswordFormatSpecialCharactersUsed( IUserParameterService parameterService, Plugin plugin )
{
return getBooleanSecurityParameter( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS );
}
/**
* Get the password duration
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return The password duration, or 0 if no value or an incorrect value is specified
*/
public static int getPasswordDuration( IUserParameterService parameterService, Plugin plugin )
{
return getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_DURATION );
}
/**
* Get the password history size
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return The password history size, or 0 if no value or an incorrect value is specified
*/
public static int getPasswordHistorySize( IUserParameterService parameterService, Plugin plugin )
{
return getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE );
}
/**
* Get the size of the time sliding window of passwor change
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return the size of the time sliding window of passwor change, or 0 if none is specified
*/
public static int getTSWSizePasswordChange( IUserParameterService parameterService, Plugin plugin )
{
return getIntegerSecurityParameter( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE );
}
/**
* Get the parameter indicating that a password must contain numbers.
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return True if passwords must contain numbers, false otherwise
*/
public static boolean isAdvancedSecurityParametersUsed( IUserParameterService parameterService, Plugin plugin )
{
return getBooleanSecurityParameter( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS );
}
/**
* Get the maximum number of time a user can change his password in a given period
*
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @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
*/
public static int getMaximumNumberPasswordChange( IUserParameterService parameterService, Plugin plugin )
{
return getIntegerSecurityParameter( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE );
}
/**
* Get the integer value of a security parameter
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strParameterkey
* Key of the security parameter to get
* @return The integer value of the security parameter
*/
public static int getIntegerSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
{
ReferenceItem refItem = parameterService.findByKey( strParameterkey, plugin );
if ( ( refItem == null ) || StringUtils.isEmpty( refItem.getName( ) ) )
{
return 0;
}
try
{
int nValue = Integer.parseInt( refItem.getName( ) );
return nValue;
}
catch( NumberFormatException e )
{
return 0;
}
}
/**
* Get the boolean value of a security parameter
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strParameterkey
* Key of the security parameter to get
* @return The boolean value of the security parameter
*/
public static boolean getBooleanSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
{
ReferenceItem refItem = parameterService.findByKey( strParameterkey, plugin );
return ( refItem == null ) ? false : refItem.isChecked( );
}
/**
* Get the value of a security parameter
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strParameterkey
* Key of the security parameter to get
* @return The value of the security parameter
*/
public static String getSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
{
ReferenceItem refItem = parameterService.findByKey( strParameterkey, plugin );
return ( refItem == null ) ? null : refItem.getName( );
}
/**
* Get the large value of a security parameter.
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strParameterkey
* Key of the security parameter to get
* @return The value of the security parameter
*/
public static String getLargeSecurityParameter( IUserParameterService parameterService, Plugin plugin, String strParameterkey )
{
return DatastoreService.getDataValue( plugin.getName( ) + CONSTANT_UNDERSCORE + strParameterkey, StringUtils.EMPTY );
}
/**
* Gets the admin message saying that the password does not match the required format
*
* @param request
* The request
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @return the url of the admin message saying that the password does not match the required format
*/
protected static String getMessageBackPasswordFormat( HttpServletRequest request, IUserParameterService parameterService, Plugin plugin )
{
Object [ ] param = {
getMessagePasswordFormat( parameterService, request.getLocale( ), plugin )
};
return AdminMessageService.getMessageUrl( request, MESSAGE_PASSWORD_FORMAT, param, AdminMessage.TYPE_STOP );
}
/**
* Gets the password message format required format
*
* @param locale
* the locale
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @return the url of the admin message saying that the password does not match the required format
*/
public static String getMessageFrontPasswordFormat( Locale locale, IUserParameterService parameterService, Plugin plugin )
{
Object [ ] param = {
getMessagePasswordFormat( parameterService, locale, plugin )
};
return I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT, param, locale );
}
/**
* The password format message
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param locale
* the locale
* @return
*/
private static String getMessagePasswordFormat( IUserParameterService parameterService, Locale locale, Plugin plugin )
{
StringBuffer strParam = new StringBuffer( );
boolean bUserPasswordFormatUpperLowerCase = isPasswordFormatUpperLowerCaseUsed( parameterService, plugin );
boolean bUserPasswordFormatNumero = isPasswordFormatNumeroUsed( parameterService, plugin );
boolean bUserPasswordFormatSpecialCaracters = isPasswordFormatSpecialCharactersUsed( parameterService, plugin );
// Add Message Upper Lower Case
if ( bUserPasswordFormatUpperLowerCase )
{
strParam.append( I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT_UPPER_LOWER_CASE, locale ) );
}
// Add Message Numero
if ( bUserPasswordFormatNumero )
{
if ( bUserPasswordFormatUpperLowerCase )
{
strParam.append( ", " );
}
strParam.append( I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT_NUMERO, locale ) );
}
// Add Message Special Characters
if ( bUserPasswordFormatSpecialCaracters )
{
if ( bUserPasswordFormatUpperLowerCase || bUserPasswordFormatNumero )
{
strParam.append( ", " );
}
strParam.append( I18nService.getLocalizedString( MESSAGE_PASSWORD_FORMAT_SPECIAL_CHARACTERS, locale ) );
}
return strParam.toString( );
}
/**
* Updates a parameter from its key with a new value.
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strKey
* The key of the parameter to update
* @param strValue
* The new value of the parameter
*/
public static void updateParameterValue( IUserParameterService parameterService, Plugin plugin, String strKey, String strValue )
{
ReferenceItem userParam = new ReferenceItem( );
userParam.setCode( strKey );
strValue = ( strValue == null ) ? StringUtils.EMPTY : strValue;
userParam.setName( strValue );
parameterService.update( userParam, plugin );
}
/**
* 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.
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strKey
* The key of the parameter to update
* @param strValue
* The new value of the parameter
*/
public static void updateLargeParameterValue( IUserParameterService parameterService, Plugin plugin, String strKey, String strValue )
{
DatastoreService.setDataValue( plugin.getName( ) + CONSTANT_UNDERSCORE + strKey, strValue );
}
/**
* Enable advanced security parameters
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
*/
public static void useAdvancedSecurityParameters( IUserParameterService parameterService, Plugin plugin )
{
updateParameterValue( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS, Boolean.TRUE.toString( ) );
updateParameterValue( parameterService, plugin, MARK_FORCE_CHANGE_PASSWORD_REINIT, Boolean.TRUE.toString( ) );
updateParameterValue( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE,
AppPropertiesService.getProperty( PROPERTY_DEFAULT_MAXIMUM_NUMBER_PASSWORD_CHANGE ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_DURATION, AppPropertiesService.getProperty( PROPERTY_DEFAULT_PASSWORD_DURATION ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, Boolean.TRUE.toString( ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO, Boolean.TRUE.toString( ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, Boolean.TRUE.toString( ) );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE, AppPropertiesService.getProperty( PROPERTY_DEFAULT_HISTORY_SIZE ) );
updateParameterValue( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE,
AppPropertiesService.getProperty( PROPERTY_DEFAULT_TSW_SIZE_PASSWORD_CHANGE ) );
int nMinPwdLength = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
if ( nMinPwdLength <= 0 )
{
updateParameterValue( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH,
AppPropertiesService.getProperty( PROPERTY_DEFAULT_PASSWORD_MINIMAL_LENGTH ) );
}
updateParameterValue( parameterService, plugin, MARK_ENABLE_PASSWORD_ENCRYPTION, Boolean.TRUE.toString( ) );
updateParameterValue( parameterService, plugin, MARK_ENCRYPTION_ALGORITHM,
AppPropertiesService.getProperty( PROPERTY_DEFAULT_ENCRYPTION_ALGORITHM, CONSTANT_DEFAULT_ENCRYPTION_ALGORITHM ) );
updateParameterValue( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED, Boolean.TRUE.toString( ) );
}
/**
* Remove the advanced security parameters
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
*/
public static void removeAdvancedSecurityParameters( IUserParameterService parameterService, Plugin plugin )
{
updateParameterValue( parameterService, plugin, MARK_USE_ADVANCED_SECURITY_PARAMETERS, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_DURATION, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_UPPER_LOWER_CASE, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_NUMERO, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_FORMAT_SPECIAL_CHARACTERS, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE, StringUtils.EMPTY );
updateParameterValue( parameterService, plugin, MARK_NOTIFY_USER_PASSWORD_EXPIRED, StringUtils.EMPTY );
}
/**
* Get the current maximum valid date of a password from the parameter service.
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @return The maximum valid date of a password
*/
public static Timestamp getPasswordMaxValidDate( IUserParameterService parameterService, Plugin plugin )
{
int nbDayPasswordValid = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_DURATION );
if ( nbDayPasswordValid <= 0 )
{
return null;
}
return PasswordUtil.getPasswordMaxValidDate( nbDayPasswordValid );
}
/**
* Compute the maximum valid date of an account with the current time and the parameters in the database.
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @return The maximum valid date of an account
*/
public static Timestamp getAccountMaxValidDate( IUserParameterService parameterService, Plugin plugin )
{
int nbDaysPasswordValid = getIntegerSecurityParameter( parameterService, plugin, MARK_ACCOUNT_LIFE_TIME );
if ( nbDaysPasswordValid <= 0 )
{
return null;
}
Calendar calendare = new GregorianCalendar( Locale.getDefault( ) );
calendare.add( Calendar.DAY_OF_MONTH, nbDaysPasswordValid );
return new Timestamp( calendare.getTimeInMillis( ) );
}
/**
* Test a password validity
*
* @param parameterService
* Paramter service to use
* @param plugin
* The plugin
* @param strPassword
* The password to test validity
* @param nUserId
* The id of the user
* @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
* short, or 'password_format' if the format of the password is not correct.
*/
public static String checkPasswordForFrontOffice( IUserParameterService parameterService, Plugin plugin, String strPassword, int nUserId )
{
// Check minimum length password
if ( !( SecurityUtils.checkUserPasswordMinimumLength( strPassword, parameterService, plugin ) ) )
{
return ERROR_PASSWORD_MINIMUM_LENGTH;
}
// Check password format
if ( !( SecurityUtils.checkPasswordFormat( strPassword, parameterService, plugin ) ) )
{
return ERROR_PASSWORD_WRONG_FORMAT;
}
// Check password history
if ( nUserId > 0 )
{
int nPasswordHistorySize = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_HISTORY_SIZE );
if ( nPasswordHistorySize > 0 )
{
String strEncryptedPassword = buildPassword( parameterService, plugin, strPassword );
List<String> passwordHistory = parameterService.selectUserPasswordHistory( nUserId, plugin );
if ( nPasswordHistorySize < passwordHistory.size( ) )
{
passwordHistory = passwordHistory.subList( 0, nPasswordHistorySize );
}
if ( passwordHistory.contains( strEncryptedPassword ) )
{
return ERROR_PASSWORD_ALREADY_USED;
}
}
int nTSWSizePasswordChange = getIntegerSecurityParameter( parameterService, plugin, MARK_TSW_SIZE_PASSWORD_CHANGE );
int nMaximumNumberPasswordChange = getIntegerSecurityParameter( parameterService, plugin, MARK_MAXIMUM_NUMBER_PASSWORD_CHANGE );
if ( nMaximumNumberPasswordChange > 0 )
{
Timestamp minDate = null;
if ( nTSWSizePasswordChange > 0 )
{
minDate = new Timestamp( new java.util.Date( ).getTime( ) - DateUtil.convertDaysInMiliseconds( nTSWSizePasswordChange ) );
}
else
{
minDate = new Timestamp( 0 );
}
if ( parameterService.countUserPasswordHistoryFromDate( minDate, nUserId, plugin ) >= nMaximumNumberPasswordChange )
{
return ERROR_MAX_PASSWORD_CHANGE;
}
}
}
return null;
}
/**
* Test a password validity
*
* @param parameterService
* Parameter service to use
* @param plugin
* The plugin
* @param strPassword
* Password to check
* @param request
* The request
* @return Returns null if the password is correct, or an admin message describing the error
*/
public static String checkPasswordForBackOffice( IUserParameterService parameterService, Plugin plugin, String strPassword, HttpServletRequest request )
{
if ( !SecurityUtils.checkUserPasswordMinimumLength( strPassword, parameterService, plugin ) )
{
return SecurityUtils.getMessagePasswordMinimumLength( request, parameterService, plugin );
}
if ( !SecurityUtils.checkPasswordFormat( strPassword, parameterService, plugin ) )
{
return SecurityUtils.getMessageBackPasswordFormat( request, parameterService, plugin );
}
return null;
}
/**
* Build the password depending of the encryption. If the encryption is enable, then it returns the password encrypted, otherwise it just returns the
* password given in parameter.
*
* @param parameterService
* The parameter service to use
* @param plugin
* The plugin
* @param strUserPassword
* the password
* @return the password encrypted or not
*/
public static String buildPassword( IUserParameterService parameterService, Plugin plugin, String strUserPassword )
{
// Check if there is an encryption algorithm
String strPassword = strUserPassword;
if ( parameterService.isPasswordEncrypted( plugin ) )
{
String strAlgorithm = parameterService.getEncryptionAlgorithm( plugin );
strPassword = CryptoService.encrypt( strUserPassword, strAlgorithm );
}
return strPassword;
}
/**
* Generate a new random password
*
* @param parameterService
* The parameter service to use
* @return the new password
*/
public static String makePassword( IUserParameterService parameterService, Plugin plugin )
{
int nMinimumLength = getIntegerSecurityParameter( parameterService, plugin, MARK_PASSWORD_MINIMUM_LENGTH );
return PasswordUtil.makePassword( nMinimumLength, isPasswordFormatUpperLowerCaseUsed( parameterService, plugin ),
isPasswordFormatNumeroUsed( parameterService, plugin ), isPasswordFormatSpecialCharactersUsed( parameterService, plugin ) );
}
/**
* Get an array containing banned domain names for email adresses
*
* @param parameterService
* Parameter service
* @param plugin
* The plugin
* @return An array containing banned domain names for email adresses
*/
public static String [ ] getBannedDomainNames( IUserParameterService parameterService, Plugin plugin )
{
String strDomainNames = SecurityUtils.getLargeSecurityParameter( parameterService, plugin, MARK_BANNED_DOMAIN_NAMES );
if ( StringUtils.isNotBlank( strDomainNames ) )
{
return strDomainNames.split( SEMICOLON );
}
return null;
}
/**
* Build an url to reset connection logs for an IP and a given user. Data is read from the request.
*
* @param nInterval
* Interval of time to reset
* @param request
* The request
* @return The url to reset connection logs.
*/
public static String buildResetConnectionLogUrl( int nInterval, HttpServletRequest request )
{
UrlItem url = new UrlItem( AppPathService.getBaseUrl( request ) + JSP_URL_RESET_CONNECTION_LOG );
String strIp = request.getRemoteAddr( );
String strDate = Long.toString( new Date( ).getTime( ) );
String strInterval = Integer.toString( nInterval );
url.addParameter( PARAMETER_IP, strIp );
url.addParameter( PARAMETER_DATE_LOGIN, strDate );
url.addParameter( PARAMETER_INTERVAL, strInterval );
String strCryptoKey = CryptoService.getCryptoKey( );
url.addParameter( PARAMETER_KEY, CryptoService.encrypt( strIp + strDate + strInterval + strCryptoKey,
AppPropertiesService.getProperty( PROPERTY_DEFAULT_ENCRYPTION_ALGORITHM, CONSTANT_DEFAULT_ENCRYPTION_ALGORITHM ) ) );
return url.getUrl( );
}
/**
* Check the format of the password from the entered parameters. The password may have to contain upper and lower case letters, numbers and special
* characters.
*
* @param strPassword
* The password to check
* @param parameterService
* Parameter service to get parameters from.
* @param plugin
* The plugin
* @return True if the giver parameter respect the parametered format, false if he violate one or more rules.
*/
protected static boolean checkPasswordFormat( String strPassword, IUserParameterService parameterService, Plugin plugin )
{
boolean bPasswordFormat = isPasswordFormatNumeroUsed( parameterService, plugin ) || isPasswordFormatSpecialCharactersUsed( parameterService, plugin )
|| isPasswordFormatUpperLowerCaseUsed( parameterService, plugin );
return bPasswordFormat ? PasswordUtil.checkPasswordFormat( strPassword, isPasswordFormatUpperLowerCaseUsed( parameterService, plugin ),
isPasswordFormatNumeroUsed( parameterService, plugin ), isPasswordFormatSpecialCharactersUsed( parameterService, plugin ) ) : true;
}
}