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 2013-2016 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.types.Entry; 039import com.unboundid.directory.sdk.ds.config. 040 OneTimePasswordDeliveryMechanismConfig; 041import com.unboundid.directory.sdk.ds.internal.DirectoryServerExtension; 042import com.unboundid.directory.sdk.ds.types.DirectoryServerContext; 043import com.unboundid.directory.sdk.proxy.internal.DirectoryProxyServerExtension; 044import com.unboundid.ldap.sdk.LDAPException; 045import com.unboundid.ldap.sdk.ResultCode; 046import com.unboundid.ldap.sdk.unboundidds.extensions. 047 SupportedOTPDeliveryMechanismInfo; 048import com.unboundid.util.Extensible; 049import com.unboundid.util.ThreadSafety; 050import com.unboundid.util.ThreadSafetyLevel; 051import com.unboundid.util.args.ArgumentException; 052import com.unboundid.util.args.ArgumentParser; 053 054 055 056/** 057 * This class defines an API that must be implemented by extensions which 058 * attempt to deliver one-time passwords (OTPs) to end users through some 059 * out-of-band mechanism. The one-time passwords will have been generated by 060 * the deliver one-time password extended request, and may be used to 061 * authenticate to the server through the UNBOUNDID-DELIVERED-OTP SASL 062 * mechanism. 063 * <BR> 064 * <H2>Configuring One-Time Password Delivery Mechanisms</H2> 065 * In order to configure a one-time password delivery mechanism created using 066 * this API, use a command like: 067 * <PRE> 068 * dsconfig create-otp-delivery-mechanism \ 069 * --mechanism-name "<I>{mechanism-name}</I>" \ 070 * --type third-party \ 071 * --set enabled:true \ 072 * --set "extension-class:<I>{class-name}</I>" \ 073 * --set "extension-argument:<I>{name=value}</I>" 074 * </PRE> 075 * where "<I>{mechanism-name}</I>" is the name to use for the one-time password 076 * instance, "<I>{class-name}</I>" is the fully-qualified name of the Java class 077 * that extends 078 * {@code com.unboundid.directory.sdk.ds.api.OneTimePasswordDeliveryMechanism}, 079 * and "<I>{name=value}</I>" represents name-value pairs for any arguments to 080 * provide to the one-time password delivery mechanism. If multiple arguments 081 * should be provided to the OTP delivery mechanism, then the 082 * "<CODE>--set extension-argument:<I>{name=value}</I></CODE>" option should be 083 * provided multiple times. 084 */ 085@Extensible() 086@DirectoryServerExtension() 087@DirectoryProxyServerExtension(appliesToLocalContent=true, 088 appliesToRemoteContent=true) 089@ThreadSafety(level=ThreadSafetyLevel.INTERFACE_THREADSAFE) 090public abstract class OneTimePasswordDeliveryMechanism 091 implements UnboundIDExtension, 092 Reconfigurable<OneTimePasswordDeliveryMechanismConfig>, 093 ExampleUsageProvider 094{ 095 /** 096 * Creates a new instance of this one-time password delivery mechanism. All 097 * OTP delivery mechanism implementations must include a default constructor, 098 * but any initialization should generally be done in the 099 * {@code initializeOTPDeliveryMechanism} method. 100 */ 101 public OneTimePasswordDeliveryMechanism() 102 { 103 // No implementation is required. 104 } 105 106 107 108 /** 109 * {@inheritDoc} 110 */ 111 @Override() 112 public abstract String getExtensionName(); 113 114 115 116 /** 117 * {@inheritDoc} 118 */ 119 @Override() 120 public abstract String[] getExtensionDescription(); 121 122 123 124 /** 125 * {@inheritDoc} 126 */ 127 @Override() 128 public void defineConfigArguments(final ArgumentParser parser) 129 throws ArgumentException 130 { 131 // No arguments will be allowed by default. 132 } 133 134 135 136 /** 137 * Initializes this one-time password delivery mechanism. 138 * 139 * @param serverContext A handle to the server context for the server in 140 * which this extension is running. 141 * @param config The general configuration for this OTP delivery 142 * mechanism. 143 * @param parser The argument parser which has been initialized from 144 * the configuration for this OTP delivery mechanism. 145 * 146 * @throws LDAPException If a problem occurs while initializing this OTP 147 * delivery mechanism. 148 */ 149 public void initializeOTPDeliveryMechanism( 150 final DirectoryServerContext serverContext, 151 final OneTimePasswordDeliveryMechanismConfig config, 152 final ArgumentParser parser) 153 throws LDAPException 154 { 155 // No initialization will be performed by default. 156 } 157 158 159 160 /** 161 * {@inheritDoc} 162 */ 163 @Override() 164 public boolean isConfigurationAcceptable( 165 final OneTimePasswordDeliveryMechanismConfig config, 166 final ArgumentParser parser, 167 final List<String> unacceptableReasons) 168 { 169 // No extended validation will be performed by default. 170 return true; 171 } 172 173 174 175 /** 176 * {@inheritDoc} 177 */ 178 @Override() 179 public ResultCode applyConfiguration( 180 final OneTimePasswordDeliveryMechanismConfig config, 181 final ArgumentParser parser, 182 final List<String> adminActionsRequired, 183 final List<String> messages) 184 { 185 // By default, no configuration changes will be applied. If there are any 186 // arguments, then add an admin action message indicating that the extension 187 // needs to be restarted for any changes to take effect. 188 if (! parser.getNamedArguments().isEmpty()) 189 { 190 adminActionsRequired.add( 191 "No configuration change has actually been applied. The new " + 192 "configuration will not take effect until this one-time " + 193 "password delivery mechanism is disabled and re-enabled or " + 194 "until the server is restarted."); 195 } 196 197 return ResultCode.SUCCESS; 198 } 199 200 201 202 /** 203 * Performs any cleanup which may be necessary when this one-time password 204 * delivery mechanism is to be taken out of service. 205 */ 206 public void finalizeOTPDeliveryMechanism() 207 { 208 // No implementation is required. 209 } 210 211 212 213 /** 214 * Attempts to deliver the provided one-time password to the specified user. 215 * 216 * @param oneTimePassword The one-time password to be delivered. 217 * @param userEntry The entry for the user to whom the one-time 218 * password should be delivered. 219 * @param targetRecipientID The target recipient ID that should be used for 220 * the delivery, if possible. It may be 221 * {@code null} if there is no appropriate 222 * identifier for this delivery mechanism or if 223 * the delivery mechanism may choose which 224 * recipient ID should be used. However, if it is 225 * non-{@code null}, then the delivery mechanism 226 * must verify that the provided recipient ID is 227 * valid for the associated user (e.g., for an 228 * e-mail delivery mechanism, the recipient ID 229 * would probably be an e-mail address, and the 230 * delivery mechanism must verify that the provided 231 * e-mail address is associated with the given 232 * user account). 233 * @param resultMessage A buffer to which a message may be appended with 234 * additional information about the password 235 * delivery. 236 * 237 * @return An identifier for the user in a format appropriate to the delivery 238 * mechanism (e.g., an e-mail address for an e-mail delivery 239 * mechanism, a phone number for an SMS or voice call delivery 240 * mechanism, etc.). It may be {@code null} if there is no 241 * appropriate identifier for this delivery mechanism that is needed 242 * beyond the name of the delivery mechanism and the DN of the 243 * recipient. 244 * 245 * @throws LDAPException If a problem is encountered while attempting to 246 * send the one-time password to the user. 247 */ 248 public abstract String deliverOneTimePassword(final String oneTimePassword, 249 final Entry userEntry, 250 final String targetRecipientID, 251 final StringBuilder resultMessage) 252 throws LDAPException; 253 254 255 256 /** 257 * Indicates whether this one-time password delivery mechanism supports 258 * general purpose message delivery via the {@link #deliverMessage} method. 259 * 260 * @return {@code true} if the {@code deliverMessage} method can be used for 261 * general-purpose message delivery, or {@code false} if only the 262 * {@code deliverOneTimePassword} method can be used. 263 */ 264 public boolean supportsGenericMessageDelivery() 265 { 266 return false; 267 } 268 269 270 271 /** 272 * Attempts to deliver a message (containing a single-use token) to the 273 * specified user. 274 * 275 * @param config The general configuration for this OTP delivery 276 * mechanism. 277 * @param tokenID The token ID for the single-use token contained 278 * in the message to be delivered. 279 * @param tokenValue The value for the single-use token contained 280 * in the message to be delivered. 281 * @param messageSubject The message subject that should be used, if 282 * appropriate. It may be {@code null} if no 283 * subject was provided. 284 * @param fullMessage The message that should be delivered if this 285 * delivery mechanism does not impose a 286 * significant constraint on message size. 287 * @param compactMessage The message that should be delivered if this 288 * delivery mechanism does impose a significant 289 * constraint on message size. 290 * @param userEntry The entry for the user to whom the token should 291 * be delivered. 292 * @param targetRecipientID The target recipient ID that should be used for 293 * the delivery, if possible. It may be 294 * {@code null} if there is no appropriate 295 * identifier for this delivery mechanism or if 296 * the delivery mechanism may choose which 297 * recipient ID should be used. However, if it is 298 * non-{@code null}, then the delivery mechanism 299 * must verify that the provided recipient ID is 300 * valid for the associated user (e.g., for an 301 * e-mail delivery mechanism, the recipient ID 302 * would probably be an e-mail address, and the 303 * delivery mechanism must verify that the 304 * provided e-mail address is associated with the 305 * given user account). 306 * @param resultMessage A buffer to which a message may be appended 307 * with additional information about the token 308 * delivery. 309 * 310 * @return An identifier for the user in a format appropriate to the delivery 311 * mechanism (e.g., an e-mail address for an e-mail delivery 312 * mechanism, a phone number for an SMS or voice call delivery 313 * mechanism, etc.). It may be {@code null} if there is no 314 * appropriate identifier for this delivery mechanism that is needed 315 * beyond the name of the delivery mechanism and the DN of the 316 * recipient. 317 * 318 * @throws LDAPException If a problem is encountered while attempting to 319 * deliver the single-use token message to the user. 320 */ 321 public String deliverMessage( 322 final OneTimePasswordDeliveryMechanismConfig config, 323 final String tokenID, final String tokenValue, 324 final String messageSubject, final String fullMessage, 325 final String compactMessage, final Entry userEntry, 326 final String targetRecipientID, 327 final StringBuilder resultMessage) 328 throws LDAPException 329 { 330 throw new LDAPException(ResultCode.OTHER, 331 "The '" + config.getConfigObjectName() + "' OTP delivery mechanism " + 332 "does not support arbitrary message delivery."); 333 } 334 335 336 337 /** 338 * Updates the provided list with one or more 339 * {@code SupportedOTPDeliveryMechanismInfo} objects indicating whether this 340 * OTP delivery mechanism is supported for the specified user. 341 * 342 * @param config The general configuration for this OTP 343 * delivery mechanism. 344 * @param userEntry The entry of the user for whom to make the 345 * determination. 346 * @param deliveryMechanismInfo The list to which any objects may be 347 * appended with information about the level 348 * of support this OTP delivery mechanism has 349 * for use in conjunction with the specified 350 * user. 351 */ 352 public void getSupportedDeliveryMechanismInfo( 353 final OneTimePasswordDeliveryMechanismConfig config, 354 final Entry userEntry, 355 final List<SupportedOTPDeliveryMechanismInfo> deliveryMechanismInfo) 356 { 357 deliveryMechanismInfo.add( 358 new SupportedOTPDeliveryMechanismInfo(config.getConfigObjectName(), 359 null, null)); 360 } 361 362 363 364 /** 365 * {@inheritDoc} 366 */ 367 @Override() 368 public Map<List<String>,String> getExamplesArgumentSets() 369 { 370 return Collections.emptyMap(); 371 } 372}