001 /*
002 * Copyright 2012-2015 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2015 UnboundID Corp.
007 *
008 * This program is free software; you can redistribute it and/or modify
009 * it under the terms of the GNU General Public License (GPLv2 only)
010 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only)
011 * as published by the Free Software Foundation.
012 *
013 * This program is distributed in the hope that it will be useful,
014 * but WITHOUT ANY WARRANTY; without even the implied warranty of
015 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
016 * GNU General Public License for more details.
017 *
018 * You should have received a copy of the GNU General Public License
019 * along with this program; if not, see <http://www.gnu.org/licenses>.
020 */
021 package com.unboundid.ldap.sdk.unboundidds.extensions;
022
023
024
025 import com.unboundid.asn1.ASN1Element;
026 import com.unboundid.asn1.ASN1OctetString;
027 import com.unboundid.asn1.ASN1Sequence;
028 import com.unboundid.ldap.sdk.Control;
029 import com.unboundid.ldap.sdk.ExtendedRequest;
030 import com.unboundid.ldap.sdk.LDAPException;
031 import com.unboundid.ldap.sdk.ResultCode;
032 import com.unboundid.util.Debug;
033 import com.unboundid.util.NotMutable;
034 import com.unboundid.util.StaticUtils;
035 import com.unboundid.util.ThreadSafety;
036 import com.unboundid.util.ThreadSafetyLevel;
037 import com.unboundid.util.Validator;
038
039 import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*;
040
041
042
043 /**
044 * <BLOCKQUOTE>
045 * <B>NOTE:</B> This class is part of the Commercial Edition of the UnboundID
046 * LDAP SDK for Java. It is not available for use in applications that
047 * include only the Standard Edition of the LDAP SDK, and is not supported for
048 * use in conjunction with non-UnboundID products.
049 * </BLOCKQUOTE>
050 * This class provides an implementation of an extended request which may be
051 * used to validate a TOTP password for a user. Note that this should not be
052 * used as an alternative to authentication because it does not perform password
053 * policy processing. Rather, this extended operation should be used only to
054 * obtain additional assurance about the identity of a user that has already
055 * been authenticated through some other means.
056 * <BR><BR>
057 * The extended request has an OID of 1.3.6.1.4.1.30221.2.6.15 and a value with
058 * the following encoding:
059 * <PRE>
060 * ValidateTOTPPasswordRequest ::= SEQUENCE {
061 * userDN [0] LDAPDN,
062 * totpPassword [1] OCTET STRING,
063 * ... }
064 * </PRE>
065 */
066 @NotMutable()
067 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
068 public final class ValidateTOTPPasswordExtendedRequest
069 extends ExtendedRequest
070 {
071 /**
072 * The OID (1.3.6.1.4.1.30221.2.6.15) for the validate TOTP password extended
073 * request.
074 */
075 public static final String VALIDATE_TOTP_PASSWORD_REQUEST_OID =
076 "1.3.6.1.4.1.30221.2.6.15";
077
078
079
080 /**
081 * The BER type for the user DN value element.
082 */
083 private static final byte TYPE_USER_DN = (byte) 0x80;
084
085
086
087 /**
088 * The BER type for the TOTP password value element.
089 */
090 private static final byte TYPE_TOTP_PASSWORD = (byte) 0x81;
091
092
093
094 /**
095 * The serial version UID for this serializable class.
096 */
097 private static final long serialVersionUID = -4610279612454559569L;
098
099
100
101 // The DN of the user for whom to validate the TOTP password.
102 private final String userDN;
103
104 // The TOTP password to validate.
105 private final String totpPassword;
106
107
108
109
110 /**
111 * Creates a new validate TOTP password extended request with the provided
112 * information.
113 *
114 * @param userDN The DN of the user for whom to validate the TOTP
115 * password.
116 * @param totpPassword The TOTP password to validate.
117 * @param controls The set of controls to include in the request.
118 */
119 public ValidateTOTPPasswordExtendedRequest(final String userDN,
120 final String totpPassword,
121 final Control... controls)
122 {
123 super(VALIDATE_TOTP_PASSWORD_REQUEST_OID,
124 encodeValue(userDN, totpPassword), controls);
125
126 Validator.ensureNotNull(userDN);
127 Validator.ensureNotNull(totpPassword);
128
129 this.userDN = userDN;
130 this.totpPassword = totpPassword;
131 }
132
133
134
135 /**
136 * Creates a new validate TOTP password extended request from the provided
137 * generic extended request.
138 *
139 * @param extendedRequest The generic extended request to parse as a
140 * validate TOTP extended request.
141 *
142 * @throws LDAPException If a problem is encountered while attempting to
143 * parse the provided extended request.
144 */
145 public ValidateTOTPPasswordExtendedRequest(
146 final ExtendedRequest extendedRequest)
147 throws LDAPException
148 {
149 super(extendedRequest);
150
151 final ASN1OctetString value = extendedRequest.getValue();
152 if (value == null)
153 {
154 throw new LDAPException(ResultCode.DECODING_ERROR,
155 ERR_VALIDATE_TOTP_REQUEST_MISSING_VALUE.get());
156 }
157
158 try
159 {
160 final ASN1Element[] elements =
161 ASN1Sequence.decodeAsSequence(value.getValue()).elements();
162 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue();
163 totpPassword =
164 ASN1OctetString.decodeAsOctetString(elements[1]).stringValue();
165 }
166 catch (final Exception e)
167 {
168 Debug.debugException(e);
169 throw new LDAPException(ResultCode.DECODING_ERROR,
170 ERR_VALIDATE_TOTP_REQUEST_MALFORMED_VALUE.get(
171 StaticUtils.getExceptionMessage(e)),
172 e);
173 }
174 }
175
176
177
178 /**
179 * Encodes the provided information into a value suitable for use as the value
180 * for this extended request.
181 *
182 * @param userDN The DN of the user for whom to validate the TOTP
183 * password.
184 * @param totpPassword The TOTP password to validate.
185 *
186 * @return The ASN.1 octet string containing the encoded value.
187 */
188 private static ASN1OctetString encodeValue(final String userDN,
189 final String totpPassword)
190 {
191 return new ASN1OctetString(new ASN1Sequence(
192 new ASN1OctetString(TYPE_USER_DN, userDN),
193 new ASN1OctetString(TYPE_TOTP_PASSWORD, totpPassword)).encode());
194 }
195
196
197
198 /**
199 * Retrieves the DN of the user for whom to validate the TOTP password.
200 *
201 * @return The DN of the user for whom to validate the TOTP password.
202 */
203 public String getUserDN()
204 {
205 return userDN;
206 }
207
208
209
210 /**
211 * Retrieves the TOTP password to validate.
212 *
213 * @return The TOTP password to validate.
214 */
215 public String getTOTPPassword()
216 {
217 return totpPassword;
218 }
219
220
221
222 /**
223 * {@inheritDoc}
224 */
225 @Override()
226 public ValidateTOTPPasswordExtendedRequest duplicate()
227 {
228 return duplicate(getControls());
229 }
230
231
232
233 /**
234 * {@inheritDoc}
235 */
236 @Override()
237 public ValidateTOTPPasswordExtendedRequest duplicate(
238 final Control[] controls)
239 {
240 final ValidateTOTPPasswordExtendedRequest r =
241 new ValidateTOTPPasswordExtendedRequest(userDN, totpPassword,
242 controls);
243 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null));
244 return r;
245 }
246
247
248
249 /**
250 * {@inheritDoc}
251 */
252 @Override()
253 public String getExtendedRequestName()
254 {
255 return INFO_EXTENDED_REQUEST_NAME_VALIDATE_TOTP.get();
256 }
257
258
259
260 /**
261 * {@inheritDoc}
262 */
263 @Override()
264 public void toString(final StringBuilder buffer)
265 {
266 buffer.append("ValidateTOTPPasswordExtendedRequest(userDN='");
267 buffer.append(userDN);
268 buffer.append('\'');
269
270 final Control[] controls = getControls();
271 if (controls.length > 0)
272 {
273 buffer.append(", controls={");
274 for (int i=0; i < controls.length; i++)
275 {
276 if (i > 0)
277 {
278 buffer.append(", ");
279 }
280
281 buffer.append(controls[i]);
282 }
283 buffer.append('}');
284 }
285
286 buffer.append(')');
287 }
288 }