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