Clover Coverage Report
Coverage timestamp: Sun Mar 23 2008 08:24:39 GMT
583   1,667   153   17.15
236   1,088   0.32   8.5
34     5.47  
4    
 
 
  SAWSServer       Line # 82 528 135 49% 0.48955613
  SAWSServer.WaitingRecordBlock       Line # 161 4 1 100% 1.0
  SAWSServer.WritingThread       Line # 1394 36 13 87.7% 0.877193
  SAWSServer.HeartbeatRecordWriting       Line # 1498 15 7 83.3% 0.8333333
 
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   
46    package issrg.SAWS;
47   
48    import issrg.SAWS.util.SAWSLogWriter;
49   
50    import issrg.utils.*;
51   
52    import java.util.*;
53    import org.w3c.dom.*;
54    import javax.xml.parsers.*;
55    import org.apache.soap.util.xml.*;
56    import org.xml.sax.*;
57    import java.io.*;
58   
59    import java.security.*;
60    import javax.crypto.*;
61    import java.security.AlgorithmParameters;
62    import javax.crypto.spec.* ;
63   
64    import java.security.KeyStore;
65    import java.security.Key;
66    import java.security.cert.Certificate;
67   
68    import javax.security.auth.callback.*;
69    import java.lang.reflect.Constructor;
70   
71    import javax.servlet.http.*;
72   
73    import issrg.SAWS.callback.*;
74   
75   
76    /**
77    * This is the SAWS Server class. It provides all the necessary API methods for SAWS API clients.
78    *
79    * @author W. Xu
80    * @version 0.1, Oct. 2005
81    */
 
