Browse Source

changed the length of the stream ids and the slitheen_header for downstream data. Made appropriate modifications to client and relay_station code to prepare for extra encryption layer

cecylia 7 years ago
parent
commit
c08d937b4a

+ 2 - 3
client/ous.js

@@ -66,13 +66,12 @@ page.onResourceReceived = function(response) {
 			delete upstream_data[id];
 		}
 	}
-	if(response.contentType == "slitheen"){
+	if(response.stage == "end" && response.contentType == "slitheen"){
 		fs.write("slitheen.out", response.body, 'a');
 		fs.write("slitheen.out", '\n', 'a');
 
-		output.write(response.body);
+		output.write(response.bodySize + '\n' + response.body);
 		output.flush();
-
 	}
 };
 

+ 94 - 47
client/socks5proxy.c

@@ -19,31 +19,32 @@
 
 #include <openssl/bio.h>
 #include <openssl/evp.h>
-#include<openssl/buffer.h>
+#include <openssl/buffer.h>
 
 #define SLITHEEN_ID_LEN 10
 
 #define NEW
 
-int proxy_data(int sockfd, uint8_t stream_id, int32_t pipefd);
+int proxy_data(int sockfd, uint16_t stream_id, int32_t pipefd);
 void *demultiplex_data();
 
-struct __attribute__ ((__packed__)) slitheen_hdr{
-	uint8_t stream_id;
+struct __attribute__ ((__packed__)) slitheen_hdr {
+	uint64_t counter;
+	uint16_t stream_id;
 	uint16_t len;
-	uint16_t garbage_len;
+	uint32_t garbage;
 };
 
-#define SLITHEEN_HEADER_LEN 5
+#define SLITHEEN_HEADER_LEN 16
 
 struct __attribute__ ((__packed__)) slitheen_up_hdr{
-	uint8_t stream_id;
+	uint16_t stream_id;
 	uint16_t len;
 };
 
 typedef struct connection_st{
 	int32_t pipe_fd;
-	uint8_t stream_id;
+	uint16_t stream_id;
 	struct connection_st *next;
 } connection;
 
@@ -226,7 +227,7 @@ struct socks_req {
 };
 
 //continuously read from the socket and look for a CONNECT message
-int proxy_data(int sockfd, uint8_t stream_id, int32_t ous_out){
+int proxy_data(int sockfd, uint16_t stream_id, int32_t ous_out){
 	uint8_t *buffer = calloc(1, BUFSIZ);
 	uint8_t *response = calloc(1, BUFSIZ);
 	printf("ous out pipe fd: %d\n", ous_out);
@@ -316,13 +317,13 @@ int proxy_data(int sockfd, uint8_t stream_id, int32_t ous_out){
 	fflush(stdout);
 
 	//pre-pend stream_id and length
-	memmove(buffer+3, buffer, bytes_read+1);
+	memmove(buffer+sizeof(struct slitheen_up_hdr), buffer, bytes_read+1);
 
 	struct slitheen_up_hdr *up_hdr = (struct slitheen_up_hdr *) buffer;
 	up_hdr->stream_id = stream_id;
 	up_hdr->len = htons(bytes_read);
 
-	bytes_read+= 3;
+	bytes_read+= sizeof(struct slitheen_up_hdr);
 
 	//encode bytes for safe transport (b64)
 	const char *encoded_bytes;
@@ -500,7 +501,7 @@ int proxy_data(int sockfd, uint8_t stream_id, int32_t ous_out){
 				up_hdr->stream_id = stream_id;
 				up_hdr->len = htons(bytes_read);
 
-				bytes_read+= 3;
+				bytes_read+= sizeof(struct slitheen_up_hdr);
 
 				bio = BIO_new(BIO_s_mem());
 				b64 = BIO_new(BIO_f_base64());
@@ -598,6 +599,9 @@ err:
 	exit(0);
 }
 
+/* Read blocks of covert data from OUS_out. Determine the stream id and the length of
+ * the block and then write the data to the correct thread to be passed to the browser
+ */
 void *demultiplex_data(){
 
 	int32_t buffer_len = BUFSIZ;
@@ -607,55 +611,108 @@ void *demultiplex_data(){
 	printf("Opening OUS_out\n");
 	int32_t ous_fd = open("OUS_out", O_RDONLY);
 	printf("Opened.\n");
-	uint8_t *overflow;
-	uint32_t overflow_len = 0;
+	uint8_t *partial_block;
+	uint32_t partial_block_len = 0;
+	uint32_t resource_remaining = 0;
 
 	for(;;){
-		int32_t bytes_read = read(ous_fd, buffer, buffer_len-overflow_len);
+		int32_t bytes_read = read(ous_fd, buffer, buffer_len-partial_block_len);
 		
 		if(bytes_read > 0){
 			int32_t bytes_remaining = bytes_read;
+			printf("Read in %d bytes from OUS_out\n", bytes_remaining);
+			p = buffer;
+
+			//the first value for a new resource will be the resource length,
+			//followed by a newline
+			if(resource_remaining > 0){
+				printf("Completing previously started resource. Reading in %d out of %d bytes remaining in resource\n", bytes_remaining, resource_remaining);
+				resource_remaining -= bytes_remaining;
+
+				if((bytes_remaining > 0) && (partial_block_len > 0)){
+					//process first part of slitheen info
+					printf("Completing previously read Slitheen block\n");
+					memmove(buffer+partial_block_len, buffer, bytes_read);
+					memcpy(buffer, partial_block, partial_block_len);
+					bytes_remaining += partial_block_len;
+					free(partial_block);
+					partial_block_len = 0;
+				}
 
-			if(overflow_len > 0){
-				//process first part of slitheen info
-				printf("Completeing previously read header\n");
-				memmove(buffer+overflow_len, buffer, bytes_read);
-				memcpy(buffer, overflow, overflow_len);
-				bytes_remaining += overflow_len;
-				free(overflow);
-				overflow_len = 0;
+			} else {
+				uint8_t *end_ptr;
+				resource_remaining = strtol((const char *) p, (char **) &end_ptr, 10);
+				if(resource_remaining == 0){
+					printf("UH OH, resource_remaining is zero or there was an error O.o\n");
+				} else {
+					bytes_remaining -= (end_ptr - p) + 1;
+					p += (end_ptr - p) + 1;
+
+					printf("Reading in %d out of %d bytes of new resource\n",
+							bytes_remaining, resource_remaining);
+
+					if(resource_remaining < bytes_remaining){
+						resource_remaining = 0;
+						printf("UH OH, shouldn't be here\n");
+					} else {
+						resource_remaining -= bytes_remaining;
+					}
+				}
 			}
+			
 
-			p = buffer;
 			while(bytes_remaining > 0){
-				if(bytes_remaining < SLITHEEN_HEADER_LEN){
+
+				if(bytes_remaining + resource_remaining < SLITHEEN_HEADER_LEN){
+					printf("Resource is padded out with garbage\n");
+					bytes_remaining = 0;
+					break;
+				}
+
+				if((bytes_remaining < SLITHEEN_HEADER_LEN)){
 					printf("Partial header: ");
 					int i;
 					for(i = 0; i< bytes_remaining; i++){
 						printf("%02x ", p[i]);
 					}
 					printf("\n");
+
+					partial_block = calloc(1, bytes_remaining);
+					memcpy(partial_block, p, bytes_remaining);
+					partial_block_len = bytes_remaining;
+					bytes_remaining = 0;
+					break;
 				}
 
 				struct slitheen_hdr *sl_hdr = (struct slitheen_hdr *) p;
 				//first see if sl_hdr corresponds to a valid stream. If not, ignore rest of read bytes
-#ifdef DEBUG
+//#ifdef DEBUG
 				printf("Slitheen header:\n");
 				int i;
 				for(i = 0; i< SLITHEEN_HEADER_LEN; i++){
 					printf("%02x ", p[i]);
 				}
 				printf("\n");
-#endif
+//#endif
+
+				if(ntohs(sl_hdr->len) > bytes_remaining){
+					printf("Received partial block\n");
+					partial_block = calloc(1, ntohs(sl_hdr->len));
+					memcpy(partial_block, p, bytes_remaining);
+					partial_block_len = bytes_remaining;
+					bytes_remaining = 0;
+					break;
+				}
 
-				p += sizeof(struct slitheen_hdr);
+				p += SLITHEEN_HEADER_LEN;
+				bytes_remaining -= SLITHEEN_HEADER_LEN;
 
-				if(sl_hdr->stream_id == 0){
-#ifdef DEBUG
+				if(sl_hdr->garbage){
+//#ifdef DEBUG
 					printf("Garbage bytes\n");
-#endif
+//#endif
 					p += ntohs(sl_hdr->len);
-					bytes_remaining -= sizeof(struct slitheen_hdr) + ntohs(sl_hdr->len);
+					bytes_remaining -= ntohs(sl_hdr->len);
 					continue;
 				}
 
@@ -684,25 +741,15 @@ void *demultiplex_data(){
 					break;
 				}
 				
-				if(ntohs(sl_hdr->len)+ sizeof(struct slitheen_hdr) > bytes_remaining){
-					overflow = calloc(1, bytes_remaining);
-					memcpy(overflow, p, bytes_remaining);
-					overflow_len = bytes_remaining;
-					bytes_remaining = 0;
-					break;
-				}
+				printf("Received information for stream id: %d of length: %u\n", sl_hdr->stream_id, ntohs(sl_hdr->len));
 
-				if(sl_hdr->garbage_len == 0){
-					printf("Received information for stream id: %d of length: %u\n", sl_hdr->stream_id, ntohs(sl_hdr->len));
-
-					int32_t bytes_sent = write(pipe_fd, p, ntohs(sl_hdr->len));
-					if(bytes_sent <= 0){
-						printf("Error reading to pipe for stream id %d\n", sl_hdr->stream_id);
-					}
+				int32_t bytes_sent = write(pipe_fd, p, ntohs(sl_hdr->len));
+				if(bytes_sent <= 0){
+					printf("Error reading to pipe for stream id %d\n", sl_hdr->stream_id);
 				}
 
 				p += ntohs(sl_hdr->len);
-				bytes_remaining -= sizeof(struct slitheen_hdr) + ntohs(sl_hdr->len);
+				bytes_remaining -= ntohs(sl_hdr->len);
 			}
 
 		} else {

+ 2 - 5
relay_station/Makefile

@@ -4,12 +4,9 @@ TARGETS=slitheen-proxy
 
 all: $(TARGETS)
 
-slitheen-proxy.o flow.o rserv.o ptwist168.o crypto.o relay.o cryptothread.o util.o:: ptwist.h rserv.h flow.h slitheen.h crypto.h relay.h cryptothread.h util.h
+slitheen-proxy.o flow.o ptwist168.o crypto.o relay.o cryptothread.o util.o:: ptwist.h flow.h slitheen.h crypto.h relay.h cryptothread.h util.h
 
-rserv: rserv.o ptwist168.o
-	gcc -g -ggdb -o $@ $^ -lssl -lcrypto
-
-slitheen-proxy: slitheen-proxy.o flow.o rserv.o ptwist168.o crypto.o relay.o cryptothread.o util.o relay.h crypto.h ptwist.h rserv.h flow.h slitheen.h cryptothread.h
+slitheen-proxy: slitheen-proxy.o flow.o ptwist168.o crypto.o relay.o cryptothread.o util.o relay.h crypto.h ptwist.h flow.h slitheen.h cryptothread.h util.h
 	gcc -g -ggdb -o $@ $^ -I/home/slitheen/Documents/include/openssl libssl.a libcrypto.a -lpcap -lpthread -ldl
 
 clean:

+ 91 - 2
relay_station/crypto.c

@@ -1,5 +1,19 @@
-/* crypto.c by Cecylia Bocovich <cbocovic@uwaterloo.ca> based on:*/
+/* Name: crypto.c
+ * Author: Cecylia Bocovich <cbocovic@uwaterloo.ca>
+ *
+ * This file contains code for checking tagged flows, processing handshake
+ * messages, and computing the master secret for a TLS session.
+ *
+ * Some code in this document is based on the OpenSSL source files:
+ * 	crypto/ec/ec_key.c
+ * 	crypto/dh/dh_key.c
+ * */
+
 /*TODO: openssl attribution */
+#include <stdio.h>
+#include <stdlib.h>
+#include <assert.h>
+#include <string.h>
 
 #include <openssl/evp.h>
 #include <openssl/dh.h>
@@ -7,8 +21,9 @@
 #include <openssl/err.h>
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
+#include <openssl/sha.h>
 
-#include "rserv.h"
+#include "ptwist.h"
 #include "crypto.h"
 #include "flow.h"
 #include "slitheen.h"
@@ -1053,3 +1068,77 @@ void check_handshake(struct packet_info *info){
 	}
 }
 
+/* Check the given tag with the given context and private key.  Return 0
+   if the tag is properly formed, non-0 if not.  If the tag is correct,
+   set key to the resulting secret key. */
+int check_tag(byte key[16], const byte privkey[PTWIST_BYTES],
+	const byte tag[PTWIST_TAG_BYTES], const byte *context,
+	size_t context_len)
+{
+    int ret = -1;
+    byte sharedsec[PTWIST_BYTES+context_len];
+    byte taghashout[32];
+#if PTWIST_PUZZLE_STRENGTH > 0
+    byte hashout[32];
+    size_t puzzle_len = 16+PTWIST_RESP_BYTES;
+    byte value_to_hash[puzzle_len];
+    unsigned int firstbits;
+    int firstpass = 0;
+#endif
+
+    /* Compute the shared secret privkey*TAG */
+    ptwist_pointmul(sharedsec, tag, privkey);
+
+    /* Create the hash tag keys */
+    memmove(sharedsec+PTWIST_BYTES, context, context_len);
+    SHA256(sharedsec, PTWIST_BYTES, taghashout);
+
+#if PTWIST_PUZZLE_STRENGTH > 0
+    /* Construct the proposed solution to the puzzle */
+    memmove(value_to_hash, taghashout, 16);
+    memmove(value_to_hash+16, tag+PTWIST_BYTES, PTWIST_RESP_BYTES);
+    value_to_hash[16+PTWIST_RESP_BYTES-1] &= PTWIST_RESP_MASK;
+
+    /* Hash the proposed solution and see if it is correct; that is, the
+     * hash should start with PTWIST_PUZZLE_STRENGTH bits of 0s,
+     * followed by the last PTWIST_HASH_SHOWBITS of the tag. */
+    md_map_sh256(hashout, value_to_hash, puzzle_len);
+#if PTWIST_PUZZLE_STRENGTH < 32
+    /* This assumes that you're on an architecture that doesn't care
+     * about alignment, and is little endian. */
+    firstbits = *(unsigned int*)hashout;
+    if ((firstbits & PTWIST_PUZZLE_MASK) == 0) {
+	firstpass = 1;
+    }
+#else
+#error "Code assumes PTWIST_PUZZLE_STRENGTH < 32"
+#endif
+    if (firstpass) {
+	bn_t Hbn, Tbn;
+	bn_new(Hbn);
+	bn_new(Tbn);
+	hashout[PTWIST_HASH_TOTBYTES-1] &= PTWIST_HASH_MASK;
+	bn_read_bin(Hbn, hashout, PTWIST_HASH_TOTBYTES, BN_POS);
+	bn_rsh(Hbn, Hbn, PTWIST_PUZZLE_STRENGTH);
+	bn_read_bin(Tbn, tag+PTWIST_BYTES, PTWIST_TAG_BYTES-PTWIST_BYTES,
+		    BN_POS);
+	bn_rsh(Tbn, Tbn, PTWIST_RESP_BITS);
+
+	ret = (bn_cmp(Tbn,Hbn) != CMP_EQ);
+
+	bn_free(Hbn);
+	bn_free(Tbn);
+    }
+#else
+    /* We're not using a client puzzle, so just check that the first
+     * PTWIST_HASH_SHOWBITS bits of the above hash fill out the rest
+     * of the tag.  If there's no puzzle, PTWIST_HASH_SHOWBITS must be
+     * a multiple of 8. */
+    ret = (memcmp(tag+PTWIST_BYTES, taghashout, PTWIST_HASH_SHOWBITS/8) != 0);
+#endif
+    if (ret == 0) {
+	memmove(key, taghashout+16, 16);
+    }
+    return ret;
+}
+

+ 4 - 0
relay_station/crypto.h

@@ -2,6 +2,7 @@
 #define _CRYPTO_H_
 
 #include "flow.h"
+#include "ptwist.h"
 
 #define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
 							(((unsigned int)(c[1]))    )),c+=2)
@@ -27,6 +28,9 @@ int init_ciphers(flow *f);
 void update_context(flow *f, uint8_t *input, int32_t len, int32_t incoming, int32_t type, int32_t enc);
 void check_handshake(struct packet_info *info);
 
+int check_tag(byte key[16], const byte privkey[PTWIST_BYTES],
+	const byte tag[PTWIST_TAG_BYTES], const byte *context,
+	size_t context_len);
 #define PRE_MASTER_MAX_LEN BUFSIZ
 
 #define SLITHEEN_KEYGEN_CONST "SLITHEEN_KEYGEN"

+ 7 - 0
relay_station/cryptothread.c

@@ -1,3 +1,10 @@
+/* Name: cryptothread.c
+ * Author: Cecylia Bocovich <cbocovic@uwaterloo.ca>
+ *
+ * This function contains the code necessary for using OpenSSL in a thread-safe
+ * manner.
+ */
+
 
 #include <pthread.h>
 #include <openssl/crypto.h>

+ 19 - 12
relay_station/flow.c

@@ -1,6 +1,21 @@
-/* flow.c by Cecylia Bocovich <cbocovic@uwaterloo.ca>*/
-
-/* Defines and modifies the flow structure. */
+/* Name: flow.c
+ * Author: Cecylia Bocovich <cbocovic@uwaterloo.ca>
+ *
+ * This file contains functions for manipulating tagged flows. 
+ *
+ * The check_flow function checks to see whether the packet that is currently
+ * being processed belongs to a tagged flow.
+ *
+ * The add_packet function attempts to reconstruct a TLS record containing
+ * handshake data from the contents of previously received packets
+ *
+ * The update_flow function processes TLS handshake messages and calls the
+ * necessary functions from crypto.c when a message has been received.
+ *
+ * There are several functions associated with the resumption of previously
+ * tagged TLS sessions.
+ *
+ */
 
 #include <stdio.h>
 #include <stdlib.h>
@@ -510,13 +525,6 @@ int remove_flow(flow *f) {
 	return 1;
 }
 
-/** Expands the flow table when we run out of space
- *  TODO: implement and test
- */
-int grow_table() {
-	return 0;
-}
-
 /** Returns the index of a flow in the flow table if
  *  it exists, returns 0 if it is not present.
  *
@@ -839,7 +847,7 @@ int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
 #endif
 	uint8_t *p = hs + HANDSHAKE_HEADER_LEN;
 	p += 4; //skip lifetime TODO: add to session struct
-	session *new_session = emalloc(sizeof(session));
+	session *new_session = ecalloc(1, sizeof(session));
 
 	new_session->session_id_len = 0;
 	
@@ -893,7 +901,6 @@ int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
 
 /* Adds a packet the flow's packet chain. If it can complete a record, gives
  * this record to update_flow */
-//TODO: check all returns and figure out what to do if there is a mem failure
 int add_packet(flow *f, struct packet_info *info){
 	if (info->tcp_hdr == NULL || info->app_data_len <= 0){
 		return 0;

+ 6 - 2
relay_station/flow.h

@@ -23,8 +23,11 @@
 #define TLS_CLNT_KEYEX 0x10
 #define TLS_FINISHED 0x14
 
+struct client_st;
+typedef struct client_st client;
+
 typedef struct stream_st {
-	uint8_t stream_id;
+	uint16_t stream_id;
 	int32_t pipefd;
 	struct stream_st *next;
 } stream;
@@ -53,7 +56,7 @@ typedef struct queue_block_st{
 	int32_t offset;
 	uint8_t *data;
 	struct queue_block_st *next;
-	uint8_t stream_id;
+	uint16_t stream_id;
 } queue_block;
 
 typedef struct data_queue_st {
@@ -93,6 +96,7 @@ typedef struct flow_st {
 	int resume_session;
 	stream_table *streams;
 	data_queue *downstream_queue;
+	client *client_ptr;
 
 	packet_chain *ds_packet_chain;
 	packet_chain *us_packet_chain;

+ 38 - 22
relay_station/relay.c

@@ -1,7 +1,13 @@
-/* relay.c by Cecylia Bocovich <cbocovic@uwaterloo.ca>
+/* Name: relay.c
+ * Author: Cecylia Bocovich <cbocovic@uwaterloo.ca>
  *
- * Once a flow has been tagged, this code will extract covert data from the header
+ * This file contains code that the relay station runs once the TLS handshake for
+ * a tagged flow has been completed.
+ *
+ * These functions will extract covert data from the header
  * of HTTP GET requests and insert downstream data into leaf resources
+ *
+ * It is also responsible for keeping track of the HTTP state of the flow
  */
 
 #include <stdio.h>
@@ -18,6 +24,7 @@
 
 #include <openssl/bio.h>
 #include <openssl/evp.h>
+#include <openssl/rand.h>
 
 #include "relay.h"
 #include "slitheen.h"
@@ -76,7 +83,7 @@ int replace_packet(flow *f, struct packet_info *info){
 		//}//TODO: need to do something about replaying packets (maybe store previously sent data??
 
 
-#ifdef DEBUG2 //TODO: fix
+#ifdef DEBUG2
 		uint8_t *p = (uint8_t *) info->tcp_hdr;
 		fprintf(stdout, "ip hdr length: %d\n", htons(info->ip_hdr->len));
 		fprintf(stdout, "Injecting the following packet:\n");
@@ -255,7 +262,7 @@ int read_header(flow *f, struct packet_info *info){
 	}
 	
 	int32_t num_messages = 1;
-	char *messages[50]; //TODO:make not just 10?
+	char *messages[50]; //TODO: grow this array
 	messages[0] = header_ptr;
 	char *c = header_ptr;
 	while(*c != '\r' && *c != '\0'){
@@ -351,6 +358,7 @@ int read_header(flow *f, struct packet_info *info){
 				new_client->downstream_queue = emalloc(sizeof(data_queue));
 
 				new_client->downstream_queue->first_block = NULL;
+				new_client->encryption_counter = 0;
 	
 				new_client->next = NULL;
 
@@ -366,6 +374,7 @@ int read_header(flow *f, struct packet_info *info){
 				}
 				
 				//set f's stream table
+				f->client_ptr = new_client; //TODO: slim down f 
 				f->streams = new_client->streams;
 				f->downstream_queue = new_client->downstream_queue;
 
@@ -377,7 +386,7 @@ int read_header(flow *f, struct packet_info *info){
 
 		while(output_len > 0){
 			struct sl_up_hdr *sl_hdr = (struct sl_up_hdr *) p;
-			uint8_t stream_id = sl_hdr->stream_id;
+			uint16_t stream_id = sl_hdr->stream_id;
 			uint16_t stream_len = ntohs(sl_hdr->len);
 
 			p += sizeof(struct sl_up_hdr);
@@ -441,7 +450,6 @@ int read_header(flow *f, struct packet_info *info){
 					return 1;
 				}
 				uint8_t *initial_data = emalloc(stream_len);
-				//TODO: ended here. create macro that just exits
 				memcpy(initial_data, p, stream_len);
 
 				struct proxy_thread_data *thread_data = 
@@ -514,7 +522,7 @@ void *proxy_covert_site(void *data){
 
 	uint8_t *p = thread_data->initial_data;
 	uint16_t data_len = thread_data->initial_len;
-	uint8_t stream_id = thread_data->stream_id;
+	uint16_t stream_id = thread_data->stream_id;
 
 	int32_t bytes_sent;
 
@@ -562,7 +570,7 @@ void *proxy_covert_site(void *data){
 		break;
 	case 0x04:
 		//IPv6
-		goto err;//TODO: fix this
+		goto err;//TODO: add IPv6 functionality
 		break;
 	}
 
@@ -591,7 +599,7 @@ void *proxy_covert_site(void *data){
 	uint8_t *response = emalloc(11);
 	//now send the reply to the client
 	response[0] = 0x05;
-	response[1] = 0x00;//TODO: make this accurate
+	response[1] = 0x00;
 	response[2] = 0x00;
 	response[3] = 0x01;
 	*((uint32_t *) (response + 4)) = my_addr.sin_addr.s_addr;
@@ -680,8 +688,6 @@ void *proxy_covert_site(void *data){
 				if( bytes_sent <= 0){
 					break;
 				} else if (bytes_sent < bytes_read){
-					//TODO: should update buffer and keep
-					//track of length of upstream data
 					break;
 				}
 			} else {
@@ -1207,9 +1213,12 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 	struct slitheen_header *sl_hdr;
 
 	data_queue *downstream_queue = f->downstream_queue;
+	client *client_ptr = f->client_ptr;
 
 	//Fill as much as we can from the censored_queue
-	while((remaining > SLITHEEN_HEADER_LEN) && downstream_queue != NULL && downstream_queue->first_block != NULL){
+	//Note: need enough for the header and one block of data (16 byte IV, 16 byte
+	//		block, 16 byte MAC) = header_len + 48.
+	while((remaining > (SLITHEEN_HEADER_LEN + 48)) && downstream_queue != NULL && downstream_queue->first_block != NULL){
 		queue_block *first_block = downstream_queue->first_block;
 		int32_t block_length = first_block->len;
 		int32_t offset = first_block->offset;
@@ -1221,9 +1230,10 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 #endif
 		
 		sl_hdr = (struct slitheen_header *) p;
+		sl_hdr->counter = ++(client_ptr->encryption_counter);
 		sl_hdr->stream_id = first_block->stream_id;
-		sl_hdr->len = 0x00;
-		sl_hdr->garbage = 0x00;
+		sl_hdr->len = 0x0000;
+		sl_hdr->garbage = 0x0000;
 		p += SLITHEEN_HEADER_LEN;
 		remaining -= SLITHEEN_HEADER_LEN;
 
@@ -1248,7 +1258,7 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		}
 		sl_hdr->len = htons(sl_hdr->len);
 
-#ifdef DEBUG
+//#ifdef DEBUG
 		printf("DWNSTRM: slitheen header: ");
 		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 			printf("%02x ",((uint8_t *) sl_hdr)[i]);
@@ -1259,28 +1269,34 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 			printf("%02x ", ((uint8_t *) sl_hdr)[i+SLITHEEN_HEADER_LEN]);
 		}
 		printf("\n");
-#endif
+//#endif
 	}
 	//now, if we need more data, fill with garbage
-	if(remaining > SLITHEEN_HEADER_LEN ){
-		//TODO: note, we may also be receiving misordered packets. Take Ian's suggestion into account here
+	if(remaining >= SLITHEEN_HEADER_LEN ){
+
 		sl_hdr = (struct slitheen_header *) p;
+		sl_hdr->counter = 0x00;
 		sl_hdr->stream_id = 0x00;
 		remaining -= SLITHEEN_HEADER_LEN;
 		sl_hdr->len = htons(remaining);
-		sl_hdr->garbage = htons(remaining);
+		sl_hdr->garbage = htons(remaining);//TODO: change this to a bit
 
-#ifdef DEBUG
+//#ifdef DEBUG
 		printf("DWNSTRM: slitheen header: ");
 		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
-#endif
+//#endif
 
 		p += SLITHEEN_HEADER_LEN;
-		memset(p, 'A', remaining);
+		RAND_bytes(p, remaining);
+	} else {
+		//fill with random data
+		printf("Less than 16 bytes remaining, had to fill with random\n");
+		RAND_bytes(p, remaining);
 	}
+
 	return 0;
 }
 

+ 3 - 2
relay_station/relay.h

@@ -7,7 +7,7 @@
 struct proxy_thread_data {
 	uint8_t *initial_data;
 	uint16_t initial_len;
-	uint8_t stream_id;
+	uint16_t stream_id;
 	int32_t pipefd;
 	stream_table *streams;
 	data_queue *downstream_queue;
@@ -17,6 +17,7 @@ typedef struct client_st {
 	uint8_t slitheen_id[SLITHEEN_ID_LEN];
 	stream_table *streams;
 	data_queue *downstream_queue;
+	uint16_t encryption_counter;
 	struct client_st *next;
 } client;
 
@@ -34,7 +35,7 @@ struct socks_req {
 };
 
 struct __attribute__((__packed__)) sl_up_hdr {
-	uint8_t stream_id;
+	uint16_t stream_id;
 	uint16_t len;
 };
 

+ 7 - 1
relay_station/slitheen-proxy.c

@@ -1,4 +1,10 @@
-/* slitheen-proxy.c by Cecylia Bocovich */
+/* Name: slitheen-proxy.c 
+ * Author: Cecylia Bocovich
+ *
+ * This code runs the main functions for the Slitheen relay station to tap and
+ * modify data.
+ *
+ */
 
 #include <pcap.h>
 #include <stdio.h>

+ 6 - 4
relay_station/slitheen.h

@@ -75,11 +75,13 @@ struct packet_info {
 };
 
 struct __attribute__((__packed__)) slitheen_header {
-	u_char stream_id; /* determines which stream the data is from */
-	u_short len;
-	u_short garbage;
+	uint64_t counter;
+	uint16_t stream_id; /* determines which stream the data is from */
+	uint16_t len;
+	uint32_t garbage;
 };
-#define SLITHEEN_HEADER_LEN 5
+
+#define SLITHEEN_HEADER_LEN 16
 
 struct __attribute__((__packed__)) record_header {
 	u_char type;

+ 8 - 0
relay_station/util.c

@@ -1,3 +1,11 @@
+/* Name: util.c
+ * Author: Cecylia Bocovich <cbocovic@uwaterloo.ca>
+ *
+ * This file contains helper functions and macros
+ */
+
+
+
 #include <stdio.h>
 #include <stdlib.h>
 #include "util.h"

+ 2 - 0
relay_station/util.h

@@ -6,6 +6,8 @@
 #ifndef _UTIL_H_
 #define _UTIL_H_
 
+#include <stddef.h>
+
 void *emalloc(size_t size);
 void *ecalloc(size_t nmemb, size_t size);