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 2013/08/11 22:15:11 UTC
svn commit: r1512996 - in /directory/apacheds/trunk/kerberos-codec/src:
main/java/org/apache/directory/server/kerberos/shared/keytab/
test/java/org/apache/directory/server/kerberos/shared/keytab/
Author: elecharny
Date: Sun Aug 11 20:15:10 2013
New Revision: 1512996
URL: http://svn.apache.org/r1512996
Log:
Fix for DIRSERVER-1882
Modified:
directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/Keytab.java
directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/KeytabEncoder.java
directory/apacheds/trunk/kerberos-codec/src/test/java/org/apache/directory/server/kerberos/shared/keytab/KeytabTest.java
Modified: directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/Keytab.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/Keytab.java?rev=1512996&r1=1512995&r2=1512996&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/Keytab.java (original)
+++ directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/Keytab.java Sun Aug 11 20:15:10 2013
@@ -35,7 +35,38 @@ import org.apache.directory.server.i18n.
/**
- * Keytab file.
+ * Keytab file. The format is the following :
+ * <pre>
+ * {
+ * version : 2 bytes (0x05 0x02)
+ * keytabEntry*
+ * }
+ *
+ * keytab_entry
+ * {
+ * size : int
+ * numComponents : short
+ * realm : countedOctetString
+ * components[numComponents] : countedOctetString
+ * nameType : int
+ * timestamp : int
+ * vno8 : byte
+ * key : keyBlock
+ * vno : int // only present if >= 4 bytes left in entry
+ * };
+ *
+ * keyblock
+ * {
+ * type : int
+ * data : countedOctetString
+ * }
+ *
+ * countedOctetString
+ * {
+ * length : short
+ * data[length] : bytes
+ * }
+ *
*
* @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
*/
@@ -44,16 +75,22 @@ public class Keytab
/**
* Byte array constant for keytab file format 5.1.
*/
- public static final byte[] VERSION_51 = new byte[]
+ public static final byte[] VERSION_0X501_BYTES = new byte[]
{ ( byte ) 0x05, ( byte ) 0x01 };
+ // Format 0x0501
+ public static final short VERSION_0X501 = 0x0501;
+
/**
* Byte array constant for keytab file format 5.2.
*/
- public static final byte[] VERSION_52 = new byte[]
+ public static final byte[] VERSION_0X502_BYTES = new byte[]
{ ( byte ) 0x05, ( byte ) 0x02 };
- private byte[] keytabVersion = VERSION_52;
+ // Format 0x0502
+ public static final short VERSION_0X502 = 0x0502;
+
+ private byte[] keytabVersion = VERSION_0X502_BYTES;
private List<KeytabEntry> entries = new ArrayList<KeytabEntry>();
@@ -218,7 +255,7 @@ public class Keytab
// Close the input stream and return bytes.
is.close();
-
+
return bytes;
}
Modified: directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/KeytabEncoder.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/KeytabEncoder.java?rev=1512996&r1=1512995&r2=1512996&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/KeytabEncoder.java (original)
+++ directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/server/kerberos/shared/keytab/KeytabEncoder.java Sun Aug 11 20:15:10 2013
@@ -20,8 +20,9 @@
package org.apache.directory.server.kerberos.shared.keytab;
+import java.io.UnsupportedEncodingException;
import java.nio.ByteBuffer;
-import java.util.Iterator;
+import java.util.ArrayList;
import java.util.List;
import org.apache.directory.shared.kerberos.components.EncryptionKey;
@@ -35,6 +36,30 @@ import org.apache.directory.shared.kerbe
class KeytabEncoder
{
/**
+ * Tells if the keytabCersion is 0x0501 or 0x0502
+ */
+ private short getKeytabVersion( byte[] version )
+ {
+ if ( ( version != null ) && ( version.length == 2 ) && ( version[0] == 0x05 ) )
+ {
+ switch ( version[1] )
+ {
+ case 0x01:
+ return Keytab.VERSION_0X501;
+
+ case 0x02:
+ return Keytab.VERSION_0X502;
+
+ default:
+ return -1;
+ }
+ }
+
+ return -1;
+ }
+
+
+ /**
* Write the keytab version and entries into a {@link ByteBuffer}.
*
* @param keytabVersion
@@ -43,45 +68,56 @@ class KeytabEncoder
*/
ByteBuffer write( byte[] keytabVersion, List<KeytabEntry> entries )
{
- ByteBuffer buffer = ByteBuffer.allocate( 512 );
- putKeytabVersion( buffer, keytabVersion );
- putKeytabEntries( buffer, entries );
- buffer.flip();
+ List<ByteBuffer> keytabEntryBuffers = new ArrayList<ByteBuffer>();;
+ short version = getKeytabVersion( keytabVersion );
- return buffer;
- }
+ int buffersSize = encodeKeytabEntries( keytabEntryBuffers, version, entries );
+ ByteBuffer buffer = ByteBuffer.allocate(
+ keytabVersion.length + buffersSize );
- /**
- * Encode the 16-bit file format version. This
- * keytab reader currently only support verision 5.2.
- */
- private void putKeytabVersion( ByteBuffer buffer, byte[] version )
- {
- buffer.put( version );
+ // The keytab version (0x0502 or 0x5001)
+ buffer.put( keytabVersion );
+
+ for ( ByteBuffer keytabEntryBuffer : keytabEntryBuffers )
+ {
+ // The buffer
+ buffer.put( keytabEntryBuffer );
+ }
+
+ buffer.flip();
+
+ return buffer;
}
/**
- * Encode the keytab entries.
+ * Encode the keytab entries. Each entry stores :
+ * - the size
+ * - the principal name
+ * - the type (int, 4 bytes)
+ * - the timestamp (int, 4 bytes)
+ * - the key version (1 byte)
+ * - the key
*
* @param buffer
* @param entries
*/
- private void putKeytabEntries( ByteBuffer buffer, List<KeytabEntry> entries )
+ private int encodeKeytabEntries( List<ByteBuffer> buffers, short version, List<KeytabEntry> entries )
{
- Iterator<KeytabEntry> iterator = entries.iterator();
+ int size = 0;
- while ( iterator.hasNext() )
+ for ( KeytabEntry keytabEntry : entries )
{
- ByteBuffer entryBuffer = putKeytabEntry( iterator.next() );
- int size = entryBuffer.position();
+ ByteBuffer entryBuffer = encodeKeytabEntry( version, keytabEntry );
- entryBuffer.flip();
+ buffers.add( entryBuffer );
- buffer.putInt( size );
- buffer.put( entryBuffer );
+ // The buffer size
+ size += entryBuffer.limit();
}
+
+ return size;
}
@@ -89,19 +125,49 @@ class KeytabEncoder
* Encode a "keytab entry," which consists of a principal name,
* principal type, key version number, and key material.
*/
- private ByteBuffer putKeytabEntry( KeytabEntry entry )
+ private ByteBuffer encodeKeytabEntry( short version, KeytabEntry entry )
{
- ByteBuffer buffer = ByteBuffer.allocate( 100 );
+ // Compute the principalName encoding
+ ByteBuffer principalNameBuffer = encodePrincipalName( version, entry.getPrincipalName() );
+
+ // Compute the keyblock encoding
+ ByteBuffer keyBlockBuffer = encodeKeyBlock( entry.getKey() );
- putPrincipalName( buffer, entry.getPrincipalName() );
+ int bufferSize =
+ 4 + // size
+ principalNameBuffer.limit() + // principalName size
+ 4 + // timeStamp
+ 1 + // keyVersion
+ keyBlockBuffer.limit(); // keyBlock size
- buffer.putInt( ( int ) entry.getPrincipalType() );
+ if ( version == Keytab.VERSION_0X502 )
+ {
+ bufferSize += 4; // Add the principal NameType only for version 0x502
+ }
+
+ ByteBuffer buffer = ByteBuffer.allocate( bufferSize );
+
+ // Store the size
+ buffer.putInt( bufferSize - 4 );
+
+ // Store the principalNames
+ buffer.put( principalNameBuffer );
+
+ // Store the principal type if version == 0x0502
+ if ( version == Keytab.VERSION_0X502 )
+ {
+ buffer.putInt( ( int ) entry.getPrincipalType() );
+ }
+ // Store the timeStamp
buffer.putInt( ( int ) ( entry.getTimeStamp().getTime() / 1000 ) );
+ // Store the key version
buffer.put( entry.getKeyVersion() );
- putKeyBlock( buffer, entry.getKey() );
+ // Store the KeyBlock
+ buffer.put( keyBlockBuffer );
+ buffer.flip();
return buffer;
}
@@ -113,34 +179,78 @@ class KeytabEncoder
* @param buffer
* @param principalName
*/
- private void putPrincipalName( ByteBuffer buffer, String principalName )
+ private ByteBuffer encodePrincipalName( short version, String principalName )
{
String[] split = principalName.split( "@" );
- String nameComponent = split[0];
+ String nameComponentPart = split[0];
String realm = split[1];
- String[] nameComponents = nameComponent.split( "/" );
+ String[] nameComponents = nameComponentPart.split( "/" );
+
+ // Compute the size of the buffer
+ List<byte[]> strings = new ArrayList<byte[]>();
+
+ // Initialize the size with the number of components' size
+ int size = 2;
+
+ size += encodeCountedString( strings, realm );
+
+ // compute NameComponents
+ for ( String nameComponent : nameComponents )
+ {
+ size += encodeCountedString( strings, nameComponent );
+ }
- // increment for v1
- buffer.putShort( ( short ) nameComponents.length );
+ ByteBuffer buffer = ByteBuffer.allocate( size );
- putCountedString( buffer, realm );
- // write components
+ // Now, write the data into the buffer
+ // store the numComponents
+ if ( version == Keytab.VERSION_0X501 )
+ {
+ // increment for version 0x0501
+ buffer.putShort( ( short ) ( nameComponents.length + 1 ) );
+ }
+ else
+ {
+ // Version = OxO502
+ buffer.putShort( ( short ) ( nameComponents.length ) );
+ }
- for ( int ii = 0; ii < nameComponents.length; ii++ )
+ // Store the realm and the nameComponents
+ for ( byte[] string : strings )
{
- putCountedString( buffer, nameComponents[ii] );
+ buffer.putShort( ( short ) ( string.length ) );
+ buffer.put( string );
}
+
+ buffer.flip();
+
+ return buffer;
}
/**
* Encode a 16-bit encryption type and symmetric key material.
+ *
+ * We store the KeyType value ( a short ) and the KeyValue ( a length
+ * on a short and the bytes )
*/
- private void putKeyBlock( ByteBuffer buffer, EncryptionKey key )
+ private ByteBuffer encodeKeyBlock( EncryptionKey key )
{
+ byte[] keyBytes = key.getKeyValue();
+ int size = 2 + 2 + keyBytes.length; // type, length, data
+ ByteBuffer buffer = ByteBuffer.allocate( size );
+
+ // The type
buffer.putShort( ( short ) key.getKeyType().getValue() );
- putCountedBytes( buffer, key.getKeyValue() );
+
+ // Use a prefixed 16-bit length to encode raw bytes.
+ buffer.putShort( ( short ) keyBytes.length );
+ buffer.put( keyBytes );
+
+ buffer.flip();
+
+ return buffer;
}
@@ -148,20 +258,18 @@ class KeytabEncoder
* Use a prefixed 16-bit length to encode a String. Realm and name
* components are ASCII encoded text with no zero terminator.
*/
- private void putCountedString( ByteBuffer buffer, String string )
+ private short encodeCountedString( List<byte[]> nameComponentBytes, String string )
{
- byte[] data = string.getBytes();
- buffer.putShort( ( short ) data.length );
- buffer.put( data );
- }
-
+ try
+ {
+ byte[] data = string.getBytes( "US-ASCII" );
+ nameComponentBytes.add( data );
- /**
- * Use a prefixed 16-bit length to encode raw bytes.
- */
- private void putCountedBytes( ByteBuffer buffer, byte[] data )
- {
- buffer.putShort( ( short ) data.length );
- buffer.put( data );
+ return ( short ) ( data.length + 2 );
+ }
+ catch ( UnsupportedEncodingException uee )
+ {
+ throw new RuntimeException( uee.getMessage(), uee );
+ }
}
}
Modified: directory/apacheds/trunk/kerberos-codec/src/test/java/org/apache/directory/server/kerberos/shared/keytab/KeytabTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-codec/src/test/java/org/apache/directory/server/kerberos/shared/keytab/KeytabTest.java?rev=1512996&r1=1512995&r2=1512996&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-codec/src/test/java/org/apache/directory/server/kerberos/shared/keytab/KeytabTest.java (original)
+++ directory/apacheds/trunk/kerberos-codec/src/test/java/org/apache/directory/server/kerberos/shared/keytab/KeytabTest.java Sun Aug 11 20:15:10 2013
@@ -35,6 +35,7 @@ import java.util.Map;
import javax.crypto.spec.DESKeySpec;
+import org.apache.directory.api.util.Strings;
import org.apache.directory.server.kerberos.shared.crypto.encryption.KerberosKeyFactory;
import org.apache.directory.shared.kerberos.KerberosTime;
import org.apache.directory.shared.kerberos.KerberosUtils;
@@ -46,6 +47,7 @@ import org.junit.runner.RunWith;
import com.mycila.junit.concurrent.Concurrency;
import com.mycila.junit.concurrent.ConcurrentJunitRunner;
+
/**
* Tests 'keytab' formatted files.
*
@@ -92,7 +94,7 @@ public class KeytabTest
{
Keytab keytab = Keytab.read( keytab1 );
- assertTrue( "Keytab version", Arrays.equals( Keytab.VERSION_52, keytab.getKeytabVersion() ) );
+ assertTrue( "Keytab version", Arrays.equals( Keytab.VERSION_0X502_BYTES, keytab.getKeytabVersion() ) );
assertEquals( "Entries size", 1, keytab.getEntries().size() );
KeytabEntry entry = keytab.getEntries().get( 0 );
@@ -119,7 +121,7 @@ public class KeytabTest
{
Keytab keytab = Keytab.read( keytab2 );
- assertTrue( "Keytab version", Arrays.equals( Keytab.VERSION_52, keytab.getKeytabVersion() ) );
+ assertTrue( "Keytab version", Arrays.equals( Keytab.VERSION_0X502_BYTES, keytab.getKeytabVersion() ) );
assertEquals( "Entries size", 1, keytab.getEntries().size() );
KeytabEntry entry = keytab.getEntries().get( 0 );
@@ -152,6 +154,8 @@ public class KeytabTest
Keytab writer = Keytab.getInstance();
writer.setEntries( entries );
ByteBuffer buffer = writer.write();
+
+ System.out.println( Strings.dumpBytes( buffer.array() ) );
assertEquals( "Expected file size.", 130, buffer.limit() );
}