82    public class SAWSServer {
83    private static final issrg.utils.Version version = new issrg.utils.Version("issrg/SAWS/version", "saws");
84    private Callback[] cbs = null;
85    private boolean writingHeartBeating = false;
86    // read from saws.xml
87    private String encryptionKeystoreLocation = null;
88    private String signingKeystoreLocation = null;
89    private int numberOfPasswordShares = 2;
90    private int numberOfEncPasswordShares =2;
91    private int heartbeatInterval = 0;
92    private String rootCA = null;
93    private String trustedLocation = null;
94    private String vtPKC = null;
95    private int signRecordNumber;
96    private String SAWSInterface = null;
97    private Map UserDNIDMap = new Hashtable();
98    private Map UserIDPKMap = new Hashtable();
99    private String logEncryption = "no";
100    private int debugLevel = SAWSConstant.ErrorInfo;
101    //private String signingAlg = "SHA1WITHRSA";
102    private byte hashAlgorithm = SAWSConstant.SHA1;
103   
104    //information for the latest log file in the TCBLocation
105    private String latestLogFilename = null;
106    // private int latestLogSequence = -1;
107    private int SNFromTCB = -1;
108    private byte[] AccHashFromTCB = null;
109    private CallbackHandler callbackHandler = new SAWSCmdPromptCallbackHandler();
110    private String callBackHandlerClass = "issrg.SAWS.callback.SAWSCmdPromptCallbackHandler";
111   
112    private TCBContentRW tcbContent = null;
113   
114    private LogFilenameClass lfc = null;
115   
116    private LogFileWriter currentLogFileWriter = null;
117   
118    private TCBKeystoreManagement tcbKM = null;
119   
120    // for inspecting the log file
121    private String logFileRoot = null;
122    private String currentInspectionLogFilename = null;
123    byte [] currentInspecitonAccHash = null;
124    byte [] currentInspectionSignature = null;
125    private String previousLogFilenameFromLogRoot = null;
126    private String previousLogFilenameFromLogRecord = null;
127   
128    //for reading an array of log files
129    public Vector logFileList = new Vector(); // log file name list
130    public int currentReadingFileNo = 0;
131    public Vector recordBlockListFromOneLogFile = null;
132   
133    private SecretKey sawsTCBSecretKey = null; // symmetric encryption key used to read and write lastSN and lastHash file
134    private PBEParameterSpec paramSpec = null;
135   
136    //for writing thread
137    Vector waitingRecordList0 = new Vector();
138    Vector waitingRecordList1 = new Vector();
139    boolean busyFlag0V = false;
140    boolean busyFlag1V = false;
141    Thread thread = null;
142    int recordCount = 0;
143   
144    // for heartbeat records
145    private long currentTime ;
146    private java.util.Timer timer = null;
147    private TimerTask tt2 = null;
148   
149    private boolean closed = false;
150   
151    //adding log4j logging
152   
153    /**
154    * @aggregation composite
155    */
156    private static SAWSLogWriter sawsDebugLog = new SAWSLogWriter(SAWSServer.class.getName());
157   
158    /**
159    * This class is used to hold a message record block waiting to be written to the log file.
160    */
 
161    class WaitingRecordBlock {
 
162  4 toggle public WaitingRecordBlock(){}
 
163  93 toggle public WaitingRecordBlock(byte[] messageBlock, byte recordType, byte encryptionFlag, byte userID){
164  93 this.messageBlock = messageBlock;
165  93 this.recordType = recordType;
166  93 this.encryptionFlag = encryptionFlag;
167  93 this.userID = userID;
168    }
169    public byte [] messageBlock = null;
170    public byte recordType;
171    public byte encryptionFlag;
172    public byte userID;
173    }
174   
175    /**
176    * This method is the constructor of SAWSServer. It is for SAWS web service interface.
177    * It is equivalent to the following constructor when flag = 1 (see SAWSServer(int flag))
178    * @param null
179    *
180    * @return null.
181    */
 
182  4 toggle public SAWSServer() {
183  4 readConf();
184  4 sawsInit();
185  4 sawsStart();
186    }
187   
188    /**
189    * This method is the constructor of SAWSServer.
190    * It accepts flag values 0 or 1. The flag=0 is for SAWS command line mode. The initialization process for logging client records is run when flag=1. It consists of reading the TCB(Trusted Computing Base) content to get the last log file name, accumulated hash
191    * and last record sequence number. It also creates a new log file to start logging and adds the information to the TCB location
192    * (e.g. name, random number). The initialization process includes verification of the last log file, creating a list of the
193    * log files in the log repository and verifying the log file chain if the administrator decides to.The chain can be constructured since each log file contains a record indicating the previous log
194    * file name. The first log file name contains a record indicating that "this is the first log file"
195    *
196    * @param int flag =0: for SAWS command line mode initialisation;
197    * flag=1: on top of flag=0, initializes SAWSServer for preparing to record client records.
198    *
199    * @return null.
200    */
 
201  4 toggle public SAWSServer(int flag) {
202  4 readConf();
203  4 if (flag == 1){
204  0 sawsInit();
205    }
206    }
207   
208   
209    /**
210    * This method is to read the configuration file, called by the SAWSServer constructor.
211    *
212    * @param null
213    *
214    * @return null
215    */
 
216  8 toggle private void readConf(){
217  8 java.net.URL configURL = this.getClass().getResource("saws.xml");
218  8 File configFile = new File("saws.xml");
219   
220  8 if ( !(configFile.exists()) )
221  0 configFile = new File(configURL.getFile() );
222   
223  8 java.io.BufferedReader in = null;
224  8 try{
225  8 in = new java.io.BufferedReader( new java.io.FileReader(configFile) );
226    } catch ( Exception e){
227  0 if (debugLevel >= SAWSConstant.ErrorInfo)
228    //adding log4j logging
229  0 sawsDebugLog.write(e.toString());
230  0 System.exit(-1);
231    }
232   
233  8 DocumentBuilder xdb = XMLParserUtils.getXMLDocBuilder();
234  8 org.w3c.dom.Document doc = null;
235   
236  8 try {
237  8 doc = xdb.parse(new InputSource(in) );
238    }
239    catch (Exception e) {
240  0 if (debugLevel >= SAWSConstant.ErrorInfo) {
241  0 sawsDebugLog.write(e.toString()
242    + "\nThe SAWS configuration file saws.xml could not be read."
243    + "\nPlease check Line " + ((SAXParseException)e).getLineNumber()
244    + " and Column " + ((SAXParseException)e).getColumnNumber()
245    + " in saws.xml.");
246    }
247   
248  0 this.showMessage("The SAWS configuration file saws.xml could not be read."
249    + "\nPlease check Line " + ((SAXParseException)e).getLineNumber()
250    + " and Column " + ((SAXParseException)e).getColumnNumber()
251    + " in saws.xml.", SAWSTextOutputCallback.ERROR);
252    /*
253    Object[] options = { "Stop" };
254    int select = JOptionPane.showOptionDialog(null,
255    "The SAWS configuration file saws.xml is corrupted. " +
256    "\nPlease create a new one." ,
257    "Error",
258    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
259    null, options, options[0]);
260    */
261  0 System.exit(-1);
262    }
263   
264  8 org.w3c.dom.Element root = null;
265  8 if (doc != null ) {
266  8 root = doc.getDocumentElement();
267    }
268   
269  8 NodeList nl4 = root.getElementsByTagName("CallbackHandler");
270  8 org.w3c.dom.Element e5 = (org.w3c.dom.Element) nl4.item (0);
271   
272  8 String className = null;
273  8 if (e5 != null) {
274  8 className = DOMUtils.getAttribute (e5, "class");
275  8 if (className != null) {
276  8 this.callBackHandlerClass = className;
277  8 String errorMessage = null;
278    //Object[] parameters = null;
279  8 try {
280    //Class chc = Class.forName(this.callBackHandlerClass);
281    //Constructor[] cs = chc.getConstructors();
282   
283  8 if (this.callBackHandlerClass.equals("issrg.SAWS.callback.SAWSFileCallbackHandler")) {
284  8 String inputFile = DOMUtils.getAttribute (e5, "inputFile");
285  8 String outputFile = DOMUtils.getAttribute (e5, "outputFile");
286  8 this.callbackHandler = new SAWSFileCallbackHandler(inputFile, outputFile);
287    } else {
288  0 this.callbackHandler = (CallbackHandler)
289    (Class.forName(this.callBackHandlerClass).newInstance());
290    }
291   
292    } catch (IllegalArgumentException iae) {
293  0 errorMessage = iae.getMessage();
294    } catch (InstantiationException ie) {
295  0 errorMessage = "The callback handler class \"" + className + "\" could not be instantiated."
296    + "\nPlease check the class name in the configuration file (saws.xml).";
297    } catch (ClassNotFoundException cnfe) {
298  0 errorMessage = "The callback handler class \"" + className + "\" could not be found."
299    + "\nPlease check the class name in the configuration file (saws.xml)"
300    + " or the class path.";
301    } catch (IllegalAccessException iae) {
302  0 errorMessage = "The callback handler class \"" + className + "\" could not be accessed."
303    + "\nPlease check the permissions to run the specified class.";
304    } finally {
305  8 if (errorMessage != null) {
306  0 String[] options = {"Continue", "Stop"};
307  0 if (debugLevel >= SAWSConstant.ErrorInfo) {
308  0 sawsDebugLog.write(errorMessage);
309    }
310  0 errorMessage = errorMessage
311    + "\n\nSAWS can use a default callback handler. Please select \"Continue\""
312    + "\nto use the default handler, or select \"Stop\" to finish SAWS.";
313  0 int selection = this.createConfirmCallback(errorMessage, options,
314    SAWSChoiceCallback.WARNING, "CallbackHandlerError");
315  0 if (selection == 1) {
316  0 System.exit(-1);
317    }
318    }
319    }
320    }
321   
322    }
323   
324   
325  8 NodeList nl= root.getElementsByTagName("SAWSBasic");
326  8 org.w3c.dom.Element e = (org.w3c.dom.Element) nl.item (0);
327   
328  8 encryptionKeystoreLocation = DOMUtils.getAttribute (e, "encryptionKeystoreLocation");
329  8 rootCA = DOMUtils.getAttribute (e, "rootCA");
330   
331    //if rootCA is set but not correct, then SAWS stops
332  8 if (rootCA != null ) {
333  8 File rootCAFile = new File (rootCA);
334  8 if ( !rootCAFile.exists() ) {
335    /*
336    Object[] options = { "Stop" };
337    int select = JOptionPane.showOptionDialog(null,
338    "SAWS can't find the rootCA public key certificate." + rootCA +
339    " \n" +
340    "\nSAWS will stop and the SAWS administrator needs to put the root CA public key certificate" +
341    "\nin the correct position as specified in the SAWS configuration file saws.xml." , "Warning",
342    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
343    null, options, options[0]);
344    */
345  0 this.showMessage("SAWS can't find the rootCA public key certificate." + rootCA
346    + "\n\nSAWS will stop and the SAWS administrator needs to put the root CA public key certificate"
347    + "\nin the correct position as specified in the SAWS configuration file saws.xml.",
348    SAWSTextOutputCallback.WARNING);
349  0 System.exit(-1);
350    }
351    } else { //if rootCA is not specified on the config file
352   
353    /*Object[] options = { "Stop" };
354    int select = JOptionPane.showOptionDialog(null,
355    "The rootCA public key certificate was not specified." +
356    "\n" +
357    "\nSAWS will stop and the SAWS administrator needs to specify the root CA public key certificate" +
358    "\nin the SAWS configuration file saws.xml." , "Warning",
359    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
360    null, options, options[0]);
361    */
362  0 this.showMessage("The rootCA public key certificate was not specified."
363    + "\n\nSAWS will stop and the SAWS administrator needs to specify the root CA public key certificate"
364    + "\nin the SAWS configuration file saws.xml.",
365    SAWSTextOutputCallback.WARNING);
366  0 System.exit(-1);
367    }
368   
369  8 signRecordNumber = Integer.parseInt ( DOMUtils.getAttribute (e, "signRecordNumber") );
370  8 numberOfEncPasswordShares = Integer.parseInt ( DOMUtils.getAttribute (e, "numberOfEncPasswordShares") );
371  8 heartbeatInterval = Integer.parseInt ( DOMUtils.getAttribute (e, "heartbeatInterval") );
372  8 logFileRoot = DOMUtils.getAttribute (e, "logFileRoot");
373  8 vtPKC = DOMUtils.getAttribute (e, "vtPKC");
374  8 SAWSInterface = DOMUtils.getAttribute (e, "SAWSInterface");
375  8 logEncryption = DOMUtils.getAttribute (e, "logEncryption");
376  8 debugLevel = Integer.parseInt ( DOMUtils.getAttribute (e, "debugLevel") );
377   
378  8 NodeList nl2= root.getElementsByTagName("TPMAdvanced");
379  8 org.w3c.dom.Element e2 = (org.w3c.dom.Element) nl2.item (0);
380  8 signingKeystoreLocation = DOMUtils.getAttribute (e2, "signingKeystoreLocation");
381  8 numberOfPasswordShares = Integer.parseInt ( DOMUtils.getAttribute (e2, "numberOfPasswordShares") );
382  8 trustedLocation = DOMUtils.getAttribute (e2, "trustedLocation");
383    //String s1 = DOMUtils.getAttribute (e2, "signingAlg");
384  8 String s1 = DOMUtils.getAttribute (e2, "hashAlg");
385  8 if (s1 != null) {
386  8 if (s1.equalsIgnoreCase("SHA-1")) {
387  8 this.hashAlgorithm = SAWSConstant.SHA1;
388  0 } else if (s1.equalsIgnoreCase("MD5")) {
389  0 this.hashAlgorithm = SAWSConstant.MD5;
390  0 } else if (s1.equalsIgnoreCase("SHA-256")) {
391  0 this.hashAlgorithm = SAWSConstant.SHA256;
392  0 } else if (s1.equalsIgnoreCase("SHA-384")) {
393  0 this.hashAlgorithm = SAWSConstant.SHA384;
394  0 } else if (s1.equalsIgnoreCase("SHA-512")) {
395  0 this.hashAlgorithm = SAWSConstant.SHA512;
396    } else {
397    /*
398    Object[] options = { "Stop" };
399    int select = JOptionPane.showOptionDialog(null,
400    "The hash algorithm specified in SAWS configuration file (saws.xml) is not supported." +
401    "\n" +
402    "\nSAWS will stop and the SAWS administrator needs to specify the the correct algorithm," +
403    "\nor remove the specification from the configuration file to use the default algorithm (SHA-1)." ,
404    "Warning", JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
405    null, options, options[0]);
406    */
407  0 this.showMessage("The hash algorithm specified in SAWS configuration file (saws.xml) is not supported."
408    + "\n\nSAWS will stop and the SAWS administrator needs to specify the the correct algorithm,"
409    + "\nor remove the specification from the configuration file to use the default algorithm (SHA-1).",
410    SAWSTextOutputCallback.WARNING);
411  0 System.exit(-1);
412    }
413   
414    //signingAlg = s1;
415    }
416   
417  8 NodeList nl3= root.getElementsByTagName("UserInfo");
418  8 int leng = nl3.getLength();
419   
420  24 for (int i = 0; i < leng; i ++) {
421  16 org.w3c.dom.Element e3 = (org.w3c.dom.Element) nl3.item (i);
422  16 String UserDNString = DOMUtils.getAttribute(e3, "userDN");
423  16 UserDNString = issrg.utils.RFC2253NameParser.toCanonicalDN(UserDNString).toUpperCase();
424  16 Byte UserIDByte = new Byte( (byte) Integer.parseInt ( DOMUtils.getAttribute (e3, "userID") ) );
425  16 String userPKC = DOMUtils.getAttribute(e3, "userPKC");
426   
427  16 PublicKey userPK = null;
428   
429  16 if (userPKC!= null) {
430  16 userPK = retrievePublicKey(userPKC);
431    }
432   
433  16 if ( UserDNString != null && UserIDByte != null ) {
434  16 UserDNIDMap.put( UserDNString, UserIDByte);
435    }
436   
437  16 if ( userPK!= null && UserIDByte != null ) {
438  16 UserIDPKMap.put(UserIDByte, userPK);
439    }
440    }
441   
442   
443    }
444   
445    /**
446    * This method is retrieve the public key from the PKC file
447    *
448    */
 
449  16 toggle private PublicKey retrievePublicKey ( String PKCFilename) {
450   
451  16 File f = new File(PKCFilename);
452  16 if ( !f.exists() ) {
453  0 String[] options = { "Continue", "Stop SAWS" };
454  0 int select = this.createConfirmCallback(
455    "SAWS can't find the PKC file " + PKCFilename + ". "
456    + "\nYou will not be able to use the corresponding user Private Key to read the log file "
457    + "\nif the log file is encrypted. "
458    + "\nDo you want to continue? \n", options, SAWSChoiceCallback.WARNING,
459    "MissingPKCFile");
460   
461  0 if ( select == 1)
462  0 System.exit(-1);
463  0 return null;
464    }
465   
466  16 PublicKey pk = null;
467  16 try{
468  16 FileInputStream fis = new FileInputStream(PKCFilename);
469  16 BufferedInputStream bis = new BufferedInputStream(fis);
470  16 java.security.cert.CertificateFactory cf = null;
471  16 cf = java.security.cert.CertificateFactory.getInstance("X.509");
472  16 java.security.cert.Certificate certTemp = cf.generateCertificate(bis);
473  16 pk = certTemp.getPublicKey();
474    } catch (Exception e2) {
475  0 if (debugLevel > SAWSConstant.ErrorInfo)
476    //e2.printStackTrace(System.err);
477    //adding log4j logging
478  0 sawsDebugLog.write(e2.toString());
479  0 String[] options = { "Continue", "Stop SAWS" };
480   
481  0 int select = this.createConfirmCallback(
482    "SAWS can't read the public key from the PKC file " + PKCFilename + "."
483    + "\nYou will not be able to use the corresponding user Private Key to read the log file "
484    + "\nif the log file is encrypted. "
485    + "\nDo you want to continue? \n", options,
486    SAWSChoiceCallback.WARNING, "ReadingPKWarning");
487   
488  0 if ( select == 1)
489  0 System.exit(-1);
490  0 return null;
491    }
492   
493  16 return pk;
494    }
495   
496   
497   
498    /**
499    * This method is the initialisation method of SAWSServer for preparing to record client records.
500    *
501    * @param null
502    *
503    * @return null
504    */
 
505  4 toggle private void sawsInit() {
506   
507  4 File logRoot = new File(logFileRoot);
508  4 if ( !logRoot.exists() )
509  0 logRoot.mkdir();
510  4 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
511    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
512    this.hashAlgorithm, this.callbackHandler);
513  4 tcbKM.checkSigningKeystoreFile();
514  4 tcbKM.checkEncKeystoreFile();
515  4 tcbKM.readKeystores();
516  4 sawsTCBSecretKey = tcbKM.getsawsTCBSecretKey();
517  4 if (sawsTCBSecretKey == null) {
518  0 this.showMessage("SAWS cannot generate the necessary secret key for the TCB. "
519    + "There is probably some problem with your Java cryptography libray."
520    + "\nSAWS will stop.", SAWSTextOutputCallback.WARNING);
521  0 System.exit(-1);
522    }
523  4 paramSpec = tcbKM.getparamSpec();
524   
525  4 readTCBContent(trustedLocation);
526   
527  4 if ( (previousLogFilenameFromLogRoot == null) && (currentInspectionLogFilename == null) ) {
528  1 String[] options = { "OK", "NO-ABORT" };
529  1 int selection = this.createConfirmCallback("This is the first time that SAWS has been started.",
530    options, SAWSChoiceCallback.WARNING, "FirstTimeInitialization");
531  1 if (selection == 1 ) {
532  0 System.exit(-1);
533    }
534    }
535   
536  4 latestLogFilename = lfc.generateNewLogFileName();
537  4 currentLogFileWriter = new LogFileWriter(logFileRoot, latestLogFilename,
538    tcbKM.getvtEncryptionPublicKey(),
539    tcbKM.getsawsEncryptionPublicKey(),
540    tcbKM.getsawsSigningPrivateKey(),
541    tcbKM.getbaSigningPublicKeyCert(),
542    this.hashAlgorithm,
543    null,
544    UserIDPKMap, this.callbackHandler);
545  4 currentLogFileWriter.setDebugLevel(debugLevel);
546  4 int ret = currentLogFileWriter.prepareNewLog();
547  4 if (ret != 0) {
548  0 System.exit(-1);
549    }
550  4 tcbContent = new TCBContentRW(trustedLocation, sawsTCBSecretKey, paramSpec,
551    debugLevel, this.callbackHandler);
552  4 tcbContent.setTCBContent(latestLogFilename, currentLogFileWriter.getCurrentRecordWriteCount(),
553    currentLogFileWriter.getAccHash());
554  4 int result = tcbContent.write();
555  4 if (result != 0) {
556  0 this.showMessage("SAWS cannot write to TCB correctly."
557    + "\nSAWS will stop.\n", SAWSTextOutputCallback.WARNING);
558  0 closeLog();
559  0 System.exit(-1);
560    }
561   
562  4 if ( (previousLogFilenameFromLogRoot == null) && (currentInspectionLogFilename == null) ) {
563  1 currentLogFileWriter.createLastFileRecord("This is the very first SAWS log file.",
564    "null".getBytes(), "null".getBytes() );
565   
566  3 } else if ( (previousLogFilenameFromLogRoot != null) && (currentInspectionLogFilename == null ) ) {
567   
568    // there are logs, but TCBLocation is missing
569  0 logFileList.addElement(previousLogFilenameFromLogRoot); // log file no.0
570  0 currentLogFileWriter.createSAWSRecord(("" + SAWSConstant.TrustedLocationMissingErrCode +
571    "; Trusted Location is missing and reconstructed." ).getBytes(),
572    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
573   
574  0 currentInspectionLogFilename = previousLogFilenameFromLogRoot;
575  0 verifyOneLogFile(logFileRoot, currentInspectionLogFilename);
576  0 currentLogFileWriter.createLastFileRecord(currentInspectionLogFilename, currentInspecitonAccHash,
577    currentInspectionSignature);
578  0 currentInspectionLogFilename = previousLogFilenameFromLogRecord;
579  0 verifyLogFileChainWithPrompt(logFileRoot, currentInspectionLogFilename);
580   
581  3 } else if ( currentInspectionLogFilename != null ) {
582    // the previous log file exists
583  3 logFileList.addElement(currentInspectionLogFilename); //log file no.0
584  3 verifyOneLogFile(logFileRoot, currentInspectionLogFilename);
585  3 currentLogFileWriter.createLastFileRecord(currentInspectionLogFilename, currentInspecitonAccHash,
586    currentInspectionSignature);
587  3 currentInspectionLogFilename = previousLogFilenameFromLogRecord;
588  3 verifyLogFileChainWithPrompt(logFileRoot, currentInspectionLogFilename);
589    }
590    }
591   
592    /**
593    * This method is to start SAWSServer to record client records.
594    *
595    * @param null
596    *
597    * @return null
598    */
 
599  4 toggle public void sawsStart() {
600  4 if ( debugLevel> SAWSConstant.VerboseInfo && logFileList.size() != 0 ) {
601  0 for (int i = logFileList.size()-1; i>=0 ; --i ) {
602  0 String logFilename = (String) logFileList.get(i);
603    //adding log4j logging
604  0 sawsDebugLog.write(logFilename);
605    }
606    }
607   
608  4 if (this.closed) {
609  0 this.showMessage("SAWS log file is already closed. SAWS have to be initialized again.",
610    SAWSTextOutputCallback.WARNING);
611  0 if ( debugLevel > SAWSConstant.NoInfo) {
612  0 sawsDebugLog.write("SAWS log file is already closed when trying to start SAWS.");
613    }
614    }
615   
616  4 String[] options = { "Yes, continue", "No, stop SAWS" };
617   
618  4 int selection = this.createConfirmCallback("SAWS has finished its initilisation process. "
619    + "\nNow SAWS can start to record client log records. Do you want to continue? \n",
620    options, SAWSChoiceCallback.WARNING, "StartRecordingLogs");
621  4 if (selection == 1) {
622  0 closeLog();
623  0 System.exit(-1);
624    }
625    // Start the thread
626  4 thread = new WritingThread();
627  4 thread.start();
628   
629  4 currentTime = System.currentTimeMillis();
630  4 if (heartbeatInterval != 0) {
631  4 setHeartbeatWriter(heartbeatInterval);
632    }
633   
634    }
635   
636    /**
637    * This method is to read the trusted location, to get the latest log filename, SN, AccHash
638    *
639    * @param String trustedLocation
640    *
641    * @return null
642    */
 
643  4 toggle private void readTCBContent(String trustedLocationLocal){
644  4 if (trustedLocationLocal == null) {
645   
646  0 this.showMessage("The trustedLocation is not present in the SAWS configuration file."
647    + "\nPlease set it correctly in the SAWS configuration file. \n"
648    + "\nSAWS will now stop.", SAWSTextOutputCallback.WARNING);
649  0 System.exit(-1);
650    }
651   
652  4 File TCBFile = new File(trustedLocationLocal);
653  4 lfc = new LogFilenameClass();
654  4 if (!TCBFile.exists()) { // TrustedLocation does not exist
655  1 String[] options = { "Create Trusted Location", "Stop SAWS", "Rebuild Trusted Location" };
656  1 int selection = this.createConfirmCallback(
657    "SAWS cannot find the Trusted Location."
658    + "\n\nOption 1: A Trusted Location does not exist because this is the first time SAWS has been started. "
659    + "\nSAWS should create a new Trusted Location. "
660    + "\nOption 2: The Trusted Location has been lost due to computer failure, or the configuration file is wrong. "
661    + "\nSAWS should stop and then be manually restarted."
662    + "\nOption 3: The Trusted Location has been lost due to a compromise or computer failure. "
663    + "\nSAWS should try to rebuild it.", options,
664    SAWSChoiceCallback.WARNING, "TrustedLocationNotFound");
665  0 if (selection == 1) System.exit(-1);
666   
667  1 if (selection == 2 ) { // option 3: TrustedLocation reconstruct, old log may exist
668    //Now keep the latest logname found in the log root as currentInspectionLogFilename
669  0 previousLogFilenameFromLogRoot = lfc.findLatestLogFileName(logFileRoot);
670  0 currentInspectionLogFilename = null;
671  0 AccHashFromTCB = null; // for the rest of the logs, don't compare SN with TCBLocation
672    }
673  1 if (selection == 0 ) { // option 1: TrustedLocation to be reconstructed, old log not exists
674  1 previousLogFilenameFromLogRoot = null;
675  1 currentInspectionLogFilename = null;
676  1 AccHashFromTCB = null;
677    }
678   
679   
680    } else { // TrustedLocation exists
681  3 previousLogFilenameFromLogRoot = lfc.findLatestLogFileName(logFileRoot);
682  3 tcbContent = new TCBContentRW(trustedLocationLocal, sawsTCBSecretKey,
683    paramSpec, debugLevel, this.callbackHandler);
684  3 int ret = tcbContent.read();
685  3 if (ret !=0 ) { //TCBLocation exists but is broken
686  0 String[] options = { "SAWS Stop", "Rebuild TCBLocation" };
687   
688  0 int selection = this.createConfirmCallback(
689    "Data corruption for the Trusted Location. "
690    + "\nOption 1: The Trusted Location has been tampered with. "
691    + "\nSAWS should stop and then the administrator needs to investigate it manually."
692    + "\nOption 2: SAWS will rebuild the Trusted Location.",
693    options, SAWSChoiceCallback.WARNING, "TrustedLocationDataCorruption");
694  0 if (selection == 0 ) System.exit(-1);
695  0 if (selection == 1) { // TrustedLocation to be reconstructed, old log may exist
696  0 previousLogFilenameFromLogRoot = lfc.findLatestLogFileName(logFileRoot);
697  0 currentInspectionLogFilename = null;
698  0 AccHashFromTCB = null; // for the rest of the logs, don't compare SN with TCBLocation
699    }
700   
701    } else { // TCBLocation exists and read fine
702  3 currentInspectionLogFilename= tcbContent.getLastFilename();
703  3 SNFromTCB = tcbContent.getLastSN();
704  3 AccHashFromTCB = tcbContent.getLastAccHash();
705   
706  3 File cLogFile = new File(logFileRoot, currentInspectionLogFilename );
707   
708  3 if ( !cLogFile.exists() ) {
709  0 String[] options = { "Stop", "Continue"};
710   
711  0 int selection = this.createConfirmCallback(
712    "SAWS cannot find the current log file for verification: " + currentInspectionLogFilename
713    + " \n\nOption 1: The current log file is missing because of tampering. "
714    + "\nSAWS will stop and the SAWS administrator needs to check it manually. "
715    + "\nOption 2: The current log file is missing because of tampering or computer failure. "
716    + "\nSAWS will continue to verify the next previous file. ",
717    options, SAWSChoiceCallback.WARNING, "MissingCurrentVerifyingLogFile");
718   
719  0 if (selection == 0)
720  0 System.exit(-1);
721  0 if (selection == 1) {
722  0 currentInspectionLogFilename = previousLogFilenameFromLogRoot;
723    }
724   
725    }
726    }
727    }
728    }
729   
730   
731   
732    /**
733    * This method simply pickup all the previous log file names one by one through the log file
734    * chain.
735    *
736    * @param String logFileRoot the log file root
737    * @param String cLogFileName the current log file name in the log file chain
738    *
739    * @return null
740    */
 
741  0 toggle private void pickupAllPreviousLogFileNames(String logFileRoot, String cLogFileName) {
742  0 currentInspectionLogFilename = cLogFileName;
743  0 while ( currentInspectionLogFilename != null ){ // previousLogFilenameFromLogRoot
744  0 File logF = new File(logFileRoot, currentInspectionLogFilename);
745  0 if ( logF.exists()) {
746  0 pickupOnePreviousLogFileName(logFileRoot, currentInspectionLogFilename);
747  0 currentInspectionLogFilename = previousLogFilenameFromLogRecord;
748    } else {
749  0 this.showMessage("SAWS cannot find the previous log file for reading: " + currentInspectionLogFilename
750    + " \n\nSAWS will stop and the SAWS administrator needs to restart SAWS to check it. ",
751    SAWSTextOutputCallback.WARNING);
752  0 currentLogFileWriter.createSAWSRecord(("" + SAWSConstant.LogFileMissingErrCode +
753    ";" + currentInspectionLogFilename +
754    ";This log file is missing." ).getBytes(),
755    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
756  0 closeLog();
757  0 System.exit(-1);
758    }
759    }
760    }
761   
762   
763    /**
764    * This method simply pickup the previous log file name from the current log file.
765    * The previous log file name is stored in Vector logFileList.
766    *
767    * @param String logFileRoot the log file root
768    * @param String cLogFileName the current log file name in the log file chain
769    *
770    * @return null
771    */
 
772  0 toggle private void pickupOnePreviousLogFileName(String logFileRoot, String inspectLogFile) {
773  0 String cLogFilename = inspectLogFile;
774  0 LogFileReader rr = new LogFileReader(debugLevel, this.callbackHandler);
775  0 rr.setSAWSPrivateKey(tcbKM.getsawsEncryptionPrivateKey());
776  0 try {
777  0 rr.setLogFilename(logFileRoot, cLogFilename);
778    } catch (logReadingException e) {
779   
780  0 this.showMessage("The error for the log file " + cLogFilename + " is: "
781    + SAWSConstant.getErrorString(e.getErrorCode())
782    + "\n\nThis log file cannot be read. "
783    + "\nSAWS will stop. Please restart SAWS to check it. ",
784    SAWSTextOutputCallback.WARNING);
785  0 closeLog();
786  0 System.exit(-1);
787    }
788  0 byte[] secureRandomB = null;
789  0 try{
790  0 try{
791  0 secureRandomB = rr.getSecureRandomNumber(tcbKM.getsawsEncryptionPrivateKey());
792    } catch (logReadingException secureHashError){
793  0 secureHashError.setErrorCode(SAWSConstant.SecureRandomRecordErrCode);
794  0 throw secureHashError;
795    }
796  0 previousLogFilenameFromLogRecord = rr.findPreviousLogfileName(secureRandomB);
797    //find the next log file to be inspected
798  0 if (previousLogFilenameFromLogRecord!=null ) {
799  0 logFileList.addElement(previousLogFilenameFromLogRecord); // log file no.?
800    }
801   
802    } catch (logReadingException e){
803   
804  0 this.showMessage("The error for the log file " + cLogFilename + " is: "
805    + SAWSConstant.getErrorString(e.getErrorCode())
806    + "\n\nThis log file has been tampered with and it cannot be read. "
807    + "\nSAWS will stop. Please restart SAWS to check it. ",
808    SAWSTextOutputCallback.WARNING);
809  0 closeLog();
810  0 System.exit(-1);
811    }
812   
813  0 return;
814    }
815   
816    /**
817    * This method is to verify the log file chain with prompts to allow SAWS administrator to decide
818    * whether to verify the log files or not
819    *
820    * @param String logFileRoot the log file root
821    * @param String cLogFileName the first log file in the log file chain
822    *
823    */
 
824  3 toggle private void verifyLogFileChainWithPrompt(String logFileRoot, String cLogFileName) {
825  3 currentInspectionLogFilename = cLogFileName;
826  3 AccHashFromTCB = null; // for the rest of the logs, don't compare SN in log with SN in TCBLocation
827  3 boolean inspectAll = false;
828  14 while ( currentInspectionLogFilename != null ){ // previousLogFilenameFromLogRoot
829   
830  11 int selection = 0;
831  11 if ( !inspectAll ) {
832  3 String[] options = { "No", "Check it", "Check all" };
833   
834  3 selection = this.createConfirmCallback(
835    "This log file: " + currentInspectionLogFilename + " was created by SAWS before."
836    + " Do you want SAWS to check it? "
837    + "\n\nOption 1: No, SAWS will ignore the log file and start to record client records."
838    + "\nOption 2: Yes, SAWS will check this log file only"
839    + "\nOption 3: SAWS will check this log file and all previous log files "
840    + "linked by this log file.", options,
841    SAWSChoiceCallback.WARNING, "CheckExistingLogFile");
842   
843   
844  3 if (selection == 0) {
845  0 pickupAllPreviousLogFileNames(logFileRoot, currentInspectionLogFilename);
846  0 return;
847    }
848  3 if (selection == 2)
849  3 inspectAll = true;
850    }
851   
852  11 File logF = new File(logFileRoot, currentInspectionLogFilename);
853  11 if ( logF.exists()) {
854  11 verifyOneLogFile(logFileRoot, currentInspectionLogFilename);
855  11 currentInspectionLogFilename = previousLogFilenameFromLogRecord;
856    } else {
857  0 String[] options = { "Stop", "Continue" };
858   
859  0 selection = this.createConfirmCallback(
860    "SAWS cannot find the log file for verification: " + currentInspectionLogFilename + "."
861    + "\n\nOption 1: This log file is missing because of tampering. "
862    + "\nSAWS will stop and the SAWS administrator needs to check it manually. "
863    + "\nOption 2: The current log file is missing because of tampering or computer failure. "
864    + "\nSAWS will continue to verify the next previous file. ",
865    options, SAWSChoiceCallback.WARNING, "CheckExistingLogFile");
866   
867   
868  0 currentLogFileWriter.createSAWSRecord(("" + SAWSConstant.LogFileMissingErrCode +
869    ";" + currentInspectionLogFilename + ";" + selection +
870    ";This log file is missing." ).getBytes(),
871    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
872  0 if (selection == 0){
873  0 closeLog();
874  0 System.exit(-1);
875    }
876  0 if (selection == 1) {
877  0 currentInspectionLogFilename =
878    lfc.getPreviousLogFilename(logFileRoot, currentInspectionLogFilename);
879    }
880   
881    }
882    }
883   
884    }
885   
886    /**
887    * This method verifies a given log file. After it is invoked, recordBlockListFromOneLogFile will be filled with the log records from the log file.
888    *
889    * @param logFileRoot String is the log file root.
890    * @param inspectLogFile String is the inspection log file name.
891    *
892    * @return int 0: verify OK; otherwise: some error found
893    */
 
894  28 toggle private int verifyOneLogFile(String logFileRoot, String inspectLogFile){
895  28 String cLogFilename = inspectLogFile;
896  28 LogFileReader rr = new LogFileReader(debugLevel, this.callbackHandler);
897  28 rr.setSAWSPrivateKey(tcbKM.getsawsEncryptionPrivateKey());
898   
899  28 try {
900  28 rr.setLogFilename(logFileRoot, cLogFilename);
901    } catch (logReadingException e) {
902    /*
903    Object[] options = { "Stop" };
904    int selection = JOptionPane.showOptionDialog(null,
905    "The error for the log file " + cLogFilename + " is: "
906    + SAWSConstant.getErrorString(e.getErrorCode()) +
907   
908    "\n\nThis log file cannot be read. " +
909    "\nSAWS will stop. Please restart SAWS to check it. ",
910    "Warning",
911    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
912    null, options, options[0]);
913    */
914  0 this.showMessage("The error for the log file " + cLogFilename + " is: "
915    + SAWSConstant.getErrorString(e.getErrorCode())
916    + "\n\nThis log file cannot be read. "
917    + "\nSAWS will stop. Please restart SAWS to check it. ",
918    SAWSTextOutputCallback.WARNING);
919  0 closeLog();
920  0 System.exit(-1);
921    }
922  28 byte[] secureRandomB = null;
923  28 try{
924  28 try{
925  28 secureRandomB = rr.getSecureRandomNumber(tcbKM.getsawsEncryptionPrivateKey());
926    } catch (logReadingException secureRandomError){
927  0 secureRandomError.setErrorCode(SAWSConstant.SecureRandomRecordErrCode);
928  0 throw secureRandomError;
929    }
930  28 rr.checkLogFile(secureRandomB);
931  28 rr.checkSignature(tcbKM.getrootCAPublicKey());
932  28 recordBlockListFromOneLogFile = rr.getRecordBlockList();
933  28 int currentRecordWriteCount = rr.getCurrentSN();
934  28 currentInspecitonAccHash = rr.getAccumulatedHashFromLog();
935  28 currentInspectionSignature = rr.getSignatureFromLog();
936  28 if ( AccHashFromTCB != null) { // if Trusted Location is OK, then compare SN in log with SN in TCBLocation
937  3 if(SNFromTCB != currentRecordWriteCount ){
938  0 String[] options = { "Stop", "Continue after tampering", "Continue after crash" };
939   
940  0 int selection = this.createConfirmCallback(
941    "The last sequence number " + currentRecordWriteCount + " of the log file " + cLogFilename
942    + "\nis not equal to the last sequence number " + SNFromTCB + " in the Trusted Location"
943    + "\n\nOption 1: Either the log file or the Trusted Location has been tampered with. "
944    + "\nSAWS will stop and the SAWS administrator needs to check it manually."
945    + "\nOption 2: Either the log file or the Trusted Location has been tampered with, "
946    + "\nSAWS will record this incident, update the Trusted Location and continue."
947    + "\nOption 3: This error is due to computer crash. "
948    + "\nSAWS will record this incident, update the Trusted Location and continue.",
949    options, SAWSChoiceCallback.WARNING, "SequenceNumberDifferentFromTCB");
950   
951    /*int selection = JOptionPane.showOptionDialog(null,
952    "The last sequence number " + currentRecordWriteCount + " of the log file " + cLogFilename +
953    "\nis not equal to the last sequence number " + SNFromTCB + " in the Trusted Location" +
954    "\n\nOption 1: Either the log file or the Trusted Location has been tampered with. " +
955    "\nSAWS will stop and the SAWS administrator needs to check it manually." +
956    "\nOption 2: Either the log file or the Trusted Location has been tampered with, " +
957    "\nSAWS will record this incident, update the Trusted Location and continue." +
958    "\nOption 3: This error is due to computer crash. " +
959    "\nSAWS will record this incident, update the Trusted Location and continue.",
960    "Warning",
961    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
962    null, options, options[0]);*/
963  0 currentLogFileWriter.createSAWSRecord(
964    ("" + SAWSConstant.SNNotMatchBetweenLogAndTCBLocationErrCode +
965    ";" + cLogFilename + ";" + currentRecordWriteCount + ";" + SNFromTCB +
966    ";" + selection +";Sequence number does not match." ).getBytes(),
967    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
968  0 if (selection == 0) {
969  0 closeLog();
970  0 System.exit(-1);
971    }
972    }
973   
974  3 if ( utility.toHexString(AccHashFromTCB).compareTo(
975    utility.toHexString(currentInspecitonAccHash)) != 0 ) {
976  0 String[] options = { "Stop", "Continue after tampering", "Continue after crash" };
977   
978  0 int selection = this.createConfirmCallback(
979    "The accumulated hash of the log file " + cLogFilename
980    + "is not equal to the one in the Trusted Location"
981    + "\n\nOption 1: Either the log file or the Trusted Location has been tampered with. "
982    + "\nSAWS will stop and the SAWS administrator needs to check it manually."
983    + "\nOption 2: Either the log file or the Trusted Location has been tampered with, "
984    + "\nSAWS will record this incident, update the Trusted Location and continue."
985    + "\nOption 3: This error is due to computer crash. "
986    + "\nSAWS will record this incident, update the Trusted Location and continue.",
987    options, SAWSChoiceCallback.WARNING, "AccHashDifferentFromTCB");
988   
989    /*int selection = JOptionPane.showOptionDialog(null,
990    "The accumulated hash of the log file " + cLogFilename +
991    "is not equal to the one in the Trusted Location" +
992    "\n\nOption 1: Either the log file or the Trusted Location has been tampered with. " +
993    "\nSAWS will stop and the SAWS administrator needs to check it manually." +
994    "\nOption 2: Either the log file or the Trusted Location has been tampered with, " +
995    "\nSAWS will record this incident, update the Trusted Location and continue." +
996    "\nOption 3: This error is due to computer crash. " +
997    "\nSAWS will record this incident, update the Trusted Location and continue.",
998    "Warning",
999    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
1000    null, options, options[0]);*/
1001  0 currentLogFileWriter.createSAWSRecord(
1002    ("" + SAWSConstant.AccHashNotMatchBetweenLogAndTCBLocationErrCode +
1003    ";" + cLogFilename + ";" + utility.toHexString(currentInspecitonAccHash) + ";" +
1004    utility.toHexString(AccHashFromTCB) +
1005    ";" + selection +";accumualted hash does not match." ).getBytes(),
1006    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
1007  0 if (selection == 0) {
1008  0 closeLog();
1009  0 System.exit(-1);
1010    }
1011   
1012    }
1013    }
1014  28 previousLogFilenameFromLogRecord = rr.getPreviousLogfileName();
1015    //find the next log file to be inspected
1016   
1017    } catch (logReadingException e){
1018  0 if ( e.getErrorCode() != SAWSConstant.LogFileIncompleteErrCode ) { // log cannot be recovered
1019  0 String[] options = { "Stop", "Continue after tampering", "Continue after crash" };
1020   
1021  0 int selection = this.createConfirmCallback(
1022    "The error for the log file " + cLogFilename + " is: "
1023    + SAWSConstant.getErrorString(e.getErrorCode())
1024    + "\n\nOption 1: This log file has been tampered with and it cannot be recovered. "
1025    + "\nSAWS will record this incident and stop."
1026    + "The SAWS administrator needs to check it manually."
1027    + "\nOption 2: The log file has been tampered with. SAWS will record this incident and continue."
1028    + "\nOption 3: This error is due to computer crash. SAWS will record this incident and continue. ",
1029    options, SAWSChoiceCallback.WARNING, "CannotRecoverLogFile");
1030   
1031    /*int selection = JOptionPane.showOptionDialog(null,
1032    "The error for the log file " + cLogFilename + " is: "
1033    + SAWSConstant.getErrorString(e.getErrorCode()) +
1034   
1035    "\n\nOption 1: This log file has been tampered with and it cannot be recovered. " +
1036    "\nSAWS will record this incident and stop." +
1037    "The SAWS administrator needs to check it manually." +
1038    "\nOption 2: The log file has been tampered with. SAWS will record this incident and continue." +
1039    "\nOption 3: This error is due to computer crash. SAWS will record this incident and continue. " ,
1040    "Warning",
1041    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
1042    null, options, options[0]); */
1043  0 currentLogFileWriter.createSAWSRecord(
1044    ("" + e.getErrorCode() +
1045    ";" + cLogFilename + ";" + selection + ";" + e.getSequence() +";" +
1046    SAWSConstant.getErrorString(e.getErrorCode()) ).getBytes(),
1047    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
1048  0 if (selection == 0) {
1049  0 closeLog();
1050  0 System.exit(-1);
1051    }
1052  0 currentInspecitonAccHash = "error".getBytes(); // for forming LastLogFileRecord
1053  0 currentInspectionSignature = "error".getBytes(); // for forming LastLogFileRecord
1054  0 previousLogFilenameFromLogRecord =
1055    lfc.getPreviousLogFilename(logFileRoot, cLogFilename);
1056    //find the next log file to be inspected
1057    //System.out.println("*********************" + previousLogFilenameFromLogRecord );
1058    }
1059   
1060  0 if ( e.getErrorCode() == SAWSConstant.LogFileIncompleteErrCode ) { //only this type of error will be recovered
1061  0 String[] options = { "Stop", "Recover this log", "Ignore this log" };
1062   
1063  0 int selection = this.createConfirmCallback(
1064    "The error for the log file " + cLogFilename + " is: "
1065    + SAWSConstant.getErrorString(e.getErrorCode())
1066    + "\n\nOption 1: This log file has been tampered with. "
1067    + "\nSAWS will record this incident and stop."
1068    + "The SAWS administrator needs to check it manually."
1069    + "\nOption 2: This error is a computer crash. SAWS will recover this log file and continue."
1070    + "\nOption 3: SAWS will ignore this log and continue. ",
1071    options, SAWSChoiceCallback.WARNING, "ReadingLogFileError");
1072   
1073    /*int selection = JOptionPane.showOptionDialog(null,
1074    "The error for the log file " + cLogFilename + " is: "
1075    + SAWSConstant.getErrorString(e.getErrorCode()) +
1076   
1077    "\n\nOption 1: This log file has been tampered with. " +
1078    "\nSAWS will record this incident and stop." +
1079    "The SAWS administrator needs to check it manually." +
1080    "\nOption 2: This error is a computer crash. SAWS will recover this log file and continue." +
1081    "\nOption 3: SAWS will ignore this log and continue. " ,
1082    "Warning",
1083    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
1084    null, options, options[0]); */
1085  0 currentLogFileWriter.createSAWSRecord(
1086    ("" + e.getErrorCode() +
1087    ";" + cLogFilename + ";" + selection + ";" + e.getSequence() +";" +
1088    SAWSConstant.getErrorString(e.getErrorCode()) ).getBytes(),
1089    SAWSConstant.SysAuditorNotificationType, SAWSConstant.NoEncryptionFlag);
1090  0 if (selection == 0) {
1091  0 closeLog();
1092  0 System.exit(-1);
1093    }
1094  0 if (selection == 1) {
1095  0 LogFileWriter repairWriter = new LogFileWriter(logFileRoot, cLogFilename,
1096    tcbKM.getvtEncryptionPublicKey(),
1097    tcbKM.getsawsEncryptionPublicKey(),
1098    tcbKM.getsawsSigningPrivateKey(),
1099    tcbKM.getbaSigningPublicKeyCert(),
1100    this.hashAlgorithm, //signingAlg, //"SHA1WITHRSA", //tcbKM.getsigningAlgName(),
1101    secureRandomB,
1102    null );
1103  0 int ret = repairWriter.repairLog(logFileRoot, cLogFilename, secureRandomB, e);
1104  0 currentInspecitonAccHash = repairWriter.getAccHash(); // for forming LastLogFileRecord
1105  0 currentInspectionSignature = repairWriter.getSignature(); // for forming LastLogFileRecord
1106  0 previousLogFilenameFromLogRecord =
1107    lfc.getPreviousLogFilename(logFileRoot, cLogFilename);
1108    //find the next log file to be inspected
1109  0 if (ret !=0) {
1110  0 return -1;
1111    }
1112    }
1113  0 if (selection == 2) {
1114  0 currentInspecitonAccHash = "error".getBytes(); // for forming LastLogFileRecord
1115  0 currentInspectionSignature = "error".getBytes(); // for forming LastLogFileRecord
1116  0 previousLogFilenameFromLogRecord =
1117    lfc.getPreviousLogFilename(logFileRoot, cLogFilename);
1118    //find the next log file to be inspected
1119    }
1120   
1121    }
1122   
1123    }
1124   
1125  28 if (previousLogFilenameFromLogRecord!=null && currentReadingFileNo==0 ) {
1126    //currentReadingFileNo==0 means it is still backward checking log files,
1127    // not forward reading log files, so this log file should be recorded.
1128  11 logFileList.addElement(previousLogFilenameFromLogRecord); // log file no.?
1129    }
1130  28 return 0;
1131    }
1132   
1133    /**
1134    * This method is to read saws log files one at a time from the first log file to the last log file
1135    * in the log file list logFileList. So you can invoke it again and again unitl null is returned.
1136    *
1137    * @param null
1138    *
1139    * @return Vector the Vector of log records
1140    */
 
1141  18 toggle public Vector sawsReadOneLogFile() {
1142  18 if (currentReadingFileNo == logFileList.size()){
1143  4 return null;
1144    }
1145   
1146  14 verifyOneLogFile( logFileRoot, (String) logFileList.get(logFileList.size()- 1 - (currentReadingFileNo++) ) );
1147   
1148  14 return recordBlockListFromOneLogFile;
1149    }
1150   
1151    /**
1152    * This method closes the current log file.
1153    */
 
1154  4 toggle public void closeLog(){
1155  4 if (this.tt2 != null) {
1156  4 ((HeartbeatRecordWriting)this.tt2).setStop(true);
1157  4 timer.cancel();
1158    }
1159  4 currentLogFileWriter.finalizeLogFile();
1160  4 tcbContent.setTCBContent(latestLogFilename, currentLogFileWriter.getCurrentRecordWriteCount(),
1161    currentLogFileWriter.getAccHash());
1162  4 int result = tcbContent.write();
1163  4 if (result != 0) {
1164    /*
1165    Object[] options = { "STOP" };
1166    int selection = JOptionPane.showOptionDialog(null,
1167    "SAWS cannot write to TCB correctly. " +
1168    "\nSAWS will stop. \n",
1169    "Warning",
1170    JOptionPane.DEFAULT_OPTION, JOptionPane.WARNING_MESSAGE,
1171    null, options, options[0]);
1172    */
1173  0 this.showMessage("SAWS cannot write to TCB correctly. " +
1174    "\nSAWS will stop. \n", SAWSTextOutputCallback.WARNING);
1175  0 System.exit(-1);
1176    }
1177  4 this.closed = true;
1178   
1179    }
1180   
1181   
1182    /**
1183    * This method is used by the SAWS API client to send a log message to SAWS server.
1184    * No encryption is used by this method.
1185    *
1186    * @param messageBlock is the log message to be sent.
1187    * @return The status of the record (RecordStatus).
1188    */
 
1189  65 toggle public RecordStatus sendLogRecord(byte[] messageBlock) {
1190  65 byte flag;
1191  65 if ( (logEncryption == null) || (logEncryption.compareTo("no")==0 ) ) {
1192  0 flag = (byte) SAWSConstant.NoEncryptionFlag;
1193    } else {
1194  65 flag = (byte) SAWSConstant.SymmetricEncryptionFlag;
1195    }
1196  65 return sendLogRecord( messageBlock, flag );
1197    }
1198   
1199    /**
1200    * This method is used by the SAWS API client to send a log message to SAWS server.
1201    * Since this log message is coming from a SAWS client, so the log message type is certainly
1202    * SAWSClientLogDataType.
1203    *
1204    * @param messageBlock is the log message to be sent.
1205    * @param encryptionFlag encryption flag to indicate the encryption requirement.
1206    * SAWSConstant.NoEncryptionFlag: log with no encryption;
1207    * SAWSConstant.SymmetricEncryptionFlag: log with symmetric encryption;
1208    * SAWSConstant.CommandFlag: command for SAWS to perform: the command contents are contained in messageBlock.
1209    *
1210    * @return The status of the record (RecordStatus).
1211    */
 
1212  65 toggle public RecordStatus sendLogRecord(byte[] messageBlock, byte encryptionFlag ){
1213  65 if (this.closed) {
1214  0 return new RecordStatus(-1, SAWSConstant.LogFileClosed);
1215    }
1216   
1217  65 if ( (encryptionFlag != SAWSConstant.NoEncryptionFlag) &&
1218    (encryptionFlag != SAWSConstant.SymmetricEncryptionFlag) &&
1219    (encryptionFlag != SAWSConstant.CommandFlag)) {
1220  0 return new RecordStatus(-1, SAWSConstant.InvalidEncryptionFlag);
1221    }
1222   
1223  65 String mBlock = new String(messageBlock);
1224  65 if ( (encryptionFlag == (byte)SAWSConstant.CommandFlag) && (mBlock.compareTo("closeLogFile") == 0) ) {
1225    //This function is reserved for future use.
1226  0 while ( (busyFlag0V == true ) || (busyFlag1V == true ) ) {
1227  0 if (debugLevel > SAWSConstant.NoInfo)
1228  0 System.err.println("wait............."); // wait until all records are written
1229    }
1230  0 currentLogFileWriter.finalizeLogFile();
1231  0 tcbContent.setTCBContent(latestLogFilename, currentLogFileWriter.getCurrentRecordWriteCount(),
1232    currentLogFileWriter.getAccHash());
1233  0 tcbContent.write();
1234  0 this.closed = true;
1235  0 System.exit(0);
1236    }
1237   
1238  65 byte userID = (byte)0x00;
1239  65 String userdn = null;
1240  65 if ( SAWSInterface.compareTo("webservice") == 0 ) {
1241  0 userdn = getSSLDN();
1242  0 Byte B1 = (Byte) UserDNIDMap.get(userdn) ;
1243  0 if (B1 == null)
1244  0 return new RecordStatus(-1, SAWSConstant.UnauthorizedUser); // this user is not listed in the saws.xml and therefore not allowed to use this SAWS server
1245  0 userID = (byte) (B1.byteValue());
1246    // to get the user ID for web services incoming request
1247    }
1248   
1249  65 if ( busyFlag0V == false) {
1250  64 if (debugLevel > SAWSConstant.NoInfo) {
1251  0 sawsDebugLog.write("\nThis is in sending thread when busyFlag0V == false");
1252    }
1253  64 busyFlag0V = true;
1254  64 WaitingRecordBlock wRecordBlock = new WaitingRecordBlock(messageBlock, SAWSConstant.SAWSClientLogDataType,
1255    encryptionFlag, userID);
1256  64 waitingRecordList0.addElement(wRecordBlock);
1257  64 busyFlag0V = false;
1258   
1259    } else {
1260  1 if (debugLevel > SAWSConstant.VerboseInfo) {
1261  0 sawsDebugLog.write("\nThis is in sending thread when busyFlag1V == false");
1262    }
1263  1 busyFlag1V = true;
1264  1 WaitingRecordBlock wRecordBlock = new WaitingRecordBlock(messageBlock, SAWSConstant.SAWSClientLogDataType,
1265    encryptionFlag, userID);
1266  1 waitingRecordList1.addElement(wRecordBlock);
1267  1 busyFlag1V = false;
1268   
1269    }
1270  1531445 while (writingHeartBeating) {}
1271  65 thread.run();
1272  65 return new RecordStatus(0, currentLogFileWriter.getCurrentRecordWriteCount());
1273    }
1274   
1275    /**
1276    * This method is used by the SAWS command line mode to output the PKC request file from
1277    * the signing keystore.
1278    */
 
1279  0 toggle public void outputPKCRequest() {
1280  0 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1281    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC,
1282    debugLevel, this.hashAlgorithm, this.callbackHandler);
1283  0 tcbKM.outputPKCRequest();
1284    }
1285   
1286    /**
1287    * This method is used by the SAWS command line mode to output the PKC
1288    * in the signing keystore.
1289    */
 
1290  1 toggle public void exportSigningPKC() {
1291  1 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1292    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
1293    this.hashAlgorithm, this.callbackHandler);
1294  1 tcbKM.exportSigningPKC();
1295    }
1296   
1297    /**
1298    * This method is used by the SAWS command line mode to create the encryption keystore
1299    *
1300    */
 
1301  1 toggle public void createEncryptionKeystore(){
1302  1 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1303    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
1304    this.hashAlgorithm, this.callbackHandler);
1305  1 tcbKM.createEncryptionKeystore();
1306    }
1307   
1308    /**
1309    * This method is used by the SAWS command line mode to create the signing keystore
1310    *
1311    */
 
1312  1 toggle public void createSigningKeystore(){
1313  1 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1314    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
1315    this.hashAlgorithm, this.callbackHandler);
1316  1 tcbKM.createSigningKeystore();
1317    }
1318   
1319    /**
1320    * This method is used by the SAWS command line mode to import the root CA PKC into the signing keystore
1321    *
1322    */
 
1323  1 toggle public void importRootCA(){
1324  1 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1325    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
1326    this.hashAlgorithm, this.callbackHandler);
1327  1 tcbKM.checkSigningKeystoreFile();
1328  1 tcbKM.importRootCA();
1329    }
1330   
1331    /**
1332    * This method is used by the SAWS command line mode to import the signing PKC which is issued by
1333    * root CA into the signing keystore
1334    *
1335    */
 
1336  0 toggle public void importSigningPKC(){
1337  0 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1338    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
1339    this.hashAlgorithm, this.callbackHandler);
1340  0 tcbKM.checkSigningKeystoreFile();
1341  0 tcbKM.importSigningPKC();
1342    }
1343   
1344    /**
1345    * This method is used by the SAWS command line mode to list all entries in the signing keystore
1346    *
1347    */
 
