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