source: java/net/deterlab/abac/CredentialFactory.java @ 8f53997

abac0-leakabac0-meimei-idmei-rt0-ntvf-new-xml
Last change on this file since 8f53997 was 6bf703b0, checked in by Ted Faber <faber@…>, 12 years ago

Add GENIProv parsing works

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