Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
406   929   104   22.56
144   550   0.3   18
18     6.72  
1    
 
 
  PermisTestBench       Line # 79 406 104 70.2% 0.70246476
 
No Tests
 
1    /*
2    * Copyright (c) 2006, 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    * 1. 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    * 2. THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS
20    * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
21    * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
22    * PURPOSE ARE DISCLAIMED.
23    *
24    * 3. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
25    * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26    * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27    * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28    * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29    * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30    * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31    * POSSIBILITY OF SUCH DAMAGE.
32    *
33    * 4. YOU AGREE THAT THE EXCLUSIONS IN PARAGRAPHS 2 AND 3 ABOVE ARE REASONABLE
34    * IN THE CIRCUMSTANCES. IN PARTICULAR, YOU ACKNOWLEDGE (1) THAT THIS
35    * SOFTWARE HAS BEEN MADE AVAILABLE TO YOU FREE OF CHARGE, (2) THAT THIS
36    * SOFTWARE IS NOT "PRODUCT" QUALITY, BUT HAS BEEN PRODUCED BY A RESEARCH
37    * GROUP WHO DESIRE TO MAKE THIS SOFTWARE FREELY AVAILABLE TO PEOPLE WHO WISH
38    * TO USE IT, AND (3) THAT BECAUSE THIS SOFTWARE IS NOT OF "PRODUCT" QUALITY
39    * IT IS INEVITABLE THAT THERE WILL BE BUGS AND ERRORS, AND POSSIBLY MORE
40    * SERIOUS FAULTS, IN THIS SOFTWARE.
41    *
42    * 5. This license is governed, except to the extent that local laws
43    * necessarily apply, by the laws of England and Wales.
44    */
45    package issrg.test.ptb;
46   
47    import issrg.pba.*;
48    import issrg.pba.rbac.*;
49    import issrg.pba.rbac.x509.RepositoryACPolicyFinder;
50   
51    import java.util.ArrayList;
52    import java.util.Hashtable;
53    import java.io.BufferedReader;
54    import java.io.FileInputStream;
55    import java.security.MessageDigest;
56    import java.math.BigInteger;
57    import java.net.URL;
58    import java.io.File;
59   
60    /**
61    * This is the class for the Permis Test Bench Program. This application can be used for two purposes:
62    * <p>
63    * <nl>
64    * <li> It can generate authorisation decisions based on the following inputs:
65    * <ul>
66    * <li> Name of the file containing the information about the identity and attribute
67    * certificates to be used during the decision process
68    * <li> Name of the file containing the set of requests (user, target, action, and arguments)
69    * </ul>
70    * <li> It is able to compare two different authorisation decision files, previously generated,
71    * in order to check whether there are differences between the decision obtained for the
72    * same input request.
73    * </nl>
74    * @author O Canovas
75    * @author O Otenko
76    * @version 0.1
77    */
78   
 
