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 * docs/licenses/cddl.txt
011 * or http://www.opensource.org/licenses/cddl1.php.
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 * docs/licenses/cddl.txt. 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 2011-2014 UnboundID Corp.
026 */
027 package com.unboundid.directory.sdk.ds.api;
028
029
030
031 import java.io.InputStream;
032 import java.io.OutputStream;
033 import java.util.Collections;
034 import java.util.List;
035 import java.util.Map;
036 import javax.crypto.CipherInputStream;
037 import javax.crypto.CipherOutputStream;
038
039 import com.unboundid.directory.sdk.broker.internal.IdentityBrokerExtension;
040 import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
041 import com.unboundid.directory.sdk.common.internal.Reconfigurable;
042 import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
043 import com.unboundid.directory.sdk.ds.config.CipherStreamProviderConfig;
044 import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
045 import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
046 import com.unboundid.ldap.sdk.LDAPException;
047 import com.unboundid.ldap.sdk.ResultCode;
048 import com.unboundid.util.Extensible;
049 import com.unboundid.util.ThreadSafety;
050 import com.unboundid.util.ThreadSafetyLevel;
051 import com.unboundid.util.args.ArgumentException;
052 import com.unboundid.util.args.ArgumentParser;
053
054
055
056 /**
057 * This class defines an API that must be implemented by extensions which
058 * provide access to cipher input streams and cipher output streams to be used
059 * by the server in order to read and write encrypted data.
060 * <BR>
061 * <H2>Configuring Cipher Stream Providers</H2>
062 * In order to configure a cipher stream provider created using this API, use a
063 * command like:
064 * <PRE>
065 * dsconfig create-cipher-stream-provider \
066 * --provider-name "<I>{provider-name}</I>" \
067 * --type third-party \
068 * --set enabled:true \
069 * --set "extension-class:<I>{class-name}</I>" \
070 * --set "extension-argument:<I>{name=value}</I>"
071 * </PRE>
072 * where "<I>{provider-name}</I>" is the name to use for the cipher stream
073 * provider instance, "<I>{class-name}</I>" is the fully-qualified name of the
074 * Java class that extends
075 * {@code com.unboundid.directory.sdk.ds.api.CipherStreamProvider},
076 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to
077 * provide to the cipher stream provider. If multiple arguments should be
078 * provided to the cipher stream provider, then the
079 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
080 * provided multiple times.
081 */
082 @Extensible()
083 @DirectoryServerExtension()
084 @IdentityBrokerExtension()
085 @ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
086 public abstract class CipherStreamProvider
087 implements UnboundIDExtension,
088 Reconfigurable<CipherStreamProviderConfig>,
089 ExampleUsageProvider
090 {
091 /**
092 * Creates a new instance of this cipher stream provider. All cipher stream
093 * provider implementations must include a default constructor, but any
094 * initialization should generally be done in the
095 * {@code initializeCipherStreamProvider} method.
096 */
097 public CipherStreamProvider()
098 {
099 // No implementation is required.
100 }
101
102
103
104 /**
105 * {@inheritDoc}
106 */
107 public abstract String getExtensionName();
108
109
110
111 /**
112 * {@inheritDoc}
113 */
114 public abstract String[] getExtensionDescription();
115
116
117
118 /**
119 * {@inheritDoc}
120 */
121 public void defineConfigArguments(final ArgumentParser parser)
122 throws ArgumentException
123 {
124 // No arguments will be allowed by default.
125 }
126
127
128
129 /**
130 * Initializes this cipher stream provider.
131 *
132 * @param serverContext A handle to the server context for the server in
133 * which this extension is running.
134 * @param config The general configuration for this cipher stream
135 * provider.
136 * @param parser The argument parser which has been initialized from
137 * the configuration for this cipher stream provider.
138 *
139 * @throws LDAPException If a problem occurs while initializing this cipher
140 * stream provider.
141 */
142 public void initializeCipherStreamProvider(
143 final DirectoryServerContext serverContext,
144 final CipherStreamProviderConfig config,
145 final ArgumentParser parser)
146 throws LDAPException
147 {
148 // No initialization will be performed by default.
149 }
150
151
152
153 /**
154 * {@inheritDoc}
155 */
156 public boolean isConfigurationAcceptable(
157 final CipherStreamProviderConfig config,
158 final ArgumentParser parser,
159 final List<String> unacceptableReasons)
160 {
161 // No extended validation will be performed by default.
162 return true;
163 }
164
165
166
167 /**
168 * {@inheritDoc}
169 */
170 public ResultCode applyConfiguration(final CipherStreamProviderConfig config,
171 final ArgumentParser parser,
172 final List<String> adminActionsRequired,
173 final List<String> messages)
174 {
175 // By default, no configuration changes will be applied. If there are any
176 // arguments, then add an admin action message indicating that the extension
177 // needs to be restarted for any changes to take effect.
178 if (! parser.getNamedArguments().isEmpty())
179 {
180 adminActionsRequired.add(
181 "No configuration change has actually been applied. The new " +
182 "configuration will not take effect until this cipher stream " +
183 "provider is disabled and re-enabled or until the server is " +
184 "restarted.");
185 }
186
187 return ResultCode.SUCCESS;
188 }
189
190
191
192 /**
193 * Performs any cleanup which may be necessary when this cipher stream
194 * provider is to be taken out of service.
195 */
196 public void finalizeCipherStreamProvider()
197 {
198 // No implementation is required.
199 }
200
201
202
203 /**
204 * Wraps the provided input stream in a cipher input stream that can be used
205 * to decrypt data read from the given stream.
206 *
207 * @param source The input stream to be wrapped with a cipher input stream.
208 *
209 * @return The cipher input stream which wraps the provided input stream.
210 *
211 * @throws LDAPException If a problem occurs while creating the cipher input
212 * stream.
213 */
214 public abstract CipherInputStream createCipherInputStream(
215 final InputStream source)
216 throws LDAPException;
217
218
219
220 /**
221 * Wraps the provided output stream in a cipher output stream that can be used
222 * to encrypt data written to the given stream.
223 *
224 * @param target The output stream to be wrapped with a cipher output
225 * stream.
226 *
227 * @return The cipher output stream which wraps the provided output stream.
228 *
229 * @throws LDAPException If a problem occurs while creating the cipher
230 * output stream.
231 */
232 public abstract CipherOutputStream createCipherOutputStream(
233 final OutputStream target)
234 throws LDAPException;
235
236
237
238 /**
239 * {@inheritDoc}
240 */
241 public Map<List<String>,String> getExamplesArgumentSets()
242 {
243 return Collections.emptyMap();
244 }
245 }