001/* 002 * Copyright 2017-2019 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2017-2019 Ping Identity Corporation 007 * 008 * This program is free software; you can redistribute it and/or modify 009 * it under the terms of the GNU General Public License (GPLv2 only) 010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 011 * as published by the Free Software Foundation. 012 * 013 * This program is distributed in the hope that it will be useful, 014 * but WITHOUT ANY WARRANTY; without even the implied warranty of 015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 016 * GNU General Public License for more details. 017 * 018 * You should have received a copy of the GNU General Public License 019 * along with this program; if not, see <http://www.gnu.org/licenses>. 020 */ 021package com.unboundid.ldap.listener; 022 023 024 025import java.util.List; 026 027import com.unboundid.asn1.ASN1OctetString; 028import com.unboundid.ldap.matchingrules.OctetStringMatchingRule; 029import com.unboundid.ldap.sdk.LDAPException; 030import com.unboundid.ldap.sdk.ReadOnlyEntry; 031import com.unboundid.util.ThreadSafety; 032import com.unboundid.util.ThreadSafetyLevel; 033 034 035 036/** 037 * This class provides a data structure that encapsulates a password used by the 038 * in-memory directory server. It may be optionally associated with an 039 * {@link InMemoryPasswordEncoder}. 040 */ 041@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 042public final class InMemoryDirectoryServerPassword 043{ 044 // The password as it is (or has the potential to be) stored in the in-memory 045 // directory server. 046 private final ASN1OctetString storedPassword; 047 048 // The password encoder that should be used when interacting with the stored 049 // password. 050 private final InMemoryPasswordEncoder passwordEncoder; 051 052 // The user entry with which the stored password is associated. 053 private final ReadOnlyEntry userEntry; 054 055 // The name of the attribute with which the stored password is associated. 056 private final String attributeName; 057 058 059 060 /** 061 * Creates a new in-memory directory server password with the provided 062 * information. 063 * 064 * @param storedPassword The password as it is (or has the potential to 065 * be) stored in the in-memory directory server. It 066 * must not be {@code null}. 067 * @param userEntry The user entry with which the stored password is 068 * associated. It must not be {@code nulL}. 069 * @param attributeName The name of the attribute with which the stored 070 * password is associated. It must not be 071 * {@code null}. 072 * @param passwordEncoders The set of password encoders configured for the 073 * in-memory directory server. It must not be 074 * {@code null} but may be empty. 075 */ 076 InMemoryDirectoryServerPassword(final ASN1OctetString storedPassword, 077 final ReadOnlyEntry userEntry, final String attributeName, 078 final List<InMemoryPasswordEncoder> passwordEncoders) 079 { 080 this.storedPassword = storedPassword; 081 this.userEntry = userEntry; 082 this.attributeName = attributeName; 083 084 InMemoryPasswordEncoder encoder = null; 085 for (final InMemoryPasswordEncoder e : passwordEncoders) 086 { 087 if (e.passwordStartsWithPrefix(storedPassword)) 088 { 089 encoder = e; 090 break; 091 } 092 } 093 094 passwordEncoder = encoder; 095 } 096 097 098 099 /** 100 * Retrieves the password as it is (or has the potential to be) stored in the 101 * in-memory directory server. If the {@link #isEncoded()} method returns 102 * {@code true}, then the stored password will be treated as an encoded 103 * password. Otherwise, it will be treated as a clear-text password with 104 * no encoding or output formatting. 105 * 106 * @return The password as it is (or has the potential to be) stored in the 107 * in-memory directory server. 108 */ 109 public ASN1OctetString getStoredPassword() 110 { 111 return storedPassword; 112 } 113 114 115 116 /** 117 * Retrieves the name of the attribute with which the stored password is 118 * associated. 119 * 120 * @return The name of the attribute with which the stored password is 121 * associated. 122 */ 123 public String getAttributeName() 124 { 125 return attributeName; 126 } 127 128 129 130 /** 131 * Indicates whether the stored password is encoded or in the clear. 132 * 133 * @return {@code true} if the stored password is encoded, or {@code false} 134 * if it is the clear. 135 */ 136 public boolean isEncoded() 137 { 138 return (passwordEncoder != null); 139 } 140 141 142 143 /** 144 * Retrieves the password encoder that should be used to interact with the 145 * stored password. 146 * 147 * @return The password encoder that should be used to interact with the 148 * stored password, or {@code null} if the password is not encoded. 149 */ 150 public InMemoryPasswordEncoder getPasswordEncoder() 151 { 152 return passwordEncoder; 153 } 154 155 156 157 /** 158 * Retrieves the clear-text representation of the stored password, if it 159 * is possible to obtain it. If the password is not encoded, then the stored 160 * password will be returned as-is. If the stored password is encoded, then 161 * the {@link InMemoryPasswordEncoder#extractClearPasswordFromEncodedPassword} 162 * method will be used in an attempt to 163 * 164 * @return The clear-text representation of the stored password. 165 * 166 * @throws LDAPException If the stored password is encoded using a mechanism 167 * that does not permit extracting the clear-text 168 * password. 169 */ 170 public ASN1OctetString getClearPassword() 171 throws LDAPException 172 { 173 if (passwordEncoder == null) 174 { 175 return storedPassword; 176 } 177 else 178 { 179 return passwordEncoder.extractClearPasswordFromEncodedPassword( 180 storedPassword, userEntry); 181 } 182 } 183 184 185 186 /** 187 * Indicates whether this password matches the provided clear-text password. 188 * 189 * @param clearPassword The clear-text password for which to make the 190 * determination. 191 * 192 * @return {@code true} if this password matches the provided clear-text 193 * password, or {@code false} if not. 194 * 195 * @throws LDAPException If a problem is encountered while trying to make 196 * the determination. 197 */ 198 public boolean matchesClearPassword(final ASN1OctetString clearPassword) 199 throws LDAPException 200 { 201 if (passwordEncoder == null) 202 { 203 return OctetStringMatchingRule.getInstance().valuesMatch(clearPassword, 204 storedPassword); 205 } 206 else 207 { 208 return passwordEncoder.clearPasswordMatchesEncodedPassword(clearPassword, 209 storedPassword, userEntry); 210 } 211 } 212}