79    public class PermisTestBench {
80    protected static java.io.PrintStream out = System.out;
81    protected static java.io.PrintStream err = System.err;
82   
83    protected String SOA = ""; //Distinguished name of the SOA
84    protected String oID = ""; //OID of the policy
85    protected PBAAPI pbaApi = null; //Reference to the PBA API
86    protected PTBClock clock;
87    protected PermisAction permisAction; //Current Action being requested
88    protected PermisTarget permisTarget; //Current Target being requested
89    protected String userDN; //Distinguished name of the current user
90    protected String rqNumber; //Number of requests already processed
91    protected issrg.pba.rbac.SignatureVerifier sv; //Signature Verifier to be used
92    protected issrg.utils.repository.VirtualRepository vr; //Virtual Repository
93    protected PolicyFinder pfinder;
94    protected boolean isXML = false;
95   
 
96  4 toggle public static void main(String [] args){
97  4 System.setProperty("line.separator", "\r\n");
98  4 try{
99   
100  4 PermisTestBench bench = new PermisTestBench();
101   
102  4 try{
103  4 if (args.length >= 5) {
104  4 java.io.PrintStream ps = new java.io.PrintStream(new java.io.FileOutputStream(args[args.length-1]));
105  4 System.setOut(ps);
106  4 System.setErr(ps);
107    }
108   
109  4 if (args.length < 5) {
110  0 System.out.println(args.length);
111  0 printUsage(); // Both generation and check need at least 4 arguments
112    }
113    // We check whether the user wants to generate a decision file
114    // (the first application's argument contains the type of operation to perform)
115  4 else if (args[0].intern() == "-generate") {
116  2 boolean check;
117    // We check whether the user is interested in verifying digital signatures
118    // attached to the identity and attribute certificates (5th argument)
119  2 if ((args.length == 6) && (args[4]).intern() == "-ignore-signatures")
120  0 check = false;
121  2 else check = true;
122    // Now, it's time to load the certificates specified by the repository file
123    // (the name of that file must be the 2nd argument of this application)
124  2 if (!bench.loadRepositoryFile(args[1],check))
125  1 return; //File format is not valid!
126    // Once we know the SOA, the policy's OID, and the certificates, we can initialise
127    // the PBA API
128  1 if (!bench.initialisePBAAPI())
129  0 return; //Problem during initialisation
130    // Finally, it's time to process the requests contained in the file specified
131    // by the 3rd argument and to generate the file containing the decisions (4th arg)
132  1 bench.loadRequestsAndGenerateDecisions(args[2],args[3]);
133    }
134    // Second option: the user wants to find out differences between two decision files
135    // specified as the 2nd and 3rd arguments, and to store those differences in the file
136    // specified by the 4th argument.
137  2 else if (args[0].intern() == "-check") {
138  2 bench.checkDecisionFiles(args[1],args[2],args[3]);
139    }
140    else {
141    // The first argument must be "-generate" or "-check"
142  0 printUsage();
143    }
144   
145    }catch (Throwable th){
146  0 System.out.println("Failed to initialise: "+th.getMessage());
147  0 th.printStackTrace();
148    }
149    }finally{
150  4 System.setOut(out);
151  4 System.setErr(err);
152    }
153    }
154   
155    /**
156    * Prints how to use this application
157    *
158    */
 
159  0 toggle public static void printUsage()
160    {
161  0 System.out.println("Usage:");
162  0 System.out.println(" 1. To generate an output file containing decisions");
163  0 System.out.println(" PermisTestBench -generate <repository_spec_file> <rq_spec_file> <decision_file> [-ignore-signatures] <stdio and stderr redirect_file>");
164  0 System.out.println(" 2. To compare two decision files containing decisions");
165  0 System.out.println(" PermisTestBench -check <decision_file1> <decision_file2> <output_diff_file> <stdio and stderr redirect_file>");
166    }
167   
168   
169    /**
170    * Constructs a Permis Test Bench. It has no parameters, and
171    * its main function is to initialise the Virtual Repository
172    */
 
173  4 toggle public PermisTestBench(){
174  4 vr = new issrg.utils.repository.VirtualRepository();
175  4 try{
176  4 CustomisePERMIS.setSystemClock("issrg.test.ptb.PTBClock");
177  4 clock = (PTBClock)CustomisePERMIS.getSystemClock();
178    }catch(Exception e){
179    // shouldn't have happened
180  0 e.printStackTrace();
181    }
182    }
183   
184    /**
185    * Loads attribute certificates in order to insert them into the
186    * virtual repository
187    *
188    * @param vr is the virtual repository
189    * @param filename is the name of the file containing the attribute certificate
190    * @return true if the certificate was successfully inserted
191    */
 
192  7 toggle protected boolean loadAC(issrg.utils.repository.VirtualRepository vr, String filename){
193  7 try{
194  7 java.io.InputStream io = new java.io.FileInputStream(filename);
195  7 byte [] ac = new byte [io.available()];
196   
197  7 io.read(ac);
198   
199  7 issrg.ac.AttributeCertificate acd = issrg.ac.AttributeCertificate.guessEncoding(ac);
200   
201  7 vr.populate(issrg.ac.Util.generalNamesToString(acd.getACInfo().getHolder().getEntityName()).toUpperCase(),
202    CustomisePERMIS.getAttributeCertificateAttribute(),
203    ac);
204  7 return true;
205    } catch (Throwable th){
206  0 System.out.println("Failed to load AC from ["+filename+"]");
207  0 th.printStackTrace();
208  0 return false;
209    }
210    }
211   
212    /**
213    * Reads the repository specification file. That file must have the
214    * following format (the number of entries, NOE, specifies the minimun and maximun number):
215    * <p>
216    * <ul>
217    * <li> <code>SOA_DN="distinguished name of the SOA"; NOE [1,1]</code>
218    * <li> <code>POLICY_OID="OID of the policy to enforce"; NOE [1,1]</code>
219    * <li> <code>CA="name of the file containing the identity certificate of the CA"; NOE [1,1]</code>
220    * <li> <code>SOA_CERT="name of the file containing the identity certificate of a SOA"; NOE [1,N]</code>
221    * <li> <code>POLICY_AC="name of the file containing the AC including the XML policy"; NOE [1,1]</code>
222    * <li> <code>AC="name of the file containing an AC to be stored"; NOE [0,N]</code>
223    * <li> <code>CURRENT_TIME="YYYY-MM-DD HH:MM:SS"; NOE [0,1]</code>
224    * </ul>
225    * <p>
226    * If a line starts with #, it will be considered as a comment (it is ignored).
227    *
228    * <p>
229    * Moreover, this method also initialises the SignatureVerifier implementation to be used
230    * during the decision process.
231    *
232    * @param filename is the name of the file specifying the repository
233    * @param check indicates whether the digital signatures will be verified
234    * @return true if the <code>AttributeRepository</code> and the <code>SignatureVerifier</code> were initialised
235    */
 
236  2 toggle public boolean loadRepositoryFile(String filename, boolean check) {
237  2 try {
238  2 java.io.BufferedReader in = new java.io.BufferedReader(new java.io.FileReader(filename));
239  2 String s; //String containing the value of a parameter
240  2 String varName = null; //String contining the name of the parameter
241  2 String[] varValue = null; //Array of strings for the loadVarValue method
242  2 PTBSignatureVerifier ptbSV = null; //Instance of the Permis Test Bench Sugnature Verifier
243   
244    // If "-ignore-signatures" was selected, then we are going to use the SamplePKI
245  0 if (!check) sv = new SamplePKI();
246    else {
247    // Otherwise, we use a customised Signature Verifier built for the PTB
248  2 sv = new PTBSignatureVerifier();
249  2 ptbSV = (PTBSignatureVerifier) sv;
250    }
251   
252  0 while ((varValue = loadVarValue(in))!=null){
253  18 s = varValue[1];
254  18 varName = varValue[0];
255   
256  18 if (varName == "SOA_DN"){
257  2 SOA = s;
258    }else
259  16 if (varName == "POLICY_OID"){
260  2 oID = s;
261    }else
262  14 if (varName == "CA") {
263  2 if (check)
264  2 if (!ptbSV.setCACertificate(s)) return false;
265    } else
266  12 if (varName == "SOA_CERT"){
267  3 if (check)
268  0 if (!ptbSV.addSOACertificate(s)) return false;
269    }else
270  9 if (varName == "POLICY_AC"){
271  0 loadAC(vr, s);
272    }else
273  9 if (varName == "CURRENT_TIME"){
274  1 clock.setTime(s);
275    }else
276  8 if (varName == "AC"){
277  7 loadAC(vr, s);
278    }else
279  1 if (varName == "POLICY_XML"){
280  1 loadXML(s);
281    }else
282  0 System.out.println("Unrecognised line; ignored: "+varName+"="+s);
283    }
284  1 return true;
285    }
286    catch (Exception e)
287    {
288  0 e.printStackTrace();
289  0 return false;
290    }
291    }
292   
293    /**
294    * Reads (attribute,value) pairs from a buffered reader. This method
295    * processes each line of the buffered reader looking for the <code>PARAMETER=VALUE</code> pattern.
296    * Once that pattern is found, it returns an array of Strings containing the name of the
297    * parameter in the first element and the value in the second element. On the other hand,
298    * when the end of the buffered reader is reached, it returns <code>null</code>.
299    *
300    * @param in is the buffered reader
301    * @return String[2]: <code>String[0]</code> is the name of the parameter;
302    * <code>String[1]</code> is the value; <code>null if EOF</code>
303    *
304    */
 
305  11116 toggle protected String[] loadVarValue(BufferedReader in) {
306  11116 String s = "";
307  11116 try {
308  11116 while (true) {
309  11122 s= in.readLine();
310  11122 if (s == null) return null;
311  11117 if (s.startsWith("#")) continue;
312  11111 int i = s.indexOf('='); // find the assignment mark
313  11111 String varName = null;
314  11111 if (i>=0){
315  11111 varName = s.substring(0, i).intern();
316  11111 s = s.substring(i+1);
317  11111 String[] result = new String[2];
318  11111 result[0] = varName;
319  11111 result[1] = s;
320  11111 return result;
321    }
322  0 else continue;
323    }
324    }
325    catch (Exception e) {
326  0 return null;
327    }
328    }
329   
330    /**
331    * Initialises the <code>PBA API</code>, that is, specifies the policy's OID,
332    * the distinguished name of the SOA, the attribute repository to be used, and the
333    * implementation of the SignatureInterface interface that is responsible for
334    * verifying the digital signatures of the attribute certificates
335    *
336    * @return boolean indicating whether the <code>PBA API</code> was successfully initialised
337    */
 
338  1 toggle public boolean initialisePBAAPI() {
339   
340  1 issrg.utils.repository.AttributeRepository r=vr;
341  1 try {
342  1 CustomisePERMIS.configureX509Flavour();
343  1 if (!isXML){
344  0 pbaApi = new PermisRBAC(new RepositoryACPolicyFinder(r, oID, new LDAPDNPrincipal(SOA), sv), r, null);
345    }else{
346  1 pbaApi = new PermisRBAC(pfinder, r, null);
347    }
348  1 return true;
349    }
350    catch (Exception e) {
351  0 e.printStackTrace();
352  0 return false;
353    }
354    }
355   
356    /**
357    * Reads a request contained in the request specification file.
358    * Each request must have the following format (the number of entries, NOE, specifies
359    * the minimun and maximun number):
360    * <p>
361    * <ul>
362    * <li> <code>RQ_NUMBER="number of the request being processed"; NOE [1,1]</code>
363    * <li> <code>(USER_DN || USER)="distinguished name of the requestor"; NOE [1,1]</code>
364    * <li> <code>(TARGET_DN || TARGET)="name of the requested resource (DN or URI)"; NOE [1,1]</code>
365    * <li> <code>ACTION="action being requested"; NOE [1,1]</code>
366    * <li> <code>ARG_TYPE="type of the argument"; NOE [0,N]</code>
367    * <li> <code>ARG_VALUE="value of the argument"; NOE [0,N]</code>
368    * </ul>
369    * <p>
370    * If a line starts with #, it will be considered as a comment (it is ignored).
371    * <p>
372    *
373    * Those field must appear in the order above specified.
374    * <p>
375    *
376    * @param in is buffered reader related to the request file
377    * @return true if the request is well-formed and it has been successfully read
378    */
 
379  721 toggle protected boolean loadRequest(BufferedReader in) {
380  721 String[] varValue; //to be used with loadVarValue()
381  721 String targetDN = ""; //name of the target
382  721 String action = ""; //name of the action
383  721 String value = ""; //value of the argument
384  721 String type = ""; //type of the argument
385  721 int argN; //Argument Number
386  721 ArrayList arguments = new ArrayList(); //List of arguments
387   
388  721 varValue = loadVarValue(in);
389  721 if (varValue == null) return false;
390   
391  720 if (varValue[0].intern() == "RQ_NUMBER") {
392  720 rqNumber = varValue[1];
393  0 } else return false;
394   
395  720 varValue = loadVarValue(in);
396  0 if (varValue == null) return false;
397   
398  720 if ((varValue[0].intern() == "USER_DN") || (varValue[0].intern() == "USER")) {
399  720 userDN = varValue[1];
400  0 } else return false;
401   
402  720 varValue = loadVarValue(in);
403  0 if (varValue == null) return false;
404   
405  720 if ((varValue[0].intern() == "TARGET_DN") || (varValue[0].intern() == "TARGET")) {
406  720 targetDN = varValue[1];
407  0 } else return false;
408   
409  720 varValue = loadVarValue(in);
410  0 if (varValue == null) return false;
411   
412  720 if (varValue[0].intern() == "ACTION") {
413  720 action = varValue[1];
414  0 } else return false;
415   
416    //Now, we are looking for arguments
417  720 argN = -1; //index for the arguments ArrayList
418  720 do {
419  1584 argN++;
420  1584 try {
421    //We mark the current position of the file just in case there are no more arguments
422  1584 in.mark(1024);
423    }
424    catch (Exception e)
425    {
426  0 return false;
427    }
428  1584 varValue = loadVarValue(in);
429  1584 if (varValue == null) break; //End of File
430   
431  1583 if (varValue[0].intern() == "RQ_NUMBER") {
432  719 try {
433    //No more arguments, therefore we return to the marked position
434  719 in.reset();
435  719 break;
436    }
437    catch (Exception e) {
438  0 return false;
439    }
440    }
441   
442  864 if (varValue[0].intern() == "ARG_TYPE") {
443    //New argument
444  864 type = varValue[1];
445  864 varValue = loadVarValue(in);
446  0 if (varValue == null) return false;
447  864 if (varValue[0].intern() == "ARG_VALUE") {
448  864 value = varValue[1];
449  0 } else return false;
450    }
451    //We build a new PermisArgument and we add it to the ArrayList
452  864 arguments.add(argN, new PermisArgument(type, value));
453    } while (true);
454   
455    //It's time to build the PermisAction
456  720 if (argN > 0) {
457    // Arguments were found, so we use the PermisAction(String, Arguments[]) constructor
458  576 PermisArgument[] permisArguments = new PermisArgument[arguments.size()];
459  576 permisArguments = (PermisArgument[]) arguments.toArray(permisArguments);
460  576 permisAction = new PermisAction(action, permisArguments);
461    } else
462    // No arguments were found, so we use the PermisAction(String) constructor
463  144 permisAction = new PermisAction(action);
464   
465    //It's time to build the PermisTarget
466  720 try {
467  720 boolean isAURL;
468    //WE are going to check whether it is a URI
469  720 try {
470  720 new URL(targetDN);
471  0 isAURL = true;
472    }
473    catch (Exception e) {
474    // A MalformedURLException is thrown when the targetDN does not contain
475    // a valid URL
476  720 isAURL = false;
477    }
478    // Depending on the type of target, we should use different constructors
479  720 if (!isAURL)
480  720 permisTarget = new PermisTarget(targetDN, null);
481  0 else permisTarget = new PermisTarget(targetDN);
482  720 return true;
483    }
484    catch (Exception e) {
485  0 e.printStackTrace();
486  0 return false;
487    }
488    }
489   
490    /**
491    * Writes the decision header. These are the fields filled by
492    * this method:
493    * <p>
494    * <ul>
495    * <li> <code>REQUEST_FILE="name of the file containing the requests"; NOE [1,1]</code>
496    * <li> <code>REQUEST_FILE_HASH="hash value of the request file"; NOE [1,1]</code>
497    * <li> <code>EVALUATION_DATE="date on which the decisions were taken"; NOE [1,1]</code>
498    * </ul>
499    *
500    * @param out is buffered writer related to the decision file
501    * @param rqFile the name of the file of the input requests
502    * @return true if the decision header was written
503    */
 
504  1 toggle protected boolean writeDecisionHeader(java.io.BufferedWriter out, String rqFile) {
505  1 try {
506    // Commet out those un-portable code, not very relevant to the test
507  1 out.write("REQUEST_FILE=");
508    //out.write(rqFile);
509  1 out.newLine();
510  1 out.write("REQUEST_FILE_HASH=");
511  1 byte[] hash = getRequestHash(rqFile); //SHA-1 hash
512  1 BigInteger bi = new BigInteger(hash);
513  1 bi = bi.abs();
514  1 String s = bi.toString(16); //String representation of Hex values
515  1 out.write(s);
516  1 out.newLine();
517  1 out.write("EVALUATION_DATE=");
518    //Current Date
519    //out.write(new java.text.SimpleDateFormat().format(new java.util.Date()));
520  1 out.newLine();
521  1 return true;
522    }
523    catch (Exception e) {
524  0 return false;
525    }
526    }
527   
528    /**
529    * Writes the decision information related to a particular request.
530    * These are the fields filled by this method:
531    * <p>
532    * <ul>
533    * <li> <code>RQ_NUMBER="number of the request"; NOE [1,1]</code>
534    * <li> <code>RESULT_CODE="0: allowed; 1: not allowed; 2: Invalid input; 3: Run-time error"; NOE [1,1]</code>
535    * <li> <code>RESULT_INFO="code description"; NOE [1,1]</code>
536    * <li> <code>ADDITIONAL_INFO="additional info about exceptions or errors"; NOE [1,1]</code>
537    * </ul>
538    *
539    * @param out is buffered writer related to the decision file
540    * @param rqNumber is the number of the request
541    * @param code represents the decision code taken by the PDP
542    * @param info contains a verbose interpretation of the decision code
543    * @param additionalInfo provides data related to exceptions or malformed requests
544    * @return true if the decision was written
545    */
 
546  720 toggle protected boolean writeDecisionData(java.io.BufferedWriter out, String rqNumber,
547    String code, String info, String additionalInfo) {
548  720 try {
549  720 out.write("RQ_NUMBER=");
550  720 out.write(rqNumber); out.newLine();
551  720 out.write("RESULT_CODE=");
552  720 out.write(code); out.newLine();
553  720 out.write("RESULT_INFO=");
554  720 out.write(info); out.newLine();
555  720 out.write("ADDITIONAL_INFO=");
556  720 out.write(additionalInfo); out.newLine();
557  720 out.flush();
558  720 return true;
559    }
560    catch (Exception e) {
561  0 return false;
562    }
563    }
564   
565    /**
566    * Coordinates the rest of protected methods in order to
567    * read all the requests contained in <code>rqFile</code> and to generate the authositaion decisions that will
568    * be stored in decisionFile
569    *
570    * @param rqFile is the name of the file containing the requests
571    * @param decisionFile is the name of the file that is going to contain the decisions
572    */
 
573  1 toggle public void loadRequestsAndGenerateDecisions(String rqFile, String decisionFile) {
574   
575  1 try {
576  1 java.io.BufferedWriter out = new java.io.BufferedWriter(new java.io.FileWriter(decisionFile));
577   
578  1 int code;
579  1 String resultInfo;
580  1 String additionalInfo;
581   
582    //First, we write the decision header (reference to the request file, hash, date)
583  0 if (!writeDecisionHeader(out,rqFile)) return;
584  1 java.io.BufferedReader in = new java.io.BufferedReader(new java.io.FileReader(rqFile));
585   
586    //Then, we read each request in the file
587  721 while (loadRequest(in)) {
588  720 resultInfo = "";
589  720 additionalInfo = "";
590  720 try{
591    // Requestor
592  720 java.security.Principal user = new LDAPDNPrincipal(userDN);
593  720 authenticate(user);
594   
595    // Attribute Certificates related to the user
596  720 Subject s = pbaApi.getCreds(user, null);
597    // We obtain the authorisation decision
598  720 Hashtable env = new Hashtable();
599  720 env.put(((PermisRBAC)pbaApi).TIME_VARIABLE,clock);
600   
601  588 if (!pbaApi.decision(s, permisAction, permisTarget, env)) {
602  588 code = 1;
603  588 resultInfo = "The action is not allowed";
604    }
605    else {
606  0 code = 0;
607  0 resultInfo = "Action succeeded";
608    }
609    } catch (PbaException pe) {
610  132 code = 2;
611  132 resultInfo = "Invalid input";
612  132 additionalInfo = pe.getMessage();
613    } catch (Throwable th){
614  0 code = 3;
615  0 resultInfo = "Run-time error";
616  0 additionalInfo = th.getMessage();
617    }
618    // Now we need to put the decision in the output file
619  720 if (!writeDecisionData(out,rqNumber,new Integer(code).toString(),resultInfo,additionalInfo))
620  0 break;
621    }
622  1 out.flush(); out.close();
623    }
624    catch (Exception e)
625    {
626  0 e.printStackTrace();
627    }
628    }
629   
630    /**
631    * Reads the decision header. These are the fields read by
632    * this method:
633    * <p>
634    * <ul>
635    * <li> <code>REQUEST_FILE="name of the file containing the requests"; NOE [1,1]</code>
636    * <li> <code>REQUEST_FILE_HASH="hash value of the request file"; NOE [1,1]</code>
637    * <li> <code>EVALUATION_DATE="date on which the decisions were taken"; NOE [1,1]</code>
638    * </ul>
639    *
640    * @param in is buffered reader related to the decision file
641    * @return String[3] containing: [0] name of the request file, [1] hash value, [2] date; null if EOF
642    */
 
643  2 toggle protected String[] loadDecisionHeader(java.io.BufferedReader in) {
644  2 String[] varValue;
645  2 String requestFile = "";
646  2 String requestHash = "";
647  2 String evaluationDate = "";
648   
649  2 varValue = loadVarValue(in);
650  0 if (varValue == null) return null;
651   
652  2 if (varValue[0].intern() == "REQUEST_FILE") {
653  2 requestFile = varValue[1];
654    }
655   
656  2 varValue = loadVarValue(in);
657  0 if (varValue == null) return null;
658   
659  2 if (varValue[0].intern() == "REQUEST_FILE_HASH") {
660  2 requestHash = varValue[1];
661    }
662   
663  2 varValue = loadVarValue(in);
664  0 if (varValue == null) return null;
665   
666  2 if (varValue[0].intern() == "EVALUATION_DATE") {
667  2 evaluationDate = varValue[1];
668    }
669  2 String[] result = new String[3];
670  2 result[0] = requestFile;
671  2 result[1] = requestHash;
672  2 result[2] = evaluationDate;
673  2 return result;
674    }
675   
676    /**
677    * Reads the information related to a decision contained in a decision file.
678    * These are the fields read by this method:
679    * <p>
680    * <ul>
681    * <li> <code>RQ_NUMBER="number of the request"; NOE [1,1]</code>
682    * <li> <code>RESULT_CODE="0: allowed; 1: not allowed; 2: Invalid input; 3: Run-time error"; NOE [1,1]</code>
683    * <li> <code>RESULT_INFO="code description"; NOE [1,1]</code>
684    * <li> <code>ADDITIONAL_INFO="additional info about exceptions or errors"; NOE [1,1]</code>
685    * </ul>
686    *
687    * @param in is buffered reader related to the decision file
688    * @return String[4]: [0] request number; [1] result code; [2] info; [3] additional info; null if EOF
689    */
 
690  1442 toggle protected String[] loadDecision(BufferedReader in) {
691  1442 String[] varValue;
692  1442 String rqNumber = "";
693  1442 String resultCode = "";
694  1442 String resultInfo = "";
695  1442 String additionalInfo = "";
696   
697  1442 varValue = loadVarValue(in);
698  1442 if (varValue == null) return null;
699   
700  1440 if (varValue[0].intern() == "RQ_NUMBER") {
701  1440 rqNumber = varValue[1];
702  0 } else return null;
703   
704  1440 varValue = loadVarValue(in);
705  0 if (varValue == null) return null;
706   
707  1440 if (varValue[0].intern() == "RESULT_CODE") {
708  1440 resultCode = varValue[1];
709  0 } else return null;
710   
711  1440 varValue = loadVarValue(in);
712  0 if (varValue == null) return null;
713   
714  1440 if (varValue[0].intern() == "RESULT_INFO") {
715  1440 resultInfo = varValue[1];
716  0 } else return null;
717   
718  1440 varValue = loadVarValue(in);
719  0 if (varValue == null) return null;
720   
721  1440 if (varValue[0].intern() == "ADDITIONAL_INFO") {
722  1440 additionalInfo = varValue[1];
723    }
724  1440 String[] result = new String[4];
725  1440 result[0] = rqNumber;
726  1440 result[1] = resultCode;
727  1440 result[2] = resultInfo;
728  1440 result[3] = additionalInfo;
729  1440 return result;
730    }
731   
732    /**
733    * Compares two decision files. As a result, a diff file is generated
734    * according to the following format:
735    * <p>
736    * HEADER: (see writeDiffHeader)
737    * <p>
738    * FOR EACH DECISION:
739    * <p>
740    * <ul>
741    * <li> <code>[Checking request "number of request"]</code>
742    * <li> <code> [(OK) Decision codes are equal || (WN) Decision codes differ "code1" VS "code2"]</code>
743    * <li> <code> [(OK) Messages are the same || (WN) Messages Differ]</code>
744    * <li> <code> [(OK) No additional information provided || (OK) Additional notes are the same || (WN) Notes differ]</code>
745    * </ul>
746    *
747    * @param f1 is one of the decision files
748    * @param f2 is the other decision file
749    * @param diff is the name of the file which is going to contain the differences
750    */
 
751  2 toggle public void checkDecisionFiles(String f1,String f2, String diff) {
752  2 try {
753  2 java.io.BufferedReader in1 = new java.io.BufferedReader(new java.io.FileReader(f1));
754  2 java.io.BufferedReader in2 = new java.io.BufferedReader(new java.io.FileReader(f2));
755  1 java.io.BufferedWriter out = new java.io.BufferedWriter(new java.io.FileWriter(diff));
756   
757    // First we read both decision headers
758  1 String[] header1 = loadDecisionHeader(in1);
759  1 String[] header2 = loadDecisionHeader(in2);
760   
761  0 if (header1 == null || header2 == null) return;
762    // Then we analyse those headers and we write the analysis in diff
763    //writeDiffHeader(out,header1,header2,new File(f1).getName(),new File(f2).getName());
764   
765  1 String[] decision1 = null;
766  1 String[] decision2 = null;
767   
768    //For each decision in the two files
769  1 decision1 = loadDecision(in1);
770  1 decision2 = loadDecision(in2);
771  721 while ((decision1 != null) && (decision2 != null)) {
772    //We check whether both decisions refer to the same request number
773  720 if (decision1[0].intern() == decision2[0].intern()) {
774  720 out.write("[Checking request " + decision1[0]+"]"); out.newLine();
775    //We check whether both decision codes are equal
776  720 if (decision1[1].intern() == decision2[1].intern()) {
777  720 out.write(" (OK) Decision codes are equal."); out.newLine();
778    }
779    else {
780  0 out.write(" (WN) Decision codes differ (" + decision1[1] + " VS " + decision2[1] + ")");
781  0 out.newLine();
782    }
783    //We check whether both code descriptions are equal
784  720 if (decision1[2].intern() == decision2[2].intern()) {
785  720 out.write(" (OK) Messages are the same."); out.newLine();
786    }
787    else {
788  0 out.write(" (WN) Messages differ:"); out.newLine();
789  0 out.write(" 1. " + decision1[2]); out.newLine();
790  0 out.write(" 2. " + decision2[2]); out.newLine();
791    }
792  720 if ((decision1[3].intern() == "") && (decision2[3].intern() == "")) {
793  588 out.write(" (OK) No additional information provided."); out.newLine();
794    }
795    else
796  132 if (decision1[3].intern() == decision2[3].intern()) {
797  132 out.write(" (OK) Additional notes are the same.");
798  132 out.newLine();
799    } else {
800  0 out.write(" (WN) Additional notes differ:");
801  0 out.newLine();
802  0 out.write(" 1. " + decision1[3]);
803  0 out.newLine();
804  0 out.write(" 2. " + decision2[3]);
805  0 out.newLine();
806    }
807    }
808  0 else break;
809  720 decision1 = loadDecision(in1);
810  720 decision2 = loadDecision(in2);
811    }
812  1 if ((decision1 != null) && (decision2 != null)) {
813  0 out.write("**ERROR**: Check the sequences of request numbers in both files, they differ.");
814  0 out.newLine();
815    }
816  1 else if ((decision1 != null) || (decision2 != null)) {
817  0 if (decision1 == null) {
818  0 out.write("**WARNING**: The first file is shorter than the second one");
819  0 out.newLine();
820    }
821    else {
822  0 out.write("**WARNING**: The second file is shorter than the first one");
823  0 out.newLine();
824    }
825    }
826  1 in1.close();in2.close();
827  1 out.flush(); out.close();
828    }
829    catch (Exception e)
830    {
831  1 e.printStackTrace();
832    }
833    }
834   
835    /**
836    * Obtains the hash value of a request file
837    *
838    * @param rqFile is name of the request file
839    * @return byte[] containing the SHA-1 hash of the file
840    */
 
841  1 toggle protected byte[] getRequestHash(String rqFile) {
842   
843  1 try {
844  1 MessageDigest md = MessageDigest.getInstance("SHA");
845  1 FileInputStream fis = new FileInputStream(rqFile);
846  1 byte[] content = new byte[fis.available()];
847  1 int nb = fis.read(content);
848  2 while (nb != -1) {
849  1 md.update(content,0,nb);
850  1 nb = fis.read(content);
851    }
852  1 byte[] result = md.digest();
853  1 return result;
854    } catch (Exception e) {
855  0 e.printStackTrace();
856  0 return null;
857    }
858   
859    }
860   
861    /**
862    * Reads the decision header. These are the fields read by
863    * this method:
864    * <p>
865    * <ul>
866    * <li> <code>REQUEST_FILE="name of the file containing the requests"; NOE [1,1]</code>
867    * <li> <code>REQUEST_FILE_HASH="hash value of the request file"; NOE [1,1]</code>
868    * <li> <code>EVALUATION_DATE="date on which the decisions were taken"; NOE [1,1]</code>
869    * </ul>
870    *
871    * @param out is buffered writer related to the diff file
872    * @param h1 contains the 3 fields of the header included in the first decision file
873    * @param h2 contains the 3 fields of the header included in the second decision file
874    * @param f1 is the name of the first decision file
875    * @param f2 is the name of the second decision file
876    * @return true if the diff header was successfully written
877    */
 
878  0 toggle protected boolean writeDiffHeader(java.io.BufferedWriter out, String[] h1, String[] h2, String f1, String f2) {
879  0 try {
880  0 out.write("CHECKING " + f1 + " against " + f2); out.newLine();
881  0 if (h1[1].intern() == h2[1].intern()) {
882  0 out.write("Both files are related to the same requests, i.e. same hash: <"+h1[1]+">");
883  0 out.newLine();
884    }
885    else {
886  0 out.write("WARNING: Decisions correspond to different request files");
887  0 out.newLine();
888  0 out.write(" Hash of File 1 <"+h1[1]+">"); out.newLine();
889  0 out.write(" Hash of File 2 <"+h2[1]+">"); out.newLine();
890    }
891   
892  0 java.util.Date date1 = new java.text.SimpleDateFormat().parse(h1[2]);
893  0 java.util.Date date2 = new java.text.SimpleDateFormat().parse(h2[2]);
894   
895  0 if (date1.before(date2)) {
896  0 out.write("File "+ f2 + " is newer than file " + f1); out.newLine();
897    }
898    else {
899  0 out.write("File "+ f1 + " is newer than file " + f2); out.newLine();
900    }
901  0 return true;
902    }
903    catch (Exception e) {
904  0 return false;
905    }
906    }
907   
 
908  1 toggle public void loadXML(
909    String filename) {
910  1 try {
911  1 try{
912  1 if (filename.endsWith(".xml") || filename.endsWith(".XML")) {
913  1 isXML = true;
914  1 pfinder = new issrg.simplePERMIS.SimplePERMISPolicyFinder(filename);
915    } else {
916  0 throw new Exception("Failed to load XML Policy from [" + filename + "]");
917    } }catch(java.io.FileNotFoundException e){
918  0 System.err.println(e.getMessage());
919    }
920    } catch (Throwable th) {
921  0 System.err.println("Failed to load XML from [" + filename + "]");
922  0 th.printStackTrace();
923   
924    }
925    }
926   
 
927  720 toggle protected void authenticate(java.security.Principal user){
928    }
929    }