Parcourir la source

debugged server and client code

cecylia il y a 8 ans
Parent
commit
a0318e7af9
6 fichiers modifiés avec 781 ajouts et 205 suppressions
  1. 49 15
      client/loadpage.js
  2. 307 106
      client/socks5proxy.c
  3. 6 0
      server/flow.c
  4. 1 1
      server/flow.h
  5. 399 83
      server/relay.c
  6. 19 0
      server/relay.h

+ 49 - 15
client/loadpage.js

@@ -3,19 +3,26 @@ var page = require('webpage').create();
 var initial_done = false;
 var initial_bytes = '';
 
+var upstream_data = {};
+
 var output = fs.open("OUS_out", {mode: 'wb'});
+
+page.captureContent = ['.*'];
+
 page.onResourceRequested = function(request, network) {
 	console.log('Request ' + JSON.stringify(request, undefined, 4));
-	if(!initial_done){
-		network.setHeader('X-Slitheen', initial_bytes);
-		initial_done = true;
-	} else if(fs.isFile("OUS_in")){
+///	if(!initial_done){
+///		network.setHeader('X-Slitheen', initial_bytes);
+///		upstream_data[request.id] = initial_bytes;
+///		initial_done = true;
+	if(fs.isFile("OUS_in")){
 		var bytes = fs.read("OUS_in");
 		if(bytes != ''){
 			fs.remove("OUS_in");
 			bytes.replace(/\r?\n|\r/g, "");
 			console.log('Read in '+bytes.length+ ' bytes:' + bytes);
 			network.setHeader('X-Slitheen', bytes);
+			upstream_data[request.id] = bytes;
 		}
 	}
 
@@ -24,28 +31,55 @@ page.onResourceRequested = function(request, network) {
 //TODO: on partial resource data coming in
 page.onResourceReceived = function(response) {
 	console.log('Receive ' + JSON.stringify(response, undefined, 4));
+	var id = response.id;
+
+	//check to see if request successfully carried data
+	if(upstream_data.hasOwnProperty(id)){
+		if(response.status != 0){
+			console.log('Successfully transmitted data (id '+id);
+			delete upstream_data[id];
+			if(upstream_data.hasOwnProperty(id)){
+				console.log('deletion failed');
+			}
+		} else {
+			console.log("Couldn't transmit data: "+upstream_data[id]);
+		}
+	} else {
+		console.log('dictionary does not have key ' + id);
+	}
 	if(response.contentType == "slitheen"){
 		console.log("WOOOOOOO\n");
 		fs.write("slitheen.out", response.body, 'a');
+		fs.write("slitheen.out", '\n', 'a');
+
+		output.write(response.body);
+		output.flush();
+
 	}
 };
 
-for(;;){
-	if(fs.isFile("OUS_in")){
-		var initial_bytes = fs.read("OUS_in");
-		if(initial_bytes != ''){
-			fs.remove("OUS_in");
-			initial_bytes.replace(/\r?\n|\r/g, "");
-			console.log('Read in '+initial_bytes.length+ ' bytes:' + initial_bytes);
 
+///for(;;){
+///	if(fs.isFile("OUS_in")){
+		//page_loaded = false;
+		///var initial_bytes = fs.read("OUS_in");
+		///if(initial_bytes != ''){
+		///	fs.remove("OUS_in");
+///			initial_bytes.replace(/\r?\n|\r/g, "");
+///			console.log('Read in '+initial_bytes.length+ ' bytes:' + initial_bytes);
 			page.open('https://cs.uwaterloo.ca', function(status) {
 			  console.log("Status: " + status);
 			  if(status === "success") {
 				page.render('example.png');
 			  }
+			  for( var id in upstream_data){
+				  //write it back to OUS_in
+				  fs.write("OUS_in", upstream_data[id], 'a');
+				  console.log("key: "+id+" value: "+upstream_data[id]);
+			  }
 			  phantom.exit();
 			});
-			break;
-		}
-	}
-}
+///			break;
+///		}
+///	}
+///}

+ 307 - 106
client/socks5proxy.c

@@ -11,10 +11,41 @@
 #include <string.h>
 #include <sys/socket.h>
 #include <sys/types.h>
+#include <sys/stat.h>
 #include <netinet/in.h>
 #include <netdb.h>
+#include <pthread.h>
+#include <fcntl.h>
 
-int proxy_data(int sockfd);
+#include <openssl/bio.h>
+#include <openssl/evp.h>
+#include<openssl/buffer.h>
+
+int proxy_data(int sockfd, uint8_t stream_id, int32_t pipefd);
+void *demultiplex_data();
+
+struct __attribute__ ((__packed__)) slitheen_hdr{
+	uint8_t stream_id;
+	uint16_t len;
+	uint16_t garbage_len;
+};
+
+struct __attribute__ ((__packed__)) slitheen_up_hdr{
+	uint8_t stream_id;
+	uint16_t len;
+};
+
+typedef struct connection_st{
+	int32_t pipe_fd;
+	uint8_t stream_id;
+	struct connection_st *next;
+} connection;
+
+typedef struct connection_table_st{
+	connection *first;
+} connection_table;
+
+static connection_table *connections;
 
 int main(void){
 	int listen_socket;
@@ -23,10 +54,24 @@ int main(void){
 	struct sockaddr_in remote_addr;
 	socklen_t addr_size;
 
-	mkfifo("OUS_in", 0666);
+	//mkfifo("OUS_in", 0666);
 	mkfifo("OUS_out", 0666);
+
+	/* Spawn process to listen for incoming data from OUS 
+	int32_t demux_pipe[2];
+	if(pipe(demux_pipe) < 0){
+		printf("Failed to create pipe for new thread\n");
+		return 1;
+	}*/
+	connections = calloc(1, sizeof(connection_table));
+	connections->first = NULL;
+	
+	pthread_t *demux_thread = calloc(1, sizeof(pthread_t));
+	pthread_create(demux_thread, NULL, demultiplex_data, NULL);
+
 	if (!(listen_socket = socket(AF_INET, SOCK_STREAM, 0))){
 		printf("Error creating socket\n");
+		fflush(stdout);
 		return 1;
 	}
 
@@ -36,14 +81,19 @@ int main(void){
 
 	if(bind(listen_socket, (struct sockaddr *) &address, sizeof(address))){
 		printf("Error binding socket\n");
+		fflush(stdout);
 		return 1;
 	}
 
 	if(listen(listen_socket, 10) < 0){
 		printf("Error listening\n");
+		fflush(stdout);
 		close(listen_socket);
 		exit(1);
 	}
+	uint8_t last_id = 0;
+
+	printf("Ready for listening\n");
 
 	for(;;){
 		addr_size = sizeof(remote_addr);
@@ -54,17 +104,51 @@ int main(void){
 			perror("accept");
 			exit(1);
 		}
+		printf("New connection\n");
+
+		//assign a new stream_id and create a pipe for the session
+		connection *new_conn = calloc(1, sizeof(connection));
+		new_conn->stream_id = last_id++;
+		
+		int32_t pipefd[2];
+		if(pipe(pipefd) < 0){
+			printf("Failed to create pipe\n");
+			continue;
+		}
+
+		new_conn->pipe_fd = pipefd[1];
+		new_conn->next = NULL;
+		
+		if(connections->first == NULL){
+			connections->first = new_conn;
+			printf("Added first connection with id: %d\n", new_conn->stream_id);
+			printf("Connection table (%p) has entry %p\n", connections, connections->first);
+			fflush(stdout);
+		} else {
+			connection *last = connections->first;
+			printf("New incoming connection\n");
+			printf("First connection was at %p\n", last);
+			fflush(stdout);
+			while(last->next != NULL){
+				last = last->next;
+				printf("Next connection was at %p\n", last);
+			}
+			last->next = new_conn;
+			printf("Added connection with id: %d at %p\n", new_conn->stream_id, last->next);
+			fflush(stdout);
+		}
 
 		int pid = fork();
-		if(pid > 0){ //child
+		if(pid == 0){ //child
 
 			close(listen_socket);
-			proxy_data(new_socket);
+			printf("demux reads from pipe fd %d", pipefd[1]);
+			fflush(stdout);
+			proxy_data(new_socket, new_conn->stream_id, pipefd[0]);
 			exit(0);
 		}
 
 		close(new_socket);
-
 		
 	}
 
@@ -84,21 +168,25 @@ struct socks_req {
 };
 
 //continuously read from the socket and look for a CONNECT message
-int proxy_data(int sockfd){
+int proxy_data(int sockfd, uint8_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);
+		fflush(stdout);
 	
 	int bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
 	if (bytes_read < 0){
-		printf("Error reading from socket\n");
+		printf("Error reading from socket (fd = %d)\n", sockfd);
+		fflush(stdout);
 		goto err;
 	}
 
-	printf("Received %d bytes:\n", bytes_read);
+	printf("Received %d bytes (id %d):\n", bytes_read, stream_id);
 	for(int i=0; i< bytes_read; i++){
 		printf("%02x ", buffer[i]);
 	}
 	printf("\n");
+		fflush(stdout);
 
 	//Respond to methods negotiation
 	struct socks_method_req *clnt_meth = (struct socks_method_req *) buffer;
@@ -106,6 +194,7 @@ int proxy_data(int sockfd){
 
 	if(clnt_meth->version != 0x05){
 		printf("Client supplied invalid version: %02x\n", clnt_meth->version);
+		fflush(stdout);
 	}
 
 	int responded = 0;
@@ -130,174 +219,192 @@ int proxy_data(int sockfd){
 	bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
 	if (bytes_read < 0){
 		printf("Error reading from socket\n");
+		fflush(stdout);
 		goto err;
 	}
 
-	printf("Received %d bytes:\n", bytes_read);
+	printf("Received %d bytes (id %d):\n", bytes_read, stream_id);
 	for(int i=0; i< bytes_read; i++){
 		printf("%02x ", buffer[i]);
 	}
 	printf("\n");
+		fflush(stdout);
 
+	//pre-pend stream_id and length
+	memmove(buffer+3, buffer, bytes_read+1);
 
-	struct socks_req *clnt_req = (struct socks_req *) buffer;
-	p = buffer+4;
-
-	//see if it's a connect request
-	if(clnt_req->cmd != 0x01){
-		printf("Error: issued a non-connect command\n");
-		goto err;
-	}
+	struct slitheen_up_hdr *up_hdr = (struct slitheen_up_hdr *) buffer;
+	up_hdr->stream_id = stream_id;
+	up_hdr->len = htons(bytes_read);
 
-	//send connect request to OUS
-	fd = open("OUS_in", O_WRONLY);
+	bytes_read+= 3;
 
-	write(fd, "Hi", sizeof("Hi"));
-	close(fd);
+	//encode bytes for safe transport (b64)
+	const char *encoded_bytes;
+	BUF_MEM *buffer_ptr;
+	BIO *bio, *b64;
+	b64 = BIO_new(BIO_f_base64());
+	bio = BIO_new(BIO_s_mem());
+	bio = BIO_push(b64, bio);
 
+	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
+	BIO_write(bio, buffer, bytes_read);
+	BIO_flush(bio);
+	BIO_get_mem_ptr(bio, &buffer_ptr);
+	BIO_set_close(bio, BIO_NOCLOSE);
+	BIO_free_all(bio);
+	encoded_bytes = (*buffer_ptr).data;
 
-	//from this point on, this code will live on slitheen relay
-
-    struct sockaddr_in dest;
-	dest.sin_family = AF_INET;
-	uint8_t domain_len;
-
-	switch(clnt_req->addr_type){
-	case 0x01:
-		//IPv4
-		dest.sin_addr.s_addr = *((uint32_t*) p);
-		printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
-		p += 4;
-		break;
-		
-	case 0x03:
-		//domain name
-		domain_len = p[0];
-		p++;
-		uint8_t *domain_name = calloc(1, domain_len+1);
-		memcpy(domain_name, p, domain_len);
-		domain_name[domain_len] = '\0';
-		struct hostent *host;
-		host = gethostbyname((const char *) domain_name);
-		dest.sin_addr = *((struct in_addr *) host->h_addr);
-		printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
-
-		p += domain_len;
-		free(domain_name);
-		break;
-	case 0x04:
-		//IPv6
-		goto err;//TODO: fix this
-		break;
-	}
-
-	//now set the port
-	dest.sin_port = *((uint16_t *) p);
-	printf("destination port: %d\n", ntohs(dest.sin_port));
-
-    int32_t handle = socket(AF_INET, SOCK_STREAM, 0);
-    if(handle < 0){
-        printf("error: constructing socket failed\n");
+	//send connect request to OUS
+	int ous_in = open("OUS_in", O_CREAT | O_WRONLY, 0666);
+	if(ous_in < 0){
+		printf("Error opening file OUS_in\n");
+		fflush(stdout);
 		goto err;
-    }
-
-	struct sockaddr_in my_addr;
-	socklen_t my_addr_len = sizeof(my_addr);
-
-    int32_t error = connect (handle, (struct sockaddr *) &dest, sizeof (struct sockaddr));
+	}
 
-    if(error <0){
-        printf("error connecting\n");
+	lseek(ous_in, 0, SEEK_END);
+	bytes_sent = write(ous_in, encoded_bytes, strlen(encoded_bytes));
+	bytes_sent += write(ous_in, " ", 1);//space delimiter
+	close(ous_in);
+	if(bytes_sent < 0){
+		printf("Error writing to named pipe\n");
+		fflush(stdout);
 		goto err;
-    }
-
-	getsockname(handle, (struct sockaddr *) &my_addr, &my_addr_len);
-
-	//now send the reply to the client
-	response[0] = 0x05;
-	response[1] = 0x00;//TODO: make this accurate
-	response[2] = 0x00;
-	response[3] = 0x01;
-	*((uint32_t *) (response + 4)) = my_addr.sin_addr.s_addr;
-	*((uint16_t *) (response + 8)) = my_addr.sin_port;
-
-	printf("Bound to %x:%d\n", my_addr.sin_addr.s_addr, ntohs(my_addr.sin_port));
+	} else {
+		printf("Wrote %d bytes to OUS_in:\n", bytes_sent);
+		for(int i=0; i< bytes_read; i++){
+			printf("%02x ",encoded_bytes[i]);
+		}
+		printf("\n");
+		fflush(stdout);
+	}
 
-	bytes_sent = send(sockfd, response, 10,0);
-	printf("Sent response (%d bytes):\n", bytes_sent);
-	for(int i=0; i< bytes_sent; i++){
-		printf("%02x ", response[i]);
+	p = buffer+sizeof(struct slitheen_up_hdr);
+	for(int i=0; i< bytes_read; i++){
+		printf("%02x ", p[i]);
 	}
 	printf("\n");
+		fflush(stdout);
+	struct socks_req *clnt_req = (struct socks_req *) p;
+	p += 4;
 
-	//now shuffle data
+	//see if it's a connect request
+	if(clnt_req->cmd != 0x01){
+		printf("Error: issued a non-connect command\n");
+		fflush(stdout);
+		goto err;
+	}
+	printf("Received a connect request from stream id %d\n", stream_id);
+		fflush(stdout);
 
+	//now select on pipe (for downstream data) and the socket (for upstream data)
 	for(;;){
 
 		fd_set readfds;
 		fd_set writefds;
 
-		int32_t nfds = (sockfd > handle) ? sockfd +1 : handle + 1;
+		int32_t nfds = (sockfd > ous_out) ? sockfd +1 : ous_out + 1;
+		//if(sockfd > ous_out){
+		//	nfds = (sockfd > ous_in) ? sockfd +1 : ous_in + 1;
+		//} else {
+		//	nfds = (ous_out > ous_in) ? ous_out +1 : ous_in + 1;
+		//}
 
 		FD_ZERO(&readfds);
 		FD_ZERO(&writefds);
 
 		FD_SET(sockfd, &readfds);
-		FD_SET(handle, &readfds);
+		FD_SET(ous_out, &readfds);
 		FD_SET(sockfd, &writefds);
-		FD_SET(handle, &writefds);
+		//FD_SET(ous_in, &writefds);
 
 		if(select(nfds, &readfds, &writefds, NULL, NULL) <0){
 			printf("Select error\n");
+		fflush(stdout);
 			continue;
 		}
 
-		if(FD_ISSET(sockfd, &readfds) && FD_ISSET(handle, &writefds)){
+		if(FD_ISSET(sockfd, &readfds)){// && FD_ISSET(ous_in, &writefds)){
 
 			bytes_read = recv(sockfd, buffer, BUFSIZ-1, 0);
 			if (bytes_read < 0){
-				printf("Error reading from socket\n");
+				printf("Error reading from socket (in for loop)\n");
+		fflush(stdout);
 				goto err;
 			}
 
 			if(bytes_read > 0){
 
-				printf("Received %d bytes:\n", bytes_read);
+				printf("Received %d data bytes from sockfd (id %d):\n", bytes_read, stream_id);
 				for(int i=0; i< bytes_read; i++){
 					printf("%02x ", buffer[i]);
 				}
 				printf("\n");
-
-				bytes_sent = send(handle, buffer, bytes_read, 0);
-				printf("Sent to website (%d bytes):\n", bytes_sent);
-				for(int i=0; i< bytes_sent; i++){
-					printf("%02x ", buffer[i]);
+		fflush(stdout);
+				memmove(buffer+sizeof(struct slitheen_up_hdr), buffer, bytes_read);
+
+				up_hdr = (struct slitheen_up_hdr *) buffer;
+				up_hdr->stream_id = stream_id;
+				up_hdr->len = htons(bytes_read);
+
+				bytes_read+= 3;
+
+				bio = BIO_new(BIO_s_mem());
+				b64 = BIO_new(BIO_f_base64());
+				bio = BIO_push(b64, bio);
+
+				printf("HERE\n");
+				fflush(stdout);
+				BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
+				BIO_write(bio, buffer, bytes_read);
+				BIO_flush(bio);
+				BIO_get_mem_ptr(bio, &buffer_ptr);
+				BIO_set_close(bio, BIO_NOCLOSE);
+				BIO_free_all(bio);
+				encoded_bytes = (*buffer_ptr).data;
+
+				int ous_in = open("OUS_in", O_CREAT | O_WRONLY, 0666);
+				if(ous_in < 0){
+					printf("Error opening file OUS_in\n");
+		fflush(stdout);
+					goto err;
 				}
-				printf("\n");
+
+				lseek(ous_in, 0, SEEK_END);
+				bytes_sent = write(ous_in, encoded_bytes, strlen(encoded_bytes));
+				bytes_sent += write(ous_in, " ", 1);//space delimiter
+
+				close(ous_in);
+				printf("Sent to OUS (%d bytes):%s\n",bytes_sent, encoded_bytes );
+		fflush(stdout);
 
 			}
-		} else if(FD_ISSET(handle, &readfds) && FD_ISSET(sockfd, &writefds)){
+		} else if(FD_ISSET(ous_out, &readfds) && FD_ISSET(sockfd, &writefds)){
 
-			bytes_read = recv(handle, buffer, BUFSIZ-1, 0);
+			bytes_read = read(ous_out, buffer, BUFSIZ-1);
 			if (bytes_read < 0){
-				printf("Error reading from socket\n");
+				printf("Error reading from ous_out (in for loop)\n");
+		fflush(stdout);
 				goto err;
 			}
 
 			if(bytes_read > 0){
 
-				printf("Received %d bytes:\n", bytes_read);
+				printf("Stream id %d received %d bytes from ous_out:\n", stream_id, bytes_read);
 				for(int i=0; i< bytes_read; i++){
 					printf("%02x ", buffer[i]);
 				}
 				printf("\n");
+		fflush(stdout);
 
 				bytes_sent = send(sockfd, buffer, bytes_read, 0);
-				printf("Sent to website (%d bytes):\n", bytes_sent);
+				printf("Sent to browser (%d bytes):\n", bytes_sent);
 				for(int i=0; i< bytes_sent; i++){
 					printf("%02x ", buffer[i]);
 				}
 				printf("\n");
+		fflush(stdout);
 
 			}
 		}
@@ -310,3 +417,97 @@ err:
 	free(response);
 	exit(0);
 }
+
+void *demultiplex_data(){
+
+	int32_t buffer_len = BUFSIZ;
+	uint8_t *buffer = calloc(1, buffer_len);
+	uint8_t *p;
+
+	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;
+
+	for(;;){
+		int32_t bytes_read = read(ous_fd, buffer, buffer_len-overflow_len);
+		
+		if(bytes_read > 0){
+			int32_t bytes_remaining = bytes_read;
+
+			if(overflow_len > 0){
+				//process first part of slitheen info
+				memmove(buffer+overflow_len, buffer, bytes_read);
+				memcpy(buffer, overflow, overflow_len);
+				bytes_remaining += overflow_len;
+				free(overflow);
+				overflow_len = 0;
+			}
+
+			p = buffer;
+			while(bytes_remaining > 0){
+
+				struct slitheen_hdr *sl_hdr = (struct slitheen_hdr *) p;
+				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;
+				}
+				p += sizeof(struct slitheen_hdr);
+
+				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 pipe_fd =-1;
+
+					if(connections->first == NULL){
+						printf("There are no connections\n");
+					} else {
+						printf("First connection was at %p\n", connections->first);
+						connection *last = connections->first;
+						if (last->stream_id == sl_hdr->stream_id){
+							printf("Found stream id %d!\n", sl_hdr->stream_id);
+							pipe_fd = last->pipe_fd;
+							printf("Pipe fd: %d\n", pipe_fd);
+						}
+						while(last->next != NULL){
+							last = last->next;
+							printf("Next connection was at %p\n", last);
+							if (last->stream_id == sl_hdr->stream_id){
+								printf("Found stream id %d!\n", sl_hdr->stream_id);
+								pipe_fd = last->pipe_fd;
+								printf("Pipe fd: %d\n", pipe_fd);
+							}
+						}
+					}
+					
+					if(pipe_fd == -1){
+						printf("No stream id exists\n");
+					} else {
+						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);
+			}
+
+		} else {
+			printf("Error: read %d bytes from OUS_out\n", bytes_read);
+			printf("Opening OUS_out\n");
+			close(ous_fd);
+			ous_fd = open("OUS_out", O_RDONLY);
+			printf("Opened.\n");
+		}
+		
+	}
+
+	close(ous_fd);
+
+}

+ 6 - 0
server/flow.c

@@ -11,6 +11,7 @@
 static flow_table *table;
 static session_cache *sessions;
 data_queue *downstream_queue;
+stream_table *streams;
 
 /* Initialize the table of tagged flows */
 int init_tables(void) {
@@ -21,6 +22,9 @@ int init_tables(void) {
 
 	downstream_queue = calloc(1, sizeof(data_queue));
 	downstream_queue->first_block = NULL;
+	
+	streams = calloc(1, sizeof(stream_table));
+	streams->first = NULL;
 	printf("initialized downstream queue\n");
 
 	return 0;
@@ -44,7 +48,9 @@ flow *add_flow(flow newFlow) {
 	newFlow.current_session = NULL;
 	newFlow.packet_chain = NULL;
 	newFlow.censored_queue = NULL;
+	newFlow.outbox = NULL;
 	newFlow.outbox_len = 0;
+	newFlow.outbox_offset = 0;
 	newFlow.remaining_record_len = 0;
 	newFlow.remaining_response_len = 0;
 	newFlow.httpstate = PARSE_HEADER;

+ 1 - 1
server/flow.h

@@ -104,7 +104,7 @@ typedef struct flow_st {
 
 	uint8_t *outbox;
 	int32_t outbox_len;
-	int32_t outbox_data_len;
+	int32_t outbox_offset;
 
 	//locking
 	//pthread_mutex_t flow_lock = PTHREAD_MUTEX_INITIALIZER;

+ 399 - 83
server/relay.c

@@ -31,8 +31,10 @@
  *  	0 on success, 1 on failure
  */
 int replace_packet(flow *f, struct packet_info *info){
+	printf("Enter replace_packet\n");
+	fflush(stdout);
 
-	if (info->tcp_hdr == NULL){
+	if (info == NULL || info->tcp_hdr == NULL){
 		return 0;
 	}
 
@@ -61,6 +63,10 @@ int replace_packet(flow *f, struct packet_info *info){
 		uint32_t offset = htonl(info->tcp_hdr->sequence_num) - f->seq_num;
 		if(offset == 0)
 			f->seq_num += info->app_data_len;
+		else
+			printf("Offset is nonzero\n");
+
+	fflush(stdout);
 		/* if incoming, replace with data from queue */
 		//if(htonl(tcp_hdr->sequence_num) >= f->seq_num){
 			process_downstream(f, offset, info);
@@ -79,6 +85,8 @@ int replace_packet(flow *f, struct packet_info *info){
 #endif
 
 	}
+	printf("Done replace_packet\n");
+	fflush(stdout);
 	return 0;
 
 }
@@ -101,6 +109,9 @@ int replace_packet(flow *f, struct packet_info *info){
 int read_header(flow *f, struct packet_info *info){
 	uint8_t *p = info->app_data;
 
+	printf("IN read_header\n");
+	fflush(stdout);
+
 	if (info->tcp_hdr == NULL){
 		return 0;
 	}
@@ -108,17 +119,26 @@ int read_header(flow *f, struct packet_info *info){
 	struct record_header *record_hdr = (struct record_header*) p;
 	uint32_t record_length = RECORD_LEN(record_hdr);
 
+	printf("HERE\n");
+	fflush(stdout);
+
 	uint8_t *decrypted_data = calloc(1, info->app_data_len);
 
+	printf("HERE2\n");
+	fflush(stdout);
 	p+= RECORD_HEADER_LEN;
 
 	memcpy(decrypted_data, p, record_length);
+	printf("HERE3\n");
+	fflush(stdout);
 
 	if(!encrypt(f, decrypted_data, decrypted_data, record_length, 0, record_hdr->type, 0)){
 		fprintf(stdout,"upstream decryption failed\n");
+	fflush(stdout);
 		return 0;
 	} else {
 		fprintf(stdout, "upstream decryption succeeded\n");
+	fflush(stdout);
 	}
 
 	if(record_hdr->type == 0x15){
@@ -129,9 +149,13 @@ int read_header(flow *f, struct packet_info *info){
 		fflush(stdout);
 	}
 
+	printf("Upstream data:\n");
+	printf("%s\n", decrypted_data+EVP_GCM_TLS_EXPLICIT_IV_LEN);
+
 	//TODO: re-write this to take a SOCKS connection request
 	/* search through decrypted data for x-ignore */
 	char *header_ptr = strstr((const char *) decrypted_data, "X-Slitheen");
+
 	uint8_t *upstream_data;
 	if(header_ptr == NULL){
 		printf("UPSTREAM: No x-slitheen header found\n");
@@ -142,64 +166,174 @@ int read_header(flow *f, struct packet_info *info){
 	fprintf(stdout, "Sequence number: %d\n", info->tcp_hdr->sequence_num);
 
 	header_ptr += strlen("X-Slitheen: ");
+	int32_t num_messages = 1;
+	char *messages[50]; //TODO:make not just 10?
+	messages[0] = header_ptr;
 	char *c = header_ptr;
 	while(*c != '\r'){
+		if(*c == ' '){
+			*c = '\0';
+			messages[num_messages] = c+1;
+			num_messages ++;
+		}
 		c++;
 	}
 	c++;
 	*c = '\0';
-	printf("upstream data: %s\n", header_ptr);
-
-	//b64 decode the data
-	int32_t decode_len = strlen(header_ptr);
-	if(header_ptr[decode_len-2] == '='){
-		decode_len = decode_len*3/4 - 2;
-	} else if(header_ptr[decode_len-1] == '='){
-		decode_len = decode_len*3/4 - 1;
-	} else {
-		decode_len = decode_len*3/4;
-	}
+	printf("upstream data (%d messages):\n", num_messages);
 
-	upstream_data = calloc(1, decode_len + 1);
+	for(int i=0; i< num_messages-1; i++){
+		char *message = messages[i];
+		printf("Message (%d bytes): %s\n", strlen(message), message);
+		fflush(stdout);
 
-	BIO *bio, *b64;
-	bio = BIO_new_mem_buf(header_ptr, -1);
-	b64 = BIO_new(BIO_f_base64());
-	bio = BIO_push(b64, bio);
-	BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
+		//b64 decode the data
+		int32_t decode_len = strlen(message);
+		if(message[decode_len-2] == '='){
+			decode_len = decode_len*3/4 - 2;
+		} else if(message[decode_len-1] == '='){
+			decode_len = decode_len*3/4 - 1;
+		} else {
+			decode_len = decode_len*3/4;
+		}
 
-	int32_t output_len = BIO_read(bio, upstream_data, strlen(header_ptr));
-	if(output_len != decode_len)
-		printf("UH OH, lens dont match\n");
+		upstream_data = calloc(1, decode_len + 1);
+		printf("HERE\n");
+		fflush(stdout);
 
-	printf("Decoded to get %d bytes:\n", output_len);
-	for(int i=0; i< output_len; i++){
-		printf("%02x ", upstream_data[i]);
-	}
-	printf("\n");
-	uint8_t stream_id = upstream_data[0];
-	p = upstream_data +1;
+		BIO *bio, *b64;
+		bio = BIO_new_mem_buf(message, -1);
+		printf("HERE 2\n");
+		fflush(stdout);
+		b64 = BIO_new(BIO_f_base64());
+		printf("HERE 3\n");
+		fflush(stdout);
+		bio = BIO_push(b64, bio);
+		printf("HERE 4\n");
+		fflush(stdout);
+		BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
+		printf("HERE 5\n");
+		fflush(stdout);
 
-	printf("Received bytes with stream id %d\n", stream_id);
+		int32_t output_len = BIO_read(bio, upstream_data, strlen(message));
+		printf("HERE 6\n");
+		fflush(stdout);
 
-	//If a thread for this stream id exists, get the thread info and pipe data
-	//TODO: fill this in
+		BIO_free_all(bio);
+		if(output_len != decode_len)
+			printf("UH OH, lens dont match\n. %d != %d", decode_len, output_len);
+		fflush(stdout);
 
-	/*Else, spawn a thread to handle the proxy to this site*/
-	pthread_t *proxy_thread = calloc(1, sizeof(pthread_t));
-	int32_t pipefd[2];
-	if(pipe(pipefd) < 0){
-		printf("Failed to create pipe for new thread\n");
-		return 1;
-	}
+		printf("Decoded to get %d bytes:\n", output_len);
+		for(int i=0; i< output_len; i++){
+			printf("%02x ", upstream_data[i]);
+		}
+		printf("\n");
+		fflush(stdout);
 
-	struct proxy_thread_data *thread_data = 
-		calloc(1, sizeof(struct proxy_thread_data));
-	thread_data->initial_data = upstream_data;
-	thread_data->f = f;
-	thread_data->pipefd = pipefd[0];
-	
-	pthread_create(proxy_thread, NULL, proxy_covert_site, (void *) thread_data);
+		p = upstream_data;
+
+		while(output_len > 0){
+			printf("Bytes left to process: %d\n", output_len);
+				fflush(stdout);
+			struct sl_up_hdr *sl_hdr = (struct sl_up_hdr *) p;
+			uint8_t stream_id = sl_hdr->stream_id;
+			uint16_t stream_len = ntohs(sl_hdr->len);
+
+			p += sizeof(struct sl_up_hdr);
+			output_len -= sizeof(struct sl_up_hdr);
+			if(stream_len > output_len)
+				printf("UH OH missing part of stream\n");
+
+			printf("Received bytes with stream id %d of len %d\n", stream_id, stream_len);
+				fflush(stdout);
+
+			//If a thread for this stream id exists, get the thread info and pipe data
+			int32_t stream_pipe = -1;
+			if(streams->first != NULL){
+				stream *last = streams->first;
+				if(last->stream_id == stream_id){
+					printf("Found stream in table!\n");
+				fflush(stdout);
+					stream_pipe = last->pipefd;
+				}
+				while(last->next != NULL){
+					last = last->next;
+					if(last->stream_id == stream_id){
+						printf("Found stream in table!\n");
+				fflush(stdout);
+						stream_pipe = last->pipefd;
+						break;
+					}
+				}
+			}
+
+			if(stream_pipe != -1){
+				int32_t bytes_sent = write(stream_pipe, p, stream_len);
+				if(bytes_sent < 0){
+					printf("Error writing to stream pipe\n");
+				fflush(stdout);
+				}
+
+			} else {
+				printf("Stream not found\n");
+				printf("Adding thread\n");
+				fflush(stdout);
+
+				/*Else, spawn a thread to handle the proxy to this site*/
+				pthread_t *proxy_thread = calloc(1, sizeof(pthread_t));
+				int32_t pipefd[2];
+				if(pipe(pipefd) < 0){
+					printf("Failed to create pipe for new thread\n");
+					return 1;
+				}
+				uint8_t *initial_data = calloc(1,stream_len);
+				memcpy(initial_data, p, stream_len);
+
+				struct proxy_thread_data *thread_data = 
+					calloc(1, sizeof(struct proxy_thread_data));
+				thread_data->initial_data = initial_data;
+				thread_data->initial_len = stream_len;
+				thread_data->f = f;
+				thread_data->stream_id = stream_id;
+				thread_data->pipefd = pipefd[0];
+				
+				pthread_create(proxy_thread, NULL, proxy_covert_site, (void *) thread_data);
+
+				//add stream to table
+				stream *new_stream = calloc(1, sizeof(stream));
+				new_stream->stream_id = stream_id;
+				new_stream->pipefd = pipefd[1];
+
+				if(streams->first == NULL){
+					streams->first = new_stream;
+				} else {
+					stream *last = streams->first;
+					while(last->next != NULL){
+						last = last->next;
+					}
+					last->next = new_stream;
+				}
+				printf("Added new stream to table\n");
+				fflush(stdout);
+
+			}
+			printf("Finished processing %d data\n", stream_len);
+				fflush(stdout);
+			output_len -= stream_len;
+			p += stream_len;
+			printf("Done adding thread\n");
+			fflush(stdout);
+
+		}
+		printf("Finished processing bytes\n");
+			fflush(stdout);
+		printf("Freeing %p\n", upstream_data);
+		fflush(stdout);
+		free(upstream_data);
+	}
+	printf("Finished processing messages\n");
+			fflush(stdout);
 
 	//save a reference to the proxy threads in a global table
 	
@@ -209,13 +343,19 @@ int read_header(flow *f, struct packet_info *info){
 	if(bytes_written < strlen( (const char *) message)){
 		printf("failed to write all bytes to pipe\n");
 	}*/
+	free(decrypted_data);
 
 	return 0;
 
 err:
 	if(upstream_data != NULL){
+		printf("Freeing %p\n", upstream_data);
+		fflush(stdout);
 		free(upstream_data);
 	}
+	if(decrypted_data != NULL){
+		free(decrypted_data);
+	}
 	return 1;
 }
 
@@ -239,14 +379,21 @@ void *proxy_covert_site(void *data){
 	flow *f = thread_data->f;
 
 	uint8_t *p = thread_data->initial_data;
-	uint8_t stream_id = p[0];
-	p++;
+	uint8_t stream_id = thread_data->stream_id;
+
+	printf("request: ");
+	for(int i=0; i< sizeof(struct socks_req); i++){
+		printf("%02x ", p[i]);
+	}
+	printf("\n");
+	fflush(stdout);
 	struct socks_req *clnt_req = (struct socks_req *) p;
 	p += 4;
 
 	//see if it's a connect request
 	if(clnt_req->cmd != 0x01){
 		printf("Error: issued a non-connect command\n");
+	fflush(stdout);
 		goto err;
 	}
 
@@ -259,6 +406,7 @@ void *proxy_covert_site(void *data){
 		//IPv4
 		dest.sin_addr.s_addr = *((uint32_t*) p);
 		printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
+	fflush(stdout);
 		p += 4;
 		break;
 		
@@ -273,8 +421,11 @@ void *proxy_covert_site(void *data){
 		host = gethostbyname((const char *) domain_name);
 		dest.sin_addr = *((struct in_addr *) host->h_addr);
 		printf("destination addr: %d\n", ntohl(dest.sin_addr.s_addr));
+	fflush(stdout);
 
 		p += domain_len;
+		printf("Freeing %p\n", domain_name);
+		fflush(stdout);
 		free(domain_name);
 		break;
 	case 0x04:
@@ -286,10 +437,12 @@ void *proxy_covert_site(void *data){
 	//now set the port
 	dest.sin_port = *((uint16_t *) p);
 	printf("destination port: %d\n", ntohs(dest.sin_port));
+	fflush(stdout);
 
     int32_t handle = socket(AF_INET, SOCK_STREAM, 0);
     if(handle < 0){
         printf("error: constructing socket failed\n");
+	fflush(stdout);
 		goto err;
     }
 
@@ -300,6 +453,7 @@ void *proxy_covert_site(void *data){
 
     if(error <0){
         printf("error connecting\n");
+	fflush(stdout);
 		goto err;
     }
 
@@ -320,6 +474,7 @@ void *proxy_covert_site(void *data){
 		printf("%02x ", response[i]);
 	}
 	printf("\n");
+	fflush(stdout);
 
 	queue_block *new_block = calloc(1, sizeof(queue_block));
 	printf("Inserting new block into queue: %p\n", new_block);
@@ -340,9 +495,10 @@ void *proxy_covert_site(void *data){
 			last = last->next;
 		last->next = new_block;
 	}
-	return 0; //slowly test
 
-	/*now select on reading from the pipe and from the socket
+	uint8_t *buffer = calloc(1, BUFSIZ);
+	int32_t buffer_len = BUFSIZ;
+	//now select on reading from the pipe and from the socket
 	for(;;){
 		fd_set readfds;
 		fd_set writefds;
@@ -359,26 +515,34 @@ void *proxy_covert_site(void *data){
 
 		if (select(nfds, &readfds, &writefds, NULL, NULL) < 0){
 			printf("select error\n");
+	fflush(stdout);
 		}
 
 		if(FD_ISSET(thread_data->pipefd, &readfds) && FD_ISSET(handle, &writefds)){
 			//we have upstream data ready for writing
 			printf("Passing along upstream data\n");
+	fflush(stdout);
 
 			int32_t bytes_read = read(thread_data->pipefd, buffer, buffer_len);
-			buffer[buffer_len] = '\0';//TODO: remove w/ print
-			printf("Read from pipe:\n %s\n", buffer);
+			printf("Read from stream pipe:\n");
+			for(int i=0; i< bytes_read; i++){
+				printf("%02x ", buffer[i]);
+			}
+			printf("\n");
+	fflush(stdout);
 
 			if(bytes_read > 0){
 				int32_t bytes_sent = send(handle, buffer,
 						bytes_read, 0);
 				if( bytes_sent < 0){
 					printf("error sending request\n");
+	fflush(stdout);
 					break;
 				} else if (bytes_sent < bytes_read){
 					//TODO: should update buffer and keep
 					//track of length of upstream data
 					printf("sent less than full upstream bytes\n");
+	fflush(stdout);
 					break;
 				}
 			}
@@ -386,42 +550,60 @@ void *proxy_covert_site(void *data){
 		}
 		
 		if (FD_ISSET(handle, &readfds)){
+			printf("Received downstream data\n");
+	fflush(stdout);
 			//we have downstream data read for saving
 			int32_t bytes_read;
-			uint8_t *buf = calloc(1, BUFSIZ);
-			bytes_read = recv(handle, buf, BUFSIZ, 0);
+			bytes_read = recv(handle, buffer, buffer_len, 0);
 			if(bytes_read <= 0){
 				break;
 			}
 			if(bytes_read > 0){
+				printf("Stream %d read %d downstream bytes:\n", stream_id, bytes_read);
+				for(int i=0; i< bytes_read; i++){
+					printf("%02x ", buffer[i]);
+				}
+				printf("\n");
+	fflush(stdout);
+				uint8_t *new_data = calloc(1, bytes_read);
+				memcpy(new_data, buffer, bytes_read);
 
 				//make a new queue block
 				new_block = calloc(1, sizeof(queue_block));
+				printf("Inserting new block into queue: %p\n", new_block);
+				fflush(stdout);
 				new_block->len = bytes_read;
 				new_block->offset = 0;
-				new_block->data = buf;
+				new_block->data = new_data;
 				new_block->next = NULL;
-				if(f->censored_queue == NULL)
-					f->censored_queue = new_block;
+				new_block->stream_id = stream_id;
+				printf("downstream_queue is at %p\n", downstream_queue);
+				fflush(stdout);
+				if(downstream_queue->first_block == NULL){
+					downstream_queue->first_block = new_block;
+				}
 				else{
-					queue_block *last = f->censored_queue;
+					queue_block *last = downstream_queue->first_block;
 					while(last->next != NULL)
 						last = last->next;
 					last->next = new_block;
 				}
 			} else {
 				printf("read 0 bytes\n");
+	fflush(stdout);
 			}
 
 		}
 	}
+	printf("Freeing: %p, %p\n", thread_data, buffer);
 	free(thread_data);
 	free(buffer);
 	close(handle);
-	*/
 	return 0;
 err:
 	if(thread_data->initial_data != NULL){
+		printf("Freeing %p\n", thread_data->initial_data);
+		fflush(stdout);
 		free(thread_data->initial_data);
 	}
 	close(handle);
@@ -444,6 +626,8 @@ err:
  *  	Returns 0 on sucess 
  */
 int process_downstream(flow *f, int32_t offset, struct packet_info *info){
+	printf("Enter process_downstream\n");
+	fflush(stdout);
 
 	printf("Processing downstream data\n");
 	uint8_t changed = 0;
@@ -457,10 +641,35 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 	if(f->remaining_record_len > 0){
 		//ignore bytes until the end of the record
 		if(f->remaining_record_len > remaining_packet_len){ //ignore entire packet
+			if(f->outbox_len > 0){
+				changed = 1;
+				printf("First byte to copy: %02x %02x\n", f->outbox[f->outbox_offset], f->outbox[f->outbox_offset+1]);
+				memcpy(p, f->outbox + f->outbox_offset, remaining_packet_len);
+				f->outbox_len -= remaining_packet_len;
+				f->outbox_offset += remaining_packet_len;
+				printf("Copied %d bytes from outbox %p at offset %d, %d bytes left to ignore\n", remaining_packet_len, f->outbox, f->outbox_offset, f->outbox_len);
+				
+			}
 			f->remaining_record_len -= remaining_packet_len;
-			printf("Ignoring %d bytes, %d bytes left to ignore\n", remaining_packet_len, f->remaining_record_len);
+			printf("Ignored/copied %d bytes, %d bytes left to ignore\n", remaining_packet_len, f->remaining_record_len);
 			remaining_packet_len -= remaining_packet_len;
 		} else {
+			if(f->outbox_len > 0){
+				changed = 1;
+				memcpy(p, f->outbox + f->outbox_offset, f->remaining_record_len);
+				if(f->outbox_len != f->remaining_record_len){
+					printf("UH OH: outbox (%d bytes left) and record (%d bytes left) did not align\n", f->outbox_len, f->remaining_record_len);
+				}
+				printf("Copied %d bytes from outbox, 0 bytes left to ignore\n", f->remaining_record_len);
+				printf("Copied %d bytes from outbox %p at offset %d, %d bytes left to ignore\n", f->remaining_record_len, f->outbox, f->outbox_offset, 0);
+				printf("First byte copied: %02x %02x\n", p[0], p[1]);
+				f->outbox_len = 0;
+				f->outbox_offset=0;
+		printf("Freeing %p\n", f->outbox);
+		fflush(stdout);
+				free(f->outbox);
+			}
+
 			p += f->remaining_record_len;
 			printf("Ignoring %d bytes\n", f->remaining_record_len);
 			remaining_packet_len -= f->remaining_record_len;
@@ -482,6 +691,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
+	fflush(stdout);
 
 		p += RECORD_HEADER_LEN;
 		remaining_packet_len -= RECORD_HEADER_LEN;
@@ -490,42 +700,86 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 		uint32_t remaining_record_len = record_len;
 
 		if(record_len > remaining_packet_len){
-			//for now, just forfeit this record
 			printf("Record is too long\n");
+	fflush(stdout);
 			f->remaining_record_len = record_len - remaining_packet_len;
-			remaining_packet_len -= remaining_packet_len;
 
 			if(f->httpstate == PARSE_HEADER || f->httpstate == BEGIN_CHUNK || f->httpstate == END_CHUNK){
 				f->httpstate = FORFEIT_REST;
 			} else if( f->httpstate == MID_CONTENT || f->httpstate == MID_CHUNK){
 				f->remaining_response_len -= record_len - 24; //len of IV and padding
 				printf("remaining response len: %d\n", f->remaining_response_len);
+	fflush(stdout);
+				if(f->remaining_response_len >= 0 && f->replace_response){
+					printf("Should be replacing this\n");
+	fflush(stdout);
+//#ifdef nothing
+					//make a huge record, encrypt it, and then place it in the outbox
+					f->outbox = calloc(1, record_len+1);
+					f->outbox_len = record_len;
+					f->outbox_offset = 0;
+					fill_with_downstream(f, f->outbox + EVP_GCM_TLS_EXPLICIT_IV_LEN , record_len - (EVP_GCM_TLS_EXPLICIT_IV_LEN+ 16)); //for now hard coded length of padding. TODO: fix this
+					//encrypt
+					printf("Encrypting outbox\n");
+	fflush(stdout);
+					int32_t n = encrypt(f, f->outbox, f->outbox,
+									record_len - 16, 1,
+									record_hdr->type, 1);
+					if(n < 0){
+						fprintf(stdout,"outbox encryption failed\n");
+	fflush(stdout);
+					} else {
+						
+						printf("Record len was: %d. Outbox len is: %d\n", record_len, n);
+	fflush(stdout);
+						memcpy(p, f->outbox, remaining_packet_len);
+						changed = 1;
+						f->outbox_len -= remaining_packet_len;
+						f->outbox_offset += remaining_packet_len;
+						printf("Copied %d from outbox. Offset is at %d\n", remaining_packet_len, f->outbox_offset);
+	fflush(stdout);
+					}
+					printf("Outbox encryption successful!\n");
+	fflush(stdout);
+//#endif
+
+				} else if(f->replace_response){
+					printf("record_len exceeds response len by %d\n", f->remaining_response_len);
+	fflush(stdout);
+				}
 				if(f->remaining_response_len == 0){
 					if(f->httpstate == MID_CHUNK)
 						f->httpstate = END_CHUNK;
-					else 
-						f->httpstate = END_BODY;
+					else {
+						printf("END_CONTENT\n");
+	fflush(stdout);
+						f->httpstate = PARSE_HEADER;
+					}
 				}
 				if(f->remaining_response_len < 0){
 					f->remaining_response_len = 0;
 					f->httpstate = FORFEIT_REST;
 				}
 			}
+			remaining_packet_len -= remaining_packet_len;
 			break;
 		}
 
 
 		//now decrypt the record
 		printf("Decrypting record\n");
+	fflush(stdout);
 		int32_t n = encrypt(f, record_ptr, record_ptr, record_len, 1,
 						record_hdr->type, 0);
 		if(n < 0){
 			//do something smarter here
 			fprintf(stdout,"application decryption failed\n");
+	fflush(stdout);
 			return 0;
 		}
 		changed = 1;
 		printf("Decryption succeeded\n");
+	fflush(stdout);
 		
 		printf("Bytes:\n");
 		for(int i=0; i< n; i++){
@@ -534,6 +788,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 		printf("\n");
 		printf("Text:\n");
 		printf("%s\n", record_ptr+EVP_GCM_TLS_EXPLICIT_IV_LEN);
+	fflush(stdout);
 
 		p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 		char *len_ptr, *needle;
@@ -546,10 +801,31 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 				case PARSE_HEADER:
 					//determine whether it's transfer encoded or otherwise
+					printf("IN PARSE HEADER\n");
+	fflush(stdout);
+					//figure out what the content-type is
+					len_ptr = strstr((const char *) p, "Content-Type: image");
+					if(len_ptr != NULL){
+						printf("SLITHEEN: replaceable content\n");
+	fflush(stdout);
+						f->replace_response = 1;
+						memcpy(len_ptr + 14, "slitheen", 8);
+						char *c = len_ptr + 14+8;
+						while(c[0] != '\r'){
+							c[0] = ' ';
+							c++;
+						}
+					} else {
+						printf("SLITHEEN: non-replaceable content\n");
+	fflush(stdout);
+						f->replace_response = 0;
+					}
+
 					len_ptr = strstr((const char *) p, "Transfer-Encoding");
 					if(len_ptr != NULL){
 						if(!memcmp(len_ptr + 19, "chunked", 7)){
 							printf("SLITHEEN: transfer chunked\n");
+	fflush(stdout);
 							//now find end of header
 							
 							len_ptr = strstr((const char *) p, "\r\n\r\n");
@@ -558,6 +834,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 								remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
 								p = (uint8_t *) len_ptr + 4;
 								printf("remaining record len: %d\n", remaining_record_len);
+	fflush(stdout);
 							}
 						}
 					} else {
@@ -566,14 +843,17 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 							len_ptr += 15;
 							f->remaining_response_len = strtol((const char *) len_ptr, NULL, 10);
 							printf("SLITHEEN: Content-Length: %d\n", f->remaining_response_len);
+	fflush(stdout);
 							len_ptr = strstr((const char *) p, "\r\n\r\n");
 							if(len_ptr != NULL){
 								f->httpstate = MID_CONTENT;
 								remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
 								p = (uint8_t *) len_ptr + 4;
 								printf("remaining record len: %d\n", remaining_record_len);
+	fflush(stdout);
 							} else {
 								printf("UH OH\n");
+	fflush(stdout);
 								remaining_record_len = 0;
 								f->httpstate = FORFEIT_REST;
 							}
@@ -583,40 +863,31 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						}
 					}
 
-					//figure out what the content-type is
-					len_ptr = strstr((const char *) record_ptr, "Content-Type: image");
-					if(len_ptr != NULL){
-						printf("SLITHEEN: replaceable content\n");
-						f->replace_response = 1;
-						memcpy(len_ptr + 14, "slitheen", 8);
-						char *c = len_ptr + 14+8;
-						while(c[0] != '\r'){
-							c[0] = ' ';
-							c++;
-						}
-					} else {
-						printf("SLITHEEN: non-replaceable content\n");
-						f->replace_response = 0;
-					}
 					break;
 
 				case MID_CONTENT:
 					//check if content is replaceable
 					printf("In MID_CONTENT\n");
+	fflush(stdout);
 					if(f->remaining_response_len > remaining_record_len){
 						if(f->replace_response){
 							fill_with_downstream(f, p, remaining_record_len);
 							printf("Replaced with:\n");
+	fflush(stdout);
 							for(int i=0; i< remaining_record_len; i++){
 								printf("%02x ", p[i]);
 							}
 							printf("\n");
+						} else {
+							printf("Non-replaceable content\n");
+	fflush(stdout);
 						}
 						f->remaining_response_len -= remaining_record_len;
 						p += remaining_record_len;
 					
 						remaining_record_len = 0;
 						printf("%d bytes left of body\n", f->remaining_response_len);
+	fflush(stdout);
 					} else {
 						if(f->replace_response){
 							fill_with_downstream(f, p, remaining_record_len);
@@ -625,20 +896,27 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 								printf("%02x ", p[i]);
 							}
 							printf("\n");
+	fflush(stdout);
+						} else {
+							printf("Non-replaceable content\n");
+	fflush(stdout);
 						}
 						remaining_record_len -= f->remaining_response_len;
 						p += f->remaining_response_len;
 						f->httpstate = PARSE_HEADER;
 						f->remaining_response_len = 0;
 						printf("rem. response len = %d\n", f->remaining_response_len);
+	fflush(stdout);
 					}
 					break;
 
 				case BEGIN_CHUNK:
 					printf("In BEGIN_CHUNK\n");
+	fflush(stdout);
 
 					int32_t chunk_size = strtol((const char *) p, NULL, 16);
 					printf("chunk size: %x\n", chunk_size);
+	fflush(stdout);
 					if(chunk_size == 0){
 						f->httpstate = END_BODY;
 					} else {
@@ -650,8 +928,10 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						remaining_record_len -= ((uint8_t *) needle - p + 2);
 						p = (uint8_t *) needle + 2;
 						printf("remaining_record len = %d\n", remaining_record_len);
+	fflush(stdout);
 					} else {
 						printf("UH OH\n");
+	fflush(stdout);
 						remaining_record_len = 0;
 						f->httpstate = FORFEIT_REST;
 					}
@@ -659,6 +939,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 				case MID_CHUNK:
 					printf("In MID_CHUNK\n");
+	fflush(stdout);
 					if(f->remaining_response_len > remaining_record_len){
 						if(f->replace_response){
 							fill_with_downstream(f, p, remaining_record_len);
@@ -667,12 +948,14 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 								printf("%02x ", p[i]);
 							}
 							printf("\n");
+	fflush(stdout);
 						}
 						f->remaining_response_len -= remaining_record_len;
 						p += remaining_record_len;
 					
 						remaining_record_len = 0;
 						printf("%d bytes left of chunk\n", f->remaining_response_len);
+	fflush(stdout);
 					} else {
 						if(f->replace_response){
 							fill_with_downstream(f, p, remaining_record_len);
@@ -681,16 +964,19 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 								printf("%02x ", p[i]);
 							}
 							printf("\n");
+	fflush(stdout);
 						}
 						remaining_record_len -= f->remaining_response_len;
 						p += f->remaining_response_len;
 						f->httpstate = END_CHUNK;
 						printf("rem. record len = %d\n", f->remaining_record_len);
+	fflush(stdout);
 					}
 					break;
 
 				case END_CHUNK:
 					printf("In END_CHUNK\n");
+	fflush(stdout);
 					needle = strstr((const char *) p, "\r\n");
 					if(needle != NULL){
 						f->httpstate = BEGIN_CHUNK;
@@ -698,6 +984,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						remaining_record_len -= 2;
 					} else {
 						printf("UH OH\n");
+	fflush(stdout);
 						remaining_record_len = 0;
 						f->httpstate = FORFEIT_REST;
 					}
@@ -705,6 +992,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 				case END_BODY:
 					printf("In END_BODY\n");
+	fflush(stdout);
 					needle = strstr((const char *) p, "\r\n");
 					if(needle != NULL){
 						f->httpstate = PARSE_HEADER;
@@ -712,6 +1000,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						remaining_record_len -= 2;
 					} else {
 						printf("UH OH\n");
+	fflush(stdout);
 						remaining_record_len = 0;
 						f->httpstate = FORFEIT_REST;
 					}
@@ -719,6 +1008,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 				case FORFEIT_REST:
 					printf("In FORFEIT_REST\n");
+	fflush(stdout);
 
 				case USE_REST:
 					remaining_record_len = 0;
@@ -760,6 +1050,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 		*/
 		printf("Re-encrypting record\n");
+	fflush(stdout);
 		if((n = encrypt(f, record_ptr, record_ptr,
 						n + EVP_GCM_TLS_EXPLICIT_IV_LEN, 1, record_hdr->type,
 						1)) < 0){
@@ -767,6 +1058,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 			return 0;
 		}
 		printf("Encryption successful!\n");
+	fflush(stdout);
 
 		p = record_ptr + record_len;
 		remaining_packet_len -= record_len;
@@ -1025,15 +1317,19 @@ reencrypt:
 	*/
 	//step 4: recompute TCP checksum
 	if(changed){
-		tcp_checksum(info);
-		printf("Computing checksum\n");
+		uint16_t sum = tcp_checksum(info);
+		printf("Computed checksum: %u\n", sum);
 		fflush(stdout);
 	}
 
+	printf("Done process_downstream\n");
+	fflush(stdout);
 	return 0;
 }
 
 int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
+	printf("Enter filling with ds data\n");
+	fflush(stdout);
 
 	uint8_t *p = data;
 	int32_t remaining = length;
@@ -1048,7 +1344,7 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 //#ifdef DEBUG
 		printf("Censored queue is at %p.\n", first_block);
 		printf("This block has %d bytes left\n", block_length - offset);
-		printf("We need %d bytes\n", remaining);
+		printf("We need %d bytes\n", remaining - SLITHEEN_HEADER_LEN);
 //#endif
 		
 		sl_hdr = (struct slitheen_header *) p;
@@ -1069,15 +1365,26 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 			//use all of the block and free it
 			memcpy(p, first_block->data+offset, block_length - offset);
 
+			printf("Freeing first block data (%p)\n", first_block->data);
+			fflush(stdout);
 			free(first_block->data);
+			printf("Freed first block data\n");
+			fflush(stdout);
 			downstream_queue->first_block = first_block->next;
 			free(first_block);
+			printf("Freed first block\n");
+			fflush(stdout);
 
 			p += (block_length - offset);
 			sl_hdr->len = (block_length - offset);
 			remaining -= (block_length - offset);
 		}
 		sl_hdr->len = htons(sl_hdr->len);
+		printf("DWNSTRM: slitheen header: ");
+		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
+			printf("%02x ",((uint8_t *) sl_hdr)[i]);
+		}
+		printf("\n");
 	}
 	//now, if we need more data, fill with garbage
 	if(remaining > SLITHEEN_HEADER_LEN ){
@@ -1085,11 +1392,18 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		sl_hdr = (struct slitheen_header *) p;
 		sl_hdr->stream_id = 0x00;
 		remaining -= SLITHEEN_HEADER_LEN;
-		sl_hdr->len = remaining;
-		sl_hdr->garbage = remaining;
+		sl_hdr->len = htons(remaining);
+		sl_hdr->garbage = htons(remaining);
+		printf("DWNSTRM: slitheen header: ");
+		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
+			printf("%02x ", p[i]);
+		}
+		printf("\n");
 		p += SLITHEEN_HEADER_LEN;
 		memset(p, 'A', remaining);
 	}
+	printf("Done filling with ds data\n");
+	fflush(stdout);
 	return 0;
 }
 
@@ -1140,8 +1454,10 @@ uint16_t tcp_checksum(struct packet_info *info){
 	if(info->app_data_len %2 != 0){
 		sum += (uint16_t) (p[info->app_data_len - 1]) << 8;
 	}
+
 	//now add most significant to last significant bits
 	sum = (sum >> 16) + (sum & 0xFFFF);
+	sum += sum >>16;
 	//now subtract from 0xFF
 	sum = 0xFFFF - sum;
 

+ 19 - 0
server/relay.h

@@ -7,9 +7,23 @@
 struct proxy_thread_data {
 	flow *f;
 	uint8_t *initial_data;
+	uint16_t initial_len;
+	uint8_t stream_id;
 	int32_t pipefd;
 };
 
+typedef struct stream_st {
+	uint8_t stream_id;
+	int32_t pipefd;
+	struct stream_st *next;
+} stream;
+
+typedef struct stream_table_st {
+	stream *first;
+} stream_table;
+
+extern stream_table *streams;
+
 struct socks_req {
 	uint8_t version;
 	uint8_t cmd;
@@ -17,6 +31,11 @@ struct socks_req {
 	uint8_t addr_type;
 };
 
+struct __attribute__((__packed__)) sl_up_hdr {
+	uint8_t stream_id;
+	uint16_t len;
+};
+
 int replace_packet(flow *f, struct packet_info *info);
 int process_downstream(flow *f, int32_t offset, struct packet_info *info);
 int read_header(flow *f, struct packet_info *info);