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 2008-2009 Sun Microsystems, Inc. 025 * Portions Copyright 2013-2015 ForgeRock AS 026 */ 027package org.opends.server.crypto; 028 029import java.io.IOException; 030 031import org.forgerock.i18n.LocalizableMessage; 032import org.opends.server.admin.std.server. 033GetSymmetricKeyExtendedOperationHandlerCfg; 034import org.opends.server.api.ExtendedOperationHandler; 035import org.forgerock.opendj.config.server.ConfigException; 036import org.opends.server.core.DirectoryServer; 037import org.opends.server.core.ExtendedOperation; 038import org.forgerock.i18n.slf4j.LocalizedLogger; 039import org.forgerock.opendj.io.ASN1; 040import org.forgerock.opendj.ldap.DecodeException; 041import org.forgerock.opendj.io.ASN1Reader; 042import org.forgerock.opendj.io.ASN1Writer; 043import org.opends.server.types.*; 044import org.forgerock.opendj.ldap.ResultCode; 045import org.forgerock.opendj.ldap.ByteString; 046import org.forgerock.opendj.ldap.ByteStringBuilder; 047import org.opends.server.util.ServerConstants; 048import org.opends.server.util.StaticUtils; 049 050import static org.opends.messages.ExtensionMessages.*; 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 */ 057public class GetSymmetricKeyExtendedOperation 058 extends ExtendedOperationHandler< 059 GetSymmetricKeyExtendedOperationHandlerCfg> 060{ 061 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 062 063 /** 064 * The BER type value for the symmetric key element of the operation value. 065 */ 066 public static final byte TYPE_SYMMETRIC_KEY_ELEMENT = (byte) 0x80; 067 068 /** 069 * The BER type value for the instance key ID element of the operation value. 070 */ 071 public static final byte TYPE_INSTANCE_KEY_ID_ELEMENT = (byte) 0x81; 072 073 /** 074 * Create an instance of this symmetric key extended operation. All 075 * initialization should be performed in the 076 * <CODE>initializeExtendedOperationHandler</CODE> method. 077 */ 078 public GetSymmetricKeyExtendedOperation() 079 { 080 super(); 081 } 082 083 /** {@inheritDoc} */ 084 @Override 085 public void initializeExtendedOperationHandler( 086 GetSymmetricKeyExtendedOperationHandlerCfg config) 087 throws ConfigException, InitializationException 088 { 089 super.initializeExtendedOperationHandler(config); 090 } 091 092 /** 093 * Processes the provided extended operation. 094 * 095 * @param operation The extended operation to be processed. 096 */ 097 @Override 098 public void processExtendedOperation(ExtendedOperation operation) 099 { 100 // Initialize the variables associated with components that may be included 101 // in the request. 102 String requestSymmetricKey = null; 103 String instanceKeyID = null; 104 105 106 107 // Parse the encoded request, if there is one. 108 ByteString requestValue = operation.getRequestValue(); 109 if (requestValue == null) 110 { 111 // The request must always have a value. 112 LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_NO_VALUE.get(); 113 operation.appendErrorMessage(message); 114 return; 115 } 116 117 try 118 { 119 ASN1Reader reader = ASN1.getReader(requestValue); 120 reader.readStartSequence(); 121 if(reader.hasNextElement() && 122 reader.peekType() == TYPE_SYMMETRIC_KEY_ELEMENT) 123 { 124 requestSymmetricKey = reader.readOctetStringAsString(); 125 } 126 if(reader.hasNextElement() && 127 reader.peekType() == TYPE_INSTANCE_KEY_ID_ELEMENT) 128 { 129 instanceKeyID = reader.readOctetStringAsString(); 130 } 131 reader.readEndSequence(); 132 } 133 catch (DecodeException e) 134 { 135 logger.traceException(e); 136 operation.appendErrorMessage(ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION.get(e.getMessage())); 137 return; 138 } 139 catch (Exception e) 140 { 141 logger.traceException(e); 142 143 operation.setResultCode(ResultCode.PROTOCOL_ERROR); 144 145 LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_DECODE_EXCEPTION.get( 146 StaticUtils.getExceptionMessage(e)); 147 operation.appendErrorMessage(message); 148 return; 149 } 150 151 CryptoManagerImpl cm = DirectoryServer.getCryptoManager(); 152 try 153 { 154 String responseSymmetricKey = cm.reencodeSymmetricKeyAttribute( 155 requestSymmetricKey, instanceKeyID); 156 157 operation.setResponseOID( 158 ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP); 159 operation.setResponseValue(ByteString.valueOfUtf8(responseSymmetricKey)); 160 operation.setResultCode(ResultCode.SUCCESS); 161 } 162 catch (CryptoManagerException e) 163 { 164 operation.setResultCode(DirectoryServer.getServerErrorResultCode()); 165 operation.appendErrorMessage(e.getMessageObject()); 166 } 167 catch (Exception e) 168 { 169 operation.setResultCode(DirectoryServer.getServerErrorResultCode()); 170 operation.appendErrorMessage(StaticUtils.getExceptionMessage(e)); 171 } 172 } 173 174 /** 175 * Encodes the provided information into an ASN.1 octet string suitable for 176 * use as the value for this extended operation. 177 * 178 * @param symmetricKey The wrapped key to use for this request control. 179 * @param instanceKeyID The requesting server instance key ID to use for 180 * this request control. 181 * 182 * @return An ASN.1 octet string containing the encoded request value. 183 */ 184 public static ByteString encodeRequestValue( 185 String symmetricKey, 186 String instanceKeyID) 187 { 188 ByteStringBuilder builder = new ByteStringBuilder(); 189 ASN1Writer writer = ASN1.getWriter(builder); 190 191 try 192 { 193 writer.writeStartSequence(); 194 writer.writeOctetString(TYPE_SYMMETRIC_KEY_ELEMENT, symmetricKey); 195 writer.writeOctetString(TYPE_INSTANCE_KEY_ID_ELEMENT, instanceKeyID); 196 writer.writeEndSequence(); 197 } 198 catch (IOException e) 199 { 200 // TODO: DO something 201 } 202 203 return builder.toByteString(); 204 } 205 206 /** {@inheritDoc} */ 207 @Override 208 public String getExtendedOperationOID() 209 { 210 return ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP; 211 } 212 213 /** {@inheritDoc} */ 214 @Override 215 public String getExtendedOperationName() 216 { 217 return "Get Symmetric Key"; 218 } 219}