Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
128   455   42   12.8
70   219   0.4   10
10     5.1  
1    
 
 
  RoleBasedACParser       Line # 82 128 42 63.5% 0.63461536
 
  (1)
 
1    /*
2    * Copyright (c) 2000-2005, University of Salford
3    * All rights reserved.
4    *
5    * Redistribution and use in source and binary forms, with or without
6    * modification, are permitted provided that the following conditions are met:
7    *
8    * Redistributions of source code must retain the above copyright notice, this
9    * list of conditions and the following disclaimer.
10    *
11    * Redistributions in binary form must reproduce the above copyright notice,
12    * this list of conditions and the following disclaimer in the documentation
13    * and/or other materials provided with the distribution.
14    *
15    * Neither the name of the University of Salford nor the names of its
16    * contributors may be used to endorse or promote products derived from this
17    * software without specific prior written permission.
18    *
19    * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
20    * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
21    * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
22    * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
23    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
24    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
25    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
26    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
27    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
28    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
29    * POSSIBILITY OF SUCH DAMAGE.
30    */
31   
32    package issrg.pba.rbac.x509;
33   
34    import issrg.ac.AttributeCertificate;
35    import issrg.ac.Extension;
36    import issrg.ac.attributes.BasicAttConstraint;
37    import issrg.ac.extensions.AttributeAuthorityInformationAccess;
38    import issrg.ac.extensions.AuthorityInformationAccess;
39    import issrg.ac.extensions.NoRevocation;
40    import issrg.ac.extensions.WebdavCertificate;
41    import issrg.ac.extensions.WebdavRevocation;
42    import issrg.ac.attributes.NoAssertion;
43    import issrg.pba.ParsedToken;
44    import issrg.pba.DefaultParsedToken;
45    import issrg.pba.DefaultDelegatableToken;
46    import issrg.pba.rbac.LDAPDNPrincipal;
47    import issrg.pba.rbac.SignatureVerifier;
48    import issrg.pba.PbaException;
49    import issrg.pba.WebDAVRevocableDelegatableParsedToken;
50    import issrg.pba.WebDAVRevocableParsedToken;
51    import issrg.pba.rbac.*;
52    import issrg.pba.rbac.policies.Subtree;
53    import issrg.pba.rbac.policies.DITSubtree;
54    import issrg.pba.rbac.x509.ACUserEntry;
55    import issrg.utils.repository.TokenLocator;
56    import issrg.utils.repository.Entry;
57    import issrg.pba.repository.EntryLocator;
58    import issrg.pba.rbac.policies.SimpleEntry;
59    import issrg.pba.rbac.PermisRBAC;
60    import java.util.ArrayList;
61    import issrg.utils.repository.AttributeRepository;
62    import java.security.Principal;
63    import java.util.*;
64    import java.util.Vector;
65    import org.apache.log4j.*;
66    import org.apache.commons.logging.Log;
67    import org.apache.commons.logging.LogFactory;
68   
69   
70    /**
71    * This is the implementation of the AuthTokenParser that extracts Roles from
72    * the Attribute Certificates as defined by the Policy.
73    *
74    * <p>This is the default AuthTokenParser used by PERMIS, when X.509 flavour is
75    * configured in using issrg.pba.rbac.CustomisePERMIS.configureX509Flavour
76    * method.
77    *
78    * @author A Otenko
79    * @version 1.0
80    */
81   
 
