directory-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From dran...@apache.org
Subject [14/50] [abbrv] directory-kerberos git commit: Many changes with newname
Date Thu, 22 Jan 2015 00:56:38 GMT
http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbInputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbInputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbInputStream.java
new file mode 100644
index 0000000..224cec3
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbInputStream.java
@@ -0,0 +1,74 @@
+/**
+ *  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.kerby.kerberos.kerb;
+
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionType;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.DataInputStream;
+import java.io.IOException;
+import java.io.InputStream;
+
+public abstract class KrbInputStream extends DataInputStream
+{
+    public KrbInputStream(InputStream in) {
+        super(in);
+    }
+
+    public KerberosTime readTime() throws IOException {
+        long value = readInt();
+        KerberosTime time = new KerberosTime(value * 1000);
+        return time;
+    }
+
+    public abstract PrincipalName readPrincipal(int version) throws IOException;
+
+    public EncryptionKey readKey(int version) throws IOException {
+        int eType = readShort();
+        EncryptionType encryptionType = EncryptionType.fromValue(eType);
+
+        byte[] keyData = readCountedOctets();
+        EncryptionKey key = new EncryptionKey(encryptionType, keyData);
+
+        return key;
+    }
+
+    public String readCountedString() throws IOException {
+        byte[] countedOctets = readCountedOctets();
+        // ASCII
+        return new String(countedOctets);
+    }
+
+    public byte[] readCountedOctets() throws IOException {
+        int len = readOctetsCount();
+        if (len == 0) {
+            return null;
+        }
+
+        byte[] data = new byte[len];
+        read(data);
+
+        return data;
+    }
+
+    public abstract int readOctetsCount() throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbOutputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbOutputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbOutputStream.java
new file mode 100644
index 0000000..7be0bdf
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/KrbOutputStream.java
@@ -0,0 +1,66 @@
+/**
+ *  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.kerby.kerberos.kerb;
+
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.DataOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+
+public abstract class KrbOutputStream extends DataOutputStream
+{
+	public KrbOutputStream(OutputStream out) {
+        super(out);
+    }
+
+    public abstract void writePrincipal(PrincipalName principal, int version) throws IOException;
+
+    public void writeRealm(String realm) throws IOException {
+        writeCountedString(realm);
+    }
+
+    public abstract void writeKey(EncryptionKey key, int version) throws IOException;
+
+    public void writeTime(KerberosTime ktime) throws IOException {
+    	int time = 0;
+    	if (ktime != null) {
+    		time = (int) (ktime.getValue().getTime() / 1000);
+    	}
+    	writeInt(time);
+    }
+
+    public void writeCountedString(String string) throws IOException {
+        byte[] data = string != null ? string.getBytes() : null; // ASCII
+
+        writeCountedOctets(data);
+    }
+
+    public void writeCountedOctets(byte[] data) throws IOException {
+        if (data != null) {
+            writeInt(data.length);
+            write(data);
+        } else {
+            writeInt(0);
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheInputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheInputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheInputStream.java
new file mode 100644
index 0000000..c97deac
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheInputStream.java
@@ -0,0 +1,167 @@
+/**
+ *  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.kerby.kerberos.kerb.ccache;
+
+import org.apache.kerby.kerberos.kerb.KrbInputStream;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.*;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlags;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CredCacheInputStream extends KrbInputStream
+{
+    public CredCacheInputStream(InputStream in) {
+        super(in);
+    }
+
+    @Override
+    public PrincipalName readPrincipal(int version) throws IOException {
+        NameType nameType = NameType.NT_UNKNOWN;
+        if (version != CredentialCache.FCC_FVNO_1) {
+            int typeValue = readInt();
+            nameType = NameType.fromValue(typeValue);
+        }
+
+        int numComponents = readInt();
+        if (version == CredentialCache.FCC_FVNO_1) {
+            numComponents -= 1;
+        }
+
+        String realm = readCountedString();
+
+        List<String> nameStrings = new ArrayList<String>();
+        String component;
+        for (int i = 0; i < numComponents; i++) { // sub 1 if version 0x501
+            component = readCountedString();
+            nameStrings.add(component);
+        }
+
+        PrincipalName principal = new PrincipalName(nameStrings, nameType);
+        principal.setRealm(realm);
+
+        return principal;
+    }
+
+    public EncryptionKey readKey(int version) throws IOException {
+        if (version == CredentialCache.FCC_FVNO_3) {
+            readShort(); //  ignore keytype
+        }
+
+        return super.readKey(version);
+    }
+
+    public KerberosTime[] readTimes() throws IOException {
+        KerberosTime[] times = new KerberosTime[4];
+
+        for (int i = 0; i < times.length; ++i) {
+            times[i] = readTime();
+        }
+
+        return times;
+    }
+
+    public boolean readIsSkey() throws IOException {
+        int value = readByte();
+        return value == 1 ? true : false;
+    }
+
+    public HostAddresses readAddr() throws IOException {
+        int numAddresses = readInt();
+        if (numAddresses <= 0) {
+            return null;
+        }
+
+        HostAddress[] addresses = new HostAddress[numAddresses];
+        for (int i = 0; i < numAddresses; i++) {
+            addresses[i] = readAddress();
+        }
+
+        HostAddresses result = new HostAddresses();
+        result.addElements(addresses);
+        return result;
+    }
+
+    public HostAddress readAddress() throws IOException {
+        int typeValue = readShort();
+        HostAddrType addrType = HostAddrType.fromValue(typeValue);
+        byte[] addrData = readCountedOctets();
+
+        HostAddress addr = new HostAddress();
+        addr.setAddrType(addrType);
+        addr.setAddress(addrData);
+
+        return addr;
+    }
+
+    public AuthorizationData readAuthzData() throws IOException {
+        int numEntries = readInt();
+        if (numEntries <= 0) {
+            return null;
+        }
+
+        AuthorizationDataEntry[] authzData = new AuthorizationDataEntry[numEntries];
+        for (int i = 0; i < numEntries; i++) {
+            authzData[i] = readAuthzDataEntry();
+        }
+
+        AuthorizationData result = new AuthorizationData();
+        result.addElements(authzData);
+        return result;
+    }
+
+    public AuthorizationDataEntry readAuthzDataEntry() throws IOException {
+        int typeValue = readShort();
+        AuthorizationType authzType = AuthorizationType.fromValue(typeValue);
+        byte[] authzData = readCountedOctets();
+
+        AuthorizationDataEntry authzEntry = new AuthorizationDataEntry();
+        authzEntry.setAuthzType(authzType);
+        authzEntry.setAuthzData(authzData);
+
+        return authzEntry;
+    }
+
+    @Override
+    public int readOctetsCount() throws IOException {
+        return readInt();
+    }
+
+    public TicketFlags readTicketFlags() throws IOException {
+        int flags = readInt();
+        TicketFlags tktFlags = new TicketFlags(flags);
+        return tktFlags;
+    }
+
+    public Ticket readTicket() throws IOException {
+        byte[] ticketData = readCountedOctets();
+        if (ticketData == null) {
+            return null;
+        }
+
+        Ticket ticket = new Ticket();
+        ticket.decode(ticketData);
+        return ticket;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheOutputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheOutputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheOutputStream.java
new file mode 100644
index 0000000..30fcd82
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredCacheOutputStream.java
@@ -0,0 +1,123 @@
+/**
+ *  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.kerby.kerberos.kerb.ccache;
+
+import org.apache.kerby.kerberos.kerb.KrbOutputStream;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.*;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlags;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+public class CredCacheOutputStream extends KrbOutputStream
+{
+	public CredCacheOutputStream(OutputStream out) {
+        super(out);
+    }
+
+    @Override
+    public void writePrincipal(PrincipalName principal, int version) throws IOException {
+        List<String> nameComponents = principal.getNameStrings();
+
+    	if (version != CredentialCache.FCC_FVNO_1) {
+        	writeInt(principal.getNameType().getValue());
+        }
+
+        int numComponents = nameComponents.size();
+        if (version == CredentialCache.FCC_FVNO_1) {
+            numComponents ++;
+        }
+        writeInt(numComponents);
+        
+        writeRealm(principal.getRealm());
+        
+        for (String nameCom : nameComponents) {
+            writeCountedString(nameCom);
+        }
+    }
+
+    @Override
+    public void writeKey(EncryptionKey key, int version) throws IOException {
+    	writeShort(key.getKeyType().getValue());
+    	if (version == CredentialCache.FCC_FVNO_3) {
+    		writeShort(key.getKeyType().getValue());
+    	}
+
+        writeCountedOctets(key.getKeyData());
+    }
+
+    public void writeTimes(KerberosTime[] times) throws IOException {
+        for (int i = 0; i < times.length; ++i) {
+            writeTime(times[i]);
+        }
+    }
+
+    public void writeAddresses(HostAddresses addrs) throws IOException {
+    	if (addrs == null) {
+    		writeInt(0);
+    	} else {
+            List<HostAddress> addresses = addrs.getElements();
+    		write(addresses.size());
+    		for (HostAddress addr : addresses) {
+                writeAddress(addr);
+    		}
+    	}
+    }
+
+    public void writeAddress(HostAddress address) throws IOException {
+        write(address.getAddrType().getValue());
+        write(address.getAddress().length);
+        write(address.getAddress(), 0,
+                address.getAddress().length);
+    }
+
+    public void writeAuthzData(AuthorizationData authData) throws IOException  {
+    	if (authData == null) {
+    		writeInt(0);
+    	} else {
+    		for (AuthorizationDataEntry entry : authData.getElements()) {
+    			write(entry.getAuthzType().getValue());
+    			write(entry.getAuthzData().length);
+    			write(entry.getAuthzData());
+    		}
+    	}
+    }
+    
+    public void writeTicket(Ticket t) throws IOException  {
+        if (t == null) {
+            writeInt(0);
+        } else {
+            byte[] bytes = t.encode();
+            writeInt(bytes.length);
+            write(bytes);
+        }
+    }
+
+    public void writeIsSkey(boolean isEncInSKey) throws IOException {
+        writeByte(isEncInSKey ? 1 : 0);
+    }
+
+    public void writeTicketFlags(TicketFlags ticketFlags) throws IOException {
+        writeInt(ticketFlags.getFlags());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Credential.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Credential.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Credential.java
new file mode 100644
index 0000000..d0e74f4
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Credential.java
@@ -0,0 +1,225 @@
+/**
+ *  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.kerby.kerberos.kerb.ccache;
+
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.AuthorizationData;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.HostAddresses;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.kdc.EncKdcRepPart;
+import org.apache.kerby.kerberos.kerb.spec.ticket.AbstractServiceTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TgtTicket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.spec.ticket.TicketFlags;
+
+import java.io.IOException;
+
+public class Credential
+{
+    private static String CONF_REALM = "X-CACHECONF:";
+
+    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 ticketFlags;
+    private Ticket ticket;
+    private Ticket secondTicket;
+
+    public Credential() {
+
+    }
+
+    public Credential(TgtTicket tgt) {
+        PrincipalName clientPrincipal = tgt.getClientPrincipal();
+
+        clientPrincipal.setRealm(tgt.getRealm());
+
+        init(tgt, clientPrincipal);
+    }
+
+    public Credential(AbstractServiceTicket tkt, PrincipalName clientPrincipal) {
+        init(tkt, clientPrincipal);
+    }
+
+    private void init(AbstractServiceTicket 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.ticketFlags = kdcRepPart.getFlags();
+        this.clientAddresses = kdcRepPart.getCaddr();
+
+        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 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 getTicketFlags() {
+        return ticketFlags;
+    }
+
+    public Ticket getTicket() {
+        return ticket;
+    }
+
+    public Ticket getSecondTicket() {
+        return secondTicket;
+    }
+
+    public void load(CredCacheInputStream ccis, int version) throws IOException {
+        this.clientName = ccis.readPrincipal(version);
+        if (clientName == null) {
+            throw new IOException("Invalid client principal name");
+        }
+
+        this.serverName = ccis.readPrincipal(version);
+        if (serverName == null) {
+            throw new IOException("Invalid server principal name");
+        }
+
+        boolean isConfEntry = false;
+
+        if (serverName.getRealm().equals(CONF_REALM)) {
+            isConfEntry = true;
+        }
+
+        this.key = ccis.readKey(version);
+
+        KerberosTime[] times = ccis.readTimes();
+        this.authTime = times[0];
+        this.startTime = times[1];
+        this.endTime = times[2];
+        this.renewTill = times[3];
+
+        this.isEncInSKey = ccis.readIsSkey();
+
+        this.ticketFlags = ccis.readTicketFlags();
+
+        this.clientAddresses = ccis.readAddr();
+
+        this.authzData = ccis.readAuthzData();
+
+        if (isConfEntry) {
+            byte[] confData = ccis.readCountedOctets();
+            // ignoring confData for now
+        } else {
+            this.ticket = ccis.readTicket();
+        }
+
+        this.secondTicket = ccis.readTicket();
+
+        // might skip krb5_ccache_conf_data/fast_avail/krbtgt/REALM@REALM in MIT KRB5
+    }
+
+    public void store(CredCacheOutputStream ccos, int version) throws IOException {
+        ccos.writePrincipal(clientName, version);
+        ccos.writePrincipal(serverName, version);
+        ccos.writeKey(key, version);
+
+        ccos.writeTimes(new KerberosTime[]{authTime, startTime, endTime, renewTill});
+
+        ccos.writeIsSkey(isEncInSKey);
+ 
+        ccos.writeTicketFlags(ticketFlags);
+
+        ccos.writeAddresses(clientAddresses);
+
+        ccos.writeAuthzData(authzData);
+
+        ccos.writeTicket(ticket);
+
+        ccos.writeTicket(secondTicket);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredentialCache.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredentialCache.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredentialCache.java
new file mode 100644
index 0000000..3598e90
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/CredentialCache.java
@@ -0,0 +1,278 @@
+/**
+ *  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.kerby.kerberos.kerb.ccache;
+
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+
+import java.io.*;
+import java.util.ArrayList;
+import java.util.List;
+
+public class CredentialCache implements KrbCredentialCache
+{
+    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;
+
+    private int version = FCC_FVNO_4;
+    private List<Tag> tags;
+    private PrincipalName primaryPrincipal;
+    private List<Credential> credentials = new ArrayList<Credential> ();
+
+    @Override
+    public void store(File ccacheFile) throws IOException {
+        OutputStream outputStream = new FileOutputStream(ccacheFile);
+
+        store(outputStream);
+    }
+
+    @Override
+    public void store(OutputStream outputStream) throws IOException {
+        if (outputStream == null) {
+            throw new IllegalArgumentException("Invalid and null output stream");
+        }
+
+        CredCacheOutputStream ccos = new CredCacheOutputStream(outputStream);
+
+        doStore(ccos);
+
+        ccos.close();
+    }
+
+    private void doStore(CredCacheOutputStream ccos) throws IOException {
+        this.version = FCC_FVNO_3;
+
+        writeVersion(ccos);
+
+        if (version == FCC_FVNO_4) {
+            writeTags(ccos);
+        }
+
+        ccos.writePrincipal(primaryPrincipal, version);
+
+        for (Credential cred : credentials) {
+            cred.store(ccos, version);
+        }
+    }
+
+    @Override
+    public void setVersion(int version) {
+        this.version = version;
+    }
+
+    @Override
+    public PrincipalName getPrimaryPrincipal() {
+        return primaryPrincipal;
+    }
+
+    @Override
+    public void setPrimaryPrincipal(PrincipalName principal) {
+        primaryPrincipal = principal;
+    }
+
+    @Override
+    public int getVersion() {
+        return version;
+    }
+
+    public void setTags(List<Tag> tags) {
+        this.tags = tags;
+    }
+
+    public List<Tag> getTags() {
+        return this.tags;
+    }
+
+    @Override
+    public List<Credential> getCredentials() {
+        return credentials;
+    }
+
+    @Override
+    public void addCredential(Credential credential) {
+        if (credential != null) {
+            this.credentials.add(credential);
+        }
+    }
+
+    @Override
+    public void addCredentials(List<Credential> credentials) {
+        if (credentials != null) {
+            this.credentials.addAll(credentials);
+        }
+    }
+
+    @Override
+    public void removeCredentials(List<Credential> credentials) {
+        if (credentials != null) {
+            for (Credential cred : credentials) {
+                removeCredential(cred);
+            }
+        }
+    }
+
+    @Override
+    public void removeCredential(Credential credential) {
+        if (credential != null) {
+            for (Credential cred : credentials) {
+                if (cred.equals(credential)) {
+                    credentials.remove(cred);
+                    break;
+                }
+            }
+        }
+    }
+
+    @Override
+    public void load(File ccacheFile) throws IOException {
+        if (! ccacheFile.exists() || ! ccacheFile.canRead()) {
+            throw new IllegalArgumentException("Invalid ccache file: " + ccacheFile.getAbsolutePath());
+        }
+
+        InputStream inputStream = new FileInputStream(ccacheFile);
+
+        load(inputStream);
+    }
+
+    @Override
+    public void load(InputStream inputStream) throws IOException {
+        if (inputStream == null) {
+            throw new IllegalArgumentException("Invalid and null input stream");
+        }
+
+        CredCacheInputStream ccis = new CredCacheInputStream(inputStream);
+
+        doLoad(ccis);
+
+        ccis.close();
+    }
+
+    private void doLoad(CredCacheInputStream ccis) throws IOException {
+        this.version = readVersion(ccis);
+
+        this.tags = readTags(ccis);
+
+        this.primaryPrincipal = ccis.readPrincipal(version);
+
+        this.credentials = readCredentials(ccis);
+    }
+
+    private List<Credential> readCredentials(CredCacheInputStream ccis) throws IOException {
+        List<Credential> results = new ArrayList<Credential>(2);
+
+        Credential cred;
+        while (ccis.available() > 0) {
+            cred =  new Credential();
+            cred.load(ccis, version);
+
+            results.add(cred);
+        }
+
+        return results;
+    }
+
+    private int readVersion(CredCacheInputStream ccis) throws IOException {
+        int result = ccis.readShort();
+        return result;
+    }
+
+    private List<Tag> readTags(CredCacheInputStream ccis) throws IOException {
+        int len = ccis.readShort();
+        List<Tag> tags = new ArrayList<Tag>();
+
+        int tag, tagLen, time, usec;
+        while (len > 0) {
+            tag = ccis.readShort();
+            tagLen = ccis.readShort();
+            switch (tag) {
+                case FCC_TAG_DELTATIME:
+                    time = ccis.readInt();
+                    usec = ccis.readInt();
+                    tags.add(new Tag(tag, time, usec));
+                    break;
+                default:
+                    ccis.read(new byte[tagLen], 0, tagLen); // ignore unknown tag
+            }
+            len = len - (4 + tagLen);
+        }
+
+        return tags;
+    }
+
+    private void writeVersion(CredCacheOutputStream ccos) throws IOException {
+        ccos.writeShort(version);
+    }
+
+    private void writeTags(CredCacheOutputStream ccos) throws IOException {
+        if (tags == null) {
+            ccos.writeShort(0);
+            return;
+        }
+
+        int length = 0;
+        for (Tag tag : tags) {
+            if (tag.tag != FCC_TAG_DELTATIME) {
+                continue;
+            }
+            length += tag.length;
+        }
+        ccos.writeShort(length);
+
+        for (Tag tag : tags) {
+            if (tag.tag != CredentialCache.FCC_TAG_DELTATIME) {
+                continue;
+            }
+            writeTag(ccos, tag);
+        }
+    }
+
+    private void writeTag(CredCacheOutputStream ccos, Tag tag) throws IOException {
+        ccos.writeShort(tag.tag);
+        ccos.writeShort(tag.length);
+        ccos.writeInt(tag.time);
+        ccos.writeInt(tag.usec);
+    }
+
+    public static void main(String[] args) throws IOException {
+        if (args.length != 2) {
+            System.err.println("Dump credential cache file");
+            System.err.println("Usage: CredentialCache <ccache-file>");
+            System.exit(1);
+        }
+
+        String cacheFile = args[1];
+        CredentialCache cc = new CredentialCache();
+        cc.load(new File(cacheFile));
+
+        Ticket tkt;
+        for (Credential cred : cc.getCredentials()) {
+            tkt = cred.getTicket();
+            System.out.println("Tkt server name: " + tkt.getSname().getName());
+            System.out.println("Tkt client name: " + cred.getClientName().getName());
+            System.out.println("Tkt encrypt type: " + tkt.getEncryptedEncPart().getEType().getName());
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/KrbCredentialCache.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/KrbCredentialCache.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/KrbCredentialCache.java
new file mode 100644
index 0000000..df70a80
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/KrbCredentialCache.java
@@ -0,0 +1,57 @@
+/**
+ *  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.kerby.kerberos.kerb.ccache;
+
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+public interface KrbCredentialCache {
+
+    public PrincipalName getPrimaryPrincipal();
+
+    public void setPrimaryPrincipal(PrincipalName principal);
+
+    public int getVersion();
+
+    public void setVersion(int version);
+
+    public List<Credential> getCredentials();
+
+    public void addCredential(Credential credential);
+
+    public void addCredentials(List<Credential> credentials);
+
+    public void removeCredentials(List<Credential> credentials);
+
+    public void removeCredential(Credential credential);
+
+    public void load(File ccacheFile) throws IOException;
+
+    public void load(InputStream inputStream) throws IOException;
+
+    public void store(File ccacheFile) throws IOException;
+
+    public void store(OutputStream outputStream) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Tag.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Tag.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Tag.java
new file mode 100644
index 0000000..21b8dd7
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/Tag.java
@@ -0,0 +1,34 @@
+/**
+ *  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.kerby.kerberos.kerb.ccache;
+
+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;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/ccache.txt
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/ccache.txt b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/ccache.txt
new file mode 100644
index 0000000..91453ea
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/ccache/ccache.txt
@@ -0,0 +1,98 @@
+The Kerberos Credential Cache Binary File Format
+Copyright (C) 2006-2013 Simon Josefsson <simon josefsson.org>
+http://josefsson.org/shishi/ccache.txt
+Last updated: Sat Sep 23 12:04:11 CEST 2006
+
+Like the MIT keytab binary format (see Michael B Allen's reverse
+engineered description in keytab.txt), the credential cache format is
+not standard nor documented anywhere.
+
+In C style notation, the MIT credential cache file format is as
+follows.  All values are in network byte order.  All text is ASCII.
+
+ccache {
+          uint16_t file_format_version; /* 0x0504 */
+          uint16_t headerlen;           /* only if version is 0x0504 */
+          header headers[];             /* only if version is 0x0504 */
+          principal primary_principal;
+          credential credentials[*];
+};
+
+header {
+       uint16_t tag;                    /* 1 = DeltaTime */
+       uint16_t taglen;
+       uint8_t tagdata[taglen]
+};
+
+The ccache.taglen and ccache.tags fields are only present in 0x0504
+versions, not in earlier.  Both MIT and Heimdal appear to correctly
+ignore unknown tags, so it appears safe to add them (although there is
+no central place to "register" tags).
+
+Currently only one tag is widely implemented, DeltaTime (0x0001).  Its
+taglen is always 8, and tagdata will contain:
+
+DeltaTime {
+       uint32_t time_offset;
+       uint32_t usec_offset;
+};
+
+After reading the file_format_version, header tags, and default
+principal, a list of credentials follow.  You deduce from the file
+length when there are no more credentials.
+
+credential {
+           principal client;
+           principal server;
+           keyblock key;
+           times    time;
+           uint8_t  is_skey;            /* 1 if skey, 0 otherwise */
+           uint32_t tktflags;           /* stored in reversed byte order */
+           uint32_t num_address;
+           address  addrs[num_address];
+           uint32_t num_authdata;
+           authdata authdata[num_authdata];
+           counted_octet_string ticket;
+           counted_octet_string second_ticket;
+};
+
+keyblock {
+         uint16_t keytype;
+         uint16_t etype;                /* only present if version 0x0503 */
+         uint32_t keylen;               /* [drankye]: corrected, before it was uint16_t */
+         uint8_t keyvalue[keylen];
+};
+
+times {
+      uint32_t  authtime;
+      uint32_t  starttime;
+      uint32_t  endtime;
+      uint32_t  renew_till;
+};
+
+address {
+        uint16_t addrtype;
+        counted_octet_string addrdata;
+};
+
+authdata {
+         uint16_t authtype;
+         counted_octet_string authdata;
+};
+
+principal {
+          uint32_t name_type;           /* not present if version 0x0501 */
+          uint32_t num_components;      /* sub 1 if version 0x501 */
+          counted_octet_string realm;
+          counted_octet_string components[num_components];
+};
+
+counted_octet_string {
+    uint32_t length;
+    uint8_t data[length];
+};
+
+Permission to copy, modify, and distribute this document, with or
+without modification, for any purpose and without fee or royalty is
+hereby granted, provided that you include this copyright notice in ALL
+copies of the document or portions thereof, including modifications.
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java
new file mode 100644
index 0000000..46891d0
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/Keytab.java
@@ -0,0 +1,197 @@
+/**
+ *  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.kerby.kerberos.kerb.keytab;
+
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionType;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.*;
+import java.nio.ByteBuffer;
+import java.util.*;
+
+public class Keytab implements KrbKeytab {
+
+    public static final int V501 = 0x0501;
+    public static final int V502 = 0x0502;
+
+    private int version = V502;
+
+    private Map<PrincipalName, List<KeytabEntry>> principalEntries;
+
+    public Keytab() {
+        this.principalEntries = new HashMap<PrincipalName, List<KeytabEntry>>();
+    }
+
+    @Override
+    public List<PrincipalName> getPrincipals() {
+        return new ArrayList<PrincipalName>(principalEntries.keySet());
+    }
+
+    @Override
+    public void addKeytabEntries(List<KeytabEntry> entries) {
+        for (KeytabEntry entry : entries) {
+            addEntry(entry);
+        }
+    }
+
+    @Override
+    public void removeKeytabEntries(PrincipalName principal) {
+        principalEntries.remove(principal);
+    }
+
+    @Override
+    public void removeKeytabEntry(KeytabEntry entry) {
+        PrincipalName principal = entry.getPrincipal();
+        List<KeytabEntry> entries = principalEntries.get(principal);
+        if (entries != null) {
+            Iterator<KeytabEntry> iter = entries.iterator();
+            KeytabEntry tmp;
+            while (iter.hasNext()) {
+                tmp = iter.next();
+                if (entry.equals(tmp)) {
+                    iter.remove();
+                    break;
+                }
+            }
+        }
+    }
+
+    @Override
+    public List<KeytabEntry> getKeytabEntries(PrincipalName principal) {
+        return principalEntries.get(principal);
+    }
+
+    @Override
+    public EncryptionKey getKey(PrincipalName principal, EncryptionType keyType) {
+        List<KeytabEntry> entries = getKeytabEntries(principal);
+        for (KeytabEntry ke : entries) {
+            if (ke.getKey().getKeyType() == keyType) {
+                return ke.getKey();
+            }
+        }
+
+        return null;
+    }
+
+    @Override
+    public void load(File keytabFile) throws IOException {
+        if (! keytabFile.exists() || ! keytabFile.canRead()) {
+            throw new IllegalArgumentException("Invalid keytab file: " + keytabFile.getAbsolutePath());
+        }
+
+        InputStream is = new FileInputStream(keytabFile);
+
+        load(is);
+    }
+
+    @Override
+    public void load(InputStream inputStream) throws IOException {
+        if (inputStream == null) {
+            throw new IllegalArgumentException("Invalid and null input stream");
+        }
+
+        KeytabInputStream kis = new KeytabInputStream(inputStream);
+
+        doLoad(kis);
+    }
+
+    private void doLoad(KeytabInputStream kis) throws IOException {
+        this.version = readVersion(kis);
+
+        List<KeytabEntry> entries = readEntries(kis);
+        addKeytabEntries(entries);
+    }
+
+    @Override
+    public void addEntry(KeytabEntry entry) {
+        PrincipalName principal = entry.getPrincipal();
+        List<KeytabEntry> entries = principalEntries.get(principal);
+        if (entries == null) {
+            entries = new ArrayList<KeytabEntry>();
+            principalEntries.put(principal, entries);
+        }
+        entries.add(entry);
+    }
+
+    private int readVersion(KeytabInputStream kis) throws IOException {
+        return kis.readShort();
+    }
+
+    private List<KeytabEntry> readEntries(KeytabInputStream kis) throws IOException {
+        List<KeytabEntry> entries = new ArrayList<KeytabEntry>();
+
+        int entrySize;
+        ByteBuffer entryData;
+        KeytabEntry entry;
+        while (kis.available() > 0) {
+            entrySize = kis.readInt();
+            if (kis.available() < entrySize) {
+                throw new IOException("Bad input stream with less data than expected: " + entrySize);
+            }
+            entry = readEntry(kis);
+            entries.add(entry);
+        }
+
+        return entries;
+    }
+
+    private KeytabEntry readEntry(KeytabInputStream kis) throws IOException {
+        KeytabEntry entry = new KeytabEntry();
+        entry.load(kis, version);
+        return entry;
+    }
+
+    @Override
+    public void store(File keytabFile) throws IOException {
+        OutputStream outputStream = new FileOutputStream(keytabFile);
+
+        store(outputStream);
+    }
+
+    @Override
+    public void store(OutputStream outputStream) throws IOException {
+        if (outputStream == null) {
+            throw new IllegalArgumentException("Invalid and null output stream");
+        }
+
+        KeytabOutputStream kos = new KeytabOutputStream(outputStream);
+
+        writeVersion(kos);
+        writeEntries(kos);
+    }
+
+    private void writeVersion(KeytabOutputStream kos) throws IOException {
+        byte[] bytes = new byte[2];
+        bytes[0] = (byte) 0x05;
+        bytes[1] = version == V502 ? (byte) 0x02 : (byte) 0x01;
+
+        kos.write(bytes);
+    }
+
+    private void writeEntries(KeytabOutputStream kos) throws IOException {
+        for (PrincipalName principal : principalEntries.keySet()) {
+            for (KeytabEntry entry : principalEntries.get(principal)) {
+                entry.store(kos);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java
new file mode 100644
index 0000000..a0b7351
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabEntry.java
@@ -0,0 +1,121 @@
+/**
+ *  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.kerby.kerberos.kerb.keytab;
+
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+
+public class KeytabEntry
+{
+    private PrincipalName principal;
+    private KerberosTime timestamp;
+    private int kvno;
+    private EncryptionKey key;
+
+    public KeytabEntry(PrincipalName principal, KerberosTime timestamp,
+                       int kvno, EncryptionKey key) {
+        this.principal = principal;
+        this.timestamp = timestamp;
+        this.kvno = kvno;
+        this.key = key;
+    }
+
+    public KeytabEntry() {
+
+    }
+
+    public void load(KeytabInputStream kis, int version) throws IOException {
+        this.principal = kis.readPrincipal(version);
+
+        this.timestamp = kis.readTime();
+
+        this.kvno = kis.readByte();
+
+        this.key = kis.readKey();
+    }
+
+    public void store(KeytabOutputStream kos) throws IOException {
+        byte[] body = null;
+
+        // compute entry body content first so that to get and write the size
+        ByteArrayOutputStream baos = new ByteArrayOutputStream();
+        KeytabOutputStream subKos = new KeytabOutputStream(baos);
+        writeBody(subKos, 0); // todo: consider the version
+        subKos.flush();
+        body = baos.toByteArray();
+
+        kos.writeInt(body.length);
+        kos.write(body);
+    }
+
+    public EncryptionKey getKey() {
+        return key;
+    }
+
+    public int getKvno() {
+        return kvno;
+    }
+
+    public PrincipalName getPrincipal() {
+        return principal;
+    }
+
+    public KerberosTime getTimestamp() {
+        return timestamp;
+    }
+
+    public void writeBody(KeytabOutputStream kos, int version) throws IOException {
+        kos.writePrincipal(principal, version);
+
+        kos.writeTime(timestamp);
+
+        kos.writeByte(kvno);
+
+        kos.writeKey(key, version);
+    }
+
+    @Override
+    public boolean equals(Object o) {
+        if (this == o) return true;
+        if (o == null || getClass() != o.getClass()) return false;
+
+        KeytabEntry that = (KeytabEntry) o;
+
+        if (kvno != that.kvno) return false;
+        if (!key.equals(that.key)) return false;
+        if (!principal.equals(that.principal)) return false;
+        if (!timestamp.equals(that.timestamp)) return false;
+
+        return true;
+    }
+
+    @Override
+    public int hashCode() {
+        int result = principal.hashCode();
+        result = 31 * result + timestamp.hashCode();
+        result = 31 * result + kvno;
+        result = 31 * result + key.hashCode();
+        return result;
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java
new file mode 100644
index 0000000..4638080
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabInputStream.java
@@ -0,0 +1,89 @@
+/**
+ *  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.kerby.kerberos.kerb.keytab;
+
+import org.apache.kerby.kerberos.kerb.KrbInputStream;
+import org.apache.kerby.kerberos.kerb.spec.KerberosTime;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionType;
+import org.apache.kerby.kerberos.kerb.spec.common.NameType;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.ArrayList;
+import java.util.List;
+
+public class KeytabInputStream extends KrbInputStream
+{
+    public KeytabInputStream(InputStream in) {
+        super(in);
+    }
+
+    public KerberosTime readTime() throws IOException {
+        long value = readInt();
+        KerberosTime time = new KerberosTime(value * 1000);
+        return time;
+    }
+
+    @Override
+    public PrincipalName readPrincipal(int version) throws IOException {
+        int numComponents = readShort();
+        if (version == Keytab.V501) {
+            numComponents -= 1;
+        }
+
+        String realm = readCountedString();
+
+        List<String> nameStrings = new ArrayList<String>();
+        String component;
+        for (int i = 0; i < numComponents; i++) { // sub 1 if version 0x501
+            component = readCountedString();
+            nameStrings.add(component);
+        }
+        int type = readInt(); // not present if version 0x501
+        NameType nameType = NameType.fromValue(type);
+        PrincipalName principal = new PrincipalName(nameStrings, nameType);
+        principal.setRealm(realm);
+
+        return principal;
+    }
+
+    public EncryptionKey readKey() throws IOException {
+        int eType = readShort();
+        EncryptionType encryptionType = EncryptionType.fromValue(eType);
+
+        byte[] keyData = readCountedOctets();
+        EncryptionKey key = new EncryptionKey(encryptionType, keyData);
+
+        return key;
+    }
+
+    public String readCountedString() throws IOException {
+        byte[] countedOctets = readCountedOctets();
+        // ASCII
+        return new String(countedOctets);
+    }
+
+    @Override
+    public int readOctetsCount() throws IOException {
+        return readShort();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabOutputStream.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabOutputStream.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabOutputStream.java
new file mode 100644
index 0000000..d69308f
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KeytabOutputStream.java
@@ -0,0 +1,63 @@
+/**
+ *  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.kerby.kerberos.kerb.keytab;
+
+import org.apache.kerby.kerberos.kerb.KrbOutputStream;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.List;
+
+public class KeytabOutputStream extends KrbOutputStream
+{
+	public KeytabOutputStream(OutputStream out) {
+        super(out);
+    }
+
+    public void writePrincipal(PrincipalName principal, int version) throws IOException {
+        List<String> nameStrings = principal.getNameStrings();
+        int numComponents = principal.getNameStrings().size();
+        String realm = principal.getRealm();
+
+        writeShort(numComponents);
+
+        writeCountedString(realm);
+
+        for (String nameCom : nameStrings) {
+            writeCountedString(nameCom);
+        }
+
+        writeInt(principal.getNameType().getValue()); // todo: consider the version
+    }
+
+    @Override
+    public void writeKey(EncryptionKey key, int version) throws IOException {
+    	writeShort(key.getKeyType().getValue());
+        writeCountedOctets(key.getKeyData());
+    }
+
+    @Override
+    public void writeCountedOctets(byte[] data) throws IOException {
+        writeShort(data.length);
+        write(data);
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KrbKeytab.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KrbKeytab.java b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KrbKeytab.java
new file mode 100644
index 0000000..1b01fc2
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/KrbKeytab.java
@@ -0,0 +1,55 @@
+/**
+ *  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.kerby.kerberos.kerb.keytab;
+
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionType;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+
+import java.io.File;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.OutputStream;
+import java.util.List;
+
+public interface KrbKeytab {
+
+    public List<PrincipalName> getPrincipals();
+
+    public void addKeytabEntries(List<KeytabEntry> entries);
+
+    public void removeKeytabEntries(PrincipalName principal);
+
+    public void removeKeytabEntry(KeytabEntry entry);
+
+    public List<KeytabEntry> getKeytabEntries(PrincipalName principal);
+
+    public EncryptionKey getKey(PrincipalName principal, EncryptionType keyType);
+
+    public void load(File keytabFile) throws IOException;
+
+    public void load(InputStream inputStream) throws IOException;
+
+    void addEntry(KeytabEntry entry);
+
+    public void store(File keytabFile) throws IOException;
+
+    public void store(OutputStream outputStream) throws IOException;
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/keytab.txt
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/keytab.txt b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/keytab.txt
new file mode 100644
index 0000000..88a7b46
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/main/java/org/apache/kerby/kerberos/kerb/keytab/keytab.txt
@@ -0,0 +1,106 @@
+The Kerberos Keytab Binary File Format
+Copyright (C) 2006 Michael B Allen <mba2000 ioplex.com>
+http://www.ioplex.com/utilities/keytab.txt
+Last updated: Fri May  5 13:39:40 EDT 2006
+
+The MIT keytab binary format is not a standard format, nor is it
+documented anywhere in detail. The format has evolved and may continue
+to. It is however understood by several Kerberos implementations including
+Heimdal and of course MIT and keytab files are created by the ktpass.exe
+utility from Windows. So it has established itself as the defacto format
+for storing Kerberos keys.
+
+The following C-like structure definitions illustrate the MIT keytab
+file format. All values are in network byte order. All text is ASCII.
+
+  keytab {
+      uint16_t file_format_version;                    /* 0x502 */
+      keytab_entry entries[*];
+  };
+
+  keytab_entry {
+      int32_t size;
+      uint16_t num_components;    /* sub 1 if version 0x501 */
+      counted_octet_string realm;
+      counted_octet_string components[num_components];
+      uint32_t name_type;   /* not present if version 0x501 */
+      uint32_t timestamp;
+      uint8_t vno8;
+      keyblock key;
+      uint32_t vno; /* only present if >= 4 bytes left in entry */
+  };
+
+  counted_octet_string {
+      uint16_t length;
+      uint8_t data[length];
+  };
+
+  keyblock {
+      uint16_t type;
+      counted_octet_string;
+  };
+
+The keytab file format begins with the 16 bit file_format_version which
+at the time this document was authored is 0x502. The format of older
+keytabs is described at the end of this document.
+
+The file_format_version is immediately followed by an array of
+keytab_entry structures which are prefixed with a 32 bit size indicating
+the number of bytes that follow in the entry. Note that the size should be
+evaluated as signed. This is because a negative value indicates that the
+entry is in fact empty (e.g. it has been deleted) and that the negative
+value of that negative value (which is of course a positive value) is
+the offset to the next keytab_entry. Based on these size values alone
+the entire keytab file can be traversed.
+
+The size is followed by a 16 bit num_components field indicating the
+number of counted_octet_string components in the components array.
+
+The num_components field is followed by a counted_octet_string
+representing the realm of the principal.
+
+A counted_octet_string is simply an array of bytes prefixed with a 16
+bit length. For the realm and name components, the counted_octet_string
+bytes are ASCII encoded text with no zero terminator.
+
+Following the realm is the components array that represents the name of
+the principal. The text of these components may be joined with slashs
+to construct the typical SPN representation. For example, the service
+principal HTTP/www.foo.net@FOO.NET would consist of name components
+"HTTP" followed by "www.foo.net".
+
+Following the components array is the 32 bit name_type (e.g. 1 is
+KRB5_NT_PRINCIPAL, 2 is KRB5_NT_SRV_INST, 5 is KRB5_NT_UID, etc). In
+practice the name_type is almost certainly 1 meaning KRB5_NT_PRINCIPAL.
+
+The 32 bit timestamp indicates the time the key was established for that
+principal. The value represents the number of seconds since Jan 1, 1970.
+
+The 8 bit vno8 field is the version number of the key. This value is
+overridden by the 32 bit vno field if it is present.
+
+The keyblock structure consists of a 16 bit value indicating the keytype
+(e.g. 3 is des-cbc-md5, 23 is arcfour-hmac-md5, 16 is des3-cbc-sha1,
+etc). This is followed by a counted_octet_string containing the key.
+
+The last field of the keytab_entry structure is optional. If the size of
+the keytab_entry indicates that there are at least 4 bytes remaining,
+a 32 bit value representing the key version number is present. This
+value supersedes the 8 bit vno8 value preceeding the keyblock.
+
+Older keytabs with a file_format_version of 0x501 are different in
+three ways:
+
+  1) All integers are in host byte order [1].
+  2) The num_components field is 1 too large (i.e. after decoding,
+     decrement by 1).
+  3) The 32 bit name_type field is not present.
+
+[1] The file_format_version field should really be treated as two
+    separate 8 bit quantities representing the major and minor version
+    number respectively.
+
+Permission to copy, modify, and distribute this document, with or
+without modification, for any purpose and without fee or royalty is
+hereby granted, provided that you include this copyright notice in ALL
+copies of the document or portions thereof, including modifications.

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/CcacheTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/CcacheTest.java b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/CcacheTest.java
new file mode 100644
index 0000000..bd5a685
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/CcacheTest.java
@@ -0,0 +1,57 @@
+/**
+ *  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.kerby.kerberos.kerb.util;
+
+import org.apache.kerby.kerberos.kerb.ccache.CredentialCache;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+
+/*
+Default principal: drankye@SH.INTEL.COM
+
+Valid starting       Expires              Service principal
+08/05/2014 00:13:17  08/05/2014 10:13:17  krbtgt/SH.INTEL.COM@SH.INTEL.COM
+        Flags: FIA, Etype (skey, tkt): des3-cbc-sha1, des3-cbc-sha1
+ */
+public class CcacheTest {
+
+    private CredentialCache cc;
+
+    @Before
+    public void setUp() throws IOException {
+        InputStream cis = CcacheTest.class.getResourceAsStream("/test.cc");
+        cc = new CredentialCache();
+        cc.load(cis);
+    }
+
+    @Test
+    public void testCc() {
+        Assert.assertNotNull(cc);
+
+        PrincipalName princ = cc.getPrimaryPrincipal();
+        Assert.assertNotNull(princ);
+        Assert.assertTrue(princ.getName().equals("drankye@SH.INTEL.COM"));
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/EncryptionTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/EncryptionTest.java b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/EncryptionTest.java
new file mode 100644
index 0000000..e632839
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/EncryptionTest.java
@@ -0,0 +1,148 @@
+/**
+ *  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.kerby.kerberos.kerb.util;
+
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.ccache.CredentialCache;
+import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.keytab.Keytab;
+import org.apache.kerby.kerberos.kerb.spec.common.*;
+import org.apache.kerby.kerberos.kerb.spec.ticket.EncTicketPart;
+import org.apache.kerby.kerberos.kerb.spec.ticket.Ticket;
+import org.apache.kerby.kerberos.kerb.codec.KrbCodec;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.Arrays;
+import java.util.List;
+
+/*
+The principal keys for krbtgt/SH.INTEL.COM@SH.INTEL.COM
+
+KVNO Principal
+---- --------------------------------------------------------------------------
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (des-cbc-crc)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (des3-cbc-raw)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (des-hmac-sha1)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (aes256-cts-hmac-sha1-96)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (aes128-cts-hmac-sha1-96)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (arcfour-hmac)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (camellia256-cts-cmac)
+   2 krbtgt/SH.INTEL.COM@SH.INTEL.COM (camellia128-cts-cmac)
+ */
+public class EncryptionTest {
+
+    private Keytab keytab;
+    private CredentialCache cc;
+
+    @Before
+    public void setUp() throws IOException {
+        InputStream kis = EncryptionTest.class.getResourceAsStream("/krbtgt.keytab");
+        keytab = new Keytab();
+        keytab.load(kis);
+    }
+
+    @Test
+    public void testAes128() throws IOException, KrbException {
+        testEncWith("aes128-cts-hmac-sha1-96.cc");
+    }
+
+    @Test
+    public void testAes256() throws IOException, KrbException {
+        testEncWith("aes256-cts-hmac-sha1-96.cc");
+    }
+
+    @Test
+    public void testRc4() throws IOException, KrbException {
+        testEncWith("arcfour-hmac.cc");
+    }
+
+    @Test
+    public void testCamellia128() throws IOException, KrbException {
+        testEncWith("camellia128-cts-cmac.cc");
+    }
+
+    @Test
+    public void testCamellia256() throws IOException, KrbException {
+        testEncWith("camellia256-cts-cmac.cc");
+    }
+
+    @Test
+    public void testDesCbcCrc() throws IOException, KrbException {
+        testEncWith("des-cbc-crc.cc");
+    }
+
+    @Test
+    public void testDes3CbcSha1() throws IOException, KrbException {
+        testEncWith("des3-cbc-sha1.cc");
+    }
+
+    private void testEncWith(String ccFile) throws IOException, KrbException, KrbException {
+        InputStream cis = CcacheTest.class.getResourceAsStream("/" + ccFile);
+        cc = new CredentialCache();
+        cc.load(cis);
+
+        Ticket ticket = getTicket();
+        EncryptionType keyType = ticket.getEncryptedEncPart().getEType();
+        EncryptionKey key = getServerKey(keyType);
+        if (! EncryptionHandler.isImplemented(keyType)) {
+            System.err.println("Key type not supported yet: " + keyType.getName());
+            return;
+        }
+
+        byte[] decrypted = EncryptionHandler.decrypt(
+                ticket.getEncryptedEncPart(), key, KeyUsage.KDC_REP_TICKET);
+        Assert.assertNotNull(decrypted);
+
+        EncTicketPart encPart = KrbCodec.decode(decrypted, EncTicketPart.class);
+        Assert.assertNotNull(encPart);
+        ticket.setEncPart(encPart);
+
+        EncryptedData encrypted = EncryptionHandler.encrypt(
+                decrypted, key, KeyUsage.KDC_REP_TICKET);
+
+        byte[] decrypted2 = EncryptionHandler.decrypt(
+                encrypted, key, KeyUsage.KDC_REP_TICKET);
+        if (! Arrays.equals(decrypted, decrypted2)) {
+            System.err.println("Encryption checking failed after decryption for key type: "
+                    + keyType.getName());
+        }
+    }
+
+    private EncryptionKey getServerKey(EncryptionType keyType) {
+        return keytab.getKey(getServer(), keyType);
+    }
+
+    private PrincipalName getServer() {
+        // only one, krbtgt/SH.INTEL.COM@SH.INTEL.COM
+        List<PrincipalName> principals = keytab.getPrincipals();
+
+        PrincipalName server = principals.get(0);
+
+        return server;
+    }
+
+    private Ticket getTicket() {
+        return cc.getCredentials().get(0).getTicket();
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeysTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeysTest.java b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeysTest.java
new file mode 100644
index 0000000..c32854f
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeysTest.java
@@ -0,0 +1,81 @@
+/**
+ *  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.kerby.kerberos.kerb.util;
+
+import org.apache.kerby.kerberos.kerb.crypto.EncryptionHandler;
+import org.apache.kerby.kerberos.kerb.keytab.Keytab;
+import org.apache.kerby.kerberos.kerb.keytab.KeytabEntry;
+import org.apache.kerby.kerberos.kerb.KrbException;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionKey;
+import org.apache.kerby.kerberos.kerb.spec.common.EncryptionType;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/*
+The principal was created with password '123456'
+KVNO Principal
+---- --------------------------------------------------------------------------
+   1 test@SH.INTEL.COM (des-cbc-crc)
+   1 test@SH.INTEL.COM (des3-cbc-sha1)
+   1 test@SH.INTEL.COM (des-hmac-sha1)
+   1 test@SH.INTEL.COM (aes256-cts-hmac-sha1-96)
+   1 test@SH.INTEL.COM (aes128-cts-hmac-sha1-96)
+   1 test@SH.INTEL.COM (arcfour-hmac)
+   1 test@SH.INTEL.COM (camellia256-cts-cmac)
+   1 test@SH.INTEL.COM (camellia128-cts-cmac)
+ */
+public class KeysTest {
+    private static String TEST_PASSWORD = "123456";
+
+    private Keytab keytab;
+
+    @Before
+    public void setUp() throws IOException {
+        InputStream kis = KeysTest.class.getResourceAsStream("/test.keytab");
+        keytab = new Keytab();
+        keytab.load(kis);
+    }
+
+    @Test
+    public void testString2Key() throws KrbException {
+        List<PrincipalName> principals = keytab.getPrincipals();
+        PrincipalName principal = principals.get(0);
+        List<KeytabEntry> entries = keytab.getKeytabEntries(principal);
+        EncryptionKey genKey;
+        EncryptionType keyType;
+        for (KeytabEntry ke : entries) {
+            keyType = ke.getKey().getKeyType();
+            if (EncryptionHandler.isImplemented(keyType)) {
+                genKey = EncryptionHandler.string2Key(principal.getName(),
+                        TEST_PASSWORD, keyType);
+                if(! ke.getKey().equals(genKey)) {
+                    Assert.fail("str2key failed for key type: " + keyType.getName());
+                    //System.err.println("str2key failed for key type: " + keyType.getName());
+                }
+            }
+        }
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
new file mode 100644
index 0000000..01cdaed
--- /dev/null
+++ b/kerby-kerb/kerb-util/src/test/java/org/apache/kerby/kerberos/kerb/util/KeytabTest.java
@@ -0,0 +1,76 @@
+/**
+ *  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.kerby.kerberos.kerb.util;
+
+import org.apache.kerby.kerberos.kerb.keytab.Keytab;
+import org.apache.kerby.kerberos.kerb.keytab.KeytabEntry;
+import org.apache.kerby.kerberos.kerb.spec.common.PrincipalName;
+import org.junit.Assert;
+import org.junit.Before;
+import org.junit.Test;
+
+import java.io.IOException;
+import java.io.InputStream;
+import java.util.List;
+
+/*
+The principal was created with password '123456'
+
+KVNO Principal
+---- --------------------------------------------------------------------------
+   1 test@SH.INTEL.COM (des-cbc-crc)
+   1 test@SH.INTEL.COM (des3-cbc-sha1)
+   1 test@SH.INTEL.COM (des-hmac-sha1)
+   1 test@SH.INTEL.COM (aes256-cts-hmac-sha1-96)
+   1 test@SH.INTEL.COM (aes128-cts-hmac-sha1-96)
+   1 test@SH.INTEL.COM (arcfour-hmac)
+   1 test@SH.INTEL.COM (camellia256-cts-cmac)
+   1 test@SH.INTEL.COM (camellia128-cts-cmac)
+ */
+public class KeytabTest {
+
+    private Keytab keytab;
+
+    @Before
+    public void setUp() throws IOException {
+        InputStream kis = KeytabTest.class.getResourceAsStream("/test.keytab");
+        keytab = new Keytab();
+        keytab.load(kis);
+    }
+
+    @Test
+    public void testKeytab() {
+        Assert.assertNotNull(keytab);
+
+        List<PrincipalName> principals = keytab.getPrincipals();
+        PrincipalName principal = principals.get(0);
+        List<KeytabEntry> entries = keytab.getKeytabEntries(principal);
+        for (KeytabEntry ke : entries) {
+            Assert.assertTrue(ke.getKvno() == 1);
+        }
+    }
+
+    public static void main(String[] args) throws IOException {
+        InputStream kis = KeytabTest.class.getResourceAsStream("test.keytab");
+        Keytab keytab = new Keytab();
+        keytab.load(kis);
+        System.out.println("Principals:" + keytab.getPrincipals().size());
+    }
+}

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/resources/aes128-cts-hmac-sha1-96.cc
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/resources/aes128-cts-hmac-sha1-96.cc b/kerby-kerb/kerb-util/src/test/resources/aes128-cts-hmac-sha1-96.cc
new file mode 100644
index 0000000..2ae9f6e
Binary files /dev/null and b/kerby-kerb/kerb-util/src/test/resources/aes128-cts-hmac-sha1-96.cc differ

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/resources/aes256-cts-hmac-sha1-96.cc
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/resources/aes256-cts-hmac-sha1-96.cc b/kerby-kerb/kerb-util/src/test/resources/aes256-cts-hmac-sha1-96.cc
new file mode 100644
index 0000000..929c40e
Binary files /dev/null and b/kerby-kerb/kerb-util/src/test/resources/aes256-cts-hmac-sha1-96.cc differ

http://git-wip-us.apache.org/repos/asf/directory-kerberos/blob/7d9261af/kerby-kerb/kerb-util/src/test/resources/arcfour-hmac.cc
----------------------------------------------------------------------
diff --git a/kerby-kerb/kerb-util/src/test/resources/arcfour-hmac.cc b/kerby-kerb/kerb-util/src/test/resources/arcfour-hmac.cc
new file mode 100644
index 0000000..f7bb88d
Binary files /dev/null and b/kerby-kerb/kerb-util/src/test/resources/arcfour-hmac.cc differ


Mime
View raw message