source: java/net/deterlab/abac/Credential.java @ 84f0e7a

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

Initial run at unifying the interface.

  • Property mode set to 100644
File size: 7.0 KB
Line 
1package net.deterlab.abac;
2
3import java.io.*;
4import java.math.*;
5
6import java.util.*;
7import java.util.zip.*;
8import java.security.*;
9import java.security.cert.*;
10
11import net.deterlab.abac.Identity;
12
13import org.bouncycastle.asn1.*;
14import org.bouncycastle.asn1.x509.*;
15import org.bouncycastle.x509.*;
16import org.bouncycastle.jce.X509Principal;
17import org.bouncycastle.jce.provider.X509AttrCertParser;
18import org.bouncycastle.jce.provider.X509CertificateObject;
19import org.bouncycastle.openssl.PEMReader;
20
21import java.security.PrivateKey;
22
23public class Credential implements Comparable {
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    protected static String authKeyOID = "2.5.29.35";
27
28    /**
29     * A dummy credential.
30     */
31    public Credential() {
32        m_head = m_tail = null;
33        m_ac = null;
34        m_id = null;
35    }
36    /**
37     * Create a credential from a head and tail role. This is only for testing.
38     * In a real implementation the Credential must be loaded from an X.509
39     * attribute cert.
40     */
41    public Credential(Role head, Role tail) {
42        m_head = head;
43        m_tail = tail;
44        m_ac = null; 
45        m_id = null;
46    }
47
48    /**
49     * Do the credential initialization from a filename.
50     */
51    protected void read_certificate(InputStream stream) 
52            throws Exception {
53        X509AttrCertParser parser = new X509AttrCertParser();
54        parser.engineInit(stream);
55        m_ac = (X509V2AttributeCertificate)parser.engineRead();
56    }
57
58
59    protected void init(InputStream stream, Collection<Identity> ids) 
60            throws Exception {
61        read_certificate(stream);
62        if (m_ac == null) throw new IOException("Unknown Format");
63        init(ids);
64    }
65
66    protected void init(Collection<Identity> ids) 
67            throws CertificateException, InvalidKeyException, NoSuchAlgorithmException, NoSuchProviderException,SignatureException {
68        for (Identity id: ids) {
69            try {
70                m_ac.verify(id.getCertificate().getPublicKey(), "BC");
71                m_id = id;
72                break;
73            }
74            catch (InvalidKeyException e) { }
75        }
76        if (m_id == null) throw new InvalidKeyException("Unknown identity");
77
78        load_roles();
79
80        if (!m_id.getKeyID().equals(m_head.issuer_part()))
81            throw new InvalidKeyException("Unknown identity");
82    }
83    /**
84     * Create a credential from an attribute cert. Throws an exception if the
85     * cert file can't be opened or if there's a format problem with the cert.
86     */
87    public Credential(String filename, Collection<Identity> ids) 
88        throws Exception { init(new FileInputStream(filename), ids); }
89
90    /**
91     * Create a credential from an attribute cert. Throws an exception if the
92     * cert file can't be opened or if there's a format problem with the cert.
93     */
94    public Credential(File file, Collection<Identity> ids) 
95        throws Exception { init(new FileInputStream(file), ids); }
96
97    /**
98     * Create a credential from an InputStream.
99     */
100    public Credential(InputStream s, Collection<Identity> ids) 
101        throws Exception { init(s, ids); }
102
103    public Credential(X509V2AttributeCertificate c, Collection<Identity> ids) 
104        throws Exception {
105        m_ac = c;
106        init(ids);
107    }
108
109
110    /**
111     * Create a certificate from this credential issued by the given identity.
112     * This is just grungy credential generation work.
113     */
114    public void make_cert(Identity i) {
115        PrivateKey key = i.getKeyPair().getPrivate();
116        SubjectPublicKeyInfo pki = Identity.extractSubjectPublicKeyInfo(
117                i.getKeyPair().getPublic());
118        X509V2AttributeCertificateGenerator gen = 
119            new X509V2AttributeCertificateGenerator();
120
121        gen.setIssuer(new AttributeCertificateIssuer(
122                    new X509Principal("CN="+m_head.issuer_part())));
123        gen.setHolder(new AttributeCertificateHolder(
124                    new X509Principal("CN="+m_head.issuer_part())));
125        gen.setNotAfter(new Date(System.currentTimeMillis() 
126                    + 3600 * 1000 * 24 * 365));
127        gen.setNotBefore(new Date(System.currentTimeMillis()));
128        gen.setSerialNumber(BigInteger.valueOf(System.currentTimeMillis()));
129        gen.addAttribute(new X509Attribute(attrOID, 
130                    new DERSequence(
131                        new DERSequence(
132                            new DERUTF8String(toString())))));
133        gen.setSignatureAlgorithm("SHA256WithRSAEncryption");
134
135        try { 
136            // Creddy expects an authority key identifier.
137            gen.addExtension(authKeyOID, false, 
138                    new AuthorityKeyIdentifier(pki));
139            // Create the cert.
140            m_ac = (X509V2AttributeCertificate) gen.generate(key, "BC");
141        }
142        catch (Exception e) { 
143            System.err.println(e);
144        }
145    }
146
147    /**
148     * Load the roles off the attribute cert. Throws a RuntimeException if
149     * there's something wrong with the cert.
150     */
151    private void load_roles() throws RuntimeException {
152        String roles = null;
153        try {
154            X509Attribute attr = m_ac.getAttributes()[0];
155
156            DERSequence    java     = (DERSequence)attr.getValues()[0];
157            DERSequence    fucking  = (DERSequence)java.getObjectAt(0);
158            DERUTF8String  sucks    = (DERUTF8String)fucking.getObjectAt(0);
159
160            roles = sucks.getString();
161        }
162        catch (Exception e) {
163            throw new RuntimeException("Your attribute certificate is funky and I'm not gonna debug it", e);
164        }
165
166        String[] parts = roles.split("\\s*<--?\\s*");
167        if (parts.length != 2)
168            throw new RuntimeException("Invalid attribute: " + roles);
169
170        m_head = new Role(parts[0]);
171        m_tail = new Role(parts[1]);
172    }
173
174    /**
175     * Two credentials are the same if their roles are the same.
176     */
177    public boolean equals(Object o) {
178        if ( o instanceof Credential ) {
179            Credential c = (Credential) o;
180
181            if (m_head == null || m_tail == null ) return false;
182            else return (m_head.equals(c.head()) && m_tail.equals(c.tail()));
183        }
184        else return false;
185    }
186
187    public int compareTo(Object o) {
188        if (o instanceof Credential) {
189            Credential c = (Credential) o;
190
191            if (head().equals(c.head())) return tail().compareTo(c.tail());
192            else return head().compareTo(c.head());
193        }
194        else return 1;
195    }
196
197
198    /**
199     * Get the head role from the credential.
200     */
201    public Role head() {
202        return m_head;
203    }
204
205    /**
206     * Get the tail role from the credential
207     */
208    public Role tail() {
209        return m_tail;
210    }
211
212    /**
213     * Gets the cert associated with this credential (if any).
214     */
215    public X509V2AttributeCertificate cert() {
216        return m_ac;
217    }
218
219    /**
220     * Turn the credential into string form. The format is head &lt;- tail. For
221     * example: A.r1 &lt;- B.r2.r3.
222     */
223    public String toString() {
224        return m_head + " <- " + m_tail;
225    }
226
227    public String simpleString(Context c) {
228        return m_head.simpleString(c) + " <- " + m_tail.simpleString(c);
229    }
230
231    public void write(OutputStream s) throws IOException {
232        s.write(m_ac.getEncoded());
233        s.flush();
234    }
235
236    public void write(String fn) throws IOException, FileNotFoundException {
237        write(new FileOutputStream(fn));
238    }
239
240    public boolean hasCertificate() { return m_ac != null; }
241
242    public Identity getID() { return m_id; }
243
244private Role m_head, m_tail;
245
246private X509V2AttributeCertificate m_ac;
247private Identity m_id;
248
249}
Note: See TracBrowser for help on using the repository browser.