1348  0 toggle public void listSigningKeystore(){
1349  0 tcbKM = new TCBKeystoreManagement(signingKeystoreLocation, numberOfPasswordShares,
1350    encryptionKeystoreLocation, numberOfEncPasswordShares, rootCA, vtPKC, debugLevel,
1351    this.hashAlgorithm, this.callbackHandler);
1352  0 tcbKM.checkSigningKeystoreFile();
1353  0 tcbKM.listSigningKeystore();
1354    }
1355   
1356    /**
1357    * This method is to get the DN from the SSL certificate. It is only used in web services interfaces.
1358    *
1359    * @param null
1360    *
1361    * @return String the DN of the SSL certificate.
1362    */
 
1363  0 toggle private String getSSLDN() {
1364  0 String issuerDN = null;
1365  0 org.apache.axis.MessageContext mct = org.apache.axis.AxisEngine.getCurrentMessageContext();
1366  0 org.apache.axis.MessageContext context = mct.getCurrentContext();
1367  0 HttpServletRequest req =
1368    (HttpServletRequest) context.getProperty(
1369    org.apache.axis.transport.http.HTTPConstants.MC_HTTP_SERVLETREQUEST);
1370  0 String certAttribute = "javax.servlet.request.X509Certificate";
1371  0 java.security.cert.X509Certificate[] certificate =
1372    (java.security.cert.X509Certificate[]) req.getAttribute(certAttribute);
1373  0 if (certificate != null) {
1374  0 java.security.cert.X509Certificate certificateSource = certificate[0];
1375  0 if (certificateSource != null) {
1376    //issuerDN = certificateSource.getSubjectDN().getName();
1377  0 issuerDN = issrg.utils.RFC2253NameParser.toCanonicalDN(certificateSource.getSubjectDN().getName()).toUpperCase();
1378  0 if (debugLevel > SAWSConstant.NoInfo)
1379  0 sawsDebugLog.write("DN is: " + issuerDN);
1380    }
1381    } else {
1382  0 this.showMessage("Certificate is null.", SAWSTextOutputCallback.WARNING);
1383    //System.out.println("certificate is null.");
1384    }
1385   
1386  0 return issuerDN;
1387    }
1388   
1389    /**
1390    * This class is the writing thread of the SAWS server. It reads waitingRecordList0 and
1391    * waitingRecordList1 and write the record blocks in them into the current log file.
1392    *
1393    */
 
