001/* 002 * Copyright 2015-2020 Ping Identity Corporation 003 * All Rights Reserved. 004 */ 005/* 006 * Copyright 2015-2020 Ping Identity Corporation 007 * 008 * Licensed under the Apache License, Version 2.0 (the "License"); 009 * you may not use this file except in compliance with the License. 010 * You may obtain a copy of the License at 011 * 012 * http://www.apache.org/licenses/LICENSE-2.0 013 * 014 * Unless required by applicable law or agreed to in writing, software 015 * distributed under the License is distributed on an "AS IS" BASIS, 016 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 017 * See the License for the specific language governing permissions and 018 * limitations under the License. 019 */ 020/* 021 * Copyright (C) 2015-2020 Ping Identity Corporation 022 * 023 * This program is free software; you can redistribute it and/or modify 024 * it under the terms of the GNU General Public License (GPLv2 only) 025 * or the terms of the GNU Lesser General Public License (LGPLv2.1 only) 026 * as published by the Free Software Foundation. 027 * 028 * This program is distributed in the hope that it will be useful, 029 * but WITHOUT ANY WARRANTY; without even the implied warranty of 030 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 031 * GNU General Public License for more details. 032 * 033 * You should have received a copy of the GNU General Public License 034 * along with this program; if not, see <http://www.gnu.org/licenses>. 035 */ 036package com.unboundid.ldap.sdk.unboundidds.extensions; 037 038 039 040import com.unboundid.asn1.ASN1Element; 041import com.unboundid.asn1.ASN1OctetString; 042import com.unboundid.asn1.ASN1Null; 043import com.unboundid.asn1.ASN1Sequence; 044import com.unboundid.ldap.sdk.Control; 045import com.unboundid.ldap.sdk.ExtendedRequest; 046import com.unboundid.ldap.sdk.ExtendedResult; 047import com.unboundid.ldap.sdk.LDAPConnection; 048import com.unboundid.ldap.sdk.LDAPException; 049import com.unboundid.ldap.sdk.ResultCode; 050import com.unboundid.util.Debug; 051import com.unboundid.util.NotMutable; 052import com.unboundid.util.StaticUtils; 053import com.unboundid.util.ThreadSafety; 054import com.unboundid.util.ThreadSafetyLevel; 055 056import static com.unboundid.ldap.sdk.unboundidds.extensions.ExtOpMessages.*; 057 058 059 060/** 061 * This class provides an implementation of an extended request that may be used 062 * to retrieve the set of password quality requirements that the Directory 063 * Server will impose for a specified operation, which may include adding a new 064 * user (including a password), a user changing his/her own password (a self 065 * change), or one user changing the password for another user (an 066 * administrative reset). 067 * <BR> 068 * <BLOCKQUOTE> 069 * <B>NOTE:</B> This class, and other classes within the 070 * {@code com.unboundid.ldap.sdk.unboundidds} package structure, are only 071 * supported for use against Ping Identity, UnboundID, and 072 * Nokia/Alcatel-Lucent 8661 server products. These classes provide support 073 * for proprietary functionality or for external specifications that are not 074 * considered stable or mature enough to be guaranteed to work in an 075 * interoperable way with other types of LDAP servers. 076 * </BLOCKQUOTE> 077 * <BR> 078 * This extended request has an OID of 1.3.6.1.4.1.30221.2.6.43 and a value with 079 * the following encoding: 080 * <PRE> 081 * GetPasswordQualityRequirementsRequestValue ::= SEQUENCE { 082 * target CHOICE { 083 * addWithDefaultPasswordPolicy [0] NULL, 084 * addWithSpecifiedPasswordPolicy [1] LDAPDN, 085 * selfChangeForAuthorizationIdentity [2] NULL, 086 * selfChangeForSpecifiedUser [3] LDAPDN, 087 * administrativeResetForUser [4] LDAPDN, 088 * ... }, 089 * ... } 090 * </PRE> 091 */ 092@NotMutable() 093@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE) 094public final class GetPasswordQualityRequirementsExtendedRequest 095 extends ExtendedRequest 096{ 097 /** 098 * The OID (1.3.6.1.4.1.30221.2.6.43) for the get password quality 099 * requirements extended request. 100 */ 101 public static final String OID_GET_PASSWORD_QUALITY_REQUIREMENTS_REQUEST = 102 "1.3.6.1.4.1.30221.2.6.43"; 103 104 105 106 /** 107 * The serial version UID for this serializable class. 108 */ 109 private static final long serialVersionUID = -3652010872400265557L; 110 111 112 113 // The target type for this get password quality requirements extended 114 // request. 115 private final GetPasswordQualityRequirementsTargetType targetType; 116 117 // The target DN for this get password quality requirements extended request. 118 private final String targetDN; 119 120 121 122 /** 123 * Creates a new get password quality requirements extended request with the 124 * provided information. 125 * 126 * @param targetType The target type for this request. It must not be 127 * {@code null}. 128 * @param targetDN The target DN for this request. It may be {@code null} 129 * if no target DN is required for the specified target 130 * type. 131 * @param controls The set of controls to include in the request. It may 132 * be {@code null} or empty if no controls should be 133 * included. 134 */ 135 private GetPasswordQualityRequirementsExtendedRequest( 136 final GetPasswordQualityRequirementsTargetType targetType, 137 final String targetDN, 138 final Control... controls) 139 { 140 super(OID_GET_PASSWORD_QUALITY_REQUIREMENTS_REQUEST, 141 encodeValue(targetType, targetDN), controls); 142 143 this.targetType = targetType; 144 this.targetDN = targetDN; 145 } 146 147 148 149 /** 150 * Creates a new get password quality requirements extended request decoded 151 * from the provided generic extended request. 152 * 153 * @param r The extended request to decode as a get password quality 154 * requirements request. 155 * 156 * @throws LDAPException If a problem is encountered while attempting to 157 * decoded the provided extended request as a 158 * get password quality requirements request. 159 */ 160 public GetPasswordQualityRequirementsExtendedRequest(final ExtendedRequest r) 161 throws LDAPException 162 { 163 super(r); 164 165 final ASN1OctetString value = r.getValue(); 166 if (value == null) 167 { 168 throw new LDAPException(ResultCode.DECODING_ERROR, 169 ERR_GET_PW_QUALITY_REQS_REQUEST_NO_VALUE.get()); 170 } 171 172 try 173 { 174 final ASN1Element[] elements = 175 ASN1Sequence.decodeAsSequence(value.getValue()).elements(); 176 177 targetType = GetPasswordQualityRequirementsTargetType.forBERType( 178 elements[0].getType()); 179 if (targetType == null) 180 { 181 throw new LDAPException(ResultCode.DECODING_ERROR, 182 ERR_GET_PW_QUALITY_REQS_REQUEST_UNKNOWN_TARGET_TYPE.get( 183 StaticUtils.toHex(elements[0].getType()))); 184 } 185 186 switch (targetType) 187 { 188 case ADD_WITH_SPECIFIED_PASSWORD_POLICY: 189 case SELF_CHANGE_FOR_SPECIFIED_USER: 190 case ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER: 191 targetDN = ASN1OctetString.decodeAsOctetString( 192 elements[0]).stringValue(); 193 break; 194 195 case ADD_WITH_DEFAULT_PASSWORD_POLICY: 196 case SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY: 197 default: 198 targetDN = null; 199 break; 200 } 201 } 202 catch (final LDAPException le) 203 { 204 Debug.debugException(le); 205 throw le; 206 } 207 catch (final Exception e) 208 { 209 Debug.debugException(e); 210 throw new LDAPException(ResultCode.DECODING_ERROR, 211 ERR_GET_PW_QUALITY_REQS_REQUEST_CANNOT_DECODE.get( 212 StaticUtils.getExceptionMessage(e)), 213 e); 214 } 215 } 216 217 218 219 /** 220 * Encodes the provided information into an ASN.1 octet string suitable for 221 * use as the value of this extended request. 222 * 223 * @param targetType The target type for this request. It must not be 224 * {@code null}. 225 * @param targetDN The target DN for this request. It may be {@code null} 226 * if no target DN is required for the specified target 227 * type. 228 * 229 * @return The ASN.1 octet string containing the encoded request value. 230 */ 231 private static ASN1OctetString encodeValue( 232 final GetPasswordQualityRequirementsTargetType targetType, 233 final String targetDN) 234 { 235 final ASN1Element targetElement; 236 switch (targetType) 237 { 238 case ADD_WITH_SPECIFIED_PASSWORD_POLICY: 239 case SELF_CHANGE_FOR_SPECIFIED_USER: 240 case ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER: 241 targetElement = new ASN1OctetString(targetType.getBERType(), targetDN); 242 break; 243 244 case ADD_WITH_DEFAULT_PASSWORD_POLICY: 245 case SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY: 246 default: 247 targetElement = new ASN1Null(targetType.getBERType()); 248 break; 249 } 250 251 final ASN1Sequence valueSequence = new ASN1Sequence( 252 targetElement); 253 254 return new ASN1OctetString(valueSequence.encode()); 255 } 256 257 258 259 /** 260 * Creates a new get password quality requirements extended request that will 261 * retrieve the password requirements for an add operation governed by the 262 * server's default password policy. 263 * 264 * @param controls The set of controls to include in the request. It may be 265 * {@code null} or empty if no controls should be included 266 * in the request. 267 * 268 * @return A new get password quality requirements extended request that will 269 * retrieve the password requirements for an add operation governed 270 * by the server's default password policy. 271 */ 272 public static GetPasswordQualityRequirementsExtendedRequest 273 createAddWithDefaultPasswordPolicyRequest( 274 final Control... controls) 275 { 276 return new GetPasswordQualityRequirementsExtendedRequest( 277 GetPasswordQualityRequirementsTargetType. 278 ADD_WITH_DEFAULT_PASSWORD_POLICY, 279 null, controls); 280 } 281 282 283 284 /** 285 * Creates a new get password quality requirements extended request that will 286 * retrieve the password requirements for an add operation governed by the 287 * specified password policy. 288 * 289 * @param policyDN The DN of the entry that defines the password policy from 290 * which to determine the password quality requirements. 291 * @param controls The set of controls to include in the request. It may be 292 * {@code null} or empty if no controls should be included 293 * in the request. 294 * 295 * @return A new get password quality requirements extended request that will 296 * retrieve the password requirements for an add operation governed 297 * by the specified password policy. 298 */ 299 public static GetPasswordQualityRequirementsExtendedRequest 300 createAddWithSpecifiedPasswordPolicyRequest( 301 final String policyDN, final Control... controls) 302 { 303 return new GetPasswordQualityRequirementsExtendedRequest( 304 GetPasswordQualityRequirementsTargetType. 305 ADD_WITH_SPECIFIED_PASSWORD_POLICY, 306 policyDN, controls); 307 } 308 309 310 311 /** 312 * Creates a new get password quality requirements extended request that will 313 * retrieve the password requirements for a self change requested with the 314 * same authorization identity as this extended request. 315 * 316 * @param controls The set of controls to include in the request. It may be 317 * {@code null} or empty if no controls should be included 318 * in the request. 319 * 320 * @return A new get password quality requirements extended request that will 321 * retrieve the password requirements for a self change requested 322 * with the same authorization identity as this extended request. 323 */ 324 public static GetPasswordQualityRequirementsExtendedRequest 325 createSelfChangeWithSameAuthorizationIdentityRequest( 326 final Control... controls) 327 { 328 return new GetPasswordQualityRequirementsExtendedRequest( 329 GetPasswordQualityRequirementsTargetType. 330 SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY, 331 null, controls); 332 } 333 334 335 336 /** 337 * Creates a new get password quality requirements extended request that will 338 * retrieve the password requirements for a self change requested by the 339 * specified user. 340 * 341 * @param userDN The DN of the user for whom to retrieve the self change 342 * password requirements. 343 * @param controls The set of controls to include in the request. It may be 344 * {@code null} or empty if no controls should be included 345 * in the request. 346 * 347 * @return A new get password quality requirements extended request that will 348 * retrieve the password requirements for a self change requested by 349 * the specified user. 350 */ 351 public static GetPasswordQualityRequirementsExtendedRequest 352 createSelfChangeForSpecifiedUserRequest( 353 final String userDN, final Control... controls) 354 { 355 return new GetPasswordQualityRequirementsExtendedRequest( 356 GetPasswordQualityRequirementsTargetType. 357 SELF_CHANGE_FOR_SPECIFIED_USER, 358 userDN, controls); 359 } 360 361 362 363 /** 364 * Creates a new get password quality requirements extended request that will 365 * retrieve the password requirements for an administrative reset targeting 366 * the specified user. 367 * 368 * @param userDN The DN of the user for whom to retrieve the 369 * administrative reset password requirements. 370 * @param controls The set of controls to include in the request. It may be 371 * {@code null} or empty if no controls should be included 372 * in the request. 373 * 374 * @return A new get password quality requirements extended request that will 375 * retrieve the password requirements for an administrative reset 376 * targeting the specified user. 377 */ 378 public static GetPasswordQualityRequirementsExtendedRequest 379 createAdministrativeResetForSpecifiedUserRequest( 380 final String userDN, final Control... controls) 381 { 382 return new GetPasswordQualityRequirementsExtendedRequest( 383 GetPasswordQualityRequirementsTargetType. 384 ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER, 385 userDN, controls); 386 } 387 388 389 390 /** 391 * Retrieves the target type for this get password quality requirements 392 * request. 393 * 394 * @return The target type for this get password quality requirements 395 * request. 396 */ 397 public GetPasswordQualityRequirementsTargetType getTargetType() 398 { 399 return targetType; 400 } 401 402 403 404 /** 405 * Retrieves the target DN for this get password quality requirements request. 406 * For a request with a target type of 407 * {@code ADD_WITH_SPECIFIED_PASSWORD_POLICY}, this will be the DN of the 408 * password policy from which to obtain the password quality requirements. 409 * For a request with a target type of either 410 * {@code SELF_CHANGE_FOR_SPECIFIED_USER} or 411 * {@code ADMINISTRATIVE_RESET_FOR_SPECIFIED_USER}, this will be the DN of the 412 * user for which to obtain the password quality requirements. For a request 413 * with a target type of either {@code ADD_WITH_DEFAULT_PASSWORD_POLICY} or 414 * {@code SELF_CHANGE_FOR_AUTHORIZATION_IDENTITY}, no target DN is required 415 * and the value returned will be {@code null}. 416 * 417 * @return The target DN for this get password quality requirements request. 418 */ 419 public String getTargetDN() 420 { 421 return targetDN; 422 } 423 424 425 426 /** 427 * {@inheritDoc} 428 */ 429 @Override() 430 public GetPasswordQualityRequirementsExtendedResult process( 431 final LDAPConnection connection, final int depth) 432 throws LDAPException 433 { 434 final ExtendedResult result = super.process(connection, depth); 435 return new GetPasswordQualityRequirementsExtendedResult(result); 436 } 437 438 439 440 /** 441 * {@inheritDoc} 442 */ 443 @Override() 444 public GetPasswordQualityRequirementsExtendedRequest duplicate() 445 { 446 return duplicate(getControls()); 447 } 448 449 450 451 /** 452 * {@inheritDoc} 453 */ 454 @Override() 455 public GetPasswordQualityRequirementsExtendedRequest duplicate( 456 final Control[] controls) 457 { 458 final GetPasswordQualityRequirementsExtendedRequest r = 459 new GetPasswordQualityRequirementsExtendedRequest(targetType, 460 targetDN, controls); 461 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 462 return r; 463 } 464 465 466 467 /** 468 * {@inheritDoc} 469 */ 470 @Override() 471 public String getExtendedRequestName() 472 { 473 return INFO_EXTENDED_REQUEST_NAME_GET_PW_QUALITY_REQS.get(); 474 } 475 476 477 478 /** 479 * {@inheritDoc} 480 */ 481 @Override() 482 public void toString(final StringBuilder buffer) 483 { 484 buffer.append("GetPasswordQualityRequirementsExtendedRequest(targetType="); 485 buffer.append(targetType.name()); 486 487 if (targetDN != null) 488 { 489 buffer.append(", targetDN='"); 490 buffer.append(targetDN); 491 buffer.append('\''); 492 } 493 494 final Control[] controls = getControls(); 495 if (controls.length > 0) 496 { 497 buffer.append(", controls={"); 498 for (int i=0; i < controls.length; i++) 499 { 500 if (i > 0) 501 { 502 buffer.append(", "); 503 } 504 505 buffer.append(controls[i]); 506 } 507 buffer.append('}'); 508 } 509 510 buffer.append(')'); 511 } 512}