You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by el...@apache.org on 2010/11/19 01:29:54 UTC

svn commit: r1036690 - /directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/messages/KrbError.java

Author: elecharny
Date: Fri Nov 19 00:29:54 2010
New Revision: 1036690

URL: http://svn.apache.org/viewvc?rev=1036690&view=rev
Log:
o Added the missing Javadoc
o Fixed the encode() and compueLength() methods

Modified:
    directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/messages/KrbError.java

Modified: directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/messages/KrbError.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/messages/KrbError.java?rev=1036690&r1=1036689&r2=1036690&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/messages/KrbError.java (original)
+++ directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/messages/KrbError.java Fri Nov 19 00:29:54 2010
@@ -17,7 +17,6 @@
  *   under the License.
  *
  */
-
 package org.apache.directory.shared.kerberos.messages;
 
 
@@ -25,7 +24,6 @@ import java.nio.BufferOverflowException;
 import java.nio.ByteBuffer;
 
 import org.apache.directory.server.i18n.I18n;
-import org.apache.directory.shared.asn1.AbstractAsn1Object;
 import org.apache.directory.shared.asn1.ber.tlv.TLV;
 import org.apache.directory.shared.asn1.ber.tlv.UniversalTag;
 import org.apache.directory.shared.asn1.ber.tlv.Value;
@@ -61,7 +59,7 @@ import org.slf4j.LoggerFactory;
  *
  * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
  */