1394    class WritingThread extends Thread {
1395    WaitingRecordBlock wRecordBlock = new WaitingRecordBlock();
1396   
 
1397  97 toggle public void run() {
1398    //while(true)
1399    {
1400  97 if ( (busyFlag0V == false) && (waitingRecordList0.size() > 0 ) ){
1401  92 busyFlag0V = true;
1402  92 boolean done = false;
1403  184 while (waitingRecordList0.size() > 0 ) {
1404  92 if (debugLevel > SAWSConstant.NoInfo)
1405  0 System.out.println("this is in writing thread: " + recordCount);
1406  92 recordCount ++;
1407  92 wRecordBlock = (WaitingRecordBlock) waitingRecordList0.get(0);
1408  92 currentLogFileWriter.createSAWSRecord( wRecordBlock.messageBlock, wRecordBlock.recordType,
1409    wRecordBlock.userID, wRecordBlock.encryptionFlag, null);
1410  92 waitingRecordList0.remove(0);
1411  92 done = true;
1412    }
1413  92 if (done) { // if writing happens
1414  92 tcbContent.setTCBContent(latestLogFilename, currentLogFileWriter.getCurrentRecordWriteCount(),
1415    currentLogFileWriter.getAccHash());
1416  92 tcbContent.write();
1417   
1418  92 currentTime = System.currentTimeMillis();
1419   
1420  92 if (recordCount > signRecordNumber ){
1421  6 startANewLog();
1422    }
1423    }
1424  92 busyFlag0V = false;
1425    }
1426   
1427  97 if ( (busyFlag1V == false) && (waitingRecordList1.size() > 0 ) ){
1428  1 busyFlag1V = true;
1429  1 boolean done = false;
1430  2 while (waitingRecordList1.size() > 0 ) {
1431  1 if (debugLevel > SAWSConstant.NoInfo)
1432  0 System.out.println("this is in writing thread: " + recordCount);
1433  1 recordCount ++;
1434  1 wRecordBlock = (WaitingRecordBlock) waitingRecordList1.get(0);
1435  1 currentLogFileWriter.createSAWSRecord( wRecordBlock.messageBlock, wRecordBlock.recordType,
1436    wRecordBlock.userID, wRecordBlock.encryptionFlag, null);
1437  1 waitingRecordList1.remove(0);
1438  1 done = true;
1439    }
1440  1 if (done) { // if writing happens
1441  1 tcbContent.setTCBContent(latestLogFilename, currentLogFileWriter.getCurrentRecordWriteCount(),
1442    currentLogFileWriter.getAccHash());
1443  1 tcbContent.write();
1444  1 currentTime = System.currentTimeMillis();
1445   
1446  1 if (recordCount > signRecordNumber ){
1447  1 startANewLog();
1448    }
1449    }
1450  1 busyFlag1V = false;
1451    }
1452    // if ( (waitingRecordList0.size() == 0 ) &&
1453    // (waitingRecordList1.size() == 0 ) ) {
1454    // this.yield();
1455    // }
1456    }
1457    }
1458    }
1459   
1460    /**
1461    * This method is to close the current log file and then start a new log file.
1462    *
1463    */
 
