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 * <H2>Example</H2> 062 * The following example demonstrates the use of the password policy state 063 * extended operation to administratively disable a user's account: 064 * <PRE> 065 * PasswordPolicyStateOperation disableOp = 066 * PasswordPolicyStateOperation.createSetAccountDisabledStateOperation( 067 * true); 068 * PasswordPolicyStateExtendedRequest pwpStateRequest = 069 * new PasswordPolicyStateExtendedRequest( 070 * "uid=john.doe,ou=People,dc=example,dc=com", disableOp); 071 * PasswordPolicyStateExtendedResult pwpStateResult = 072 * (PasswordPolicyStateExtendedResult) 073 * connection.processExtendedOperation(pwpStateRequest); 074 * 075 * // NOTE: The processExtendedOperation method will generally only throw an 076 * // exception if a problem occurs while trying to send the request or read 077 * // the response. It will not throw an exception because of a non-success 078 * // response. 079 * 080 * if (pwpStateResult.getResultCode() == ResultCode.SUCCESS) 081 * { 082 * boolean isDisabled = pwpStateResult.getBooleanValue( 083 * PasswordPolicyStateOperation.OP_TYPE_GET_ACCOUNT_DISABLED_STATE); 084 * if (isDisabled) 085 * { 086 * // The user account has been disabled. 087 * } 088 * else 089 * { 090 * // The user account is not disabled. 091 * } 092 * } 093 * </PRE> 094 */ 095@NotMutable() 096@ThreadSafety(level=ThreadSafetyLevel.NOT_THREADSAFE) 097public final class PasswordPolicyStateExtendedRequest 098 extends ExtendedRequest 099{ 100 /** 101 * The OID (1.3.6.1.4.1.30221.1.6.1) for the password policy state extended 102 * request. 103 */ 104 public static final String PASSWORD_POLICY_STATE_REQUEST_OID = 105 "1.3.6.1.4.1.30221.1.6.1"; 106 107 108 109 /** 110 * The serial version UID for this serializable class. 111 */ 112 private static final long serialVersionUID = -1644137695182620213L; 113 114 115 116 // The set of password policy state operations to process. 117 private final PasswordPolicyStateOperation[] operations; 118 119 // The DN of the user account on which to operate. 120 private final String userDN; 121 122 123 124 /** 125 * Creates a new password policy state extended request with the provided user 126 * DN and optional set of operations. 127 * 128 * @param userDN The DN of the user account on which to operate. 129 * @param operations The set of password policy state operations to process. 130 * If no operations are provided, then the effect will be 131 * to retrieve the values of all available password policy 132 * state properties. 133 */ 134 public PasswordPolicyStateExtendedRequest(final String userDN, 135 final PasswordPolicyStateOperation... operations) 136 { 137 this(userDN, null, operations); 138 } 139 140 141 142 /** 143 * Creates a new password policy state extended request with the provided user 144 * DN, optional set of operations, and optional set of controls. 145 * 146 * @param userDN The DN of the user account on which to operate. 147 * @param controls The set of controls to include in the request. 148 * @param operations The set of password policy state operations to process. 149 * If no operations are provided, then the effect will be 150 * to retrieve the values of all available password policy 151 * state properties. 152 */ 153 public PasswordPolicyStateExtendedRequest(final String userDN, 154 final Control[] controls, 155 final PasswordPolicyStateOperation... operations) 156 { 157 super(PASSWORD_POLICY_STATE_REQUEST_OID, encodeValue(userDN, operations), 158 controls); 159 160 this.userDN = userDN; 161 this.operations = operations; 162 } 163 164 165 166 /** 167 * Creates a new password policy state extended request from the provided 168 * generic extended request. 169 * 170 * @param extendedRequest The generic extended request to use to create this 171 * password policy state extended request. 172 * 173 * @throws LDAPException If a problem occurs while decoding the request. 174 */ 175 public PasswordPolicyStateExtendedRequest( 176 final ExtendedRequest extendedRequest) 177 throws LDAPException 178 { 179 super(extendedRequest); 180 181 final ASN1OctetString value = extendedRequest.getValue(); 182 if (value == null) 183 { 184 throw new LDAPException(ResultCode.DECODING_ERROR, 185 ERR_PWP_STATE_REQUEST_NO_VALUE.get()); 186 } 187 188 final ASN1Element[] elements; 189 try 190 { 191 final ASN1Element valueElement = ASN1Element.decode(value.getValue()); 192 elements = ASN1Sequence.decodeAsSequence(valueElement).elements(); 193 } 194 catch (final Exception e) 195 { 196 debugException(e); 197 throw new LDAPException(ResultCode.DECODING_ERROR, 198 ERR_PWP_STATE_REQUEST_VALUE_NOT_SEQUENCE.get(e), 199 e); 200 } 201 202 if ((elements.length < 1) || (elements.length > 2)) 203 { 204 throw new LDAPException(ResultCode.DECODING_ERROR, 205 ERR_PWP_STATE_REQUEST_INVALID_ELEMENT_COUNT.get( 206 elements.length)); 207 } 208 209 userDN = ASN1OctetString.decodeAsOctetString(elements[0]).stringValue(); 210 211 if (elements.length == 1) 212 { 213 operations = new PasswordPolicyStateOperation[0]; 214 } 215 else 216 { 217 try 218 { 219 final ASN1Element[] opElements = 220 ASN1Sequence.decodeAsSequence(elements[1]).elements(); 221 operations = new PasswordPolicyStateOperation[opElements.length]; 222 for (int i=0; i < opElements.length; i++) 223 { 224 operations[i] = PasswordPolicyStateOperation.decode(opElements[i]); 225 } 226 } 227 catch (final Exception e) 228 { 229 debugException(e); 230 throw new LDAPException(ResultCode.DECODING_ERROR, 231 ERR_PWP_STATE_REQUEST_CANNOT_DECODE_OPS.get(e), 232 e); 233 } 234 } 235 } 236 237 238 239 /** 240 * Encodes the provided information into an ASN.1 octet string that may be 241 * used as the value for this extended request. 242 * 243 * @param userDN The DN of the user account on which to operate. 244 * @param operations The set of operations to be processed. 245 * 246 * @return An ASN.1 octet string containing the encoded value. 247 */ 248 private static ASN1OctetString encodeValue(final String userDN, 249 final PasswordPolicyStateOperation[] operations) 250 { 251 final ASN1Element[] elements; 252 if ((operations == null) || (operations.length == 0)) 253 { 254 elements = new ASN1Element[] 255 { 256 new ASN1OctetString(userDN) 257 }; 258 } 259 else 260 { 261 final ASN1Element[] opElements = new ASN1Element[operations.length]; 262 for (int i=0; i < operations.length; i++) 263 { 264 opElements[i] = operations[i].encode(); 265 } 266 267 elements = new ASN1Element[] 268 { 269 new ASN1OctetString(userDN), 270 new ASN1Sequence(opElements) 271 }; 272 } 273 274 return new ASN1OctetString(new ASN1Sequence(elements).encode()); 275 } 276 277 278 279 /** 280 * Retrieves the DN of the user account on which to operate. 281 * 282 * @return The DN of the user account on which to operate. 283 */ 284 public String getUserDN() 285 { 286 return userDN; 287 } 288 289 290 291 /** 292 * Retrieves the set of password policy state operations to be processed. 293 * 294 * @return The set of password policy state operations to be processed, or 295 * an empty list if the values of all password policy state 296 * properties should be retrieved. 297 */ 298 public PasswordPolicyStateOperation[] getOperations() 299 { 300 return operations; 301 } 302 303 304 305 /** 306 * {@inheritDoc} 307 */ 308 @Override() 309 public PasswordPolicyStateExtendedResult 310 process(final LDAPConnection connection, final int depth) 311 throws LDAPException 312 { 313 final ExtendedResult extendedResponse = super.process(connection, depth); 314 return new PasswordPolicyStateExtendedResult(extendedResponse); 315 } 316 317 318 319 /** 320 * {@inheritDoc} 321 */ 322 @Override() 323 public PasswordPolicyStateExtendedRequest duplicate() 324 { 325 return duplicate(getControls()); 326 } 327 328 329 330 /** 331 * {@inheritDoc} 332 */ 333 @Override() 334 public PasswordPolicyStateExtendedRequest duplicate(final Control[] controls) 335 { 336 final PasswordPolicyStateExtendedRequest r = 337 new PasswordPolicyStateExtendedRequest(userDN, controls, operations); 338 r.setResponseTimeoutMillis(getResponseTimeoutMillis(null)); 339 return r; 340 } 341 342 343 344 /** 345 * {@inheritDoc} 346 */ 347 @Override() 348 public String getExtendedRequestName() 349 { 350 return INFO_EXTENDED_REQUEST_NAME_PW_POLICY_STATE.get(); 351 } 352 353 354 355 /** 356 * {@inheritDoc} 357 */ 358 @Override() 359 public void toString(final StringBuilder buffer) 360 { 361 buffer.append("PasswordPolicyStateExtendedRequest(userDN='"); 362 buffer.append(userDN); 363 364 if (operations.length > 0) 365 { 366 buffer.append("', operations={"); 367 for (int i=0; i < operations.length; i++) 368 { 369 if (i > 0) 370 { 371 buffer.append(", "); 372 } 373 374 operations[i].toString(buffer); 375 } 376 buffer.append('}'); 377 } 378 379 final Control[] controls = getControls(); 380 if (controls.length > 0) 381 { 382 buffer.append(", controls={"); 383 for (int i=0; i < controls.length; i++) 384 { 385 if (i > 0) 386 { 387 buffer.append(", "); 388 } 389 390 buffer.append(controls[i]); 391 } 392 buffer.append('}'); 393 } 394 395 buffer.append(')'); 396 } 397}