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 }