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/09/09 10:12:25 UTC

svn commit: r1520988 - in /directory/apacheds/trunk: kerberos-client/src/main/java/org/apache/directory/kerberos/client/ kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/ kerberos-client/src/main/java/org/apache/directory/kerbero...

Author: elecharny
Date: Mon Sep  9 08:12:25 2013
New Revision: 1520988

URL: http://svn.apache.org/r1520988
Log:
Applied patch from DIRSERVER-1889

Added:
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/Kinit.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheInputStream.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheOutputStream.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Credentials.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCache.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCacheConstants.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/SampleCredentialsCacheResource.java
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Tag.java
    directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/CredentialsCacheTest.java
Modified:
    directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/AbstractTicket.java
    directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/KdcConnectionTest.java
    directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/components/PrincipalName.java

Modified: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/AbstractTicket.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/AbstractTicket.java?rev=1520988&r1=1520987&r2=1520988&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/AbstractTicket.java (original)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/AbstractTicket.java Mon Sep  9 08:12:25 2013
@@ -42,7 +42,12 @@ public abstract class AbstractTicket
     }
 
 
-    /*default protected*/ Ticket getTicket()
+    public EncKdcRepPart getEncKdcRepPart()
+    {
+    	return this.encKdcRepPart;
+    }
+    
+    public Ticket getTicket()
     {
         return ticket;
     }

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/Kinit.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/Kinit.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/Kinit.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/client/Kinit.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,66 @@
+package org.apache.directory.kerberos.client;
+
+import java.io.File;
+
+import org.apache.directory.kerberos.credentials.cache.Credentials;
+import org.apache.directory.kerberos.credentials.cache.CredentialsCache;
+import org.apache.directory.shared.kerberos.codec.types.PrincipalNameType;
+import org.apache.directory.shared.kerberos.components.PrincipalName;
+
+/**
+ * Authenticates to the Kerberos server and gets the initial Ticket Granting Ticket,
+ * then cache the tgt in credentials cache, as MIT kinit does.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Kinit
+{
+	
+	private KdcConnection kdc;
+	private File credCacheFile;
+	
+	public Kinit( KdcConnection kdc )
+	{
+		this.kdc = kdc;
+	}
+	
+	public void setCredCacheFile( File credCacheFile )
+	{
+		this.credCacheFile = credCacheFile;
+	}
+	
+	public File getCredCacheFile()
+	{
+		return this.credCacheFile;
+	}
+	
+    /**
+     * Authenticates to the Kerberos server and gets the initial Ticket Granting Ticket,
+     * then cache the tgt in credentials cache, as MIT kinit does.
+     * 
+     * @param principal the client's principal 
+     * @param password password of the client
+     * @return
+     * @throws Exception
+     */
+    public void kinit( String principal, String password ) throws Exception
+    {
+    	if ( principal == null || password == null || credCacheFile == null )
+    	{
+    		throw new IllegalArgumentException( "Invalid principal, password, or credentials cache file" );
+    	}
+    	
+    	TgTicket tgt = kdc.getTgt( principal, password );
+    	
+    	CredentialsCache credCache = new CredentialsCache();
+    	
+    	PrincipalName princ = new PrincipalName( principal, PrincipalNameType.KRB_NT_PRINCIPAL );
+    	princ.setRealm( tgt.getRealm() );
+    	credCache.setPrimaryPrincipalName( princ );
+    	
+    	Credentials cred = new Credentials( tgt );
+    	credCache.addCredentials( cred );
+    	
+    	CredentialsCache.store( credCacheFile, credCache );
+    }    
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheInputStream.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheInputStream.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheInputStream.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheInputStream.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,378 @@
+/*
+ *  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.kerberos.credentials.cache;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.server.kerberos.protocol.codec.KerberosDecoder;
+import org.apache.directory.shared.kerberos.KerberosTime;
+import org.apache.directory.shared.kerberos.codec.types.AuthorizationType;
+import org.apache.directory.shared.kerberos.codec.types.EncryptionType;
+import org.apache.directory.shared.kerberos.codec.types.HostAddrType;
+import org.apache.directory.shared.kerberos.components.AuthorizationData;
+import org.apache.directory.shared.kerberos.components.AuthorizationDataEntry;
+import org.apache.directory.shared.kerberos.components.EncryptionKey;
+import org.apache.directory.shared.kerberos.components.HostAddress;
+import org.apache.directory.shared.kerberos.components.HostAddresses;
+import org.apache.directory.shared.kerberos.components.PrincipalName;
+import org.apache.directory.shared.kerberos.flags.TicketFlags;
+
+/**
+ * Reading credentials cache according to FCC format by reference the following
+ * https://www.gnu.org/software/shishi/manual/html_node/The-Credential-Cache-Binary-File-Format.html
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CacheInputStream extends DataInputStream
+{	
+	public CacheInputStream( InputStream in )
+	{
+        super( in );
+    }
+
+    public void read(CredentialsCache cache) throws IOException 
+    {   
+    	int version;
+    	List<Tag> tags;
+    	PrincipalName principal;
+    	Credentials cred; 
+    	
+        version = readVersion();
+        cache.setVersion( version );
+        
+        if ( version == CredentialsCacheConstants.FCC_FVNO_4 )
+        {
+            tags = readTag();
+        } 
+        else
+        {
+            tags = null;
+        }
+        cache.setTags( tags );
+        
+        principal = readPrincipal( version );
+        cache.setPrimaryPrincipalName( principal );
+        
+        while ( available() > 0 )
+        {
+            cred = readCredentials( version );
+            if (cred != null)
+            {
+                cache.addCredentials( cred );
+            }
+        }
+    }
+    
+    private int readVersion() throws IOException
+    {
+        int result = readShort();
+        return result;
+    }
+    
+    private List<Tag> readTag() throws IOException
+    {
+    	int len;
+    	int tag;
+    	int taglen;
+    	int time;
+    	int usec;
+
+    	len = readShort();
+    	List<Tag> tags = new ArrayList<Tag>();
+    	
+    	while (len > 0)
+    	{
+    		tag = readShort();
+    		taglen = readShort();
+    		switch (tag)
+    		{
+    			case CredentialsCacheConstants.FCC_TAG_DELTATIME:
+    				time = readInt();
+    				usec = readInt();
+    				tags.add(new Tag(tag, time, usec));
+    				break;
+    			default:
+    				read( new byte[taglen], 0, taglen ); // ignore unknown tag
+    		}
+    		len = len - (4 + taglen);
+    	}
+    	
+    	return tags;
+    }
+    
+    private PrincipalName readPrincipal( int version ) throws IOException 
+    {
+        int type, length;
+        PrincipalName pname;
+
+        if (version == CredentialsCacheConstants.FCC_FVNO_1)
+        {
+            type = CredentialsCacheConstants.NT_UNKNOWN;
+        }
+        else
+        {
+            type = readInt();
+        }
+        length = readInt();
+        
+        if (version == CredentialsCacheConstants.FCC_FVNO_1)
+        {
+            length--;
+        }
+        
+        String realm = readCountedString();
+        
+        String[] result = new String[length];
+        for ( int i = 0; i < length; i++ )
+        {
+        	result[i] = readCountedString();
+        }
+ 
+        pname = new PrincipalName(result, type);
+        if ( isRealm( realm ) )
+        {
+        	pname.setRealm( realm );
+        }
+
+        return pname;
+    }
+
+    private String readCountedString() throws IOException {
+        int namelength = readInt();
+        if ( namelength > CredentialsCacheConstants.MAXNAMELENGTH )
+        {
+            throw new IOException("Invalid name length in principal name.");
+        }
+        byte[] bytes = new byte[namelength];
+        read( bytes, 0, bytes.length );
+        
+        return new String( bytes );
+    }
+    
+    /*
+	 * Domain style realm names MUST look like domain names: they consist of
+     * components separated by periods (.) and they contain neither colons
+     * (:) nor slashes (/). When establishing a new realm name based on an 
+     * internet domain name it is recommended by convention that the characters 
+     * be converted to uppercase.
+     */
+    private static boolean isRealm( String str )
+    {
+    	char chr;
+    	for ( int i = 0; i < str.length(); i++ )
+    	{
+    		chr = str.charAt(i);
+    		if ( chr != '.' && chr >= 'a' )
+    		{
+    			return false;
+    		}
+    	}
+    	
+    	return true;
+    }
+    
+    private EncryptionKey readKey(int version) throws IOException
+    {
+        int keyType, keyLen;
+        keyType = readShort();
+        if ( version == CredentialsCacheConstants.FCC_FVNO_3 )
+            readShort();
+        // It's not correct with "uint16_t keylen", instead "uint32_t keylen" in keyblock 
+        keyLen = readInt();
+        byte[] bytes = new byte[keyLen];
+        read( bytes, 0, bytes.length );
+        
+        return new EncryptionKey( EncryptionType.getTypeByValue( keyType ), bytes );
+    }
+
+    private KerberosTime[] readKerberosTimes() throws IOException
+    {
+    	long[] times = readTimes();
+    	KerberosTime[] results = new KerberosTime[times.length];
+    	KerberosTime ktime;
+    	for ( int i = 0; i < times.length; ++i ) 
+    	{
+    		ktime = times[i] == 0 ? null : new KerberosTime( times[i] );
+    		results[i] = ktime;
+    	}
+    	
+    	return results;
+    }
+    
+    private long[] readTimes() throws IOException
+    {
+        long[] times = new long[4];
+        times[0] = (long)readInt() * 1000;
+        times[1] = (long)readInt() * 1000;
+        times[2] = (long)readInt() * 1000;
+        times[3] = (long)readInt() * 1000;
+        return times;
+    }
+
+    private boolean readskey() throws IOException
+    {
+        if ( read() == 0 )
+        {
+            return false;
+        }
+        
+        return true;
+    }
+
+    private HostAddress[] readAddr() throws IOException
+    {
+        int numAddrs, addrType, addrLength;
+        numAddrs = readInt();
+        if ( numAddrs > 0 )
+        {
+            HostAddress[] addrs = new HostAddress[numAddrs];
+            for ( int i = 0; i < numAddrs; i++ )
+            {
+                addrType = readShort();
+                addrLength = readInt();
+                if ( !( addrLength == 4 || addrLength == 16 ) )
+                {
+                    return null;
+                }
+                byte[] result = new byte[addrLength];
+                for (int j = 0; j < addrLength; j++)
+                {
+                    result[j] = (byte)readByte();
+                }
+                addrs[i] = new HostAddress( HostAddrType.getTypeByOrdinal( addrType ), result );
+            }
+            return addrs;
+        }
+        
+        return null;
+    }
+
+    private AuthorizationDataEntry[] readAuth() throws IOException
+    {
+        int num, adtype, adlength;
+        num = readInt();
+        if ( num > 0 )
+        {
+            AuthorizationDataEntry[] auData = new AuthorizationDataEntry[num];
+            byte[] data = null;
+            for (int i = 0; i < num; i++)
+            {
+                adtype = readShort();
+                adlength = readInt();
+                data = new byte[adlength];
+                read( data, 0, data.length );
+                auData[i] = new AuthorizationDataEntry( AuthorizationType.getTypeByValue( adtype ), data );
+            }
+            return auData;
+        }
+        
+        return null;
+    }
+
+    private byte[] readData() throws IOException
+    {
+        int length;
+        length = readInt();
+        if ( length == 0 )
+        {
+            return null;
+        }
+        else 
+        {
+            byte[] bytes = new byte[length];
+            read( bytes, 0, length );
+            return bytes;
+        }
+    }
+
+    private int readFlags() throws IOException
+    {
+        int ticketFlags;
+        ticketFlags = readInt();
+        return ticketFlags;
+    }
+
+    private Credentials readCredentials( int version ) throws IOException
+    {
+        PrincipalName cpname = readPrincipal(version);
+        PrincipalName spname = readPrincipal(version);
+        
+        if ( cpname == null || spname == null )
+        {
+        	throw new IOException("Invalid client principal name or service principal name");
+        }
+        
+        EncryptionKey key = readKey(version);
+
+        KerberosTime[] times = readKerberosTimes();
+        KerberosTime authtime = times[0];
+        KerberosTime starttime = times[1];
+        KerberosTime endtime = times[2];
+        KerberosTime renewTill = times[3];
+        
+        boolean skey = readskey();
+        
+        int flags = readFlags();
+        TicketFlags tFlags = new TicketFlags(flags);
+        HostAddress addr[] = readAddr();
+        HostAddresses addrs = null;
+        if (addr != null)
+        {
+            addrs = new HostAddresses(addr);
+        }
+        
+        AuthorizationDataEntry[] auDataEntries = readAuth();
+        AuthorizationData auData = null;
+        if (auDataEntries != null)
+        {
+        	auData = new AuthorizationData();
+        	for (AuthorizationDataEntry ade : auDataEntries)
+        	{
+        		auData.addEntry(ade);
+        	}
+        }
+        
+        byte[] ticketData = readData();
+        byte[] ticketData2 = readData();
+
+        if ( version != CredentialsCacheConstants.FCC_FVNO_1 && 
+        		spname.getNameType().getValue() == CredentialsCacheConstants.NT_UNKNOWN )
+        {
+        	// skip krb5_ccache_conf_data/fast_avail/krbtgt/REALM@REALM in MIT KRB5
+        	return null; 
+        }
+        
+        try 
+        {
+            return new Credentials(cpname, spname, key, authtime, starttime,
+                endtime, renewTill, skey, tFlags, addrs, auData,
+                ticketData != null ? KerberosDecoder.decodeTicket( ticketData ) : null,
+                ticketData2 != null ? KerberosDecoder.decodeTicket( ticketData2 ) : null);
+        }
+        catch (Exception e)
+        {
+            return null;
+        }
+    }
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheOutputStream.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheOutputStream.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheOutputStream.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CacheOutputStream.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,252 @@
+/*
+ *  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.kerberos.credentials.cache;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+import org.apache.directory.server.kerberos.protocol.codec.KerberosEncoder;
+import org.apache.directory.shared.kerberos.KerberosTime;
+import org.apache.directory.shared.kerberos.components.AuthorizationData;
+import org.apache.directory.shared.kerberos.components.AuthorizationDataEntry;
+import org.apache.directory.shared.kerberos.components.EncryptionKey;
+import org.apache.directory.shared.kerberos.components.HostAddress;
+import org.apache.directory.shared.kerberos.components.HostAddresses;
+import org.apache.directory.shared.kerberos.components.PrincipalName;
+import org.apache.directory.shared.kerberos.messages.Ticket;
+
+/**
+ * Writing credentials cache according to FCC format by reference the following
+ * https://www.gnu.org/software/shishi/manual/html_node/The-Credential-Cache-Binary-File-Format.html
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CacheOutputStream extends DataOutputStream
+{
+	
+	public CacheOutputStream( OutputStream out )
+	{
+        super( out );
+    }
+
+    public void write( CredentialsCache credCache ) throws IOException 
+    {   
+    	/**
+    	 * Currently we always write using this version to limit the test effort.
+    	 * This version seems to be the easiest to be compatible with MIT tools.
+    	 * In future we might allow to specify the format version to write if necessary. 
+    	 */
+    	int writeVersion = CredentialsCacheConstants.FCC_FVNO_3;
+    	
+        writeVersion( writeVersion );
+        
+        if ( writeVersion == CredentialsCacheConstants.FCC_FVNO_4 )
+        {
+        	writeTags( credCache.getTags() );
+        }
+        
+        writePrincipal( credCache.getPrimaryPrincipalName(), writeVersion );
+
+        List<Credentials> credentialsList = credCache.getCredsList();
+        if ( credentialsList != null )
+        {
+            for ( Credentials cred : credentialsList )
+            {
+                writeCredentials( cred, writeVersion );
+            }
+        }
+    }
+
+    private void writeVersion( int version ) throws IOException 
+    {
+        writeShort( version );        
+    }
+
+    private void writeTags( List<Tag> tags ) throws IOException 
+    {
+    	int length = 0;
+    	if ( tags != null )
+    	{
+    		for ( Tag tag : tags ) 
+    		{
+    			if ( tag.tag != CredentialsCacheConstants.FCC_TAG_DELTATIME ) 
+    			{
+    				continue;
+    			}
+    			length += tag.length;
+    		}
+    	}
+    	
+    	writeShort( length );
+    	
+    	if ( tags != null )
+    	{
+    		for ( Tag tag : tags ) 
+    		{
+    			if ( tag.tag != CredentialsCacheConstants.FCC_TAG_DELTATIME ) 
+    			{
+    				continue;
+    			}
+    			writeTag( tag );
+    		}
+    	}
+    }
+    
+    private void writeTag( Tag tag ) throws IOException
+    {
+        writeShort( tag.tag );
+        writeShort( tag.length );
+        writeInt( tag.time );
+        writeInt( tag.usec );
+    }
+    
+    private void writePrincipal( PrincipalName pname, int version ) throws IOException
+    {
+        int num = pname.getNames().size();
+        
+    	if ( version != CredentialsCacheConstants.FCC_FVNO_1 )
+        {
+        	writeInt( pname.getNameType().getValue() );
+        }
+    	else
+    	{
+        	num++;
+        }
+        
+        writeInt( num );
+        
+        if ( pname.getRealm() != null) 
+        {
+            byte[] realmBytes = null;
+            realmBytes = pname.getRealm().getBytes();
+            writeInt( realmBytes.length );
+            write( realmBytes );
+        }
+        else
+        {
+        	writeInt( 0 );
+        }
+        
+        byte[] bytes = null;
+        for ( int i = 0; i < pname.getNames().size(); i++ )
+        {
+            bytes = pname.getNames().get( i ).getBytes();
+            writeInt( bytes.length );
+            write( bytes );
+        }
+    }
+    
+    private void writeCredentials( Credentials creds, int version ) throws IOException
+    {
+        writePrincipal( creds.getClientName(), version );
+        writePrincipal( creds.getServerName(), version );
+        writeKey( creds.getKey(), version );
+
+        writeKerberosTime( creds.getAuthTime() );
+        writeKerberosTime( creds.getStartTime() );
+        writeKerberosTime( creds.getEndTime() );
+        writeKerberosTime( creds.getRenewTill() );
+        
+        writeByte( creds.isEncInSKey() ? 1 : 0);
+        
+        writeInt( creds.getFlags().getIntValue() );
+        
+        writeAddrs( creds.getClientAddresses() );
+        writeAuth( creds.getAuthzData() );
+        
+        writeTicket( creds.getTicket() );
+        writeTicket( creds.getSecondTicket() );
+    }
+
+    private void writeKerberosTime( KerberosTime ktime) throws IOException
+    {
+    	int time = 0;
+    	if (ktime != null)
+    	{
+    		time = (int) ( ktime.getTime() / 1000 );
+    	}
+    	writeInt( time );
+    }
+    
+    private void writeKey( EncryptionKey key, int version ) throws IOException 
+    {
+    	writeShort( key.getKeyType().getValue());
+    	if ( version == CredentialsCacheConstants.FCC_FVNO_3 )
+    	{
+    		writeShort( key.getKeyType().getValue() );
+    	}
+    	// It's not correct with "uint16_t keylen", instead "uint32_t keylen" in keyblock    	
+    	writeInt( key.getKeyValue().length );
+    	write( key.getKeyValue() );
+    }
+    
+    private void writeAddrs( HostAddresses addresses ) throws IOException 
+    {
+    	if (addresses == null)
+    	{
+    		writeInt( 0 );
+    	}
+    	else
+    	{
+    		HostAddress[] addrs = addresses.getAddresses();
+    		write( addrs.length );
+    		for ( int i = 0; i < addrs.length; i++ )
+    		{
+    			write( addrs[i].getAddrType().getValue() );
+    			write( addrs[i].getAddress().length );
+    			write( addrs[i].getAddress(), 0,
+    					addrs[i].getAddress().length );
+    		}
+    	}
+    }
+    
+    private void writeAuth( AuthorizationData authData ) throws IOException 
+    {
+    	if ( authData == null )
+    	{
+    		writeInt( 0 );
+    	}
+    	else
+    	{
+    		for (AuthorizationDataEntry ade : authData.getAuthorizationData())
+    		{
+    			write(ade.getAdType().getValue());
+    			write(ade.getAdData().length);
+    			write(ade.getAdData());
+    		}
+    	}
+    }
+    
+    private void writeTicket( Ticket t ) throws IOException 
+    {
+        if (t == null)
+        {
+            writeInt( 0 );
+        }
+        else
+        {
+            byte[] bytes = KerberosEncoder.encode(t, false).array();
+            writeInt( bytes.length );
+            write( bytes );
+        }
+    }
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Credentials.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Credentials.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Credentials.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Credentials.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,216 @@
+
+package org.apache.directory.kerberos.credentials.cache;
+
+import java.text.ParseException;
+
+import org.apache.directory.kerberos.client.AbstractTicket;
+import org.apache.directory.kerberos.client.TgTicket;
+import org.apache.directory.shared.kerberos.KerberosTime;
+import org.apache.directory.shared.kerberos.codec.types.PrincipalNameType;
+import org.apache.directory.shared.kerberos.components.AuthorizationData;
+import org.apache.directory.shared.kerberos.components.EncKdcRepPart;
+import org.apache.directory.shared.kerberos.components.EncryptionKey;
+import org.apache.directory.shared.kerberos.components.HostAddresses;
+import org.apache.directory.shared.kerberos.components.PrincipalName;
+import org.apache.directory.shared.kerberos.flags.TicketFlags;
+import org.apache.directory.shared.kerberos.messages.Ticket;
+
+/**
+ * Looks like KrbCredInfo can be used here, however it's not enough for this
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Credentials
+{
+
+    private PrincipalName clientName;
+    private String clientRealm;
+    private PrincipalName serverName;
+    private String serverRealm;
+    private EncryptionKey key;
+    private KerberosTime authTime;
+    private KerberosTime startTime;
+    private KerberosTime endTime;
+    private KerberosTime renewTill;
+    private HostAddresses clientAddresses;
+    private AuthorizationData authzData;
+    private boolean isEncInSKey;
+    private TicketFlags flags;
+    private Ticket ticket;
+    private Ticket secondTicket;
+    
+    public Credentials(
+            PrincipalName cname,
+            PrincipalName sname,
+            EncryptionKey ekey,
+            KerberosTime authtime,
+            KerberosTime starttime,
+            KerberosTime endtime,
+            KerberosTime renewTill,
+            boolean isEncInSKey,
+            TicketFlags flags,
+            HostAddresses caddr,
+            AuthorizationData authData,
+            Ticket ticket,
+            Ticket secondTicket)
+    {
+        this.clientName = (PrincipalName) cname;
+
+        if (cname.getRealm() != null)
+        {
+            clientRealm = cname.getRealm();
+        }
+
+        this.serverName = (PrincipalName) sname;
+
+        if (sname.getRealm() != null)
+        {
+            serverRealm = sname.getRealm();
+        }
+
+        this.key = ekey;
+
+        this.authTime = authtime;
+        this.startTime = starttime;
+        this.endTime = endtime;
+        this.renewTill = renewTill;
+        this.clientAddresses = caddr;
+        this.authzData = authData;
+        this.isEncInSKey = isEncInSKey;
+        this.flags = flags;
+        this.ticket = ticket;
+        this.secondTicket = secondTicket;
+    }
+
+    public Credentials( TgTicket tgt )
+    {
+    	PrincipalName clientPrincipal = null;
+    	try {
+			clientPrincipal = new PrincipalName( tgt.getClientName(), 
+					PrincipalNameType.KRB_NT_PRINCIPAL );
+		} catch (ParseException e) {
+			throw new RuntimeException( "Invalid tgt with bad client name" );
+		}
+    	
+    	clientPrincipal.setRealm( tgt.getRealm() );
+    	
+    	init( tgt, clientPrincipal );
+    }
+    
+    public Credentials( AbstractTicket tkt, PrincipalName clientPrincipal ) 
+    {
+    	init( tkt, clientPrincipal );
+    }
+    
+    private void init( AbstractTicket tkt, PrincipalName clientPrincipal )
+    {
+    	EncKdcRepPart kdcRepPart = tkt.getEncKdcRepPart();
+    	
+        this.serverName = kdcRepPart.getSName();
+        this.serverRealm = kdcRepPart.getSRealm();
+        this.serverName.setRealm(serverRealm);
+
+        this.clientName = clientPrincipal;
+        
+        this.key = kdcRepPart.getKey();
+        this.authTime = kdcRepPart.getAuthTime();
+        this.startTime = kdcRepPart.getStartTime();
+        this.endTime = kdcRepPart.getEndTime();
+
+        this.renewTill = kdcRepPart.getRenewTill();
+
+        this.flags = kdcRepPart.getFlags();
+        this.clientAddresses = kdcRepPart.getClientAddresses();
+
+        this.ticket = tkt.getTicket();
+        
+        this.isEncInSKey = false;
+        
+        this.secondTicket = null;
+    }
+
+    public PrincipalName getServicePrincipal()
+    {
+        return serverName;
+    }
+
+    public KerberosTime getAuthTime()
+    {
+        return authTime;
+    }
+
+    public KerberosTime getEndTime()
+    {
+        return endTime;
+    }
+
+    public TicketFlags getTicketFlags()
+    {
+        return flags;
+    }
+
+    public int getEType()
+    {
+        return key.getKeyType().getValue();
+    }
+
+	public PrincipalName getClientName()
+	{
+		return clientName;
+	}
+
+	public PrincipalName getServerName()
+	{
+		return serverName;
+	}
+	
+	public String getClientRealm()
+	{
+		return clientRealm;
+	}
+
+	public EncryptionKey getKey()
+	{
+		return key;
+	}
+
+	public KerberosTime getStartTime()
+	{
+		return startTime;
+	}
+
+	public KerberosTime getRenewTill()
+	{
+		return renewTill;
+	}
+
+	public HostAddresses getClientAddresses()
+	{
+		return clientAddresses;
+	}
+
+	public AuthorizationData getAuthzData()
+	{
+		return authzData;
+	}
+
+	public boolean isEncInSKey()
+	{
+		return isEncInSKey;
+	}
+
+	public TicketFlags getFlags()
+	{
+		return flags;
+	}
+
+	public Ticket getTicket()
+	{
+		return ticket;
+	}
+	
+	public Ticket getSecondTicket()
+	{
+		return secondTicket;
+	}
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCache.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCache.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCache.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCache.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,142 @@
+package org.apache.directory.kerberos.credentials.cache;
+
+import java.io.ByteArrayInputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+import org.apache.directory.shared.kerberos.components.PrincipalName;
+
+/**
+ * Kerberos credentials cache in FCC format
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CredentialsCache
+{	
+	private int version = CredentialsCacheConstants.FCC_FVNO_4;
+	private List<Tag> tags;
+	private PrincipalName primaryPrincipal;
+	private List<Credentials> credentialsList = new ArrayList<Credentials> ();
+	
+    public static CredentialsCache load( File cacheFile ) throws IOException 
+    {
+        return load(new FileInputStream( cacheFile ));
+    }
+    
+    public static CredentialsCache load( InputStream is ) throws IOException 
+    {
+        CacheInputStream cis = new CacheInputStream(is);
+        
+        CredentialsCache credCache = new CredentialsCache();
+        cis.read(credCache);
+        
+        cis.close();
+        
+        return credCache;
+    }
+    
+    public static void store( File fileName, CredentialsCache credCache ) throws IOException 
+    {
+        store( new FileOutputStream(fileName), credCache );
+    }
+    
+    public static void store( OutputStream os, CredentialsCache credCache ) throws IOException 
+    {
+        CacheOutputStream cos = new CacheOutputStream(os);
+        
+        cos.write( credCache );
+        
+        cos.close();
+    }
+    
+    public void addCredentials( Credentials cred )
+    {
+    	this.credentialsList.add( cred );
+    }
+    
+    public int getVersion()
+    {
+    	return this.version;
+    }
+    
+    public void setVersion( int version )
+    {
+    	this.version = version;
+    }
+    
+    /**
+     * Returns the primary principal
+     */
+    public PrincipalName getPrimaryPrincipalName() 
+    {
+    	return this.primaryPrincipal;
+    }
+    
+    /**
+     * Set the primary principal
+     */
+    public void setPrimaryPrincipalName( PrincipalName principal ) 
+    {
+    	this.primaryPrincipal = principal;
+    }
+    
+    public void setTags( List<Tag> tags )
+    {
+    	this.tags = tags;
+    }
+    
+    public List<Tag> getTags()
+    {
+    	return this.tags;
+    }
+    
+    /**
+     * Returns the credentials entries
+     */
+    public List<Credentials> getCredsList() 
+    {
+    	return this.credentialsList;
+    }
+
+    
+    public static void main(String[] args) throws IOException
+    {
+    	String dumpFile = File.createTempFile( "credCache-", ".cc" ).getAbsolutePath();
+    	System.out.println( "This tool tests CredentialsCache reading and writing, " + 
+				"and will load the built-in sample credentials cache by default, and dump to " + dumpFile );
+    	
+    	System.out.println( "To specify your own credentials cache file, run this as: CredentialsCache [cred-cache-file] " );
+    	
+    	System.out.println( "When dumped successfully, run 'klist -e -c' from MIT to check the dumped file" );
+    	
+    	CredentialsCache cc;
+    	String cacheFile = args.length > 0 ? args[0] : null;
+    	if (cacheFile == null)
+    	{    		
+    		byte[] sampleCache = SampleCredentialsCacheResource.getCacheContent();
+    		ByteArrayInputStream bais = new ByteArrayInputStream(sampleCache);
+    		cc = CredentialsCache.load(bais);
+    	} 
+    	else
+    	{
+    		cc = CredentialsCache.load( new File( cacheFile ) );
+    	}
+    	
+    	if ( cc != null )
+    	{
+    		System.out.println( "Reading credentials cache is successful" );
+    		
+    		File tmpCacheFile = new File(dumpFile);
+    		tmpCacheFile.delete();
+    		CredentialsCache.store(tmpCacheFile, cc);
+
+    		System.out.println( "Writing credentials cache successfully to: " + dumpFile );
+    	}
+    }
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCacheConstants.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCacheConstants.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCacheConstants.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/CredentialsCacheConstants.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,35 @@
+/*
+ *  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.kerberos.credentials.cache;
+
+/**
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public interface CredentialsCacheConstants
+{
+    public static final int FCC_FVNO_1 = 0x501;
+    public static final int FCC_FVNO_2 = 0x502;
+    public static final int FCC_FVNO_3 = 0x503;
+    public static final int FCC_FVNO_4 = 0x504;
+    public static final int FCC_TAG_DELTATIME = 1;
+    public static final int NT_UNKNOWN = 0;
+    public static final int MAXNAMELENGTH = 1024;
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/SampleCredentialsCacheResource.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/SampleCredentialsCacheResource.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/SampleCredentialsCacheResource.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/SampleCredentialsCacheResource.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,110 @@
+/*
+ *  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.kerberos.credentials.cache;
+
+
+import org.apache.directory.api.util.Base64;
+
+
+/**
+ * This is a sample credentials cache generated using MIT KRB5 kinit command.
+ * SAMPLE_CACHE_CONTENT is the content of the sample cache encoded in base64.
+ * It's not just for unit test, but also for development, so better to maintain it here,
+ * instead of just as resource file.
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class SampleCredentialsCacheResource
+{
+	/**
+	 * klist
+     * Ticket cache: FILE:/tmp/krb5cc_0
+     * Default principal: apacheds@SH.INTEL.COM
+     *
+     * Valid starting     Expires            Service principal
+     * 09/06/13 01:54:10  09/06/13 11:54:10  krbtgt/SH.INTEL.COM@SH.INTEL.COM
+	 * renew until 09/07/13 01:54:07
+     * 09/06/13 01:54:11  09/06/13 11:54:10  host/hadoop-nn.sh.intel.com@SH.INTEL.COM
+	 * renew until 09/07/13 01:54:07
+	 */
+	private static final String SAMPLE_CACHE_CONTENT = 
+			        "BQQADAABAAgAAAAAAAAAAAAAAAEAAAABAAAADFNILklOVEVMLkNPTQAAAAhhcGFjaGVkcwAAAAEA" +
+					"AAABAAAADFNILklOVEVMLkNPTQAAAAhhcGFjaGVkcwAAAAIAAAACAAAADFNILklOVEVMLkNPTQAA" +
+					"AAZrcmJ0Z3QAAAAMU0guSU5URUwuQ09NAAEAAAAI3H/4OE/NpCpSKGeiUihnolIo9EJSKbkfAEDh" +
+					"AAAAAAAAAAAAAAAAAUFhggE9MIIBOaADAgEFoQ4bDFNILklOVEVMLkNPTaIhMB+gAwIBAqEYMBYb" +
+					"BmtyYnRndBsMU0guSU5URUwuQ09No4H+MIH7oAMCARehAwIBAaKB7gSB6/v51fFhnp/E2uto2e9I" +
+					"9+RUk2grlKW9pYQUc4lAV602hdP6I80s1KU1rNtezbmf8plmxdZ48yogt0KwzAoGoFWCiZk4S1dR" +
+					"zzvl/TmNtk9q1gFuVycoP1EvScPYWhdTPAR4/t1Si1DKrYY19eegYmv6PfKoisdAADatLOjqJsVc" +
+					"Ntl/cUU4qUJfm181X1b+mguIdAX4jKzWbEc52pYQr8UIDl3TNT8OIzmQC0Wjn93ocOpKwOGsclbN" +
+					"OoxSfqpxvARjg+uE5HSm5tX7nUsccjhKMJ76Uy78CEULXkg6ySPYiim5wKVvgwxI7/AAAAAAAAAA" +
+					"AQAAAAEAAAAMU0guSU5URUwuQ09NAAAACGFwYWNoZWRzAAAAAAAAAAMAAAAMWC1DQUNIRUNPTkY6" +
+					"AAAAFWtyYjVfY2NhY2hlX2NvbmZfZGF0YQAAAApmYXN0X2F2YWlsAAAAIGtyYnRndC9TSC5JTlRF" +
+					"TC5DT01AU0guSU5URUwuQ09NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD" +
+					"eWVzAAAAAAAAAAEAAAABAAAADFNILklOVEVMLkNPTQAAAAhhcGFjaGVkcwAAAAMAAAACAAAADFNI" +
+					"LklOVEVMLkNPTQAAAARob3N0AAAAFmhhZG9vcC1ubi5zaC5pbnRlbC5jb20AAQAAAAgsx5ub9wI0" +
+					"01IoZ6JSKGemUij0QlIpuR8AQKkAAAAAAAAAAAAAAAABX2GCAVswggFXoAMCAQWhDhsMU0guSU5U" +
+					"RUwuQ09NoikwJ6ADAgEDoSAwHhsEaG9zdBsWaGFkb29wLW5uLnNoLmludGVsLmNvbaOCARMwggEP" +
+					"oAMCARehAwIBB6KCAQEEgf7Z6Xz1bYJ9uE4e2Buyrp2aflcqgVoh9YUVAZyIiqpsrMa71wMuZFUl" +
+					"FD+S58Q3T39pZ9vIfXENNoKje1Y5kyImPHC1D/eHIeUN9v5kmDPJP9U31di8dOi3TbHUQWWLbB6k" +
+					"+uQE25GAP2hQg0vm5WtU3Fjo0ysXQTMpe+FSwe9ca9V3soPSbDhmlEt8WjAY05iXD8Fe6o/aY/PJ" +
+					"nElmCwQayRT87vENJI9LeMVEzhIjxBmg124G4nGnjUCaf++G03kJ04mLFZDB9kS8sA7V8AT1IF00" +
+					"ehpt7c9KbUM1Iz/S3Ni5hq8IfdOTSWMjGdNIsUMhJmivYFzQ0PRBzSBxbAAAAAA=";
+	
+	private static final String SAMPLE_PRINCIPAL = "apacheds";
+	private static final String SAMPLE_REALM = "SH.INTEL.COM";
+	private static final String[] SAMPLE_SERVERS = new String[] {"krbtgt/SH.INTEL.COM", "host/hadoop-nn.sh.intel.com"};
+	
+	public static byte[] getCacheContent()
+	{
+		byte[] content = Base64.decode(SampleCredentialsCacheResource.SAMPLE_CACHE_CONTENT.toCharArray());
+		return content;
+	}
+	
+	/**
+	 * Get the primary principal name contained in the sample cache
+	 */
+	public static String getSamplePrincipal()
+	{
+		return SAMPLE_PRINCIPAL;
+	}
+	
+	/**
+	 * Get the realm contained in the sample cache
+	 */
+	public static String getSampleRealm()
+	{
+		return SAMPLE_REALM;
+	}
+	
+	/**
+	 * Get the servers in the tickets contained in the sample cache
+	 */
+	public static String[] getSampleServers()
+	{
+		return SAMPLE_SERVERS;
+	}
+
+	/**
+	 * Get the tickets count in the sample cache
+	 */
+	public static int getSampleTicketsCount() {
+		return 2;
+	}
+}