1464  7 toggle private void startANewLog(){
1465  7 currentLogFileWriter.finalizeLogFile();
1466  7 currentInspecitonAccHash = currentLogFileWriter.getAccHash(); // for forming LastLogFileRecord
1467  7 currentInspectionSignature = currentLogFileWriter.getSignature(); // for forming LastLogFileRecord
1468  7 previousLogFilenameFromLogRecord = latestLogFilename; // for forming LastLogFileRecord
1469   
1470  7 latestLogFilename = lfc.generateNewLogFileName();
1471  7 currentLogFileWriter = new LogFileWriter(logFileRoot, latestLogFilename,
1472    tcbKM.getvtEncryptionPublicKey(),
1473    tcbKM.getsawsEncryptionPublicKey(),
1474    tcbKM.getsawsSigningPrivateKey(),
1475    tcbKM.getbaSigningPublicKeyCert(),
1476    this.hashAlgorithm, //signingAlg, //"SHA1WITHRSA", //tcbKM.getsigningAlgName(),
1477    null,
1478    UserIDPKMap, this.callbackHandler);
1479  7 currentLogFileWriter.setDebugLevel(debugLevel);
1480  7 int ret = currentLogFileWriter.prepareNewLog();
1481  7 if (ret != 0) {
1482  0 System.exit(-1);
1483    }
1484   
1485  7 currentLogFileWriter.createLastFileRecord(previousLogFilenameFromLogRecord, currentInspecitonAccHash,
1486    currentInspectionSignature);
1487   
1488  7 tcbContent.setTCBContent(latestLogFilename, currentLogFileWriter.getCurrentRecordWriteCount(),
1489    currentLogFileWriter.getAccHash());
1490  7 tcbContent.write();
1491  7 recordCount = 0;
1492    }
1493   
1494    /**
1495    * This sub class is for generating heartbeat records.
1496    */
1497   
 
