001/*
002 * Copyright 2007-2020 Ping Identity Corporation
003 * All Rights Reserved.
004 */
005/*
006 * Copyright 2007-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) 2008-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.controls;
037
038
039
040import com.unboundid.asn1.ASN1OctetString;
041import com.unboundid.ldap.sdk.Control;
042import com.unboundid.ldap.sdk.DecodeableControl;
043import com.unboundid.ldap.sdk.LDAPException;
044import com.unboundid.ldap.sdk.LDAPResult;
045import com.unboundid.ldap.sdk.ResultCode;
046import com.unboundid.util.Debug;
047import com.unboundid.util.NotMutable;
048import com.unboundid.util.ThreadSafety;
049import com.unboundid.util.ThreadSafetyLevel;
050
051import static com.unboundid.ldap.sdk.controls.ControlMessages.*;
052
053
054
055/**
056 * This class provides an implementation of the expiring expiring control as
057 * described in draft-vchu-ldap-pwd-policy.  It may be used to indicate that the
058 * authenticated user's password will expire in the near future.  The value of
059 * this control includes the length of time in seconds until the user's
060 * password actually expires.
061 * <BR><BR>
062 * No request control is required to trigger the server to send the password
063 * expiring response control.  If the server supports the use of this control
064 * and the user's password will expire within a time frame that the server
065 * considers to be the near future, then it will be included in the bind
066 * response returned to the client.
067 * <BR><BR>
068 * See the documentation for the {@link PasswordExpiredControl} to see an
069 * example that demonstrates the use of both the password expiring and password
070 * expired controls.
071 */
072@NotMutable()
073@ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
074public final class PasswordExpiringControl
075       extends Control
076       implements DecodeableControl
077{
078  /**
079   * The OID (2.16.840.1.113730.3.4.5) for the password expiring response
080   * control.
081   */
082  public static final String PASSWORD_EXPIRING_OID = "2.16.840.1.113730.3.4.5";
083
084
085
086  /**
087   * The serial version UID for this serializable class.
088   */
089  private static final long serialVersionUID = 1250220480854441338L;
090
091
092
093  // The length of time in seconds until the password expires.
094  private final int secondsUntilExpiration;
095
096
097
098  /**
099   * Creates a new empty control instance that is intended to be used only for
100   * decoding controls via the {@code DecodeableControl} interface.
101   */
102  PasswordExpiringControl()
103  {
104    secondsUntilExpiration = -1;
105  }
106
107
108
109  /**
110   * Creates a new password expiring control with the provided information.
111   *
112   * @param  secondsUntilExpiration  The length of time in seconds until the
113   *                                 password expires.
114   */
115  public PasswordExpiringControl(final int secondsUntilExpiration)
116  {
117    super(PASSWORD_EXPIRING_OID, false,
118          new ASN1OctetString(String.valueOf(secondsUntilExpiration)));
119
120    this.secondsUntilExpiration = secondsUntilExpiration;
121  }
122
123
124
125  /**
126   * Creates a new password expiring control with the provided information.
127   *
128   * @param  oid         The OID for the control.
129   * @param  isCritical  Indicates whether the control should be marked
130   *                     critical.
131   * @param  value       The encoded value for the control.  This may be
132   *                     {@code null} if no value was provided.
133   *
134   * @throws  LDAPException  If the provided control cannot be decoded as a
135   *                         password expiring response control.
136   */
137  public PasswordExpiringControl(final String oid, final boolean isCritical,
138                                 final ASN1OctetString value)
139         throws LDAPException
140  {
141    super(oid, isCritical, value);
142
143    if (value == null)
144    {
145      throw new LDAPException(ResultCode.DECODING_ERROR,
146                              ERR_PW_EXPIRING_NO_VALUE.get());
147    }
148
149    try
150    {
151      secondsUntilExpiration = Integer.parseInt(value.stringValue());
152    }
153    catch (final NumberFormatException nfe)
154    {
155      Debug.debugException(nfe);
156      throw new LDAPException(ResultCode.DECODING_ERROR,
157                              ERR_PW_EXPIRING_VALUE_NOT_INTEGER.get(), nfe);
158    }
159  }
160
161
162
163  /**
164   * {@inheritDoc}
165   */
166  @Override()
167  public PasswordExpiringControl
168              decodeControl(final String oid, final boolean isCritical,
169                            final ASN1OctetString value)
170         throws LDAPException
171  {
172    return new PasswordExpiringControl(oid, isCritical, value);
173  }
174
175
176
177  /**
178   * Extracts a password expiring control from the provided result.
179   *
180   * @param  result  The result from which to retrieve the password expiring
181   *                 control.
182   *
183   * @return  The password expiring control contained in the provided result, or
184   *          {@code null} if the result did not contain a password expiring
185   *          control.
186   *
187   * @throws  LDAPException  If a problem is encountered while attempting to
188   *                         decode the password expiring control contained in
189   *                         the provided result.
190   */
191  public static PasswordExpiringControl get(final LDAPResult result)
192         throws LDAPException
193  {
194    final Control c = result.getResponseControl(PASSWORD_EXPIRING_OID);
195    if (c == null)
196    {
197      return null;
198    }
199
200    if (c instanceof PasswordExpiringControl)
201    {
202      return (PasswordExpiringControl) c;
203    }
204    else
205    {
206      return new PasswordExpiringControl(c.getOID(), c.isCritical(),
207           c.getValue());
208    }
209  }
210
211
212
213  /**
214   * Retrieves the length of time in seconds until the password expires.
215   *
216   * @return  The length of time in seconds until the password expires.
217   */
218  public int getSecondsUntilExpiration()
219  {
220    return secondsUntilExpiration;
221  }
222
223
224
225  /**
226   * {@inheritDoc}
227   */
228  @Override()
229  public String getControlName()
230  {
231    return INFO_CONTROL_NAME_PW_EXPIRING.get();
232  }
233
234
235
236  /**
237   * {@inheritDoc}
238   */
239  @Override()
240  public void toString(final StringBuilder buffer)
241  {
242    buffer.append("PasswordExpiringControl(secondsUntilExpiration=");
243    buffer.append(secondsUntilExpiration);
244    buffer.append(", isCritical=");
245    buffer.append(isCritical());
246    buffer.append(')');
247  }
248}