package org.apache.kerberos.kerb.ccache;
import org.apache.kerberos.kerb.spec.common.PrincipalName;
import org.apache.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());
}
}
}