001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2006-2008 Sun Microsystems, Inc. 015 * Portions Copyright 2014-2015 ForgeRock AS. 016 */ 017package org.opends.server.extensions; 018 019import org.forgerock.i18n.LocalizableMessage; 020import java.util.List; 021import java.util.Set; 022 023import org.opends.server.admin.server.ConfigurationChangeListener; 024import org.opends.server.admin.std.server.LengthBasedPasswordValidatorCfg; 025import org.opends.server.admin.std.server.PasswordValidatorCfg; 026import org.opends.server.api.PasswordValidator; 027import org.forgerock.opendj.config.server.ConfigChangeResult; 028import org.forgerock.opendj.config.server.ConfigException; 029import org.opends.server.types.*; 030import org.forgerock.opendj.ldap.ByteString; 031import static org.opends.messages.ExtensionMessages.*; 032import org.forgerock.i18n.LocalizableMessageBuilder; 033 034/** 035 * This class provides a password validator that can ensure that the provided 036 * password meets minimum and/or maximum length requirements. 037 */ 038public class LengthBasedPasswordValidator extends 039 PasswordValidator<LengthBasedPasswordValidatorCfg> implements 040 ConfigurationChangeListener<LengthBasedPasswordValidatorCfg> 041{ 042 /** The current configuration for this password validator. */ 043 private LengthBasedPasswordValidatorCfg currentConfig; 044 045 046 047 /** 048 * Creates a new instance of this password validator. 049 */ 050 public LengthBasedPasswordValidator() 051 { 052 super(); 053 054 // All initialization must be done in the initializePasswordValidator 055 // method. 056 } 057 058 059 060 /** {@inheritDoc} */ 061 @Override 062 public void initializePasswordValidator( 063 LengthBasedPasswordValidatorCfg configuration) 064 throws ConfigException, InitializationException 065 { 066 configuration.addLengthBasedChangeListener(this); 067 068 currentConfig = configuration; 069 070 // Make sure that if both the maximum and minimum lengths are set, the 071 // maximum length is greater than or equal to the minimum length. 072 int maxLength = configuration.getMaxPasswordLength(); 073 int minLength = configuration.getMinPasswordLength(); 074 if (maxLength > 0 && minLength > 0 && minLength > maxLength) 075 { 076 LocalizableMessage message = 077 ERR_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX.get(minLength, maxLength); 078 throw new ConfigException(message); 079 } 080 } 081 082 083 084 /** {@inheritDoc} */ 085 @Override 086 public void finalizePasswordValidator() 087 { 088 currentConfig.removeLengthBasedChangeListener(this); 089 } 090 091 092 093 /** {@inheritDoc} */ 094 @Override 095 public boolean passwordIsAcceptable(ByteString newPassword, 096 Set<ByteString> currentPasswords, 097 Operation operation, Entry userEntry, 098 LocalizableMessageBuilder invalidReason) 099 { 100 LengthBasedPasswordValidatorCfg config = currentConfig; 101 102 int numChars = newPassword.toString().length(); 103 104 int minLength = config.getMinPasswordLength(); 105 if (minLength > 0 && numChars < minLength) 106 { 107 invalidReason.append(ERR_PWLENGTHVALIDATOR_TOO_SHORT.get(minLength)); 108 return false; 109 } 110 111 int maxLength = config.getMaxPasswordLength(); 112 if (maxLength > 0 && numChars > maxLength) 113 { 114 invalidReason.append(ERR_PWLENGTHVALIDATOR_TOO_LONG.get(maxLength)); 115 return false; 116 } 117 118 return true; 119 } 120 121 122 123 /** {@inheritDoc} */ 124 @Override 125 public boolean isConfigurationAcceptable(PasswordValidatorCfg configuration, 126 List<LocalizableMessage> unacceptableReasons) 127 { 128 LengthBasedPasswordValidatorCfg config = 129 (LengthBasedPasswordValidatorCfg) configuration; 130 return isConfigurationChangeAcceptable(config, unacceptableReasons); 131 } 132 133 134 135 /** {@inheritDoc} */ 136 public boolean isConfigurationChangeAcceptable( 137 LengthBasedPasswordValidatorCfg configuration, 138 List<LocalizableMessage> unacceptableReasons) 139 { 140 // Make sure that if both the maximum and minimum lengths are set, the 141 // maximum length is greater than or equal to the minimum length. 142 int maxLength = configuration.getMaxPasswordLength(); 143 int minLength = configuration.getMinPasswordLength(); 144 if (maxLength > 0 && minLength > 0 && minLength > maxLength) 145 { 146 LocalizableMessage message = ERR_PWLENGTHVALIDATOR_MIN_GREATER_THAN_MAX.get( 147 minLength, maxLength); 148 unacceptableReasons.add(message); 149 return false; 150 } 151 152 return true; 153 } 154 155 156 157 /** {@inheritDoc} */ 158 public ConfigChangeResult applyConfigurationChange( 159 LengthBasedPasswordValidatorCfg configuration) 160 { 161 currentConfig = configuration; 162 return new ConfigChangeResult(); 163 } 164}