1498    public class HeartbeatRecordWriting extends TimerTask{
1499    private volatile boolean stop = false;
1500   
 
1501  4 toggle public HeartbeatRecordWriting(){
1502    }
 
1503  44 toggle public void run(){
1504  44 if (!stop) {
1505  44 long t1 = System.currentTimeMillis();
1506  44 if (debugLevel > 0)
1507  0 System.out.println("In HeartbeatRecordWriting: busyFlag0V * busyFlag1V " + busyFlag0V + "*" + busyFlag1V );
1508  44 if ( (busyFlag0V== false) && (busyFlag1V== false) &&
1509    (heartbeatInterval>=5) && ( ( t1 - currentTime) >= heartbeatInterval-5) ) {
1510  28 writingHeartBeating = true;
1511  28 busyFlag0V = true;
1512  28 WaitingRecordBlock wRecordBlock = new WaitingRecordBlock(utility.longToByteArray(t1),
1513    SAWSConstant.SysHeartbeatType, SAWSConstant.NoEncryptionFlag, (byte)0x00);
1514  28 waitingRecordList0.addElement(wRecordBlock);
1515  28 busyFlag0V = false;
1516  28 currentTime = t1;
1517  28 thread.run();
1518  28 writingHeartBeating = false;
1519   
1520    }
1521    } else {
1522  0 this.cancel();
1523    }
1524    }
1525   
 
1526  4 toggle public void setStop(boolean stop) {
1527  4 this.stop = stop;
1528    }
1529    }
1530   
1531    /**
1532    * This method sets the heartbeat writer.
1533    *
1534    * @param null.
1535    */
 
