Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
636   2,653   167   6.17
284   1,133   0.42   5.72
103     2.61  
18    
 
 
  XMLPolicyParser       Line # 88 116 25 76.7% 0.76666665
  XMLPolicyParser.ActionPolicyNode       Line # 730 31 8 96% 0.96
  XMLPolicyParser.DomainPolicyNode       Line # 870 11 2 100% 1.0
  XMLPolicyParser.SubjectDomainPolicyNode       Line # 952 2 1 100% 1.0
  XMLPolicyParser.TargetDomainPolicyNode       Line # 965 2 1 100% 1.0
  XMLPolicyParser.DomainSpecNode       Line # 980 59 20 82% 0.82
  XMLPolicyParser.SubjectDomainSpecNode       Line # 1167 1 1 100% 1.0
  XMLPolicyParser.TargetDomainSpecNode       Line # 1177 1 1 100% 1.0
  XMLPolicyParser.RoleAssignmentPolicyNode       Line # 1191 85 22 86.3% 0.86290324
  XMLPolicyParser.RoleHierarchyNode       Line # 1449 44 18 82.7% 0.8271605
  XMLPolicyParser.RoleHierarchyPolicyNode       Line # 1659 21 4 85.7% 0.85714287
  XMLPolicyParser.RoleListNode       Line # 1794 28 8 82% 0.82
  XMLPolicyParser.RoleSpecNode       Line # 1925 17 4 90% 0.9
  XMLPolicyParser.SOAPolicyNode       Line # 2027 25 10 75.6% 0.75609756
  XMLPolicyParser.TargetAccessPolicyNode       Line # 2115 105 34 79.6% 0.7962963
  XMLPolicyParser.PMIXMLPolicyNode       Line # 2441 3 1 100% 1.0
  XMLPolicyParser.RepositoryPolicyNode       Line # 2457 9 3 87.5% 0.875
  XMLPolicyParser.MSoDPolicySetNode       Line # 2499 76 21 81.7% 0.8173913
 
  (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.xmlpolicy;
33   
34    import issrg.pba.rbac.policies.*; // added for MSoD
35    import issrg.pba.rbac.*;
36    import issrg.pba.Obligations;
37    import issrg.pba.SimpleObligations;
38   
39    import org.xml.sax.Attributes;
40    import javax.xml.parsers.SAXParserFactory;
41   
42    import issrg.pba.rbac.policies.DITSubtree;
43    import issrg.pba.rbac.policies.Subtree;
44   
45    import issrg.pba.rbac.PolicyParsingException;
46    import issrg.pba.rbac.LDAPDNPrincipal;
47    import issrg.pba.rbac.BadURLException;
48    import issrg.pba.rbac.URLHandler;
49   
50   
51    import java.security.Principal;
52   
53    import java.util.ArrayList;
54    import java.util.Vector;
55    import java.util.Map;
56    import java.util.Enumeration; //added for MSoD
57   
58    /**
59    * This class parses the given XML into an internal representation.
60    * It creates rules for the DelegationPolicy and AccessPolicy objects.
61    *
62    * <p>The parser was written in 2000 when XML DOM3 parsers were not readily
63    * available with JDK, so we went for a (lightweight) SAX API. Effectively,
64    * this parser converts XML into a tree of PolicyXMLNode objects or its
65    * subclasses, very much like modern DOM3 parsers convert XML into a tree of
66    * Nodes.
67    *
68    * <p>To extend the set of XML elements understood by XML Parser, you need to
69    * extend the PolicyXMLNode class and provide a special constructor that
70    * contains two arguments: XMLPolicyParser and org.xml.sax.Attributes. Note
71    * that the inner classes will have an additional implied argument that is of
72    * the type
73    * of the containing class (for example, this is why the extensions of the
74    * PolicyXMLNode internal to this class do not have
75    * XMLPolicyParser as one of their parameters to the constructor - it is there
76    * implicitly).
77    *
78    * <p>This is a Role based implementation, so it constructs the RoleHierarchy
79    * along with Role based rules for the Delegation and Access policy objects.
80    *
81    * <p>Note that if the XML complies to a different syntax, the results are
82    * unpredictable.
83    *
84    * @author A Otenko
85    * @version 1.0
86    */
87   
 
88    public class XMLPolicyParser implements issrg.pba.PolicyParser,
89    org.xml.sax.ContentHandler,
90    org.xml.sax.ErrorHandler {
91   
92    /**
93    * This method registers a set of default XML Nodes understood by XML
94    * Parser. The general XML syntax does not need to be extensible, but
95    * the IF-statement is extensible through this mechanism. You do not have
96    * to call this method, if you have registered other classes to handle
97    * the nodes that appear in the IF-statement; otherwise, you need to
98    * call this method to use the default implementation.
99    *
100    * @see #registerXMLNode
101    */
 
102  21 toggle public static void registerDefaultNodes(){
103  21 issrg.pba.rbac.xmlpolicy.ifstatement.ArgNode.register();
104  21 issrg.pba.rbac.xmlpolicy.ifstatement.ConstantNode.register();
105  21 issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode.register();
106   
107  21 issrg.pba.rbac.xmlpolicy.ifstatement.OperatorNode.register();
108   
109  21 issrg.pba.rbac.xmlpolicy.ifstatement.PresentNode.register(); // this one registers a default interpreter as well
110  21 issrg.pba.rbac.xmlpolicy.ifstatement.NotNode.register(); // this one registers a default interpreter as well
111   
112  21 issrg.pba.rbac.xmlpolicy.ifstatement.AndNode.register(); // this one registers a default interpreter as well
113  21 issrg.pba.rbac.xmlpolicy.ifstatement.OrNode.register(); // this one registers a default interpreter as well
114   
115  21 issrg.pba.rbac.xmlpolicy.ifstatement.EqNode.register(); // this node also has a default interpreter
116  21 issrg.pba.rbac.xmlpolicy.ifstatement.GeNode.register();
117  21 issrg.pba.rbac.xmlpolicy.ifstatement.LeNode.register();
118  21 issrg.pba.rbac.xmlpolicy.ifstatement.GtNode.register();
119  21 issrg.pba.rbac.xmlpolicy.ifstatement.LtNode.register();
120  21 issrg.pba.rbac.xmlpolicy.ifstatement.SubstringsNode.register();
121   
122  21 issrg.pba.rbac.xmlpolicy.ifstatement.IntegerInterpreter.register();
123  21 issrg.pba.rbac.xmlpolicy.ifstatement.StringInterpreter.register();
124   
125  21 issrg.pba.rbac.Time.register();
126  21 issrg.pba.rbac.TimeInterpreter.register();
127    }
128   
129    /**
130    * This is a utility method that parses the policy provided as a String.
131    *
132    * @param policy - the XML text of the PERMIS XML Policy
133    *
134    * @return XMLPolicyParser that has successfully parsed the policy; use its
135    * methods to retrieve the subpolicies and other rules
136    * @throws PbaException, if there was a problem parsing the policy
137    */
 
138  0 toggle public static XMLPolicyParser getXMLPolicyParser(String policy) throws issrg.pba.PbaException{
139  0 return new XMLPolicyParser(policy);
140    }
141   
142   
143    /**
144    * This is a utility method that parses the policy provided as a
145    * InputStream.
146    *
147    * @param is - the InputStream with the XML text of the PERMIS XML Policy
148    *
149    * @return XMLPolicyParser that has successfully parsed the policy; use its
150    * methods to retrieve the subpolicies and other rules
151    */
 
152  1 toggle public static XMLPolicyParser getXMLPolicyParser(java.io.InputStream is) throws issrg.pba.PbaException{
153  1 return new XMLPolicyParser(new org.xml.sax.InputSource(is));
154    }
155   
156    /**
157    * This is a collection of all known nodes. It is useful for quick lookup of
158    * the needed node to create for a given node name.
159    */
160    protected final static java.util.Map knownNodes = new java.util.Hashtable();
161    private static Class [] defaultConstr = new Class[]{XMLPolicyParser.class, org.xml.sax.Attributes.class};
 
162  21 toggle static{
163  21 try{
164  21 registerXMLNode(XMLTags.ROLE_HIERARCHY_POLICY_NODE, RoleHierarchyPolicyNode.class);
165  21 registerXMLNode(XMLTags.ROLE_SPEC_NODE, RoleSpecNode.class);
166  21 registerXMLNode(XMLTags.SUP_ROLE_NODE, RoleHierarchyNode.class);
167  21 registerXMLNode(XMLTags.SUBJECT_POLICY_NODE, SubjectDomainPolicyNode.class);
168  21 registerXMLNode(XMLTags.SUBJECT_DOMAIN_SPEC_NODE, SubjectDomainSpecNode.class);
169  21 registerXMLNode(XMLTags.SOA_POLICY_NODE, SOAPolicyNode.class);
170  21 registerXMLNode(XMLTags.REPOSITORY_POLICY_NODE, RepositoryPolicyNode.class);
171  21 registerXMLNode(XMLTags.TARGET_ACCESS_POLICY_NODE, TargetAccessPolicyNode.class);
172  21 registerXMLNode(XMLTags.TARGET_POLICY_NODE, TargetDomainPolicyNode.class);
173  21 registerXMLNode(XMLTags.TARGET_DOMAIN_SPEC_NODE, TargetDomainSpecNode.class);
174  21 registerXMLNode(XMLTags.ACTION_POLICY_NODE, ActionPolicyNode.class);
175  21 registerXMLNode(XMLTags.ROLE_ASSIGNMENT_POLICY_NODE, RoleAssignmentPolicyNode.class);
176  21 registerXMLNode(XMLTags.ROLE_LIST_NODE, RoleListNode.class);
177  21 registerXMLNode(XMLTags.X_509_PMI_RBAC_POLICY_NODE, PMIXMLPolicyNode.class);
178    // registerXMLNode(XMLTags.ROLE_MAPPING_POLICY_NODE, RoleMappingPolicyNode.class);
179  21 registerXMLNode(XMLTags.MSoD_POLICY_SET_NODE, MSoDPolicySetNode.class); // added for MSoD
180   
181    }catch (NoSuchMethodException nsme){
182  0 nsme.printStackTrace(); // this shouldn't happen
183    }
184    }
185   
186    /**
187    * For debugging purposes. It prints out the names of all known nodes to
188    * System.out.
189    */
 
190  0 toggle public static void printNodes(){
191  0 System.out.println("The nodes registered with the XML Policy parser:");
192  0 Object [] keys = knownNodes.keySet().toArray();
193   
194  0 for (int i=0; i<keys.length; i++){
195  0 System.out.println(keys[i]);
196    }
197  0 System.out.println();
198    }
199   
200    /**
201    * This method can register any PolicyXMLNode constructor with parameters
202    * XMLPolicyParser and org.xml.sax.Attributes
203    * to it.
204    *
205    * @param nodeName is the name of the XML element the provided class can
206    * parse
207    * @param nodeClass is the class of the parser; it must have a constructor
208    * with the first parameter
209    * being XMLPolicyParser and the other being org.xml.sax.Attributes,
210    * where XMLPolicyParser will be the reference to the XMLPolicyParser
211    * that performs parsing, and the Attributes is the set of attributes of
212    * the element being parsed
213    */
 
214  609 toggle public static void registerXMLNode(String nodeName, Class nodeClass) throws NoSuchMethodException {
215  609 knownNodes.put(nodeName, nodeClass.getConstructor(defaultConstr));
216    }
217   
218    /**
219    * This is the whole Policy as a parsed tree of XML nodes.
220    */
221    protected PMIXMLPolicyNode pmiXMLPolicy;
222   
223    /**
224    * The node stack represents the current state of the parsing tree. The
225    * nodes
226    * are inserted at the beginning, its parent is the object number 1, etc.
227    */
228    protected java.util.Vector nodeStack;
229   
230    /**
231    * This is a reference to a &lt;RoleHierarchyPolicy&gt; XML node. However,
232    * it is functional on its own.
233    */
234    protected RoleHierarchyPolicyNode roleHierarchyPolicy; // this is just a bunch of Roles we know
235    // they are linked into a hierarchy when parsing
236   
237    /**
238    * This variable is used by the RoleList node to assign the correct
239    * validity period to the
240    * roles in the role list. This value is changed by the
241    * RoleAssignmentPolicy and by the
242    * TargetAccessPolicy.
243    */
244    protected issrg.pba.rbac.ValidityPeriod validityForRoleList;
245   
246    /**
247    * This is used when parsing the RoleSpec entity. It holds the collection of
248    * roles, defined within one RoleSpec. Note that embedded RoleSpecs are not
249    * allowed: there can be only one open RoleSpec at a time.
250    */
251    private java.util.Map rolespec;
252   
253    /**
254    * This is used when parsing the SubjectPolicy entry. It holds the
255    * SubjectPolicy
256    * object until the Assignment Policy has been created.
257    */
258    private DomainPolicyNode subjectPolicy;
259   
260    /**
261    * This is used when parsing the SOAPolicy entry. It holds a collection of all
262    * known SOAs and their DNs. Note that it is used in AssignmentPolicy only.
263    */
264    private SOAPolicyNode soaPolicy;
265   
266    /**
267    * This is used when parsing the Target policy
268    */
269    private DomainPolicyNode targetPolicy;
270   
271    /**
272    * This is used when parsing the Action policy, and later will be referred
273    * by
274    * the Target Access policy.
275    */
276    private ActionPolicyNode actionPolicy;
277   
278    /**
279    * This is used when parsing the Target Access policy
280    */
281    private TargetAccessPolicyNode targetAccessPolicy;
282   
283    /**
284    * This is where MSoDPolicy goes, added for MSoD
285    */
286    private MSoDPolicySetNode msodPolicySetNode;
287   
288    /**
289    * This is where Repository Policy goes
290    */
291    private RepositoryPolicyNode repositoryPolicy;
292   
293    /**
294    * This is a parsing-specific variable. It is used to locate the error
295    * point.
296    */
297    protected org.xml.sax.Locator locator; // this is for parsing
298   
299    /**
300    * This is the reference to the object, containing the rules for role
301    * assignment
302    */
303    protected RoleAssignmentPolicyNode delegationPolicy;
304   
305    /**
306    * This is used when creating new nodes
307    */
308    protected org.xml.sax.Attributes attrs;
309   
310   
 
311  0 toggle protected XMLPolicyParser(){}
312   
313    /**
314    * This constructor can build a policy out of an InputSource, containing an
315    * XML Policy.
316    *
317    * @param xmlSource is the source, containing the XML Policy to parse
318    */
 
319  1 toggle public XMLPolicyParser(org.xml.sax.InputSource xmlSource) throws issrg.pba.PbaException{
320  1 _init_(xmlSource);
321    }
322   
323    /**
324    * This constructor can build a policy out of the string representation of
325    * the XML.
326    *
327    * @param xml is the XML text of the policy
328    */
 
329  24 toggle public XMLPolicyParser(String xml) throws issrg.pba.PbaException {
330  24 org.xml.sax.InputSource xmlSource = new org.xml.sax.InputSource(new java.io.StringReader(xml));
331  24 _init_(xmlSource);
332    }
333   
334    /**
335    * This is the method that does the actual initialisation of the object. It
336    * accepts parameters in the same meaning as the constructor with the same
337    * parameter.
338    *
339    * @param xmlSource is the source, containing the XML Policy to parse
340    */
 
341  25 toggle private void _init_(org.xml.sax.InputSource xmlSource) throws issrg.pba.PbaException {
342  25 SAXParserFactory sf = SAXParserFactory.newInstance(); //new SAXParserFactoryImpl();//newInstance();
343    // perhaps, I'll remove this?..
344  25 sf.setValidating(false);
345  25 sf.setNamespaceAware(false);
346   
347  25 try{
348  25 org.xml.sax.XMLReader parser = sf.newSAXParser().getXMLReader();
349    /*parser.setEntityResolver(new org.xml.sax.EntityResolver(){
350    * //private final org.xml.sax.InputSource is = new org.xml.sax.InputSource(new java.io.FileReader("policy.dtd"));
351    * public org.xml.sax.InputSource resolveEntity(String id0, String id1){
352    * try{
353    * return new org.xml.sax.InputSource(new java.io.FileReader(id0==null?id1:id0)); // always return an empty Input Source
354    * }catch(java.io.FileNotFoundException fnfe){
355    * return null;
356    * }
357    * }
358    * });
359    */
360    //parser.setErrorHandler(this);
361  25 parser.setContentHandler(this);
362  25 parser.parse(xmlSource);
363    //sf.newSAXParser().parse(xmlSource, new org.xml.sax.helpers.DefaultHandler());
364    }catch (org.xml.sax.SAXParseException se){
365  0 if (se.getException()!=null){
366    //String cause=se.getCause().getMessage();
367  0 throw new issrg.pba.PbaException("Could not initialise; parse error @ line "+se.getLineNumber(), se.getException());
368   
369    }else{
370    //String cause=se.getMessage();
371  0 throw new issrg.pba.PbaException("Could not initialise; parse error @ line "+se.getLineNumber(), se);
372    //String cause=se.getCause().getMessage();
373    }
374    }catch (org.xml.sax.SAXException sae){
375  0 throw new issrg.pba.PbaException("Policy parse failed: "+sae.getMessage(), sae);
376    }catch (javax.xml.parsers.ParserConfigurationException pce){
377  0 throw new issrg.pba.PbaException("Policy parse failed: "+pce.getMessage(), pce);
378    }catch (java.io.IOException io){
379  0 throw new issrg.pba.PbaException("IO failure: "+io.getMessage(), io);
380    }
381    }
382   
383    /**
384    * VOID
385    */
 
386  0 toggle public void skippedEntity(String what){
387    }
388   
389    /**
390    * VOID
391    */
 
392  0 toggle public void processingInstruction(String target, String data){
393    }
394   
395    /**
396    * VOID
397    */
 
398  0 toggle public void ignorableWhitespace(char [] arr, int start, int len){
399    }
400   
401    /**
402    * This is a callback function that is invoked by the SAX parsing process.
403    * It will be
404    * invoked when the parse encounter string text in the xml file.
405    *
406    * <p>For the details of the parameters please refer to the XML SAX API
407    * documentation.
408    *
409    * @Gansen: I changed this implementation to allow the system to get the strings of obligations.
410    * before I do this, the system only get the attributes of obligation.
411    *
412    * @Sassa: Why don't you create a String out of a char array and trim it,
413    * if you want to get rid of whitespace?
414    */
415   
 
416  10141 toggle public void characters(char [] arr, int start, int len){
417  10141 if (len>0 && nodeStack.size()>0) // that's your test if it is inside a node - should always be true, because this method is called so; just a sanity check
418  7094 ((PolicyXMLNode)nodeStack.get(0)).addString(new String(arr, start, len).trim());
419    }
420   
421    /**
422    * This is the start of the recursion body of the parser; it is called any
423    * time
424    * the opening tag of an element is encountered: <b>You should not invoke
425    * it manually</b>. It creates a proper
426    * PolicyXMLNode implementation object and maintains a stack of nodes for
427    * the
428    * current branch.
429    *
430    * @see PolicyXMLNode
431    */
 
432  2668 toggle public void startElement(String URI, String localName, String qName, org.xml.sax.Attributes attrs) throws org.xml.sax.SAXParseException{
433    // System.out.println("getting in: <"+localName+"("+qName+")"+"> @ "+locator.getLineNumber()+"..." ); //****
434    //System.out.println("Attrs:" + attrs.getIndex(qName)+":" + attrs.getLocalName(0) + ":" + attrs.getQName(0) + ":" + attrs.getType(0) + ":" + attrs.getValue(0));
435    // int num = attrs.getLength();
436    // System.out.println(num);
437    // for (int i = 0; i < num; i++) {
438    // System.out.println("LocalName: " + attrs.getLocalName(i) + "Qname: " + attrs.getQName(i) + "Type: " + attrs.getType(i) + "URI: " + attrs.getURI(i) + "Value: " + attrs.getValue(i));
439    // }
440   
441    //localName = localName.intern();
442  2668 if (localName.intern()==""){
443  0 localName=qName;//.intern();
444    }
445    // from now on it is safe (and quick) to just compare localName to one of the *_NODE variables
446    //System.out.print(localName+"..."); //****
447   
448  2668 this.attrs=attrs;
449   
450  2668 PolicyXMLNode node=null;
451  2668 try{
452  2668 java.lang.reflect.Constructor co = (java.lang.reflect.Constructor)knownNodes.get(localName);
453  2668 if (co!=null){ // if there is such node defined; otherwise it must be some node that does not have a corresponding class, so the PolicyXMLNode class should be used instead
454  926 node=(PolicyXMLNode)(co.newInstance(new Object[]{this, this.attrs}));
455    }
456    }catch(Exception iae){
457  0 throw new org.xml.sax.SAXParseException(iae.getMessage(), locator, iae);
458    //iae.printStackTrace(); //****
459    //node=null;
460    }/*catch(InstantiationException ie){
461    //ie.printStackTrace(); //****
462    //node=null;
463    }catch(java.lang.reflect.InvocationTargetException ite){
464    //ite.printStackTrace(); //****
465    }*/
466   
467  2668 if (node==null){
468  1742 node = new PolicyXMLNode(localName, attrs);
469    }
470  2668 nodeStack.insertElementAt(node, 0);
471   
472    //System.out.println("instantiated "+node.getClass().getName()+" ok"); //*****
473    }
474   
475    /**
476    * This is the end of the recursion body; it is called each time the element
477    * closing tag is encountered: <b>You should not invoke
478    * it manually</b>. This method simply maintains the node stack and
479    * constructs
480    * the XML node tree, and invokes the <code>{@link PolicyXMLNode#construct()
481    * construct}</code> method of the closing element.
482    */
 
483  2668 toggle public void endElement(String URI, String localName, String qName) throws org.xml.sax.SAXException {
484    //System.out.print("getting out: </"+localName+"("+qName+")"+"> @ "+locator.getLineNumber()+"..."); //****
485   
486  2668 try{
487  2668 PolicyXMLNode node = (PolicyXMLNode)nodeStack.remove(0);
488   
489  2668 if (nodeStack.size()==0){ // we are there at last! :-)
490  25 pmiXMLPolicy=(PMIXMLPolicyNode)node;
491    }else{
492  2643 ((PolicyXMLNode)nodeStack.get(0)).addChild(node);
493    }
494   
495    // now let the node know it finished and is ready to prepare its data now
496    //System.out.print("entering the construct..."); //*******
497  2668 node.construct();
498    //System.out.println("ok"); //*******
499    }catch (Exception e){
500  0 throw new org.xml.sax.SAXParseException(e.getMessage(), locator, e);
501    }catch (Throwable th){
502  0 throw new org.xml.sax.SAXParseException(th.getMessage(), locator);
503    }
504    }
505   
 
506  25 toggle public void startDocument(){
507  25 pmiXMLPolicy = null;
508  25 roleHierarchyPolicy = null;
509  25 nodeStack = new java.util.Vector();
510    }
511   
512    /**
513    * VOID
514    */
 
515  25 toggle public void endDocument(){
516    }
517   
518    /**
519    * This method sets a source locator, which is used when sending error
520    * messages: <b>You should not invoke this method manually</b>.
521    */
 
522  25 toggle public void setDocumentLocator(org.xml.sax.Locator l){
523  25 this.locator=l;
524    }
525   
526    /**
527    * VOID
528    */
 
529  0 toggle public void startPrefixMapping(String prefix, String URI){
530    }
531   
532    /**
533    * VOID
534    */
 
535  0 toggle public void endPrefixMapping(String prefix){
536    }
537   
538   
539    /*
540    * PARSER FUNCTIONS ENDED.
541    */
542   
543    /*
544    * ERROR HANDLER FUNCTIONS
545    */
 
546  0 toggle public void warning(org.xml.sax.SAXParseException spe){
547    }
548   
 
549  0 toggle public void fatalError(org.xml.sax.SAXParseException spe){
550    }
551   
 
552  0 toggle public void error(org.xml.sax.SAXParseException spe){
553    }
554   
555    /**
556    * Does the same as expect with boolean parameter optional=false.
557    *
558    * @see expect(java.util.Vector, int, String, boolean)
559    */
560   
 
561  770 toggle private static PolicyXMLNode expect(java.util.Vector where, int pos, String what) throws PolicyParsingException{
562  770 return expect(where, pos, what, false);
563    }
564   
565    /**
566    * This is a tiny service function that just checks if the given vector of
567    * child
568    * nodes contains the needed node at the given position. If not, an
569    * exception
570    * is thrown. It may be marked optional, in which case null is returned if
571    * the
572    * node at that position is not what is expected.
573    *
574    * @param where is the vector of child nodes
575    * @param pos is the position in the vector where the sought node is
576    * expected to be
577    * @param what is the string name of the node
578    * @param optional says whether the sought node is optional or not; if true,
579    * no
580    * exception is thrown if the node is not what was expected, or the
581    * vector
582    * is too short
583    *
584    * @return the reference to the node
585    *
586    * @throws PolicyParsingException if the vector is too short or the node in
587    * that
588    * position is not the expected one
589    */
590   
 
591  1439 toggle private static PolicyXMLNode expect(java.util.Vector where, int pos, String what, boolean optional) throws PolicyParsingException{
592  1439 try{
593  1439 if (where.size()<=pos){
594  0 if (!optional) throw new PolicyParsingException("Cannot access an expected child node: "+what);
595  416 return null; // if optional, then just return null
596    }
597  1023 PolicyXMLNode c2 = (PolicyXMLNode)where.get(pos);
598  1023 if (c2.getName().intern()!=what.intern()){
599  0 if (!optional) throw new PolicyParsingException(what+" node has been exected, but "+c2.getName()+" was found");
600  11 c2=null;
601    }
602   
603  1023 return c2;
604    }catch (PolicyParsingException ppe){
605  0 throw ppe; // don't embed the PPE.
606    }catch (Throwable th){
607    // could be a class cast exception, for example
608  0 throw new PolicyParsingException("Parse error", th);
609    }
610    }
611   
612   
613    /*
614    * POLICY FUNCTIONS
615    */
616   
617    /**
618    * Returns the role with the given value from the RoleHierarchy.
619    *
620    * @param roleType - the type of the role, as defined in the
621    * RoleHierarchyPolicy; if there is no RoleSpec with this type, null is
622    * returned
623    * @param roleValue - the value of the role of the given type, as defined
624    * in the RoleSpec defining the role hierarchy of the given type
625    *
626    * @return RoleHierarchyNode representing the role, or null, if there is
627    * no such type defined in the policy, or no such value for the given
628    * type
629    */
 
630  89 toggle public RoleHierarchyNode getRole(String roleType, String roleValue){
631  89 RoleSpecNode rsn = roleHierarchyPolicy.getByType(roleType);
632  89 return rsn==null?null:rsn.getRole(roleValue);
633    }
634   
635   
636    /**
637    * This method returns a Map of Target Access Rules, indexed by action name.
638    * There are other entries as well, as explained in TargetAccessPolicyNode
639    * documentation.
640    *
641    * @return Map of Target Access Rules
642    */
 
643  24 toggle public java.util.Map getAccessRules(){
644    //System.out.println("target access policy: "+targetAccessPolicy);//****
645  24 return targetAccessPolicy.getRules();
646    }
647   
648    /**
649    * This method returns the set of delegation and assignment rules, as
650    * specified by RoleHierarchyPolicy.
651    *
652    * @see AssignmentRule
653    */
 
654  25 toggle public java.util.Map getAssignmentRules(){
655  25 return delegationPolicy.getRules();
656    }
657   
658    /**
659    * This method returns a Role Hierarchy Policy as the only rule. The key in
660    * the map is
661    * issrg.pba.rbac.RoleHierarchyPolicy.class, and the object is the
662    * RoleHierarchyPolicy. These rules are used by AuthTokenParsers to extract
663    * valid roles from Authorisation Tokens.
664    */
 
665  28 toggle public java.util.Map getAuthTokenParsingRules(){
666  28 java.util.Map h = new java.util.Hashtable();
667  28 h.put(issrg.pba.rbac.RoleHierarchyPolicy.class, roleHierarchyPolicy);
668  28 return h;
669    }
670   
671    /**
672    * This method returns the ID of the parsed Policy.
673    *
674    * @return the String identifier of the policy (the string representation of
675    * the OID in the dotted form for PERMIS XML policies)
676    */
 
677  14 toggle public String getPolicyID(){
678  14 return pmiXMLPolicy.getOID();
679    }
680   
681    /**
682    * This method returns the URLs of the repositories specified in the
683    * RepositoryPolicy.
684    *
685    * @return array of Strings, each being a non-null URL; may return an empty
686    * array or null, if no repositories are defined in the policy
687    */
 
688  25 toggle public String [] getRepositoryURLs(){
689  25 if (repositoryPolicy==null) return null;
690   
691  2 return repositoryPolicy.getURLs();
692    }
693   
694    /**
695    * This method returns the domain covering all the allowed subjects. This
696    * is a union of all Subject Domains declared in the policy.
697    *
698    * @return Subtree that is a union of all Subject Domains.
699    */
 
700  0 toggle public Subtree getSubjectDomains() {
701  0 return subjectPolicy.getCoverageDomain();
702    }
703   
704    /**
705    *This method returns the SOA policy of the current XML policy
706    *@return the soa policy
707    */
708   
 
709  1 toggle public java.util.Map getSOAs() {
710  1 return soaPolicy.getSOAs();
711    }
712   
713   
714   
715    /*
716    * POLICY XML NODE CLASSES
717    */
718   
719   
720    /**
721    * The class representing an ActionPolicy XML node. It holds a collection of
722    * action definitions, indexed by the action name. The definitions include
723    * parameter names and order, and the return type name.
724    *
725    * @see #getActionDefinition(String)
726    * @author A Otenko
727    * @version 1.0
728    */
729   
 
730    public class ActionPolicyNode extends PolicyXMLNode{
731    /**
732    * This is the string, containing all the delimiter characters between
733    * arguments in NMTOKENS.
734    */
735    public final static String ARGS_SEPARATORS = ",";
736   
737    /**
738    * This is the storage of the defined actions
739    */
740    private java.util.Map actions = new java.util.Hashtable();
741   
742    /**
743    * This is the storage of targets an action applies to
744    */
745    private java.util.Map targets = new java.util.Hashtable();
746   
747    /**
748    * This is the default constructor used by the XMLPolicyParser.
749    */
 
750  25 toggle public ActionPolicyNode(Attributes attrs) {
751  25 super(XMLTags.ACTION_POLICY_NODE, attrs);
752   
753  25 actionPolicy = this;
754    }
755   
756    /**
757    * This method gets information from the child nodes and sticks them in
758    * the
759    * actions map. The definitions are created as specified in <code>{@link
760    * #getActionDefinition(String) getActionDefinition}</code>
761    */
 
762  25 toggle public void construct(){
763    /**
764    * TODO: treat no children case
765    */
766  134 for (int i=children.size(); i-->0;){
767  109 PolicyXMLNode c = (PolicyXMLNode)children.get(i);
768  109 if (c.getName().intern()!=XMLTags.ACTION_NODE){
769    /**
770    * TODO: signal a syntax error
771    */
772    }
773   
774  109 java.util.Map m = c.getAttributes();
775  109 String n = (String)m.get(XMLTags.NAME_ATTRIBUTE);
776  109 String ret = (String)m.get(XMLTags.RETURN_TYPE_ATTRIBUTE);
777   
778  109 String args = (String)m.get(XMLTags.ARGS_ATTRIBUTE);
779  109 String [] def = new String [] {ret};
780  109 if (args!=null){
781  68 java.util.Vector v = split(args);
782  68 def = new String[1+v.size()];
783  68 def[0]=ret;
784   
785  68 if (def.length>1){
786  13 System.arraycopy(v.toArray(), 0, def, 1, def.length-1);
787    }
788    }
789   
790  109 actions.put(n, def);
791   
792  109 String targetAttribute = (String)m.get(XMLTags.TARGET_ATTRIBUTE);
793  109 if(targetAttribute != null)
794    {
795  1 java.util.Vector targetVector = split(targetAttribute);
796  1 String[] tars = new String[targetVector.size()];
797  1 System.arraycopy(targetVector.toArray(), 0, tars, 0, targetVector.size());
798  1 targets.put(n, tars);
799    }
800    }
801    }
802   
803    /**
804    * Returns the action definition as an array of strings. Can be null,
805    * if no
806    * such method has been defined. The definition is as follows: the 0-th
807    * element
808    * is the return type name, or null, if no return type has been
809    * specified; the
810    * rest of the array elements name the parameters in the order they
811    * appeared
812    * in the XML.
813    *
814    * TODO: check for duplicate parameter identifiers, when constructing?
815    *
816    * @param name - the action name
817    *
818    * @return an array of String, where the 0-th element is the return type
819    * and the others are types of the action parameters
820    */
 
821  1250 toggle public String [] getActionDefinition(String name){
822  1250 return (String [])actions.get(name);
823    }
824   
825    /**
826    * Returns an array of String of the targets this action applies to.
827    *
828    * @param name - the action name
829    *
830    * @return an array of String target names
831    */
 
832  197 toggle public String[] getApplyToTargets(String name)
833    {
834  197 return (String [])targets.get(name);
835    }
836   
837    /**
838    * This method just splits an NMTOKENS string into a Vector of strings.
839    *
840    * @param args - a comma- and/or space-separated list of arguments
841    *
842    * @return Vector of arguments; each element is a String
843    */
 
844  69 toggle private java.util.Vector split(String args){
845  69 java.util.Vector v = new java.util.Vector();
846   
847  69 if (args!=null){
848  69 java.util.Enumeration st = new java.util.StringTokenizer(args, ARGS_SEPARATORS);
849   
850  85 while (st.hasMoreElements()){
851  16 v.add(st.nextElement());
852    }
853    }
854   
855  69 return v;
856    }
857    }
858   
859   
860    /**
861    * This class represents the object that can store many Subject or Target
862    * Domain specifications. As part of its operation it also constructs a
863    * collective domain of all Subjects or all Targets, so that it will be easy
864    * to determine whether an arbitrary entity is part of any domain declared
865    * in the policy.
866    *
867    * @author A Otenko
868    * @version 1.0
869    */
 
870    public class DomainPolicyNode extends PolicyXMLNode{
871   
872    /**
873    * This is the end of the name of a Policy XML node.
874    */
875    public final static String NODE_NAME = "Policy";
876   
877    protected java.util.Map domains;
878    protected issrg.pba.rbac.policies.Subtree coverageDomain;
879   
880    /**
881    * This constructor builds a DomainPolicyNode given the prefix of
882    * nodes to look for ("Subject" or "Target") and the set of attributes.
883    *
884    * @param prefix - the prefix to use before "Policy"; meaningful values
885    * are "Subject" and "Target"
886    * @param attrs - the attributes of the XML element
887    */
 
888  50 toggle public DomainPolicyNode(String prefix, Attributes attrs) {
889  50 super(prefix+NODE_NAME, attrs);
890    }
891   
892    /**
893    * This method constructs a table of domains indexed by their ID and an
894    * aggregated domain that is a union of all domains. The latter is used
895    * to see if a particular entity matches any of the domains in the
896    * policy (to tell if the policy is applicable at all).
897    */
 
898  50 toggle public void construct(){
899    /**
900    * TODO: if a ClassCast exception is thrown,then a Syntax error must have
901    * occurred
902    */
903  50 DomainSpecNode [] s = new DomainSpecNode[children.size()];
904  50 System.arraycopy(children.toArray(), 0, s, 0, s.length);
905   
906  50 domains = new java.util.Hashtable();
907  50 java.util.Vector coverage = new java.util.Vector();
908   
909    //System.out.println("\t\t*** BUILDING A DOMAIN POLICY ***"); //*******
910  166 for (int i=0; i<s.length; i++){
911    //System.out.println("\t"+s[i].getID()+" "+s[i].getSubtree()); //*******
912  116 domains.put(s[i].getID(), s[i].getSubtree());
913  116 coverage.add(s[i].getSubtree());
914    }
915   
916  50 coverageDomain = new issrg.pba.rbac.policies.ComplexSubtree(coverage, null);
917   
918    //System.out.println("\t***"+domains); //*******
919    }
920   
921    /**
922    * Returns the given domain; can be null, if no such domain has been
923    * specified.
924    *
925    * @param id is the domain id
926    *
927    * @return the Subtree object with this ID; can be null, if no such
928    * domain has been defined
929    */
 
930  233 toggle public issrg.pba.rbac.policies.Subtree getDomain(String id){
931    //System.out.println("\t*** getting domain: "+id); //*******
932  233 return (issrg.pba.rbac.policies.Subtree)domains.get(id);
933    }
934   
935    /**
936    * Returns the domain covering all domains declared in this policy.
937    * Subject and Target domains are treated separately, so there are
938    * two coverage domains available: one for Subjects, one for Targets
939    * (query the corresponding policies).
940    */
 
941  1384 toggle public issrg.pba.rbac.policies.Subtree getCoverageDomain(){
942  1384 return coverageDomain;
943    }
944   
945    }
946   
947    /**
948    * This is a simple extension of DomainPolicyNode that makes sure that
949    * SubjectPolicy is constructed correctly. When an instance of this object
950    * is created, subjectPolicy is set in XMLPolicyParser.
951    */
 
952    public class SubjectDomainPolicyNode extends DomainPolicyNode{
 
953  25 toggle public SubjectDomainPolicyNode(Attributes attrs){
954  25 super(XMLTags.SUBJECT_PREFIX, attrs);
955  25 subjectPolicy = this;
956    }
957    }
958   
959   
960    /**
961    * This is a simple extension of DomainPolicyNode that makes sure that
962    * TargetPolicy is constructed correctly. When an instance of this object
963    * is created, targetPolicy is set in XMLPolicyParser.
964    */
 
965    public class TargetDomainPolicyNode extends DomainPolicyNode{
 
966  25 toggle public TargetDomainPolicyNode(Attributes attrs){
967  25 super(XMLTags.TARGET_PREFIX, attrs);
968  25 targetPolicy = this;
969    }
970    }
971   
972    /**
973    * This class represents the abstract DomainSpec, of which there are two
974    * extensions: SubjectDomainSpec and TargetDomainSpec.
975    * It simply creates a ComplexSubtree object and gives it a name.
976    *
977    * @author A Otenko
978    * @version 1.0
979    */
 
980    public class DomainSpecNode extends PolicyXMLNode {
981   
982    /**
983    * This is the end of the name of the DomainSpec node.
984    */
985    public static final String NODE_NAME = "DomainSpec";
986   
987    private String domainID;
988   
989    private issrg.pba.rbac.policies.Subtree subTree;
990   
991    /**
992    * This variable says whether or not the Object Class statements should
993    * follow.
994    */
995    private boolean expectObjClasses;
996   
997    /**
998    * This constructor builds a DomainSpecNode, given the prefix in the
999    * node name ("Subject" or "Target"), the flag whether Object Classes
1000    * should be expected, and the other attributes of the XML element.
1001    *
1002    * @param prefix - the prefix of the DomainSpec XML elements; the only
1003    * meaningful values are "Subject" and "Target", but this is not
1004    * checked
1005    * @param objClass - the flag indicating whether ObjectClass elements
1006    * are allowed in this DomainSpec; if true, they are allowed;
1007    * otherwise a signal error is signaled, when such elements are
1008    * encountered in XML
1009    * @param attrs - the attributes of the XML element
1010    */
 
1011  116 toggle public DomainSpecNode(String prefix, boolean objClass, Attributes attrs) {
1012  116 super(prefix+NODE_NAME, attrs);
1013   
1014  116 expectObjClasses = objClass;
1015    }
1016   
1017    /**
1018    * This method uses gatherSubtrees method to construct a ComplexSubtree
1019    * representing the Domain Specification.
1020    */
 
1021  116 toggle public void construct() throws PolicyParsingException{
1022  116 try{
1023  116 subTree = new issrg.pba.rbac.policies.ComplexSubtree(gatherSubtrees(children, true), null);
1024  116 domainID = (String)this.attributes.get(XMLTags.ID_ATTRIBUTE);
1025    //System.out.println("\t"+attributes); //*******
1026   
1027    }catch(issrg.utils.RFC2253ParsingException rpe){
1028  0 throw new PolicyParsingException(rpe.getMessage(), rpe);
1029    }catch(BadURLException bue){
1030  0 throw new PolicyParsingException(bue.getMessage(), bue);
1031    }catch(java.lang.NumberFormatException nfe){
1032  0 throw new PolicyParsingException("Error parsing integer", nfe);
1033    }
1034    }
1035   
1036    /**
1037    * This method gathers all subtrees defined by the vector of nodes.
1038    * It supports both nested Excludes and sequences of Include and
1039    * Exclude nodes.
1040    * As the result, the following construct is supported:
1041    * &lt;Include ...>&lt;Exclude .../>..&lt;/Include>&lt;Exclude .../>,
1042    * where both Excludes are excluded from the same Include. The nested
1043    * Excludes is the preferred method, whilst the other is kept for
1044    * historic reasons.
1045    *
1046    * @param children the Vector of Include and Exclude nodes
1047    * @param includes the boolean value telling whether Includes should be
1048    * expected; if true, it is the first level of nodes and Includes
1049    * are allowed (as well as the Excludes); otherwise, it is the second
1050    * level of nodes (inside the Includes) and Includes are not allowed
1051    * (whilst the Excludes are still allowed)
1052    */
 
1053  118 toggle protected java.util.Vector gatherSubtrees(java.util.Vector children, boolean includes) throws PolicyParsingException, issrg.utils.RFC2253ParsingException, BadURLException {
1054  118 java.util.Vector subtrees = new java.util.Vector();
1055   
1056  118 java.util.Vector excl = includes?new java.util.Vector():subtrees; // if includes are not expected, collect the excludes into the subtrees - that's what should be returned
1057  118 java.util.Vector classes = null;
1058  118 int i=children.size();
1059  118 boolean objClasses = includes && expectObjClasses; //true; only if includes is true, i.e. it is the first level of nodes, objClasses can be expected
1060   
1061    //System.out.println("\t\t*** BUILDING A DOMAIN SPEC ***"); //*******
1062  303 while(i-->0){ // start from tail - gather ObjectClasses first
1063  185 PolicyXMLNode child = (PolicyXMLNode)children.get(i);
1064  185 String s = child.getName().intern();
1065    // the attributes are collected without checking the name
1066    // of the XML element - that's fine, they can be null
1067  185 String minmax = (String)child.getAttributes().get(XMLTags.MIN_ATTRIBUTE);
1068  185 int min=minmax==null?0:Integer.parseInt(minmax);
1069   
1070  185 minmax = (String)child.getAttributes().get(XMLTags.MAX_ATTRIBUTE);
1071  185 int max=minmax==null?-1:Integer.parseInt(minmax);
1072   
1073    //System.out.println("\t"+s); //*******
1074   
1075  185 String dn = (String)child.getAttributes().get(XMLTags.LDAPDN_ATTRIBUTE);
1076  185 String url = (String)child.getAttributes().get(XMLTags.URL_ATTRIBUTE);
1077   
1078  185 if (dn!=null && url!=null){
1079  0 throw new PolicyParsingException("Invalid subtree specification: cannot have "+XMLTags.LDAPDN_ATTRIBUTE+" and "+XMLTags.URL_ATTRIBUTE+" attributes at the same time.");
1080    }
1081   
1082  185 if (dn==null && url==null){ // if both were not specified, imply "world" LDAPDN (DN="")
1083  1 dn="";
1084    }
1085   
1086  185 Subtree sub=null;
1087   
1088  185 objClasses &= s==XMLTags.OBJECT_CLASS_NODE; // as soon as no more ObjectClasses are there, let no more appear
1089   
1090  185 if (s==XMLTags.INCLUDE_NODE){
1091  0 if (!includes) throw new PolicyParsingException(s+" nodes cannot be nested"); // !includes => second level of nodes, inside an Include
1092   
1093    //System.out.println("\t\tchildren: "+child.getChildren()); //*********
1094  172 if (child.getChildren().size()!=0){ // if include node has children, all of them should be Exclude nodes - add them all to the list of already collected Exclude nodes
1095  2 excl.addAll(0, gatherSubtrees(child.getChildren(), false));
1096    }
1097   
1098  172 Subtree [] exclude = (Subtree[])excl.toArray(new Subtree[0]);
1099  172 excl = new java.util.Vector(); // reset the list of Excludes once it has been used
1100   
1101  172 if (dn==null){ // URL is not null then! if dn==null and url==null, then dn="";
1102    //System.out.print("\t\t\turl: "+url); //*********
1103  42 sub=issrg.pba.rbac.URLHandler.getSubtreeByURL(url, min, max, exclude);
1104    }else{
1105  130 sub=new DITSubtree(new LDAPDNPrincipal(dn), min, max, classes==null?null:(String[])classes.toArray(new String[0]), exclude);
1106    }
1107   
1108    //System.out.println("\tsubtree: "+sub); //*********
1109    // this should never happen - just a sanity check
1110  0 if (sub==null) throw new PolicyParsingException("Invalid subtree specification: DN="+dn+", URL="+url);
1111   
1112    // adding from before, so the array will look as a copy of the actual
1113    // XML: note, that the XML child nodes are passed in the reverse order
1114   
1115  172 subtrees.add(0, sub);
1116  13 }else if (s==XMLTags.EXCLUDE_NODE){
1117  12 if (dn==null){ // URL is not null then! if dn==null and url==null, then dn="";
1118  2 sub=issrg.pba.rbac.URLHandler.getSubtreeByURL(url, min, max, null);
1119    }else{
1120  10 sub=new DITSubtree(new LDAPDNPrincipal(dn), min, max, null, null);
1121    }
1122   
1123    // this should never happen - just a sanity check
1124  0 if (sub==null) throw new PolicyParsingException("Invalid subtree specification: DN="+dn+", URL="+url);
1125   
1126  12 excl.add(0, sub);
1127  1 }else if (objClasses){// && s==OBJECT_CLASS_NODE){ -- this comparison is superficial, when objClasses is already tracking this
1128  1 if (classes==null){
1129  1 classes = new java.util.Vector();
1130    }
1131   
1132  1 s=(String)child.getAttributes().get(XMLTags.NAME_ATTRIBUTE);
1133  1 if (s==null){
1134  0 throw new PolicyParsingException(XMLTags.NAME_ATTRIBUTE+" is required, but not found");
1135    }
1136  1 classes.add(s);
1137    }else{
1138  0 throw new PolicyParsingException(s+" node was found, but was not expected");
1139    }
1140    }
1141    // TODO: check that includes==true and excl.size()==0? i.e. unused Excludes were found - they should never go before Includes?
1142    // and complain?
1143   
1144  118 return subtrees;
1145    }
1146   
1147    /**
1148    * Returns the ID of the Domain.
1149    */
 
1150  116 toggle public String getID(){
1151  116 return domainID;
1152    }
1153   
1154    /**
1155    * Returns the Subtree of this Domain specification.
1156    */
 
1157  232 toggle public Subtree getSubtree(){
1158  232 return subTree;
1159    }
1160   
1161    }
1162   
1163    /**
1164    * This is a simple extension of DomainSpecNode that makes sure that only
1165    * SubjectDomainSpecs are interpreted, and no ObjectClasses are allowed.
1166    */
 
1167    public class SubjectDomainSpecNode extends DomainSpecNode{
 
1168  50 toggle public SubjectDomainSpecNode(Attributes attrs){
1169  50 super(XMLTags.SUBJECT_PREFIX, false, attrs);
1170    }
1171    }
1172   
1173    /**
1174    * This is a simple extension of DomainSpecNode that makes sure that only
1175    * TargetDomainSpecs are interpreted, and ObjectClasses are allowed.
1176    */
 
1177    public class TargetDomainSpecNode extends DomainSpecNode{
 
1178  66 toggle public TargetDomainSpecNode(Attributes attrs){
1179  66 super(XMLTags.TARGET_PREFIX, true, attrs);
1180    }
1181    }
1182   
1183    /**
1184    * This node implements the RoleAssignmentPolicy XML node. It is intelligent
1185    * enough to walk through its children and retrieve all the information to
1186    * build an index of AssignmentRule vectors by SOA DNs.
1187    *
1188    * @author A Otenko
1189    * @version 1.0
1190    */
 
1191    public class RoleAssignmentPolicyNode extends PolicyXMLNode{
1192    /**
1193    * These numbers are the position of the nodes under the RoleAssignment node.
1194    */
1195    public static final int SUBJECT_DOMAIN_NODE_SEQUENCE = 0;
1196    public static final int ROLE_LIST_NODE_SEQUENCE = 1;
1197    public static final int DELEGATE_NODE_SEQUENCE = 2;
1198    public static final int SOA_NODE_SEQUENCE = 3;
1199    public static final int VALIDITY_NODE_SEQUENCE = 4;
1200   
1201    public static final int ABSOLUTE_VALIDITY_NODE_SEQUENCE = 0;
1202    public static final int AGE_VALIDITY_NODE_SEQUENCE = 1;
1203    public static final int MAXIMUM_VALIDITY_NODE_SEQUENCE = 2;
1204    public static final int MINIMUM_VALIDITY_NODE_SEQUENCE = 3;
1205   
1206    /**
1207    * Temporary storage for different policies.
1208    */
1209    private DomainPolicyNode subjectPol;
1210    private SOAPolicyNode soas;
1211   
1212    /**
1213    * This is where the final rules are stored, indexed by SOA DN.
1214    */
1215    protected java.util.Map rules;
1216   
1217    /**
1218    * This constructor builds a RoleAssingmentPolicyNode, given the
1219    * attributes of the XML element. It uses the Subject Policy and
1220    * SOA Policy constructed by XMLPolicyParser, so these must already be
1221    * known at the time of constructing the object.
1222    *
1223    * @param attrs - the attributes of this XML element
1224    */
 
1225  25 toggle public RoleAssignmentPolicyNode(Attributes attrs){
1226  25 this(subjectPolicy, soaPolicy, attrs);
1227    }
1228   
1229    /**
1230    * This constructor builds the object from explicitly specified
1231    * Subject Policy, SOA Policy and the attributes of the XML element.
1232    *
1233    * @param subjectPolicy - the Subject Policy to be used
1234    * @param soaPolicy - the SOA Policy to be used
1235    * @param attrs - the attributes of this XML element
1236    */
 
1237  25 toggle public RoleAssignmentPolicyNode(DomainPolicyNode subjectPolicy,
1238    SOAPolicyNode soaPolicy, Attributes attrs) {
1239  25 super(XMLTags.ROLE_ASSIGNMENT_POLICY_NODE, attrs);
1240   
1241  25 this.subjectPol = subjectPolicy;
1242  25 soas = soaPolicy;
1243  25 delegationPolicy = this;
1244    }
1245   
1246    /**
1247    * This method finishes the construction of the Role Assignment Policy.
1248    * During this process it checks that the right XML statements appear
1249    * in the policy and in the correct sequence. It checks that the SOA
1250    * and the Subject domain with the specified IDs have been declared in
1251    * the corresponding policies.
1252    */
 
1253  25 toggle public void construct() throws PolicyParsingException{
1254  25 rules = new java.util.Hashtable();
1255   
1256  25 rules.put(issrg.pba.rbac.policies.Subtree.class, subjectPol.getCoverageDomain());
1257   
1258    //System.out.println("\t\t*** BUILDING ROLE ASSIGNMENT POLICY ***"); //********
1259  77 for (int i=children.size(); i-->0; ){
1260  52 PolicyXMLNode c = (PolicyXMLNode)children.get(i);
1261  52 String s = c.getName().intern();
1262  52 if (s!=XMLTags.ROLE_ASSIGNMENT_NODE){
1263  0 throw new PolicyParsingException("Only "+XMLTags.ROLE_ASSIGNMENT_NODE+" nodes are allowed under this node");
1264    }
1265   
1266  52 java.util.Vector v = c.getChildren();
1267    //System.out.println("\t"+i+": "+c.getName()+" children:"+v.size()); //********
1268   
1269  52 String subjId = (String)expect(v, SUBJECT_DOMAIN_NODE_SEQUENCE, XMLTags.SUBJECT_DOMAIN_NODE).getAttributes().get(XMLTags.ID_ATTRIBUTE);
1270    //System.out.print("subjId: "+subjId); //********
1271   
1272  52 RoleListNode roleList = (RoleListNode)expect(v, ROLE_LIST_NODE_SEQUENCE, XMLTags.ROLE_LIST_NODE);
1273   
1274  52 String delegationDepth = (String)expect(v, DELEGATE_NODE_SEQUENCE, XMLTags.DELEGATE_NODE).getAttributes().get(XMLTags.DEPTH_ATTRIBUTE);
1275    //System.out.print(" delegationDepth: "+delegationDepth); //********
1276  52 int delegation;
1277   
1278  52 try{
1279  52 delegation=delegationDepth==null? -1 : Integer.parseInt(delegationDepth);
1280  0 if (delegation<-1) throw new NumberFormatException();
1281    }catch(java.lang.NumberFormatException ex){
1282  0 throw new PolicyParsingException("Delegation Depth should be a valid non-negative integer number, or be missing", ex);
1283    }
1284   
1285   
1286  52 String soaId = (String)expect(v, SOA_NODE_SEQUENCE, XMLTags.SOA_NODE).getAttributes().get(XMLTags.ID_ATTRIBUTE);
1287    //System.out.print(" soaId: "+soaId); //********
1288   
1289  52 Vector validity = expect(v, VALIDITY_NODE_SEQUENCE, XMLTags.VALIDITY_NODE).getChildren();
1290   
1291  52 validityForRoleList = new issrg.pba.rbac.AnyTimeValidityPeriod(); // the default validity period
1292  52 int missingnodes=0;
1293  52 PolicyXMLNode val_node = expect(validity, ABSOLUTE_VALIDITY_NODE_SEQUENCE, XMLTags.ABSOLUTE_NODE, true);
1294  52 issrg.pba.rbac.RelativeDate rd;
1295   
1296  52 if (val_node==null){
1297  33 missingnodes++;
1298    }else{
1299  19 java.util.Date nb = null;
1300  19 java.util.Date na = null;
1301  19 s = (String)val_node.getAttributes().get(XMLTags.START_ATTRIBUTE);
1302  19 if (s!=null && s.intern()!=""){
1303  19 rd = parseDateTime(s);
1304  19 rd.months--;
1305  19 nb = rd.getDate();
1306    }
1307   
1308  19 s = (String)val_node.getAttributes().get(XMLTags.END_ATTRIBUTE);
1309  19 if (s!=null && s.intern()!=""){
1310  19 rd = parseDateTime(s);
1311  19 rd.months--;
1312  19 na = rd.getDate();
1313    }
1314   
1315  19 validityForRoleList=new issrg.pba.rbac.AbsoluteValidityPeriod(nb, na);
1316    }
1317   
1318  52 issrg.pba.rbac.RelativeDate age=null;
1319  52 issrg.pba.rbac.RelativeDate min=null;
1320  52 issrg.pba.rbac.RelativeDate max=null;
1321   
1322  52 val_node = expect(validity, AGE_VALIDITY_NODE_SEQUENCE-missingnodes, XMLTags.AGE_NODE, true);
1323  52 if (val_node==null){
1324  50 missingnodes++;
1325    }else{
1326  2 s = (String)val_node.getAttributes().get(XMLTags.TIME_ATTRIBUTE);
1327  2 if (s==null){
1328  0 throw new PolicyParsingException(XMLTags.TIME_ATTRIBUTE+" attribute is missing in "+XMLTags.AGE_NODE);
1329    }
1330   
1331  2 age=parseDateTime(s);
1332    }
1333   
1334  52 val_node = expect(validity, MAXIMUM_VALIDITY_NODE_SEQUENCE-missingnodes, XMLTags.MAXIMUM_NODE, true);
1335  52 if (val_node==null){
1336  50 missingnodes++;
1337    }else{
1338  2 s = (String)val_node.getAttributes().get(XMLTags.TIME_ATTRIBUTE);
1339  2 if (s==null){
1340  0 throw new PolicyParsingException(XMLTags.TIME_ATTRIBUTE+" attribute is missing in "+XMLTags.MAXIMUM_NODE);
1341    }
1342   
1343  2 max=parseDateTime(s);
1344    }
1345   
1346  52 val_node = expect(validity, MINIMUM_VALIDITY_NODE_SEQUENCE-missingnodes, XMLTags.MINIMUM_NODE, true);
1347  52 if (val_node==null){
1348  51 missingnodes++;
1349    }else{
1350  1 s = (String)val_node.getAttributes().get(XMLTags.TIME_ATTRIBUTE);
1351  1 if (s==null){
1352  0 throw new PolicyParsingException(XMLTags.TIME_ATTRIBUTE+" attribute is missing in "+XMLTags.MINIMUM_NODE);
1353    }
1354   
1355  1 min=parseDateTime(s);
1356    }
1357   
1358  52 if (age!=null || min!=null || max!=null){
1359  5 validityForRoleList = new issrg.pba.rbac.AdjustedPeriodCollection(
1360    validityForRoleList,
1361    new issrg.pba.rbac.AdjustedValidityPeriod(age, min, max)
1362    );
1363    }
1364   
1365  52 roleList.construct(); // this is a bit clumsy - the roleList has already constructed the list of roles
1366    // but the Validity could not be defined properly at that time
1367    // so I have to call construct again. this is only due to the syntax of the policy (that the nodes appear in this sequence)
1368  52 issrg.pba.Credentials soaCreds = roleList.getCredential();
1369    //System.out.print(" soaCreds: "+soaCreds); //********
1370   
1371  52 java.security.Principal soa = soas.getSOA(soaId);
1372    //System.out.println("\nsoa: "+soa); //********
1373  52 if (soa==null){
1374  0 throw new PolicyParsingException("No SOA with "+soaId+" has been defined");
1375    }
1376   
1377    //System.out.print("getting subject domain:..."); //********
1378  52 Subtree subj = subjectPol.getDomain(subjId);
1379    //System.out.println("ok : "+subj); //********
1380  52 if (subj==null){
1381  0 throw new PolicyParsingException("No Subject Domain with "+subjId+" has been defined");
1382    }
1383   
1384  52 java.util.Vector v2 = (java.util.Vector)rules.get(soa.getName());
1385  52 if (v2==null){ // a rule for a new SOA
1386  40 v2 = new java.util.Vector();
1387  40 rules.put(soa.getName(), v2);
1388    }
1389   
1390    //System.out.println("creating an assignment rule:..."); //********
1391  52 v2.add(new issrg.pba.rbac.policies.AssignmentRule(subj, delegation, soaCreds));
1392    //System.out.println("ok"); //********
1393    }
1394    }
1395   
1396    /**
1397    * This method returns the rules defined by the appropriate XML node.
1398    * The rules contain Vectors of issrg.pba.rbac.policies.AssignmentRule
1399    * objects, indexed by the SOA name. There also is a special entry
1400    * with the key issrg.pba.rbac.policies.Subtree.class: its value is
1401    * a issrg.pba.rbac.policies.Subtree of the coverage domain of the
1402    * Subject Policy.
1403    */
 
1404  25 toggle public java.util.Map getRules(){
1405  25 return rules;
1406    }
1407   
1408    /**
1409    * This routine parses the string in format ccyy-mm-ddThh:mm:ss and
1410    * separates it into
1411    * the integers. The syntax is not strict, so any nymber of subsequent
1412    * digits is allowed,
1413    * and any non-digit characters can be used as separators (the parser
1414    * does not ensure the
1415    * separators are "-", "T", ":", and that they are used in that order).
1416    *
1417    * <p>Examples:
1418    * <p>"00000002~73|1" is parsed as year 2, month 73, day 1. Note that
1419    * the actual meaning
1420    * depends on where this statement is used. If it is the Absolute date
1421    * specification, then
1422    * it is equal to "8-1-1" (73 months is the same as 6 more years and 1
1423    * month).
1424    * <p>"2002-12-31T12:00:21:567" - the last term ":567" is ignored.
1425    *
1426    * @param s is the string of format "ccyy-mm-ddThh:mm:ss" to parse
1427    *
1428    * @return a RelativeDate object with appropriate integers assigned
1429    */
 
1430  43 toggle protected issrg.pba.rbac.RelativeDate parseDateTime(String s){
1431  43 int [] d = new issrg.pba.rbac.Time(s).getEvaluationTime(); // use the existing parser
1432   
1433  43 return new issrg.pba.rbac.RelativeDate(d[0], d[1], d[2], d[3], d[4], d[5]);
1434    }
1435    }
1436   
1437   
1438   
1439   
1440   
1441    /**
1442    * This is the class representing SupRole nodes. It knows its value and its
1443    * direct subordinates. However, it can always tell you whether a given Role
1444    * is subordinate to it or not.
1445    *
1446    * @author A Otenko
1447    * @version 1.0
1448    */
 
1449    public class RoleHierarchyNode extends PolicyXMLNode implements issrg.pba.rbac.RoleHierarchyNode {
1450    /**
1451    * This is a number, representing how high in the hierarchy this node is
1452    * located. It helps to optimise calculations of who is superior to who.
1453    *
1454    * <p>Its property is that hierarchy level of the most superior roles is
1455    * 0,
1456    * and that any child role hierarchy level is a bigger integer (not
1457    * always
1458    * greater just by one, because this is not a tree). So if this role
1459    * has bigger integer than another, then the former definitely cannot be
1460    * superior to the latter.
1461    */
1462    protected int hierarchyLevel = -1;
1463   
1464    protected String type;
1465    protected String value;
1466   
1467    protected RoleHierarchyNode [] subordinates=null;
1468   
1469    /**
1470    * This is a flag that indicates how many loops include this node. There
1471    * always
1472    * should be zero loops.
1473    */
1474    private int loops = 0;
1475   
 
1476  101 toggle public RoleHierarchyNode(org.xml.sax.Attributes attrs) {
1477  101 super(XMLTags.SUP_ROLE_NODE, attrs);
1478   
1479  101 _init_();
1480    }
1481   
 
1482  101 toggle private void _init_(){
1483  101 value = attrs.getValue(XMLTags.VALUE_ATTRIBUTE);
1484    }
1485   
1486    /**
1487    * This method links the roles together, using the given Map as a
1488    * reference to
1489    * other Roles. Before calling this method, it is useless to call
1490    * getLevel or
1491    * isSuperiorTo, as they will not be able to determine hierarchical
1492    * relationships between two roles.
1493    *
1494    * @param roleHierarchy - the Map of roles, where the key is the role
1495    * value, and the value is the RoleHierarchyNode
1496    */
 
1497  101 toggle public void optimise(java.util.Map roleHierarchy) throws PolicyParsingException{
1498  101 try{
1499  101 if (subordinates!=null){ // optimised already
1500  0 return;
1501    }
1502   
1503  101 Object [] childs = children.toArray();
1504  101 subordinates = new RoleHierarchyNode[childs.length];
1505   
1506  149 for (int i=0; i<childs.length; i++){
1507  48 String s = (String)(((PolicyXMLNode)childs[i]).getAttributes().get(XMLTags.VALUE_ATTRIBUTE));
1508   
1509  48 RoleHierarchyNode sub = (RoleHierarchyNode)roleHierarchy.get(s);
1510   
1511  48 if (sub==null){
1512  0 throw new PolicyParsingException("Could not find Role "+s+" in this hierarchy");
1513    }
1514   
1515  48 subordinates[i]=sub;
1516  48 sub.setLevel(getLevel()+1); // not the suggested level, but the one,
1517    // that is set now
1518    }
1519    }catch(Throwable th){
1520  0 throw new PolicyParsingException(th.getMessage());
1521    }
1522   
1523  101 if (loops!=0){
1524  0 throw new PolicyParsingException("Role Hierarchy directed graph contains loops");
1525    }
1526    }
1527   
1528    /**
1529    * This method returns the hierarchy level of the node.
1530    */
 
1531  24231 toggle public int getLevel(){
1532  24231 return hierarchyLevel;
1533    }
1534   
1535    /**
1536    * This method sets the hierarchy level of the node. It is set only if
1537    * the
1538    * given level is greater (lower position) than the current. It also
1539    * updates
1540    * the counter of loops in the hierarchy that appeared by adding this
1541    * node.
1542    * Note that the latter counter depends on the sequence of updating the
1543    * hierarchy.
1544    *
1545    * @param level - the least new level of the node; if the node already
1546    * has a higher level, the level won't be updated; otherwise its
1547    * level and the level of all of its subordinates will be updated
1548    */
 
1549  113 toggle public void setLevel(int level){
1550  113 loops++; // update always; it will be restored to zero, if no loops encountered
1551  113 if (loops!=1){
1552  0 return;
1553    }
1554   
1555  113 if (level>=getLevel()){
1556    // updating ok: no loops encountered
1557  108 hierarchyLevel = level;
1558  108 if (subordinates!=null)
1559  173 for(int i=0; i<subordinates.length; i++){
1560  65 subordinates[i].setLevel(level+1);
1561    }
1562    }
1563  113 loops--;
1564    }
1565   
1566    /**
1567    * This method returns the Role Value as String.
1568    */
 
1569  45595 toggle public String getValue(){
1570  45595 return value;
1571    }
1572   
1573    /**
1574    * This method returns the Role Value as Object (required by
1575    * issrg.pba.rbac.Role interface).
1576    */
 
1577  17244 toggle public Object getRoleValue(){
1578  17244 return getValue();
1579    }
1580   
1581    /**
1582    * This method returns the Role Type.
1583    */
 
1584  2711 toggle public String getRoleType(){
1585  2711 return type;
1586    }
1587   
1588    /**
1589    * This method sets the type of the role; for use by the Role Spec
1590    * Policy only at the object
1591    * initialisation time.
1592    */
 
1593  101 toggle protected void setRoleType(String t){
1594  101 type=t;
1595    }
1596   
1597    /**
1598    * This method returns whether or not the given role's privileges should
1599    * be
1600    * inherited or not. The node is equal to the current one only if they
1601    * refer
1602    * to the same node, or their values are equal.
1603    *
1604    * <p>TODO: do i remove String equality of their values?
1605    *
1606    * @return true, if rhn is equal to, or is subordinate to this node
1607    */
 
1608  17641 toggle public boolean isSuperiorTo(issrg.pba.rbac.RoleHierarchyNode rhn){
1609    //System.out.println("checking if "+this+" is superior to "+rhn);//*************
1610   
1611  17641 if (rhn==null || !(rhn instanceof RoleHierarchyNode)){
1612    //System.out.println(rhn+": is not an instance of RoleHierarchyNode");//*************
1613  0 return false;
1614    }
1615   
1616  17641 RoleHierarchyNode rhn1 = (RoleHierarchyNode)rhn;
1617   
1618  17641 if (rhn1==this || rhn1.getValue().intern()==getValue().intern()){
1619    //System.out.println(this+" is superior to "+rhn1);//*************
1620  5606 return true;
1621    }
1622   
1623    // this is why I invented that hierarchy level thing: now I can stop
1624    // if I am definitely on the wrong branch.
1625  12035 if (rhn1.getLevel()<=getLevel() || subordinates==null){
1626    //System.out.println(this+" is not superior to "+rhn1+": this level="+getLevel()+">="+rhn1.getLevel()+", "+(subordinates==null));//*************
1627  6715 return false;
1628    }
1629   
1630  6029 for (int i=0; i<subordinates.length; i++){
1631    //System.out.println(": lets check if "+subordinates[i]+" is superior to "+rhn);//*************
1632  5963 if (subordinates[i].isSuperiorTo(rhn)){
1633    //System.out.println(subordinates[i]+" is superior to "+rhn);//*************
1634  5254 return true;
1635    }
1636    //System.out.println(": no, "+subordinates[i]+" is not superior to "+rhn);//*************
1637    }
1638   
1639    //System.out.println(this+" is not superior to "+rhn+": no subordinate is superior to it");//*************
1640  66 return false;
1641    }
1642   
1643    /**
1644    * The string representation of this node is the role value.
1645    */
 
1646  0 toggle public String toString(){
1647  0 return getValue();
1648    }
1649    }
1650   
1651   
1652    /**
1653    * This is the class that represents the RoleHierarchyPolicy node. It knows
1654    * all the types and OIDs of all Role hierarchies declared in the policy.
1655    *
1656    * @author A Otenko
1657    * @version 1.0
1658    */
 
1659    public class RoleHierarchyPolicyNode extends PolicyXMLNode implements issrg.pba.rbac.RoleHierarchyPolicy {
1660    /**
1661    * This is a Map of Role hierarchies, indexed by their type.
1662    */
1663    protected java.util.Map byType = new java.util.Hashtable();
1664   
1665    /**
1666    * This is a Map of Role hierarchies, indexed by their OID.
1667    */
1668    protected java.util.Map byOID = new java.util.Hashtable();
1669    protected java.util.Map typeOid = new java.util.Hashtable();
1670   
1671    /**
1672    * This is the only constructor, and it simply creates a PolicyXMLNode
1673    * of this type.
1674    */
 
1675  25 toggle public RoleHierarchyPolicyNode(Attributes attrs) {
1676  25 super(XMLTags.ROLE_HIERARCHY_POLICY_NODE, attrs);
1677   
1678  25 roleHierarchyPolicy = this;
1679    }
1680   
1681    /**
1682    * This method looks through its children and rearranges them into maps
1683    * of
1684    * role hierarchies by type and by OID.
1685    *
1686    * @throws PolicyParsingException if a semantic error is encountered
1687    * (for
1688    * example, two role hierarchies of the same type)
1689    */
 
1690  25 toggle public void construct() throws PolicyParsingException{
1691  25 Object [] childs = children.toArray();
1692   
1693  55 for (int i=0; i<childs.length; i++){
1694  30 RoleSpecNode rsn = (RoleSpecNode)childs[i];
1695   
1696  30 String s = rsn.getType();
1697  30 String oid = rsn.getOID();
1698  30 if (byType.get(s)!=null){ // such a type exists
1699  0 throw new PolicyParsingException("Role Type "+s+" defined more than once");
1700    }
1701   
1702  30 if (byOID.get(oid)!=null){ // such an OID is defined
1703  0 throw new PolicyParsingException("Role OID "+oid+" defined more than once");
1704    }
1705   
1706  30 byType.put(s, rsn);
1707  30 byOID.put(oid, rsn); // the Type and OID should not be the same anyway?.. so it could be the same Hashtable, couldn't it?
1708  30 typeOid.put(s,oid);
1709    }
1710    }
1711   
1712    /**
1713    * This method returns a RoleSpecNode (a role hierarchy) of the given
1714    * type.
1715    *
1716    * @param roleType is the String name of the role type to return
1717    *
1718    * @return the RoleSpecNode representing the hierarchy of roles of the
1719    * given
1720    * type, or null, if no such type has been defined
1721    */
 
1722  2919 toggle public RoleSpecNode getByType(String roleType){
1723  2919 return roleType==null ? null : (RoleSpecNode)byType.get(roleType);
1724    }
1725   
1726   
1727    /**
1728    * This method returns a RoleSpecNode (a role hierarchy) of the given
1729    * OID.
1730    *
1731    * @param roleOID is the dotted representation of the OID of the role
1732    * hierarchy to return
1733    *
1734    * @return the RoleSpecNode representing the hierarchy of roles of the
1735    * given
1736    * OID, or null, if no such type has been defined
1737    */
 
1738  1803 toggle public RoleSpecNode getByOID(String roleOID){
1739  1803 return roleOID==null ? null : (RoleSpecNode)byOID.get(roleOID);
1740    }
1741   
1742    /**
1743    * This method returns the role type defined for a specific OID.
1744    *
1745    * @param roleOID - the OID in dotted form of the role type
1746    *
1747    * @return the role type, as declared in the policy, or null, if no
1748    * role type for this OID has been declared
1749    */
 
1750  1803 toggle public String getTypeByOID(String roleOID){
1751  1803 RoleSpecNode rsn = getByOID(roleOID);
1752   
1753  1803 return rsn==null ? null : rsn.getType();
1754    }
1755   
1756    /**
1757    * This method returns a reference to a hierarchy node for the role of
1758    * the given type and value.
1759    *
1760    * @param type - the type of the role, as declared in the policy
1761    * @param value - the value of the role, as declared in the policy
1762    *
1763    * @return issrg.pba.rbac.RoleHierarchyNode that represents the role
1764    * with the given value of the given type, or null, if no such type
1765    * has been declared, or if there is no such value for the existing
1766    * type
1767    */
 
1768  2589 toggle public issrg.pba.rbac.RoleHierarchyNode getRole(String type, String value){
1769  2589 RoleSpecNode rsn = getByType(type);
1770  2589 return rsn==null ? null : rsn.getRole(value);
1771    }
1772   
1773    /**
1774    * This method returns a Map of types into OIDs. The keys in the Map
1775    * are the role types, as defined in the policy, and the values in the
1776    * Map are the OIDs of these roles.
1777    */
 
1778  1 toggle public Map getTypeOid() {
1779  1 return typeOid;
1780    }
1781    }
1782   
1783   
1784   
1785    /**
1786    * This is an implementation of Role List. The object constructs the
1787    * credential
1788    * the Role List represents. It uses a RoleHierarchyPolicyNode to identify
1789    * the roles listed.
1790    *
1791    * @author A Otenko
1792    * @version 1.0
1793    */
 
1794    public class RoleListNode extends PolicyXMLNode {
1795    /**
1796    * This is the reference to the Role Hierarchy Policy
1797    */
1798    protected RoleHierarchyPolicyNode policy;
1799   
1800    /**
1801    * This is the credential, represented by the Role List.
1802    */
1803    protected issrg.pba.Credentials credential;
1804   
1805    /**
1806    * This constructor builds a RoleListNode given the set of attributes.
1807    * It uses the default RoleHierarchyPolicy that must be discovered by
1808    * XMLPolicyParser by the time of constructing this Role List.
1809    *
1810    * <p>This is a shortcut to calling new RoleListNode(null, attrs).
1811    *
1812    * @param attrs - the attributes of this XML element
1813    */
 
1814  151 toggle public RoleListNode(Attributes attrs){
1815  151 this(null, attrs);
1816    }
1817   
1818    /**
1819    * This constructor builds a RoleListNode given the RoleHierarchyPolicy
1820    * and the attributes of the XML element.
1821    *
1822    * @param rhpn - RoleHierarchyPolicyNode representing the role hierarchy
1823    * policy to be used by this Role List; if null, the default
1824    * RoleHierarchyPolicy discovered by XMLPolicyParser will be used
1825    * @param attrs - the attributes of the XML element
1826    */
 
1827  151 toggle public RoleListNode(RoleHierarchyPolicyNode rhpn, Attributes attrs){
1828  151 super(XMLTags.ROLE_LIST_NODE, attrs);
1829   
1830  151 policy = rhpn==null?roleHierarchyPolicy:rhpn;
1831    }
1832   
1833    /**
1834    * This method checks that all the roles listed have been declared in
1835    * the corresponding RoleHierarchyPolicyNode and constructs a
1836    * Credentials representing the union of all the roles in the list. The
1837    * validityForRoleList is assumed to have been set by XMLPolicyParser,
1838    * but this is not always so (because of the sequence of policy
1839    * parsing), so the RoleAssignmentPolicyNode invokes this method again
1840    * after the validity of the roles has been discovered.
1841    */
 
1842  203 toggle public void construct() throws PolicyParsingException {
1843  203 java.util.Vector v = new java.util.Vector();
1844   
1845  444 for (int i=children.size(); i-->0; ){
1846  241 PolicyXMLNode c2 = (PolicyXMLNode)children.get(i);
1847  241 if (c2.getName().intern()!=XMLTags.ROLE_NODE){
1848  0 throw new PolicyParsingException("Syntax error. "+XMLTags.ROLE_NODE+" node was expected, but "+c2.getName()+" was found");
1849    }
1850  241 String roleType = (String)c2.getAttributes().get(XMLTags.TYPE_ATTRIBUTE);
1851  241 String roleValue = (String)c2.getAttributes().get(XMLTags.VALUE_ATTRIBUTE);
1852   
1853  241 RoleSpecNode rsn = null;
1854  241 RoleHierarchyNode rhn = null;
1855   
1856  241 issrg.pba.Credentials cred=null;
1857   
1858  241 if (roleType==null){
1859  0 throw new PolicyParsingException("No Role Type has been specified");
1860    }
1861   
1862  241 rsn = policy.getByType(roleType);
1863  241 if (rsn==null){
1864  0 throw new PolicyParsingException("No Role Type "+roleType+" has been defined");
1865    }
1866   
1867  241 if (roleValue==null){
1868  24 roleValue=""; // "Any value"
1869    //throw new PolicyParsingException("No Role Value for Role Type "+roleType+" has been defined");
1870    }
1871   
1872  241 if (roleValue.intern()!=""){ // this means "Any value for this type"
1873  203 rhn = rsn.getRole(roleValue);
1874  203 if (rhn==null){
1875  0 throw new PolicyParsingException("No such Role Value "+roleValue+" for Role Type "+roleType+" has been defined");
1876    }
1877    }
1878   
1879  241 cred = new issrg.pba.rbac.ExpirableCredentials(
1880  241 rhn==null ? new issrg.pba.rbac.PermisCredentials(roleType) :new issrg.pba.rbac.PermisCredentials(rhn),
1881    validityForRoleList
1882    );
1883   
1884    /*
1885    * TODO: build special credentials when RoleValue or RoleType has not been specified.
1886    * the problem being that this object is used in two places: RoleAssignmentPolicy
1887    * and TargetAccessPolicy. Note that in the second case if the SOACredential
1888    * is created, no access can be granted to anyone: no one can contain an
1889    * SOACredential with no Value specified in it.
1890    */
1891    //if (cred==null) {
1892    // it seems that rhn is always null here
1893    // do i remove the rhn from the SOACredential altogether?
1894    //cred = new issrg.pba.rbac.SOACredentials(rsn, rhn);
1895    // throw new PolicyParsingException("No such Role Value "+roleValue+" for Role Type "+roleType+" has been defined");
1896    //}
1897   
1898  241 v.add(cred);
1899   
1900    }
1901  203 credential = new issrg.pba.rbac.SetOfSubsetsCredentials(v);
1902    }
1903   
1904   
1905    /**
1906    * This method returns the credential this role list represents
1907    */
 
1908  151 toggle public issrg.pba.Credentials getCredential(){
1909  151 return credential;
1910    }
1911    }
1912   
1913    /**
1914    * This class is the implementation of the RoleSpec XML node. It encapsulates one
1915    * directed graph, which is a hierarchy of roles of the same type.
1916    *
1917    * <p>It knows the RoleType
1918    * it represents and the OID of the Role it represents. It also knows all
1919    * the
1920    * roles that are defined in the SupRole nodes embedded.
1921    *
1922    * @author A Otenko
1923    * @version 1.0
1924    */
 
1925    public class RoleSpecNode extends PolicyXMLNode{
1926    /**
1927    * The following two characterise this Role Hierarchy.
1928    */
1929    protected String type;
1930    protected String oid;
1931   
1932    /**
1933    * This is where the roles are mapped.
1934    */
1935    protected java.util.Map roles = new java.util.Hashtable();
1936   
1937    /**
1938    * This constructor builds a RoleSpecNode given a set of attributes of
1939    * the XML element.
1940    */
 
1941  30 toggle public RoleSpecNode(org.xml.sax.Attributes attrs) {
1942  30 super(XMLTags.ROLE_SPEC_NODE, attrs);
1943   
1944  30 type = attrs.getValue(XMLTags.TYPE_ATTRIBUTE);
1945  30 oid = attrs.getValue(XMLTags.OID_ATTRIBUTE);
1946    }
1947   
1948    /**
1949    * This method creates the map of roles, derived from the collection of
1950    * children of this node; it assumes all of them are RoleHierarchyNodes.
1951    *
1952    * <p>This method also triggers the hierarchy optimisation algorithm,
1953    * which will detect loops in the role hierarchy and assign levels to
1954    * the Role Hierarchy nodes so that in some cases it will be easy to
1955    * tell if two roles are hierarchically related.
1956    *
1957    * @throws PolicyParsingException, if a semantics error has been
1958    * encountered;
1959    * for example, two roles with the same ID have been defined
1960    */
 
1961  30 toggle public void construct() throws PolicyParsingException{
1962    //System.out.println("RoleSpec closed @ "+locator.getLineNumber());
1963    /**
1964    * TODO: check for null pointers, as appropriate
1965    */
1966  30 Object [] curr_roles=children.toArray();
1967   
1968    //System.out.println("Roles discovered: "+curr_roles.length);
1969   
1970  131 for (int i=0; i<curr_roles.length; i++){
1971  101 RoleHierarchyNode rhn = (RoleHierarchyNode)curr_roles[i];
1972  101 String s = rhn.getValue();
1973  101 if (roles.get(s)!=null){ // no roles with two names allowed!
1974  0 throw new PolicyParsingException("Role reference ID "+s+" defined elsewhere");
1975    }
1976   
1977  101 rhn.setRoleType(type);
1978   
1979  101 roles.put(s, rhn);
1980    }
1981   
1982  131 for (int i=0; i<curr_roles.length; i++){
1983  101 RoleHierarchyNode rhn = (RoleHierarchyNode)curr_roles[i];
1984  101 rhn.optimise(roles);
1985    }
1986   
1987    //System.out.println("\tquitting construct"); //*******
1988    }
1989   
1990    /**
1991    * This method returns a RoleHierarchy node of the needed Value.
1992    *
1993    * @param value - the value of the role, as defined in the policy
1994    *
1995    * @return RoleHierarchyNode corresponding to the role, or null, if no
1996    * such role exists
1997    */
 
1998  2875 toggle public RoleHierarchyNode getRole(String value){
1999  2875 return value==null ? null : (RoleHierarchyNode)roles.get(value);
2000    }
2001   
2002    /**
2003    * This method returns the RoleType value.
2004    */
 
2005  1829 toggle public String getType(){
2006  1829 return type;
2007    }
2008   
2009    /**
2010    * Apparently, this method returns the Role OID value. The value is in
2011    * dotted form.
2012    */
 
2013  30 toggle public String getOID(){
2014  30 return oid;
2015    }
2016    }
2017   
2018   
2019    /**
2020    * This class implements the SOAPolicy XML node. It holds an index of all
2021    * declared SOA ids, and their LDAP DNs can be retrieved by the SOA ID.
2022    *
2023    * @author A Otenko
2024    * @version 1.0
2025    */
2026   
 
2027    public class SOAPolicyNode extends PolicyXMLNode{
2028    /**
2029    * This is where the SOAs are stored.
2030    */
2031    private java.util.Map soas;
2032   
2033    /**
2034    * This constructor builds a SOAPolicyNode using a set of attributes of
2035    * the XML element. It sets the soaPolicy of the XMLPolicyParser, so
2036    * that it can be found by other policies.
2037    *
2038    * @param attrs - the attributes of the XML element.
2039    */
 
2040  25 toggle public SOAPolicyNode(Attributes attrs) {
2041  25 super(XMLTags.SOA_POLICY_NODE, attrs);
2042   
2043  25 soaPolicy = this;
2044    }
2045   
2046    /**
2047    * This method checks that all the SOA definitions are semantically
2048    * correct. In particular, it checks that the URL of the SOA can be
2049    * interpreted, that the LDAP DN of the SOA is a valid Distinguished
2050    * Name and that the IDs of the SOAs are unique throughout this policy.
2051    */
 
2052  25 toggle public void construct() throws PolicyParsingException{
2053  25 try{
2054  25 soas = new java.util.Hashtable();
2055  65 for (int i=children.size(); i-->0; ){
2056  40 PolicyXMLNode c = (PolicyXMLNode)children.get(i);
2057  40 if (c.getName().intern()!=XMLTags.SOA_SPEC_NODE){
2058  0 throw new PolicyParsingException(XMLTags.SOA_SPEC_NODE+" nodes are allowed under this node");
2059    }
2060  40 String id = (String) c.getAttributes().get(XMLTags.ID_ATTRIBUTE);
2061  40 String dn = (String) c.getAttributes().get(XMLTags.LDAPDN_ATTRIBUTE);
2062  40 String url = (String) c.getAttributes().get(XMLTags.URL_ATTRIBUTE);
2063   
2064  40 if (id==null || (dn==null && url==null)){
2065  0 throw new PolicyParsingException(XMLTags.ID_ATTRIBUTE+" and "+XMLTags.LDAPDN_ATTRIBUTE+" or "+XMLTags.URL_ATTRIBUTE+" attributes are required for "+XMLTags.SOA_SPEC_NODE+" nodes");
2066    }
2067   
2068  40 if (soas.get(id)!=null){
2069  0 throw new PolicyParsingException("Several SOAs with the same id: "+id);
2070    }
2071   
2072    // here either dn or url is non-null (or both, so dn will take precedence)
2073  40 Principal soa;
2074  40 try{
2075    //@comment by Gansen : here we build the soa principal based on the LDAPDN or the URL
2076  40 soa = dn!=null?new LDAPDNPrincipal(dn): URLHandler.getPrincipalByURL(url);
2077    }catch (BadURLException bue){
2078  0 throw new PolicyParsingException("URL Handling failed: "+bue.getMessage(), bue);
2079    }
2080   
2081  40 if (soa==null){
2082  0 throw new PolicyParsingException("URL Handler was not found for "+URLHandler.getProtocolName(url));
2083    }
2084   
2085  40 soas.put(id, soa);
2086    }
2087   
2088    }catch (Throwable th){
2089  0 throw new PolicyParsingException("Syntax error: "+th.getMessage());
2090    }
2091    }
2092   
2093    /**
2094    * This method returns the SOA for the given ID. It returns null, if no
2095    * such ID
2096    * has been defined.
2097    */
 
2098  52 toggle public java.security.Principal getSOA(String id){
2099  52 return (java.security.Principal)soas.get(id);
2100    }
2101   
2102    /**
2103    * This method returns the list of SOAs
2104    *@return a map that store that maps from soas' id to soas' DNs
2105    */
 
2106  1 toggle public java.util.Map getSOAs(){
2107  1 return soas;
2108    }
2109    }
2110   
2111    /**
2112    * This class represents the TargetAccessPolicy XML node. It indexes all
2113    * the target access rules by action name.
2114    */
 
2115    public class TargetAccessPolicyNode extends PolicyXMLNode {
2116    //@Gansen : this is the sequence of various components in the target access rule.
2117    //originally defined by Sassa.
2118    public static final int ROLE_LIST_SEQUENCE = 0;
2119    public static final int TARGET_LIST_SEQUENCE = 1;
2120    public static final int IF_SEQUENCE = 2;
2121   
2122    //@Gansen : The following two are added for parsing obligations.
2123    //Obligations are put at the end of the old style target access rule, thus
2124    //Obligations are at the 3rd position (begin with 0). but when IF statement
2125    //is not presented, the position will be moved one forward by using
2126    //OBLIGATIONS_SHIFT.
2127    public static final int OBLIGATIONS_SEQUENCE=3;
2128    public static final int OBLIGATIONS_SHIFT=-1;
2129   
2130    /**
2131    * This is the string of character separators between actions in the action list
2132    */
2133    public static final char ACTIONS_SEPARATORS = ',';
2134   
2135    /**
2136    * This is where the rules are stored as an index by action name
2137    */
2138    private java.util.Map rules = new java.util.Hashtable();
2139   
2140    /**
2141    * This is the IF_StatementNode, in order to extract all enviroment nodes
2142    */
2143   
2144    private PolicyXMLNode[] if_statementNodes = null;
2145   
2146    /**
2147    * This method returns the array of environment nodes, which represent all of the
2148    * environmental (coordination) attributes in the current target access policy.
2149    * These attributes include the all coordination attributes, which need to be retrieved from a coordination database.
2150    * @return an array of environment nodes
2151    */
 
2152  1 toggle public issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode[] getAllNeededAttributes() {
2153  1 ArrayList list = new ArrayList();
2154  2 for (int i=0; i<this.if_statementNodes.length; i++) {
2155  1 ArrayList local=travers(this.if_statementNodes[i]);
2156  1 if (!local.isEmpty()) list.addAll(local);
2157    }
2158  1 issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode[] nodes =
2159    new issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode[list.size()];
2160  1 nodes = (issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode[])list.toArray(nodes);
2161  1 return nodes;
2162    }
2163   
2164    /**
2165    * Taken as input an IF statement node, this method returns all of the environment nodes in it.
2166    * @param node, which represents this IF statement node.
2167    * @return an list of environment nodes.
2168    */
2169   
 
2170  8 toggle private ArrayList travers(PolicyXMLNode node) {
2171  8 ArrayList list = new ArrayList();
2172  8 if (node.getChildren().size()>0) {
2173  11 for (int i=0; i<node.getChildren().size(); i++) {
2174  7 PolicyXMLNode child = (PolicyXMLNode)node.getChildren().get(i);
2175  7 ArrayList sub = this.travers(child);
2176  7 list.addAll(sub);
2177    }
2178    } else {
2179  4 if (node instanceof issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode) {
2180  2 list.add(node);
2181    }
2182    }
2183  8 return list;
2184    }
2185   
2186    /**
2187    * This constructor builds a TargetAccessPolicyNode given the attributes
2188    * of the XML element. It also sets the targetAccessPolicy of
2189    * XMLPolicyParser, so that it can be used later by other policies.
2190    * The validityForRoleList is set to NowValidityPeriod, so that all
2191    * role lists in any TargetAccess will construct Credentials that
2192    * will be valid at the time of decision making only.
2193    *
2194    * @param attrs - the attributes of the XML element
2195    */
 
2196  25 toggle public TargetAccessPolicyNode(Attributes attrs){
2197  25 super(XMLTags.TARGET_ACCESS_POLICY_NODE, attrs);
2198   
2199  25 targetAccessPolicy = this;
2200   
2201  25 validityForRoleList = new issrg.pba.rbac.NowValidityPeriod();
2202    }
2203   
2204    /**
2205    * This method checks that the TargetAccesses contained in this policy
2206    * are semantically correct and indexes them by the action name. If
2207    * no action name has been specified, it means that any action is
2208    * allowed, and a special list of TargetAccesses is maintained for that.
2209    */
 
2210  25 toggle public void construct() throws PolicyParsingException{
2211    //@Linying:
2212    //This is for the collection of all of the IF statements in this target access policy
2213  25 ArrayList envList = new ArrayList();
2214   
2215    //@Gansen:
2216    //this is use for coz the position of the obligations in the
2217    //target access rule may change from 3 to 2 if the if statment
2218    //is missing from the rule.
2219    //when the if statement is missing, obligs_shift_factor is set to
2220    // OBLIGATIONS_SHIFT (which is -1), and the actual pos of the obligations is caulculated by
2221    // OBLIGATIONS_SEQUENCE+oblgs_shift_factor
2222   
2223    //oblgs_shift_factor MUST BE RESET TO ZERO for each rule
2224  25 int oblgs_shift_factor=0;
2225   
2226    //@Gansen : process the target access rules one by one.
2227    //@Sassa : in reverse order
2228   
2229  124 for(int i=children.size(); i-->0;){
2230   
2231  99 oblgs_shift_factor=0;
2232   
2233    //@Gansen : Get the next target access rule
2234  99 PolicyXMLNode ta = expect(children, i, XMLTags.TARGET_ACCESS_NODE);
2235   
2236    //@Gansen : ta is the target access rule which is currently being processed.
2237  99 Vector ta_children = ta.getChildren(); //@Gansen : ta_children is the <role-list,targetlist>
2238   
2239    //@Gansen : cred is the role-list of the target access rule
2240  99 issrg.pba.Credentials cred = ((RoleListNode)expect(ta_children, ROLE_LIST_SEQUENCE, XMLTags.ROLE_LIST_NODE)).getCredential();
2241   
2242    //@Gansen : tl is the target list of the target access rule
2243  99 Vector tl = expect(ta_children, TARGET_LIST_SEQUENCE, XMLTags.TARGET_LIST_NODE).getChildren();
2244  99 if (tl.size()<1){
2245  0 throw new PolicyParsingException("TargetList cannot be empty");
2246    }
2247   
2248    //@Gansen : _if is the if statement of the target access rule
2249  99 PolicyXMLNode _if = expect(ta_children, IF_SEQUENCE, XMLTags.IF_NODE, true);
2250  99 issrg.pba.rbac.xmlpolicy.ifstatement.Term the_if=null;
2251   
2252  99 if (_if!=null){ // there's an IF-statement
2253  35 envList.add(_if);
2254  35 oblgs_shift_factor=0;
2255  35 Vector if_children = _if.getChildren();
2256   
2257  35 if (if_children.size()!=1){
2258  0 throw new PolicyParsingException("IF-statement must contain one child node");
2259    }
2260   
2261  35 Object o=if_children.get(0);
2262  35 if (!(o instanceof issrg.pba.rbac.xmlpolicy.ifstatement.Term)){
2263  0 throw new PolicyParsingException("IF-statement can contain only valid evaluation operations: "+o.getClass().getName()+" object found, but Term was expected. Node name: "+((PolicyXMLNode)o).getName());
2264    }
2265   
2266  35 the_if=(issrg.pba.rbac.xmlpolicy.ifstatement.Term)o;
2267  35 if (the_if.getType().intern()!=issrg.pba.rbac.xmlpolicy.ifstatement.Types.BOOLEAN_TYPE.intern()){
2268  0 throw new PolicyParsingException("IF-statement can start only with a boolean term");
2269    }
2270    }else{//@Gansen : there is no IF-statement
2271    //set the shift flaf of the pos of the obligations.
2272  64 oblgs_shift_factor=OBLIGATIONS_SHIFT;
2273    }
2274   
2275    //@Gansen : process the target list.
2276  280 for (int j=tl.size(); j-->0;){
2277    //@Gansen : Get the targets one by one. t is the target currently being processed.
2278  181 PolicyXMLNode t = expect(tl, j, XMLTags.TARGET_NODE);
2279   
2280    //@Gansen : Check if the target contains only one node? (there shall be only one entity
2281    // in the target.
2282  181 Vector v = t.getChildren();
2283  181 if (v.size()!=1){
2284  0 throw new PolicyParsingException(XMLTags.TARGET_NODE+" must contain one node");
2285    }
2286   
2287    //@Gansen : t1 is the actual target domain (the only one).
2288  181 PolicyXMLNode t1 = expect(v, 0, XMLTags.TARGET_DOMAIN_NODE, true);
2289  181 Subtree targetDomain;
2290  181 String targetAttribute;
2291   
2292  181 if (t1==null){
2293  0 t1 = expect(v, 0, XMLTags.TARGET_NAME_NODE);
2294    //@Gansen : s is the LDAP DN
2295  0 targetAttribute = (String)t1.getAttributes().get(XMLTags.LDAPDN_ATTRIBUTE);
2296  0 if (targetAttribute==null){
2297  0 throw new PolicyParsingException(XMLTags.LDAPDN_ATTRIBUTE+" attribute is required for "+XMLTags.TARGET_NAME_NODE+" tag");
2298    }
2299   
2300  0 try{
2301    //@Gansen : create a PermisTarget using the ldap dn
2302  0 issrg.pba.rbac.PermisTarget target = new issrg.pba.rbac.PermisTarget(targetAttribute, null);
2303    /**
2304    * TODO: check if it belongs to any of the declared Target Domains
2305    */
2306   
2307  0 targetDomain = new DITSubtree(target.getDN(), 0, 0, null, null);
2308    // this Domain consists of only one DN, so the Min and Max are set appropriately
2309   
2310    }catch (issrg.utils.RFC2253ParsingException rpe){
2311  0 throw new PolicyParsingException(targetAttribute+" is not a valid target name", rpe);
2312    }
2313    }else{
2314    //@Gansen : get the id of the target
2315  181 targetAttribute = (String)t1.getAttributes().get(XMLTags.ID_ATTRIBUTE);
2316  181 if (targetAttribute==null){
2317  0 throw new PolicyParsingException(XMLTags.ID_ATTRIBUTE+" attribute is required for "+XMLTags.TARGET_DOMAIN_NODE+" tag");
2318    }
2319   
2320  181 targetDomain = targetPolicy.getDomain(targetAttribute);
2321    }
2322   
2323  181 if (targetDomain==null){
2324  0 throw new PolicyParsingException(targetAttribute+" is not within declared Target domains");
2325    }
2326   
2327   
2328    //@Gansen
2329    //Add the following code to construct an obligations object for the access rule
2330    //the obligation object will be passed to the construciton of the AccessRule;
2331  181 Obligations oblgsOfRule=null;
2332  181 SimpleObligations ruleObligations=null;
2333   
2334  181 PolicyXMLNode obligationsNode = expect(ta_children, OBLIGATIONS_SEQUENCE+oblgs_shift_factor, XMLTags.OBLIGATIONS_NODE, true);
2335   
2336  181 if(obligationsNode!=null){ //@Gansen : if there is obligations associated with the rule, then construct the corresponding object
2337   
2338  2 ruleObligations=new SimpleObligations(obligationsNode);
2339    //System.out.print(ruleObligations.toXML());
2340    //System.out.print("\r\n");
2341    }else{//@Gansen : if there is obligations associated with the rule, then set it to be null
2342  179 ruleObligations=null;
2343    }
2344   
2345    //@Gansen : store the obligations object, which might be null when no obligations are in the rule
2346  181 oblgsOfRule=ruleObligations;
2347   
2348    //@Gansen : here we construct the AccessRule with the obligation object.
2349  181 issrg.pba.rbac.policies.AccessRule ar = new
2350    issrg.pba.rbac.policies.AccessRule(targetDomain, cred, the_if, oblgsOfRule);
2351   
2352  181 String acts = (String)t.getAttributes().get(XMLTags.ACTIONS_ATTRIBUTE);
2353   
2354  181 Object act = null;
2355  181 if (acts==null || acts.intern()==""){ // ylep, empty list of actions should be treated the same way
2356  0 acts="";
2357  0 act=""; // put the rule into the default collection then
2358    }
2359   
2360    //@Gansen : Is it correct that, the target access rule are indexed by the action it
2361    //authorise? if the target access rule authorises 2 or more actions, it will be indexed
2362    //two or more times.
2363    //@Sassa : yes, that's the idea; this way it is easy to find
2364    // the TargetAccess statements for a specific request later
2365  181 java.util.Enumeration actions=new EscapedStringTokenizer(acts, ACTIONS_SEPARATORS);
2366  181 while(true){ //@Gansen : Enumerate all actions, thus loop for n times if the rule has n actions.
2367    //System.out.println("adding access rule for :"+act+": - "+ar);//**************
2368  378 if (act!=null){ // if the action name is known, put the definition under that name
2369    // act is null, if the action names are not yet known and have to be parsed
2370    // act is not null, if the action names are parsed now, or the action names are missing from the XML tag
2371  197 java.util.Vector v1 = (java.util.Vector)rules.get(act);
2372  197 if (v1==null){
2373  93 rules.put(act, v1=new java.util.Vector());
2374    }
2375   
2376  197 String[] applyToTargets = actionPolicy.getApplyToTargets((String)act);
2377  197 if(applyToTargets != null && applyToTargets.length>0)
2378    {
2379  1 boolean foundTarget = false;
2380  1 for(int k=0;k<applyToTargets.length;k++)
2381  1 if((t1.getName().intern() == XMLTags.TARGET_DOMAIN_NODE
2382    && applyToTargets[k].equals(targetAttribute))
2383    ||(t1.getName().intern() == XMLTags.TARGET_NAME_NODE
2384    && targetPolicy.getDomain(applyToTargets[k]).equals(targetDomain)))
2385    {
2386  1 foundTarget = true;
2387  1 break;
2388    }
2389  1 if(!foundTarget)
2390  0 throw new PolicyParsingException(act + " can not be applied to " + targetAttribute);
2391    }
2392   
2393  197 v1.add(ar);//@Gansen : The target access rule is added under the action.
2394    }
2395   
2396  378 if (!actions.hasMoreElements()){
2397  181 break;
2398    }
2399   
2400  197 act = actions.nextElement();
2401    }
2402    }
2403    }
2404  25 this.if_statementNodes = new PolicyXMLNode[envList.size()];
2405  25 this.if_statementNodes = (PolicyXMLNode[])envList.toArray(this.if_statementNodes);
2406    //Why Sassa put two policy in that map ??
2407    //@Sassa : because they are needed when making a decision:
2408    // ActionPolicyNode is needed to see if the action is defined
2409    // DomainPolicyNode is needed to see if the target hits any target
2410    // domain at all
2411    // The hashtable is a hashtable of rules, these two policies are
2412    // two rules.
2413  25 rules.put(ActionPolicyNode.class, actionPolicy);
2414  25 rules.put(DomainPolicyNode.class, targetPolicy);
2415    }
2416   
2417    /**
2418    * This method returns a Map of TargetAccess rules, indexed by action
2419    * name. There is a special key, "", which contains a list of
2420    * TargetAccesses allowing any action to be performed on their
2421    * corresponding targets.
2422    *
2423    * <p>There are two more rules with keys ActionPolicyNode.class and
2424    * DomainPolicyNode.class, with the values of corresponding types.
2425    * The ActionPolicyNode in this map defines all the actions declared
2426    * in this policy. The DomainPolicyNode in this map defines all the
2427    * Target Domains declared in this policy, and can tell the overall
2428    * target coverage domain.
2429    */
 
2430  24 toggle public Map getRules(){
2431  24 return rules;
2432    }
2433   
2434    }
2435   
2436    /**
2437    * This class represents the topmost node: the policy. It knows the OID of
2438    * the
2439    * policy.
2440    */
 
2441    public class PMIXMLPolicyNode extends PolicyXMLNode{
 
2442  25 toggle public PMIXMLPolicyNode(Attributes attrs){
2443  25 super(XMLTags.X_509_PMI_RBAC_POLICY_NODE, attrs);
2444   
2445  25 pmiXMLPolicy = this;
2446    }
2447   
 
2448  14 toggle public String getOID(){
2449  14 return (String)getAttributes().get(XMLTags.OID_ATTRIBUTE);
2450    }
2451    }
2452   
2453    /**
2454    * This class represents the RepositoryPolicy node. It knows URLs of all
2455    * repositories listed.
2456    */
 
2457    public class RepositoryPolicyNode extends PolicyXMLNode{
2458    String [] urls;
2459   
2460    /**
2461    * This constructor builds a RepositoryPolicyNode given the set of
2462    * attributes of the XML element. It also sets repositoryPolicy of this
2463    * XMLPolicyParser, so it can be used later.
2464    *
2465    * @param attrs - the attributes of the XML element
2466    */
 
2467  2 toggle public RepositoryPolicyNode(Attributes attrs){
2468  2 super(XMLTags.REPOSITORY_POLICY_NODE, attrs);
2469   
2470  2 repositoryPolicy = this;
2471    }
2472   
2473    /**
2474    * This method gets the URLs, but it does not check if they can be
2475    * interpreted by any URLHandler.
2476    */
 
2477  2 toggle public void construct() throws PolicyParsingException {
2478  2 urls=new String[children.size()];
2479  6 for (int i=children.size(); i-->0;){
2480  4 PolicyXMLNode t = expect(children, i, XMLTags.REPOSITORY_NODE);
2481  4 urls[i]=(String)t.getAttributes().get(XMLTags.URL_ATTRIBUTE);
2482  0 if (urls[i]==null) throw new PolicyParsingException(XMLTags.URL_ATTRIBUTE+" attribute must be specified for "+XMLTags.REPOSITORY_NODE);
2483    }
2484    }
2485   
2486    /**
2487    * This method returns an array of repository URLs declared in this
2488    * policy. It is never null, an does not contain null entries.
2489    */
 
2490  2 toggle public String[] getURLs(){
2491  2 return urls;
2492    }
2493    }
2494   
2495    /**
2496    * This class represents the MSoDPolicy set. added for MSoD
2497    *
2498    */
 
2499    public class MSoDPolicySetNode extends PolicyXMLNode{
2500   
2501    private java.util.Vector msodRules = new java.util.Vector();
2502   
 
2503  4 toggle public MSoDPolicySetNode(Attributes attrs){
2504  4 super("MSoDPolicySetNode", attrs);
2505  4 msodPolicySetNode = this;
2506    }
2507   
 
2508  4 toggle public void construct() throws PolicyParsingException {
2509  32 for(int i=children.size(); i-->0;){
2510  28 issrg.pba.rbac.policies.MSoDRule msodRule = null;
2511   
2512  28 PolicyXMLNode ta = expect(children, i, XMLTags.MSoD_POLICY_NODE);
2513   
2514  28 String contextName = (String) ( (java.util.Hashtable)(ta.getAttributes()) ).get(XMLTags.CONTEXT_NAME);
2515   
2516  28 String firstAction=null, firstTarget=null, lastAction=null, lastTarget=null;
2517   
2518  28 java.util.Vector mmer = new java.util.Vector();
2519  28 java.util.Vector mmep = new java.util.Vector();
2520   
2521  28 Vector ta_children = ta.getChildren();
2522  128 for (int j=0; j<ta_children.size(); ++j) {
2523  100 PolicyXMLNode t2=(PolicyXMLNode) ta_children.get(j);
2524  100 if (t2.getName().equals(XMLTags.MSoD_POLICY_FIRSTSTEP) ) {
2525  12 firstAction = (String) t2.getAttributes().get("operation");
2526  12 if (actionPolicy.getActionDefinition(firstAction) == null ) {
2527  0 throw new PolicyParsingException(firstAction + " does not exist in the Action policy.");
2528    }
2529  12 firstTarget = (String) t2.getAttributes().get("targetURI");
2530    // System.out.println(" " + operation + " " + targetURI);
2531   
2532    } else
2533   
2534  88 if (t2.getName().equals(XMLTags.MSoD_POLICY_LASTSTEP) ) {
2535  24 lastAction = (String) t2.getAttributes().get("operation");
2536  24 if (actionPolicy.getActionDefinition(lastAction) == null ) {
2537  0 throw new PolicyParsingException(lastAction + " does not exist in the Action policy.");
2538    }
2539  24 lastTarget = (String) t2.getAttributes().get("targetURI");
2540    // System.out.println(" " + operation + " " + targetURI);
2541   
2542    } else
2543   
2544  64 if (t2.getName().equals("MMER") ) {
2545  28 int forbiddenCardinality;
2546  28 String intS =(String) t2.getAttributes().get("ForbiddenCardinality");
2547  28 try {
2548  28 forbiddenCardinality = Integer.parseInt( intS );
2549    }
2550    catch (Exception me) {
2551  0 throw new PolicyParsingException(intS + " for ForbiddenCardinality is not a valid integer", me);
2552    }
2553   
2554  28 if (forbiddenCardinality <=1 ) {
2555  0 throw new PolicyParsingException("ForbiddenCardinality =" + forbiddenCardinality + ", it is less then 2, this is not allowed");
2556    }
2557   
2558  28 Vector mmer_children = t2.getChildren();
2559  28 Vector mmerRoles = new Vector(); // to hold mmer roles
2560  28 int roleCount = 0;
2561   
2562  92 for (int k=0; k<mmer_children.size(); ++k) {
2563  64 PolicyXMLNode t3=(PolicyXMLNode) mmer_children.get(k);
2564  64 if (t3.getName().equals("Role") ) {
2565  64 String type = (String) t3.getAttributes().get("type");
2566  64 String value = (String) t3.getAttributes().get("value");
2567    //issrg.pba.rbac.RoleBasedCredentials roleC =
2568    // new issrg.pba.rbac.RoleBasedCredentials(type, value);
2569  64 RoleHierarchyNode rhn2 = getRole(type, value);
2570  64 if (rhn2 == null) {
2571  0 throw new PolicyParsingException(type + " " + value + " does not exist in the role assignment policy.");
2572    }
2573  64 issrg.pba.Credentials roleC = new PermisCredentials( rhn2);
2574  64 mmerRoles.add(roleC);
2575  64 ++roleCount;
2576    }
2577    }
2578  28 if ( roleCount < forbiddenCardinality ) {
2579  0 throw new PolicyParsingException("Number of roles is less than ForbiddenCardinality " + forbiddenCardinality + ", this is not allowed");
2580    }
2581  28 MMERUnit mmerUnit =
2582    new MMERUnit(forbiddenCardinality, mmerRoles);
2583  28 mmer.add(mmerUnit);
2584   
2585    } else
2586  36 if (t2.getName().equals("MMEP") ) {
2587  36 int forbiddenCardinality;
2588  36 String intS = (String) t2.getAttributes().get("ForbiddenCardinality");
2589  36 try {
2590  36 forbiddenCardinality = Integer.parseInt( intS );
2591    }
2592    catch (Exception me) {
2593  0 throw new PolicyParsingException(intS + " for ForbiddenCardinality is not a valid integer", me);
2594    }
2595   
2596  36 if (forbiddenCardinality <=1 ) {
2597  0 throw new PolicyParsingException("ForbiddenCardinality =" + forbiddenCardinality + ", it is less then 2, this is not allowed");
2598    }
2599   
2600  36 Vector mmep_children = t2.getChildren();
2601  36 Vector mmepOperations = new Vector(); // to hold mmep operations
2602  36 int operationCount = 0;
2603   
2604  132 for (int k=0; k<mmep_children.size(); ++k) {
2605  96 PolicyXMLNode t3=(PolicyXMLNode) mmep_children.get(k);
2606  96 if (t3.getName().equals("Operation") ) {
2607  96 String value = (String) t3.getAttributes().get("value");
2608  96 if (actionPolicy.getActionDefinition(value) == null ) {
2609  0 throw new PolicyParsingException(value + " does not exist in the Action policy.");
2610    }
2611  96 String target = (String) t3.getAttributes().get("target");
2612  96 UserAction ua = new UserAction(value, target);
2613  96 mmepOperations.add(ua);
2614  96 ++operationCount;
2615    }
2616    }
2617  36 if ( operationCount < forbiddenCardinality ) {
2618  0 throw new PolicyParsingException("Number of operations is less than ForbiddenCardinality " + forbiddenCardinality + ", this is not allowed");
2619    }
2620  36 MMEPUnit mmepUnit =
2621    new MMEPUnit(forbiddenCardinality, mmepOperations);
2622  36 mmep.add(mmepUnit);
2623    }
2624   
2625    } // for int j=...
2626  28 issrg.pba.rbac.policies.MSoDRule msodr =
2627    new issrg.pba.rbac.policies.MSoDRule(contextName, firstAction, firstTarget,
2628    lastAction, lastTarget, mmer, mmep );
2629  28 msodRules.add(msodr); //msodRules stores all mmer and mmep rules.
2630    } // for int i=...
2631    } // construct()
2632   
 
2633  8 toggle public Vector getMSoDRules(){
2634  8 return msodRules; //msodRules contains all mmer and mmep rules.
2635    }
2636   
2637    }
2638   
2639    // added for MSoD
 
2640  18 toggle public Vector getMSoDSet(){
2641  18 if (msodPolicySetNode== null)
2642  10 return null;
2643    else
2644  8 return msodPolicySetNode.getMSoDRules();
2645    }
2646    /**
2647    * This method returns the array of environment nodes in a target access policy node.
2648    * @return an array of environment nodes
2649    */
 
2650  1 toggle public issrg.pba.rbac.xmlpolicy.ifstatement.EnvironmentNode[] getEnvAttributes() {
2651  1 return this.targetAccessPolicy.getAllNeededAttributes();
2652    }
2653    }