Timing, Attacks
authorAli Younis <ayounis@uci.edu>
Tue, 14 Feb 2017 06:53:37 +0000 (22:53 -0800)
committerAli Younis <ayounis@uci.edu>
Tue, 14 Feb 2017 06:53:37 +0000 (22:53 -0800)
23 files changed:
version2/src/java/iotcloud/CloudComm.java
version2/src/java/iotcloud/CloudComm.java_back [new file with mode: 0644]
version2/src/java/iotcloud/Table.java
version2/src/java/iotcloud/Test.java
version2/src/java/iotcloud/TimingSingleton.java [new file with mode: 0644]
version2/src/server_malicious_ignore_seq/.dir-locals.el [new file with mode: 0644]
version2/src/server_malicious_ignore_seq/Makefile [new file with mode: 0644]
version2/src/server_malicious_ignore_seq/README.txt [new file with mode: 0644]
version2/src/server_malicious_ignore_seq/iotcloud.cpp [new file with mode: 0644]
version2/src/server_malicious_ignore_seq/iotquery.cpp [new file with mode: 0644]
version2/src/server_malicious_ignore_seq/iotquery.h [new file with mode: 0644]
version2/src/server_malicious_override_do_rej/.dir-locals.el [new file with mode: 0644]
version2/src/server_malicious_override_do_rej/Makefile [new file with mode: 0644]
version2/src/server_malicious_override_do_rej/README.txt [new file with mode: 0644]
version2/src/server_malicious_override_do_rej/iotcloud.cpp [new file with mode: 0644]
version2/src/server_malicious_override_do_rej/iotquery.cpp [new file with mode: 0644]
version2/src/server_malicious_override_do_rej/iotquery.h [new file with mode: 0644]
version2/src/server_malicious_switch_slot/.dir-locals.el [new file with mode: 0644]
version2/src/server_malicious_switch_slot/Makefile [new file with mode: 0644]
version2/src/server_malicious_switch_slot/README.txt [new file with mode: 0644]
version2/src/server_malicious_switch_slot/iotcloud.cpp [new file with mode: 0644]
version2/src/server_malicious_switch_slot/iotquery.cpp [new file with mode: 0644]
version2/src/server_malicious_switch_slot/iotquery.h [new file with mode: 0644]

