blob: 444376b63c6581ec0d3be513902a25a784945525 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you under the Apache License, Version 2.0 (the
* "License"); you may not use this file except in compliance
* with the License. You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing,
* software distributed under the License is distributed on an
* "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
* KIND, either express or implied. See the License for the
* specific language governing permissions and limitations
* under the License.
*
*/
package org.apache.directory.shared.kerberos.components;
import java.nio.ByteBuffer;
import java.util.ArrayList;
import java.util.List;
import org.apache.directory.api.asn1.EncoderException;
import org.apache.directory.api.asn1.ber.tlv.BerValue;
import org.apache.directory.api.asn1.ber.tlv.TLV;
import org.apache.directory.api.asn1.ber.tlv.UniversalTag;
import org.apache.directory.server.i18n.I18n;
import org.apache.directory.shared.kerberos.KerberosConstants;
import org.apache.directory.shared.kerberos.KerberosMessageType;
import org.apache.directory.shared.kerberos.messages.KerberosMessage;
/**
* The KDC-REQ data structure. It will store the object described by the ASN.1 grammar :
* <pre>
* KDC-REQ ::= SEQUENCE {
* -- NOTE: first tag is [1], not [0]
* pvno [1] INTEGER (5) ,
* msg-type [2] INTEGER (10 -- AS -- | 12 -- TGS --),
* padata [3] SEQUENCE OF <PA-DATA> OPTIONAL
-- NOTE: not empty --,
* req-body [4] <KDC-REQ-BODY>
* }
* </pre>
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public abstract class KdcReq extends KerberosMessage
{
/** The PA-DATAs */
private List<PaData> paData;
/** The KDC-REQ-BODY */
private KdcReqBody kdcReqBody;
// Storage for computed lengths
private int pvnoLength;
private int msgTypeLength;
private int paDataLength;
private int paDataSeqLength;
private int[] paDataLengths;
private int kdcReqBodyLength;
private int kdcReqSeqLength;
private int kdcReqLength;
/**
* Creates a new instance of KDC-REQ.
*/
public KdcReq( KerberosMessageType msgType )
{
super( msgType );
paData = new ArrayList<PaData>();
}
/**
* @return the pvno
*/
public int getPvno()
{
return getProtocolVersionNumber();
}
/**
* @param pvno the pvno to set
*/
public void setPvno( int pvno )
{
setProtocolVersionNumber( pvno );
}
/**
* @return the paData
*/
public List<PaData> getPaData()
{
return paData;
}
/**
* @param paData the paData to set
*/
public void addPaData( PaData paData )
{
this.paData.add( paData );
}
/**
* @return the kdcReqBody
*/
public KdcReqBody getKdcReqBody()
{
return kdcReqBody;
}
/**
* @param kdcReqBody the kdcReqBody to set
*/
public void setKdcReqBody( KdcReqBody kdcReqBody )
{
this.kdcReqBody = kdcReqBody;
}
/**
* Compute the KDC-REQ length
* <pre>
* KDC-REQ :
*
* 0x30 L1 KDC-REQ sequence
* |
* +--> 0xA1 0x03 pvno tag
* | |
* | +--> 0x02 0x01 0x05 pvno (5)
* |
* +--> 0xA2 0x03 msg-type tag
* | |
* | +--> 0x02 0x01 0x0A/0x0C msg-type : either AS-REQ (0x0A) or TGS-REQ (0x0C)
* |
* +--> 0xA3 L2 pa-data tag
* | |
* | +--> 0x30 L2-1 pa-data SEQ
* | |
* | +--> 0x30 L2-1-1 pa-data
* | |
* | +--> 0x30 L2-1-2 pa-data
* | :
* |
* +--> 0xA4 L3 req-body tag
* | |
* | +--> 0x30 L3-1 req-body (KDC-REQ-BODY)
* </pre>
*/
public int computeLength()
{
// The pvno length
pvnoLength = 1 + 1 + 1;
kdcReqSeqLength = 1 + TLV.getNbBytes( pvnoLength ) + pvnoLength;
// The msg-type length
msgTypeLength = 1 + 1 + 1;
kdcReqSeqLength += 1 + TLV.getNbBytes( msgTypeLength ) + msgTypeLength;
// Compute the pa-data length.
if ( paData.size() > 0 )
{
paDataLengths = new int[paData.size()];
int pos = 0;
paDataSeqLength = 0;
for ( PaData paDataElem : paData )
{
paDataLengths[pos] = paDataElem.computeLength();
paDataSeqLength += paDataLengths[pos];
pos++;
}
paDataLength = 1 + TLV.getNbBytes( paDataSeqLength ) + paDataSeqLength;
kdcReqSeqLength += 1 + TLV.getNbBytes( paDataLength ) + paDataLength;
}
// The KDC-REQ-BODY length
kdcReqBodyLength = kdcReqBody.computeLength();
kdcReqSeqLength += 1 + TLV.getNbBytes( kdcReqBodyLength ) + kdcReqBodyLength;
// compute the global size
kdcReqLength = 1 + TLV.getNbBytes( kdcReqSeqLength ) + kdcReqSeqLength;
return kdcReqLength;
}
/**
* Encode the KDC-REQ component
*
* @param buffer The buffer containing the encoded result
* @return The encoded component
* @throws EncoderException If the encoding failed
*/
public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
{
if ( buffer == null )
{
throw new EncoderException( I18n.err( I18n.ERR_148 ) );
}
// The KDC-REQ SEQ Tag
buffer.put( UniversalTag.SEQUENCE.getValue() );
buffer.put( TLV.getBytes( kdcReqSeqLength ) );
// The PVNO -----------------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REQ_PVNO_TAG );
buffer.put( TLV.getBytes( pvnoLength ) );
// The value
BerValue.encode( buffer, getProtocolVersionNumber() );
// The msg-type if any ------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REQ_MSG_TYPE_TAG );
buffer.put( TLV.getBytes( msgTypeLength ) );
// The value
BerValue.encode( buffer, getMessageType().getValue() );
// The PD-DATA if any -------------------------------------------------
if ( paData.size() > 0 )
{
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REQ_PA_DATA_TAG );
buffer.put( TLV.getBytes( paDataLength ) );
// The sequence
buffer.put( UniversalTag.SEQUENCE.getValue() );
buffer.put( TLV.getBytes( paDataSeqLength ) );
// The values
for ( PaData paDataElem : paData )
{
paDataElem.encode( buffer );
}
}
// The KDC-REQ-BODY ---------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REQ_KDC_REQ_BODY_TAG );
buffer.put( TLV.getBytes( kdcReqBodyLength ) );
// The value
kdcReqBody.encode( buffer );
return buffer;
}
/**
* Pretty print the instance
*/
public String toString( String tabs )
{
StringBuilder sb = new StringBuilder();
sb.append( tabs ).append(
"\n>-------------------------------------------------------------------------------\n" );
if ( getMessageType() == KerberosMessageType.AS_REQ )
{
sb.append( tabs ).append( "AS-REQ" ).append( '\n' );
}
else if ( getMessageType() == KerberosMessageType.TGS_REQ )
{
sb.append( tabs ).append( "TGS-REQ" ).append( '\n' );
}
else
{
sb.append( tabs ).append( "Unknown" ).append( '\n' );
}
sb.append( tabs ).append( "pvno : " ).append( getProtocolVersionNumber() ).append( '\n' );
sb.append( tabs ).append( "msg-type : " ).append( getMessageType() ).append( "\n" );
for ( PaData paDataElem : paData )
{
sb.append( tabs ).append( "padata :\n" );
sb.append( paDataElem.toString( tabs + " " ) ).append( '\n' );
}
sb.append( tabs ).append( "kdc-req-body : \n" );
sb.append( kdcReqBody.toString( tabs + " " ) ).append( '\n' );
sb.append( tabs ).append( "\n-------------------------------------------------------------------------------<\n" );
return sb.toString();
}
/**
* @see Object#toString()
*/
public String toString()
{
return toString( "" );
}
}