1536  4 toggle private void setHeartbeatWriter(int interval){
1537  4 tt2 = new HeartbeatRecordWriting();
1538  4 timer = new java.util.Timer(true );
1539  4 timer.schedule(tt2, 1000, interval);
1540    }
1541   
1542    /**
1543    * Method to create the callback (SAWSTextOutputCallback) with the message to be
1544    * presented to the user and send it to the callback handler.
1545    *
1546    * @param message The message to be presented.
1547    * @param type The type of the message (SAWSTextOutputCallback.WARNING,
1548    * SAWSTextOutputCallback.ERROR, SAWSTextOutputCallback.INFORMATION)
1549    */
 
1550  0 toggle private void showMessage(String message, int type) {
1551  0 this.cbs = new Callback[1];
1552  0 this.cbs[0] = new SAWSTextOutputCallback(type, message);
1553  0 try {
1554  0 this.callbackHandler.handle(this.cbs);
1555    }
1556    catch (Exception e) {
1557  0 System.err.println(e.getMessage());
1558  0 sawsDebugLog.write(e);
1559    }
1560    }
1561   
1562    /**
1563    * Method that creates a callback (SAWSChoiceCallback) that asks the user
1564    * to choose one option, and sends it to the callback handler.
1565    *
1566    * @param prompt The message to be presented to the user.
1567    * @param options The available options for the user.
1568    * @param type The type of the callback (Warning, Information, etc.)
1569    *
1570    * @return the selected option.
1571    */
 
