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 2012-2015 UnboundID Corp.
026 */
027package com.unboundid.directory.sdk.ds.api;
028
029
030
031import java.util.Collections;
032import java.util.List;
033import java.util.Map;
034
035import com.unboundid.directory.sdk.common.internal.ExampleUsageProvider;
036import com.unboundid.directory.sdk.common.internal.Reconfigurable;
037import com.unboundid.directory.sdk.common.internal.UnboundIDExtension;
038import com.unboundid.directory.sdk.common.operation.SASLBindRequest;
039import com.unboundid.directory.sdk.common.types.OperationContext;
040import com.unboundid.directory.sdk.ds.config.SASLMechanismHandlerConfig;
041import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension;
042import com.unboundid.directory.sdk.ds.types.DirectoryServerContext;
043import com.unboundid.directory.sdk.ds.types.SASLBindResult;
044import com.unboundid.directory.sdk.ds.types.SASLBindResultFactory;
045import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension;
046import com.unboundid.directory.sdk.sync.internal.SynchronizationServerExtension;
047import com.unboundid.ldap.sdk.LDAPException;
048import com.unboundid.ldap.sdk.ResultCode;
049import com.unboundid.util.Extensible;
050import com.unboundid.util.ThreadSafety;
051import com.unboundid.util.ThreadSafetyLevel;
052import com.unboundid.util.args.ArgumentException;
053import com.unboundid.util.args.ArgumentParser;
054
055
056
057/**
058 * This class defines an API that must be implemented by extensions which add
059 * support for custom SASL mechanisms to the server, which can provide support
060 * for custom authentication (and optionally, authorization) methods.
061 * <BR>
062 * <H2>Configuring SASL Mechanism Handlers</H2>
063 * In order to configure a SASL mechanism handler created using this API, use a
064 * command like:
065 * <PRE>
066 *      dsconfig create-sasl-mechanism-handler \
067 *           --handler-name "<I>{handler-name}</I>" \
068 *           --type third-party \
069 *           --set enabled:true \
070 *           --set "extension-class:<I>{class-name}</I>" \
071 *           --set "extension-argument:<I>{name=value}</I>"
072 * </PRE>
073 * where "<I>{handler-name}</I>" is the name to use for the SASL mechanism
074 * handler instance, "<I>{class-name}</I>" is the fully-qualified name of the
075 * Java class that extends
076 * {@code com.unboundid.directory.sdk.ds.api.SASLMechanismHandler}, and
077 * "<I>{name=value}</I>" represents name-value pairs for any arguments to
078 * provide to the handler.  If multiple arguments should be provided to the SASL
079 * mechanism handler, then the
080 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be
081 * provided multiple times.
082 */
083@Extensible()
084@DirectoryServerExtension()
085@DirectoryProxyServerExtension(appliesToLocalContent=true,
086     appliesToRemoteContent=true,
087     notes="Any SASL bind requests received by the Directory Proxy Server " +
088          "will be processed by the Directory Proxy Server itself rather " +
089          "than being forwarded to backend servers.  However, a SASL " +
090          "mechanism handler running in the Directory Proxy Server may " +
091          "perform internal operations which reference content in the " +
092          "backend servers as if it was contained locally in the server.")
093@SynchronizationServerExtension(appliesToLocalContent=true,
094     appliesToSynchronizedContent=false)
095@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE)
096public abstract class SASLMechanismHandler
097       implements UnboundIDExtension,
098                  Reconfigurable<SASLMechanismHandlerConfig>,
099                  ExampleUsageProvider
100{
101  /**
102   * Creates a new instance of this SASL mechanism handler.  All SASL
103   * mechanism handler implementations must include a default constructor, but
104   * any initialization
105   * should generally be done in the {@code initializeSASLMechanismHandler}
106   * method.
107   */
108  public SASLMechanismHandler()
109  {
110    // No implementation is required.
111  }
112
113
114
115  /**
116   * {@inheritDoc}
117   */
118  public abstract String getExtensionName();
119
120
121
122  /**
123   * {@inheritDoc}
124   */
125  public abstract String[] getExtensionDescription();
126
127
128
129  /**
130   * {@inheritDoc}
131   */
132  public void defineConfigArguments(final ArgumentParser parser)
133         throws ArgumentException
134  {
135    // No arguments will be allowed by default.
136  }
137
138
139
140  /**
141   * Initializes this SASL mechanism handler.
142   *
143   * @param  serverContext  A handle to the server context for the server in
144   *                        which this extension is running.
145   * @param  config         The general configuration for this SASL mechanism
146   *                        handler.
147   * @param  parser         The argument parser which has been initialized from
148   *                        the configuration for this SASL mechanism handler.
149   *
150   * @throws  LDAPException  If a problem occurs while initializing this SASL
151   *                         mechanism handler.
152   */
153  public void initializeSASLMechanismHandler(
154                   final DirectoryServerContext serverContext,
155                   final SASLMechanismHandlerConfig config,
156                   final ArgumentParser parser)
157         throws LDAPException
158  {
159    // No initialization will be performed by default.
160  }
161
162
163
164  /**
165   * {@inheritDoc}
166   */
167  public boolean isConfigurationAcceptable(
168                      final SASLMechanismHandlerConfig config,
169                      final ArgumentParser parser,
170                      final List<String> unacceptableReasons)
171  {
172    // No extended validation will be performed by default.
173    return true;
174  }
175
176
177
178  /**
179   * {@inheritDoc}
180   */
181  public ResultCode applyConfiguration(final SASLMechanismHandlerConfig config,
182                                       final ArgumentParser parser,
183                                       final List<String> adminActionsRequired,
184                                       final List<String> messages)
185  {
186    // By default, no configuration changes will be applied.  If there are any
187    // arguments, then add an admin action message indicating that the extension
188    // needs to be restarted for any changes to take effect.
189    if (! parser.getNamedArguments().isEmpty())
190    {
191      adminActionsRequired.add(
192           "No configuration change has actually been applied.  The new " +
193                "configuration will not take effect until this SASL " +
194                "mechanism handler is disabled and re-enabled or until the " +
195                "server is restarted.");
196    }
197
198    return ResultCode.SUCCESS;
199  }
200
201
202
203  /**
204   * Performs any cleanup which may be necessary when this SASL mechanism
205   * handler is to be taken out of service.
206   */
207  public void finalizeSASLMechanismHandler()
208  {
209    // No implementation is required.
210  }
211
212
213
214  /**
215   * Retrieves a list of the names of the SASL mechanisms supported by this
216   * SASL mechanism handler.  This method will be invoked only immediately after
217   * the {@link #initializeSASLMechanismHandler} method is called.
218   *
219   * @return  A list of the names of the SASL mechanisms supported by this SASL
220   *          mechanism handler.
221   */
222  public abstract List<String> getSASLMechanismNames();
223
224
225
226  /**
227   * Indicates whether the SASL authentication process using the specified
228   * mechanism may be considered secure (i.e., that a third party able to
229   * observe the communication, potentially over an insecure communication
230   * channel, would not be able to reproduce the authentication process).
231   *
232   * @param  mechanism  The name of the mechanism for which to make the
233   *                    determination.  This will only be invoked with names of
234   *                    mechanisms returned by the
235   *                    {@link #getSASLMechanismNames} method.
236   *
237   * @return  {@code true} if the specified SASL mechanism should be considered
238   *          secure, or {@code false} if not.
239   */
240  public abstract boolean isSecure(final String mechanism);
241
242
243
244  /**
245   * Indicates whether the SASL authentication process using the specified
246   * mechanism involves the use of a password stored locally in the server
247   * (optionally in combination with other forms of credentials).
248   *
249   * @param  mechanism  The name of the mechanism for which to make the
250   *                    determination.  This will only be invoked with names of
251   *                    mechanisms returned by the
252   *                    {@link #getSASLMechanismNames} method.
253   *
254   * @return  {@code true} if the specified SASL mechanism makes use of a local
255   *          password, or {@code false} if not.
256   */
257  public abstract boolean isPasswordBased(final String mechanism);
258
259
260
261  /**
262   * Performs the appropriate processing for the provided SASL bind request.
263   *
264   * @param  operationContext  The context for the bind operation.
265   * @param  bindRequest       The SASL bind request to be processed.
266   * @param  resultFactory     A factory object that will be used to construct
267   *                           the result to return.
268   *
269   * @return  An object with information about the result of the SASL bind
270   *          processing.
271   */
272  public abstract SASLBindResult processSASLBind(
273                       final OperationContext operationContext,
274                       final SASLBindRequest bindRequest,
275                       final SASLBindResultFactory resultFactory);
276
277
278
279  /**
280   * {@inheritDoc}
281   */
282  public Map<List<String>,String> getExamplesArgumentSets()
283  {
284    return Collections.emptyMap();
285  }
286}