001/* 002 * Copyright 2008-2017 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright (C) 2015-2017 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 * ... }, 152 * opValues SEQUENCE OF OCTET STRING OPTIONAL } 153 * </PRE> 154 * <BR> 155 * <H2>Example</H2> 156 * The following example demonstrates the use of the password policy state 157 * extended operation to administratively disable a user's account: 158 * <PRE> 159 * PasswordPolicyStateOperation disableOp = 160 * PasswordPolicyStateOperation.createSetAccountDisabledStateOperation( 161 * true); 162 * PasswordPolicyStateExtendedRequest pwpStateRequest = 163 * new PasswordPolicyStateExtendedRequest( 164 * "uid=john.doe,ou=People,dc=example,dc=com", disableOp); 165 * PasswordPolicyStateExtendedResult pwpStateResult = 166 * (PasswordPolicyStateExtendedResult) 167 * connection.processExtendedOperation(pwpStateRequest); 168 * 169 * // NOTE: The processExtendedOperation method will generally only throw an 170 * // exception if a problem occurs while trying to send the request or read 171 * // the response. It will not throw an exception because of a non-success 172 * // response. 173 * 174 * if (pwpStateResult.getResultCode() == ResultCode.SUCCESS) 175 * { 176 * boolean isDisabled = pwpStateResult.getBooleanValue( 177 * PasswordPolicyStateOperation.OP_TYPE_GET_ACCOUNT_DISABLED_STATE); 178 * if (isDisabled) 179 * { 180 * // The user account has been disabled. 181 * } 182 * else 183 * { 184 * // The user account is not disabled. 185 * } 186 * } 187 * </PRE> 188 */ 189@NotMutable() 190@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 191public final class PasswordPolicyStateExtendedRequest 192 extends ExtendedRequest 193{ 194 /** 195 * The OID (1.3.6.1.4.1.30221.1.6.1) for the password policy state extended 196 * request. 197 */ 198 public static final String PASSWORD_POLICY_STATE_REQUEST_OID = 199 "1.3.6.1.4.1.30221.1.6.1"; 200 201 202 203 /** 204 * The serial version UID for this serializable class. 205 */ 206 private static final long serialVersionUID = -1644137695182620213L; 207 208 209 210 // The set of password policy state operations to process. 211 private final PasswordPolicyStateOperation[] operations; 212 213 // The DN of the user account on which to operate. 214 private final String userDN; 215 216 217 218 /** 219 * Creates a new password policy state extended request with the provided user 220 * DN and optional set of operations. 221 * 222 * @param userDN The DN of the user account on which to operate. 223 * @param operations The set of password policy state operations to process. 224 * If no operations are provided, then the effect will be 225 * to retrieve the values of all available password policy 226 * state properties. 227 */ 228 public PasswordPolicyStateExtendedRequest(final String userDN, 229 final PasswordPolicyStateOperation... operations) 230 { 231 this(userDN, null, operations); 232 } 233 234 235 236 /** 237 * Creates a new password policy state extended request with the provided user 238 * DN, optional set of operations, and optional set of controls. 239 * 240 * @param userDN The DN of the user account on which to operate. 241 * @param controls The set of controls to include in the request. 242 * @param operations The set of password policy state operations to process. 243 * If no operations are provided, then the effect will be 244 * to retrieve the values of all available password policy 245 * state properties. 246 */ 247 public PasswordPolicyStateExtendedRequest(final String userDN, 248 final Control[] controls, 249 final PasswordPolicyStateOperation... operations) 250 { 251 super(PASSWORD_POLICY_STATE_REQUEST_OID, encodeValue(userDN, operations), 252 controls); 253 254 this.userDN = userDN; 255 this.operations = operations; 256 } 257 258 259 260 /** 261 * Creates a new password policy state extended request from the provided 262 * generic extended request. 263 * 264 * @param extendedRequest The generic extended request to use to create this 265 * password policy state extended request. 266 * 267 * @throws LDAPException If a problem occurs while decoding the request. 268 */ 269 public PasswordPolicyStateExtendedRequest( 270 final ExtendedRequest extendedRequest) 271 throws LDAPException 272 { 273 super(extendedRequest); 274 275 final ASN1OctetString value = extendedRequest.getValue(); 276 if (value == null) 277 { 278 throw new LDAPException(ResultCode.DECODING_ERROR, 279 ERR_PWP_STATE_REQUEST_NO_VALUE.get()); 280 } 281 282 final ASN1Element[] elements; 283 try 284 { 285 final ASN1Element valueElement = ASN1Element.decode(value.getValue()); 286 elements = ASN1Sequence.decodeAsSequence(valueElement).elements(); 287 } 288 catch (final Exception e) 289 { 290 debugException(e); 291 throw new LDAPException(ResultCode.DECODING_ERROR, 292 ERR_PWP_STATE_REQUEST_VALUE_NOT_SEQUENCE.get(e), 293 e); 294 } 295 296 if ((elements.length < 1) || (elements.length > 2)) 297 { 298 throw new LDAPException(ResultCode.DECODING_ERROR, 299 ERR_PWP_STATE_REQUEST_INVALID_ELEMENT_COUNT.get( 300 elements.length)); 301 } 302 303 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 304 305 if (elements.length == 1) 306 { 307 operations = new PasswordPolicyStateOperation[0]; 308 } 309 else 310 { 311 try 312 { 313 final ASN1Element[] opElements = 314 ASN1Sequence.decodeAsSequence(elements[1]).elements(); 315 operations = new PasswordPolicyStateOperation[opElements.length]; 316 for (int i=0; i < opElements.length; i++) 317 { 318 operations[i] = PasswordPolicyStateOperation.decode(opElements[i]); 319 } 320 } 321 catch (final Exception e) 322 { 323 debugException(e); 324 throw new LDAPException(ResultCode.DECODING_ERROR, 325 ERR_PWP_STATE_REQUEST_CANNOT_DECODE_OPS.get(e), 326 e); 327 } 328 } 329 } 330 331 332 333 /** 334 * Encodes the provided information into an ASN.1 octet string that may be 335 * used as the value for this extended request. 336 * 337 * @param userDN The DN of the user account on which to operate. 338 * @param operations The set of operations to be processed. 339 * 340 * @return An ASN.1 octet string containing the encoded value. 341 */ 342 private static ASN1OctetString encodeValue(final String userDN, 343 final PasswordPolicyStateOperation[] operations) 344 { 345 final ASN1Element[] elements; 346 if ((operations == null) || (operations.length == 0)) 347 { 348 elements = new ASN1Element[] 349 { 350 new ASN1OctetString(userDN) 351 }; 352 } 353 else 354 { 355 final ASN1Element[] opElements = new ASN1Element[operations.length]; 356 for (int i=0; i < operations.length; i++) 357 { 358 opElements[i] = operations[i].encode(); 359 } 360 361 elements = new ASN1Element[] 362 { 363 new ASN1OctetString(userDN), 364 new ASN1Sequence(opElements) 365 }; 366 } 367 368 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 369 } 370 371 372 373 /** 374 * Retrieves the DN of the user account on which to operate. 375 * 376 * @return The DN of the user account on which to operate. 377 */ 378 public String getUserDN() 379 { 380 return userDN; 381 } 382 383 384 385 /** 386 * Retrieves the set of password policy state operations to be processed. 387 * 388 * @return The set of password policy state operations to be processed, or 389 * an empty list if the values of all password policy state 390 * properties should be retrieved. 391 */ 392 public PasswordPolicyStateOperation[] getOperations() 393 { 394 return operations; 395 } 396 397 398 399 /** 400 * {@inheritDoc} 401 */ 402 @Override() 403 public PasswordPolicyStateExtendedResult 404 process(final LDAPConnection connection, final int depth) 405 throws LDAPException 406 { 407 final ExtendedResult extendedResponse = super.process(connection, depth); 408 return new PasswordPolicyStateExtendedResult(extendedResponse); 409 } 410 411 412 413 /** 414 * {@inheritDoc} 415 */ 416 @Override() 417 public PasswordPolicyStateExtendedRequest duplicate() 418 { 419 return duplicate(getControls()); 420 } 421 422 423 424 /** 425 * {@inheritDoc} 426 */ 427 @Override() 428 public PasswordPolicyStateExtendedRequest duplicate(final Control[] controls) 429 { 430 final PasswordPolicyStateExtendedRequest r = 431 new PasswordPolicyStateExtendedRequest(userDN, controls, operations); 432 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 433 return r; 434 } 435 436 437 438 /** 439 * {@inheritDoc} 440 */ 441 @Override() 442 public String getExtendedRequestName() 443 { 444 return INFO_EXTENDED_REQUEST_NAME_PW_POLICY_STATE.get(); 445 } 446 447 448 449 /** 450 * {@inheritDoc} 451 */ 452 @Override() 453 public void toString(final StringBuilder buffer) 454 { 455 buffer.append("PasswordPolicyStateExtendedRequest(userDN='"); 456 buffer.append(userDN); 457 458 if (operations.length > 0) 459 { 460 buffer.append("', operations={"); 461 for (int i=0; i < operations.length; i++) 462 { 463 if (i > 0) 464 { 465 buffer.append(", "); 466 } 467 468 operations[i].toString(buffer); 469 } 470 buffer.append('}'); 471 } 472 473 final Control[] controls = getControls(); 474 if (controls.length > 0) 475 { 476 buffer.append(", controls={"); 477 for (int i=0; i < controls.length; i++) 478 { 479 if (i > 0) 480 { 481 buffer.append(", "); 482 } 483 484 buffer.append(controls[i]); 485 } 486 buffer.append('}'); 487 } 488 489 buffer.append(')'); 490 } 491}