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 }