-public class KrbError extends AbstractAsn1Object
+public class KrbError extends KerberosMessage
 {
 
     /** The logger */
@@ -70,12 +68,6 @@ public class KrbError extends AbstractAs
     /** Speedup for logs */
     private static final boolean IS_DEBUG = log.isDebugEnabled();
 
-    /** the kerberos version number, default is 5 */
-    private int pvno = KerberosMessage.PVNO;
-
-    /** the kerberos message type */
-    private KerberosMessageType msgType = KerberosMessageType.KRB_ERROR; // default value
-
     /** the current time of client */
     private KerberosTime cTime;
 
@@ -109,297 +101,33 @@ public class KrbError extends AbstractAs
     /** the error data */
     private byte[] eData;
 
-    private transient int pvnoLen;
-    private transient int msgTypeLen;
-    private transient int cTimeLen;
-    private transient int cusecLen;
-    private transient int sTimeLen;
-    private transient int susecLen;
-    private transient int errorCodeLen;
-    private transient int cRealmLen;
-    private transient int cNameLen;
-    private transient int realmLen;
-    private transient int sNameLen;
-    private transient int eTextLen;
-    private transient int eDataLen;
-    private transient int krbErrorSeqLen;
-
-
-    @Override
-    public int computeLength()
-    {
-        pvnoLen = Value.getNbBytes( pvno );
-        pvnoLen = 1 + TLV.getNbBytes( pvnoLen ) + pvnoLen;
-        krbErrorSeqLen = pvnoLen;
-
-        msgTypeLen = Value.getNbBytes( msgType.getValue() );
-        msgTypeLen = 1 + TLV.getNbBytes( msgTypeLen ) + msgTypeLen;
-        krbErrorSeqLen += msgTypeLen;
-
-        if ( cTime != null )
-        {
-            cTimeLen = cTime.getBytes().length;
-            cTimeLen = 1 + TLV.getNbBytes( cTimeLen ) + cTimeLen;
-            krbErrorSeqLen += cTimeLen;
-        }
-
-        if ( cusec > 0 )
-        {
-            cusecLen = Value.getNbBytes( cusec );
-            cusecLen = 1 + TLV.getNbBytes( cusecLen ) + cusecLen;
-            krbErrorSeqLen += cusecLen;
-        }
-
-        sTimeLen = sTime.getBytes().length;
-        sTimeLen = 1 + TLV.getNbBytes( sTimeLen ) + sTimeLen;
-        krbErrorSeqLen += sTimeLen;
-
-        susecLen = Value.getNbBytes( susec );
-        susecLen = 1 + TLV.getNbBytes( susecLen ) + susecLen;
-        krbErrorSeqLen += susecLen;
-
-        errorCodeLen = Value.getNbBytes( errorCode.getOrdinal() );
-        errorCodeLen = 1 + TLV.getNbBytes( errorCodeLen ) + errorCodeLen;
-        krbErrorSeqLen += errorCodeLen;
-
-        if ( cRealm != null )
-        {
-            cRealmLen = StringTools.getBytesUtf8( cRealm ).length;
-            cRealmLen = 1 + TLV.getNbBytes( cRealmLen ) + cRealmLen;
-            krbErrorSeqLen += cRealmLen;
-        }
-
-        if ( cName != null )
-        {
-            cNameLen = cName.computeLength();
-            krbErrorSeqLen += cNameLen;
-        }
-
-        realmLen = StringTools.getBytesUtf8( realm ).length;
-        realmLen = 1 + TLV.getNbBytes( realmLen ) + realmLen;
-        krbErrorSeqLen += realmLen;
-
-        sNameLen = sName.computeLength();
-        krbErrorSeqLen += sNameLen;
-
-        if ( eText != null )
-        {
-            eTextLen = StringTools.getBytesUtf8( eText ).length;
-            eTextLen = 1 + TLV.getNbBytes( eTextLen ) + eTextLen;
-            krbErrorSeqLen += eTextLen;
-        }
-
-        if ( eData != null )
-        {
-            eDataLen = 1 + TLV.getNbBytes( eData.length ) + eData.length;
-            krbErrorSeqLen += eDataLen;
-        }
-
-        return 1 + TLV.getNbBytes( krbErrorSeqLen ) + krbErrorSeqLen;
-    }
-
-
-    @Override
-    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
-    {
-        if ( buffer == null )
-        {
-            throw new EncoderException( I18n.err( I18n.ERR_148 ) );
-        }
-
-        try
-        {
-            buffer.put( UniversalTag.SEQUENCE.getValue() );
-            buffer.put( TLV.getBytes( krbErrorSeqLen ) );
-
-            //pvno
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_PVNO_TAG );
-            buffer.put( TLV.getBytes( pvnoLen ) );
-            Value.encode( buffer, pvno );
-
-            //msg-type
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_MSGTYPE_TAG );
-            buffer.put( TLV.getBytes( msgTypeLen ) );
-            Value.encode( buffer, msgType.getValue() );
-
-            //ctime
-            if ( cTimeLen > 0 )
-            {
-                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CTIME_TAG );
-                buffer.put( TLV.getBytes( cTimeLen ) );
-                Value.encode( buffer, cTime.getBytes() );
-            }
-
-            //cusec
-            if ( cusec > 0 )
-            {
-                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CUSEC_TAG );
-                buffer.put( TLV.getBytes( cusecLen ) );
-                Value.encode( buffer, cusec );
-            }
-
-            //stime
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_STIME_TAG );
-            buffer.put( TLV.getBytes( sTimeLen ) );
-            Value.encode( buffer, sTime.getBytes() );
-
-            //susec
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_SUSEC_TAG );
-            buffer.put( TLV.getBytes( susecLen ) );
-            Value.encode( buffer, susec );
-
-            //error-code
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_ERROR_CODE_TAG );
-            buffer.put( TLV.getBytes( errorCodeLen ) );
-            Value.encode( buffer, errorCode.getOrdinal() );
-
-            //crealm
-            if ( cRealmLen > 0 )
-            {
-                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CREALM_TAG );
-                buffer.put( TLV.getBytes( cRealmLen ) );
-                Value.encode( buffer, cRealm );
-            }
-
-            //cname
-            if ( cNameLen > 0 )
-            {
-                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CNAME_TAG );
-                buffer.put( TLV.getBytes( cNameLen ) );
-                cName.encode( buffer );
-            }
-
-            //realm
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_REALM_TAG );
-            buffer.put( TLV.getBytes( realmLen ) );
-            Value.encode( buffer, realm );
-
-            //sname
-            buffer.put( ( byte ) KerberosConstants.KRB_ERR_SNAME_TAG );
-            buffer.put( TLV.getBytes( sNameLen ) );
-            sName.encode( buffer );
-
-            //etext
-            if ( eTextLen > 0 )
-            {
-                buffer.put( ( byte ) KerberosConstants.KRB_ERR_ETEXT_TAG );
-                buffer.put( TLV.getBytes( eTextLen ) );
-                Value.encode( buffer, eText );
-            }
-
-            //edata
-            if ( eDataLen > 0 )
-            {
-                buffer.put( ( byte ) KerberosConstants.KRB_ERR_EDATA_TAG );
-                buffer.put( TLV.getBytes( eDataLen ) );
-                Value.encode( buffer, eData );
-            }
-        }
-        catch ( BufferOverflowException boe )
-        {
-            log.error( I18n.err( I18n.ERR_734_CANNOT_ENCODE_KRBERROR, 1 + TLV.getNbBytes( krbErrorSeqLen )
-                + krbErrorSeqLen, buffer.capacity() ) );
-            throw new EncoderException( I18n.err( I18n.ERR_138 ) );
-        }
-
-        if ( IS_DEBUG )
-        {
-            log.debug( "KrbError encoding : {}", StringTools.dumpBytes( buffer.array() ) );
-            log.debug( "KrbError initial value : {}", toString() );
-        }
-
-        return buffer;
-    }
+    // Storage for computed lengths
+    private transient int pvnoLength;
+    private transient int msgTypeLength;
+    private transient int cTimeLength;
+    private transient int cusecLength;
+    private transient int sTimeLength;
+    private transient int susecLength;
+    private transient int errorCodeLength;
+    private transient int cRealmLength;
+    private transient byte[] crealmBytes;
+    private transient int cNameLength;
+    private transient int realmLength;
+    private transient byte[] realmBytes;
+    private transient int sNameLength;
+    private transient int eTextLength;
+    private transient byte[] eTextBytes;
+    private transient int eDataLength;
+    private transient int krbErrorSeqLength;
+    private transient int krbErrorLength;
 
 
     /**
-     * @see Object#toString()
+     * Creates a new instance of Ticket.
      */
