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
028 package org.opends.server.crypto;
029
030 import org.opends.server.admin.std.server.
031 GetSymmetricKeyExtendedOperationHandlerCfg;
032 import org.opends.server.api.ExtendedOperationHandler;
033 import org.opends.server.loggers.debug.DebugTracer;
034 import org.opends.server.loggers.debug.DebugLogger;
035 import org.opends.server.types.*;
036 import org.opends.server.config.ConfigException;
037 import org.opends.server.core.DirectoryServer;
038 import org.opends.server.core.ExtendedOperation;
039 import org.opends.server.protocols.asn1.ASN1Sequence;
040 import org.opends.server.protocols.asn1.ASN1Element;
041 import org.opends.server.protocols.asn1.ASN1Exception;
042 import org.opends.server.protocols.asn1.ASN1OctetString;
043 import org.opends.server.util.StaticUtils;
044 import org.opends.server.util.ServerConstants;
045 import org.opends.messages.Message;
046 import static org.opends.messages.ExtensionMessages.*;
047
048 import java.util.Set;
049 import java.util.HashSet;
050 import java.util.ArrayList;
051
052 /**
053 * This class implements the get symmetric key extended operation, an OpenDS
054 * proprietary extension used for distribution of symmetric keys amongst
055 * servers.
056 */
057 public class GetSymmetricKeyExtendedOperation
058 extends ExtendedOperationHandler<
059 GetSymmetricKeyExtendedOperationHandlerCfg>
060 {
061 /**
062 * The tracer object for the debug logger.
063 */
064 private static final DebugTracer TRACER = DebugLogger.getTracer();
065
066
067
068 /**
069 * The BER type value for the symmetric key element of the operation value.
070 */
071 public static final byte TYPE_SYMMETRIC_KEY_ELEMENT = (byte) 0x80;
072
073
074
075 /**
076 * The BER type value for the instance key ID element of the operation value.
077 */
078 public static final byte TYPE_INSTANCE_KEY_ID_ELEMENT = (byte) 0x81;
079
080
081
082 // The default set of supported control OIDs for this extended operation.
083 private Set<String> supportedControlOIDs = new HashSet<String>(0);
084
085
086
087 /**
088 * Create an instance of this symmetric key extended operation. All
089 * initialization should be performed in the
090 * <CODE>initializeExtendedOperationHandler</CODE> method.
091 */
092 public GetSymmetricKeyExtendedOperation()
093 {
094 super();
095
096 }
097
098
099
100
101 /**
102 * {@inheritDoc}
103 */
104 public void initializeExtendedOperationHandler(
105 GetSymmetricKeyExtendedOperationHandlerCfg config)
106 throws ConfigException, InitializationException
107 {
108 supportedControlOIDs = new HashSet<String>();
109
110
111 DirectoryServer.registerSupportedExtension(
112 ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP, this);
113
114 registerControlsAndFeatures();
115 }
116
117
118
119 /**
120 * Performs any finalization that may be necessary for this extended
121 * operation handler. By default, no finalization is performed.
122 */
123 public void finalizeExtendedOperationHandler()
124 {
125 DirectoryServer.deregisterSupportedExtension(
126 ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP);
127
128 deregisterControlsAndFeatures();
129 }
130
131
132
133 /**
134 * {@inheritDoc}
135 */
136 @Override()
137 public Set<String> getSupportedControls()
138 {
139 return supportedControlOIDs;
140 }
141
142
143
144 /**
145 * Processes the provided extended operation.
146 *
147 * @param operation The extended operation to be processed.
148 */
149 public void processExtendedOperation(ExtendedOperation operation)
150 {
151 // Initialize the variables associated with components that may be included
152 // in the request.
153 String requestSymmetricKey = null;
154 String instanceKeyID = null;
155
156
157
158 // Parse the encoded request, if there is one.
159 ByteString requestValue = operation.getRequestValue();
160 if (requestValue == null)
161 {
162 // The request must always have a value.
163 Message message = ERR_GET_SYMMETRIC_KEY_NO_VALUE.get();
164 operation.appendErrorMessage(message);
165 return;
166 }
167
168 try
169 {
170 ASN1Sequence valueSequence =
171 ASN1Sequence.decodeAsSequence(requestValue.value());
172 for (ASN1Element e : valueSequence.elements())
173 {
174 switch (e.getType())
175 {
176 case TYPE_SYMMETRIC_KEY_ELEMENT:
177 requestSymmetricKey =
178 ASN1OctetString.decodeAsOctetString(e).stringValue();
179 break;
180
181 case TYPE_INSTANCE_KEY_ID_ELEMENT:
182 instanceKeyID =
183 ASN1OctetString.decodeAsOctetString(e).stringValue();
184 break;
185
186 default:
187 Message message = ERR_GET_SYMMETRIC_KEY_INVALID_TYPE.get(
188 StaticUtils.byteToHex(e.getType()));
189 operation.appendErrorMessage(message);
190 return;
191 }
192 }
193 }
194 catch (ASN1Exception ae)
195 {
196 if (DebugLogger.debugEnabled())
197 {
198 TRACER.debugCaught(DebugLogLevel.ERROR, ae);
199 }
200
201 Message message = ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION.get(
202 ae.getMessage());
203 operation.appendErrorMessage(message);
204 return;
205 }
206 catch (Exception e)
207 {
208 if (DebugLogger.debugEnabled())
209 {
210 TRACER.debugCaught(DebugLogLevel.ERROR, e);
211 }
212
213 operation.setResultCode(ResultCode.PROTOCOL_ERROR);
214
215 Message message = ERR_GET_SYMMETRIC_KEY_DECODE_EXCEPTION.get(
216 StaticUtils.getExceptionMessage(e));
217 operation.appendErrorMessage(message);
218 return;
219 }
220
221 CryptoManagerImpl cm = DirectoryServer.getCryptoManager();
222 try
223 {
224 String responseSymmetricKey = cm.reencodeSymmetricKeyAttribute(
225 requestSymmetricKey, instanceKeyID);
226
227 operation.setResponseOID(
228 ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP);
229 operation.setResponseValue(new ASN1OctetString(responseSymmetricKey));
230 operation.setResultCode(ResultCode.SUCCESS);
231 }
232 catch (CryptoManagerException e)
233 {
234 operation.setResultCode(DirectoryServer.getServerErrorResultCode());
235 operation.appendErrorMessage(e.getMessageObject());
236 }
237 catch (Exception e)
238 {
239 operation.setResultCode(DirectoryServer.getServerErrorResultCode());
240 operation.appendErrorMessage(StaticUtils.getExceptionMessage(e));
241 }
242 }
243
244 /**
245 * Encodes the provided information into an ASN.1 octet string suitable for
246 * use as the value for this extended operation.
247 *
248 * @param symmetricKey The wrapped key to use for this request control.
249 * @param instanceKeyID The requesting server instance key ID to use for
250 * this request control.
251 *
252 * @return An ASN.1 octet string containing the encoded request value.
253 */
254 public static ASN1OctetString encodeRequestValue(
255 String symmetricKey,
256 String instanceKeyID)
257 {
258 ArrayList<ASN1Element> elements = new ArrayList<ASN1Element>(2);
259
260 ASN1OctetString symmetricKeyElement =
261 new ASN1OctetString(TYPE_SYMMETRIC_KEY_ELEMENT, symmetricKey);
262 elements.add(symmetricKeyElement);
263
264 ASN1OctetString instanceKeyIDElement =
265 new ASN1OctetString(TYPE_INSTANCE_KEY_ID_ELEMENT,
266 instanceKeyID);
267 elements.add(instanceKeyIDElement);
268
269 ASN1Sequence valueSequence = new ASN1Sequence(elements);
270 return new ASN1OctetString(valueSequence.encode());
271 }
272
273
274 }