001/* 002 * Licensed to the Apache Software Foundation (ASF) under one 003 * or more contributor license agreements. See the NOTICE file 004 * distributed with this work for additional information 005 * regarding copyright ownership. The ASF licenses this file 006 * to you under the Apache License, Version 2.0 (the 007 * "License"); you may not use this file except in compliance 008 * with the License. You may obtain a copy of the License at 009 * 010 * http://www.apache.org/licenses/LICENSE-2.0 011 * 012 * Unless required by applicable law or agreed to in writing, 013 * software distributed under the License is distributed on an 014 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 015 * KIND, either express or implied. See the License for the 016 * specific language governing permissions and limitations 017 * under the License. 018 * 019 */ 020package org.apache.directory.shared.ldap.extras.controls.ppolicy; 021 022 023import java.nio.ByteBuffer; 024 025import org.apache.directory.shared.asn1.Asn1Object; 026import org.apache.directory.shared.asn1.DecoderException; 027import org.apache.directory.shared.asn1.EncoderException; 028import org.apache.directory.shared.asn1.ber.Asn1Decoder; 029import org.apache.directory.shared.asn1.ber.tlv.TLV; 030import org.apache.directory.shared.asn1.ber.tlv.UniversalTag; 031import org.apache.directory.shared.asn1.ber.tlv.Value; 032import org.apache.directory.shared.i18n.I18n; 033import org.apache.directory.shared.ldap.codec.api.ControlDecorator; 034import org.apache.directory.shared.ldap.codec.api.LdapApiService; 035 036 037/** 038 * PasswordPolicy decorator. 039 * 040 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 041 */ 042public class PasswordPolicyDecorator extends ControlDecorator<PasswordPolicy> implements PasswordPolicy 043{ 044 /** An instance of this decoder */ 045 private static final Asn1Decoder decoder = new Asn1Decoder(); 046 047 // Storage for computed lengths 048 private int valueLength = 0; 049 private int ppolicySeqLength = 0; 050 private int warningLength = 0; 051 private int timeBeforeExpirationTagLength; 052 private int graceAuthNsRemainingTagLength; 053 054 055 public PasswordPolicyDecorator( LdapApiService codec ) 056 { 057 super( codec, new PasswordPolicyImpl() ); 058 } 059 060 061 public PasswordPolicyDecorator( LdapApiService codec, boolean hasResponse ) 062 { 063 super( codec, new PasswordPolicyImpl( hasResponse ) ); 064 } 065 066 067 public PasswordPolicyDecorator( LdapApiService codec, PasswordPolicy policy ) 068 { 069 super( codec, policy ); 070 } 071 072 073 /** 074 * {@inheritDoc} 075 */ 076 @Override 077 public void setValue( byte[] value ) 078 { 079 if ( value == null || value.length == 0 ) 080 { 081 setResponse( null ); 082 } 083 084 if ( value != null && ! hasResponse() ) 085 { 086 setResponse( true ); 087 } 088 089 super.setValue( value ); 090 } 091 092 093 @Override 094 public int computeLength() 095 { 096 // reset the length values 097 valueLength = 0; 098 ppolicySeqLength = 0; 099 warningLength = 0; 100 timeBeforeExpirationTagLength = 0; 101 graceAuthNsRemainingTagLength = 0; 102 103 if ( ! hasResponse() ) 104 { 105 return 0; 106 } 107 108 if ( getResponse().getTimeBeforeExpiration() >= 0 ) 109 { 110 timeBeforeExpirationTagLength = TLV.getNbBytes( getResponse().getTimeBeforeExpiration() ); 111 warningLength = 1 + TLV.getNbBytes( timeBeforeExpirationTagLength ) + timeBeforeExpirationTagLength; 112 } 113 else if ( getResponse().getGraceAuthNsRemaining() >= 0 ) 114 { 115 graceAuthNsRemainingTagLength = TLV.getNbBytes( getResponse().getGraceAuthNsRemaining() ); 116 warningLength = 1 + TLV.getNbBytes( graceAuthNsRemainingTagLength ) + graceAuthNsRemainingTagLength; 117 } 118 119 if ( warningLength != 0 ) 120 { 121 ppolicySeqLength = 1 + TLV.getNbBytes( warningLength ) + warningLength; 122 } 123 124 if ( getResponse().getPasswordPolicyError() != null ) 125 { 126 ppolicySeqLength += 1 + 1 + 1; 127 } 128 129 if ( ppolicySeqLength > 0 ) 130 { 131 valueLength = 1 + TLV.getNbBytes( ppolicySeqLength ) + ppolicySeqLength; 132 } 133 134 return valueLength; 135 } 136 137 138 @Override 139 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 140 { 141 if ( ! hasResponse() ) 142 { 143 return buffer; 144 } 145 146 if ( buffer == null ) 147 { 148 throw new EncoderException( I18n.err( I18n.ERR_04023 ) ); 149 } 150 151 if ( ( getResponse().getTimeBeforeExpiration() < 0 ) && ( getResponse().getGraceAuthNsRemaining() < 0 ) && ( 152 getResponse().getPasswordPolicyError() == null ) ) 153 { 154 return buffer; 155 } 156 else 157 { 158 // Encode the Sequence tag 159 buffer.put( UniversalTag.SEQUENCE.getValue() ); 160 buffer.put( TLV.getBytes( ppolicySeqLength ) ); 161 162 if ( warningLength > 0 ) 163 { 164 // Encode the Warning tag 165 buffer.put( ( byte )PasswordPolicyTags.PPOLICY_WARNING_TAG.getValue() ); 166 buffer.put( TLV.getBytes( warningLength ) ); 167 168 if ( getResponse().getTimeBeforeExpiration() >= 0 ) 169 { 170 buffer.put( ( byte ) PasswordPolicyTags.TIME_BEFORE_EXPIRATION_TAG.getValue() ); 171 buffer.put( TLV.getBytes( timeBeforeExpirationTagLength ) ); 172 buffer.put( Value.getBytes( getResponse().getTimeBeforeExpiration() ) ); 173 } 174 else if ( getResponse().getGraceAuthNsRemaining() >= 0 ) 175 { 176 buffer.put( ( byte ) PasswordPolicyTags.GRACE_AUTHNS_REMAINING_TAG.getValue() ); 177 buffer.put( TLV.getBytes( graceAuthNsRemainingTagLength ) ); 178 buffer.put( Value.getBytes( getResponse().getGraceAuthNsRemaining() ) ); 179 } 180 } 181 182 if ( getResponse().getPasswordPolicyError() != null ) 183 { 184 buffer.put( (byte)PasswordPolicyTags.PPOLICY_ERROR_TAG.getValue() ); 185 buffer.put( ( byte ) 0x01 ); 186 buffer.put( Value.getBytes( getResponse().getPasswordPolicyError().getValue() ) ); 187 } 188 } 189 190 return buffer; 191 } 192 193 194 @Override 195 public String toString() 196 { 197 StringBuilder sb = new StringBuilder(); 198 199 sb.append( " PasswordPolicyResponse control :\n" ); 200 sb.append( " oid : '" ).append( getOid() ).append( '\n' ); 201 202 if ( hasResponse() && getResponse().getTimeBeforeExpiration() >= 0 ) 203 { 204 sb.append( " timeBeforeExpiration : '" ).append( getResponse().getTimeBeforeExpiration() ).append( '\n' ); 205 } 206 else if ( hasResponse() && getResponse().getGraceAuthNsRemaining() >= 0 ) 207 { 208 sb.append( " graceAuthNsRemaining : '" ).append( getResponse().getGraceAuthNsRemaining() ).append( '\n' ); 209 } 210 211 if ( hasResponse() && getResponse().getPasswordPolicyError() != null ) 212 { 213 sb.append( " ppolicyError : '" ).append( getResponse().getPasswordPolicyError().toString() ).append( '\n' ); 214 } 215 216 return sb.toString(); 217 } 218 219 220 /** 221 * {@inheritDoc} 222 */ 223 public Asn1Object decode( byte[] controlBytes ) throws DecoderException 224 { 225 if ( ! hasResponse() ) 226 { 227 return this; 228 } 229 230 ByteBuffer bb = ByteBuffer.wrap( controlBytes ); 231 PasswordPolicyContainer container = new PasswordPolicyContainer( getCodecService(), this ); 232 decoder.decode( bb, container ); 233 return this; 234 } 235 236 237 /** 238 * 239 * {@inheritDoc} 240 */ 241 public boolean hasResponse() 242 { 243 return getDecorated().hasResponse(); 244 } 245 246 247 /** 248 * 249 * {@inheritDoc} 250 */ 251 public void setResponse( PasswordPolicyResponse response ) 252 { 253 getDecorated().setResponse( response ); 254 } 255 256 257 /** 258 * 259 * {@inheritDoc} 260 */ 261 public PasswordPolicyResponse setResponse( boolean hasResponse ) 262 { 263 return getDecorated().setResponse( hasResponse ); 264 } 265 266 267 /** 268 * 269 * {@inheritDoc} 270 */ 271 public PasswordPolicyResponse getResponse() 272 { 273 return getDecorated().getResponse(); 274 } 275}