1572  9 toggle private int createConfirmCallback(String prompt, String[] options, int type, String key) {
1573  9 this.cbs = new Callback[1];
1574  9 this.cbs[0] = new SAWSChoiceCallback(prompt, options, key, 0, type);
1575  9 try {
1576  9 this.callbackHandler.handle(cbs);
1577    }
1578    catch (Exception e) {
1579  0 System.err.println(e.getMessage());
1580  0 sawsDebugLog.write(e);
1581    }
1582   
1583  9 return ((SAWSChoiceCallback)this.cbs[0]).getSelectedIndex();
1584    }
1585   
1586   
1587    /**
1588    * This main method is SAWS command-line working mode.
1589    */
 
1590  4 toggle public static void main(String[] args) throws Exception {
1591  4 System.out.println("Secure Audit Web-Service v" + version.getVersion());
1592   
1593  4 String sIn = null;
1594  4 try {
1595  4 if (args.length > 0) {
1596  4 sIn = args[0];
1597    } else {
1598  0 System.out.println("\nSAWS is now working in the keystore creation mode. Please select the following options:");
1599  0 System.out.println("\nOption 1: Create an encryption keystore." );
1600  0 System.out.println("\nOption 2: Create a signing keystore." );
1601  0 System.out.println("\nOption 3: Import the rootCA specified in the SAWS configuration file into the signing keystore. " +
1602    "This is required by keytool to be able to later import the PKC issued by this rootCA into the signing keystore." );
1603  0 System.out.println("\nOption 4: Output a PKC request file from the signing keystore." );
1604  0 System.out.println("\nOption 5: Input the PKC issued by the rootCA into the signing keystore." );
1605  0 System.out.println("\nOption 6: List all the entries in the signing keystore." );
1606  0 System.out.println("\nOption 7: Export the Signing PKC from the sining keystore." );
1607  0 System.out.println("\nOption 9: Test mode: SAWS will create a new log file and check old log files, then close the new log file. " +
1608    "This is for testing purposes. " );
1609  0 System.out.println("\n\nPlease input your choice (1, 2, 3, 4, 5, 6, 7 or 9) or any other input to stop: " );
1610  0 InputStreamReader is = new InputStreamReader(System.in);
1611  0 BufferedReader systemIn = new BufferedReader(is);
1612  0 sIn = systemIn.readLine();
1613    }
1614    //is.close();
1615    } catch (IOException e){
1616  0 e.printStackTrace(System.err);
1617  0 System.exit(-1);
1618    }
1619  4 if ( (sIn.compareTo("1") == 0) ) { // create an encryption keystore
1620  1 SAWSServer sw = new SAWSServer(0);
1621  1 sw.createEncryptionKeystore();
1622    }
1623   
1624  4 if ( (sIn.compareTo("2") == 0) ) { // create a signing keystore
1625  1 SAWSServer sw = new SAWSServer(0);
1626  1 sw.createSigningKeystore();
1627    }
1628   
1629  4 if ( (sIn.compareTo("3") == 0) ) { // create a signing keystore
1630  1 SAWSServer sw = new SAWSServer(0);
1631  1 sw.importRootCA();
1632    }
1633   
1634  4 if ( (sIn.compareTo("4") == 0) ) { // output siging public key PKC request
1635  0 SAWSServer sw = new SAWSServer(0);
1636  0 sw.outputPKCRequest();
1637    }
1638  4 if ( (sIn.compareTo("5") == 0) ) { // import saws PKC
1639  0 SAWSServer sw = new SAWSServer(0);
1640  0 sw.importSigningPKC();
1641    }
1642  4 if ( (sIn.compareTo("6") == 0) ) { // list saws PKC
1643  0 SAWSServer sw = new SAWSServer(0);
1644  0 sw.listSigningKeystore();
1645    }
1646   
1647  4 if ( (sIn.compareTo("7") == 0) ) { // export the PKC on signing keystore
1648  1 SAWSServer sw = new SAWSServer(0);
1649  1 sw.exportSigningPKC();
1650    }
1651  4 if ( (sIn.compareTo("9") == 0) ) { // test mode
1652  0 SAWSServer sw = new SAWSServer(1);
1653  0 sw.sawsStart();
1654  0 sw.sendLogRecord("This is a test.".getBytes());
1655  0 sw.sendLogRecord("This is a test 2.".getBytes());
1656  0 sw.sendLogRecord("This is a test 3.".getBytes());
1657   
1658  0 sw.closeLog();
1659  0 System.exit(0);
1660    }
1661   
1662  4 if (args == null || args.length == 0) {
1663  0 System.exit(0);
1664    }
1665    }
1666   
1667    }