source: java/net/deterlab/abac/CredentialFactory.java @ 2d56f83

abac0-leakabac0-mei
Last change on this file since 2d56f83 was a1a9a47, checked in by Ted Faber <faber@…>, 11 years ago

Bump version

  • Property mode set to 100644
File size: 8.2 KB
RevLine 
[3797bbe]1package net.deterlab.abac;
2
3import java.io.*;
4import java.util.*;
[3612811]5import java.lang.reflect.*;
[3797bbe]6
7
8/**
[a7f73b5]9 * A class for parsing and generating Credentials inside a Context.  All
10 * credential parsing should use a credential factory inside a context uses a
11 * CredentialFactory.
[3797bbe]12 * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
[a1a9a47]13 * @version 1.5
[3797bbe]14 */
[d06c453]15public class CredentialFactory implements Cloneable {
[aaadefd]16    protected List<CredentialFactorySpecialization> spec;
[6bf703b0]17
18    /**
19     * The xmlparsing routines helpfully close input streams when they
20     * successfully parse a document from one.  It's possible for a correctly
21     * parsed XML document to need to be reparsed by later specialization, for
22     * example because the XML was fine, but it was the wrong type of
23     * credential.  This makes the close operation a NOOP.
24     */
25    static protected class UnclosableBufferedInputStream extends 
26        BufferedInputStream {
27            public UnclosableBufferedInputStream(InputStream is) {
28                super(is);
29            }
30            public UnclosableBufferedInputStream(InputStream is, int s) {
31                super(is, s);
32            }
33
34            public void close() throws IOException { }
35    };
[a7f73b5]36    /** The classes understood by the default CredentialFactory (in order) */
[1a1acd9]37    static public String[] defNames = new String[] {
[c1736fe]38        "net.deterlab.abac.GENICredentialv1_1",
39        "net.deterlab.abac.GENICredentialv1_0",
[6bf703b0]40        "net.deterlab.abac.X509Credential",
41        "net.deterlab.abac.GENIPrivCredential",
[1a1acd9]42    };
[6bf703b0]43
[a7f73b5]44    /** Maximum credential size that can be rewound for reparsing */
[3612811]45    public static final int maxSize = 50 * 1024;
46
[f84d71e]47    /**
[d06c453]48     * Create a Credential Factory that parses the default type(s)
49     * @throws ABACException if the object cannot be created
[f84d71e]50     */
[d06c453]51    public CredentialFactory() throws ABACException {
[aaadefd]52        spec = new ArrayList<CredentialFactorySpecialization>();
[1a1acd9]53        for ( String name: defNames) 
54            registerClass(name);
[d06c453]55    }
56
57    /**
58     * Create a Credential Factory that parses the given type(s).  Each String
59     * should be the binary name for a class that exports a static
60     * getCredentialParser method that returns a CredentialParser for the
61     * class.
62     * @param names a Collection of Strings naming the classes to parse
63     * @throws ABACException if the object cannot be created
64     */
65    public CredentialFactory(Collection<String> names) throws ABACException {
[aaadefd]66        spec = new ArrayList<CredentialFactorySpecialization>();
[d06c453]67        for (String n : names ) 
68            registerClass(n);
69    }
70
71    /**
72     * Create a Credential Factory that parses the given type(s).  Each String
73     * should be the binary name for a class that exports a static
74     * getCredentialParser method that returns a CredentialParser for the
75     * class.
76     * @param names an Array of Strings naming the classes to parse
77     * @throws ABACException if the object cannot be created
78     */
79    public CredentialFactory(String[] names) throws ABACException {
[aaadefd]80        spec = new ArrayList<CredentialFactorySpecialization>();
[d06c453]81        for (String n : names ) 
82            registerClass(n);
83    }
[f84d71e]84
[d06c453]85    /**
86     * Create a Credential Factory that is a clone of the given
87     * CredentialFactory.
88     * @param cf the CredentialFactory to copy
89     * @throws ABACException if the object cannot be created
90     */
91    public CredentialFactory(CredentialFactory cf) throws ABACException {
92        this();
93
[aaadefd]94        spec = new ArrayList<CredentialFactorySpecialization>();
[d06c453]95
[aaadefd]96        for ( int i = 0; i < spec.size(); i++) 
97            spec.add(cf.spec.get(i));
[d06c453]98    }
99
100    /**
101     * Make a copy of this CredentialFactory
[a7f73b5]102     * @return a CredentialFactory, a copy of this one
[d06c453]103     */
104    public Object clone() throws CloneNotSupportedException {
105        CredentialFactory cf = null;
106        try {
107            cf = new CredentialFactory(this);
[3797bbe]108        }
[d06c453]109        catch (ABACException ae) {
110            return null;
[3797bbe]111        }
[d06c453]112        return cf;
[3612811]113    }
114
[d06c453]115
[f84d71e]116    /**
117     * Parse an input stream using each possible credential format and the
118     * available identities for validation.  Return the credentials found or
119     * throw an ABACException with the problem.  It wraps the input stream in a
120     * BufferedInputStream in order to retry is a parser fails.  Credentials
121     * larger than maxSize will nor be able to be reparsed.
122     * @param is an InputStream to parse
123     * @param ids a Collection of Identities for validation
124     * @return an Array of Credentials parsed
125     * @throws CertInvalidException if the stream is unparsable
126     * @throws MissingIssuerException if none of the Identities can validate the
127     * @throws BadSignatureException if the signature check fails
128     */
[d06c453]129    public Credential[] parseCredential(InputStream is, 
[f84d71e]130            Collection<Identity> ids) throws ABACException {
131        Credential[] rv = null;
[3612811]132        ABACException err = null;
[6bf703b0]133        UnclosableBufferedInputStream bs = 
134            new UnclosableBufferedInputStream(is, maxSize);
[3612811]135
[6bf703b0]136        bs.mark(maxSize);
[aaadefd]137        for (CredentialFactorySpecialization c : spec ) {
[3612811]138            try {
[6bf703b0]139                rv = c.parseCredential(bs, ids);
[f84d71e]140                break;
[3612811]141            }
[f84d71e]142            catch (ABACException e ) {
143                err = e;
[3612811]144                rv = null;
145            }
146            try {
[6bf703b0]147                if (spec.size() > 1) bs.reset(); 
[3612811]148            }
149            catch (IOException ie) { 
150                break;
151            }
[3797bbe]152        }
[3612811]153
[3797bbe]154        if ( rv != null ) 
[f84d71e]155            return rv;
[3797bbe]156        else 
[3612811]157            throw (err != null) ? err :
158                new ABACException("null exception and failed construction??");
159    }
160
161
[f84d71e]162    /**
163     * Parse a File using each possible credential format and the
164     * available identities for validation.  Return the credentials found or
165     * throw an ABACException with the problem.  Calls the InputStream version
166     * internally.
167     * @param f a File to parse
168     * @param ids a Collection of Identities for validation
169     * @return an Array of Credentials parsed
170     * @throws CertInvalidException if the stream is unparsable
171     * @throws MissingIssuerException if none of the Identities can validate the
172     * @throws BadSignatureException if the signature check fails
173     */
[d06c453]174    public Credential[] parseCredential(File f, 
[f84d71e]175            Collection<Identity> ids) throws ABACException {
[3612811]176        try {
[f84d71e]177            return parseCredential(new FileInputStream(f), ids);
[3612811]178        }
179        catch (FileNotFoundException e) {
180            throw new CertInvalidException(e.getMessage(), e);
181        }
[3797bbe]182    }
[f84d71e]183    /**
184     * Parse a file named fn using each possible credential format and the
185     * available identities for validation.  Return the credentials found or
186     * throw an ABACException with the problem.  Calls the InputStream version
187     * internally.
188     * @param fn a String holding the filename to parse
189     * @param ids a Collection of Identities for validation
190     * @return an Array of Credentials parsed
191     * @throws CertInvalidException if the stream is unparsable
192     * @throws MissingIssuerException if none of the Identities can validate the
193     * @throws BadSignatureException if the signature check fails
194     */
[d06c453]195    public Credential[] parseCredential(String fn, 
[f84d71e]196            Collection<Identity> ids) throws ABACException {
197        return parseCredential(new File(fn), ids);
[3797bbe]198    }
[3612811]199
[f84d71e]200    /**
[a7f73b5]201     * Return a credential from the first class registered in
202     * the factory.
[aaadefd]203     * @param head a Role, the head of the encoded ABAC statement
204     * @param tail a Role, the tail of the decoded ABAC statement
[79f516b]205     * @param aliases a KeyIDMap holding aliases for this creation
[aaadefd]206     * @return a Credential encoding that ABAC statement
207     */
[79f516b]208    public Credential generateCredential(Role head, Role tail, 
209            KeyIDMap aliases) {
[aaadefd]210        if (spec.isEmpty()) return null;
[79f516b]211        return spec.get(0).generateCredential(head, tail, aliases);
[aaadefd]212    }
213
214    /**
215     * Add the named class to the list of usable specializations.  The class
216     * passed in must have a static getCredentialFactorySpecialization() method
217     * that returns a CredentialFactorySpecialization to use.
[f84d71e]218     * @param name a String containing the binary name of the class to register
219     * @throws ABACException if there is a problem.  The cause field of this
220     * exception is set to the classloading exception, if any.
221     */
[d06c453]222    public void registerClass(String name)
[f84d71e]223        throws ABACException {
[aaadefd]224        CredentialFactorySpecialization cs = null;
[f84d71e]225
226        try {
[152673d]227            /* <?> doesn't guarantee much, but shuts the compiler up */
228            Class<?> c =  Class.forName(name);
[aaadefd]229            Method m = c.getMethod("getCredentialFactorySpecialization");
[3612811]230
[aaadefd]231            cs = (CredentialFactorySpecialization) m.invoke(null);
[f84d71e]232        }
233        catch (Exception e) {
234            throw new ABACException("Could not register credential type" + 
235                    e.getMessage(), e);
236        }
[3612811]237
[aaadefd]238        spec.add(cs);
[3612811]239    }
[3797bbe]240}
Note: See TracBrowser for help on using the repository browser.