001/* 002 * The contents of this file are subject to the terms of the Common Development and 003 * Distribution License (the License). You may not use this file except in compliance with the 004 * License. 005 * 006 * You can obtain a copy of the License at legal/CDDLv1.0.txt. See the License for the 007 * specific language governing permission and limitations under the License. 008 * 009 * When distributing Covered Software, include this CDDL Header Notice in each file and include 010 * the License file at legal/CDDLv1.0.txt. If applicable, add the following below the CDDL 011 * Header, with the fields enclosed by brackets [] replaced by your own identifying 012 * information: "Portions Copyright [year] [name of copyright owner]". 013 * 014 * Copyright 2008-2009 Sun Microsystems, Inc. 015 * Portions Copyright 2013-2016 ForgeRock AS. 016 */ 017package org.opends.server.crypto; 018 019import java.io.IOException; 020 021import org.forgerock.i18n.LocalizableMessage; 022import org.forgerock.opendj.server.config.server. 023GetSymmetricKeyExtendedOperationHandlerCfg; 024import org.opends.server.api.ExtendedOperationHandler; 025import org.forgerock.opendj.config.server.ConfigException; 026import org.opends.server.core.DirectoryServer; 027import org.opends.server.core.ExtendedOperation; 028import org.forgerock.i18n.slf4j.LocalizedLogger; 029import org.forgerock.opendj.io.ASN1; 030import org.forgerock.opendj.ldap.DecodeException; 031import org.forgerock.opendj.io.ASN1Reader; 032import org.forgerock.opendj.io.ASN1Writer; 033import org.opends.server.types.*; 034import org.forgerock.opendj.ldap.ResultCode; 035import org.forgerock.opendj.ldap.ByteString; 036import org.forgerock.opendj.ldap.ByteStringBuilder; 037import org.opends.server.util.ServerConstants; 038import org.opends.server.util.StaticUtils; 039 040import static org.opends.messages.ExtensionMessages.*; 041 042/** 043 * This class implements the get symmetric key extended operation, an OpenDS 044 * proprietary extension used for distribution of symmetric keys amongst 045 * servers. 046 */ 047public class GetSymmetricKeyExtendedOperation 048 extends ExtendedOperationHandler< 049 GetSymmetricKeyExtendedOperationHandlerCfg> 050{ 051 private static final LocalizedLogger logger = LocalizedLogger.getLoggerForThisClass(); 052 053 /** 054 * The BER type value for the symmetric key element of the operation value. 055 */ 056 public static final byte TYPE_SYMMETRIC_KEY_ELEMENT = (byte) 0x80; 057 058 /** 059 * The BER type value for the instance key ID element of the operation value. 060 */ 061 public static final byte TYPE_INSTANCE_KEY_ID_ELEMENT = (byte) 0x81; 062 063 /** 064 * Create an instance of this symmetric key extended operation. All 065 * initialization should be performed in the 066 * <CODE>initializeExtendedOperationHandler</CODE> method. 067 */ 068 public GetSymmetricKeyExtendedOperation() 069 { 070 super(); 071 } 072 073 /** {@inheritDoc} */ 074 @Override 075 public void initializeExtendedOperationHandler( 076 GetSymmetricKeyExtendedOperationHandlerCfg config) 077 throws ConfigException, InitializationException 078 { 079 super.initializeExtendedOperationHandler(config); 080 } 081 082 /** 083 * Processes the provided extended operation. 084 * 085 * @param operation The extended operation to be processed. 086 */ 087 @Override 088 public void processExtendedOperation(ExtendedOperation operation) 089 { 090 // Initialize the variables associated with components that may be included 091 // in the request. 092 String requestSymmetricKey = null; 093 String instanceKeyID = null; 094 095 096 097 // Parse the encoded request, if there is one. 098 ByteString requestValue = operation.getRequestValue(); 099 if (requestValue == null) 100 { 101 // The request must always have a value. 102 LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_NO_VALUE.get(); 103 operation.appendErrorMessage(message); 104 return; 105 } 106 107 try 108 { 109 ASN1Reader reader = ASN1.getReader(requestValue); 110 reader.readStartSequence(); 111 if(reader.hasNextElement() && 112 reader.peekType() == TYPE_SYMMETRIC_KEY_ELEMENT) 113 { 114 requestSymmetricKey = reader.readOctetStringAsString(); 115 } 116 if(reader.hasNextElement() && 117 reader.peekType() == TYPE_INSTANCE_KEY_ID_ELEMENT) 118 { 119 instanceKeyID = reader.readOctetStringAsString(); 120 } 121 reader.readEndSequence(); 122 } 123 catch (DecodeException e) 124 { 125 logger.traceException(e); 126 operation.appendErrorMessage(ERR_GET_SYMMETRIC_KEY_ASN1_DECODE_EXCEPTION.get(e.getMessage())); 127 return; 128 } 129 catch (Exception e) 130 { 131 logger.traceException(e); 132 133 operation.setResultCode(ResultCode.PROTOCOL_ERROR); 134 135 LocalizableMessage message = ERR_GET_SYMMETRIC_KEY_DECODE_EXCEPTION.get( 136 StaticUtils.getExceptionMessage(e)); 137 operation.appendErrorMessage(message); 138 return; 139 } 140 141 CryptoManagerImpl cm = DirectoryServer.getCryptoManager(); 142 try 143 { 144 String responseSymmetricKey = cm.reencodeSymmetricKeyAttribute( 145 requestSymmetricKey, instanceKeyID); 146 147 operation.setResponseOID( 148 ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP); 149 operation.setResponseValue(ByteString.valueOfUtf8(responseSymmetricKey)); 150 operation.setResultCode(ResultCode.SUCCESS); 151 } 152 catch (CryptoManagerException e) 153 { 154 operation.setResultCode(DirectoryServer.getServerErrorResultCode()); 155 operation.appendErrorMessage(e.getMessageObject()); 156 } 157 catch (Exception e) 158 { 159 operation.setResultCode(DirectoryServer.getServerErrorResultCode()); 160 operation.appendErrorMessage(StaticUtils.getExceptionMessage(e)); 161 } 162 } 163 164 /** 165 * Encodes the provided information into an ASN.1 octet string suitable for 166 * use as the value for this extended operation. 167 * 168 * @param symmetricKey The wrapped key to use for this request control. 169 * @param instanceKeyID The requesting server instance key ID to use for 170 * this request control. 171 * 172 * @return An ASN.1 octet string containing the encoded request value. 173 */ 174 public static ByteString encodeRequestValue( 175 String symmetricKey, 176 String instanceKeyID) 177 { 178 ByteStringBuilder builder = new ByteStringBuilder(); 179 ASN1Writer writer = ASN1.getWriter(builder); 180 181 try 182 { 183 writer.writeStartSequence(); 184 writer.writeOctetString(TYPE_SYMMETRIC_KEY_ELEMENT, symmetricKey); 185 writer.writeOctetString(TYPE_INSTANCE_KEY_ID_ELEMENT, instanceKeyID); 186 writer.writeEndSequence(); 187 } 188 catch (IOException e) 189 { 190 // TODO: DO something 191 } 192 193 return builder.toByteString(); 194 } 195 196 /** {@inheritDoc} */ 197 @Override 198 public String getExtendedOperationOID() 199 { 200 return ServerConstants.OID_GET_SYMMETRIC_KEY_EXTENDED_OP; 201 } 202 203 /** {@inheritDoc} */ 204 @Override 205 public String getExtendedOperationName() 206 { 207 return "Get Symmetric Key"; 208 } 209}