001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. 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, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020 021package org.apache.directory.server.core.authn; 022 023 024import org.apache.directory.api.ldap.model.constants.SchemaConstants; 025import org.apache.directory.api.util.Base64; 026import org.apache.directory.api.util.Strings; 027 028 029/** 030 * A class to hold the data of historical passwords of a entry. 031 * Note: This class's natural ordering is inconsistent with the equals() method 032 * hence it is advised not to use this in any implementations of sorted sets 033 * Instead use Collections.sort() to sort the collection of PasswordHistory objects. 034 * 035 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 036 * @version $Rev$, $Date$ 037 */ 038public class PasswordHistory implements Comparable<PasswordHistory> 039{ 040 /** time when password was last changed */ 041 private String time; 042 043 /** the syntax OID that is to be used on the password data */ 044 private String syntaxOID = SchemaConstants.OCTET_STRING_SYNTAX; 045 046 /** the length of the password data */ 047 private int length; 048 049 /** password octet string */ 050 private String data; 051 052 private static final char DELIMITER = '#'; 053 054 055 /** 056 * Create a new instance of PasswordHistory 057 * 058 * @param pwdHistoryVal The history date 059 */ 060 public PasswordHistory( String pwdHistoryVal ) 061 { 062 int pos = pwdHistoryVal.indexOf( DELIMITER ); 063 time = pwdHistoryVal.substring( 0, pos ); 064 065 pos++; 066 int nextPos = pwdHistoryVal.indexOf( DELIMITER, pos ); 067 syntaxOID = pwdHistoryVal.substring( pos, nextPos ); 068 069 nextPos++; 070 pos = pwdHistoryVal.indexOf( DELIMITER, nextPos ); 071 length = Integer.parseInt( pwdHistoryVal.substring( nextPos, pos ) ); 072 073 data = pwdHistoryVal.substring( pos + 1 ); 074 } 075 076 077 /** 078 * Create a new instance of PasswordHistory 079 * 080 * @param time The time we changed the password 081 * @param password The password to store 082 */ 083 public PasswordHistory( String time, byte[] password ) 084 { 085 this.time = time; 086 this.data = String.valueOf( Base64.encode( password ) ); 087 this.length = data.length(); 088 } 089 090 091 public byte[] getHistoryValue() 092 { 093 StringBuilder sb = new StringBuilder(); 094 095 sb.append( time ).append( DELIMITER ); 096 097 sb.append( syntaxOID ).append( DELIMITER ); 098 099 sb.append( length ).append( DELIMITER ); 100 101 sb.append( data ); 102 103 return Strings.getBytesUtf8( sb.toString() ); 104 } 105 106 107 public String getTime() 108 { 109 return time; 110 } 111 112 113 public String getSyntaxOID() 114 { 115 return syntaxOID; 116 } 117 118 119 public int getLength() 120 { 121 return length; 122 } 123 124 125 public byte[] getPassword() 126 { 127 return Base64.decode( data.toCharArray() ); 128 } 129 130 131 /** 132 * {@inheritDoc} 133 */ 134 @Override 135 public int compareTo( PasswordHistory o ) 136 { 137 return o.getTime().compareTo( time ); 138 } 139 140 141 /** 142 * @see Object#toString() 143 */ 144 @Override 145 public boolean equals( Object o ) 146 { 147 if ( !( o instanceof PasswordHistory ) ) 148 { 149 return false; 150 } 151 152 PasswordHistory other = ( PasswordHistory ) o; 153 154 return this.getTime().equals( other.getTime() ) && this.data.equals( other.data ); 155 } 156 157 158 @Override 159 public int hashCode() 160 { 161 final int prime = 31; 162 int result = 1; 163 result = prime * result + ( ( data == null ) ? 0 : data.hashCode() ); 164 result = prime * result + length; 165 result = prime * result + ( ( syntaxOID == null ) ? 0 : syntaxOID.hashCode() ); 166 result = prime * result + ( ( time == null ) ? 0 : time.hashCode() ); 167 return result; 168 } 169 170 171 @Override 172 public String toString() 173 { 174 return "PasswordHistory [time=" + time + ", syntaxOID=" + syntaxOID + ", length=" + length + ", data=" + data 175 + "]"; 176 } 177}