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.kerberos.components; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025import java.util.ArrayList; 026import java.util.List; 027 028import org.apache.directory.api.asn1.Asn1Object; 029import org.apache.directory.api.asn1.EncoderException; 030import org.apache.directory.api.asn1.ber.tlv.BerValue; 031import org.apache.directory.api.asn1.ber.tlv.TLV; 032import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 033import org.apache.directory.api.util.Strings; 034import org.apache.directory.server.i18n.I18n; 035import org.apache.directory.shared.kerberos.KerberosConstants; 036import org.apache.directory.shared.kerberos.KerberosTime; 037import org.apache.directory.shared.kerberos.codec.types.LastReqType; 038import org.slf4j.Logger; 039import org.slf4j.LoggerFactory; 040 041 042/** 043 * The LastReq structure. 044 * 045 * The ASN.1 grammar is : 046 * <pre> 047 * LastReq ::= SEQUENCE OF SEQUENCE { 048 * lr-type [0] Int32, 049 * lr-value [1] KerberosTime 050 * } 051 * </pre> 052 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 053 */ 054public class LastReq implements Asn1Object 055{ 056 /** The logger */ 057 private static final Logger LOG = LoggerFactory.getLogger( LastReq.class ); 058 059 /** Speedup for logs */ 060 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 061 062 /** The list of LastReq elements */ 063 private List<LastReqEntry> lastReqs = new ArrayList<>(); 064 065 /** The current LastReqEntry being processed */ 066 private LastReqEntry currentLR; 067 068 // Storage for computed lengths 069 private int lrTypeTagLen[]; 070 private int lrValueTagLen[]; 071 private int lastReqSeqLen[]; 072 private int lastReqSeqSeqLen; 073 074 075 /** 076 * Creates a new instance of LastReq. 077 */ 078 public LastReq() 079 { 080 } 081 082 083 /** 084 * @return the CurrentLr type 085 */ 086 public LastReqType getCurrentLrType() 087 { 088 return currentLR.getLrType(); 089 } 090 091 092 /** 093 * Set the CurrentLr type 094 */ 095 public void setCurrentLrType( LastReqType lrType ) 096 { 097 currentLR.setLrType( lrType ); 098 } 099 100 101 /** 102 * @return the CurrentLr value 103 */ 104 public KerberosTime getCurrentLrValue() 105 { 106 return currentLR.getLrValue(); 107 } 108 109 110 /** 111 * Set the CurrentLr value 112 */ 113 public void setCurrentLrValue( KerberosTime lrValue ) 114 { 115 currentLR.setLrValue( lrValue ); 116 } 117 118 119 /** 120 * @return the CurrentLR 121 */ 122 public LastReqEntry getCurrentLR() 123 { 124 return currentLR; 125 } 126 127 128 /** 129 * Create a new currentLR 130 */ 131 public void createNewLR() 132 { 133 currentLR = new LastReqEntry(); 134 lastReqs.add( currentLR ); 135 } 136 137 138 /** 139 * Add a new LastReqEntry 140 * @param lastReqEntry The enry to add 141 */ 142 public void addEntry( LastReqEntry lastReqEntry ) 143 { 144 lastReqs.add( lastReqEntry ); 145 } 146 147 148 /** 149 * @return the LastReqs 150 */ 151 public List<LastReqEntry> getLastReqs() 152 { 153 return lastReqs; 154 } 155 156 157 /** 158 * Compute the LastReq length 159 * 160 * <pre> 161 * LastReq : 162 * 163 * 0x30 L1 LastReq 164 * | 165 * +--> 0x30 L2 166 * | 167 * +--> 0xA0 L3 lr-type tag 168 * | | 169 * | +--> 0x02 L3-1 lrType (int) 170 * | 171 * +--> 0xA1 0x11 lr-value tag 172 * | 173 * +--> 0x18 0x0F ttt (KerberosString) 174 * </pre> 175 */ 176 public int computeLength() 177 { 178 int i = 0; 179 lastReqSeqLen = new int[lastReqs.size()]; 180 lrTypeTagLen = new int[lastReqs.size()]; 181 lrValueTagLen = new int[lastReqs.size()]; 182 lastReqSeqSeqLen = 0; 183 184 for ( LastReqEntry lre : lastReqs ) 185 { 186 int lrTypeLen = BerValue.getNbBytes( lre.getLrType().getValue() ); 187 lrTypeTagLen[i] = 1 + TLV.getNbBytes( lrTypeLen ) + lrTypeLen; 188 byte[] lrValyeBytes = lre.getLrValue().getBytes(); 189 lrValueTagLen[i] = 1 + TLV.getNbBytes( lrValyeBytes.length ) + lrValyeBytes.length; 190 191 lastReqSeqLen[i] = 1 + TLV.getNbBytes( lrTypeTagLen[i] ) + lrTypeTagLen[i] + 192 1 + TLV.getNbBytes( lrValueTagLen[i] ) + lrValueTagLen[i]; 193 194 lastReqSeqSeqLen += 1 + TLV.getNbBytes( lastReqSeqLen[i] ) + lastReqSeqLen[i]; 195 i++; 196 } 197 198 return 1 + TLV.getNbBytes( lastReqSeqSeqLen ) + lastReqSeqSeqLen; 199 } 200 201 202 /** 203 * Encode the LastReq message to a PDU. 204 * 205 * <pre> 206 * LastReq : 207 * 208 * 0x30 LL 209 * 0x30 LL 210 * 0xA0 LL 211 * 0x02 0x01 lrType 212 * 0xA1 0x11 213 * 0x18 0x0F lrValue 214 * </pre> 215 * 216 * @param buffer The buffer where to put the PDU. It should have been allocated 217 * before, with the right size. 218 * @return The constructed PDU. 219 */ 220 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 221 { 222 if ( buffer == null ) 223 { 224 throw new EncoderException( I18n.err( I18n.ERR_148 ) ); 225 } 226 227 try 228 { 229 // The lastRequest SEQ OF Tag 230 buffer.put( UniversalTag.SEQUENCE.getValue() ); 231 buffer.put( TLV.getBytes( lastReqSeqSeqLen ) ); 232 233 int i = 0; 234 235 for ( LastReqEntry lre : lastReqs ) 236 { 237 buffer.put( UniversalTag.SEQUENCE.getValue() ); 238 buffer.put( TLV.getBytes( lastReqSeqLen[i] ) ); 239 240 // the lrType 241 buffer.put( ( byte ) KerberosConstants.LAST_REQ_LR_TYPE_TAG ); 242 buffer.put( TLV.getBytes( lrTypeTagLen[i] ) ); 243 BerValue.encode( buffer, lre.getLrType().getValue() ); 244 245 // the lrValue tag 246 buffer.put( ( byte ) KerberosConstants.LAST_REQ_LR_VALUE_TAG ); 247 buffer.put( TLV.getBytes( lrValueTagLen[i] ) ); 248 249 // the lrValue value 250 buffer.put( UniversalTag.GENERALIZED_TIME.getValue() ); 251 buffer.put( ( byte ) 0x0F ); 252 buffer.put( lre.getLrValue().getBytes() ); 253 } 254 } 255 catch ( BufferOverflowException boe ) 256 { 257 LOG.error( I18n.err( I18n.ERR_139, 1 + TLV.getNbBytes( lastReqSeqSeqLen ) 258 + lastReqSeqSeqLen, buffer.capacity() ) ); 259 throw new EncoderException( I18n.err( I18n.ERR_138 ) , boe); 260 } 261 262 if ( IS_DEBUG ) 263 { 264 LOG.debug( "LastReq encoding : {}", Strings.dumpBytes( buffer.array() ) ); 265 LOG.debug( "LastReq initial value : {}", this ); 266 } 267 268 return buffer; 269 } 270 271 272 /** 273 * @see Object#toString() 274 */ 275 public String toString( String tabs ) 276 { 277 StringBuilder sb = new StringBuilder(); 278 279 sb.append( tabs ).append( "LastReq : \n" ); 280 281 for ( LastReqEntry lre : lastReqs ) 282 { 283 sb.append( lre.toString( tabs + " " ) ); 284 } 285 286 return sb.toString(); 287 } 288 289 290 /** 291 * @see Object#toString() 292 */ 293 public String toString() 294 { 295 return toString( "" ); 296 } 297}