-    public String toString()
+    public KrbError()
     {
-        StringBuilder sb = new StringBuilder();
-
-        sb.append( "KrbError : {\n" );
-        sb.append( "    pvno: " ).append( pvno ).append( '\n' );
-        sb.append( "    msgType: " ).append( msgType ).append( '\n' );
-
-        if ( cTime != null )
-        {
-            sb.append( "    cTime: " ).append( cTime ).append( '\n' );
-        }
-
-        if ( cusec > 0 )
-        {
-            sb.append( "    cusec: " ).append( cusec ).append( '\n' );
-        }
-
-        sb.append( "    sTime: " ).append( sTime ).append( '\n' );
-        sb.append( "    susec: " ).append( susec ).append( '\n' );
-        sb.append( "    errorCode: " ).append( errorCode ).append( '\n' );
-
-        if ( cRealm != null )
-        {
-            sb.append( "    cRealm: " ).append( cRealm ).append( '\n' );
-        }
-
-        if ( cName != null )
-        {
-            sb.append( "    cName: " ).append( cName ).append( '\n' );
-        }
-
-        sb.append( "    realm: " ).append( realm ).append( '\n' );
-
-        sb.append( "    sName: " ).append( sName ).append( '\n' );
-
-        if ( eText != null )
-        {
-            sb.append( "    eText: " ).append( eText ).append( '\n' );
-        }
-
-        if ( eData != null )
-        {
-            sb.append( "    eData: " ).append( StringTools.dumpBytes( eData ) ).append( '\n' );
-        }
-
-        sb.append( "}\n" );
-
-        return sb.toString();
-    }
-
-
-    /**
-     * @return the pvno
-     */
-    public int getPvno()
-    {
-        return pvno;
-    }
-
-
-    /**
-     * @param pvno the pvno to set
-     */
-    public void setPvno( int pvno )
-    {
-        this.pvno = pvno;
-    }
-
-
-    /**
-     * @return the msgType
-     */
-    public KerberosMessageType getMsgType()
-    {
-        return msgType;
-    }
-
-
-    /**
-     * @param msgType the msgType to set
-     */
-    public void setMsgType( KerberosMessageType msgType )
-    {
-        this.msgType = msgType;
+        super( KerberosMessageType.KRB_ERROR );
     }
 
 
@@ -599,4 +327,393 @@ public class KrbError extends AbstractAs
     {
         this.eData = eData;
     }
