001package org.apache.archiva.redback.policy.rules; 002 003/* 004 * Copyright 2001-2006 The Apache Software Foundation. 005 * 006 * Licensed under the Apache License, Version 2.0 (the "License"); 007 * you may not use this file except in compliance with the License. 008 * You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, software 013 * distributed under the License is distributed on an "AS IS" BASIS, 014 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 015 * See the License for the specific language governing permissions and 016 * limitations under the License. 017 */ 018 019import org.apache.archiva.redback.configuration.UserConfigurationKeys; 020import org.apache.archiva.redback.policy.PasswordRuleViolations; 021import org.apache.archiva.redback.policy.UserSecurityPolicy; 022import org.apache.archiva.redback.users.User; 023import org.apache.commons.lang3.StringUtils; 024import org.springframework.stereotype.Service; 025 026import javax.annotation.PostConstruct; 027import java.util.Iterator; 028 029/** 030 * Password Rule, Checks supplied password found at {@link User#getPassword()} against 031 * the {@link User#getPreviousEncodedPasswords()} to ensure that a password is not reused. 032 * 033 * @author <a href="mailto:joakim@erdfelt.com">Joakim Erdfelt</a> 034 */ 035@Service("passwordRule#reuse") 036public class ReusePasswordRule 037 extends AbstractPasswordRule 038{ 039 public static final String REUSE_VIOLATION = "user.password.violation.reuse"; 040 041 private UserSecurityPolicy securityPolicy; 042 043 public void setUserSecurityPolicy( UserSecurityPolicy policy ) 044 { 045 this.securityPolicy = policy; 046 } 047 048 /** 049 * true if the security policy is required for this rule 050 * 051 * @return boolean 052 */ 053 public boolean requiresSecurityPolicy() 054 { 055 return true; 056 } 057 058 public int getPreviousPasswordCount() 059 { 060 if ( securityPolicy == null ) 061 { 062 throw new IllegalStateException( "The security policy has not yet been set." ); 063 } 064 065 return securityPolicy.getPreviousPasswordsCount(); 066 } 067 068 private boolean hasReusedPassword( User user, String password ) 069 { 070 if ( securityPolicy == null ) 071 { 072 throw new IllegalStateException( "The security policy has not yet been set." ); 073 } 074 075 if ( StringUtils.isEmpty( password ) ) 076 { 077 return false; 078 } 079 080 String encodedPassword = securityPolicy.getPasswordEncoder().encodePassword( password ); 081 082 int checkCount = getPreviousPasswordCount(); 083 084 Iterator<String> it = user.getPreviousEncodedPasswords().iterator(); 085 086 while ( it.hasNext() && checkCount >= 0 ) 087 { 088 String prevEncodedPassword = it.next(); 089 if ( encodedPassword.equals( prevEncodedPassword ) ) 090 { 091 return true; 092 } 093 checkCount--; 094 } 095 096 return false; 097 } 098 099 public void setPreviousPasswordCount( int previousPasswordCount ) 100 { 101 securityPolicy.setPreviousPasswordsCount( previousPasswordCount ); 102 } 103 104 public void testPassword( PasswordRuleViolations violations, User user ) 105 { 106 String password = user.getPassword(); 107 108 if ( hasReusedPassword( user, password ) ) 109 { 110 violations.addViolation( REUSE_VIOLATION, 111 new String[]{ String.valueOf( getPreviousPasswordCount() ) } ); //$NON-NLS-1$ 112 } 113 } 114 115 @PostConstruct 116 public void initialize() 117 { 118 enabled = config.getBoolean( UserConfigurationKeys.POLICY_PASSWORD_RULE_REUSE_ENABLED ); 119 } 120}