source: java/net/deterlab/abac/GENIPrivCredential.java @ 461edba

Last change on this file since 461edba was 461edba, checked in by Ted Faber <faber@…>, 10 years ago

Clean up javadoc for v8.

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