Added: directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Tag.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Tag.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Tag.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/main/java/org/apache/directory/kerberos/credentials/cache/Tag.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,21 @@
+package org.apache.directory.kerberos.credentials.cache;
+
+/**
+ * 
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class Tag
+{
+    int tag = 0;
+    int tagLen = 8;
+    int time = 0;
+    int usec = 0;
+    int length = 2 + 2 + 8; // len(tag) + len(tagLen) + len(tagData);
+
+    public Tag(int tag, int time, int usec)
+    {
+        this.tag = tag;
+        this.time = time;
+        this.usec = usec;
+    }
+}

Added: directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/CredentialsCacheTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/CredentialsCacheTest.java?rev=1520988&view=auto
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/CredentialsCacheTest.java (added)
+++ directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/CredentialsCacheTest.java Mon Sep  9 08:12:25 2013
@@ -0,0 +1,75 @@
+/*
+ *  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.kerberos.client;
+
+
+import static org.junit.Assert.assertTrue;
+import static org.junit.Assert.fail;
+
+import java.io.ByteArrayInputStream;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.directory.kerberos.credentials.cache.Credentials;
+import org.apache.directory.kerberos.credentials.cache.CredentialsCache;
+import org.apache.directory.kerberos.credentials.cache.SampleCredentialsCacheResource;
+import org.apache.directory.shared.kerberos.components.PrincipalName;
+import org.junit.Test;
+
+/**
+ *
+ * @author <a href="mailto:dev@directory.apache.org">Apache Directory Project</a>
+ */
+public class CredentialsCacheTest
+{	
+    @Test
+    public void testReadMITCredCache()
+    {
+    	byte[] sampleCache = SampleCredentialsCacheResource.getCacheContent();
+    	ByteArrayInputStream bais = new ByteArrayInputStream(sampleCache);
+    	    	
+        try
+        {
+        	CredentialsCache cc = CredentialsCache.load(bais);
+        	
+            PrincipalName principal = cc.getPrimaryPrincipalName();
+            assertTrue( principal.getNameString().equals( SampleCredentialsCacheResource.getSamplePrincipal() ) );
+            assertTrue( principal.getRealm().equals( SampleCredentialsCacheResource.getSampleRealm() ) );
+            
+            assertTrue( cc.getCredsList().size() == SampleCredentialsCacheResource.getSampleTicketsCount() );
+            
+            Set<String> servers = new HashSet<String>();
+            for (String server : SampleCredentialsCacheResource.getSampleServers())
+            {
+            	servers.add( server );
+            }
+            
+            String tktServer;
+            for (Credentials cred : cc.getCredsList()) {
+            	tktServer = cred.getTicket().getSName().getNameString();
+            	assertTrue( servers.contains( tktServer ) );
+            }
+        }
+        catch ( Exception ike )
+        {
+            fail( "Testing failed due to " + ike.getMessage() );
+        }
+    }
+}

