001 /*
002 * Copyright 2007-2013 UnboundID Corp.
003 * All Rights Reserved.
004 */
005 /*
006 * Copyright (C) 2008-2013 UnboundID Corp.
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 */
021 package com.unboundid.ldap.sdk.controls;
022
023
024
025 import com.unboundid.asn1.ASN1OctetString;
026 import com.unboundid.ldap.sdk.Control;
027 import com.unboundid.ldap.sdk.DecodeableControl;
028 import com.unboundid.ldap.sdk.LDAPException;
029 import com.unboundid.ldap.sdk.LDAPResult;
030 import com.unboundid.ldap.sdk.ResultCode;
031 import com.unboundid.util.NotMutable;
032 import com.unboundid.util.ThreadSafety;
033 import com.unboundid.util.ThreadSafetyLevel;
034
035 import static com.unboundid.ldap.sdk.controls.ControlMessages.*;
036 import static com.unboundid.util.Debug.*;
037
038
039
040 /**
041 * This class provides an implementation of the password expired control as
042 * described in draft-vchu-ldap-pwd-policy. It may be included in the response
043 * for an unsuccessful bind operation to indicate that the reason for the
044 * failure is that the target user's password has expired and must be reset
045 * before the user will be allowed to authenticate. Some servers may also
046 * include this control in a successful bind response to indicate that the
047 * authenticated user must change his or her password before being allowed to
048 * perform any other operation.
049 * <BR><BR>
050 * No request control is required to trigger the server to send the password
051 * expired response control. If the server supports the use of this control and
052 * the corresponding bind operation meets the criteria for this control to be
053 * included in the response, then it will be returned to the client.
054 * <BR><BR>
055 * <H2>Example</H2>
056 * The following example demonstrates a process that may be used to perform a
057 * simple bind to authenticate against the server and handle any password
058 * expired or password expiring control that may be included in the response:
059 * <PRE>
060 * BindRequest bindRequest =
061 * new SimpleBindRequest("uid=john.doe,ou=People,dc=example,dc=com",
062 * "password");
063 * try
064 * {
065 * BindResult bindResult = connection.bind(bindRequest);
066 * for (Control c : bindResult.getResponseControls())
067 * {
068 * if (c instanceof PasswordExpiringControl)
069 * {
070 * System.err.println("WARNING: Your password will expire in " +
071 * ((PasswordExpiringControl) c).getSecondsUntilExpiration() +
072 * " seconds.");
073 * }
074 * else if (c instanceof PasswordExpiredControl)
075 * {
076 * System.err.println("WARNING: You must change your password " +
077 * "before you will be allowed to perform any other operations.");
078 * }
079 * }
080 * }
081 * catch (LDAPException le)
082 * {
083 * for (Control c : le.getResponseControls())
084 * {
085 * if (c instanceof PasswordExpiredControl)
086 * {
087 * System.err.println("ERROR: Your password is expired.");
088 * }
089 * }
090 * }
091 * </PRE>
092 */
093 @NotMutable()
094 @ThreadSafety(level=ThreadSafetyLevel.COMPLETELY_THREADSAFE)
095 public final class PasswordExpiredControl
096 extends Control
097 implements DecodeableControl
098 {
099 /**
100 * The OID (2.16.840.1.113730.3.4.4) for the password expired response
101 * control.
102 */
103 public static final String PASSWORD_EXPIRED_OID = "2.16.840.1.113730.3.4.4";
104
105
106
107 /**
108 * The serial version UID for this serializable class.
109 */
110 private static final long serialVersionUID = -2731704592689892224L;
111
112
113
114 /**
115 * Creates a new password expired control.
116 */
117 public PasswordExpiredControl()
118 {
119 super(PASSWORD_EXPIRED_OID, false, new ASN1OctetString("0"));
120 }
121
122
123
124 /**
125 * Creates a new password expired control with the provided information.
126 *
127 * @param oid The OID for the control.
128 * @param isCritical Indicates whether the control should be marked
129 * critical.
130 * @param value The encoded value for the control. This may be
131 * {@code null} if no value was provided.
132 *
133 * @throws LDAPException If the provided control cannot be decoded as a
134 * password expired response control.
135 */
136 public PasswordExpiredControl(final String oid, final boolean isCritical,
137 final ASN1OctetString value)
138 throws LDAPException
139 {
140 super(oid, isCritical, value);
141
142 if (value == null)
143 {
144 throw new LDAPException(ResultCode.DECODING_ERROR,
145 ERR_PW_EXPIRED_NO_VALUE.get());
146 }
147
148 try
149 {
150 Integer.parseInt(value.stringValue());
151 }
152 catch (NumberFormatException nfe)
153 {
154 debugException(nfe);
155 throw new LDAPException(ResultCode.DECODING_ERROR,
156 ERR_PW_EXPIRED_VALUE_NOT_INTEGER.get(), nfe);
157 }
158 }
159
160
161
162 /**
163 * {@inheritDoc}
164 */
165 public PasswordExpiredControl
166 decodeControl(final String oid, final boolean isCritical,
167 final ASN1OctetString value)
168 throws LDAPException
169 {
170 return new PasswordExpiredControl(oid, isCritical, value);
171 }
172
173
174
175 /**
176 * Extracts a password expired control from the provided result.
177 *
178 * @param result The result from which to retrieve the password expired
179 * control.
180 *
181 * @return The password expired control contained in the provided result, or
182 * {@code null} if the result did not contain a password expired
183 * control.
184 *
185 * @throws LDAPException If a problem is encountered while attempting to
186 * decode the password expired control contained in
187 * the provided result.
188 */
189 public static PasswordExpiredControl get(final LDAPResult result)
190 throws LDAPException
191 {
192 final Control c = result.getResponseControl(PASSWORD_EXPIRED_OID);
193 if (c == null)
194 {
195 return null;
196 }
197
198 if (c instanceof PasswordExpiredControl)
199 {
200 return (PasswordExpiredControl) c;
201 }
202 else
203 {
204 return new PasswordExpiredControl(c.getOID(), c.isCritical(),
205 c.getValue());
206 }
207 }
208
209
210
211 /**
212 * {@inheritDoc}
213 */
214 @Override()
215 public String getControlName()
216 {
217 return INFO_CONTROL_NAME_PW_EXPIRED.get();
218 }
219
220
221
222 /**
223 * {@inheritDoc}
224 */
225 @Override()
226 public void toString(final StringBuilder buffer)
227 {
228 buffer.append("PasswordExpiredControl(isCritical=");
229 buffer.append(isCritical());
230 buffer.append(')');
231 }
232 }