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.messages; 021 022 023import java.nio.BufferOverflowException; 024import java.nio.ByteBuffer; 025 026import org.apache.directory.api.asn1.EncoderException; 027import org.apache.directory.api.asn1.ber.tlv.BerValue; 028import org.apache.directory.api.asn1.ber.tlv.TLV; 029import org.apache.directory.api.asn1.ber.tlv.UniversalTag; 030import org.apache.directory.api.util.Strings; 031import org.apache.directory.server.i18n.I18n; 032import org.apache.directory.shared.kerberos.KerberosConstants; 033import org.apache.directory.shared.kerberos.KerberosMessageType; 034import org.apache.directory.shared.kerberos.codec.options.ApOptions; 035import org.apache.directory.shared.kerberos.components.EncryptedData; 036import org.slf4j.Logger; 037import org.slf4j.LoggerFactory; 038 039 040/** 041 * AP-REQ message component . It will store the object described by the ASN.1 grammar : 042 * <pre> 043 * AP-REQ ::= [APPLICATION 14] SEQUENCE { 044 * pvno [0] INTEGER (5), 045 * msg-type [1] INTEGER (14), 046 * ap-options [2] APOptions, 047 * ticket [3] Ticket, 048 * authenticator [4] EncryptedData -- Authenticator 049 * } 050 * </pre> 051 * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a> 052 */ 053public class ApReq extends KerberosMessage 054{ 055 /** The logger */ 056 private static final Logger LOG = LoggerFactory.getLogger( ApReq.class ); 057 058 /** Speedup for logs */ 059 private static final boolean IS_DEBUG = LOG.isDebugEnabled(); 060 061 /** The AP options */ 062 private ApOptions apOptions; 063 064 /** The Ticket */ 065 private Ticket ticket; 066 067 /** The encryptedData, an encrypted Authenticator */ 068 private EncryptedData authenticator; 069 070 // Storage for computed lengths 071 private int pvnoLength; 072 private int msgTypeLength; 073 private int apOptionsLength; 074 private int ticketLength; 075 private int authenticatorLength; 076 private int apReqLength; 077 private int apReqSeqLength; 078 079 080 /** 081 * Creates a new instance of ApplicationRequest. 082 */ 083 public ApReq() 084 { 085 super( KerberosMessageType.AP_REQ ); 086 } 087 088 089 /** 090 * Returns the {@link ApOptions}. 091 * 092 * @return The {@link ApOptions}. 093 */ 094 public ApOptions getApOptions() 095 { 096 return apOptions; 097 } 098 099 100 /** 101 * Returns the {@link Ticket}. 102 * 103 * @return The {@link Ticket}. 104 */ 105 public Ticket getTicket() 106 { 107 return ticket; 108 } 109 110 111 /** 112 * Returns the option at a specified index. 113 * 114 * @param option 115 * @return The option. 116 */ 117 public boolean getOption( int option ) 118 { 119 return apOptions.get( option ); 120 } 121 122 123 /** 124 * Sets the options 125 * 126 * @param apOptions The options to set 127 */ 128 public void setOption( ApOptions apOptions ) 129 { 130 this.apOptions = apOptions; 131 } 132 133 134 /** 135 * Clears the option at a specified index. 136 * 137 * @param option 138 */ 139 public void clearOption( int option ) 140 { 141 apOptions.clear( option ); 142 } 143 144 145 /** 146 * Returns the {@link EncryptedData}. 147 * 148 * @return The {@link EncryptedData}. 149 */ 150 public EncryptedData getAuthenticator() 151 { 152 return authenticator; 153 } 154 155 156 /** 157 * Sets the {@link EncryptedData}. 158 * 159 * @param authenticator The encrypted authenticator 160 */ 161 public void setAuthenticator( EncryptedData authenticator ) 162 { 163 this.authenticator = authenticator; 164 } 165 166 167 /** 168 * Sets the {@link ApOptions}. 169 * 170 * @param options 171 */ 172 public void setApOptions( ApOptions options ) 173 { 174 apOptions = options; 175 } 176 177 178 /** 179 * Sets the {@link Ticket}. 180 * 181 * @param ticket 182 */ 183 public void setTicket( Ticket ticket ) 184 { 185 this.ticket = ticket; 186 } 187 188 189 /** 190 * Compute the AP-REQ length 191 * <pre> 192 * AP-REQ : 193 * 194 * 0x6E L1 AP-REQ [APPLICATION 14] 195 * | 196 * +--> 0x30 L2 197 * | 198 * +--> 0xA0 0x03 pvno tag 199 * | | 200 * | +--> 0x02 0x01 0x05 pvno (5) 201 * | 202 * +--> 0xA1 0x03 msg-type tag 203 * | | 204 * | +--> 0x02 0x01 0x0E msg-type (14) 205 * | 206 * +--> 0xA2 0x03 APOptions tag 207 * | | 208 * | +--> 0x03 0x05 0x00 b1 b2 b3 b4 APOtions 209 * | 210 * +--> 0xA3 L3 ticket tag 211 * | | 212 * | +--> 0x61 L3-1 ticket 213 * | 214 * +--> 0xA4 L4 authenticator tag 215 * | 216 * +--> 0x30 L4-1 authenticator (encrypted) 217 * </pre> 218 */ 219 public int computeLength() 220 { 221 reset(); 222 223 // Compute the PVNO length. 224 pvnoLength = 1 + 1 + BerValue.getNbBytes( getProtocolVersionNumber() ); 225 226 // Compute the msg-type length 227 msgTypeLength = 1 + 1 + BerValue.getNbBytes( getMessageType().getValue() ); 228 229 // Compute the APOptions length 230 apOptionsLength = 1 + 1 + apOptions.getBytes().length; 231 232 // Compute the ticket length 233 ticketLength = ticket.computeLength(); 234 235 // Compute the authenticator length 236 authenticatorLength = authenticator.computeLength(); 237 238 // Compute the sequence size 239 apReqLength = 240 1 + TLV.getNbBytes( pvnoLength ) + pvnoLength + 241 1 + TLV.getNbBytes( msgTypeLength ) + msgTypeLength + 242 1 + TLV.getNbBytes( apOptionsLength ) + apOptionsLength + 243 1 + TLV.getNbBytes( ticketLength ) + ticketLength + 244 1 + TLV.getNbBytes( authenticatorLength ) + authenticatorLength; 245 246 apReqSeqLength = 1 + TLV.getNbBytes( apReqLength ) + apReqLength; 247 248 return 1 + TLV.getNbBytes( apReqSeqLength ) + apReqSeqLength; 249 } 250 251 252 /** 253 * Encode the AP-REQ component 254 * 255 * @param buffer The buffer containing the encoded result 256 * @return The encoded component 257 * @throws EncoderException If the encoding failed 258 */ 259 public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException 260 { 261 if ( buffer == null ) 262 { 263 buffer = ByteBuffer.allocate( computeLength() ); 264 } 265 266 try 267 { 268 // The AP-REP Tag 269 buffer.put( ( byte ) KerberosConstants.AP_REQ_TAG ); 270 buffer.put( TLV.getBytes( apReqSeqLength ) ); 271 272 // The AP-REP SEQ Tag 273 buffer.put( UniversalTag.SEQUENCE.getValue() ); 274 buffer.put( TLV.getBytes( apReqLength ) ); 275 276 // The PVNO ------------------------------------------------------- 277 // The tag 278 buffer.put( ( byte ) KerberosConstants.AP_REQ_PVNO_TAG ); 279 buffer.put( TLV.getBytes( pvnoLength ) ); 280 281 // The value 282 BerValue.encode( buffer, getProtocolVersionNumber() ); 283 284 // The msg-type --------------------------------------------------- 285 // The tag 286 buffer.put( ( byte ) KerberosConstants.AP_REQ_MSG_TYPE_TAG ); 287 buffer.put( TLV.getBytes( msgTypeLength ) ); 288 289 // The value 290 BerValue.encode( buffer, getMessageType().getValue() ); 291 292 // The ap-options ------------------------------------------------- 293 // The tag 294 buffer.put( ( byte ) KerberosConstants.AP_REQ_AP_OPTIONS_TAG ); 295 buffer.put( TLV.getBytes( apOptionsLength ) ); 296 297 // The value 298 BerValue.encode( buffer, apOptions ); 299 300 // The ticket ----------------------------------------------------- 301 // The tag 302 buffer.put( ( byte ) KerberosConstants.AP_REQ_TICKET_TAG ); 303 buffer.put( TLV.getBytes( ticketLength ) ); 304 305 // The value 306 ticket.encode( buffer ); 307 308 // The authenticator ---------------------------------------------- 309 // The tag 310 buffer.put( ( byte ) KerberosConstants.AP_REQ_AUTHENTICATOR_TAG ); 311 buffer.put( TLV.getBytes( authenticatorLength ) ); 312 313 // The value 314 authenticator.encode( buffer ); 315 } 316 catch ( BufferOverflowException boe ) 317 { 318 LOG.error( I18n.err( I18n.ERR_137, 1 + TLV.getNbBytes( apReqLength ) + apReqLength, 319 buffer.capacity() ) ); 320 throw new EncoderException( I18n.err( I18n.ERR_138 ), boe ); 321 } 322 323 if ( IS_DEBUG ) 324 { 325 LOG.debug( "AP-REQ encoding : {}", Strings.dumpBytes( buffer.array() ) ); 326 LOG.debug( "AP-REQ initial value : {}", this ); 327 } 328 329 return buffer; 330 } 331 332 333 /** 334 * reset the fields used while computing length 335 */ 336 private void reset() 337 { 338 pvnoLength = 0; 339 msgTypeLength = 0; 340 apOptionsLength = 0; 341 ticketLength = 0; 342 authenticatorLength = 0; 343 apReqLength = 0; 344 apReqSeqLength = 0; 345 } 346 347 348 /** 349 * @see Object#toString() 350 */ 351 public String toString() 352 { 353 StringBuilder sb = new StringBuilder(); 354 355 sb.append( "AP-REQ :\n" ); 356 sb.append( " pvno : " ).append( getProtocolVersionNumber() ).append( "\n" ); 357 sb.append( " msg-type : " ).append( getMessageType() ).append( "\n" ); 358 sb.append( " ap-options : " ).append( apOptions ).append( "\n" ); 359 sb.append( " ticket : " ).append( ticket ).append( "\n" ); 360 sb.append( " authenticator : " ).append( authenticator ).append( "\n" ); 361 362 return sb.toString(); 363 } 364}