source: java/net/deterlab/abac/Credential.java @ be05757

abac0-leakabac0-meicompt_changesgec13mei-idmei-rt0-nmei_rt0mei_rt2mei_rt2_fix_1meiyap-rt1meiyap1rt2tvf-new-xml
Last change on this file since be05757 was be05757, checked in by Ted Faber <faber@…>, 13 years ago

Read from diretory in Credentials.

  • Property mode set to 100644
File size: 7.9 KB
Line 
1package net.deterlab.abac;
2
3import java.io.*;
4import java.math.*;
5
6import java.util.*;
7import java.security.*;
8import java.security.cert.*;
9
10import net.deterlab.abac.Identity;
11
12import org.bouncycastle.asn1.*;
13import org.bouncycastle.x509.*;
14import org.bouncycastle.jce.X509Principal;
15import org.bouncycastle.jce.provider.X509AttrCertParser;
16import org.bouncycastle.jce.provider.X509CertificateObject;
17import org.bouncycastle.openssl.PEMReader;
18
19import org.bouncycastle.asn1.util.ASN1Dump;
20
21import java.security.PrivateKey;
22
23public class Credential {
24    protected static Vector<Identity> s_ids = new Vector<Identity>();
25    protected static String attrOID = "1.3.6.1.5.5.7.10.4";
26
27    /**
28     * A dummy credential.
29     */
30    public Credential() {
31        m_head = m_tail = null;
32        m_ac = null;
33        m_id = null;
34    }
35    /**
36     * Create a credential from a head and tail role. This is only for testing.
37     * In a real implementation the Credential must be loaded from an X.509
38     * attribute cert.
39     */
40    public Credential(Role head, Role tail) {
41        m_head = head;
42        m_tail = tail;
43        m_ac = null; 
44        m_id = null;
45    }
46
47    /**
48     * Do the credential initialization from a filename.
49     */
50    protected void init(InputStream stream) throws Exception {
51        X509AttrCertParser parser = new X509AttrCertParser();
52        parser.engineInit(stream);
53        m_ac = (X509V2AttributeCertificate)parser.engineRead();
54        m_id = null;
55
56        if ( m_ac == null ) throw new IOException("Invalid Credential Format");
57
58        for (Identity id: s_ids) {
59            try {
60                m_ac.verify(id.getCertificate().getPublicKey(), "BC");
61                m_id = id;
62                break;
63            }
64            catch (InvalidKeyException e) { }
65        }
66        if (m_id == null) throw new InvalidKeyException("Unknown identity");
67
68        load_roles();
69
70        if (!m_id.getKeyID().equals(m_head.issuer_part()))
71            throw new InvalidKeyException("Unknown identity");
72    }
73
74    /**
75     * Create a credential from an attribute cert. Throws an exception if the
76     * cert file can't be opened or if there's a format problem with the cert.
77     */
78    public Credential(String filename) throws Exception {
79        init(new FileInputStream(filename));
80    }
81
82    /**
83     * Create a credential from an attribute cert. Throws an exception if the
84     * cert file can't be opened or if there's a format problem with the cert.
85     */
86    public Credential(File file) throws Exception {
87        init(new FileInputStream(file));
88    }
89
90    /**
91     * Create a credential from an InputStream.
92     */
93    public Credential(InputStream s) throws Exception { 
94        init(s);
95    }
96
97    public void make_cert(PrivateKey key) {
98        X509V2AttributeCertificateGenerator gen = 
99            new X509V2AttributeCertificateGenerator();
100
101        gen.setIssuer(new AttributeCertificateIssuer(
102                    new X509Principal("CN="+m_head.issuer_part())));
103        gen.setHolder(new AttributeCertificateHolder(
104                    new X509Principal("CN="+m_head.issuer_part())));
105        gen.setNotAfter(new Date(System.currentTimeMillis() 
106                    + 3600 * 1000 * 24 * 365));
107        gen.setNotBefore(new Date(System.currentTimeMillis()));
108        gen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
109        gen.addAttribute(new X509Attribute(attrOID, 
110                    new DERSequence(
111                        new DERSequence(
112                            new DERUTF8String(toString())))));
113        gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
114
115        try { 
116            m_ac = (X509V2AttributeCertificate) gen.generate(key, "BC");
117        }
118        catch (Exception e) { 
119            System.err.println(e);
120        }
121    }
122
123    /**
124     * Load the roles off the attribute cert. Throws a RuntimeException if
125     * there's something wrong with the cert.
126     */
127    private void load_roles() throws RuntimeException {
128        String roles = null;
129        try {
130            X509Attribute attr = m_ac.getAttributes()[0];
131
132            //System.err.println(ASN1Dump.dumpAsString(attr));
133
134            DERSequence    java     = (DERSequence)attr.getValues()[0];
135            DERSequence    fucking  = (DERSequence)java.getObjectAt(0);
136            DERUTF8String  sucks    = (DERUTF8String)fucking.getObjectAt(0);
137
138            roles = sucks.getString();
139        }
140        catch (Exception e) {
141            throw new RuntimeException("Your attribute certificate is funky and I'm not gonna debug it", e);
142        }
143
144        String[] parts = roles.split("\\s*<--?\\s*");
145        if (parts.length != 2)
146            throw new RuntimeException("Invalid attribute: " + roles);
147
148        m_head = new Role(parts[0]);
149        m_tail = new Role(parts[1]);
150    }
151
152    /**
153     * Two credentials are the same if their roles are the same.
154     */
155    public boolean equals(Object o) {
156        if ( o instanceof Credential ) {
157            Credential c = (Credential) o;
158
159            if (m_head == null || m_tail == null ) return false;
160            else return (m_head.equals(c.head()) && m_tail.equals(c.tail()));
161        }
162        else return false;
163    }
164
165    /**
166     * Get the head role from the credential.
167     */
168    public Role head() {
169        return m_head;
170    }
171
172    /**
173     * Get the tail role from the credential
174     */
175    public Role tail() {
176        return m_tail;
177    }
178
179    /**
180     * Gets the cert associated with this credential (if any).
181     */
182    public X509V2AttributeCertificate cert() {
183        return m_ac;
184    }
185
186    /**
187     * Turn the credential into string form. The format is head &lt;- tail. For
188     * example: A.r1 &lt;- B.r2.r3.
189     */
190    public String toString() {
191        return m_head + " <- " + m_tail;
192    }
193
194    public String simpleString() {
195        return m_head.simpleString() + " <- " + m_tail.simpleString();
196    }
197
198    public void write(OutputStream s) throws IOException {
199        s.write(m_ac.getEncoded());
200    }
201
202    public void write(String fn) throws IOException, FileNotFoundException {
203        write(new FileOutputStream(fn));
204    }
205
206    public boolean hasCertificate() { return m_ac != null; }
207
208    /**
209     * Import a directory full of files.  First import all the identities
210     * (pem), then the credentials (der) into the credential graph then any
211     * alias files into the two maps.  If keys is not null, any key pairs in
212     * PEM files are put in there.  If errors is not null, errors reading files
213     * are added indexed by filename.
214     */
215    static public Collection<Credential> readDirectory(File d, 
216            Collection<KeyPair> keys, Map<File, Exception> errors) {
217        Vector<Credential> creds = new Vector<Credential>();
218        Vector<File> derFiles = new Vector<File>();
219
220        for (File f: d.listFiles() ) {
221            Object o = null;
222            try {
223                o = new PEMReader(new FileReader(f)).readObject();
224            }
225            catch (IOException e) { 
226                // PEMReader couldn't deal, so we assume it's a DER
227                derFiles.add(f);
228                continue;
229            }
230            try {
231                if ( o == null ) {
232                    // This shouldn't be, but assume it's a DER
233                    derFiles.add(f);
234                }
235                else if (o instanceof X509CertificateObject) {
236                    Credential.addIdentity(
237                            new Identity((X509CertificateObject)o));
238                }
239                else if (o instanceof KeyPair ) {
240                    if ( keys != null ) keys.add((KeyPair) o);
241                }
242                else {
243                    throw new IOException("Unexpected PEM object: " + 
244                            o.getClass().getName());
245                }
246            }
247            catch (Exception e ) {
248                if (errors != null ) errors.put(f, e);
249            }
250        }
251
252        for ( File f : derFiles ) {
253            try {
254                creds.add(new Credential(f));
255            }
256            catch (Exception e ) {
257                if (errors != null ) errors.put(f, e);
258            }
259        }
260        return creds;
261    }
262
263    static public Collection<Credential> readDirectory(File d) {
264        return readDirectory(d, null, null);
265    }
266    static public Collection<Credential> readDirectory(File d, 
267            Map<File, Exception> errors) {
268        return readDirectory(d, null, errors);
269    }
270    static public Collection<Credential> readDirectory(File d, 
271            Collection<KeyPair> keys) {
272        return readDirectory(d, keys, null);
273    }
274
275private Role m_head, m_tail;
276
277private X509V2AttributeCertificate m_ac;
278private Identity m_id;
279
280    public static void addIdentity(Identity id) { 
281        s_ids.add(id);
282        if (id.getName() != null && id.getKeyID() != null) 
283            Role.add_mapping(id.getName(), id.getKeyID());
284    }
285    public static Collection<Identity> identities() { return s_ids; }
286}
Note: See TracBrowser for help on using the repository browser.