Modified: directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/KdcConnectionTest.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/KdcConnectionTest.java?rev=1520988&r1=1520987&r2=1520988&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/KdcConnectionTest.java (original)
+++ directory/apacheds/trunk/kerberos-client/src/test/java/org/apache/directory/kerberos/client/KdcConnectionTest.java Mon Sep  9 08:12:25 2013
@@ -26,9 +26,13 @@ import static org.junit.Assert.assertNot
 import static org.junit.Assert.assertTrue;
 import static org.junit.Assert.fail;
 
+import java.io.File;
+
 import org.apache.directory.api.ldap.model.entry.DefaultEntry;
 import org.apache.directory.api.ldap.model.entry.Entry;
 import org.apache.directory.api.ldap.model.name.Dn;
+import org.apache.directory.kerberos.client.Kinit;
+import org.apache.directory.kerberos.credentials.cache.CredentialsCache;
 import org.apache.directory.server.annotations.CreateChngPwdServer;
 import org.apache.directory.server.annotations.CreateKdcServer;
 import org.apache.directory.server.annotations.CreateLdapServer;
@@ -221,6 +225,19 @@ public class KdcConnectionTest extends A
         assertNotNull( rep );
     }
     
+    @Test
+    public void testKinit() throws Exception
+    {
+    	File ccFile = File.createTempFile( "credCache-", ".cc" );
+    	Kinit kinit = new Kinit( conn );
+    	kinit.setCredCacheFile( ccFile );
+    	
+    	kinit.kinit(principalName, userPassword);
+    	System.out.println( "Kinit generated file " + ccFile.getAbsolutePath() );
+    	
+    	CredentialsCache credCache = CredentialsCache.load( ccFile );    	
+        assertNotNull( credCache );
+    }
     
     @Test
     public void testChangePassword() throws Exception

