Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
247   458   66   35.29
102   314   0.29   7
7     10.29  
1    
 
 
  PermisRBACTest       Line # 80 247 66 85.1% 0.8511236
 
No Tests
 
1    /*
2    * Copyright (c) 2005, University of Kent
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 Kent 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    package issrg.test;
32   
33    import issrg.pba.*;
34    import issrg.pba.rbac.*;
35    import issrg.pba.rbac.x509.RepositoryACPolicyFinder;
36    import issrg.utils.repository.*;
37   
38    import issrg.security.*;
39   
40    import java.io.*;
41    import java.util.*;
42   
43    /**
44    * This class is an application that processes a batch of user/target/action
45    * requests in a fashion very similar to SamleAEF. It outputs the results of
46    * processing the batch line by line. It is possible to compare the results
47    * of processing with different versions of PERMIS RBAC. If the results differ,
48    * then the code changed inconsistently.
49    *
50    * <p>The batch file has the following format:
51    * # comments<br>
52    * # and empty lines are allowed<br>
53    * [instruction]: [what to do]<br>
54    *
55    * <p>An instruction can be: "inc" - include another batch file; "ini" - initialise
56    * Permis RBAC, "env" - set an environmental parameter, "usr" - getCreds for the
57    * given user, "arg" - set an argument, "act" - set an action name, "tgt" - set
58    * a target name, "..." - same instruction as above, which is used to group
59    * multi-line settings.
60    *
61    * <p>E.g.:
62    * <br>env: clock=2005-10-23T0:0
63    * <br>...: balance=0
64    * <br>env: clock=2005-01-01T0:0
65    * <p>In the above example the first two environmental settings relate to the
66    * same environment. The third line is in another environment. Later the application
67    * will try both environments individually.
68    *
69    * <p>The application will try the specified environments,
70    * users, actions and targets in the sequence that the file states them.
71    *
72    * <p>The algorithm of processing the batch is as follows:
73    * <br>"ini:", "env:" and "arg:"+"act:" are multi-line settings. The settings
74    * are grouped into one collection as described above for "ini:". Other settings
75    * are one-line, and are collected irrespective of whether they are grouped or
76    * not. The settings between one "ini:" group and another "ini:" group are
77    * treated as a single test suite.
78    */
79   
 
