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 010 * trunk/opends/resource/legal-notices/OpenDS.LICENSE 011 * or https://OpenDS.dev.java.net/OpenDS.LICENSE. 012 * See the License for the specific language governing permissions 013 * and limitations under the License. 014 * 015 * When distributing Covered Code, include this CDDL HEADER in each 016 * file and include the License file at 017 * trunk/opends/resource/legal-notices/OpenDS.LICENSE. If applicable, 018 * add the following below this CDDL HEADER, with the fields enclosed 019 * by brackets "[]" replaced with your own identifying information: 020 * Portions Copyright [yyyy] [name of copyright owner] 021 * 022 * CDDL HEADER END 023 * 024 * 025 * Copyright 2008 Sun Microsystems, Inc. 026 */ 027 package org.opends.server.extensions; 028 029 030 031 import java.util.Arrays; 032 033 import org.opends.messages.Message; 034 import org.opends.server.admin.std.server.RC4PasswordStorageSchemeCfg; 035 import org.opends.server.api.PasswordStorageScheme; 036 import org.opends.server.config.ConfigException; 037 import org.opends.server.core.DirectoryServer; 038 import org.opends.server.loggers.debug.DebugTracer; 039 import org.opends.server.types.*; 040 import org.opends.server.util.Base64; 041 042 import static org.opends.messages.ExtensionMessages.*; 043 import static org.opends.server.extensions.ExtensionsConstants.*; 044 import static org.opends.server.loggers.debug.DebugLogger.*; 045 import static org.opends.server.util.StaticUtils.*; 046 047 048 /** 049 * This class defines a Directory Server password storage scheme that will 050 * encode values using the RC4 reversible encryption algorithm. This 051 * implementation supports only the user password syntax and not the auth 052 * password syntax. 053 */ 054 public class RC4PasswordStorageScheme 055 extends PasswordStorageScheme<RC4PasswordStorageSchemeCfg> 056 { 057 /** 058 * The tracer object for the debug logger. 059 */ 060 private static final DebugTracer TRACER = getTracer(); 061 062 063 064 // The reference to the Directory Server crypto manager that we will use to 065 // handle the encryption/decryption. 066 private CryptoManager cryptoManager; 067 068 069 070 /** 071 * Creates a new instance of this password storage scheme. Note that no 072 * initialization should be performed here, as all initialization should be 073 * done in the {@code initializePasswordStorageScheme} method. 074 */ 075 public RC4PasswordStorageScheme() 076 { 077 super(); 078 } 079 080 081 082 /** 083 * {@inheritDoc} 084 */ 085 @Override() 086 public void initializePasswordStorageScheme( 087 RC4PasswordStorageSchemeCfg configuration) 088 throws ConfigException, InitializationException 089 { 090 cryptoManager = DirectoryServer.getCryptoManager(); 091 } 092 093 094 095 /** 096 * {@inheritDoc} 097 */ 098 @Override() 099 public String getStorageSchemeName() 100 { 101 return STORAGE_SCHEME_NAME_RC4; 102 } 103 104 105 106 /** 107 * {@inheritDoc} 108 */ 109 @Override() 110 public ByteString encodePassword(ByteString plaintext) 111 throws DirectoryException 112 { 113 try 114 { 115 byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_RC4, 116 KEY_SIZE_RC4, 117 plaintext.value()); 118 return ByteStringFactory.create(Base64.encode(encodedBytes)); 119 } 120 catch (Exception e) 121 { 122 if (debugEnabled()) 123 { 124 TRACER.debugCaught(DebugLogLevel.ERROR, e); 125 } 126 127 Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_RC4, 128 getExceptionMessage(e)); 129 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 130 m, e); 131 } 132 } 133 134 135 136 /** 137 * {@inheritDoc} 138 */ 139 @Override() 140 public ByteString encodePasswordWithScheme(ByteString plaintext) 141 throws DirectoryException 142 { 143 StringBuilder buffer = new StringBuilder(); 144 buffer.append('{'); 145 buffer.append(STORAGE_SCHEME_NAME_RC4); 146 buffer.append('}'); 147 148 try 149 { 150 byte[] encodedBytes = cryptoManager.encrypt(CIPHER_TRANSFORMATION_RC4, 151 KEY_SIZE_RC4, 152 plaintext.value()); 153 buffer.append(Base64.encode(encodedBytes)); 154 } 155 catch (Exception e) 156 { 157 if (debugEnabled()) 158 { 159 TRACER.debugCaught(DebugLogLevel.ERROR, e); 160 } 161 162 Message m = ERR_PWSCHEME_CANNOT_ENCRYPT.get(STORAGE_SCHEME_NAME_RC4, 163 getExceptionMessage(e)); 164 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 165 m, e); 166 } 167 168 return ByteStringFactory.create(buffer.toString()); 169 } 170 171 172 173 /** 174 * {@inheritDoc} 175 */ 176 @Override() 177 public boolean passwordMatches(ByteString plaintextPassword, 178 ByteString storedPassword) 179 { 180 try 181 { 182 byte[] decryptedPassword = 183 cryptoManager.decrypt(Base64.decode(storedPassword.stringValue())); 184 return Arrays.equals(plaintextPassword.value(), decryptedPassword); 185 } 186 catch (Exception e) 187 { 188 if (debugEnabled()) 189 { 190 TRACER.debugCaught(DebugLogLevel.ERROR, e); 191 } 192 193 return false; 194 } 195 } 196 197 198 199 /** 200 * {@inheritDoc} 201 */ 202 @Override() 203 public boolean isReversible() 204 { 205 return true; 206 } 207 208 209 210 /** 211 * {@inheritDoc} 212 */ 213 @Override() 214 public ByteString getPlaintextValue(ByteString storedPassword) 215 throws DirectoryException 216 { 217 try 218 { 219 byte[] decryptedPassword = 220 cryptoManager.decrypt(Base64.decode(storedPassword.stringValue())); 221 return ByteStringFactory.create(decryptedPassword); 222 } 223 catch (Exception e) 224 { 225 if (debugEnabled()) 226 { 227 TRACER.debugCaught(DebugLogLevel.ERROR, e); 228 } 229 230 Message m = ERR_PWSCHEME_CANNOT_DECRYPT.get(STORAGE_SCHEME_NAME_RC4, 231 getExceptionMessage(e)); 232 throw new DirectoryException(DirectoryServer.getServerErrorResultCode(), 233 m, e); 234 } 235 } 236 237 238 239 /** 240 * {@inheritDoc} 241 */ 242 @Override() 243 public boolean supportsAuthPasswordSyntax() 244 { 245 // This storage scheme does not support the authentication password syntax. 246 return false; 247 } 248 249 250 251 /** 252 * {@inheritDoc} 253 */ 254 @Override() 255 public ByteString encodeAuthPassword(ByteString plaintext) 256 throws DirectoryException 257 { 258 Message message = 259 ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName()); 260 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 261 } 262 263 264 265 /** 266 * {@inheritDoc} 267 */ 268 @Override() 269 public boolean authPasswordMatches(ByteString plaintextPassword, 270 String authInfo, String authValue) 271 { 272 // This storage scheme does not support the authentication password syntax. 273 return false; 274 } 275 276 277 278 /** 279 * {@inheritDoc} 280 */ 281 @Override() 282 public ByteString getAuthPasswordPlaintextValue(String authInfo, 283 String authValue) 284 throws DirectoryException 285 { 286 Message message = 287 ERR_PWSCHEME_DOES_NOT_SUPPORT_AUTH_PASSWORD.get(getStorageSchemeName()); 288 throw new DirectoryException(ResultCode.UNWILLING_TO_PERFORM, message); 289 } 290 291 292 293 /** 294 * {@inheritDoc} 295 */ 296 @Override() 297 public boolean isStorageSchemeSecure() 298 { 299 // This password storage scheme should be considered secure. 300 return true; 301 } 302 } 303