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}