80    public class PermisRBACTest extends Clock {
81    static Hashtable files = new Hashtable();
82    static PrintStream out = System.out;
83    static PrintStream err = System.err;
84    static String theParentDir = null;
85   
 
86  2 toggle public static void main(String [] args){
87  2 System.setProperty("line.separator", "\r\n");
88  2 if (args.length<1 || args.length>2){
89  0 out.println("Usage: PermisRBACTest [batchFile [outputFile]]\n\n<batchFile> is a file in format:\n# comments\n<empty lines>\nini: clear | init | (soa | url | rootca | oid | pkc | pkcattribute | ac | acattribute=...)\nenv: clear | (clock | variable=value)\narg: type=value\nusr: dn\ntgt: dn | url\nact: action\ninc: anotherBatchFile\n...: <same format as the previous instruction>\n\nIf <batchFile> is missing, standard input is used. If <outputFile> is missing,\nstandard output is used.");
90  0 if (args.length>2) return;
91    }
92   
93  2 if (args.length==2){
94  2 try{
95  2 out = new PrintStream(new FileOutputStream(args[1]));
96    }catch(IOException ioe){
97  0 out.println("This shouldn't have happened! "+ioe.getMessage());
98    }
99    }
100   
101  2 err=out;
102  2 System.setErr(err);
103  2 try{
104  2 CustomisePERMIS.registerACExtensions();
105    }catch(PbaException pe){
106    // you shouldn't get this error
107  0 pe.printStackTrace(err);
108    }
109    // now both the error stream and output stream are the same stream - easy to log
110   
111    // now let's set the time to UTC, so that the logs are consistent
112  2 java.util.TimeZone tz = java.util.TimeZone.getDefault();
113  2 tz.setRawOffset(0);
114  2 java.util.TimeZone.setDefault(tz);
115  2 try{
116  2 process(args);
117    }finally{
118  2 out.println("# *** end of test sequence");
119  2 out.close(); // flush and close the output stream
120    }
121    }
122   
 
123  5 toggle public static void process(String [] args){
124  5 String inputFilename="standard input";
125  5 InputStream in = System.in;
126  5 File parentDir = null;
127   
128  5 if (args.length>0){
129  5 try{
130  5 inputFilename=new File(args[0]).toURL().getPath();
131  0 if (files.get(inputFilename)!=null) throw new IOException("can't process "+inputFilename+" recursively");
132  5 File inFile = new File(args[0]);
133  5 in = new FileInputStream(inFile);
134  5 parentDir=inFile.getParentFile();
135  5 if (theParentDir==null) theParentDir=new File(parentDir.getAbsolutePath()).toURL().getPath();
136  5 if (inputFilename.startsWith(theParentDir)) inputFilename=inputFilename.substring(theParentDir.length());
137    }catch(IOException ioe){
138  0 err.println(ioe.getMessage());
139  0 return;
140    }
141  5 files.put(inputFilename, inputFilename);
142    }
143  5 out.println("Processing instructions from "+inputFilename);
144   
145    // now the input stream has been set, too
146   
147  5 Hashtable env = new Hashtable();
148  5 Hashtable setup = new Hashtable();
149  5 PermisRBAC pba = null;
150  5 PermisRBACTest theClock = null;
151   
152  5 Vector arguments = new Vector();
153   
154  5 LDAPDNPrincipal user=null;
155  5 Subject subject=null;
156  5 PermisTarget target=null;
157   
158  5 String prev=""; // this is the instruction in the previous loop
159   
160   
161  5 BufferedReader br=new BufferedReader(new InputStreamReader(in));
162  5 String s=null;
163  5 int line=0;
164  5 try{
165  0 while((s=br.readLine())!=null){
166  163 try{
167  163 line++;
168  163 out.println("# "+line);
169  163 out.println(s);
170  163 out.print("# ");
171   
172  163 if (s.trim().equals("")){
173  37 out.println("empty line - ignored");
174  126 }else if (s.trim().startsWith("#")){
175  44 out.println("comment - ignored");
176    }else{
177  82 String instruction = s.substring(0, 4).intern();
178  82 boolean newInstr = instruction!="...:";
179  82 if (newInstr) prev=instruction;
180  16 else instruction=prev.intern();
181   
182  82 String rhs = s.substring(4);
183   
184  82 int idx=rhs.indexOf("=");
185  82 String var=rhs, val="";
186  82 if (idx>=0){ // found an assignment - then split it into variable and value
187  40 var=rhs.substring(0, idx).trim().intern();
188  40 if ((idx+1)<rhs.length()) val=rhs.substring(idx+1);
189    }
190  82 rhs=rhs.trim().intern();
191   
192    // now rhs is the right-hand-side of the instruction
193    // var is the variable in the assignment, val is the value of the variable.
194   
195  82 if (instruction=="inc:"){ // include another batch file
196  3 out.println("include batch "+rhs);
197  3 File inFile=new File(rhs);
198  3 if (!inFile.isAbsolute()){
199  3 inFile = new File(parentDir, rhs);
200    }
201   
202  3 process(new String[]{inFile.getAbsolutePath()}); // call it recursively
203   
204  3 out.println("# resume processing of "+inputFilename);
205  79 }else if (instruction=="ini:"){ // setting initialisation parameters for PERMIS RBAC
206  19 if (rhs=="init"){
207  3 out.println("initialising PERMIS RBAC...");
208   
209  3 try{
210  3 out.print("# setting system clock...");
211  3 CustomisePERMIS.setSystemClock("issrg.test.PermisRBACTest");
212  3 theClock = (PermisRBACTest)CustomisePERMIS.getSystemClock();
213  3 out.println("done");
214  3 out.print("# collecting system setup...");
215   
216  3 String soa = (String)setup.get("soa");
217  3 String oid = (String)setup.get("oid");
218  3 String rootca = (String)setup.get("rootca");
219  3 byte [] rootcaPKC = null;
220  3 Vector url = (Vector)setup.get("url");
221  3 Vector pkc = (Vector)setup.get("pkc");
222  3 Vector ac = (Vector)setup.get("ac");
223   
224  3 String acattribute = (String)setup.get("acattribute");
225  3 String pkcattribute = (String)setup.get("pkcattribute");
226  3 if (acattribute==null) acattribute=CustomisePERMIS.getAttributeCertificateAttribute();
227  0 else CustomisePERMIS.setAttributeCertificateAttribute(acattribute);
228   
229  3 if (pkcattribute==null) pkcattribute=CustomisePERMIS.getUserCertificateAttribute();
230  0 else CustomisePERMIS.setUserCertificateAttribute(pkcattribute);
231   
232  3 out.println("done");
233  3 out.print("# checking system setup...");
234  0 if (soa==null || oid==null) throw new Exception("Mandatory parameters missing: SOA DN and OID of the Policy must be specified");
235  3 out.println("system setup ok");
236  3 out.print("# checking if signature verification is required...");
237   
238  3 if (rootca!=null && pkc==null) pkc=new Vector();
239  3 if (rootca!=null) pkc.add(0, rootca);
240   
241  3 out.println("done");
242  3 out.println("# building attribute repositories...");
243  3 AttributeRepository [] ar = new AttributeRepository[(url==null?0:url.size())+(ac==null?0:1)];
244  3 AttributeRepository [] pr = new AttributeRepository[(url==null?0:url.size())+(pkc==null?0:1)];
245   
246  3 if (url!=null){
247  2 out.println("# connecting to repositories...");
248  4 for (int i=url.size(); i-->0; ){
249  2 out.print("# "+url.get(i)+"...");
250  2 ar[i]=URLHandler.getRepositoryByURL((String)url.get(i));
251  2 pr[i]=ar[i];
252  2 out.println("ok");
253    }
254  2 out.println("# done");
255    }
256   
257  3 if (ac!=null){
258  1 out.println("# loading ACs from files...");
259  1 VirtualRepository vr=new VirtualRepository();
260  1 ar[ar.length-1]=vr;
261   
262  7 for(int i=ac.size(); i-->0; ){
263  6 out.print("# "+ac.get(i)+"...");
264  6 File f=new File((String)ac.get(i));
265  6 if (!f.isAbsolute()){
266  6 f=new File(parentDir, f.getPath());
267    }
268  6 byte [] b=new byte[(int)f.length()];
269  6 new FileInputStream(f).read(b);
270  6 vr.populate(issrg.ac.AttributeCertificate.getHolderDN(b), acattribute, b);
271  6 out.println("ok");
272    }
273  1 out.println("# done");
274    }
275   
276  3 if (pkc!=null){ // now rootca is always the first in the list
277  2 out.println("# loading PKCs from files...");
278  2 VirtualRepository vr=new VirtualRepository();
279  2 pr[pr.length-1]=vr;
280   
281   
282  4 for(int i=pkc.size(); i-->0; ){ // rootca PKC will always be loaded last
283  2 out.print("# "+pkc.get(i)+"...");
284  2 File f=new File((String)pkc.get(i));
285  2 if (!f.isAbsolute()){
286  2 f=new File(parentDir, f.getPath());
287    }
288  2 rootcaPKC=new byte[(int)f.length()];
289  2 new FileInputStream(f).read(rootcaPKC);
290  2 vr.populate(new iaik.x509.X509Certificate(rootcaPKC).getSubjectDN().getName(), pkcattribute, rootcaPKC);
291  2 out.println("ok");
292    }
293  2 out.println("# done");
294    // now rootcaPKC is the byte array pointing to the last PKC read - the root CA PKC
295    }
296   
297  3 SignatureVerifier sv=null;
298   
299  3 if (rootcaPKC!=null){
300  2 out.println("# setting signature verification...");
301  2 DefaultVerifier dv = new DefaultVerifier();
302  2 dv.setRootCA(rootcaPKC);
303  2 dv.setPKCRepository(new PKCRepository(new MultiRepository(pr)));
304  2 sv=new SimpleSignatureVerifier(dv);
305  2 out.println("# done");
306    }else{
307  1 out.println("# signature verification is disabled");
308    }
309   
310  3 out.println("# creating PERMIS RBAC object...");
311  3 issrg.pba.rbac.CustomisePERMIS.configureX509Flavour();
312  3 MultiRepository mr = new MultiRepository(ar);
313  3 pba = new PermisRBAC(new RepositoryACPolicyFinder(mr, oid, new LDAPDNPrincipal(soa), sv), mr, null);
314  3 out.println("# done");
315    }catch (Exception pe){
316  0 out.println("# failed");
317  0 pe.printStackTrace(err);
318    }
319  16 }else if (rhs=="clear"){
320  0 out.println("reset initialisation parameters for PERMIS RBAC");
321  0 setup = new Hashtable();
322    }else{
323  16 out.println("setting initialisation parameters for PERMIS RBAC");
324    //soa | oid | rootca | url | pkc | ac
325  16 if (var=="soa" || var=="oid" || var=="rootca" || var=="acattribute" || var=="pkcattribute"){
326  0 if (setup.get(var)!=null) out.println("# "+var+" is already set to "+setup.get(var)+" - ignored");
327    else{
328  8 out.println("# set "+var+" to "+val);
329  8 setup.put(var, val);
330    }
331  8 }else if (var=="url" || var=="pkc" || var=="ac"){
332  8 Vector v=(Vector)setup.get(var);
333  8 if (v==null){
334  3 out.println("# set "+var+" to "+val);
335  3 v=new Vector();
336  3 setup.put(var, v);
337    }else{
338  5 out.println("# add "+val+" to collection of "+var);
339    }
340  8 v.add(val);
341    }else{
342  0 throw new Exception("unknown setting: "+var);
343    }
344    }
345  60 }else if (instruction=="env:"){
346  10 if (newInstr){
347  10 out.println("setting new environment");
348  10 out.println("#");
349  10 env=new Hashtable();
350    }
351  10 out.println("set environmental parameters: "+var+" = ["+val+"]");
352  10 if (var.intern()=="clock"){
353  10 out.println("# set system clock to "+val);
354  10 theClock.setTime(theClock.toTime(val));
355    //out.println("# clock is set to "+theClock.getTime());
356    }else{
357  0 env.put(var, val);
358    }
359  50 }else if (instruction=="arg:"){
360  0 out.println("add to action an argument of type "+var+" and value "+val);
361  0 arguments.add(new PermisArgument(var, val));
362  50 }else if (instruction=="act:"){
363  26 Action act = new PermisAction(rhs, (Argument[])arguments.toArray(new Argument[0]));
364  26 arguments=new Vector(); // clear the list of arguments straightaway
365   
366  26 try{
367  26 out.println("request action "+act.getActionName()+" on target "+target.getName()+" on behalf of user "+user.getName());
368  0 if (pba==null) throw new PbaException("PermisRBAC is not initialised");
369  26 out.println("# decision: "+(pba.decision(subject, act, target, env)?"grant":"deny"));
370    }catch(Exception e){
371  0 err.println("# failed to get decision: "+e.getMessage());
372    }
373  24 }else if (instruction=="tgt:"){
374  11 out.println("set target to "+rhs);
375  11 String tgt=rhs;
376  11 String proto = null;
377  11 try{
378  11 proto=URLHandler.getProtocolName(tgt);
379    }catch(BadURLException bue){ /* ignore it */ }
380   
381  11 if (proto!=null && URLHandler.getURLHandler(proto)!=null){ // it is a URL then
382  10 target = new PermisTarget(tgt);
383    }else{ // well, it must be a LDAP DN then
384  1 target = new PermisTarget(tgt, null); // this time it is treated as a DN + a null array of object classes
385    }
386  13 }else if (instruction=="usr:"){
387  13 try{
388  13 out.println("set user to "+rhs);
389  13 user=new LDAPDNPrincipal(rhs);
390  13 out.print("# getting credentials for user "+user.getName()+"...");
391  0 if (pba==null) throw new PbaException("PermisRBAC is not initialised");
392  13 subject=pba.getCreds(user);
393  13 out.println("done");
394    }catch (PbaException pe){
395  0 err.println("failed to get credentials for user "+rhs+": "+pe.getMessage());
396    }
397    }else{
398  0 throw new Exception("Invalid instruction line");
399    }
400    }
401    }catch(PbaException pe){
402  0 out.println("# Error occured while processing line "+line+": "+pe.getMessage());
403    // don't print the stack trace and don't break the loop - PbaExceptions are part of testing
404    }
405    }
406    }catch(Throwable e){
407  0 out.println("Stopped @ "+line+": "+s);
408  0 e.printStackTrace(err);
409    }
410   
411  5 files.remove(inputFilename);
412    }
413   
414   
415    static final Date STARTUP=new GregorianCalendar().getTime();
416    Date time=STARTUP; // by default the clock is set to the time of the application startup
417   
 
418  3 toggle public PermisRBACTest(){}
419   
420    /**
421    * The time is stopped forever, so the latch returns the same as getTime()
422    */
 
423  52 toggle public Date latch(){
424  52 return getTime();
425    }
426   
 
427  116 toggle public Date getTime(){
428  116 return time;
429    }
430   
431    /**
432    * This method returns the time encoded as a string.
433    *
434    * @param timeString - the time to set; the format is the same as the string representation of time in the policy, e.g. "2005-09-25T23:59:59"
435    * @return the Date representing the specified time.
436    */
 
437  10 toggle public static Date toTime(String timeString) throws IllegalArgumentException{
438  10 int [] t = new Time(timeString).getEvaluationTime();
439  10 Calendar c = new GregorianCalendar();
440  10 c.set(Calendar.DST_OFFSET, 0);
441  10 c.set(Calendar.ZONE_OFFSET, 0);
442   
443  10 c.set(t[0], t[1]-1, t[2], t[3], t[4], t[5]);
444  10 c.set(Calendar.MILLISECOND, 0);
445   
446  10 return c.getTime();
447    }
448   
449    /**
450    * This method sets the current time. Initially the time is set to
451    * the time of the application startup.
452    *
453    * @param time - the time to set.
454    */
 
455  10 toggle public void setTime(Date time){
456  10 this.time=time;
457    }
458    }