source: java/net/deterlab/abac/GENIPrivCredential.java @ e9b0027

Last change on this file since e9b0027 was a1a9a47, checked in by Ted Faber <faber@…>, 11 years ago

Bump version

  • Property mode set to 100644
File size: 10.3 KB
Line 
1package net.deterlab.abac;
2
3import java.io.*;
4import java.math.*;
5import java.text.*;
6
7import java.util.*;
8import java.security.*;
9import java.security.cert.*;
10
11import javax.security.auth.x500.*;
12
13import javax.xml.parsers.*;
14import javax.xml.transform.*;
15import javax.xml.transform.dom.*;
16import javax.xml.transform.stream.*;
17
18import javax.xml.crypto.*;
19import javax.xml.crypto.dsig.*;
20import javax.xml.crypto.dsig.dom.*;
21import javax.xml.crypto.dsig.keyinfo.*;
22import javax.xml.crypto.dsig.spec.*;
23
24import org.xml.sax.*;
25import org.w3c.dom.*;
26
27import org.bouncycastle.asn1.*;
28import org.bouncycastle.asn1.x509.*;
29import org.bouncycastle.x509.*;
30import org.bouncycastle.x509.util.*;
31import org.bouncycastle.openssl.*;
32
33/**
34 * An ABAC credential formatted as an abac-type GENI credential.
35 * @author <a href="http://abac.deterlab.net">ISI ABAC team</a>
36 * @version 1.5
37 */
38public class GENIPrivCredential extends GENICredential {
39    /**
40     * Create an empty Credential.
41     */
42    public GENIPrivCredential() {
43        super();
44        doc = null;
45    }
46    /**
47     * Create a credential from a head and tail role.  This credential has no
48     * underlying certificate, and cannot be exported or used in real proofs.
49     * make_cert can create a certificate for a credential initialized this
50     * way.
51     * @param head the Role at the head of the credential
52     * @param tail the Role at the tail of the credential
53     */
54    public GENIPrivCredential(Role head, Role tail, Document d, Identity i,
55            Date e) {
56        m_head = head;
57        m_tail = tail;
58        doc = null; 
59        id = null;
60        m_expiration = e;
61    }
62    /**
63     * Create a certificate from this credential issued by the given identity
64     * valid for the given period; these credentials cannot be turned into
65     * certificates, so this will always throw an exception.
66     * @param i the Identity that will issue the certificate
67     * @param validity a long holding the number of seconds that the credential
68     * is valid for.
69     * @throws ABACException if xml creation fails
70     * @throws MissingIssuerException if the issuer is bad
71     * @throws BadSignatureException if the signature creation fails
72     */
73    public void make_cert(Identity i, long validity) 
74            throws ABACException {
75        throw new ABACException("Cannot generate a GENIPrivCredential");
76    }
77
78
79    /**
80     * Create a certificate from this credential issued by the given identity;
81     * these credentials cannot be turned into certificates, so this will
82     * always throw an exception.
83     * @param i the Identity that will issue the certificate
84     * @throws ABACException if xml creation fails
85     * @throws MissingIssuerException if the issuer is bad
86     * @throws BadSignatureException if the signature creation fails
87     */
88    public void make_cert(Identity i) 
89            throws ABACException {
90        throw new ABACException("Cannot generate a GENIPrivCredential");
91    }
92
93    /**
94     * Class that parses a GENI privilege credential into multiple
95     * GENIPrivCredential objects.
96     */
97    static class GENIPrivSpecialization 
98            extends CredentialFactorySpecialization {
99
100        /**
101         * Extract an identity from a field holding a PEM-encoded x.509
102         * certificate (for example, owner_gid).
103         * @param n a Node that has the certificate in its Text Content
104         * @return the Identity
105         */
106        protected Identity nodeToIdentity(Node n) {
107            String certStr = null;
108
109            if ( ( certStr = n.getTextContent()) == null ) return null;
110            try {
111                certStr = "-----BEGIN CERTIFICATE-----\n" + 
112                    certStr + 
113                "\n-----END CERTIFICATE-----";
114                return new Identity(new StringReader(certStr));
115            } 
116            catch (Exception e) {
117                return null;
118            }
119        }
120
121        /**
122         * Parses the credential into multiple Objects based on the permissions
123         * imbued by the credential.
124         * @param d a Document, the parsed credential
125         * @param issuer an Identity that signed the credential
126         * @return an array of GENIPrivCredentials that represent the
127         * credential
128         */
129        protected Credential[] make_creds(Document d, Identity issuer) 
130                throws ABACException {
131            Node root = null;
132            Node credential = null;
133            Node owner_gid = null;
134            Node target_gid = null;
135            Node privileges = null;
136            Node priv = null;
137            Identity owner = null;
138            Identity target = null;
139            ArrayList<GENIPrivCredential> rv = 
140                new ArrayList<GENIPrivCredential>();
141
142
143            if ( (root = getChildByName(d, "signed-credential")) == null)
144                throw new CertInvalidException("No signed-credential element");
145            if ( (credential = getChildByName(root, "credential")) == null )
146                throw new CertInvalidException("No credential element");
147            if ( (owner_gid = getChildByName(credential, "owner_gid")) == null )
148                throw new CertInvalidException("No owner_gid element");
149            if ((target_gid = getChildByName(credential,"target_gid")) == null )
150                throw new CertInvalidException("No target_gid element");
151            if ((privileges = getChildByName(credential,"privileges")) == null )
152                throw new CertInvalidException("No privileges element");
153
154            Date exp = getTime(d, "expires");
155
156            if ( exp.before(new Date()))
157                throw new CertInvalidException("Certificate Expired " + exp);
158
159            if ( (owner = nodeToIdentity(owner_gid)) == null) 
160                throw new CertInvalidException("Bad owner_gid element");
161            if ( (target = nodeToIdentity(target_gid)) == null) 
162                throw new CertInvalidException("Bad target_gid element");
163
164            for (Node n = privileges.getFirstChild(); n != null; 
165                    n = n.getNextSibling()) {
166                /* Ignore non-elements and non-privilege elements */
167                if (n.getNodeType() != Node.ELEMENT_NODE ||
168                        !"privilege".equals(n.getNodeName())) continue;
169                Node name = null;
170                Node can_delegate = null;
171                boolean cd = false;
172                String cds = null;
173                String pname = null;
174
175                if ( (name = getChildByName(n, "name")) == null)
176                    throw new CertInvalidException("No privilege name");
177
178                if ((can_delegate = getChildByName(n, "can_delegate")) == null)
179                    throw new CertInvalidException("No privilege delegate");
180
181                if ( (pname = name.getTextContent()) == null)
182                    throw new CertInvalidException("No privilege name text");
183                if ((cds = can_delegate.getTextContent()) == null)
184                    throw new CertInvalidException("No delegate text");
185                cd = cds.equals("1") || cds.equals("true");
186
187                /* First privilege includes the basic speaks for defintion
188                 * for this owner */
189                if ( rv.isEmpty() ) {
190                    rv.add(new GENIPrivCredential(
191                                new Role(issuer.getKeyID() + ".speaks_for_" +
192                                    owner.getKeyID()),
193                                new Role(owner.getKeyID()), d, issuer, exp));
194                    rv.add(new GENIPrivCredential(
195                                new Role(issuer.getKeyID() + ".speaks_for_" +
196                                    owner.getKeyID()),
197                                new Role(owner.getKeyID() + ".speaks_for_" +
198                                    owner.getKeyID()), d, issuer, exp));
199                }
200
201                /* The privilege itself */
202                rv.add(new GENIPrivCredential(
203                            new Role(issuer.getKeyID() + "." + pname + "_" +
204                                target.getKeyID()),
205                            new Role(issuer.getKeyID() + ".speaks_for_" +
206                                owner.getKeyID()), d, issuer, exp));
207                if (cd ) {
208                    /* The rules for delegation, if necessary */
209                    rv.add(new GENIPrivCredential(
210                                new Role(issuer.getKeyID() + "." + pname + 
211                                    "_" + target.getKeyID()),
212                                new Role(issuer.getKeyID() + ".can_delegate_" 
213                                    + pname + "_" + target.getKeyID() + 
214                                    "." + pname + "_" + target.getKeyID()), 
215                                d, issuer, exp));
216                    rv.add(new GENIPrivCredential(
217                                new Role(issuer.getKeyID() + 
218                                    ".can_delegate_" + pname),
219                                new Role(owner.getKeyID()), d, issuer, exp));
220                }
221            }
222            return rv.toArray(new Credential[rv.size()]);
223        }
224
225        /**
226         * Parse the credential into multiple GENIPrivCredentials that encode
227         * its semantics.
228         * @param is an InputStream containing the credentals
229         * @param ids a Collection of Identities to use in validation
230         * @return an array of GENIPrivCredentials that represent the
231         * credential
232         * @throws CertInvalidException if the stream is unparsable
233         * @throws MissingIssuerException if none of the Identities can
234         *                      validate the certificate
235         * @throws BadSignatureException if the signature check fails
236         */
237        public Credential[] parseCredential(InputStream is, 
238                Collection<Identity> ids) throws ABACException {
239            try {
240                Document d = read_certificate(is);
241                XMLSignatureFactory fac = 
242                    XMLSignatureFactory.getInstance("DOM");
243                NodeList nl = d.getElementsByTagNameNS(XMLSignature.XMLNS, 
244                        "Signature");
245                DOMValidateContext valContext = null;
246                XMLSignature signature = null;
247                Identity lid = null;
248
249
250                if (nl.getLength() == 0) 
251                    throw new CertInvalidException(
252                            "Cannot find Signature element");
253
254                setIDAttrs(d);
255                valContext = new DOMValidateContext(new X509KeySelector(),
256                        nl.item(0));
257                if ( valContext == null )
258                    throw new ABACException("No validation context!?");
259
260                signature = fac.unmarshalXMLSignature(valContext);
261                if (signature == null) 
262                    throw new BadSignatureException(
263                            "Cannot unmarshal signature");
264
265                if (!signature.validate(valContext))
266                    throw new BadSignatureException("bad signature");
267
268                lid = getIdentity(nl.item(0));
269
270                if ( !ids.contains(lid) ) ids.add(lid);
271
272                return make_creds(d, lid);
273            }
274            catch (ABACException ae) {
275                throw ae;
276            }
277            catch (Exception e) {
278                throw new BadSignatureException(e.getMessage(), e);
279            }
280        }
281
282        /**
283         * One cannot create a GENIPrivCredential to encodes a single arbitrary
284         * head and tail, so this always fails.
285         * @param head a Role to encode
286         * @param tail a Role to encode
287         * @param aliases a KeyIDMap with keyid aliases
288         * @return null
289         */
290        public Credential generateCredential(Role head, Role tail, 
291                KeyIDMap aliases) {
292            return null;
293        }
294    };
295
296    /**
297     * These credentials are parsed in the specialization, so load_roles is
298     * not used.
299     * @throws CertInvalidException never
300     */
301    protected void load_roles() throws CertInvalidException { }
302
303
304    /**
305     * These credentials are never baked so make_rt0_content is
306     * not used.
307     * @return a Node, the place to attach signatures
308     * @throws ABACException never
309     */
310    protected Node make_rt0_content(long validity) throws ABACException { 
311        return null;
312    }
313
314    /**
315     * Return a CredentialCredentialFactorySpecialization for
316     * GENIPrivCredentials.  Used by the CredentialFactory to parse these kind
317     * of credentials.
318     * @return a CredentialFactorySpecialization for this kind of credential.
319     */
320    static public CredentialFactorySpecialization
321            getCredentialFactorySpecialization() {
322        return new GENIPrivSpecialization();
323    }
324}
Note: See TracBrowser for help on using the repository browser.