+
+    
+    /**
+     * Compute the KRB-ERROR length
+     * <pre>
+     * KRB-ERROR :
+     * 
+     * 0x7E L1 KRB-ERROR APPLICATION[30]
+     *  |
+     *  +--> 0x30 L2 KRB-ERROR sequence
+     *        |
+     *        +--> 0xA0 0x03 pvno tag
+     *        |     |
+     *        |     +--> 0x02 0x01 0x05 pvno (5)
+     *        |
+     *        +--> 0xA1 0x03 msg-type tag
+     *        |     |
+     *        |     +--> 0x02 0x01 0x1E msg-type (30)
+     *        |     
+     *        +--> 0xA2 0x11 ctime tag
+     *        |     |
+     *        |     +--> 0x18 0x0F ttt ctime (KerberosTime)
+     *        |     
+     *        +--> 0xA3 L3 cusec tag
+     *        |     |
+     *        |     +--> 0x02 L3-1 cusec
+     *        |     
+     *        +--> 0xA4 0x11 stime tag
+     *        |     |
+     *        |     +--> 0x18 0x0F ttt stime (KerberosTime)
+     *        |     
+     *        +--> 0xA5 L4 susec tag
+     *        |     |
+     *        |     +--> 0x02 L4-1 susec (KerberosTime)
+     *        |     
+     *        +--> 0xA6 L5 error-code tag
+     *        |     |
+     *        |     +--> 0x02 L5-1 nnn error-code
+     *        |     
+     *        +--> 0xA7 L6 crealm tag
+     *        |     |
+     *        |     +--> 0x1B L6-1 crealm (KerberosString)
+     *        |     
+     *        +--> 0xA8 L7 cname tag
+     *        |     |
+     *        |     +--> 0x30 L7-1 cname (PrincipalName)
+     *        |
+     *        +--> 0xA9 L8 realm tag
+     *        |     |
+     *        |     +--> 0x1B L8-1 realm (KerberosString)
+     *        |     
+     *        +--> 0xAA L9 sname tag
+     *        |     |
+     *        |     +--> 0x30 L9-1 sname (PrincipalName)
+     *        |     
+     *        +--> 0xAB L10 e-text tag
+     *        |     |
+     *        |     +--> 0x1B L10-1 e-text (KerberosString)
+     *        |
+     *        +--> 0xAC L11 e-data
+     *              |
+     *              +--> 0x04 L11-1 e-data (Octet String)
+     * </pre>       
+     */
+    public int computeLength()
+    {
+        pvnoLength = 1 + 1 + 1;
+
+        msgTypeLength = 1 + 1 + Value.getNbBytes( getMessageType().getValue() );
+
+        if ( cTime != null )
+        {
+            cTimeLength = 1 + 1 + 0x0F;
+        }
+
+        if ( cusec >= 0 )
+        {
+            int cusecLen = Value.getNbBytes( cusec );
+            cusecLength = 1 + TLV.getNbBytes( cusecLen ) + cusecLen;
+        }
+
+        sTimeLength = 1 + 1 + 0x0F;
+
+        int susecLen = Value.getNbBytes( susec );
+        susecLength = 1 + TLV.getNbBytes( susecLen ) + susecLen;
+
+        errorCodeLength = 1 + 1 + Value.getNbBytes( errorCode.getOrdinal() );
+
+        if ( cRealm != null )
+        {
+            crealmBytes = StringTools.getBytesUtf8( cRealm );
+            cRealmLength = 1 + TLV.getNbBytes( crealmBytes.length ) + crealmBytes.length;
+        }
+
+        if ( cName != null )
+        {
+            cNameLength = cName.computeLength();
+        }
+
+        realmBytes = StringTools.getBytesUtf8( realm );
+        realmLength = 1 + TLV.getNbBytes( realmBytes.length ) + realmBytes.length;
+
+        sNameLength = sName.computeLength();
+
+        if ( eText != null )
+        {
+            eTextBytes = StringTools.getBytesUtf8( eText );
+            eTextLength = 1 + TLV.getNbBytes( eTextBytes.length ) + eTextBytes.length;
+        }
+
+        if ( eData != null )
+        {
+            eDataLength = 1 + TLV.getNbBytes( eData.length ) + eData.length;
+        }
+        
+        // Compute the sequence size.
+        // The mandatory fields first
+        krbErrorSeqLength = 1 + TLV.getNbBytes( pvnoLength ) + pvnoLength;
+        krbErrorSeqLength += 1 + TLV.getNbBytes( msgTypeLength ) + msgTypeLength;
+        krbErrorSeqLength += 1 + TLV.getNbBytes( sTimeLength ) + sTimeLength;
+        krbErrorSeqLength += 1 + TLV.getNbBytes( susecLength ) + susecLength;
+        krbErrorSeqLength += 1 + TLV.getNbBytes( errorCodeLength ) + errorCodeLength;
+        krbErrorSeqLength += 1 + TLV.getNbBytes( realmLength ) + realmLength;
+        krbErrorSeqLength += 1 + TLV.getNbBytes( sNameLength ) + sNameLength;
+
+        // The optional fields then
+        if ( cTime != null )
+        {
+            krbErrorSeqLength += 1 + TLV.getNbBytes( cTimeLength ) + cTimeLength;
+        }
+
+        if ( cusec >= 0 )
+        {
+            krbErrorSeqLength += 1 + TLV.getNbBytes( cusecLength ) + cusecLength;
+        }
+
+        if ( cRealm != null )
+        {
+            krbErrorSeqLength += 1 + TLV.getNbBytes( cRealmLength ) + cRealmLength;
+        }
+
+        if ( cName != null )
+        {
+            krbErrorSeqLength += 1 + TLV.getNbBytes( cNameLength ) + cNameLength;
+        }
+
+        if ( eText != null )
+        {
+            krbErrorSeqLength += 1 + TLV.getNbBytes( eTextLength ) + eTextLength;
+        }
+
+        if ( eData != null )
+        {
+            krbErrorSeqLength += 1 + TLV.getNbBytes( eDataLength ) + eDataLength;
+        }
+        
+        krbErrorLength = 1 + TLV.getNbBytes( krbErrorSeqLength ) + krbErrorSeqLength;
+
+        return 1 + TLV.getNbBytes( krbErrorLength ) + krbErrorLength;
+    }
+
+
+    /**
+     * Encode the KRB-ERROR message to a PDU. 
+     * <pre>
+     * KRB-ERROR :
+     * 
+     * 0x7E LL
+     *   0x30 LL
+     *     0xA0 0x03 
+     *       0x02 0x01 0x05  pvno 
+     *     0xA1 0x03 
+     *       0x02 0x01 0x1E msg-type
+     *    [0xA2 0x11
+     *       0x18 0x0F ttt] ctime
+     *    [0xA3 LL
+     *       0x02 LL nnn] cusec
+     *     0xA4 0x11
+     *       0x18 0x0F ttt  stime
+     *     0xA5 LL
+     *       0x02 LL nnn susec
+     *     0xA6 LL
+     *       0x02 LL nnn error-code
+     *    [0xA7 LL
+     *       0x1B LL abcd] crealm
+     *    [0xA8 LL
+     *       0x30 LL abcd] cname
+     *     0xA9 LL
+     *       0x1B LL abcd realm
+     *     0xAA LL
+     *       0x30 LL abcd sname
+     *    [0xAB LL
+     *       0x1B LL abcd] e-text
+     *    [0xAC LL
+     *       0x04 LL abcd] e-data
+     * </pre>
+     * @return The constructed PDU.
+     */
+    public ByteBuffer encode( ByteBuffer buffer ) throws EncoderException
+    {
+        if ( buffer == null )
+        {
+            throw new EncoderException( I18n.err( I18n.ERR_148 ) );
+        }
+
+        try
+        {
+            // The KRB-ERROR APPLICATION tag
+            buffer.put( (byte)0x7E );
+            buffer.put( TLV.getBytes( krbErrorLength ) );
+
+            // The KRB_ERROR sequence
+            buffer.put( UniversalTag.SEQUENCE.getValue() );
+            buffer.put( TLV.getBytes( krbErrorSeqLength ) );
+
+            // pvno tag and value
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_PVNO_TAG );
+            buffer.put( TLV.getBytes( pvnoLength ) );
+            Value.encode( buffer, getProtocolVersionNumber() );
+
+            // msg-type tag and value
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_MSGTYPE_TAG );
+            buffer.put( TLV.getBytes( msgTypeLength ) );
+            Value.encode( buffer, getMessageType().getValue() );
+
+            // ctime tag and value if any
+            if ( cTimeLength > 0 )
+            {
+                // The tag
+                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CTIME_TAG );
+                buffer.put( TLV.getBytes( cTimeLength ) );
+                
+                // The value
+                buffer.put( (byte)UniversalTag.GENERALIZED_TIME.getValue() );
+                buffer.put( (byte)0x0F );
+                buffer.put(cTime.getBytes() );
+            }
+
+            // cusec tag and value if any
+            if ( cusec > 0 )
+            {
+                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CUSEC_TAG );
+                buffer.put( TLV.getBytes( cusecLength ) );
+                Value.encode( buffer, cusec );
+            }
+
+            // stime tag and value
+            // The tag
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_STIME_TAG );
+            buffer.put( TLV.getBytes( sTimeLength ) );
+
+            // The value
+            buffer.put( (byte)UniversalTag.GENERALIZED_TIME.getValue() );
+            buffer.put( (byte)0x0F );
+            buffer.put( sTime.getBytes() );
+
+            // susec tag and value
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_SUSEC_TAG );
+            buffer.put( TLV.getBytes( susecLength ) );
+            Value.encode( buffer, susec );
+
+            // error-code tag and value
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_ERROR_CODE_TAG );
+            buffer.put( TLV.getBytes( errorCodeLength ) );
+            Value.encode( buffer, errorCode.getOrdinal() );
+
+            // crealm tage and value, if any
+            if ( cRealm != null)
+            {
+                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CREALM_TAG );
+                buffer.put( TLV.getBytes( cRealmLength ) );
+
+                buffer.put( UniversalTag.GENERAL_STRING.getValue() );
+                buffer.put( TLV.getBytes( crealmBytes.length ) );
+                buffer.put( crealmBytes );
+            }
+
+            // cname tag and value, if any
+            if ( cName != null )
+            {
+                buffer.put( ( byte ) KerberosConstants.KRB_ERR_CNAME_TAG );
+                buffer.put( TLV.getBytes( cNameLength ) );
+                cName.encode( buffer );
+            }
+
+            // realm tag and value
+            // the tag
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_REALM_TAG );
+            buffer.put( TLV.getBytes( realmLength ) );
+
+            // The value
+            buffer.put( UniversalTag.GENERAL_STRING.getValue() );
+            buffer.put( TLV.getBytes( realmBytes.length ) );
+            buffer.put( realmBytes );
+
+            // sname tag and value
+            buffer.put( ( byte ) KerberosConstants.KRB_ERR_SNAME_TAG );
+            buffer.put( TLV.getBytes( sNameLength ) );
+            sName.encode( buffer );
+
+            // etext tag and value, if any
+            if ( eText != null )
+            {
+                buffer.put( ( byte ) KerberosConstants.KRB_ERR_ETEXT_TAG );
+                buffer.put( TLV.getBytes( eTextLength ) );
+
+                buffer.put( UniversalTag.GENERAL_STRING.getValue() );
+                buffer.put( TLV.getBytes( eTextBytes.length ) );
+                buffer.put( eTextBytes );
+            }
+
+            // edata tag and value, if any
+            if ( eData != null )
+            {
+                buffer.put( ( byte ) KerberosConstants.KRB_ERR_EDATA_TAG );
+                buffer.put( TLV.getBytes( eDataLength ) );
+                Value.encode( buffer, eData );
+            }
+        }
+        catch ( BufferOverflowException boe )
+        {
+            log.error( I18n.err( I18n.ERR_734_CANNOT_ENCODE_KRBERROR, 1 + TLV.getNbBytes( krbErrorLength )
+                + krbErrorLength, buffer.capacity() ) );
+            throw new EncoderException( I18n.err( I18n.ERR_138 ) );
+        }
+
+        if ( IS_DEBUG )
+        {
+            log.debug( "KrbError encoding : {}", StringTools.dumpBytes( buffer.array() ) );
+            log.debug( "KrbError initial value : {}", toString() );
+        }
+
+        return buffer;
+    }
+
+
+    /**
+     * @see Object#toString()
+     */
+    public String toString()
+    {
+        StringBuilder sb = new StringBuilder();
+
+        sb.append( "KrbError : {\n" );
+        sb.append( "    pvno: " ).append( getProtocolVersionNumber() ).append( '\n' );
+        sb.append( "    msgType: " ).append( getMessageType() ).append( '\n' );
+
+        if ( cTime != null )
+        {
+            sb.append( "    cTime: " ).append( cTime ).append( '\n' );
+        }
+
+        if ( cusec > 0 )
+        {
+            sb.append( "    cusec: " ).append( cusec ).append( '\n' );
+        }
+
+        sb.append( "    sTime: " ).append( sTime ).append( '\n' );
+        sb.append( "    susec: " ).append( susec ).append( '\n' );
+        sb.append( "    errorCode: " ).append( errorCode ).append( '\n' );
+
+        if ( cRealm != null )
+        {
+            sb.append( "    cRealm: " ).append( cRealm ).append( '\n' );
+        }
+
+        if ( cName != null )
+        {
+            sb.append( "    cName: " ).append( cName ).append( '\n' );
+        }
+
+        sb.append( "    realm: " ).append( realm ).append( '\n' );
+
+        sb.append( "    sName: " ).append( sName ).append( '\n' );
+
+        if ( eText != null )
+        {
+            sb.append( "    eText: " ).append( eText ).append( '\n' );
+        }
+
+        if ( eData != null )
+        {
+            sb.append( "    eData: " ).append( StringTools.dumpBytes( eData ) ).append( '\n' );
+        }
+
+        sb.append( "}\n" );
+
+        return sb.toString();
+    }
 }