Modified: directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/components/PrincipalName.java
URL: http://svn.apache.org/viewvc/directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/components/PrincipalName.java?rev=1520988&r1=1520987&r2=1520988&view=diff
==============================================================================
--- directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/components/PrincipalName.java (original)
+++ directory/apacheds/trunk/kerberos-codec/src/main/java/org/apache/directory/shared/kerberos/components/PrincipalName.java Mon Sep  9 08:12:25 2013
@@ -166,6 +166,7 @@ public class PrincipalName extends Abstr
         try
         {
             nameString = KerberosUtils.getNames( principal );
+            realm = principal.getRealm();
         }
         catch ( ParseException pe )
         {
@@ -189,7 +190,32 @@ public class PrincipalName extends Abstr
         this.nameType = nameType;
     }
 
-
+    
+    /**
+     * Creates a new instance of PrincipalName given a String[] and an 
+     * principal type.
+     * 
+     * @param nameParts The name string, which can contains more than one nameComponent
+     * @param nameType The principal name type
+     */
+    public PrincipalName( String[] nameParts, int nameType )
+    {
+    	if ( nameParts == null || nameParts.length == 0 )
+    	{
+    		throw new IllegalArgumentException("Empty name parts");
+    	}
+    	
+    	List<String> nameComponents = new ArrayList<String>();
+    	for ( String np : nameParts )
+    	{
+    		nameComponents.add( np );
+    	}
+    	
+        this.nameString = nameComponents;
+        this.nameType = PrincipalNameType.getTypeByValue( nameType );;
+    }
+    
+    
     /**
      * Creates a new instance of PrincipalName.
      *
@@ -241,7 +267,24 @@ public class PrincipalName extends Abstr
         this.nameType = PrincipalNameType.getTypeByValue( nameType );
     }
 
-
+    /**
+     * Set the realm for the principal
+     * @param realm the realm of the principal
+     */
+    public void setRealm( String realm )
+    {
+    	this.realm = realm;
+    }
+    
+    /**
+     * Get the realm for the principal
+     * @return realm the realm of the principal
+     */
+    public String getRealm()
+    {
+    	return realm;
+    }
+    
     /**
      * Returns the name components.
      *
@@ -483,13 +526,20 @@ public class PrincipalName extends Abstr
                 sb.append( '\'' ).append( name ).append( '\'' );
             }
 
-            sb.append( "> }" );
+            sb.append( ">" );
         }
         else
         {
-            sb.append( " no name-string }" );
+            sb.append( " no name-string" );
         }
 
+        if ( realm != null )
+        {
+        	sb.append( "realm: " ).append( realm );
+        }
+        
+        sb.append( " }" );
+        
         return sb.toString();
     }