/* * Password Management Servlets (PWM) * http://www.pwm-project.org * * Copyright (c) 2006-2009 Novell, Inc. * Copyright (c) 2009-2017 The PWM Project * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ package password.pwm.http.tag; import password.pwm.PwmApplication; import password.pwm.config.Configuration; import password.pwm.config.option.ADPolicyComplexity; import password.pwm.config.profile.NewUserProfile; import password.pwm.config.profile.PwmPasswordPolicy; import password.pwm.config.profile.PwmPasswordRule; import password.pwm.http.PwmRequest; import password.pwm.http.PwmSession; import password.pwm.http.servlet.newuser.NewUserServlet; import password.pwm.i18n.Display; import password.pwm.i18n.Message; import password.pwm.util.LocaleHelper; import password.pwm.util.java.StringUtil; import password.pwm.util.logging.PwmLogger; import password.pwm.util.macro.MacroMachine; import javax.servlet.http.HttpServletRequest; import javax.servlet.http.HttpServletResponse; import javax.servlet.jsp.JspTagException; import javax.servlet.jsp.tagext.TagSupport; import java.util.ArrayList; import java.util.List; import java.util.Locale; import java.util.MissingResourceException; /** * @author Jason D. Rivard */ public class PasswordRequirementsTag extends TagSupport { // ------------------------------ FIELDS ------------------------------ private static final PwmLogger LOGGER = PwmLogger.forClass(PasswordRequirementsTag.class); private String separator; private String prepend; private String form; // -------------------------- STATIC METHODS -------------------------- public static List<String> getPasswordRequirementsStrings( final PwmPasswordPolicy pwordPolicy, final Configuration config, final Locale locale, final MacroMachine macroMachine ) { final List<String> returnValues = new ArrayList<>(); final ADPolicyComplexity ADPolicyLevel = pwordPolicy.getRuleHelper().getADComplexityLevel(); final PwmPasswordPolicy.RuleHelper ruleHelper = pwordPolicy.getRuleHelper(); if (ruleHelper.readBooleanValue(PwmPasswordRule.CaseSensitive)) { returnValues.add(getLocalString(Message.Requirement_CaseSensitive, null, locale, config)); } else { returnValues.add(getLocalString(Message.Requirement_NotCaseSensitive, null, locale, config)); } { int value = ruleHelper.readIntValue(PwmPasswordRule.MinimumLength); if (ADPolicyLevel == ADPolicyComplexity.AD2003 || ADPolicyLevel == ADPolicyComplexity.AD2008) { if (value < 6) { value = 6; } } if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MinLength, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MaximumLength); if (value > 0 && value < 64) { returnValues.add(getLocalString(Message.Requirement_MaxLength, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MinimumAlpha); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MinAlpha, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MaximumAlpha); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MaxAlpha, value, locale, config)); } } { if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowNumeric)) { returnValues.add(getLocalString(Message.Requirement_AllowNumeric, null, locale, config)); } else { final int minValue = ruleHelper.readIntValue(PwmPasswordRule.MinimumNumeric); if (minValue > 0) { returnValues.add(getLocalString(Message.Requirement_MinNumeric, minValue, locale, config)); } final int maxValue = ruleHelper.readIntValue(PwmPasswordRule.MaximumNumeric); if (maxValue > 0) { returnValues.add(getLocalString(Message.Requirement_MaxNumeric, maxValue, locale, config)); } if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowFirstCharNumeric)) { returnValues.add(getLocalString(Message.Requirement_FirstNumeric, maxValue, locale, config)); } if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowLastCharNumeric)) { returnValues.add(getLocalString(Message.Requirement_LastNumeric, maxValue, locale, config)); } } } { if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowSpecial)) { returnValues.add(getLocalString(Message.Requirement_AllowSpecial, null, locale, config)); } else { final int minValue = ruleHelper.readIntValue(PwmPasswordRule.MinimumSpecial); if (minValue > 0) { returnValues.add(getLocalString(Message.Requirement_MinSpecial, minValue, locale, config)); } final int maxValue = ruleHelper.readIntValue(PwmPasswordRule.MaximumSpecial); if (maxValue > 0) { returnValues.add(getLocalString(Message.Requirement_MaxSpecial, maxValue, locale, config)); } if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowFirstCharSpecial)) { returnValues.add(getLocalString(Message.Requirement_FirstSpecial, maxValue, locale, config)); } if (!ruleHelper.readBooleanValue(PwmPasswordRule.AllowLastCharSpecial)) { returnValues.add(getLocalString(Message.Requirement_LastSpecial, maxValue, locale, config)); } } } { final int value = pwordPolicy.getRuleHelper().readIntValue(PwmPasswordRule.MaximumRepeat); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MaxRepeat, value, locale, config)); } } { final int value = pwordPolicy.getRuleHelper().readIntValue(PwmPasswordRule.MaximumSequentialRepeat); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MaxSeqRepeat, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MinimumLowerCase); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MinLower, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MaximumLowerCase); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MaxLower, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MinimumUpperCase); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MinUpper, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MaximumUpperCase); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MaxUpper, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MinimumUnique); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_MinUnique, value, locale, config)); } } { final List<String> setValue = ruleHelper.getDisallowedValues(); if (!setValue.isEmpty()) { final StringBuilder fieldValue = new StringBuilder(); for (final String loopValue : setValue) { fieldValue.append(" "); final String expandedValue = macroMachine.expandMacros(loopValue); fieldValue.append(StringUtil.escapeHtml(expandedValue)); } returnValues.add( getLocalString(Message.Requirement_DisAllowedValues, fieldValue.toString(), locale, config)); } } { final List<String> setValue = ruleHelper.getDisallowedAttributes(); if (!setValue.isEmpty() || ADPolicyLevel == ADPolicyComplexity.AD2003) { returnValues.add(getLocalString(Message.Requirement_DisAllowedAttributes, "", locale, config)); } } if (ruleHelper.readBooleanValue(PwmPasswordRule.EnableWordlist)) { returnValues.add(getLocalString(Message.Requirement_WordList, "", locale, config)); } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MaximumOldChars); if (value > 0) { returnValues.add(getLocalString(Message.Requirement_OldChar, value, locale, config)); } } { final int value = ruleHelper.readIntValue(PwmPasswordRule.MinimumLifetime); if (value > 0) { final int SECONDS_PER_DAY = 60 * 60 * 24; final String durationStr; if (value % SECONDS_PER_DAY == 0) { final int valueAsDays = value / (60 * 60 * 24); final Display key = valueAsDays <= 1 ? Display.Display_Day : Display.Display_Days; durationStr = valueAsDays + " " + LocaleHelper.getLocalizedMessage(locale, key, config); } else { final int valueAsHours = value / (60 * 60); final Display key = valueAsHours <= 1 ? Display.Display_Hour : Display.Display_Hours; durationStr = valueAsHours + " " + LocaleHelper.getLocalizedMessage(locale, key, config); } final String userMsg = Message.getLocalizedMessage(locale, Message.Requirement_MinimumFrequency, config, durationStr); returnValues.add(userMsg); } } if (ADPolicyLevel == ADPolicyComplexity.AD2003) { returnValues.add(getLocalString(Message.Requirement_ADComplexity, "", locale, config)); } else if (ADPolicyLevel == ADPolicyComplexity.AD2008) { final int maxViolations = ruleHelper.readIntValue(PwmPasswordRule.ADComplexityMaxViolations); final int minGroups = 5 - maxViolations; returnValues.add(getLocalString(Message.Requirement_ADComplexity2008, String.valueOf(minGroups), locale, config)); } if (ruleHelper.readBooleanValue(PwmPasswordRule.UniqueRequired)) { returnValues.add(getLocalString(Message.Requirement_UniqueRequired, "", locale, config)); } return returnValues; } private static String getLocalString(final Message message, final int size, final Locale locale, final Configuration config) { final Message effectiveMessage = size > 1 && message.getPluralMessage() != null ? message.getPluralMessage() : message; try { return Message.getLocalizedMessage(locale, effectiveMessage, config, String.valueOf(size)); } catch (MissingResourceException e) { LOGGER.error("unable to display requirement tag for message '" + message.toString() + "': " + e.getMessage()); } return "UNKNOWN MESSAGE STRING"; } private static String getLocalString(final Message message, final String field, final Locale locale, final Configuration config) { try { return Message.getLocalizedMessage(locale, message, config, field); } catch (MissingResourceException e) { LOGGER.error("unable to display requirement tag for message '" + message.toString() + "': " + e.getMessage()); } return "UNKNOWN MESSAGE STRING"; } // --------------------- GETTER / SETTER METHODS --------------------- public String getSeparator() { return separator; } public void setSeparator(final String separator) { this.separator = separator; } public String getPrepend() { return prepend; } public void setPrepend(final String prepend) { this.prepend = prepend; } public String getForm() { return form; } public void setForm(final String form) { this.form = form; } // ------------------------ INTERFACE METHODS ------------------------ // --------------------- Interface Tag --------------------- public int doEndTag() throws javax.servlet.jsp.JspTagException { try { final PwmRequest pwmRequest = PwmRequest.forRequest((HttpServletRequest)pageContext.getRequest(),(HttpServletResponse)pageContext.getResponse()); final PwmSession pwmSession = pwmRequest.getPwmSession(); final PwmApplication pwmApplication = pwmRequest.getPwmApplication(); final Configuration config = pwmApplication.getConfig(); final Locale locale = pwmSession.getSessionStateBean().getLocale(); pwmSession.getSessionManager().getMacroMachine(pwmApplication); final PwmPasswordPolicy passwordPolicy; if (getForm() != null && getForm().equalsIgnoreCase("newuser")) { final NewUserProfile newUserProfile = NewUserServlet.getNewUserProfile(pwmRequest); passwordPolicy = newUserProfile.getNewUserPasswordPolicy(pwmApplication, locale); } else { passwordPolicy = pwmSession.getUserInfoBean().getPasswordPolicy(); } final String configuredRuleText = passwordPolicy.getRuleText(); if (configuredRuleText != null && configuredRuleText.length() > 0) { pageContext.getOut().write(configuredRuleText); } else { final MacroMachine macroMachine = pwmSession.getSessionManager().getMacroMachine(pwmApplication); final String pre = prepend != null && prepend.length() > 0 ? prepend : ""; final String sep = separator != null && separator.length() > 0 ? separator : "<br/>"; final List<String> requirementsList = getPasswordRequirementsStrings(passwordPolicy, config, locale, macroMachine); final StringBuilder requirementsText = new StringBuilder(); for (final String requirementStatement : requirementsList) { requirementsText.append(pre); requirementsText.append(requirementStatement); requirementsText.append(sep); } pageContext.getOut().write(requirementsText.toString()); } } catch (Exception e) { LOGGER.error("unexpected error during password requirements generation: " + e.getMessage(), e); throw new JspTagException(e.getMessage()); } return EVAL_PAGE; } }