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 029 030 031import org.forgerock.i18n.LocalizableMessage; 032import org.opends.server.admin.std.server.Base64PasswordStorageSchemeCfg; 033import org.opends.server.api.PasswordStorageScheme; 034import org.forgerock.opendj.config.server.ConfigException; 035import org.forgerock.i18n.slf4j.LocalizedLogger; 036import org.opends.server.types.*; 037import org.forgerock.opendj.ldap.ResultCode; 038import org.forgerock.opendj.ldap.ByteString; 039import org.forgerock.opendj.ldap.ByteSequence; 040import org.opends.server.util.Base64; 041 042import static org.opends.messages.ExtensionMessages.*; 043import static org.opends.server.extensions.ExtensionsConstants.*; 044 045 046 047/** 048 * This class defines a Directory Server password storage scheme that will store 049 * the values in base64-encoded form. This is a reversible algorithm that 050 * offers very little actual protection -- it will merely obscure the plaintext 051 * value from the casual observer. 052 */ 053public class Base64PasswordStorageScheme 054 extends PasswordStorageScheme<Base64PasswordStorageSchemeCfg> 055{ 056 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 057 058 059 060 /** 061 * Creates a new instance of this password storage scheme. Note that no 062 * initialization should be performed here, as all initialization should be 063 * done in the <CODE>initializePasswordStorageScheme</CODE> method. 064 */ 065 public Base64PasswordStorageScheme() 066 { 067 super(); 068 } 069 070 071 072 /** {@inheritDoc} */ 073 @Override 074 public void initializePasswordStorageScheme( 075 Base64PasswordStorageSchemeCfg configuration) 076 throws ConfigException, InitializationException 077 { 078 // No initialization is required. 079 } 080 081 082 083 /** {@inheritDoc} */ 084 @Override 085 public String getStorageSchemeName() 086 { 087 return STORAGE_SCHEME_NAME_BASE64; 088 } 089 090 091 092 /** {@inheritDoc} */ 093 @Override 094 public ByteString encodePassword(ByteSequence plaintext) 095 throws DirectoryException 096 { 097 return ByteString.valueOfUtf8(Base64.encode(plaintext)); 098 } 099 100 101 102 /** {@inheritDoc} */ 103 @Override 104 public ByteString encodePasswordWithScheme(ByteSequence plaintext) 105 throws DirectoryException 106 { 107 StringBuilder buffer = new StringBuilder(); 108 buffer.append('{'); 109 buffer.append(STORAGE_SCHEME_NAME_BASE64); 110 buffer.append('}'); 111 buffer.append(Base64.encode(plaintext)); 112 113 return ByteString.valueOfUtf8(buffer); 114 } 115 116 117 118 /** {@inheritDoc} */ 119 @Override 120 public boolean passwordMatches(ByteSequence plaintextPassword, 121 ByteSequence storedPassword) 122 { 123 String userString = Base64.encode(plaintextPassword); 124 String storedString = storedPassword.toString(); 125 return userString.equals(storedString); 126 } 127 128 129 130 /** {@inheritDoc} */ 131 @Override 132 public boolean isReversible() 133 { 134 return true; 135 } 136 137 138 139 /** {@inheritDoc} */ 140 @Override 141 public ByteString getPlaintextValue(ByteSequence storedPassword) 142 throws DirectoryException 143 { 144 try 145 { 146 return ByteString.wrap(Base64.decode(storedPassword.toString())); 147 } 148 catch (Exception e) 149 { 150 logger.traceException(e); 151 152 LocalizableMessage message = ERR_PWSCHEME_CANNOT_BASE64_DECODE_STORED_PASSWORD.get( 153 storedPassword, e); 154 throw new DirectoryException(ResultCode.INVALID_CREDENTIALS, message, e); 155 } 156 } 157 158 159 160 /** {@inheritDoc} */ 161 @Override 162 public boolean supportsAuthPasswordSyntax() 163 { 164 // This storage scheme does not support the authentication password syntax. 165 return false; 166 } 167 168 169 170 /** {@inheritDoc} */ 171 @Override 172 public ByteString encodeAuthPassword(ByteSequence plaintext) 173 throws DirectoryException 174 { 175 LocalizableMessage message = 176 ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName()); 177 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 178 } 179 180 181 182 /** {@inheritDoc} */ 183 @Override 184 public boolean authPasswordMatches(ByteSequence plaintextPassword, 185 String authInfo, String authValue) 186 { 187 // This storage scheme does not support the authentication password syntax. 188 return false; 189 } 190 191 192 193 /** {@inheritDoc} */ 194 @Override 195 public ByteString getAuthPasswordPlaintextValue(String authInfo, 196 String authValue) 197 throws DirectoryException 198 { 199 LocalizableMessage message = 200 ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName()); 201 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 202 } 203 204 205 206 /** {@inheritDoc} */ 207 @Override 208 public boolean isStorageSchemeSecure() 209 { 210 // Base64-encoded values may be easily decoded with no key or special 211 // knowledge. 212 return false; 213 } 214} 215