package net.deterlab.abac;
import java.io.*;
import java.math.*;
import java.util.*;
import java.security.*;
import java.security.cert.*;
import javax.security.auth.x500.*;
import org.bouncycastle.asn1.*;
import org.bouncycastle.asn1.x509.*;
import org.bouncycastle.x509.*;
import org.bouncycastle.x509.util.*;
import org.bouncycastle.openssl.*;
/**
* An ABAC credential, with or without an underlying certificate that
* represents it. These are edges in proof graphs and can be constructed from
* their constituent Roles.
* @author ISI ABAC team
* @version 1.4
*/
public abstract class Credential implements Comparable {
/** The role at the head */
protected Role m_head
/** The role at the tail */;
protected Role m_tail;
/** The identity that issued the certificate */
protected Identity id;
/** The expiration time of the credential */
protected Date m_expiration;
/**
* Create an empty Credential.
*/
Credential() {
m_head = m_tail = null;
id = null;
m_expiration = null;
}
/**
* Create a credential from a head and tail role. This credential has no
* underlying certificate, and cannot be exported or used in real proofs.
* make_cert can create a certificate for a credential initialized this
* way.
* @param head the Role at the head of the credential
* @param tail the Role at the tail of the credential
*/
Credential(Role head, Role tail) {
m_head = head;
m_tail = tail;
id = null;
m_expiration = null;
}
/**
* Create a credential from an attribute cert in a file. Throws an
* exception if the cert file can't be opened or if there's a format
* problem with the cert. Note that catching
* java.security.GeneralSecurityException catches most of the exceptions
* this throws.
* @param filename a String containing the filename to read
* @param ids a Collection of Identities to use in validating the cert
* @throws CertInvalidException if the stream is unparsable
* @throws MissingIssuerException if none of the Identities can validate the
* certificate
* @throws BadSignatureException if the signature check fails
*/
Credential(String filename, Collection ids)
throws ABACException { this(); }
/**
* Create a credential from an attribute cert in a file. Throws an
* exception if the cert file can't be opened or if there's a format
* problem with the cert. Note that catching
* java.security.GeneralSecurityException catches most of the exceptions
* this throws.
* @param file the File to read
* @param ids a Collection of Identities to use in validating the cert
* @throws CertInvalidException if the stream is unparsable
* @throws MissingIssuerException if none of the Identities can validate the
* certificate
* @throws BadSignatureException if the signature check fails
*/
Credential(File file, Collection ids)
throws ABACException {
this();
}
/**
* Create a credential from an InputStream. Throws an exception if the
* stream can't be parsed or if there's a format problem with the cert.
* Note that catching java.security.GeneralSecurityException catches most
* of the exceptions this throws.
* @param s the InputStream to read
* @param ids a Collection of Identities to use in validating the cert
* @throws CertInvalidException if the stream is unparsable
* @throws MissingIssuerException if none of the Identities can validate the
* certificate
* @throws BadSignatureException if the signature check fails
*/
Credential(InputStream s, Collection ids)
throws ABACException {
this();
}
/**
* Create a certificate from this credential issued by the given identity.
* Note that catching java.security.GeneralSecurityException catches most
* of the exceptions this throws.
* @param i the Identity that will issue the certificate
* @throws ABACException for Credential-specific errors
* @throws MissingIssuerException the identity is invalid
* @throws BadSignatureException if the signature creation fails
*/
public abstract void make_cert(Identity i)
throws ABACException;
/**
* Return true if 2 credentials represent the same ABAC. Two credentials
* are the same if their roles are the same.
* @param o an Object to compare
* @return true if the Credentials have the Roles
*/
public boolean equals(Object o) {
if ( o instanceof Credential ) {
Credential c = (Credential) o;
if (m_head == null || m_tail == null ) return false;
else return (m_head.equals(c.head()) && m_tail.equals(c.tail()));
}
else return false;
}
/**
* Compare 2 credentials for sorting. They are ordered by their Roles,
* head then tail.
* @param o an Object to compare
* @return -1 if this Credential is before, 0 if they are the same, and 1
* if this Credential is after the given object.
*/
public int compareTo(Object o) {
if (o instanceof Credential) {
Credential c = (Credential) o;
if (head().equals(c.head())) return tail().compareTo(c.tail());
else return head().compareTo(c.head());
}
else return 1;
}
/**
* Get the head role from the credential.
* @return the Role in the head
*/
public Role head() { return m_head; }
/**
* Get the tail role from the credential
* @return the Role in the tail
*/
public Role tail() { return m_tail; }
/**
* Get the expiration Date of the credential.
*/
public Date expiration() { return m_expiration; }
/**
* Return an untranslated string form of the credential. The format is head
* <- tail. For example: A.r1 <- B.r2.r3. Principal names are key
* identifiers.
* @return the string form
*/
public String toString() {
return m_head + " <- " + m_tail;
}
/**
* Return a translated string form of the credential. The format is head
* <- tail. For example: A.r1 <- B.r2.r3. Principal names are
* shortened to menmonics if the Context knows the identity.
* @param c the Context to translate names in
* @return the string form
*/
public String simpleString(Context c) {
return m_head.simpleString(c) + " <- " + m_tail.simpleString(c);
}
/**
* Output the external representation of the Credential to the OutputStream
* given. Subclasses will overload this for their output format.
* @param s the OutputStream on which to write
* @throws IOException if there is an error writing.
*/
public abstract void write(OutputStream s) throws IOException;
/**
* Output the external representation of the Credential to the filename
* given. Subclasses will overload this for their output format.
* @param fn a String containing the output filename
* @throws IOException if there is an error writing.
*/
public abstract void write(String fn)
throws IOException, FileNotFoundException;
/**
* Return true if this Credential has a certificate associated. A jabac
* extension.
* @return true if this Credential has a certificate associated.
*/
public abstract boolean hasCertificate();
/**
* Return the Identity that issued the underlying certificate (if any). A
* jabac extension.
* @return the Identity that issued the underlying certificate.
*/
public Identity issuer() { return id; }
}