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