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