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 {
/** Default validity period (in seconds) */
static public long defaultValidity = 3600L * 24L * 365L;
/** 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;
/**
* Suggested file suffix to save this format credential under. Subclasses
should override it.
*/
protected String suffix;
/** Default file suffix. */
private static final String defSuffix = ".cred";
/**
* Create an empty Credential.
*/
Credential() {
m_head = m_tail = null;
id = null;
m_expiration = null;
suffix = defSuffix;
}
/**
* 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;
suffix = defSuffix;
}
/**
* 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,
* valid for the given time.
* @param i the Identity that will issue the certificate
* @param validity a long holding the number of seconds that the credential
* is valid for.
* @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, long validity)
throws ABACException;
/**
* Create a certificate from this credential issued by the given identity,
* valid for the default interval.
* @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;
}
/**
* Return a hash code for the Credential - the hashes of its roles.
* @return an int, the hashCode
*/
public int hashCode() {
if ( m_head == null || m_tail == null) return super.hashCode();
return m_head.hashCode() + m_tail.hashCode();
}
/**
* 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; }
/**
* Return an suggested suffix for output files (most start with a ".").
* @return a String, an optional suffix for output files.
*/
public String getSuffix() { return suffix; }
/**
* Set the suggested suffix for output files (most start with a ".").
* Available for subclasses to set the value without knowing the member
* name.
* @param suff a String, an optional suffix for output files.
*/
protected void setSuffix(String suff) { suffix = suff; }
}