index f1f436a..5e60e3c 100644 (file)
@@ -17,7 +17,7 @@ import java.security.SecureRandom;
 
 class CloudComm {
        private static final int SALT_SIZE = 8;
-       private static final int TIMEOUT_MILLIS = 25; // 100
+       private static final int TIMEOUT_MILLIS = 2000; // 100
 
        /** Sets the size for the HMAC. */
        static final int HMAC_SIZE = 32;
@@ -34,16 +34,20 @@ class CloudComm {
        private Thread localServerThread = null;
        private boolean doEnd = false;
 
+       private TimingSingleton timer = null;
+
        /**
         * Empty Constructor needed for child class.
         */
        CloudComm() {
+               timer = TimingSingleton.getInstance();
        }
 
        /**
         * Constructor for actual use. Takes in the url and password.
         */
        CloudComm(Table _table,  String _baseurl, String _password, int _listeningPort) {
+               timer = TimingSingleton.getInstance();
                this.table = _table;
                this.baseurl = _baseurl;
                this.password = _password;
@@ -137,6 +141,8 @@ class CloudComm {
                        random.nextBytes(saltTmp);
 
                        URL url = new URL(baseurl + "?req=setsalt");
+                       
+                       timer.startTime();
                        URLConnection con = url.openConnection();
                        HttpURLConnection http = (HttpURLConnection) con;
 
@@ -144,12 +150,14 @@ class CloudComm {
                        http.setFixedLengthStreamingMode(saltTmp.length);
                        http.setDoOutput(true);
                        http.setConnectTimeout(TIMEOUT_MILLIS);
+
+                       
                        http.connect();
 
                        OutputStream os = http.getOutputStream();
                        os.write(saltTmp);
                        os.flush();
-
+                       
                        int responsecode = http.getResponseCode();
                        if (responsecode != HttpURLConnection.HTTP_OK) {
                                // TODO: Remove this print
@@ -157,9 +165,12 @@ class CloudComm {
                                throw new Error("Invalid response");
                        }
 
+                       timer.endTime();
+
                        salt = saltTmp;
                } catch (Exception e) {
                        // e.printStackTrace();
+                       timer.endTime();
                        throw new ServerException("Failed setting salt", ServerException.TypeConnectTimeout);
                }
        }
@@ -177,13 +188,18 @@ class CloudComm {
                }
                try {
 
+                       timer.startTime();
                        con = url.openConnection();
                        http = (HttpURLConnection) con;
                        http.setRequestMethod("POST");
                        http.setConnectTimeout(TIMEOUT_MILLIS);
                        http.setReadTimeout(TIMEOUT_MILLIS);
+
+                       
                        http.connect();
+                       timer.endTime();
                } catch (SocketTimeoutException e) {
+                       timer.endTime();
                        throw new ServerException("getSalt failed", ServerException.TypeConnectTimeout);
                } catch (Exception e) {
                        // e.printStackTrace();
@@ -192,6 +208,8 @@ class CloudComm {
 
                try {
 
+                       timer.startTime();
+
                        int responsecode = http.getResponseCode();
                        if (responsecode != HttpURLConnection.HTTP_OK) {
                                // TODO: Remove this print
@@ -206,11 +224,17 @@ class CloudComm {
                                byte [] tmp = new byte[salt_length];
                                dis.readFully(tmp);
                                salt = tmp;
+                               timer.endTime();
+
                                return true;
                        } else {
+                               timer.endTime();
+
                                return false;
                        }
                } catch (SocketTimeoutException e) {
+                       timer.endTime();
+
                        throw new ServerException("getSalt failed", ServerException.TypeInputTimeout);
                } catch (Exception e) {
                        // e.printStackTrace();
@@ -240,7 +264,12 @@ class CloudComm {
                        byte[] bytes = slot.encode(mac);
                        bytes = encryptCipher.doFinal(bytes);
 
+
+
+
                        url = buildRequest(true, sequencenumber, max);
+
+                       timer.startTime();
                        con = url.openConnection();
                        http = (HttpURLConnection) con;
 
@@ -255,10 +284,17 @@ class CloudComm {
                        os.write(bytes);
                        os.flush();
 
+                       timer.endTime();
+
+
                        // System.out.println("Bytes Sent: " + bytes.length);
                } catch (ServerException e) {
+                       timer.endTime();
+
                        throw e;
                } catch (SocketTimeoutException e) {
+                       timer.endTime();
+
                        throw new ServerException("putSlot failed", ServerException.TypeConnectTimeout);
                } catch (Exception e) {
                        // e.printStackTrace();
@@ -268,19 +304,26 @@ class CloudComm {
 
 
                try {
+                       timer.startTime();
                        InputStream is = http.getInputStream();
                        DataInputStream dis = new DataInputStream(is);
                        byte[] resptype = new byte[7];
                        dis.readFully(resptype);
+                       timer.endTime();
 
                        if (Arrays.equals(resptype, "getslot".getBytes()))
+                       {       
                                return processSlots(dis);
+                       }
                        else if (Arrays.equals(resptype, "putslot".getBytes()))
+                       {
                                return null;
+                       }
                        else
                                throw new Error("Bad response to putslot");
 
                } catch (SocketTimeoutException e) {
+                               timer.endTime();
                        throw new ServerException("putSlot failed", ServerException.TypeInputTimeout);
                } catch (Exception e) {
                        // e.printStackTrace();
@@ -306,15 +349,25 @@ class CloudComm {
                        }
 
                        url = buildRequest(false, sequencenumber, 0);
+                       timer.startTime();
                        con = url.openConnection();
                        http = (HttpURLConnection) con;
                        http.setRequestMethod("POST");
                        http.setConnectTimeout(TIMEOUT_MILLIS);
                        http.setReadTimeout(TIMEOUT_MILLIS);
+
+                       
+
                        http.connect();
+                       timer.endTime();
+
                } catch (SocketTimeoutException e) {
+                       timer.endTime();
+
                        throw new ServerException("getSlots failed", ServerException.TypeConnectTimeout);
                } catch (ServerException e) {
+                       timer.endTime();
+
                        throw e;
                } catch (Exception e) {
                        // e.printStackTrace();
@@ -322,15 +375,22 @@ class CloudComm {
                }
 
                try {
-                       InputStream is = http.getInputStream();
+                       
+                       timer.startTime();
+                       InputStream is = http.getInputStream(); 
                        DataInputStream dis = new DataInputStream(is);
                        byte[] resptype = new byte[7];
+                       
                        dis.readFully(resptype);
+                       timer.endTime();
+
                        if (!Arrays.equals(resptype, "getslot".getBytes()))
                                throw new Error("Bad Response: " + new String(resptype));
-                       else
-                               return processSlots(dis);
+
+                       return processSlots(dis);
                } catch (SocketTimeoutException e) {
+                       timer.endTime();
+
                        throw new ServerException("getSlots failed", ServerException.TypeInputTimeout);
                } catch (Exception e) {
                        // e.printStackTrace();
@@ -388,6 +448,8 @@ class CloudComm {
                        DataOutputStream output = new DataOutputStream(socket.getOutputStream());
                        DataInputStream input = new DataInputStream(socket.getInputStream());
 
+
+                       timer.startTime();
                        // Send data to output (length of data, the data)
                        output.writeInt(encryptedData.length);
                        output.write(encryptedData, 0, encryptedData.length);
@@ -396,6 +458,9 @@ class CloudComm {
                        int lengthOfReturnData = input.readInt();
                        byte[] returnData = new byte[lengthOfReturnData];
                        input.readFully(returnData);
+
+                       timer.endTime();
+
                        returnData = decryptCipher.doFinal(returnData);
 
                        // We are done with this socket
@@ -456,6 +521,8 @@ class CloudComm {
                                byte[] readData = new byte[dataSize];
                                input.readFully(readData);
 
+                               timer.endTime();
+
                                // Decrypt the data
                                readData = decryptCipher.doFinal(readData);
 
@@ -483,6 +550,8 @@ class CloudComm {
                                // Encrypt the data for sending
                                byte[] encryptedData = encryptCipher.doFinal(totalData);
 
+
+                               timer.startTime();
                                // Send data to output (length of data, the data)
                                output.writeInt(encryptedData.length);
                                output.write(encryptedData, 0, encryptedData.length);
diff --git a/version2/src/java/iotcloud/CloudComm.java_back b/version2/src/java/iotcloud/CloudComm.java_back
new file mode 100644 (file)
index 0000000..f1f436a
--- /dev/null
@@ -0,0 +1,539 @@
+package iotcloud;
+
+import java.io.*;
+import java.net.*;
+import java.util.Arrays;
+import javax.crypto.*;
+import javax.crypto.spec.*;
+import java.security.SecureRandom;
+
+/**
+ * This class provides a communication API to the webserver.  It also
+ * validates the HMACs on the slots and handles encryption.
+ * @author Brian Demsky <bdemsky@uci.edu>
+ * @version 1.0
+ */
+
+
+class CloudComm {
+       private static final int SALT_SIZE = 8;
+       private static final int TIMEOUT_MILLIS = 25; // 100
+
+       /** Sets the size for the HMAC. */
+       static final int HMAC_SIZE = 32;
+
+       private String baseurl;
+       private Cipher encryptCipher;
+       private Cipher decryptCipher;
+       private Mac mac;
+       private String password;
+       private SecureRandom random;
+       private byte salt[];
+       private Table table;
+       private int listeningPort = -1;
+       private Thread localServerThread = null;
+       private boolean doEnd = false;
+
+       /**
+        * Empty Constructor needed for child class.
+        */
+       CloudComm() {
+       }
+
+       /**
+        * Constructor for actual use. Takes in the url and password.
+        */
+       CloudComm(Table _table,  String _baseurl, String _password, int _listeningPort) {
+               this.table = _table;
+               this.baseurl = _baseurl;
+               this.password = _password;
+               this.random = new SecureRandom();
+               this.listeningPort = _listeningPort;
+
+               if (this.listeningPort > 0) {
+                       localServerThread = new Thread(new Runnable() {
+                               public void run() {
+                                       localServerWorkerFunction();
+                               }
+                       });
+                       localServerThread.start();
+               }
+       }
+
+       /**
+        * Generates Key from password.
+        */
+       private SecretKeySpec initKey() {
+               try {
+                       PBEKeySpec keyspec = new PBEKeySpec(password.toCharArray(),
+                                                           salt,
+                                                           65536,
+                                                           128);
+                       SecretKey tmpkey = SecretKeyFactory.getInstance("PBKDF2WithHmacSHA256").generateSecret(keyspec);
+                       return new SecretKeySpec(tmpkey.getEncoded(), "AES");
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("Failed generating key.");
+               }
+       }
+
+       /**
+        * Inits all the security stuff
+        */
+       public void initSecurity() throws ServerException {
+               // try to get the salt and if one does not exist set one
+               if (!getSalt()) {
+                       //Set the salt
+                       setSalt();
+               }
+
+               initCrypt();
+       }
+
+       /**
+        * Inits the HMAC generator.
+        */
+       private void initCrypt() {
+
+               if (password == null) {
+                       return;
+               }
+
+               try {
+                       SecretKeySpec key = initKey();
+                       password = null; // drop password
+                       mac = Mac.getInstance("HmacSHA256");
+                       mac.init(key);
+                       encryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+                       encryptCipher.init(Cipher.ENCRYPT_MODE, key);
+                       decryptCipher = Cipher.getInstance("AES/ECB/PKCS5Padding");
+                       decryptCipher.init(Cipher.DECRYPT_MODE, key);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("Failed To Initialize Ciphers");
+               }
+       }
+
+       /*
+        * Builds the URL for the given request.
+        */
+       private URL buildRequest(boolean isput, long sequencenumber, long maxentries) throws IOException {
+               String reqstring = isput ? "req=putslot" : "req=getslot";
+               String urlstr = baseurl + "?" + reqstring + "&seq=" + sequencenumber;
+               if (maxentries != 0)
+                       urlstr += "&max=" + maxentries;
+               return new URL(urlstr);
+       }
+
+       private void setSalt() throws ServerException {
+
+               if (salt != null) {
+                       // Salt already sent to server so dont set it again
+                       return;
+               }
+
+               try {
+                       byte[] saltTmp = new byte[SALT_SIZE];
+                       random.nextBytes(saltTmp);
+
+                       URL url = new URL(baseurl + "?req=setsalt");
+                       URLConnection con = url.openConnection();
+                       HttpURLConnection http = (HttpURLConnection) con;
+
+                       http.setRequestMethod("POST");
+                       http.setFixedLengthStreamingMode(saltTmp.length);
+                       http.setDoOutput(true);
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+
+                       OutputStream os = http.getOutputStream();
+                       os.write(saltTmp);
+                       os.flush();
+
+                       int responsecode = http.getResponseCode();
+                       if (responsecode != HttpURLConnection.HTTP_OK) {
+                               // TODO: Remove this print
+                               System.out.println(responsecode);
+                               throw new Error("Invalid response");
+                       }
+
+                       salt = saltTmp;
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new ServerException("Failed setting salt", ServerException.TypeConnectTimeout);
+               }
+       }
+
+       private boolean getSalt() throws ServerException {
+               URL url = null;
+               URLConnection con = null;
+               HttpURLConnection http = null;
+
+               try {
+                       url = new URL(baseurl + "?req=getsalt");
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("getSlot failed");
+               }
+               try {
+
+                       con = url.openConnection();
+                       http = (HttpURLConnection) con;
+                       http.setRequestMethod("POST");
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("getSalt failed", ServerException.TypeConnectTimeout);
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("getSlot failed");
+               }
+
+               try {
+
+                       int responsecode = http.getResponseCode();
+                       if (responsecode != HttpURLConnection.HTTP_OK) {
+                               // TODO: Remove this print
+                               // System.out.println(responsecode);
+                               throw new Error("Invalid response");
+                       }
+
+                       InputStream is = http.getInputStream();
+                       if (is.available() > 0) {
+                               DataInputStream dis = new DataInputStream(is);
+                               int salt_length = dis.readInt();
+                               byte [] tmp = new byte[salt_length];
+                               dis.readFully(tmp);
+                               salt = tmp;
+                               return true;
+                       } else {
+                               return false;
+                       }
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("getSalt failed", ServerException.TypeInputTimeout);
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("getSlot failed");
+               }
+       }
+
+       /*
+        * API for putting a slot into the queue.  Returns null on success.
+        * On failure, the server will send slots with newer sequence
+        * numbers.
+        */
+       public Slot[] putSlot(Slot slot, int max) throws ServerException {
+               URL url = null;
+               URLConnection con = null;
+               HttpURLConnection http = null;
+
+               try {
+                       if (salt == null) {
+                               if (!getSalt()) {
+                                       throw new ServerException("putSlot failed", ServerException.TypeSalt);
+                               }
+                               initCrypt();
+                       }
+
+                       long sequencenumber = slot.getSequenceNumber();
+                       byte[] bytes = slot.encode(mac);
+                       bytes = encryptCipher.doFinal(bytes);
+
+                       url = buildRequest(true, sequencenumber, max);
+                       con = url.openConnection();
+                       http = (HttpURLConnection) con;
+
+                       http.setRequestMethod("POST");
+                       http.setFixedLengthStreamingMode(bytes.length);
+                       http.setDoOutput(true);
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+
+                       OutputStream os = http.getOutputStream();
+                       os.write(bytes);
+                       os.flush();
+
+                       // System.out.println("Bytes Sent: " + bytes.length);
+               } catch (ServerException e) {
+                       throw e;
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("putSlot failed", ServerException.TypeConnectTimeout);
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("putSlot failed");
+               }
+
+
+
+               try {
+                       InputStream is = http.getInputStream();
+                       DataInputStream dis = new DataInputStream(is);
+                       byte[] resptype = new byte[7];
+                       dis.readFully(resptype);
+
+                       if (Arrays.equals(resptype, "getslot".getBytes()))
+                               return processSlots(dis);
+                       else if (Arrays.equals(resptype, "putslot".getBytes()))
+                               return null;
+                       else
+                               throw new Error("Bad response to putslot");
+
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("putSlot failed", ServerException.TypeInputTimeout);
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("putSlot failed");
+               }
+       }
+
+       /**
+        * Request the server to send all slots with the given
+        * sequencenumber or newer.
+        */
+       public Slot[] getSlots(long sequencenumber) throws ServerException {
+               URL url = null;
+               URLConnection con = null;
+               HttpURLConnection http = null;
+
+               try {
+                       if (salt == null) {
+                               if (!getSalt()) {
+                                       throw new ServerException("getSlots failed", ServerException.TypeSalt);
+                               }
+                               initCrypt();
+                       }
+
+                       url = buildRequest(false, sequencenumber, 0);
+                       con = url.openConnection();
+                       http = (HttpURLConnection) con;
+                       http.setRequestMethod("POST");
+                       http.setConnectTimeout(TIMEOUT_MILLIS);
+                       http.setReadTimeout(TIMEOUT_MILLIS);
+                       http.connect();
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("getSlots failed", ServerException.TypeConnectTimeout);
+               } catch (ServerException e) {
+                       throw e;
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("getSlots failed");
+               }
+
+               try {
+                       InputStream is = http.getInputStream();
+                       DataInputStream dis = new DataInputStream(is);
+                       byte[] resptype = new byte[7];
+                       dis.readFully(resptype);
+                       if (!Arrays.equals(resptype, "getslot".getBytes()))
+                               throw new Error("Bad Response: " + new String(resptype));
+                       else
+                               return processSlots(dis);
+               } catch (SocketTimeoutException e) {
+                       throw new ServerException("getSlots failed", ServerException.TypeInputTimeout);
+               } catch (Exception e) {
+                       // e.printStackTrace();
+                       throw new Error("getSlots failed");
+               }
+       }
+
+       /**
+        * Method that actually handles building Slot objects from the
+        * server response.  Shared by both putSlot and getSlots.
+        */
+       private Slot[] processSlots(DataInputStream dis) throws Exception {
+               int numberofslots = dis.readInt();
+               int[] sizesofslots = new int[numberofslots];
+
+               Slot[] slots = new Slot[numberofslots];
+               for (int i = 0; i < numberofslots; i++)
+                       sizesofslots[i] = dis.readInt();
+
+               for (int i = 0; i < numberofslots; i++) {
+
+                       byte[] data = new byte[sizesofslots[i]];
+                       dis.readFully(data);
+
+                       data = decryptCipher.doFinal(data);
+
+                       slots[i] = Slot.decode(table, data, mac);
+               }
+               dis.close();
+               return slots;
+       }
+
+       public byte[] sendLocalData(byte[] sendData, String host, int port) {
+
+               if (salt == null) {
+                       return null;
+               }
+               try {
+
+                       System.out.println("Passing Locally");
+
+                       mac.update(sendData);
+                       byte[] genmac = mac.doFinal();
+                       byte[] totalData = new byte[sendData.length + genmac.length];
+                       System.arraycopy(sendData, 0, totalData, 0, sendData.length);
+                       System.arraycopy(genmac, 0, totalData, sendData.length, genmac.length);
+
+                       // Encrypt the data for sending
+                       // byte[] encryptedData = encryptCipher.doFinal(totalData);
+                       byte[] encryptedData = encryptCipher.doFinal(totalData);
+
+                       // Open a TCP socket connection to a local device
+                       Socket socket = new Socket(host, port);
+                       socket.setReuseAddress(true);
+                       DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+                       DataInputStream input = new DataInputStream(socket.getInputStream());
+
+                       // Send data to output (length of data, the data)
+                       output.writeInt(encryptedData.length);
+                       output.write(encryptedData, 0, encryptedData.length);
+                       output.flush();
+
+                       int lengthOfReturnData = input.readInt();
+                       byte[] returnData = new byte[lengthOfReturnData];
+                       input.readFully(returnData);
+                       returnData = decryptCipher.doFinal(returnData);
+
+                       // We are done with this socket
+                       socket.close();
+
+                       mac.update(returnData, 0, returnData.length - HMAC_SIZE);
+                       byte[] realmac = mac.doFinal();
+                       byte[] recmac = new byte[HMAC_SIZE];
+                       System.arraycopy(returnData, returnData.length - realmac.length, recmac, 0, realmac.length);
+
+                       if (!Arrays.equals(recmac, realmac))
+                               throw new Error("Local Error: Invalid HMAC!  Potential Attack!");
+
+                       byte[] returnData2 = new byte[lengthOfReturnData - recmac.length];
+                       System.arraycopy(returnData, 0, returnData2, 0, returnData2.length);
+
+                       return returnData2;
+               } catch (SocketTimeoutException e) {
+
+               } catch (BadPaddingException e) {
+
+               } catch (IllegalBlockSizeException e) {
+
+               } catch (UnknownHostException e) {
+
+               } catch (IOException e) {
+
+               }
+
+               return null;
+       }
+
+       private void localServerWorkerFunction() {
+
+               ServerSocket inputSocket = null;
+
+               try {
+                       // Local server socket
+                       inputSocket = new ServerSocket(listeningPort);
+                       inputSocket.setReuseAddress(true);
+                       inputSocket.setSoTimeout(TIMEOUT_MILLIS);
+               } catch (Exception e) {
+                       e.printStackTrace();
+                       throw new Error("Local server setup failure...");
+               }
+
+               while (!doEnd) {
+
+                       try {
+                               // Accept incoming socket
+                               Socket socket = inputSocket.accept();
+
+                               DataInputStream input = new DataInputStream(socket.getInputStream());
+                               DataOutputStream output = new DataOutputStream(socket.getOutputStream());
+
+                               // Get the encrypted data from the server
+                               int dataSize = input.readInt();
+                               byte[] readData = new byte[dataSize];
+                               input.readFully(readData);
+
+                               // Decrypt the data
+                               readData = decryptCipher.doFinal(readData);
+
+                               mac.update(readData, 0, readData.length - HMAC_SIZE);
+                               byte[] genmac = mac.doFinal();
+                               byte[] recmac = new byte[HMAC_SIZE];
+                               System.arraycopy(readData, readData.length - recmac.length, recmac, 0, recmac.length);
+
+                               if (!Arrays.equals(recmac, genmac))
+                                       throw new Error("Local Error: Invalid HMAC!  Potential Attack!");
+
+                               byte[] returnData = new byte[readData.length - recmac.length];
+                               System.arraycopy(readData, 0, returnData, 0, returnData.length);
+
+                               // Process the data
+                               // byte[] sendData = table.acceptDataFromLocal(readData);
+                               byte[] sendData = table.acceptDataFromLocal(returnData);
+
+                               mac.update(sendData);
+                               byte[] realmac = mac.doFinal();
+                               byte[] totalData = new byte[sendData.length + realmac.length];
+                               System.arraycopy(sendData, 0, totalData, 0, sendData.length);
+                               System.arraycopy(realmac, 0, totalData, sendData.length, realmac.length);
+
+                               // Encrypt the data for sending
+                               byte[] encryptedData = encryptCipher.doFinal(totalData);
+
+                               // Send data to output (length of data, the data)
+                               output.writeInt(encryptedData.length);
+                               output.write(encryptedData, 0, encryptedData.length);
+                               output.flush();
+
+                               // close the socket
+                               socket.close();
+                       } catch (SocketTimeoutException e) {
+
+                       } catch (BadPaddingException e) {
+
+                       } catch (IllegalBlockSizeException e) {
+
+                       } catch (UnknownHostException e) {
+
+                       } catch (IOException e) {
+
+                       }
+               }
+
+               if (inputSocket != null) {
+                       try {
+                               inputSocket.close();
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                               throw new Error("Local server close failure...");
+                       }
+               }
+       }
+
+       public void close() {
+               doEnd = true;
+
+               if (localServerThread != null) {
+                       try {
+                               localServerThread.join();
+                       } catch (Exception e) {
+                               e.printStackTrace();
+                               throw new Error("Local Server thread join issue...");
+                       }
+               }
+
+               // System.out.println("Done Closing Cloud Comm");
+       }
+
+       protected void finalize() throws Throwable {
+               try {
+                       close();        // close open files
+               } finally {
+                       super.finalize();
+               }
+       }
+
+}
index 225d25f..59a12f4 100644 (file)
@@ -364,6 +364,10 @@ final public class Table {
                        return true;
                } catch (Exception e) {
                        // e.printStackTrace();
+
+                       for (Long m : localCommunicationTable.keySet()) {
+                               updateFromLocal(m);
+                       }
                }
 
                return false;
@@ -698,7 +702,6 @@ final public class Table {
 
                                // If there is a new key with same name then end
                                if ((newKey != null) && (arbitratorTable.get(newKey.getKey()) != null)) {
-                                       System.out.println("New Key Fail");
                                        return false;
                                }
 
@@ -779,10 +782,6 @@ final public class Table {
                                                if (transaction.didSendAllParts()) {
                                                        transaction.getTransactionStatus().setStatus(TransactionStatus.StatusSentFully);
                                                        pendingTransactionQueue.remove(transaction);
-
-                                                       for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
-                                                               System.out.println("Sent: " + kv + "  from: " + localMachineId + "   Slot:" + slot.getSequenceNumber() + "  Claimed:" + transaction.getSequenceNumber());
-                                                       }
                                                }
                                        }
                                } else {
@@ -840,13 +839,6 @@ final public class Table {
 
                } catch (ServerException e) {
 
-                       System.out.println("Server Failure:   " + e.getType());
-                       for (Transaction transaction : transactionPartsSent.keySet()) {
-                               for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
-                                       System.out.println("Sent Error: " + kv + "    " + e.getType());
-                               }
-                       }
-
                        if (e.getType() != ServerException.TypeInputTimeout) {
                                // e.printStackTrace();
 
@@ -885,7 +877,7 @@ final public class Table {
                return newKey == null;
        }
 
-       public synchronized boolean updateFromLocal(long machineId) {
+       private synchronized boolean updateFromLocal(long machineId) {
                Pair<String, Integer> localCommunicationInformation = localCommunicationTable.get(machineId);
                if (localCommunicationInformation == null) {
                        // Cant talk to that device locally so do nothing
@@ -1645,9 +1637,6 @@ final public class Table {
                for (Long transactionSequenceNumber : transactionSequenceNumbers) {
                        Transaction transaction = liveTransactionBySequenceNumberTable.get(transactionSequenceNumber);
 
-                       for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
-                               System.out.println("Arb Seen: " + kv + "   " + lastSeqNumArbOn + "    " + transactionSequenceNumber + "  " + localMachineId + "   " + transaction.getArbitrator());
-                       }
 
 
                        // Check if this machine arbitrates for this transaction if not then we cant arbitrate this transaction
@@ -1659,11 +1648,6 @@ final public class Table {
                                continue;
                        }
 
-                       for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
-                               System.out.println("Arb Seen: " + kv + "   " + lastSeqNumArbOn + "    " + transactionSequenceNumber + "  " + localMachineId);
-                       }
-
-
                        if (offlineTransactionsCommittedAndAtServer.contains(transaction.getId())) {
                                // We have seen this already locally so dont commit again
                                continue;
@@ -1676,10 +1660,6 @@ final public class Table {
                                break;
                        }
 
-                       for (KeyValue kv : transaction.getKeyValueUpdateSet()) {
-                               System.out.println("Arb on: " + kv + "   " + lastSeqNumArbOn + "    " + transactionSequenceNumber + "  " + localMachineId);
-                       }
-
 
                        // update the largest transaction seen by arbitrator from server
                        if (lastTransactionSeenFromMachineFromServer.get(transaction.getMachineId()) == null) {
@@ -1701,8 +1681,6 @@ final public class Table {
 
                                // Update what the last transaction committed was for use in batch commit
                                lastTransactionCommitted = transactionSequenceNumber;
-
-                               System.out.println("Commit Generated: " + lastTransactionCommitted + "   " + localMachineId);
                        } else {
                                // Guard evaluated was false so create abort
 
@@ -2056,20 +2034,6 @@ final public class Table {
                                        }
                                }
 
-
-                               for (KeyValue kv : commit.getKeyValueUpdateSet()) {
-                                       System.out.println("Commit Seen: " + kv + "   " + commit.getTransactionSequenceNumber() + "   " + localMachineId);
-                               }
-
-
-
-
-
-
-
-
-
-
                                // Update the last arbitration data that we have seen so far
                                if (lastArbitrationDataLocalSequenceNumberSeenFromArbitrator.get(commit.getMachineId()) != null) {
 
index 99babcb..158dd72 100644 (file)
@@ -11,7 +11,7 @@ import java.util.ArrayList;
 
 public class Test {
 
-    public static final  int NUMBER_OF_TESTS = 15;
+    public static final  int NUMBER_OF_TESTS = 25;
 
     public static void main(String[] args)  throws ServerException {
         if (args[0].equals("2")) {
@@ -34,10 +34,269 @@ public class Test {
             test10();
         } else if (args[0].equals("11")) {
             test11();
+        } else if (args[0].equals("12")) {
+            test12();
+        } else if (args[0].equals("13")) {
+            test13();
+        }
+
+        else if (args[0].equals("14")) {
+            test14();
         }
     }
 
 
+    static void test14() throws ServerException {
+        TimingSingleton timer = TimingSingleton.getInstance();
+
+        boolean foundError = false;
+        long startTime = 0;
+        long endTime = 0;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 321, -1);
+        t1.initTable();
+        System.out.println("T1 Ready");
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        startTime = System.nanoTime();
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            System.out.println(i);
+            String a = "a" + i;
+            IoTString ia = new IoTString(a);
+            t1.createNewKey(ia, 321);
+        }
+        endTime = System.nanoTime();
+        long keysDt = endTime - startTime;
+        long keysNet = timer.getTime();
+
+        System.out.println("Total Key Create Time: " + keysDt / 1000000);
+        System.out.println("Total Key Create Time Network: " + keysNet / 1000000);
+        System.out.println("Total Key Create Time no Network: " + (keysDt - keysNet) / 1000000);
+        System.out.println();
+   }
+
+
+    static void test13() throws ServerException {
+        TimingSingleton timer = TimingSingleton.getInstance();
+
+        boolean foundError = false;
+        long startTime = 0;
+        long endTime = 0;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 321, -1);
+        t1.initTable();
+        System.out.println("T1 Ready");
+
+        Table t2 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 351, -1);
+        t2.update();
+        System.out.println("T2 Ready");
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        startTime = System.nanoTime();
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            System.out.println(i);
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 351);
+            t1.createNewKey(ib, 351);
+            t2.createNewKey(ic, 321);
+            t2.createNewKey(id, 321);
+        }
+        endTime = System.nanoTime();
+        long keysDt = endTime - startTime;
+        long keysNet = timer.getTime();
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+        startTime = System.nanoTime();
+        for (int t = 0; t < 3; t++) {
+            for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                System.out.println(i);
+                String keyA = "a" + i;
+                String keyB = "b" + i;
+                String keyC = "c" + i;
+                String keyD = "d" + i;
+                String valueA = "a" + i;
+                String valueB = "b" + i;
+                String valueC = "c" + i;
+                String valueD = "d" + i;
+
+                IoTString iKeyA = new IoTString(keyA);
+                IoTString iKeyB = new IoTString(keyB);
+                IoTString iKeyC = new IoTString(keyC);
+                IoTString iKeyD = new IoTString(keyD);
+                IoTString iValueA = new IoTString(valueA);
+                IoTString iValueB = new IoTString(valueB);
+                IoTString iValueC = new IoTString(valueC);
+                IoTString iValueD = new IoTString(valueD);
+
+
+                t1.startTransaction();
+                t1.addKV(iKeyA, iValueA);
+                transStatusList.add(t1.commitTransaction());
+
+                t1.startTransaction();
+                t1.addKV(iKeyB, iValueB);
+                transStatusList.add(t1.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyC, iValueC);
+                transStatusList.add(t2.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyD, iValueD);
+                transStatusList.add(t2.commitTransaction());
+
+            }
+        }
+        endTime = System.nanoTime();
+        long writesDt = endTime - startTime;
+        long writesNet = timer.getTime() - keysNet;
+
+        System.out.println("Updating Clients...");
+        startTime = System.nanoTime();
+        t1.update();
+        t2.update();
+        endTime = System.nanoTime();
+        long updatesDt = endTime - startTime;
+        long updatesNet = timer.getTime() - keysNet - writesNet;
+
+
+        System.out.println("Total Key Create Time: " + keysDt / 1000000);
+        System.out.println("Total Key Create Time Network: " + keysNet / 1000000);
+        System.out.println("Total Key Create Time no Network: " + (keysDt - keysNet) / 1000000);
+        System.out.println();
+        System.out.println("Total write Time: " + writesDt / 1000000);
+        System.out.println("Total write Time Network: " + writesNet / 1000000);
+        System.out.println("Total write Time no Network: " + (writesDt - writesNet) / 1000000);
+        System.out.println();
+        System.out.println("Total updates Time: " + updatesDt / 1000000);
+        System.out.println("Total updates Time Network: " + updatesNet / 1000000);
+        System.out.println("Total updates Time no Network: " + (updatesDt - updatesNet) / 1000000);
+    }
+
+
+    static void test12() throws ServerException {
+        TimingSingleton timer = TimingSingleton.getInstance();
+
+        boolean foundError = false;
+        long startTime = 0;
+        long endTime = 0;
+        List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
+
+        // Setup the 2 clients
+        Table t1 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 321, -1);
+        t1.initTable();
+        System.out.println("T1 Ready");
+
+        Table t2 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 351, -1);
+        t2.update();
+        System.out.println("T2 Ready");
+
+        // Make the Keys
+        System.out.println("Setting up keys");
+        startTime = System.nanoTime();
+        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+            System.out.println(i);
+            String a = "a" + i;
+            String b = "b" + i;
+            String c = "c" + i;
+            String d = "d" + i;
+            IoTString ia = new IoTString(a);
+            IoTString ib = new IoTString(b);
+            IoTString ic = new IoTString(c);
+            IoTString id = new IoTString(d);
+            t1.createNewKey(ia, 321);
+            t1.createNewKey(ib, 321);
+            t2.createNewKey(ic, 351);
+            t2.createNewKey(id, 351);
+        }
+        endTime = System.nanoTime();
+        long keysDt = endTime - startTime;
+        long keysNet = timer.getTime();
+
+        // Do Updates for the keys
+        System.out.println("Setting Key-Values...");
+        startTime = System.nanoTime();
+        for (int t = 0; t < 3; t++) {
+            for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+                System.out.println(i);
+                String keyA = "a" + i;
+                String keyB = "b" + i;
+                String keyC = "c" + i;
+                String keyD = "d" + i;
+                String valueA = "a" + i;
+                String valueB = "b" + i;
+                String valueC = "c" + i;
+                String valueD = "d" + i;
+
+                IoTString iKeyA = new IoTString(keyA);
+                IoTString iKeyB = new IoTString(keyB);
+                IoTString iKeyC = new IoTString(keyC);
+                IoTString iKeyD = new IoTString(keyD);
+                IoTString iValueA = new IoTString(valueA);
+                IoTString iValueB = new IoTString(valueB);
+                IoTString iValueC = new IoTString(valueC);
+                IoTString iValueD = new IoTString(valueD);
+
+
+                t1.startTransaction();
+                t1.addKV(iKeyA, iValueA);
+                transStatusList.add(t1.commitTransaction());
+
+                t1.startTransaction();
+                t1.addKV(iKeyB, iValueB);
+                transStatusList.add(t1.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyC, iValueC);
+                transStatusList.add(t2.commitTransaction());
+
+                t2.startTransaction();
+                t2.addKV(iKeyD, iValueD);
+                transStatusList.add(t2.commitTransaction());
+
+            }
+        }
+        endTime = System.nanoTime();
+        long writesDt = endTime - startTime;
+        long writesNet = timer.getTime() - keysNet;
+
+        System.out.println("Updating Clients...");
+        startTime = System.nanoTime();
+        t1.update();
+        t2.update();
+        endTime = System.nanoTime();
+        long updatesDt = endTime - startTime;
+        long updatesNet = timer.getTime() - keysNet - writesNet;
+
+
+        System.out.println("Total Key Create Time: " + keysDt / 1000000);
+        System.out.println("Total Key Create Time Network: " + keysNet / 1000000);
+        System.out.println("Total Key Create Time no Network: " + (keysDt - keysNet) / 1000000);
+        System.out.println();
+        System.out.println("Total write Time: " + writesDt / 1000000);
+        System.out.println("Total write Time Network: " + writesNet / 1000000);
+        System.out.println("Total write Time no Network: " + (writesDt - writesNet) / 1000000);
+        System.out.println();
+        System.out.println("Total updates Time: " + updatesDt / 1000000);
+        System.out.println("Total updates Time Network: " + updatesNet / 1000000);
+        System.out.println("Total updates Time no Network: " + (updatesDt - updatesNet) / 1000000);
+    }
+
+
     static void test11() {
 
         boolean foundError = false;
@@ -583,8 +842,8 @@ public class Test {
             transStatusList.add(t2.commitTransaction());
         }
 
-        while (t1.updateFromLocal(351) == false) {}
-        while (t2.updateFromLocal(321) == false) {}
+        // while (t1.updateFromLocal(351) == false) {}
+        // while (t2.updateFromLocal(321) == false) {}
 
 
         System.out.println("Updating...");
@@ -649,6 +908,9 @@ public class Test {
     }
 
     static void test8() {
+        TimingSingleton timer = TimingSingleton.getInstance();
+        long startTime = 0;
+        long endTime = 0;
 
         boolean foundError = false;
         List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
@@ -675,6 +937,7 @@ public class Test {
 
         // Make the Keys
         System.out.println("Setting up keys");
+        startTime = System.nanoTime();
         for (int i = 0; i < NUMBER_OF_TESTS; i++) {
             System.out.println(i);
 
@@ -715,8 +978,13 @@ public class Test {
                 } catch (Exception e) { }
             }
         }
+        endTime = System.nanoTime();
+        long keysDt = endTime - startTime;
+        long keysNet = timer.getTime();
+
 
         // Do Updates for the keys
+        startTime = System.nanoTime();
         System.out.println("Setting Key-Values...");
         for (int i = 0; i < NUMBER_OF_TESTS; i++) {
             System.out.println(i);
@@ -773,113 +1041,134 @@ public class Test {
             t2.addKV(iKeyD, iValueD);
             transStatusList.add(t2.commitTransaction());
         }
+        endTime = System.nanoTime();
+        long writesDt = endTime - startTime;
+        long writesNet = timer.getTime() - keysNet;
+
+
 
         System.out.println("Updating...");
+        startTime = System.nanoTime();
         while (t1.update() == false) {}
         while (t2.update() == false) {}
         while (t1.update() == false) {}
         while (t2.update() == false) {}
+        endTime = System.nanoTime();
+        long updatesDt = endTime - startTime;
+        long updatesNet = timer.getTime() - keysNet - writesNet;
 
-        System.out.println("Checking Key-Values...");
-        for (int i = 0; i < NUMBER_OF_TESTS; i++) {
-
-            String keyA = "a" + i;
-            String keyB = "b" + i;
-            String keyC = "c" + i;
-            String keyD = "d" + i;
-            String valueA = "a" + i;
-            String valueB = "b" + i;
-            String valueC = "c" + i;
-            String valueD = "d" + i;
-
-            IoTString iKeyA = new IoTString(keyA);
-            IoTString iKeyB = new IoTString(keyB);
-            IoTString iKeyC = new IoTString(keyC);
-            IoTString iKeyD = new IoTString(keyD);
-            IoTString iValueA = new IoTString(valueA);
-            IoTString iValueB = new IoTString(valueB);
-            IoTString iValueC = new IoTString(valueC);
-            IoTString iValueD = new IoTString(valueD);
-
-
-            IoTString testValA1 = t1.getCommitted(iKeyA);
-            IoTString testValB1 = t1.getCommitted(iKeyB);
-            IoTString testValC1 = t1.getCommitted(iKeyC);
-            IoTString testValD1 = t1.getCommitted(iKeyD);
-
-            IoTString testValA2 = t2.getCommitted(iKeyA);
-            IoTString testValB2 = t2.getCommitted(iKeyB);
-            IoTString testValC2 = t2.getCommitted(iKeyC);
-            IoTString testValD2 = t2.getCommitted(iKeyD);
-
-            if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
-                System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
-                foundError = true;
-            }
-
-            if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
-                System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
-                foundError = true;
-            }
-
-            if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
-                System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
-                foundError = true;
-            }
-
-            if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
-                System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
-                foundError = true;
-            }
-
-
-            if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
-                System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
-                foundError = true;
-            }
-
-            if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
-                System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
-                foundError = true;
-            }
-
-            if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
-                System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
-                foundError = true;
-            }
-
-            if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
-                System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
-                foundError = true;
-            }
-        }
-
-        int count = 0;
-        for (TransactionStatus status : transStatusList) {
-            if (status.getStatus() != TransactionStatus.StatusCommitted) {
-                foundError = true;
-                System.out.println("Status: " + status.getStatus() + "   " + status.getTransactionSequenceNumber());
-            }
-
-            count++;
-        }
 
-        if (foundError) {
-            System.out.println("Found Errors...");
-        } else {
-            System.out.println("No Errors Found...");
-        }
+        System.out.println("Total Key Create Time: " + keysDt / 1000000);
+        System.out.println("Total Key Create Time Network: " + keysNet / 1000000);
+        System.out.println("Total Key Create Time no Network: " + (keysDt - keysNet) / 1000000);
+        System.out.println();
+        System.out.println("Total write Time: " + writesDt / 1000000);
+        System.out.println("Total write Time Network: " + writesNet / 1000000);
+        System.out.println("Total write Time no Network: " + (writesDt - writesNet) / 1000000);
+        System.out.println();
+        System.out.println("Total updates Time: " + updatesDt / 1000000);
+        System.out.println("Total updates Time Network: " + updatesNet / 1000000);
+        System.out.println("Total updates Time no Network: " + (updatesDt - updatesNet) / 1000000);
+
+
+
+
+        // System.out.println("Checking Key-Values...");
+        // for (int i = 0; i < NUMBER_OF_TESTS; i++) {
+
+        //     String keyA = "a" + i;
+        //     String keyB = "b" + i;
+        //     String keyC = "c" + i;
+        //     String keyD = "d" + i;
+        //     String valueA = "a" + i;
+        //     String valueB = "b" + i;
+        //     String valueC = "c" + i;
+        //     String valueD = "d" + i;
+
+        //     IoTString iKeyA = new IoTString(keyA);
+        //     IoTString iKeyB = new IoTString(keyB);
+        //     IoTString iKeyC = new IoTString(keyC);
+        //     IoTString iKeyD = new IoTString(keyD);
+        //     IoTString iValueA = new IoTString(valueA);
+        //     IoTString iValueB = new IoTString(valueB);
+        //     IoTString iValueC = new IoTString(valueC);
+        //     IoTString iValueD = new IoTString(valueD);
+
+
+        //     IoTString testValA1 = t1.getCommitted(iKeyA);
+        //     IoTString testValB1 = t1.getCommitted(iKeyB);
+        //     IoTString testValC1 = t1.getCommitted(iKeyC);
+        //     IoTString testValD1 = t1.getCommitted(iKeyD);
+
+        //     IoTString testValA2 = t2.getCommitted(iKeyA);
+        //     IoTString testValB2 = t2.getCommitted(iKeyB);
+        //     IoTString testValC2 = t2.getCommitted(iKeyC);
+        //     IoTString testValD2 = t2.getCommitted(iKeyD);
+
+        //     if ((testValA1 == null) || (testValA1.equals(iValueA) == false)) {
+        //         System.out.println("Key-Value t1 incorrect: " + keyA + "    " + testValA1);
+        //         foundError = true;
+        //     }
+
+        //     if ((testValB1 == null) || (testValB1.equals(iValueB) == false)) {
+        //         System.out.println("Key-Value t1 incorrect: " + keyB + "    " + testValB1);
+        //         foundError = true;
+        //     }
+
+        //     if ((testValC1 == null) || (testValC1.equals(iValueC) == false)) {
+        //         System.out.println("Key-Value t1 incorrect: " + keyC + "    " + testValC1);
+        //         foundError = true;
+        //     }
+
+        //     if ((testValD1 == null) || (testValD1.equals(iValueD) == false)) {
+        //         System.out.println("Key-Value t1 incorrect: " + keyD + "    " + testValD1);
+        //         foundError = true;
+        //     }
+
+
+        //     if ((testValA2 == null) || (testValA2.equals(iValueA) == false)) {
+        //         System.out.println("Key-Value t2 incorrect: " + keyA + "    " + testValA2);
+        //         foundError = true;
+        //     }
+
+        //     if ((testValB2 == null) || (testValB2.equals(iValueB) == false)) {
+        //         System.out.println("Key-Value t2 incorrect: " + keyB + "    " + testValB2);
+        //         foundError = true;
+        //     }
+
+        //     if ((testValC2 == null) || (testValC2.equals(iValueC) == false)) {
+        //         System.out.println("Key-Value t2 incorrect: " + keyC + "    " + testValC2);
+        //         foundError = true;
+        //     }
+
+        //     if ((testValD2 == null) || (testValD2.equals(iValueD) == false)) {
+        //         System.out.println("Key-Value t2 incorrect: " + keyD + "    " + testValD2);
+        //         foundError = true;
+        //     }
+        // }
+
+        // for (TransactionStatus status : transStatusList) {
+        //     if (status.getStatus() != TransactionStatus.StatusCommitted) {
+        //         foundError = true;
+        //     }
+        // }
+
+        // if (foundError) {
+        //     System.out.println("Found Errors...");
+        // } else {
+        //     System.out.println("No Errors Found...");
+        // }
 
         t1.close();
         t2.close();
 
-        System.out.println();
-        System.out.println();
-        t1.printSlots();
+        // System.out.println();
+        // System.out.println();
+        // t1.printSlots();
 
-        System.out.println();
-        System.out.println();
-        t2.printSlots();
+        // System.out.println();
+        // System.out.println();
+        // t2.printSlots();
     }
 
     static void test7() throws ServerException {
@@ -1835,24 +2124,22 @@ public class Test {
     }
 
     static void test2() throws ServerException {
+        TimingSingleton timer = TimingSingleton.getInstance();
 
         boolean foundError = false;
-        long startTime = 0;
-        long endTime = 0;
         List<TransactionStatus> transStatusList = new ArrayList<TransactionStatus>();
 
         // Setup the 2 clients
-        Table t1 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 321, -1);
+        Table t1 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 321, -1);
         t1.initTable();
         System.out.println("T1 Ready");
 
-        Table t2 = new Table("http://127.0.0.1/test.iotcloud/", "reallysecret", 351, -1);
+        Table t2 = new Table("http://dc-6.calit2.uci.edu/test.iotcloud/", "reallysecret", 351, -1);
         t2.update();
         System.out.println("T2 Ready");
 
         // Make the Keys
         System.out.println("Setting up keys");
-        startTime = System.currentTimeMillis();
         for (int i = 0; i < NUMBER_OF_TESTS; i++) {
             System.out.println(i);
             String a = "a" + i;
@@ -1868,14 +2155,9 @@ public class Test {
             t2.createNewKey(ic, 321);
             t2.createNewKey(id, 351);
         }
-        endTime = System.currentTimeMillis();
-        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-        System.out.println("Time Taken Per Key: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-        System.out.println();
 
         // Do Updates for the keys
         System.out.println("Setting Key-Values...");
-        startTime = System.currentTimeMillis();
         for (int i = 0; i < NUMBER_OF_TESTS; i++) {
             System.out.println(i);
             String keyA = "a" + i;
@@ -1900,8 +2182,6 @@ public class Test {
             t1.startTransaction();
             t1.addKV(iKeyA, iValueA);
             transStatusList.add(t1.commitTransaction());
-
-
             t1.startTransaction();
             t1.addKV(iKeyB, iValueB);
             transStatusList.add(t1.commitTransaction());
@@ -1915,17 +2195,14 @@ public class Test {
             transStatusList.add(t2.commitTransaction());
 
         }
-        endTime = System.currentTimeMillis();
-        System.out.println("Time Taken: " + (double)   ((endTime - startTime) / 1000.0)    );
-        System.out.println("Time Taken Per Update: " + (double)  (((endTime - startTime) / 1000.0) / (NUMBER_OF_TESTS * 4))   );
-        System.out.println();
-
 
         System.out.println("Updating Clients...");
         t1.update();
         t2.update();
 
 
+
+
         System.out.println("Checking Key-Values...");
         for (int i = 0; i < NUMBER_OF_TESTS; i++) {
 
diff --git a/version2/src/java/iotcloud/TimingSingleton.java b/version2/src/java/iotcloud/TimingSingleton.java
new file mode 100644 (file)
index 0000000..c3ce863
--- /dev/null
@@ -0,0 +1,33 @@
+package iotcloud;
+
+
+class TimingSingleton {
+    private static TimingSingleton singleton = new TimingSingleton( );
+    private static long startTime = 0;
+
+    private static long totalTime = 0;
+
+    private TimingSingleton() {
+
+    }
+
+    public static TimingSingleton getInstance( ) {
+        return singleton;
+    }
+
+
+    public static void startTime( ) {
+        startTime = System.nanoTime();
+    }
+
+    public static void endTime( ) {
+        totalTime += System.nanoTime() - startTime;
+
+    }
+
+    public static long getTime( ) {
+        return totalTime;
+    }
+
+
+}
\ No newline at end of file
diff --git a/version2/src/server_malicious_ignore_seq/.dir-locals.el b/version2/src/server_malicious_ignore_seq/.dir-locals.el
new file mode 100644 (file)
index 0000000..e166a2e
--- /dev/null
@@ -0,0 +1,2 @@
+((nil . ((indent-tabs-mode . t))))
+
diff --git a/version2/src/server_malicious_ignore_seq/Makefile b/version2/src/server_malicious_ignore_seq/Makefile
new file mode 100644 (file)
index 0000000..8eee1fa
--- /dev/null
@@ -0,0 +1,15 @@
+CPPFLAGS=-O0 -g -Wall
+
+all: iotcloud.fcgi
+
+iotcloud.fcgi: iotcloud.o iotquery.o
+       g++ $(CPPFLAGS) -o iotcloud.fcgi iotcloud.o iotquery.o -lfcgi -lfcgi++
+
+iotcloud.o: iotcloud.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotcloud.o iotcloud.cpp
+
+iotquery.o: iotquery.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotquery.o iotquery.cpp
+
+clean:
+       rm *.o iotcloud.fcgi
diff --git a/version2/src/server_malicious_ignore_seq/README.txt b/version2/src/server_malicious_ignore_seq/README.txt
new file mode 100644 (file)
index 0000000..6eb138f
--- /dev/null
@@ -0,0 +1,32 @@
+1) Requires apache2
+2) Requires fastcgi (libapache2-mod-fastcgi and libfcgi-dev)
+
+Setup on ubuntu
+1) Install modules
+
+2) Add .htaccess file in /var/www/html
+RewriteEngine on
+RewriteBase /
+SetHandler cgi-script
+RewriteRule ^([a-zA-Z0-9._]*\.iotcloud/([a-zA-Z0-9._]*))$ /cgi-bin/iotcloud.fcgi/$1
+
+3) Create account directory.  For example, create the directory test.iotcloud in /var/www/html
+   -- To password protect, create the following .htaccess file in the account directory:
+AuthType Basic
+AuthName "Private"
+AuthUserFile /var/www/html/foo.iotcloud/.htpasswd
+Require valid-user
+
+4) In apache2.conf, add to the /var/www directory section:
+AllowOverride FileInfo AuthConfig
+
+5) In the sites-enabled/000-default.conf file, add the line:
+SetEnv IOTCLOUD_ROOT /iotcloud/
+
+6) Create the /iotcloud directory.
+
+7) Create the account directory in the /iotcloud directory.  For example, test.iotcloud and give it permissions that the apache daemon can write to.
+
+8) Compile cloud server by typing make
+
+9) Copy it to the cgi-bin directory.
diff --git a/version2/src/server_malicious_ignore_seq/iotcloud.cpp b/version2/src/server_malicious_ignore_seq/iotcloud.cpp
new file mode 100644 (file)
index 0000000..bb9eff8
--- /dev/null
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "iotquery.h"
+
+using namespace std;
+
+
+int main(void) {
+       // Backup the stdio streambufs
+       streambuf * cin_streambuf  = cin.rdbuf();
+       streambuf * cout_streambuf = cout.rdbuf();
+       streambuf * cerr_streambuf = cerr.rdbuf();
+
+       FCGX_Request request;
+
+       FCGX_Init();
+       FCGX_InitRequest(&request, 0, 0);
+
+       while (FCGX_Accept_r(&request) == 0) {
+               fcgi_streambuf cin_fcgi_streambuf(request.in);
+               fcgi_streambuf cout_fcgi_streambuf(request.out);
+               fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+               cin.rdbuf(&cin_fcgi_streambuf);
+               cout.rdbuf(&cout_fcgi_streambuf);
+               cerr.rdbuf(&cerr_fcgi_streambuf);
+
+               IoTQuery * iotquery=new IoTQuery(&request);
+               iotquery->processQuery();
+
+               delete iotquery;
+       }
+
+       // restore stdio streambufs
+       cin.rdbuf(cin_streambuf);
+       cout.rdbuf(cout_streambuf);
+       cerr.rdbuf(cerr_streambuf);
+
+       return 0;
+}
+
diff --git a/version2/src/server_malicious_ignore_seq/iotquery.cpp b/version2/src/server_malicious_ignore_seq/iotquery.cpp
new file mode 100644 (file)
index 0000000..5a7cbbd
--- /dev/null
@@ -0,0 +1,544 @@
+#include "iotquery.h"
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+using namespace std;
+
+const char * query_str = "QUERY_STRING";
+const char * uri_str = "REQUEST_URI";
+const char * method_str = "REQUEST_METHOD";
+const char * iotcloudroot_str = "IOTCLOUD_ROOT";
+const char * length_str = "CONTENT_LENGTH";
+
+IoTQuery::IoTQuery(FCGX_Request *request) :
+       request(request),
+       data(NULL),
+       directory(NULL),
+       uri(NULL),
+       query(NULL),
+       method(NULL),
+       iotcloudroot(NULL),
+       length(0),
+       oldestentry(0),
+       newestentry(0),
+       requestsequencenumber(0),
+       numqueueentries(DEFAULT_SIZE),
+       fd(-1),
+       reqGetSlot(false),
+       reqPutSlot(false),
+       reqSetSalt(false),
+       reqGetSalt(false) {
+}
+
+IoTQuery::~IoTQuery() {
+       if (fd >= 0)
+               close(fd);
+       if (directory)
+               delete directory;
+       if (data)
+               delete data;
+}
+
+/**
+ *  Returns true if the account directory exists.
+ */
+
+bool IoTQuery::checkDirectory() {
+       struct stat s;
+       int err = stat(directory, &s);
+       if (-1 == err)
+               return false;
+       return S_ISDIR(s.st_mode);
+}
+
+/**
+ * Decodes query string from client. Extracts type of request,
+ * sequence number, and whether the request changes the number of
+ * slots.
+ */
+
+void IoTQuery::decodeQuery() {
+       int len = strlen(query);
+       char * str = new char[len + 1];
+       memcpy(str, query, len + 1);
+       char *tok_ptr = str;
+
+       /* Parse commands */
+       char *command = strsep(&tok_ptr, "&");
+       if (strncmp(command, "req=putslot", 11) == 0)
+               reqPutSlot = true;
+       else if (strncmp(command, "req=getslot", 11) == 0)
+               reqGetSlot = true;
+       else if (strncmp(command, "req=setsalt", 11) == 0)
+               reqSetSalt = true;
+       else if (strncmp(command, "req=getsalt", 11) == 0)
+               reqGetSalt = true;
+
+       /* Load Sequence Number for request */
+       char *sequencenumber_str = strsep(&tok_ptr, "&");
+       if (sequencenumber_str != NULL &&
+               strncmp(sequencenumber_str, "seq=", 4) == 0) {
+               sequencenumber_str = strchr(sequencenumber_str, '=');
+               if (sequencenumber_str != NULL) {
+                       requestsequencenumber = strtoll(sequencenumber_str + 1, NULL, 10);
+               }
+       }
+
+       /* don't allow a really old sequence number */
+       if (requestsequencenumber < oldestentry)
+               requestsequencenumber = oldestentry;
+
+       /* Update size if we get request */
+       char * numqueueentries_str = tok_ptr;
+       if (numqueueentries_str != NULL &&
+               strncmp(numqueueentries_str, "max=", 4) == 0) {
+               numqueueentries_str = strchr(numqueueentries_str, '=') + 1;
+               numqueueentries = strtoll(numqueueentries_str, NULL, 10);
+       }
+
+       delete str;
+}
+
+/**
+ * Helper function to write data to file.
+ */
+
+void doWrite(int fd, char *data, long long length) {
+       long long offset = 0;
+       do {
+               long long byteswritten = write(fd, &data[offset], length);
+               if (byteswritten > 0) {
+                       length -= byteswritten;
+                       offset += byteswritten;
+               } else {
+                       cerr << "Bytes not written" << endl;
+                       if (byteswritten < 0) {
+                               cerr << strerror(errno) << " error writing slot file" << endl;
+                       }
+                       return;
+               }
+       } while (length != 0);
+}
+
+/** Helper function to read data from file. */
+bool doRead(int fd, void *buf, int numbytes) {
+       int offset = 0;
+       char *ptr = (char *)buf;
+       do {
+               int bytesread = read(fd, ptr + offset, numbytes);
+               if (bytesread > 0) {
+                       offset += bytesread;
+                       numbytes -= bytesread;
+               } else
+                       return false;
+       } while (numbytes != 0);
+       return true;
+}
+
+/**
+ * Function that handles a getSlot request.
+ */
+
+void IoTQuery::getSlot() {
+       int numrequeststosend = (int)((newestentry - requestsequencenumber) + 1);
+       if (numrequeststosend < 0)
+               numrequeststosend = 0;
+       long long numbytes = 0;
+       int filesizes[numrequeststosend];
+       int fdarray[numrequeststosend];
+       int index = 0;
+       for (long long seqn = requestsequencenumber; seqn <= newestentry; seqn++, index++) {
+               struct stat st;
+               char *filename = getSlotFileName(seqn);
+               if (stat(filename, &st) == 0) {
+                       fdarray[index] = open(filename, O_RDONLY);
+                       filesizes[index] = st.st_size;
+                       numbytes += filesizes[index];
+               } else {
+                       fdarray[index] = -1;
+                       filesizes[index] = 0;
+               }
+               delete filename;
+       }
+       const char header[] = "getslot";
+
+       /* Size is the header + the payload + space for number of requests
+                plus sizes of each slot */
+
+       long long size = sizeof(header) - 1 + sizeof(numrequeststosend) + 4 * numrequeststosend + numbytes;
+       char * response = new char[size];
+       long long offset = 0;
+       memcpy(response, header, sizeof(header) - 1);
+       offset += sizeof(header) - 1;
+       int numreq = htonl(numrequeststosend);
+       memcpy(response + offset, &numreq, sizeof(numreq));
+       offset += sizeof(numrequeststosend);
+       for (int i = 0; i < numrequeststosend; i++) {
+               int filesize = htonl(filesizes[i]);
+               memcpy(response + offset, &filesize, sizeof(filesize));
+               offset += sizeof(int);
+       }
+
+       /* Read the file data into the buffer */
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0) {
+                       doRead(fdarray[i], response + offset, filesizes[i]);
+                       offset += filesizes[i];
+               }
+       }
+
+       /* Send the response out to the webserver. */
+       sendResponse(response, size);
+
+       /* Delete the response buffer and close the files. */
+       delete response;
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0)
+                       close(fdarray[i]);
+       }
+}
+
+/**
+ * The method setSalt handles a setSalt request from the client.
+ */
+void IoTQuery::setSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int saltfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+       doWrite(saltfd, data, length);
+       char response[0];
+       sendResponse(response, 0);
+       close(saltfd);
+       delete filename;
+}
+
+/**
+ * The method getSalt handles a getSalt request from the client.
+ */
+
+void IoTQuery::getSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int filesize = 0;
+       struct stat st;
+       if (stat(filename, &st) == 0) {
+               filesize = st.st_size;
+       } else {
+               char response[0];
+               sendResponse(response, 0);
+               delete filename;
+               return;
+       }
+       int saltfd = open(filename, O_RDONLY);
+       int responsesize = filesize + sizeof(int);
+       char * response = new char[responsesize];
+       doRead(saltfd, response + sizeof(int), filesize);
+       int n_filesize = htonl(filesize);
+       *((int*) response) = n_filesize;
+       sendResponse(response, responsesize);
+       close(saltfd);
+       delete filename;
+       delete response;
+}
+
+/**
+ *     The method putSlot handles a putSlot request from the client
+ */
+
+void IoTQuery::putSlot() {
+       /* Check if the request is stale and send update in that case.  This
+                servers as an implicit failure of the request. */
+       if (requestsequencenumber != (newestentry + 1)) {
+               getSlot();
+               return;
+       }
+
+       if (requestsequencenumber == 150)
+       {
+               /* Send response acknowledging success */
+               char command[] = "putslot";
+               sendResponse(command, sizeof(command) - 1);
+               return;
+       }
+
+       /* See if we have too many slots and if so, delete the old one */
+       int numberofliveslots = (int) ((newestentry - oldestentry) + 1);
+       if (numberofliveslots >=  numqueueentries) {
+               removeOldestSlot();
+       }
+
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSlotFileName(requestsequencenumber);
+       int slotfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+       doWrite(slotfd, data, length);
+       close(slotfd);
+       delete filename;
+       newestentry = requestsequencenumber;
+
+       /* Update the seuqence numbers and other status file information. */
+       updateStatusFile();
+
+       /* Send response acknowledging success */
+       char command[] = "putslot";
+       sendResponse(command, sizeof(command) - 1);
+}
+
+/**
+ * Method sends response.  It wraps in appropriate headers for web
+ * server.
+ */
+
+void IoTQuery::sendResponse(char * bytes, int len) {
+       cout << "Accept-Ranges: bytes\r\n"
+            << "Content-Length: " << len << "\r\n"
+            << "\r\n";
+       cout.write(bytes, len);
+       cout << flush;
+}
+
+/**
+ *     Computes the name for a slot file for the given sequence number.
+ */
+
+char * IoTQuery::getSlotFileName(long long seqnum) {
+       int directorylen = strlen(directory);
+
+       /* Size is 19 digits for ASCII representation of a long + 4
+                characters for SLOT string + 1 character for null termination +
+                directory size*/
+
+       char * filename = new char[25 + directorylen];
+       snprintf(filename, 25 + directorylen, "%s/SLOT%lld", directory, seqnum);
+       return filename;
+}
+
+/**
+ *     Computes the name for a salt file
+ */
+
+char * IoTQuery::getSaltFileName() {
+       int directorylen = strlen(directory);
+
+       /* Size is 4 characters for SALT string + 1 character for null
+                termination + directory size*/
+
+       char * filename = new char[6 + directorylen];
+       snprintf(filename, 6 + directorylen, "%s/SALT", directory);
+       return filename;
+}
+
+/**
+ *  Removes the oldest slot file
+ */
+
+void IoTQuery::removeOldestSlot() {
+       if (oldestentry != 0) {
+               char * filename = getSlotFileName(oldestentry);
+               unlink(filename);
+               delete filename;
+       }
+       oldestentry++;
+}
+
+/**
+ * Processes the query sent to the fastcgi handler.
+ */
+
+void IoTQuery::processQuery() {
+       getQuery();
+       getDirectory();
+       // readData();
+       if (!readData())
+       {
+               cerr << "No Data Available" << endl;
+               return;
+       }
+
+
+       /* Verify that we receive a post request. */
+       if (strncmp(method, "POST", 4) != 0) {
+               cerr << "Not POST Request" << endl;
+               return;
+       }
+
+       /* Make sure the directory is okay. */
+       if (directory == NULL ||
+               !checkDirectory()) {
+               cerr << "Directory " << directory << " does not exist" << endl;
+               return;
+       }
+
+       /* Get queue state from the status file.  If it doesn't exist,
+                create it. */
+       if (!openStatusFile()) {
+               cerr << "Failed to open status file" << endl;
+               return;
+       }
+
+       /* Lock status file to keep other requests out. */
+       flock(fd, LOCK_EX);
+
+       /* Decode query. */
+       decodeQuery();
+
+       /* Handle request. */
+       if (reqGetSlot)
+               getSlot();
+       else if (reqPutSlot)
+               putSlot();
+       else if (reqSetSalt)
+               setSalt();
+       else if (reqGetSalt)
+               getSalt();
+       else {
+               cerr << "No recognized request" << endl;
+               return;
+       }
+}
+
+/**
+ * Reads in data for request.  This is used for the slot to be
+ * inserted.
+ */
+
+bool IoTQuery::readData() {
+       if (length != 0) {
+               data = new char[length + 1];
+               memset(data, 0, length + 1);
+               cin.read(data, length);
+       }
+
+       do {
+               char dummy;
+               cin >> dummy;
+       } while (!cin.eof());
+
+       if (length != 0)
+       {
+               if (cin.gcount() != length)
+               {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+
+/**
+ * Reads relevant environmental variables to find out the request.
+ */
+
+void IoTQuery::getQuery() {
+       uri = FCGX_GetParam(uri_str, request->envp);
+       query = FCGX_GetParam(query_str, request->envp);
+       method = FCGX_GetParam(method_str, request->envp);
+       iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp);
+
+       /** We require the content-length header to be sent. */
+       char * reqlength = FCGX_GetParam(length_str, request->envp);
+       if (reqlength) {
+               length = strtoll(reqlength, NULL, 10);
+       } else {
+               length = 0;
+       }
+}
+
+/**
+ *  Initializes directory field from environmental variables.
+ */
+
+void IoTQuery::getDirectory() {
+       char * split = strchr((char *)uri, '?');
+       if (split == NULL)
+               return;
+       int split_len = (int) (split - uri);
+       int rootdir_len = strlen(iotcloudroot);
+       int directory_len = split_len + rootdir_len + 1;
+       directory = new char[directory_len];
+       memcpy(directory, iotcloudroot, rootdir_len);
+       memcpy(directory + rootdir_len, uri, split_len);
+       directory[directory_len - 1] = 0;
+}
+
+/**
+ * Helper function that is used to read the status file.
+ */
+
+int doread(int fd, void *ptr, size_t count, off_t offset) {
+       do {
+               size_t bytesread = pread(fd, ptr, count, offset);
+               if (bytesread == count) {
+                       return 1;
+               } else if (bytesread == 0) {
+                       return 0;
+               }
+       } while (1);
+}
+
+
+/**
+ * Writes the current state to the status file.
+ */
+
+void IoTQuery::updateStatusFile() {
+       pwrite(fd, &numqueueentries, sizeof(numqueueentries), OFFSET_MAX);
+       pwrite(fd, &oldestentry, sizeof(oldestentry), OFFSET_OLD);
+       pwrite(fd, &newestentry, sizeof(newestentry), OFFSET_NEW);
+}
+
+/**
+ * Reads in queue state from the status file.  Returns true if
+ * successful.
+ */
+
+bool IoTQuery::openStatusFile() {
+       char statusfile[] = "queuestatus";
+       int len = strlen(directory);
+
+       char * filename = new char[len + sizeof(statusfile) + 2];
+       memcpy(filename, directory, len);
+       filename[len] = '/';
+       memcpy(filename + len + 1, statusfile, sizeof(statusfile));
+       filename[len + sizeof(statusfile) + 1] = 0;
+       fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+       delete filename;
+
+       if (fd < 0) {
+               cerr << strerror(errno) << " error opening statusfile" << endl;
+               return false;
+       }
+
+       /* Read in queue size, oldest sequence number, and newest sequence number. */
+       int size;
+       int needwrite = 0;
+       if (doread(fd, &size, sizeof(size), OFFSET_MAX))
+               numqueueentries = size;
+       else
+               needwrite = 1;
+
+       long long entry;
+       if (doread(fd, &entry, sizeof(entry), OFFSET_OLD))
+               oldestentry = entry;
+       else
+               needwrite = 1;
+
+       if (doread(fd, &entry, sizeof(entry), OFFSET_NEW))
+               newestentry = entry;
+       else
+               needwrite = 1;
+
+       if (needwrite)
+               updateStatusFile();
+
+       return true;
+}
+
+
diff --git a/version2/src/server_malicious_ignore_seq/iotquery.h b/version2/src/server_malicious_ignore_seq/iotquery.h
new file mode 100644 (file)
index 0000000..6ac5113
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef IOTQUERY_H
+#define IOTQUERY_H
+#include <iostream>
+#include "fcgio.h"
+#include "fcgi_stdio.h"
+
+#define DEFAULT_SIZE 128
+#define OFFSET_MAX 0
+#define OFFSET_OLD 4
+#define OFFSET_NEW 12
+
+class IoTQuery {
+public:
+       IoTQuery(FCGX_Request * request);
+       ~IoTQuery();
+       void processQuery();
+
+private:
+       void sendResponse(char *data, int length);
+       void getQuery();
+       void getDirectory();
+       bool readData();
+       bool checkDirectory();
+       bool openStatusFile();
+       void updateStatusFile();
+       void decodeQuery();
+       void getSlot();
+       void putSlot();
+       void setSalt();
+       void getSalt();
+       void removeOldestSlot();
+       char * getSlotFileName(long long);
+       char * getSaltFileName();
+
+       FCGX_Request * request;
+       char *data;
+       /* Directory slot files are placed in. */
+       char *directory;
+       /* Full URI from Apache */
+       const char * uri;
+       /* Query portion of URI */
+       const char * query;
+       /* Type of request: GET or PUT */
+       const char * method;
+       /* Root directory for all accounts */
+       const char * iotcloudroot;
+       /* Expected length of data from client */
+       long long length;
+       /* Sequence number for oldest slot */
+       long long oldestentry;
+       /* Sequence number for newest slot */
+       long long newestentry;
+       /* Sequence number from request */
+       long long requestsequencenumber;
+       /* Size of queue */
+       int numqueueentries;
+       /* fd for queuestatus file */
+       int fd;
+       /* Is the request to get a slot? */
+       bool reqGetSlot;
+       /* Is the request to put a slot? */
+       bool reqPutSlot;
+       /* Is the request to set the salt? */
+       bool reqSetSalt;
+       /* Is the request to get the salt? */
+       bool reqGetSalt;
+};
+#endif
diff --git a/version2/src/server_malicious_override_do_rej/.dir-locals.el b/version2/src/server_malicious_override_do_rej/.dir-locals.el
new file mode 100644 (file)
index 0000000..e166a2e
--- /dev/null
@@ -0,0 +1,2 @@
+((nil . ((indent-tabs-mode . t))))
+
diff --git a/version2/src/server_malicious_override_do_rej/Makefile b/version2/src/server_malicious_override_do_rej/Makefile
new file mode 100644 (file)
index 0000000..8eee1fa
--- /dev/null
@@ -0,0 +1,15 @@
+CPPFLAGS=-O0 -g -Wall
+
+all: iotcloud.fcgi
+
+iotcloud.fcgi: iotcloud.o iotquery.o
+       g++ $(CPPFLAGS) -o iotcloud.fcgi iotcloud.o iotquery.o -lfcgi -lfcgi++
+
+iotcloud.o: iotcloud.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotcloud.o iotcloud.cpp
+
+iotquery.o: iotquery.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotquery.o iotquery.cpp
+
+clean:
+       rm *.o iotcloud.fcgi
diff --git a/version2/src/server_malicious_override_do_rej/README.txt b/version2/src/server_malicious_override_do_rej/README.txt
new file mode 100644 (file)
index 0000000..6eb138f
--- /dev/null
@@ -0,0 +1,32 @@
+1) Requires apache2
+2) Requires fastcgi (libapache2-mod-fastcgi and libfcgi-dev)
+
+Setup on ubuntu
+1) Install modules
+
+2) Add .htaccess file in /var/www/html
+RewriteEngine on
+RewriteBase /
+SetHandler cgi-script
+RewriteRule ^([a-zA-Z0-9._]*\.iotcloud/([a-zA-Z0-9._]*))$ /cgi-bin/iotcloud.fcgi/$1
+
+3) Create account directory.  For example, create the directory test.iotcloud in /var/www/html
+   -- To password protect, create the following .htaccess file in the account directory:
+AuthType Basic
+AuthName "Private"
+AuthUserFile /var/www/html/foo.iotcloud/.htpasswd
+Require valid-user
+
+4) In apache2.conf, add to the /var/www directory section:
+AllowOverride FileInfo AuthConfig
+
+5) In the sites-enabled/000-default.conf file, add the line:
+SetEnv IOTCLOUD_ROOT /iotcloud/
+
+6) Create the /iotcloud directory.
+
+7) Create the account directory in the /iotcloud directory.  For example, test.iotcloud and give it permissions that the apache daemon can write to.
+
+8) Compile cloud server by typing make
+
+9) Copy it to the cgi-bin directory.
diff --git a/version2/src/server_malicious_override_do_rej/iotcloud.cpp b/version2/src/server_malicious_override_do_rej/iotcloud.cpp
new file mode 100644 (file)
index 0000000..bb9eff8
--- /dev/null
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "iotquery.h"
+
+using namespace std;
+
+
+int main(void) {
+       // Backup the stdio streambufs
+       streambuf * cin_streambuf  = cin.rdbuf();
+       streambuf * cout_streambuf = cout.rdbuf();
+       streambuf * cerr_streambuf = cerr.rdbuf();
+
+       FCGX_Request request;
+
+       FCGX_Init();
+       FCGX_InitRequest(&request, 0, 0);
+
+       while (FCGX_Accept_r(&request) == 0) {
+               fcgi_streambuf cin_fcgi_streambuf(request.in);
+               fcgi_streambuf cout_fcgi_streambuf(request.out);
+               fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+               cin.rdbuf(&cin_fcgi_streambuf);
+               cout.rdbuf(&cout_fcgi_streambuf);
+               cerr.rdbuf(&cerr_fcgi_streambuf);
+
+               IoTQuery * iotquery=new IoTQuery(&request);
+               iotquery->processQuery();
+
+               delete iotquery;
+       }
+
+       // restore stdio streambufs
+       cin.rdbuf(cin_streambuf);
+       cout.rdbuf(cout_streambuf);
+       cerr.rdbuf(cerr_streambuf);
+
+       return 0;
+}
+
diff --git a/version2/src/server_malicious_override_do_rej/iotquery.cpp b/version2/src/server_malicious_override_do_rej/iotquery.cpp
new file mode 100644 (file)
index 0000000..fb05a2e
--- /dev/null
@@ -0,0 +1,555 @@
+#include "iotquery.h"
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+using namespace std;
+
+const char * query_str = "QUERY_STRING";
+const char * uri_str = "REQUEST_URI";
+const char * method_str = "REQUEST_METHOD";
+const char * iotcloudroot_str = "IOTCLOUD_ROOT";
+const char * length_str = "CONTENT_LENGTH";
+
+IoTQuery::IoTQuery(FCGX_Request *request) :
+       request(request),
+       data(NULL),
+       directory(NULL),
+       uri(NULL),
+       query(NULL),
+       method(NULL),
+       iotcloudroot(NULL),
+       length(0),
+       oldestentry(0),
+       newestentry(0),
+       requestsequencenumber(0),
+       numqueueentries(DEFAULT_SIZE),
+       fd(-1),
+       reqGetSlot(false),
+       reqPutSlot(false),
+       reqSetSalt(false),
+       reqGetSalt(false) {
+}
+
+IoTQuery::~IoTQuery() {
+       if (fd >= 0)
+               close(fd);
+       if (directory)
+               delete directory;
+       if (data)
+               delete data;
+}
+
+/**
+ *  Returns true if the account directory exists.
+ */
+
+bool IoTQuery::checkDirectory() {
+       struct stat s;
+       int err = stat(directory, &s);
+       if (-1 == err)
+               return false;
+       return S_ISDIR(s.st_mode);
+}
+
+/**
+ * Decodes query string from client. Extracts type of request,
+ * sequence number, and whether the request changes the number of
+ * slots.
+ */
+
+void IoTQuery::decodeQuery() {
+       int len = strlen(query);
+       char * str = new char[len + 1];
+       memcpy(str, query, len + 1);
+       char *tok_ptr = str;
+
+       /* Parse commands */
+       char *command = strsep(&tok_ptr, "&");
+       if (strncmp(command, "req=putslot", 11) == 0)
+               reqPutSlot = true;
+       else if (strncmp(command, "req=getslot", 11) == 0)
+               reqGetSlot = true;
+       else if (strncmp(command, "req=setsalt", 11) == 0)
+               reqSetSalt = true;
+       else if (strncmp(command, "req=getsalt", 11) == 0)
+               reqGetSalt = true;
+
+       /* Load Sequence Number for request */
+       char *sequencenumber_str = strsep(&tok_ptr, "&");
+       if (sequencenumber_str != NULL &&
+               strncmp(sequencenumber_str, "seq=", 4) == 0) {
+               sequencenumber_str = strchr(sequencenumber_str, '=');
+               if (sequencenumber_str != NULL) {
+                       requestsequencenumber = strtoll(sequencenumber_str + 1, NULL, 10);
+               }
+       }
+
+       /* don't allow a really old sequence number */
+       if (requestsequencenumber < oldestentry)
+               requestsequencenumber = oldestentry;
+
+       /* Update size if we get request */
+       char * numqueueentries_str = tok_ptr;
+       if (numqueueentries_str != NULL &&
+               strncmp(numqueueentries_str, "max=", 4) == 0) {
+               numqueueentries_str = strchr(numqueueentries_str, '=') + 1;
+               numqueueentries = strtoll(numqueueentries_str, NULL, 10);
+       }
+
+       delete str;
+}
+
+/**
+ * Helper function to write data to file.
+ */
+
+void doWrite(int fd, char *data, long long length) {
+       long long offset = 0;
+       do {
+               long long byteswritten = write(fd, &data[offset], length);
+               if (byteswritten > 0) {
+                       length -= byteswritten;
+                       offset += byteswritten;
+               } else {
+                       cerr << "Bytes not written" << endl;
+                       if (byteswritten < 0) {
+                               cerr << strerror(errno) << " error writing slot file" << endl;
+                       }
+                       return;
+               }
+       } while (length != 0);
+}
+
+/** Helper function to read data from file. */
+bool doRead(int fd, void *buf, int numbytes) {
+       int offset = 0;
+       char *ptr = (char *)buf;
+       do {
+               int bytesread = read(fd, ptr + offset, numbytes);
+               if (bytesread > 0) {
+                       offset += bytesread;
+                       numbytes -= bytesread;
+               } else
+                       return false;
+       } while (numbytes != 0);
+       return true;
+}
+
+/**
+ * Function that handles a getSlot request.
+ */
+
+void IoTQuery::getSlot() {
+       int numrequeststosend = (int)((newestentry - requestsequencenumber) + 1);
+       if (numrequeststosend < 0)
+               numrequeststosend = 0;
+       long long numbytes = 0;
+       int filesizes[numrequeststosend];
+       int fdarray[numrequeststosend];
+       int index = 0;
+       for (long long seqn = requestsequencenumber; seqn <= newestentry; seqn++, index++) {
+               struct stat st;
+               char *filename = getSlotFileName(seqn);
+               if (stat(filename, &st) == 0) {
+                       fdarray[index] = open(filename, O_RDONLY);
+                       filesizes[index] = st.st_size;
+                       numbytes += filesizes[index];
+               } else {
+                       fdarray[index] = -1;
+                       filesizes[index] = 0;
+               }
+               delete filename;
+       }
+       const char header[] = "getslot";
+
+       /* Size is the header + the payload + space for number of requests
+                plus sizes of each slot */
+
+       long long size = sizeof(header) - 1 + sizeof(numrequeststosend) + 4 * numrequeststosend + numbytes;
+       char * response = new char[size];
+       long long offset = 0;
+       memcpy(response, header, sizeof(header) - 1);
+       offset += sizeof(header) - 1;
+       int numreq = htonl(numrequeststosend);
+       memcpy(response + offset, &numreq, sizeof(numreq));
+       offset += sizeof(numrequeststosend);
+       for (int i = 0; i < numrequeststosend; i++) {
+               int filesize = htonl(filesizes[i]);
+               memcpy(response + offset, &filesize, sizeof(filesize));
+               offset += sizeof(int);
+       }
+
+       /* Read the file data into the buffer */
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0) {
+                       doRead(fdarray[i], response + offset, filesizes[i]);
+                       offset += filesizes[i];
+               }
+       }
+
+       /* Send the response out to the webserver. */
+       sendResponse(response, size);
+
+       /* Delete the response buffer and close the files. */
+       delete response;
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0)
+                       close(fdarray[i]);
+       }
+}
+
+/**
+ * The method setSalt handles a setSalt request from the client.
+ */
+void IoTQuery::setSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int saltfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+       doWrite(saltfd, data, length);
+       char response[0];
+       sendResponse(response, 0);
+       close(saltfd);
+       delete filename;
+}
+
+/**
+ * The method getSalt handles a getSalt request from the client.
+ */
+
+void IoTQuery::getSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int filesize = 0;
+       struct stat st;
+       if (stat(filename, &st) == 0) {
+               filesize = st.st_size;
+       } else {
+               char response[0];
+               sendResponse(response, 0);
+               delete filename;
+               return;
+       }
+       int saltfd = open(filename, O_RDONLY);
+       int responsesize = filesize + sizeof(int);
+       char * response = new char[responsesize];
+       doRead(saltfd, response + sizeof(int), filesize);
+       int n_filesize = htonl(filesize);
+       *((int*) response) = n_filesize;
+       sendResponse(response, responsesize);
+       close(saltfd);
+       delete filename;
+       delete response;
+}
+
+/**
+ *     The method putSlot handles a putSlot request from the client
+ */
+
+void IoTQuery::putSlot() {
+       /* Check if the request is stale and send update in that case.  This
+                servers as an implicit failure of the request. */
+       if (requestsequencenumber == 150)
+       {
+               if (requestsequencenumber != (newestentry + 1)) {
+
+                       /* Write the slot data we received to a SLOT file */
+                       char *filename = getSlotFileName(requestsequencenumber);
+                       unlink(filename);
+                       int slotfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+                       doWrite(slotfd, data, length);
+                       close(slotfd);
+                       delete filename;
+
+                       getSlot();
+                       return;
+               }
+       }
+
+
+
+       if (requestsequencenumber != (newestentry + 1)) {
+               getSlot();
+               return;
+       }
+
+       /* See if we have too many slots and if so, delete the old one */
+       int numberofliveslots = (int) ((newestentry - oldestentry) + 1);
+       if (numberofliveslots >=  numqueueentries) {
+               removeOldestSlot();
+       }
+
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSlotFileName(requestsequencenumber);
+       int slotfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+       doWrite(slotfd, data, length);
+       close(slotfd);
+       delete filename;
+       newestentry = requestsequencenumber;
+
+       /* Update the seuqence numbers and other status file information. */
+       updateStatusFile();
+
+       /* Send response acknowledging success */
+       char command[] = "putslot";
+       sendResponse(command, sizeof(command) - 1);
+}
+
+/**
+ * Method sends response.  It wraps in appropriate headers for web
+ * server.
+ */
+
+void IoTQuery::sendResponse(char * bytes, int len) {
+       cout << "Accept-Ranges: bytes\r\n"
+            << "Content-Length: " << len << "\r\n"
+            << "\r\n";
+       cout.write(bytes, len);
+       cout << flush;
+}
+
+/**
+ *     Computes the name for a slot file for the given sequence number.
+ */
+
+char * IoTQuery::getSlotFileName(long long seqnum) {
+       int directorylen = strlen(directory);
+
+       /* Size is 19 digits for ASCII representation of a long + 4
+                characters for SLOT string + 1 character for null termination +
+                directory size*/
+
+       char * filename = new char[25 + directorylen];
+       snprintf(filename, 25 + directorylen, "%s/SLOT%lld", directory, seqnum);
+       return filename;
+}
+
+/**
+ *     Computes the name for a salt file
+ */
+
+char * IoTQuery::getSaltFileName() {
+       int directorylen = strlen(directory);
+
+       /* Size is 4 characters for SALT string + 1 character for null
+                termination + directory size*/
+
+       char * filename = new char[6 + directorylen];
+       snprintf(filename, 6 + directorylen, "%s/SALT", directory);
+       return filename;
+}
+
+/**
+ *  Removes the oldest slot file
+ */
+
+void IoTQuery::removeOldestSlot() {
+       if (oldestentry != 0) {
+               char * filename = getSlotFileName(oldestentry);
+               unlink(filename);
+               delete filename;
+       }
+       oldestentry++;
+}
+
+/**
+ * Processes the query sent to the fastcgi handler.
+ */
+
+void IoTQuery::processQuery() {
+       getQuery();
+       getDirectory();
+       // readData();
+       if (!readData())
+       {
+               cerr << "No Data Available" << endl;
+               return;
+       }
+
+
+       /* Verify that we receive a post request. */
+       if (strncmp(method, "POST", 4) != 0) {
+               cerr << "Not POST Request" << endl;
+               return;
+       }
+
+       /* Make sure the directory is okay. */
+       if (directory == NULL ||
+               !checkDirectory()) {
+               cerr << "Directory " << directory << " does not exist" << endl;
+               return;
+       }
+
+       /* Get queue state from the status file.  If it doesn't exist,
+                create it. */
+       if (!openStatusFile()) {
+               cerr << "Failed to open status file" << endl;
+               return;
+       }
+
+       /* Lock status file to keep other requests out. */
+       flock(fd, LOCK_EX);
+
+       /* Decode query. */
+       decodeQuery();
+
+       /* Handle request. */
+       if (reqGetSlot)
+               getSlot();
+       else if (reqPutSlot)
+               putSlot();
+       else if (reqSetSalt)
+               setSalt();
+       else if (reqGetSalt)
+               getSalt();
+       else {
+               cerr << "No recognized request" << endl;
+               return;
+       }
+}
+
+/**
+ * Reads in data for request.  This is used for the slot to be
+ * inserted.
+ */
+
+bool IoTQuery::readData() {
+       if (length != 0) {
+               data = new char[length + 1];
+               memset(data, 0, length + 1);
+               cin.read(data, length);
+       }
+
+       do {
+               char dummy;
+               cin >> dummy;
+       } while (!cin.eof());
+
+       if (length != 0)
+       {
+               if (cin.gcount() != length)
+               {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+
+/**
+ * Reads relevant environmental variables to find out the request.
+ */
+
+void IoTQuery::getQuery() {
+       uri = FCGX_GetParam(uri_str, request->envp);
+       query = FCGX_GetParam(query_str, request->envp);
+       method = FCGX_GetParam(method_str, request->envp);
+       iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp);
+
+       /** We require the content-length header to be sent. */
+       char * reqlength = FCGX_GetParam(length_str, request->envp);
+       if (reqlength) {
+               length = strtoll(reqlength, NULL, 10);
+       } else {
+               length = 0;
+       }
+}
+
+/**
+ *  Initializes directory field from environmental variables.
+ */
+
+void IoTQuery::getDirectory() {
+       char * split = strchr((char *)uri, '?');
+       if (split == NULL)
+               return;
+       int split_len = (int) (split - uri);
+       int rootdir_len = strlen(iotcloudroot);
+       int directory_len = split_len + rootdir_len + 1;
+       directory = new char[directory_len];
+       memcpy(directory, iotcloudroot, rootdir_len);
+       memcpy(directory + rootdir_len, uri, split_len);
+       directory[directory_len - 1] = 0;
+}
+
+/**
+ * Helper function that is used to read the status file.
+ */
+
+int doread(int fd, void *ptr, size_t count, off_t offset) {
+       do {
+               size_t bytesread = pread(fd, ptr, count, offset);
+               if (bytesread == count) {
+                       return 1;
+               } else if (bytesread == 0) {
+                       return 0;
+               }
+       } while (1);
+}
+
+
+/**
+ * Writes the current state to the status file.
+ */
+
+void IoTQuery::updateStatusFile() {
+       pwrite(fd, &numqueueentries, sizeof(numqueueentries), OFFSET_MAX);
+       pwrite(fd, &oldestentry, sizeof(oldestentry), OFFSET_OLD);
+       pwrite(fd, &newestentry, sizeof(newestentry), OFFSET_NEW);
+}
+
+/**
+ * Reads in queue state from the status file.  Returns true if
+ * successful.
+ */
+
+bool IoTQuery::openStatusFile() {
+       char statusfile[] = "queuestatus";
+       int len = strlen(directory);
+
+       char * filename = new char[len + sizeof(statusfile) + 2];
+       memcpy(filename, directory, len);
+       filename[len] = '/';
+       memcpy(filename + len + 1, statusfile, sizeof(statusfile));
+       filename[len + sizeof(statusfile) + 1] = 0;
+       fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+       delete filename;
+
+       if (fd < 0) {
+               cerr << strerror(errno) << " error opening statusfile" << endl;
+               return false;
+       }
+
+       /* Read in queue size, oldest sequence number, and newest sequence number. */
+       int size;
+       int needwrite = 0;
+       if (doread(fd, &size, sizeof(size), OFFSET_MAX))
+               numqueueentries = size;
+       else
+               needwrite = 1;
+
+       long long entry;
+       if (doread(fd, &entry, sizeof(entry), OFFSET_OLD))
+               oldestentry = entry;
+       else
+               needwrite = 1;
+
+       if (doread(fd, &entry, sizeof(entry), OFFSET_NEW))
+               newestentry = entry;
+       else
+               needwrite = 1;
+
+       if (needwrite)
+               updateStatusFile();
+
+       return true;
+}
+
+
diff --git a/version2/src/server_malicious_override_do_rej/iotquery.h b/version2/src/server_malicious_override_do_rej/iotquery.h
new file mode 100644 (file)
index 0000000..6ac5113
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef IOTQUERY_H
+#define IOTQUERY_H
+#include <iostream>
+#include "fcgio.h"
+#include "fcgi_stdio.h"
+
+#define DEFAULT_SIZE 128
+#define OFFSET_MAX 0
+#define OFFSET_OLD 4
+#define OFFSET_NEW 12
+
+class IoTQuery {
+public:
+       IoTQuery(FCGX_Request * request);
+       ~IoTQuery();
+       void processQuery();
+
+private:
+       void sendResponse(char *data, int length);
+       void getQuery();
+       void getDirectory();
+       bool readData();
+       bool checkDirectory();
+       bool openStatusFile();
+       void updateStatusFile();
+       void decodeQuery();
+       void getSlot();
+       void putSlot();
+       void setSalt();
+       void getSalt();
+       void removeOldestSlot();
+       char * getSlotFileName(long long);
+       char * getSaltFileName();
+
+       FCGX_Request * request;
+       char *data;
+       /* Directory slot files are placed in. */
+       char *directory;
+       /* Full URI from Apache */
+       const char * uri;
+       /* Query portion of URI */
+       const char * query;
+       /* Type of request: GET or PUT */
+       const char * method;
+       /* Root directory for all accounts */
+       const char * iotcloudroot;
+       /* Expected length of data from client */
+       long long length;
+       /* Sequence number for oldest slot */
+       long long oldestentry;
+       /* Sequence number for newest slot */
+       long long newestentry;
+       /* Sequence number from request */
+       long long requestsequencenumber;
+       /* Size of queue */
+       int numqueueentries;
+       /* fd for queuestatus file */
+       int fd;
+       /* Is the request to get a slot? */
+       bool reqGetSlot;
+       /* Is the request to put a slot? */
+       bool reqPutSlot;
+       /* Is the request to set the salt? */
+       bool reqSetSalt;
+       /* Is the request to get the salt? */
+       bool reqGetSalt;
+};
+#endif
diff --git a/version2/src/server_malicious_switch_slot/.dir-locals.el b/version2/src/server_malicious_switch_slot/.dir-locals.el
new file mode 100644 (file)
index 0000000..e166a2e
--- /dev/null
@@ -0,0 +1,2 @@
+((nil . ((indent-tabs-mode . t))))
+
diff --git a/version2/src/server_malicious_switch_slot/Makefile b/version2/src/server_malicious_switch_slot/Makefile
new file mode 100644 (file)
index 0000000..8eee1fa
--- /dev/null
@@ -0,0 +1,15 @@
+CPPFLAGS=-O0 -g -Wall
+
+all: iotcloud.fcgi
+
+iotcloud.fcgi: iotcloud.o iotquery.o
+       g++ $(CPPFLAGS) -o iotcloud.fcgi iotcloud.o iotquery.o -lfcgi -lfcgi++
+
+iotcloud.o: iotcloud.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotcloud.o iotcloud.cpp
+
+iotquery.o: iotquery.cpp iotquery.h
+       g++ $(CPPFLAGS) -c -o iotquery.o iotquery.cpp
+
+clean:
+       rm *.o iotcloud.fcgi
diff --git a/version2/src/server_malicious_switch_slot/README.txt b/version2/src/server_malicious_switch_slot/README.txt
new file mode 100644 (file)
index 0000000..6eb138f
--- /dev/null
@@ -0,0 +1,32 @@
+1) Requires apache2
+2) Requires fastcgi (libapache2-mod-fastcgi and libfcgi-dev)
+
+Setup on ubuntu
+1) Install modules
+
+2) Add .htaccess file in /var/www/html
+RewriteEngine on
+RewriteBase /
+SetHandler cgi-script
+RewriteRule ^([a-zA-Z0-9._]*\.iotcloud/([a-zA-Z0-9._]*))$ /cgi-bin/iotcloud.fcgi/$1
+
+3) Create account directory.  For example, create the directory test.iotcloud in /var/www/html
+   -- To password protect, create the following .htaccess file in the account directory:
+AuthType Basic
+AuthName "Private"
+AuthUserFile /var/www/html/foo.iotcloud/.htpasswd
+Require valid-user
+
+4) In apache2.conf, add to the /var/www directory section:
+AllowOverride FileInfo AuthConfig
+
+5) In the sites-enabled/000-default.conf file, add the line:
+SetEnv IOTCLOUD_ROOT /iotcloud/
+
+6) Create the /iotcloud directory.
+
+7) Create the account directory in the /iotcloud directory.  For example, test.iotcloud and give it permissions that the apache daemon can write to.
+
+8) Compile cloud server by typing make
+
+9) Copy it to the cgi-bin directory.
diff --git a/version2/src/server_malicious_switch_slot/iotcloud.cpp b/version2/src/server_malicious_switch_slot/iotcloud.cpp
new file mode 100644 (file)
index 0000000..bb9eff8
--- /dev/null
@@ -0,0 +1,40 @@
+#include <iostream>
+#include "iotquery.h"
+
+using namespace std;
+
+
+int main(void) {
+       // Backup the stdio streambufs
+       streambuf * cin_streambuf  = cin.rdbuf();
+       streambuf * cout_streambuf = cout.rdbuf();
+       streambuf * cerr_streambuf = cerr.rdbuf();
+
+       FCGX_Request request;
+
+       FCGX_Init();
+       FCGX_InitRequest(&request, 0, 0);
+
+       while (FCGX_Accept_r(&request) == 0) {
+               fcgi_streambuf cin_fcgi_streambuf(request.in);
+               fcgi_streambuf cout_fcgi_streambuf(request.out);
+               fcgi_streambuf cerr_fcgi_streambuf(request.err);
+
+               cin.rdbuf(&cin_fcgi_streambuf);
+               cout.rdbuf(&cout_fcgi_streambuf);
+               cerr.rdbuf(&cerr_fcgi_streambuf);
+
+               IoTQuery * iotquery=new IoTQuery(&request);
+               iotquery->processQuery();
+
+               delete iotquery;
+       }
+
+       // restore stdio streambufs
+       cin.rdbuf(cin_streambuf);
+       cout.rdbuf(cout_streambuf);
+       cerr.rdbuf(cerr_streambuf);
+
+       return 0;
+}
+
diff --git a/version2/src/server_malicious_switch_slot/iotquery.cpp b/version2/src/server_malicious_switch_slot/iotquery.cpp
new file mode 100644 (file)
index 0000000..5661ccf
--- /dev/null
@@ -0,0 +1,543 @@
+#include "iotquery.h"
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/file.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <netinet/in.h>
+
+using namespace std;
+
+const char * query_str = "QUERY_STRING";
+const char * uri_str = "REQUEST_URI";
+const char * method_str = "REQUEST_METHOD";
+const char * iotcloudroot_str = "IOTCLOUD_ROOT";
+const char * length_str = "CONTENT_LENGTH";
+
+IoTQuery::IoTQuery(FCGX_Request *request) :
+       request(request),
+       data(NULL),
+       directory(NULL),
+       uri(NULL),
+       query(NULL),
+       method(NULL),
+       iotcloudroot(NULL),
+       length(0),
+       oldestentry(0),
+       newestentry(0),
+       requestsequencenumber(0),
+       numqueueentries(DEFAULT_SIZE),
+       fd(-1),
+       reqGetSlot(false),
+       reqPutSlot(false),
+       reqSetSalt(false),
+       reqGetSalt(false) {
+}
+
+IoTQuery::~IoTQuery() {
+       if (fd >= 0)
+               close(fd);
+       if (directory)
+               delete directory;
+       if (data)
+               delete data;
+}
+
+/**
+ *  Returns true if the account directory exists.
+ */
+
+bool IoTQuery::checkDirectory() {
+       struct stat s;
+       int err = stat(directory, &s);
+       if (-1 == err)
+               return false;
+       return S_ISDIR(s.st_mode);
+}
+
+/**
+ * Decodes query string from client. Extracts type of request,
+ * sequence number, and whether the request changes the number of
+ * slots.
+ */
+
+void IoTQuery::decodeQuery() {
+       int len = strlen(query);
+       char * str = new char[len + 1];
+       memcpy(str, query, len + 1);
+       char *tok_ptr = str;
+
+       /* Parse commands */
+       char *command = strsep(&tok_ptr, "&");
+       if (strncmp(command, "req=putslot", 11) == 0)
+               reqPutSlot = true;
+       else if (strncmp(command, "req=getslot", 11) == 0)
+               reqGetSlot = true;
+       else if (strncmp(command, "req=setsalt", 11) == 0)
+               reqSetSalt = true;
+       else if (strncmp(command, "req=getsalt", 11) == 0)
+               reqGetSalt = true;
+
+       /* Load Sequence Number for request */
+       char *sequencenumber_str = strsep(&tok_ptr, "&");
+       if (sequencenumber_str != NULL &&
+               strncmp(sequencenumber_str, "seq=", 4) == 0) {
+               sequencenumber_str = strchr(sequencenumber_str, '=');
+               if (sequencenumber_str != NULL) {
+                       requestsequencenumber = strtoll(sequencenumber_str + 1, NULL, 10);
+               }
+       }
+
+       /* don't allow a really old sequence number */
+       if (requestsequencenumber < oldestentry)
+               requestsequencenumber = oldestentry;
+
+       /* Update size if we get request */
+       char * numqueueentries_str = tok_ptr;
+       if (numqueueentries_str != NULL &&
+               strncmp(numqueueentries_str, "max=", 4) == 0) {
+               numqueueentries_str = strchr(numqueueentries_str, '=') + 1;
+               numqueueentries = strtoll(numqueueentries_str, NULL, 10);
+       }
+
+       delete str;
+}
+
+/**
+ * Helper function to write data to file.
+ */
+
+void doWrite(int fd, char *data, long long length) {
+       long long offset = 0;
+       do {
+               long long byteswritten = write(fd, &data[offset], length);
+               if (byteswritten > 0) {
+                       length -= byteswritten;
+                       offset += byteswritten;
+               } else {
+                       cerr << "Bytes not written" << endl;
+                       if (byteswritten < 0) {
+                               cerr << strerror(errno) << " error writing slot file" << endl;
+                       }
+                       return;
+               }
+       } while (length != 0);
+}
+
+/** Helper function to read data from file. */
+bool doRead(int fd, void *buf, int numbytes) {
+       int offset = 0;
+       char *ptr = (char *)buf;
+       do {
+               int bytesread = read(fd, ptr + offset, numbytes);
+               if (bytesread > 0) {
+                       offset += bytesread;
+                       numbytes -= bytesread;
+               } else
+                       return false;
+       } while (numbytes != 0);
+       return true;
+}
+
+/**
+ * Function that handles a getSlot request.
+ */
+
+void IoTQuery::getSlot() {
+       int numrequeststosend = (int)((newestentry - requestsequencenumber) + 1);
+       if (numrequeststosend < 0)
+               numrequeststosend = 0;
+       long long numbytes = 0;
+       int filesizes[numrequeststosend];
+       int fdarray[numrequeststosend];
+       int index = 0;
+       for (long long seqn = requestsequencenumber; seqn <= newestentry; seqn++, index++) {
+               struct stat st;
+
+               int seqnt = seqn;
+               if (seqn > 150)
+               {
+                       seqnt--;
+               }
+
+               char *filename = getSlotFileName(seqnt);
+               if (stat(filename, &st) == 0) {
+                       fdarray[index] = open(filename, O_RDONLY);
+                       filesizes[index] = st.st_size;
+                       numbytes += filesizes[index];
+               } else {
+                       fdarray[index] = -1;
+                       filesizes[index] = 0;
+               }
+               delete filename;
+       }
+       const char header[] = "getslot";
+
+       /* Size is the header + the payload + space for number of requests
+                plus sizes of each slot */
+
+       long long size = sizeof(header) - 1 + sizeof(numrequeststosend) + 4 * numrequeststosend + numbytes;
+       char * response = new char[size];
+       long long offset = 0;
+       memcpy(response, header, sizeof(header) - 1);
+       offset += sizeof(header) - 1;
+       int numreq = htonl(numrequeststosend);
+       memcpy(response + offset, &numreq, sizeof(numreq));
+       offset += sizeof(numrequeststosend);
+       for (int i = 0; i < numrequeststosend; i++) {
+               int filesize = htonl(filesizes[i]);
+               memcpy(response + offset, &filesize, sizeof(filesize));
+               offset += sizeof(int);
+       }
+
+       /* Read the file data into the buffer */
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0) {
+                       doRead(fdarray[i], response + offset, filesizes[i]);
+                       offset += filesizes[i];
+               }
+       }
+
+       /* Send the response out to the webserver. */
+       sendResponse(response, size);
+
+       /* Delete the response buffer and close the files. */
+       delete response;
+       for (int i = 0; i < numrequeststosend; i++) {
+               if (fdarray[i] >= 0)
+                       close(fdarray[i]);
+       }
+}
+
+/**
+ * The method setSalt handles a setSalt request from the client.
+ */
+void IoTQuery::setSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int saltfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+       doWrite(saltfd, data, length);
+       char response[0];
+       sendResponse(response, 0);
+       close(saltfd);
+       delete filename;
+}
+
+/**
+ * The method getSalt handles a getSalt request from the client.
+ */
+
+void IoTQuery::getSalt() {
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSaltFileName();
+       int filesize = 0;
+       struct stat st;
+       if (stat(filename, &st) == 0) {
+               filesize = st.st_size;
+       } else {
+               char response[0];
+               sendResponse(response, 0);
+               delete filename;
+               return;
+       }
+       int saltfd = open(filename, O_RDONLY);
+       int responsesize = filesize + sizeof(int);
+       char * response = new char[responsesize];
+       doRead(saltfd, response + sizeof(int), filesize);
+       int n_filesize = htonl(filesize);
+       *((int*) response) = n_filesize;
+       sendResponse(response, responsesize);
+       close(saltfd);
+       delete filename;
+       delete response;
+}
+
+/**
+ *     The method putSlot handles a putSlot request from the client
+ */
+
+void IoTQuery::putSlot() {
+       /* Check if the request is stale and send update in that case.  This
+                servers as an implicit failure of the request. */
+       if (requestsequencenumber != (newestentry + 1)) {
+               getSlot();
+               return;
+       }
+
+       /* See if we have too many slots and if so, delete the old one */
+       int numberofliveslots = (int) ((newestentry - oldestentry) + 1);
+       if (numberofliveslots >=  numqueueentries) {
+               removeOldestSlot();
+       }
+
+       /* Write the slot data we received to a SLOT file */
+       char *filename = getSlotFileName(requestsequencenumber);
+       int slotfd = open(filename, O_CREAT | O_WRONLY, S_IRUSR | S_IWUSR);
+       doWrite(slotfd, data, length);
+       close(slotfd);
+       delete filename;
+       newestentry = requestsequencenumber;
+
+       /* Update the seuqence numbers and other status file information. */
+       updateStatusFile();
+
+       /* Send response acknowledging success */
+       char command[] = "putslot";
+       sendResponse(command, sizeof(command) - 1);
+}
+
+/**
+ * Method sends response.  It wraps in appropriate headers for web
+ * server.
+ */
+
+void IoTQuery::sendResponse(char * bytes, int len) {
+       cout << "Accept-Ranges: bytes\r\n"
+            << "Content-Length: " << len << "\r\n"
+            << "\r\n";
+       cout.write(bytes, len);
+       cout << flush;
+}
+
+/**
+ *     Computes the name for a slot file for the given sequence number.
+ */
+
+char * IoTQuery::getSlotFileName(long long seqnum) {
+       int directorylen = strlen(directory);
+
+       /* Size is 19 digits for ASCII representation of a long + 4
+                characters for SLOT string + 1 character for null termination +
+                directory size*/
+
+       char * filename = new char[25 + directorylen];
+       snprintf(filename, 25 + directorylen, "%s/SLOT%lld", directory, seqnum);
+       return filename;
+}
+
+/**
+ *     Computes the name for a salt file
+ */
+
+char * IoTQuery::getSaltFileName() {
+       int directorylen = strlen(directory);
+
+       /* Size is 4 characters for SALT string + 1 character for null
+                termination + directory size*/
+
+       char * filename = new char[6 + directorylen];
+       snprintf(filename, 6 + directorylen, "%s/SALT", directory);
+       return filename;
+}
+
+/**
+ *  Removes the oldest slot file
+ */
+
+void IoTQuery::removeOldestSlot() {
+       if (oldestentry != 0) {
+               char * filename = getSlotFileName(oldestentry);
+               unlink(filename);
+               delete filename;
+       }
+       oldestentry++;
+}
+
+/**
+ * Processes the query sent to the fastcgi handler.
+ */
+
+void IoTQuery::processQuery() {
+       getQuery();
+       getDirectory();
+       // readData();
+       if (!readData())
+       {
+               cerr << "No Data Available" << endl;
+               return;
+       }
+
+
+       /* Verify that we receive a post request. */
+       if (strncmp(method, "POST", 4) != 0) {
+               cerr << "Not POST Request" << endl;
+               return;
+       }
+
+       /* Make sure the directory is okay. */
+       if (directory == NULL ||
+               !checkDirectory()) {
+               cerr << "Directory " << directory << " does not exist" << endl;
+               return;
+       }
+
+       /* Get queue state from the status file.  If it doesn't exist,
+                create it. */
+       if (!openStatusFile()) {
+               cerr << "Failed to open status file" << endl;
+               return;
+       }
+
+       /* Lock status file to keep other requests out. */
+       flock(fd, LOCK_EX);
+
+       /* Decode query. */
+       decodeQuery();
+
+       /* Handle request. */
+       if (reqGetSlot)
+               getSlot();
+       else if (reqPutSlot)
+               putSlot();
+       else if (reqSetSalt)
+               setSalt();
+       else if (reqGetSalt)
+               getSalt();
+       else {
+               cerr << "No recognized request" << endl;
+               return;
+       }
+}
+
+/**
+ * Reads in data for request.  This is used for the slot to be
+ * inserted.
+ */
+
+bool IoTQuery::readData() {
+       if (length != 0) {
+               data = new char[length + 1];
+               memset(data, 0, length + 1);
+               cin.read(data, length);
+       }
+
+       do {
+               char dummy;
+               cin >> dummy;
+       } while (!cin.eof());
+
+       if (length != 0)
+       {
+               if (cin.gcount() != length)
+               {
+                       return false;
+               }
+       }
+
+       return true;
+}
+
+
+/**
+ * Reads relevant environmental variables to find out the request.
+ */
+
+void IoTQuery::getQuery() {
+       uri = FCGX_GetParam(uri_str, request->envp);
+       query = FCGX_GetParam(query_str, request->envp);
+       method = FCGX_GetParam(method_str, request->envp);
+       iotcloudroot = FCGX_GetParam(iotcloudroot_str, request->envp);
+
+       /** We require the content-length header to be sent. */
+       char * reqlength = FCGX_GetParam(length_str, request->envp);
+       if (reqlength) {
+               length = strtoll(reqlength, NULL, 10);
+       } else {
+               length = 0;
+       }
+}
+
+/**
+ *  Initializes directory field from environmental variables.
+ */
+
+void IoTQuery::getDirectory() {
+       char * split = strchr((char *)uri, '?');
+       if (split == NULL)
+               return;
+       int split_len = (int) (split - uri);
+       int rootdir_len = strlen(iotcloudroot);
+       int directory_len = split_len + rootdir_len + 1;
+       directory = new char[directory_len];
+       memcpy(directory, iotcloudroot, rootdir_len);
+       memcpy(directory + rootdir_len, uri, split_len);
+       directory[directory_len - 1] = 0;
+}
+
+/**
+ * Helper function that is used to read the status file.
+ */
+
+int doread(int fd, void *ptr, size_t count, off_t offset) {
+       do {
+               size_t bytesread = pread(fd, ptr, count, offset);
+               if (bytesread == count) {
+                       return 1;
+               } else if (bytesread == 0) {
+                       return 0;
+               }
+       } while (1);
+}
+
+
+/**
+ * Writes the current state to the status file.
+ */
+
+void IoTQuery::updateStatusFile() {
+       pwrite(fd, &numqueueentries, sizeof(numqueueentries), OFFSET_MAX);
+       pwrite(fd, &oldestentry, sizeof(oldestentry), OFFSET_OLD);
+       pwrite(fd, &newestentry, sizeof(newestentry), OFFSET_NEW);
+}
+
+/**
+ * Reads in queue state from the status file.  Returns true if
+ * successful.
+ */
+
+bool IoTQuery::openStatusFile() {
+       char statusfile[] = "queuestatus";
+       int len = strlen(directory);
+
+       char * filename = new char[len + sizeof(statusfile) + 2];
+       memcpy(filename, directory, len);
+       filename[len] = '/';
+       memcpy(filename + len + 1, statusfile, sizeof(statusfile));
+       filename[len + sizeof(statusfile) + 1] = 0;
+       fd = open(filename, O_CREAT | O_RDWR, S_IRUSR | S_IWUSR);
+       delete filename;
+
+       if (fd < 0) {
+               cerr << strerror(errno) << " error opening statusfile" << endl;
+               return false;
+       }
+
+       /* Read in queue size, oldest sequence number, and newest sequence number. */
+       int size;
+       int needwrite = 0;
+       if (doread(fd, &size, sizeof(size), OFFSET_MAX))
+               numqueueentries = size;
+       else
+               needwrite = 1;
+
+       long long entry;
+       if (doread(fd, &entry, sizeof(entry), OFFSET_OLD))
+               oldestentry = entry;
+       else
+               needwrite = 1;
+
+       if (doread(fd, &entry, sizeof(entry), OFFSET_NEW))
+               newestentry = entry;
+       else
+               needwrite = 1;
+
+       if (needwrite)
+               updateStatusFile();
+
+       return true;
+}
+
+
diff --git a/version2/src/server_malicious_switch_slot/iotquery.h b/version2/src/server_malicious_switch_slot/iotquery.h
new file mode 100644 (file)
index 0000000..6ac5113
--- /dev/null
@@ -0,0 +1,68 @@
+#ifndef IOTQUERY_H
+#define IOTQUERY_H
+#include <iostream>
+#include "fcgio.h"
+#include "fcgi_stdio.h"
+
+#define DEFAULT_SIZE 128
+#define OFFSET_MAX 0
+#define OFFSET_OLD 4
+#define OFFSET_NEW 12
+
+class IoTQuery {
+public:
+       IoTQuery(FCGX_Request * request);
+       ~IoTQuery();
+       void processQuery();
+
+private:
+       void sendResponse(char *data, int length);
+       void getQuery();
+       void getDirectory();
+       bool readData();
+       bool checkDirectory();
+       bool openStatusFile();
+       void updateStatusFile();
+       void decodeQuery();
+       void getSlot();
+       void putSlot();
+       void setSalt();
+       void getSalt();
+       void removeOldestSlot();
+       char * getSlotFileName(long long);
+       char * getSaltFileName();
+
+       FCGX_Request * request;
+       char *data;
+       /* Directory slot files are placed in. */
+       char *directory;
+       /* Full URI from Apache */
+       const char * uri;
+       /* Query portion of URI */
+       const char * query;
+       /* Type of request: GET or PUT */
+       const char * method;
+       /* Root directory for all accounts */
+       const char * iotcloudroot;
+       /* Expected length of data from client */
+       long long length;
+       /* Sequence number for oldest slot */
+       long long oldestentry;
+       /* Sequence number for newest slot */
+       long long newestentry;
+       /* Sequence number from request */
+       long long requestsequencenumber;
+       /* Size of queue */
+       int numqueueentries;
+       /* fd for queuestatus file */
+       int fd;
+       /* Is the request to get a slot? */
+       bool reqGetSlot;
+       /* Is the request to put a slot? */
+       bool reqPutSlot;
+       /* Is the request to set the salt? */
+       bool reqSetSalt;
+       /* Is the request to get the salt? */
+       bool reqGetSalt;
+};
+#endif