001/* 002 * Copyright 2008-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.ExtendedResult; 031import com.unboundid.ldap.sdk.LDAPConnection; 032import com.unboundid.ldap.sdk.LDAPException; 033import com.unboundid.ldap.sdk.ResultCode; 034import com.unboundid.util.NotMutable; 035import com.unboundid.util.ThreadSafety; 036import com.unboundid.util.ThreadSafetyLevel; 037 038import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 039import static com.unboundid.util.Debug.*; 040 041 042 043/** 044 * This class provides an implementation of the password policy state extended 045 * request as used in the Ping Identity, UnboundID, or Alcatel-Lucent 8661 046 * Directory Server. It may be used to retrieve and/or alter password policy 047 * properties for a user account. See the documentation in the 048 * {@link PasswordPolicyStateOperation} class for information about the types of 049 * operations that can be performed. 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 Alcatel-Lucent 8661 055 * server products. These classes provide support for proprietary 056 * functionality or for external specifications that are not considered stable 057 * or mature enough to be guaranteed to work in an interoperable way with 058 * other types of LDAP servers. 059 * </BLOCKQUOTE> 060 * <BR> 061 * The extended request has an OID of 1.3.6.1.4.1.30221.1.6.1 and a value with 062 * the following encoding: 063 * <PRE> 064 * PasswordPolicyStateValue ::= SEQUENCE { 065 * targetUser LDAPDN 066 * operations SEQUENCE OF PasswordPolicyStateOperation OPTIONAL } 067 * 068 * PasswordPolicyStateOperation ::= SEQUENCE { 069 * opType ENUMERATED { 070 * getPasswordPolicyDN (0), 071 * getAccountDisabledState (1), 072 * setAccountDisabledState (2), 073 * clearAccountDisabledState (3), 074 * getAccountExpirationTime (4), 075 * setAccountExpirationTime (5), 076 * clearAccountExpirationTime (6), 077 * getSecondsUntilAccountExpiration (7), 078 * getPasswordChangedTime (8), 079 * setPasswordChangedTime (9), 080 * clearPasswordChangedTime (10), 081 * getPasswordExpirationWarnedTime (11), 082 * setPasswordExpirationWarnedTime (12), 083 * clearPasswordExpirationWarnedTime (13), 084 * getSecondsUntilPasswordExpiration (14), 085 * getSecondsUntilPasswordExpirationWarning (15), 086 * getAuthenticationFailureTimes (16), 087 * addAuthenticationFailureTime (17), 088 * setAuthenticationFailureTimes (18), 089 * clearAuthenticationFailureTimes (19), 090 * getSecondsUntilAuthenticationFailureUnlock (20), 091 * getRemainingAuthenticationFailureCount (21), 092 * getLastLoginTime (22), 093 * setLastLoginTime (23), 094 * clearLastLoginTime (24), 095 * getSecondsUntilIdleLockout (25), 096 * getPasswordResetState (26), 097 * setPasswordResetState (27), 098 * clearPasswordResetState (28), 099 * getSecondsUntilPasswordResetLockout (29), 100 * getGraceLoginUseTimes (30), 101 * addGraceLoginUseTime (31), 102 * setGraceLoginUseTimes (32), 103 * clearGraceLoginUseTimes (33), 104 * getRemainingGraceLoginCount (34), 105 * getPasswordChangedByRequiredTime (35), 106 * setPasswordChangedByRequiredTime (36), 107 * clearPasswordChangedByRequiredTime (37), 108 * getSecondsUntilRequiredChangeTime (38), 109 * getPasswordHistory (39), -- Deprecated 110 * clearPasswordHistory (40), 111 * hasRetiredPassword (41), 112 * getPasswordRetiredTime (42), 113 * getRetiredPasswordExpirationTime (43), 114 * purgeRetiredPassword (44), 115 * getAccountActivationTime (45), 116 * setAccountActivationTime (46), 117 * clearAccountActivationTime (47), 118 * getSecondsUntilAccountActivation (48), 119 * getLastLoginIPAddress (49), 120 * setLastLoginIPAddress (50), 121 * clearLastLoginIPAddress (51), 122 * getAccountUsabilityNotices (52), 123 * getAccountUsabilityWarnings (53), 124 * getAccountUsabilityErrors (54), 125 * getAccountIsUsable (55), 126 * getAccountIsNotYetActive (56), 127 * getAccountIsExpired (57), 128 * getPasswordExpirationTime (58), 129 * getAccountIsFailureLocked (59), 130 * setAccountIsFailureLocked (60), 131 * getFailureLockoutTime (61), 132 * getAccountIsIdleLocked (62), 133 * getIdleLockoutTime (63), 134 * getAccountIsResetLocked (64), 135 * getResetLockoutTime (65), 136 * getPasswordHistoryCount (66), 137 * getPasswordIsExpired (67), 138 * getAvailableSASLMechanisms (68), 139 * getAvailableOTPDeliveryMechanisms (69), 140 * getHasTOTPSharedSecret (70), 141 * getRegisteredYubiKeyPublicIDs (71), 142 * addRegisteredYubiKeyPublicID (72), 143 * removeRegisteredYubiKeyPublicID (73), 144 * setRegisteredYubiKeyPublicIDs (74), 145 * clearRegisteredYubiKeyPublicIDs (75), 146 * addTOTPSharedSecret (76), 147 * removeTOTPSharedSecret (77), 148 * setTOTPSharedSecrets (78), 149 * clearTOTPSharedSecrets (79), 150 * hasRegisteredYubiKeyPublicID (80), 151 * hasStaticPassword (81), 152 * ... }, 153 * opValues SEQUENCE OF OCTET STRING OPTIONAL } 154 * </PRE> 155 * <BR> 156 * <H2>Example</H2> 157 * The following example demonstrates the use of the password policy state 158 * extended operation to administratively disable a user's account: 159 * <PRE> 160 * PasswordPolicyStateOperation disableOp = 161 * PasswordPolicyStateOperation.createSetAccountDisabledStateOperation( 162 * true); 163 * PasswordPolicyStateExtendedRequest pwpStateRequest = 164 * new PasswordPolicyStateExtendedRequest( 165 * "uid=john.doe,ou=People,dc=example,dc=com", disableOp); 166 * PasswordPolicyStateExtendedResult pwpStateResult = 167 * (PasswordPolicyStateExtendedResult) 168 * connection.processExtendedOperation(pwpStateRequest); 169 * 170 * // NOTE: The processExtendedOperation method will generally only throw an 171 * // exception if a problem occurs while trying to send the request or read 172 * // the response. It will not throw an exception because of a non-success 173 * // response. 174 * 175 * if (pwpStateResult.getResultCode() == ResultCode.SUCCESS) 176 * { 177 * boolean isDisabled = pwpStateResult.getBooleanValue( 178 * PasswordPolicyStateOperation.OP_TYPE_GET_ACCOUNT_DISABLED_STATE); 179 * if (isDisabled) 180 * { 181 * // The user account has been disabled. 182 * } 183 * else 184 * { 185 * // The user account is not disabled. 186 * } 187 * } 188 * </PRE> 189 */ 190@NotMutable() 191@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 192public final class PasswordPolicyStateExtendedRequest 193 extends ExtendedRequest 194{ 195 /** 196 * The OID (1.3.6.1.4.1.30221.1.6.1) for the password policy state extended 197 * request. 198 */ 199 public static final String PASSWORD_POLICY_STATE_REQUEST_OID = 200 "1.3.6.1.4.1.30221.1.6.1"; 201 202 203 204 /** 205 * The serial version UID for this serializable class. 206 */ 207 private static final long serialVersionUID = -1644137695182620213L; 208 209 210 211 // The set of password policy state operations to process. 212 private final PasswordPolicyStateOperation[] operations; 213 214 // The DN of the user account on which to operate. 215 private final String userDN; 216 217 218 219 /** 220 * Creates a new password policy state extended request with the provided user 221 * DN and optional set of operations. 222 * 223 * @param userDN The DN of the user account on which to operate. 224 * @param operations The set of password policy state operations to process. 225 * If no operations are provided, then the effect will be 226 * to retrieve the values of all available password policy 227 * state properties. 228 */ 229 public PasswordPolicyStateExtendedRequest(final String userDN, 230 final PasswordPolicyStateOperation... operations) 231 { 232 this(userDN, null, operations); 233 } 234 235 236 237 /** 238 * Creates a new password policy state extended request with the provided user 239 * DN, optional set of operations, and optional set of controls. 240 * 241 * @param userDN The DN of the user account on which to operate. 242 * @param controls The set of controls to include in the request. 243 * @param operations The set of password policy state operations to process. 244 * If no operations are provided, then the effect will be 245 * to retrieve the values of all available password policy 246 * state properties. 247 */ 248 public PasswordPolicyStateExtendedRequest(final String userDN, 249 final Control[] controls, 250 final PasswordPolicyStateOperation... operations) 251 { 252 super(PASSWORD_POLICY_STATE_REQUEST_OID, encodeValue(userDN, operations), 253 controls); 254 255 this.userDN = userDN; 256 this.operations = operations; 257 } 258 259 260 261 /** 262 * Creates a new password policy state extended request from the provided 263 * generic extended request. 264 * 265 * @param extendedRequest The generic extended request to use to create this 266 * password policy state extended request. 267 * 268 * @throws LDAPException If a problem occurs while decoding the request. 269 */ 270 public PasswordPolicyStateExtendedRequest( 271 final ExtendedRequest extendedRequest) 272 throws LDAPException 273 { 274 super(extendedRequest); 275 276 final ASN1OctetString value = extendedRequest.getValue(); 277 if (value == null) 278 { 279 throw new LDAPException(ResultCode.DECODING_ERROR, 280 ERR_PWP_STATE_REQUEST_NO_VALUE.get()); 281 } 282 283 final ASN1Element[] elements; 284 try 285 { 286 final ASN1Element valueElement = ASN1Element.decode(value.getValue()); 287 elements = ASN1Sequence.decodeAsSequence(valueElement).elements(); 288 } 289 catch (final Exception e) 290 { 291 debugException(e); 292 throw new LDAPException(ResultCode.DECODING_ERROR, 293 ERR_PWP_STATE_REQUEST_VALUE_NOT_SEQUENCE.get(e), 294 e); 295 } 296 297 if ((elements.length < 1) || (elements.length > 2)) 298 { 299 throw new LDAPException(ResultCode.DECODING_ERROR, 300 ERR_PWP_STATE_REQUEST_INVALID_ELEMENT_COUNT.get( 301 elements.length)); 302 } 303 304 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 305 306 if (elements.length == 1) 307 { 308 operations = new PasswordPolicyStateOperation[0]; 309 } 310 else 311 { 312 try 313 { 314 final ASN1Element[] opElements = 315 ASN1Sequence.decodeAsSequence(elements[1]).elements(); 316 operations = new PasswordPolicyStateOperation[opElements.length]; 317 for (int i=0; i < opElements.length; i++) 318 { 319 operations[i] = PasswordPolicyStateOperation.decode(opElements[i]); 320 } 321 } 322 catch (final Exception e) 323 { 324 debugException(e); 325 throw new LDAPException(ResultCode.DECODING_ERROR, 326 ERR_PWP_STATE_REQUEST_CANNOT_DECODE_OPS.get(e), 327 e); 328 } 329 } 330 } 331 332 333 334 /** 335 * Encodes the provided information into an ASN.1 octet string that may be 336 * used as the value for this extended request. 337 * 338 * @param userDN The DN of the user account on which to operate. 339 * @param operations The set of operations to be processed. 340 * 341 * @return An ASN.1 octet string containing the encoded value. 342 */ 343 private static ASN1OctetString encodeValue(final String userDN, 344 final PasswordPolicyStateOperation[] operations) 345 { 346 final ASN1Element[] elements; 347 if ((operations == null) || (operations.length == 0)) 348 { 349 elements = new ASN1Element[] 350 { 351 new ASN1OctetString(userDN) 352 }; 353 } 354 else 355 { 356 final ASN1Element[] opElements = new ASN1Element[operations.length]; 357 for (int i=0; i < operations.length; i++) 358 { 359 opElements[i] = operations[i].encode(); 360 } 361 362 elements = new ASN1Element[] 363 { 364 new ASN1OctetString(userDN), 365 new ASN1Sequence(opElements) 366 }; 367 } 368 369 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 370 } 371 372 373 374 /** 375 * Retrieves the DN of the user account on which to operate. 376 * 377 * @return The DN of the user account on which to operate. 378 */ 379 public String getUserDN() 380 { 381 return userDN; 382 } 383 384 385 386 /** 387 * Retrieves the set of password policy state operations to be processed. 388 * 389 * @return The set of password policy state operations to be processed, or 390 * an empty list if the values of all password policy state 391 * properties should be retrieved. 392 */ 393 public PasswordPolicyStateOperation[] getOperations() 394 { 395 return operations; 396 } 397 398 399 400 /** 401 * {@inheritDoc} 402 */ 403 @Override() 404 public PasswordPolicyStateExtendedResult 405 process(final LDAPConnection connection, final int depth) 406 throws LDAPException 407 { 408 final ExtendedResult extendedResponse = super.process(connection, depth); 409 return new PasswordPolicyStateExtendedResult(extendedResponse); 410 } 411 412 413 414 /** 415 * {@inheritDoc} 416 */ 417 @Override() 418 public PasswordPolicyStateExtendedRequest duplicate() 419 { 420 return duplicate(getControls()); 421 } 422 423 424 425 /** 426 * {@inheritDoc} 427 */ 428 @Override() 429 public PasswordPolicyStateExtendedRequest duplicate(final Control[] controls) 430 { 431 final PasswordPolicyStateExtendedRequest r = 432 new PasswordPolicyStateExtendedRequest(userDN, controls, operations); 433 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 434 return r; 435 } 436 437 438 439 /** 440 * {@inheritDoc} 441 */ 442 @Override() 443 public String getExtendedRequestName() 444 { 445 return INFO_EXTENDED_REQUEST_NAME_PW_POLICY_STATE.get(); 446 } 447 448 449 450 /** 451 * {@inheritDoc} 452 */ 453 @Override() 454 public void toString(final StringBuilder buffer) 455 { 456 buffer.append("PasswordPolicyStateExtendedRequest(userDN='"); 457 buffer.append(userDN); 458 459 if (operations.length > 0) 460 { 461 buffer.append("', operations={"); 462 for (int i=0; i < operations.length; i++) 463 { 464 if (i > 0) 465 { 466 buffer.append(", "); 467 } 468 469 operations[i].toString(buffer); 470 } 471 buffer.append('}'); 472 } 473 474 final Control[] controls = getControls(); 475 if (controls.length > 0) 476 { 477 buffer.append(", controls={"); 478 for (int i=0; i < controls.length; i++) 479 { 480 if (i > 0) 481 { 482 buffer.append(", "); 483 } 484 485 buffer.append(controls[i]); 486 } 487 buffer.append('}'); 488 } 489 490 buffer.append(')'); 491 } 492}