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 java.nio.charset.StandardCharsets; 025import java.util.Base64; 026 027import org.apache.directory.api.ldap.model.constants.SchemaConstants; 028import org.apache.directory.api.util.Strings; 029 030 031/** 032 * A class to hold the data of historical passwords of a entry. 033 * Note: This class's natural ordering is inconsistent with the equals() method 034 * hence it is advised not to use this in any implementations of sorted sets 035 * Instead use Collections.sort() to sort the collection of PasswordHistory objects. 036 * 037 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 038 * @version $Rev$, $Date$ 039 */ 040public class PasswordHistory implements Comparable<PasswordHistory> 041{ 042 /** time when password was last changed */ 043 private String time; 044 045 /** the syntax OID that is to be used on the password data */ 046 private String syntaxOID = SchemaConstants.OCTET_STRING_SYNTAX; 047 048 /** the length of the password data */ 049 private int length; 050 051 /** password octet string */ 052 private String data; 053 054 private static final char DELIMITER = '#'; 055 056 057 /** 058 * Create a new instance of PasswordHistory 059 * 060 * @param pwdHistoryVal The history date 061 */ 062 public PasswordHistory( String pwdHistoryVal ) 063 { 064 int pos = pwdHistoryVal.indexOf( DELIMITER ); 065 time = pwdHistoryVal.substring( 0, pos ); 066 067 pos++; 068 int nextPos = pwdHistoryVal.indexOf( DELIMITER, pos ); 069 syntaxOID = pwdHistoryVal.substring( pos, nextPos ); 070 071 nextPos++; 072 pos = pwdHistoryVal.indexOf( DELIMITER, nextPos ); 073 length = Integer.parseInt( pwdHistoryVal.substring( nextPos, pos ) ); 074 075 data = pwdHistoryVal.substring( pos + 1 ); 076 } 077 078 079 /** 080 * Create a new instance of PasswordHistory 081 * 082 * @param time The time we changed the password 083 * @param password The password to store 084 */ 085 public PasswordHistory( String time, byte[] password ) 086 { 087 this.time = time; 088 this.data = new String( Base64.getEncoder().encode( password ), StandardCharsets.UTF_8 ); 089 this.length = data.length(); 090 } 091 092 093 public byte[] getHistoryValue() 094 { 095 StringBuilder sb = new StringBuilder(); 096 097 sb.append( time ).append( DELIMITER ); 098 099 sb.append( syntaxOID ).append( DELIMITER ); 100 101 sb.append( length ).append( DELIMITER ); 102 103 sb.append( data ); 104 105 return Strings.getBytesUtf8( sb.toString() ); 106 } 107 108 109 public String getTime() 110 { 111 return time; 112 } 113 114 115 public String getSyntaxOID() 116 { 117 return syntaxOID; 118 } 119 120 121 public int getLength() 122 { 123 return length; 124 } 125 126 127 public byte[] getPassword() 128 { 129 return Base64.getDecoder().decode( data ); 130 } 131 132 133 /** 134 * {@inheritDoc} 135 */ 136 @Override 137 public int compareTo( PasswordHistory o ) 138 { 139 return o.getTime().compareTo( time ); 140 } 141 142 143 /** 144 * @see Object#toString() 145 */ 146 @Override 147 public boolean equals( Object o ) 148 { 149 if ( !( o instanceof PasswordHistory ) ) 150 { 151 return false; 152 } 153 154 PasswordHistory other = ( PasswordHistory ) o; 155 156 return getTime().equals( other.getTime() ) && data.equals( other.data ); 157 } 158 159 160 @Override 161 public int hashCode() 162 { 163 final int prime = 31; 164 int result = 1; 165 result = prime * result + ( ( data == null ) ? 0 : data.hashCode() ); 166 result = prime * result + length; 167 result = prime * result + ( ( syntaxOID == null ) ? 0 : syntaxOID.hashCode() ); 168 result = prime * result + ( ( time == null ) ? 0 : time.hashCode() ); 169 return result; 170 } 171 172 173 @Override 174 public String toString() 175 { 176 return "PasswordHistory [time=" + time + ", syntaxOID=" + syntaxOID + ", length=" + length + ", data=" + data 177 + "]"; 178 } 179}