blob: 1dfe381e73d9d2b554b994e53f1ed24cf6563b92 [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.api.util.Strings;
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;
import org.apache.directory.shared.kerberos.messages.Ticket;
/**
* The KDC-REP data structure. It will store the object described by the ASN.1 grammar :
* <pre>
* KDC-REP ::= SEQUENCE {
* pvno [0] INTEGER (5),
* msg-type [1] INTEGER (11 -- AS -- | 13 -- TGS --),
* padata [2] SEQUENCE OF PA-DATA OPTIONAL
* -- NOTE: not empty --,
* crealm [3] Realm,
* cname [4] <PrincipalName>,
* ticket [5] <Ticket>,
* enc-part [6] <EncryptedData>
* -- EncASRepPart or EncTGSRepPart,
* -- as appropriate
* }
* </pre>
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
public class KdcRep extends KerberosMessage
{
/** The PA-DATAs */
private List<PaData> paData;
/** The client realm */
private String crealm;
/** A storage for a byte array representation of the realm */
private byte[] crealmBytes;
/** The client principal name */
private PrincipalName cname;
/** The ticket tickets */
private Ticket ticket;
/** Encoded part */
private EncryptedData encPart;
/** The decoded KDC-REP part */
protected EncKdcRepPart encKdcRepPart;
// Storage for computed lengths
private int pvnoLength;
private int msgTypeLength;
private int paDataLength;
private int paDataSeqLength;
private int[] paDataLengths;
private int cnameLength;
private int crealmLength;
private int ticketLength;
private int encPartLength;
private int kdcRepSeqLength;
private int kdcRepLength;
/**
* Creates a new instance of KDC-REP.
*/
public KdcRep( 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 );
}
/**
* Returns the client realm.
*
* @return The client realm.
*/
public String getCRealm()
{
return crealm;
}
/**
* Set the client realm
* @param crealm the client realm
*/
public void setCRealm( String crealm )
{
this.crealm = crealm;
}
/**
* Returns the client {@link PrincipalName}.
*
* @return The client {@link PrincipalName}.
*/
public PrincipalName getCName()
{
return cname;
}
/**
* Set the client principalName
* @param cname the client principalName
*/
public void setCName( PrincipalName cname )
{
this.cname = cname;
}
/**
* Returns the {@link Ticket}
*
* @return The {@link Ticket}
*/
public Ticket getTicket()
{
return ticket;
}
/**
* Set the Ticket
* @param ticket the ticket to set
*/
public void setTicket( Ticket ticket )
{
this.ticket = ticket;
}
/**
* Returns the encrypted part as {@link EncryptedData}.
*
* @return The encrypted part as {@link EncryptedData}.
*/
public EncryptedData getEncPart()
{
return encPart;
}
/**
* @param encPart the encPart to set
*/
public void setEncPart( EncryptedData encPart )
{
this.encPart = encPart;
}
/**
* @return the encKdcRepPart
*/
public EncKdcRepPart getEncKdcRepPart()
{
return encKdcRepPart;
}
/**
* @param encKdcRepPart the encKdcRepPart to set
*/
public void setEncKdcRepPart( EncKdcRepPart encKdcRepPart )
{
this.encKdcRepPart = encKdcRepPart;
}
/**
* Compute the KDC-REP length
* <pre>
* KDC-REP :
*
* 0x30 L1 KDC-REP sequence
* |
* +--> 0xA0 0x03 pvno tag
* | |
* | +--> 0x02 0x01 0x05 pvno (5)
* |
* +--> 0xA1 0x03 msg-type tag
* | |
* | +--> 0x02 0x01 0x0B/0x0D msg-type : either AS-REP (0x0B) or TGS-REP (0x0D)
* |
* +--> 0xA2 L2 pa-data tag
* | |
* | +--> 0x30 L2-1 pa-data SEQ
* | |
* | +--> 0x30 L2-1-1 pa-data
* | |
* | +--> 0x30 L2-1-2 pa-data
* | :
* |
* +--> 0xA3 L3 crealm tag
* | |
* | +--> 0x1B L3-1 crealm
* |
* +--> 0xA4 L4 cname tag
* | |
* | +--> 0x30 L4-1 cname
* |
* +--> 0xA5 L5 ticket tag
* | |
* | +--> 0x61 L5-1 ticket
* |
* +--> 0xA6 L6 enc-part tag
* |
* +--> 0x30 L6-1 enc-part
*
* </pre>
*/
public int computeLength()
{
// The pvno length
pvnoLength = 1 + 1 + 1;
kdcRepSeqLength = 1 + TLV.getNbBytes( pvnoLength ) + pvnoLength;
// The msg-type length
msgTypeLength = 1 + 1 + 1;
kdcRepSeqLength += 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;
kdcRepSeqLength += 1 + TLV.getNbBytes( paDataLength ) + paDataLength;
}
// The crealm length
crealmBytes = Strings.getBytesUtf8( crealm );
crealmLength = 1 + TLV.getNbBytes( crealmBytes.length ) + crealmBytes.length;
kdcRepSeqLength += 1 + TLV.getNbBytes( crealmLength ) + crealmLength;
// Compute the client principalName length
cnameLength = cname.computeLength();
kdcRepSeqLength += 1 + TLV.getNbBytes( cnameLength ) + cnameLength;
// Compute the ticket length
ticketLength = ticket.computeLength();
kdcRepSeqLength += 1 + TLV.getNbBytes( ticketLength ) + ticketLength;
// Compute the encrypted part
encPartLength = encPart.computeLength();
kdcRepSeqLength += 1 + TLV.getNbBytes( encPartLength ) + encPartLength;
// compute the global size
kdcRepLength = 1 + TLV.getNbBytes( kdcRepSeqLength ) + kdcRepSeqLength;
return kdcRepLength;
}
/**
* Encode the KDC-REP 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-REP SEQ Tag
buffer.put( UniversalTag.SEQUENCE.getValue() );
buffer.put( TLV.getBytes( kdcRepSeqLength ) );
// The PVNO -----------------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REP_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_REP_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_REP_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 CREALM ---------------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REP_CREALM_TAG );
buffer.put( TLV.getBytes( crealmLength ) );
// The value
buffer.put( UniversalTag.GENERAL_STRING.getValue() );
buffer.put( TLV.getBytes( crealmBytes.length ) );
buffer.put( crealmBytes );
// The CNAME ----------------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REP_CNAME_TAG );
buffer.put( TLV.getBytes( cnameLength ) );
// The value
cname.encode( buffer );
// The TICKET ---------------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REP_TICKET_TAG );
buffer.put( TLV.getBytes( ticketLength ) );
// The value
ticket.encode( buffer );
// The ENC-PART -------------------------------------------------------
// The tag
buffer.put( ( byte ) KerberosConstants.KDC_REP_ENC_PART_TAG );
buffer.put( TLV.getBytes( encPartLength ) );
// The value
encPart.encode( buffer );
return buffer;
}
/**
* Pretty print the instance
*/
public String toString( String tabs )
{
StringBuilder sb = new StringBuilder();
sb.append( tabs ).append(
"\n>-------------------------------------------------------------------------------\n" );
sb.append( tabs ).append( "KdcRep : " );
if ( getMessageType() == KerberosMessageType.AS_REP )
{
sb.append( "AS-REP" ).append( '\n' );
}
else if ( getMessageType() == KerberosMessageType.TGS_REP )
{
sb.append( "TGS-REP" ).append( '\n' );
}
else
{
sb.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 : " ).append( paDataElem.toString( tabs + " " ) ).append( '\n' );
}
sb.append( tabs ).append( "crealm : " ).append( crealm ).append( '\n' );
sb.append( tabs ).append( "cname : " ).append( cname ).append( '\n' );
sb.append( ticket.toString( tabs ) );
sb.append( encPart.toString( tabs ) );
sb.append( tabs ).append(
"\n-------------------------------------------------------------------------------<\n" );
return sb.toString();
}
/**
* @see Object#toString()
*/
public String toString()
{
return toString( "" );
}
}