82    public class RoleBasedACParser implements issrg.pba.rbac.RoleBasedAuthzTokenParser {
83    /**
84    * This is the default constructor. If you instantiate the RoleBasedACParser
85    * using this constructor, the code will fail to decode any Attribute
86    * Certificates until the Role Hierarchy is set by setRoleHierarchy method.
87    */
88   
89    //private static Log logger2 = LogFactory.getLog(RoleBasedACParser.class.getName());
90   
 
91  27 toggle public RoleBasedACParser(){}
92   
93    issrg.pba.rbac.RoleHierarchyPolicy roleHierarchy = null;
94    private static final issrg.pba.Credentials NullCreds=new issrg.pba.rbac.SetOfSubsetsCredentials();
95    private SignatureVerifier SV = null;
96    Logger logger = Logger.getLogger("issrg.pba.rbac.x509.RoleBasedACParser");
97    /**
98    * The constructor uses the Role Hierarchy policy and the Signature
99    * Verifier to subsequently decode the Attribute Certificates. If Signature
100    * Verifier is specified, it will be used to validate digital signatures on
101    * the ACs; otherwise signature verification will be ignored (e.g. for
102    * testing purposes - not recommended for real life deployments).
103    *
104    * @param rhpn is the RoleHierarchyPolicy used to decode the role values in
105    * the Attribute Certificates; can't be null
106    * @param signatureVerifier will be used to validate digital signatures;
107    * if null, no signature verification will be performed (NOT RECOMMENDED
108    * FOR REAL DEPLOYMENT AS INSECURE!)
109    */
 
110  0 toggle public RoleBasedACParser(issrg.pba.rbac.RoleHierarchyPolicy rhpn, SignatureVerifier signatureVerifier ) {
111  0 setRoleHierarchy(rhpn);
112  0 setSignatureVerifier(signatureVerifier);
113    }
114   
115    /**
116    * The constructor takes the Map of Assignment Rules, as returned by the
117    * PolicyParser and the Signature Verifier, which can be null.
118    * The Map of Assignment Rules must contain a RoleHierarchyPolicy under
119    * the key
120    * issrg.pba.rbac.RoleHierarchyPolicy.class.
121    *
122    * @param m is the map of assignment rules to use
123    * @param signatureVerifier will be used to validate digital signatures;
124    * if null, no signature verification will be performed (NOT RECOMMENDED
125    * FOR REAL DEPLOYMENT AS INSECURE!)
126    */
 
127  0 toggle public RoleBasedACParser(java.util.Map m, SignatureVerifier signatureVerifier){
128  0 setAuthTokenParsingRules(m);
129  0 setSignatureVerifier(signatureVerifier);
130    }
131   
132    /**
133    * This method returns the Authorisation Token Parsing Rules, as a Map with
134    * a single entry with the key issrg.pba.rbac.RoleHierarchyPolicy.class and
135    * the value being the RoleHierarchyPolicy used by this RoleBasedACParser.
136    *
137    * @return Map of rules; this implementation fills a single entry with the
138    * key issrg.pba.rbac.RoleHierarchyPolicy.class and the value being the
139    * RoleHierarchyPolicy; if the RoleHierarchyPolicy has not been set,
140    * the Map does not contain any entries
141    */
 
142  0 toggle public java.util.Map getAuthTokenParsingRules(){
143  0 java.util.Map m = new java.util.Hashtable();
144  0 if (roleHierarchy!=null) m.put(issrg.pba.rbac.RoleHierarchyPolicy.class, roleHierarchy);
145  0 return m;
146    }
147   
148    /**
149    * This method sets the SignatureVerifier to be used to validate the X.509
150    * Attribute Certificates.
151    *
152    * @param signatureVerifier is the SignatureVerifier used to validate the
153    * ACs; if null, no signature verification will be performed (SHOULD NOT
154    * BE USED IN PRODUCTION SCENARIOS!)
155    */
 
156  13 toggle public void setSignatureVerifier(SignatureVerifier signatureVerifier){
157  13 this.SV = signatureVerifier;
158    }
159   
160    /**
161    * This method returns the SignatureVerifier used by this RoleBasedACParser.
162    *
163    * @return SignatureVerifier used by this RoleBasedACParser, or null, if
164    * no signature verification is being performed.
165    */
 
166  0 toggle public SignatureVerifier getSignatureVerifier(){
167  0 return SV;
168    }
169   
170    /**
171    * This method sets the Authorisation Token Parsing Rules. It should
172    * contain a issrg.pba.rbac.RoleHierarchyPolicy in the entry
173    * with the key issrg.pba.rbac.RoleHierarchyPolicy.class.
174    *
175    * @param m - the Map of rules with a RoleHierarchyPolicy inside
176    */
 
177  15 toggle public void setAuthTokenParsingRules(java.util.Map m){
178  15 setRoleHierarchy((issrg.pba.rbac.RoleHierarchyPolicy) m.get(issrg.pba.rbac.RoleHierarchyPolicy.class));
179    }
180   
181    /**
182    * This method sets the Authorisation Token Parsing Rules by directly
183    * specifying the Role Hierarchy to be used.
184    *
185    * @param rhpn - the RoleHierarchyPolicy to be used; if null, decoding the
186    * ACs will always fail
187    */
 
188  15 toggle public void setRoleHierarchy(issrg.pba.rbac.RoleHierarchyPolicy rhpn){
189  0 if (logger.isDebugEnabled())logger.debug("got parsing rules: "+rhpn);//*********
190    //System.out.println("the rules: "+rhpn);//*********
191  15 roleHierarchy = rhpn;
192    }
193   
194    /**
195    * This method decodes a given Attribute Certificate. The Object is a byte
196    * array of the
197    * BER-encoded X.509 Attribute Certificate
198    *
199    * <p>First it is seen if the Authorisation Token is an X.509 Attribute
200    * Certificate. If there is no SignatureVerifier provided,
201    * the next stage is skipped; otherwise the digital signature on it is
202    * verified using the
203    * Signature Verifier provided at construction time or by calling the
204    * setSignatureVerifier method. If this fails, a
205    * SignatureVerificationFailedException is thrown with the would-be-valid
206    * ParsedToken and the original object in it.
207    *
208    * <p>If the X.509
209    * Attribute Certificate to be decoded contains an attribute with the OID
210    * matching one of the role types defined in the RoleHierarchyPolicy, all
211    * the
212    * values are assumed to be Printable Strings. Among these values the ones
213    * not mentioned in the RoleHierarchyPolicy are ignored; the known values
214    * are mapped into the role hierarchy, so that the resulting Credentials
215    * contained in the ParsedToken can be compared.
216    *
217    * <p>The attributes with OID not mentioned in the RoleHierarchyPolicy are
218    * ignored.
219    *
220    * <p>If an unknown critical extension is encountered, parsing of the AC
221    * fails.
222    *
223    * <p>If the AC contains a noAssertion extension, the ParsedToken's
224    * Credentials will be an empty set (but the delegatable Credentials may not
225    * be an empty set).
226    *
227    * <p>If the AC contains a basicAttributeConstraints extension, the result
228    * will be a DelegatableToken with the delegatable Credentials set to the
229    * set of Credentials contained in the AC. It will be the same as the
230    * assertable Credentials, if no noAssertion extension is there. The depth
231    * of delegation in the DelegatableToken will be the value of the
232    * basicAttributeContraints cast to a 32 bit non-negative number (should be
233    * enough to express any delegation tree in the world) with the same
234    * semantics as in basicAttributeConstraints, or "-1", if unconstrained
235    * delegation is allowed by the extension (no delegation depth was
236    * specified in the AC).
237    *
238    * @param acB a byte array of the BER-encoded X.509 AttributeCertificate
239    *
240    * @return the ParsedToken representing the Attribute Certificate
241    *
242    * @throws PbaException, if no Role Hierarchy Policy has been specified
243    * through the constructor or either of the methods, or if there was a
244    * problem when decoding the Authorisation Token
245    */
 
246  1788 toggle protected ParsedToken decodeX509AC(Object acB) throws issrg.pba.PbaException {
247  1788 logger.debug("to parse an X509 AC in DER");
248  0 if (roleHierarchy==null) throw new issrg.pba.PbaException("Failed to decode an AC: no Role Hierarchy was specified");
249   
250    // If it has already been decoded
251  1788 boolean bSignatureVerification=false;
252  1788 boolean checkRevocation=true;
253  1788 if (acB instanceof ParsedToken) return (ParsedToken)acB;
254  1779 issrg.ac.AttributeCertificate ac;
255    //if (acB instanceof byte[]){
256  1779 Principal signer;
257  1779 try{
258   
259  1779 ac = issrg.ac.AttributeCertificate.guessEncoding(acB);
260  0 if (logger.isDebugEnabled())logger.debug("Recieved certificate : " + ac.toString());
261  1779 signer = new LDAPDNPrincipal(issrg.ac.Util.generalNamesToString(ac.getACInfo().getIssuer().getV1Form()==null?ac.getACInfo().getIssuer().getV2Form().getIssuerName():ac.getACInfo().getIssuer().getV1Form()));
262    }catch (Throwable th){
263  0 if (logger.isDebugEnabled())logger.debug("Couldn't decode the Attribute Certificate");
264  0 throw new issrg.pba.PbaException("Couldn't decode the Attribute Certificate", th);
265    }
266   
267  1779 byte[] value;
268  1779 byte[] signature;
269  1779 String algorithmid;
270  1779 Exception signatureVerificationFailed=null;
271  1779 issrg.pba.rbac.ValidityPeriod vp = new issrg.pba.rbac.AbsoluteValidityPeriod(
272    ac.getACInfo().getValidityPeriod().getNotBefore().getTime().getTime(),
273    ac.getACInfo().getValidityPeriod().getNotAfter().getTime().getTime()
274    );
275  1779 java.util.Vector attributes = ac.getACInfo().getAttributes();
276  1779 java.util.Vector roles = new java.util.Vector();
277   
278  3562 for (int i=attributes.size(); i-->0;){
279  1783 issrg.ac.Attribute att = (issrg.ac.Attribute)attributes.get(i);
280  1783 String type = roleHierarchy.getTypeByOID(att.getType());
281  1783 if (type!=null){ // aha! such a type has been registered. we know roles of this type
282  1779 java.util.Vector av = att.getValues();
283  1779 try{
284  3667 for (int j=av.size(); j-->0;){
285  1888 issrg.pba.rbac.RoleHierarchyNode rhn = roleHierarchy.getRole(type, new issrg.ac.attributes.PermisRole(
286    (issrg.ac.AttributeValue)av.get(j)
287    ).getRoleValue()
288    );
289   
290    // System.out.println("\t\textracting "+type+": "+(rhn==null?"null": rhn.getRoleValue())); //***********
291  1888 if (rhn!=null){ // if null, then no such role has been found
292  1888 if (logger.isDebugEnabled()){
293  0 logger.debug((issrg.ac.AttributeValue)av.get(j) + " has been found in the role hierarchy policy as has been added to the valid roles");
294    }
295  1888 roles.add(new issrg.pba.rbac.ExpirableCredentials(
296    new issrg.pba.rbac.PermisCredentials(rhn),
297    vp
298    )
299    );
300    }else{
301  0 if (logger.isDebugEnabled()){
302  0 logger.debug((issrg.ac.AttributeValue)av.get(j) + " has not been found in the role hierarchy policy as has been ignored");
303    }
304    }
305    }
306    }catch(iaik.asn1.CodingException ce){
307    // ignore malformed Attributes
308    }
309    }
310    }
311   
312  1779 Vector extensions = ac.getACInfo().getExtensions().getValues();
313  1779 int numberOfExtension = extensions.size();
314  1779 int depth=0;
315   
316  1779 issrg.pba.Credentials creds=new issrg.pba.rbac.SetOfSubsetsCredentials(roles);
317  1779 issrg.pba.Credentials assertableCredentials=creds;
318  1779 issrg.pba.Credentials delegateableCredentials=null;
319  1779 ACUserEntry h = new ACUserEntry(ac);
320  1779 TokenLocator issuerTokenLocator=null;
321  1779 TokenLocator signerTokenLocator=null;
322   
323    // the default Subject Domain is set to the whole world, excluding the Holder of the AC - the Holder can't delegate to himself
324  1779 Subtree subjectDomain=new DITSubtree(LDAPDNPrincipal.WHOLE_WORLD_DN, 0, -1, null,
325    new Subtree[]{new DITSubtree(h.getDN(), 0, 0, null, null)});
326   
327  1779 Entry signerEntry = new SimpleEntry(signer);
328  1779 String revLoc=null, valLoc=null; //Variables used for holding revocation information for a token
329   
330  4765 for (int ii = 0; ii < numberOfExtension; ii++) {
331  2986 Extension e = (Extension) extensions.get(ii);
332  2986 if (e instanceof NoAssertion) {
333  622 assertableCredentials=NullCreds;
334    }
335  2986 if (e instanceof BasicAttConstraint) {
336  870 delegateableCredentials=creds;
337  870 depth = ((BasicAttConstraint) e).getDepth(); //-1 for unlimited, 0 for 1 level, 2 for 2 level...
338    }
339    // Rune Bjerk 10.07.2007
340   
341    //Old implementation:
342    //if (e instanceof AttributeAuthorityInformationAccess){
343    // AttributeRepository rep = PermisRBAC.getRepositories(((AttributeAuthorityInformationAccess)e).getLocations());
344    // issuerTokenLocator = new EntryLocator(signerEntry, LDAPDNPrincipal.WHOLE_WORLD_DN, rep, issuerTokenLocator);
345    //}
346   
347   
348    //Checking if revocation checking should be performed
349  2986 if(e instanceof NoRevocation){
350  0 checkRevocation=false; //No revocation checking should be performed
351    }
352   
353  2986 if(checkRevocation){
354  12124 for(int i =0;i<extensions.size();i++){
355  9138 if(e instanceof AuthorityInformationAccess){
356  0 AuthorityInformationAccess aia =(AuthorityInformationAccess)e;
357  0 ArrayList exts =aia.getValues();
358  0 for(int j=0;j<exts.size();j++){
359  0 if(exts.get(j)instanceof WebdavRevocation){
360  0 revLoc =((WebdavRevocation)exts.get(j)).getLocation();
361    }
362  0 if(exts.get(j)instanceof WebdavCertificate){
363  0 valLoc =((WebdavCertificate)exts.get(j)).getLocation();
364    }
365   
366    }
367    }
368    }
369    }
370    // when Subject Domain extension is supported, insert code here to modify subjectDomain
371   
372  2986 if (e.getClass().equals(Extension.class) && e.isCritical()){
373    // it wasn't parsed using a special class, so it is an unsupported critical extension
374    // ignore the extracted attributes, but don't complain
375  0 assertableCredentials=NullCreds;
376  0 delegateableCredentials=null;
377  0 break; // no point looking through the AC anymore
378    }
379    }
380  1779 if (signerTokenLocator==null) signerTokenLocator=issuerTokenLocator;
381    // add the default locators too - the DN without any Repository attached to it
382  1779 issuerTokenLocator=new EntryLocator(signerEntry, signer, null, issuerTokenLocator);
383  1779 signerTokenLocator=new EntryLocator(signerEntry, signer, null, signerTokenLocator);
384   
385    // no harm passing delegatable credentials and a depth. If BasicAttConstraint
386    // extension is present, the delegatableCredentials is not an empty set
387    // and depth is meaningful. Otherwise delegatableCredentials is an empty set.
388  1779 ParsedToken p;
389   
390  1779 if(delegateableCredentials!=null && revLoc!=null && valLoc!=null){ //The token is both WebDAVRevocable and Delegatable
391  0 p= new WebDAVRevocableDelegatableParsedToken(h, issuerTokenLocator, assertableCredentials, delegateableCredentials, subjectDomain, depth,revLoc,valLoc,(byte[])acB, checkRevocation);
392   
393  1779 }else if (delegateableCredentials!=null){// Only Delegatable
394  870 p=new DefaultDelegatableToken(h, issuerTokenLocator, assertableCredentials, delegateableCredentials, subjectDomain, depth, checkRevocation);
395   
396  909 }else if(revLoc!=null && valLoc!=null){ //Only WebDAVRevocable
397  0 p=new WebDAVRevocableParsedToken(h,issuerTokenLocator,assertableCredentials,revLoc,valLoc,(byte[])acB,checkRevocation);
398   
399    }else{ //Neither WebDAVRevocable nor Delegatable
400  909 p=new DefaultParsedToken(h, issuerTokenLocator, assertableCredentials,checkRevocation);
401    }
402   
403  1779 try{
404   
405    // because the AC has been successfully decode previously, acB must be a byte array
406   
407   
408  1779 value=issrg.ac.AttributeCertificate.getToBeSignedByteArray((byte[])acB);
409   
410  1779 signature=(byte[]) ac.getSignatureValue().getValue();
411    //algorithmid=ac.getSignatureAlgorithm().toString();
412  1779 algorithmid=ac.getSignatureAlgorithm().getAlgorithm().getID();
413   
414  1779 if (SV == null) {// no signature verfication is needed
415  0 if (logger.isDebugEnabled())logger.debug("Signature verification is turned off");
416  740 bSignatureVerification = true;
417    }
418    else {// the signature verification process is needed
419  0 if (logger.isDebugEnabled())logger.debug("Signature verification is enabled");
420  1039 Date date = new Date();
421  1039 long start=date.getTime();
422  1039 bSignatureVerification=SV.checkSignature(value,signature,algorithmid,signerTokenLocator);
423  1039 date = new Date();
424  1039 long end=date.getTime();
425  1039 end = end - start;
426    }
427   
428  1779 if(bSignatureVerification==false){
429    //signature verification fails...
430  0 if (logger.isDebugEnabled()){
431  0 String but = "";
432  0 int i = 0;
433   
434  0 logger.debug("Signature verification failed for token");
435    }
436  0 throw new issrg.pba.PbaException("Signature verification failed");
437   
438    }
439   
440    }catch(Exception e){
441  0 signatureVerificationFailed=e; // now we won't throw the exception just yet - wait for the token to be decoded
442    }
443   
444    // now if signature verification failed, we will throw the exception
445    // with the successfully decoded AC in it; some intelligent code may find it useful
446  0 if (signatureVerificationFailed!=null) throw new SignatureVerificationFailedException(signatureVerificationFailed, p, acB);
447  0 if (logger.isDebugEnabled())logger.debug("certificate parsed succesfully : " + p.getHolder().getEntryName().getName() + " has : " + p.getCredentials());
448  1779 return p;
449    }
450   
 
451  1788 toggle public ParsedToken decode(Object acB) throws issrg.pba.PbaException {
452  1788 return this.decodeX509AC(acB);
453    }
454    }
455