Browse Source

cleaned up code: reduced redundancies and function arguments

cbocovic 8 years ago
parent
commit
9c98735413
9 changed files with 364 additions and 419 deletions
  1. 53 73
      server/crypto.c
  2. 12 0
      server/crypto.h
  3. 16 45
      server/flow.c
  4. 10 3
      server/flow.h
  5. 4 1
      server/ptwist168.c
  6. 158 219
      server/relay.c
  7. 4 4
      server/relay.h
  8. 95 74
      server/slitheen-proxy.c
  9. 12 0
      server/slitheen.h

+ 53 - 73
server/crypto.c

@@ -62,15 +62,11 @@ int extract_parameters(flow *f, uint8_t *hs){
 /** MAC a message
  * TODO: look at tls1_mac in t1_enc.c
  * For now, only goes one way (macs message to be written)
- */
+ *
 int32_t mac(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incoming, int32_t type, int32_t enc){
-	uint8_t *seq;
 	uint8_t header[13];
 	int32_t md_size;
 
-	//TODO: update this is I need more than two
-	seq = (incoming) ? f->read_seq : f->write_seq;
-
     header[8] = type;
     header[9] = 0x03;//TODO: update for different versions
     header[10] = 0x03;
@@ -79,11 +75,11 @@ int32_t mac(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 
 	EVP_DigestSignUpdate(f->read_mac_ctx, header, sizeof(header));
 	EVP_DigestSignUpdate(f->read_mac_ctx, input, len);
-	int32_t t = EVP_DigestSignFinal(f->read_mac_ctx, output, &md_size);
+	EVP_DigestSignFinal(f->read_mac_ctx, output, &md_size);
 
 	return md_size;
 
-}
+}*/
 
 /* Encrypt/decrypt message
  *
@@ -108,15 +104,14 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 		}
 	}
 
-//	printf("\t\tiv: ");
-//	for(int i=0; i<ds->cipher->iv_len; i++){
-//		printf("%02X ", ds->iv[i]);
-//	}
-//	printf("\n");
+#ifdef DEBUG
+	printf("\t\tiv: ");
+	for(int i=0; i<ds->cipher->iv_len; i++){
+		printf("%02X ", ds->iv[i]);
+	}
+	printf("\n");
+#endif
 
-	int32_t bs = EVP_CIPHER_block_size(ds->cipher);
-	printf("bs = %d\n", bs);
-	//padding stuff? TODO: understand this
 	uint8_t buf[13];
 	memcpy(buf, seq, 8);
 
@@ -133,45 +128,23 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 	buf[12] = len & 0xff;//len *0xff;
 	int32_t pad = EVP_CIPHER_CTX_ctrl(ds, EVP_CTRL_AEAD_TLS1_AAD,
 			13, buf); // = int32_t pad?
-	printf("buf (%s): ", incoming ? "read" : "write");
-	for(int i=0; i<13; i++){
-		printf("%02x ", buf[i]);
-	}
-	printf("\n");
 
 	if(enc)
 		len += pad;
 
-/*	printf("Decrypting: ");
-	for(int i=0; i<len; i++){
-		printf("%02x ", p[i]);
-	}
-	printf("\n");*/
 	int32_t n = EVP_Cipher(ds, p, p, len); //decrypt in place
 	if(n<0) return 0;
-	printf("%s %d bytes\n", (enc) ? "Encrypted" : "Decrypted", n);
-	printf("seq after (%s): ", incoming ? "read" : "write");
-	for(int i=0; i<8; i++){
-		printf("%02x ", seq[i]);
-	}
-	printf("\n");
-/*	printf("Decrypted: ");
-	for(int i=0; i<n; i++){
-		printf("%02x ", p[i]);
-	}
-	printf("\n");
-	printf("decrypted %d/%d bytes.\n", n, len);*/
+
 	if(!enc)
 		p[EVP_GCM_TLS_EXPLICIT_IV_LEN+n] = '\0';
 
-
 	return n;
 }
 
 int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 	EVP_MD_CTX ctx;
 	uint8_t hash[EVP_MAX_MD_SIZE];
-	int32_t hash_len;
+	uint32_t hash_len;
 
 	EVP_MD_CTX_init(&ctx);
 	
@@ -188,9 +161,9 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 	//now use pseudorandom function
 	uint8_t *output = calloc(1, fin_length);
 	if(incoming){
-		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, (uint8_t *) TLS_MD_SERVER_FINISH_CONST, TLS_MD_SERVER_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
 	} else {
-		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
+		PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE, (uint8_t *) TLS_MD_CLIENT_FINISH_CONST, TLS_MD_CLIENT_FINISH_CONST_SIZE , hash, hash_len, NULL, 0, NULL, 0, output, fin_length);
 	}
 
 	//now compare
@@ -254,7 +227,7 @@ int compute_master_secret(flow *f){
 
 	DH_compute_key(pre_master_secret, dh_srvr->pub_key, dh_clnt);
 	
-	PRF(pre_master_secret, PRE_MASTER_LEN, TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, f->client_random, SSL3_RANDOM_SIZE, f->server_random, SSL3_RANDOM_SIZE, NULL, 0, f->master_secret, SSL3_MASTER_SECRET_SIZE);
+	PRF(pre_master_secret, PRE_MASTER_LEN, (uint8_t *) TLS_MD_MASTER_SECRET_CONST, TLS_MD_MASTER_SECRET_CONST_SIZE, f->client_random, SSL3_RANDOM_SIZE, f->server_random, SSL3_RANDOM_SIZE, NULL, 0, f->master_secret, SSL3_MASTER_SECRET_SIZE);
 
 	//remove pre_master_secret from memory
 	memset(pre_master_secret, 0, PRE_MASTER_LEN);
@@ -370,14 +343,9 @@ int init_ciphers(flow *f){
 	EVP_CIPHER_CTX *r_ctx_srvr;
 	const EVP_CIPHER *c = EVP_aes_256_gcm();
 
-	EVP_MD_CTX *read_mac_ctx;
-	EVP_MD_CTX *write_mac_ctx;
-	EVP_PKEY *read_mac_key;
-	EVP_PKEY *write_mac_key;
-
 	/* Generate Keys */
-	uint8_t *write_mac, *write_key, *write_iv;
-	uint8_t *read_mac, *read_key, *read_iv;
+	uint8_t *write_key, *write_iv;
+	uint8_t *read_key, *read_iv;
 	int32_t mac_len, key_len, iv_len;
 
 	key_len = EVP_CIPHER_key_length(c);
@@ -388,17 +356,19 @@ int init_ciphers(flow *f){
 	uint8_t *key_block = calloc(1, total_len);
 
 	PRF(f->master_secret, SSL3_MASTER_SECRET_SIZE,
-			TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
+			(uint8_t *) TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
 			f->server_random, SSL3_RANDOM_SIZE,
 			f->client_random, SSL3_RANDOM_SIZE,
 			NULL, 0,
 			key_block, total_len);
 
-	/*printf("keyblock:\n");
+#ifdef DEBUG
+	printf("keyblock:\n");
 	for(int i=0; i< total_len; i++){
 		printf("%02x ", key_block[i]);
 	}
-	printf("\n");*/
+	printf("\n");
+#endif
 
 	iv_len = EVP_GCM_TLS_FIXED_IV_LEN;
 	
@@ -406,18 +376,6 @@ int init_ciphers(flow *f){
 	read_key = key_block + key_len;
 	write_iv = key_block + 2*key_len;
 	read_iv = key_block + 2*key_len + iv_len;
-	write_mac = key_block + 2*key_len + 2*iv_len;
-	read_mac = key_block + 2*key_len + 2*iv_len + mac_len;
-
-	/*
-	printf("read_mac: \n");
-	for(int i=0; i< mac_len; i++){
-		printf("%02x ", read_mac[i]);
-	}
-	printf("write_mac: \n");
-	for(int i=0; i< mac_len; i++){
-		printf("%02x ", write_mac[i]);
-	}*/
 
 	/* Initialize Cipher Contexts */
 	r_ctx = EVP_CIPHER_CTX_new();
@@ -429,10 +387,12 @@ int init_ciphers(flow *f){
 	EVP_CIPHER_CTX_init(w_ctx_srvr);
 	EVP_CIPHER_CTX_init(r_ctx_srvr);
 
-	/* Initialize MACs */
+	/* Initialize MACs --- not needed for aes_256_gcm
+	write_mac = key_block + 2*key_len + 2*iv_len;
+	read_mac = key_block + 2*key_len + 2*iv_len + mac_len;
 	read_mac_ctx = EVP_MD_CTX_create();
 	write_mac_ctx = EVP_MD_CTX_create();
-	/*read_mac_key =EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, read_mac, mac_len);
+	read_mac_key =EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, read_mac, mac_len);
 	write_mac_key =EVP_PKEY_new_mac_key(EVP_PKEY_HMAC, NULL, write_mac, mac_len);
 	EVP_DigestSignInit(read_mac_ctx, NULL, EVP_sha384(), NULL, read_mac_key);
 	EVP_DigestSignInit(write_mac_ctx, NULL, EVP_sha384(), NULL, write_mac_key);
@@ -440,7 +400,7 @@ int init_ciphers(flow *f){
 	EVP_PKEY_free(write_mac_key);*/
 
 
-#ifdef KSSL_DEBUG
+#ifdef DEBUG
     {
         int i;
         fprintf(stderr, "EVP_CipherInit_ex(r_ctx,c,key=,iv=,which)\n");
@@ -453,8 +413,8 @@ int init_ciphers(flow *f){
             fprintf(stderr, "%02x", read_iv[i]);
         fprintf(stderr, "\n");
     }
-#endif                           KSSL_DEBUG_
-    {
+    
+	{
         int i;
         fprintf(stderr, "EVP_CipherInit_ex(w_ctx,c,key=,iv=,which)\n");
         fprintf(stderr, "\tkey= ");
@@ -466,8 +426,7 @@ int init_ciphers(flow *f){
             fprintf(stderr, "%02x", write_iv[i]);
         fprintf(stderr, "\n");
     }
-//#endif                           KSSL_DEBUG */
-
+#endif 
 
 	EVP_CipherInit_ex(r_ctx, c, NULL, read_key, NULL, 0);
 	EVP_CipherInit_ex(w_ctx, c, NULL, write_key, NULL, 1);
@@ -482,8 +441,29 @@ int init_ciphers(flow *f){
 	f->clnt_write_ctx = w_ctx;
 	f->srvr_read_ctx = r_ctx_srvr;
 	f->srvr_write_ctx = w_ctx_srvr;
-	f->read_mac_ctx = read_mac_ctx;
-	f->write_mac_ctx = write_mac_ctx;
 
 	return 0;
 }
+
+// To avoid warnings about MAC paddings, use this to update contexts
+void update_context(flow *f, uint8_t *input, int32_t len, int32_t incoming, int32_t type, int32_t enc){
+
+	uint8_t *output = calloc(1, len+16+8);
+	memcpy(output + EVP_GCM_TLS_EXPLICIT_IV_LEN, input, len);
+
+	//If the original message was a decryption, this will be an necryption.
+	//Incoming field stays the same
+	encrypt(f, output, output, len+8, incoming, type, !enc);
+
+	//revert the sequence number
+	uint8_t *seq = incoming ? f->read_seq : f->write_seq;
+	for(int i=7; i>=0; i--){
+		--seq[i];
+		if(seq[i] >= 0)
+			break;
+		else
+			seq[i] = 0;
+	}
+
+	free(output);
+}

+ 12 - 0
server/crypto.h

@@ -10,6 +10,18 @@ int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incom
 void extract_server_random(flow *f, uint8_t *hs);
 int compute_master_secret(flow *f);
 
+int PRF(uint8_t *secret, int32_t secret_len,
+		uint8_t *seed1, int32_t seed1_len,
+		uint8_t *seed2, int32_t seed2_len,
+		uint8_t *seed3, int32_t seed3_len,
+		uint8_t *seed4, int32_t seed4_len,
+		uint8_t *output, int32_t output_len);
+
+int update_finish_hash(flow *f, uint8_t *hs);
+int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming);
+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);
+
 #define PRE_MASTER_LEN 256
 
 #endif /* _CRYPTO_H_ */

+ 16 - 45
server/flow.c

@@ -42,8 +42,7 @@ flow *add_flow(flow newFlow) {
 	newFlow.out_encrypted = 0;
 	newFlow.application = 0;
 	newFlow.packet_chain = NULL;
-	newFlow.censored_queue = calloc(1,2048);
-	newFlow.censored_length = 0;
+	newFlow.censored_queue = NULL;
 	newFlow.outbox_len = 0;
 
 	newFlow.finish_md_ctx = EVP_MD_CTX_create();
@@ -71,22 +70,18 @@ int update_flow(flow *f) {
 	int record_len;
 	int data_len;
 
-	//printf("record version(major): %d.\n", (record_hdr->version&0xFF00)>>8);
-	//printf("record version(minor): %d.\n", record_hdr->version&0xFF);
-	//printf("record length: %d.\n", RECORD_LEN(record_hdr));
-
 	record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
 	data_len = f->packet_chain->data_len;
 	packet *current = f->packet_chain;
 	int incoming = current->incoming;
 	record = calloc(1, record_len);
+	
 	for(int i=0; (i<data_len) && (i<record_len); i++){
 		record[i] = p[i];
 	}
-	//printf("record len: %d, data_len: %d\n", record_len, data_len);
+
 	while(record_len > data_len) {
 		if(current->next == NULL){
-			//printf("Don't have enought to reconstruct record\n");
 			free(record);
 			return 0;
 		}
@@ -103,7 +98,6 @@ int update_flow(flow *f) {
 
 			record[data_len+i] = p[i];
 		}
-		//printf("Filled %d\n", i);
 		data_len += current->data_len;
 	}
 
@@ -112,12 +106,10 @@ int update_flow(flow *f) {
 			p = record;
 			p += RECORD_HEADER_LEN;
 
-			//int size_hs = HANDSHAKE_MESSAGE_LEN(handshake_hdr);
-			printf("Handshake Message:\n");
-
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
-				encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16, 0);
+				int32_t n = encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16, 0);
 				p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
+				update_context(f, p, n, incoming, 0x16, 0);
 				if(incoming) f->in_encrypted = 2;
 				else f->out_encrypted = 2;
 			}
@@ -149,7 +141,7 @@ int update_flow(flow *f) {
 					break;
 				case TLS_SRVR_KEYEX:
 					update_finish_hash(f, p);
-					printf("Received server key exchange!\n");
+					printf("Received server key exchange (seq num= %d!\n", current->seq_num);
 					/* Need to extract server params */
 					if(extract_parameters(f, p)){
 						printf("Error extracting params\n");
@@ -164,7 +156,7 @@ int update_flow(flow *f) {
 					break;
 				case TLS_SRVR_HELLO_DONE:
 					update_finish_hash(f, p);
-					printf("Received server hello done!\n");
+					printf("Received server hello done (seq_num = %d)!\n", current->seq_num);
 					break;
 				case TLS_CERT_VERIFY:
 					update_finish_hash(f, p);
@@ -183,13 +175,10 @@ int update_flow(flow *f) {
 						f->application = 1;
 						if(current->incoming)
 							f->seq_num = current->seq_num + current->len;
-						printf("current sequence number: %d = %d, plus length %d\n", f->seq_num, current->seq_num, current->len);
-						//update sequence number to reflect latest incoming packet
 						while(current->next != NULL){
 							current = current->next;
 							if(current->incoming)
 								f->seq_num = current->seq_num+ current->len;
-							printf("current sequence number: %d, plus length %d\n", current->seq_num, current->len);
 						}
 					}
 					break;
@@ -209,6 +198,7 @@ int update_flow(flow *f) {
 			} else {
 				f->out_encrypted = 1;
 			}
+			
 			/*Initialize ciphers */
 			init_ciphers(f);
 			break;
@@ -242,7 +232,7 @@ int update_flow(flow *f) {
 		f->packet_chain = current->next;
 	} else {
 		/* need to update data */
-		f->packet_chain = current; //TODO: make current
+		f->packet_chain = current;
 		current->data = current->data + (current->data_len - (data_len - record_len));
 		current->data_len = data_len - record_len;
 		update_flow(f);
@@ -326,40 +316,26 @@ flow *get_flow(int index){
 }
 
 /* Adds a packet the flow's packet chain */
-int add_packet(flow *f, uint8_t *p){
-	const struct ip_header *ip_hdr;
-	const struct tcp_header *tcp_hdr;
-
+int add_packet(flow *f, struct packet_info *info){
 	packet *new_packet = malloc(sizeof(packet));
 
-	p += ETHER_HEADER_LEN; //skip ethernet header
-	ip_hdr = (struct ip_header*) p;
-	int size_ip = IP_HEADER_LEN(ip_hdr);
-
-	if (ip_hdr->proto != IPPROTO_TCP){
+	if (info->tcp_hdr == NULL){
 		return 0;
 	}
 
-	p += size_ip;	//skip IP header
-
-	tcp_hdr = (struct tcp_header*) p;
-	int size_tcp = TCP_HEADER_LEN(tcp_hdr);
-	p += size_tcp;
-
-	new_packet->seq_num = htonl(tcp_hdr->sequence_num);
-	new_packet->len = htons(ip_hdr->len) - (size_ip + size_tcp);
-	new_packet->data = p;
-	new_packet->data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
+	new_packet->seq_num = htonl(info->tcp_hdr->sequence_num);
+	new_packet->len = info->app_data_len;
+	new_packet->data = info->app_data;
+	new_packet->data_len = new_packet->len;
 	new_packet->next = NULL;
 	new_packet->incoming = 
-		(ip_hdr->src.s_addr == f->src_ip.s_addr) ? 0 : 1;
+		(info->ip_hdr->src.s_addr == f->src_ip.s_addr) ? 0 : 1;
 
 	/* Find appropriate place in chain */
 	if(new_packet->data_len > 0){
 		packet *previous = NULL;
 		packet *next = f->packet_chain;
 		while(next != NULL && (next->seq_num <= new_packet->seq_num)){
-			//printf("next: %u <= new: %u\n", next->seq_num, new_packet->seq_num);
 			previous = next;
 			next = next->next;
 		}
@@ -373,11 +349,6 @@ int add_packet(flow *f, uint8_t *p){
 			new_packet->next = next;
 			previous->next = new_packet;
 		}
-		/*printf("Flow: %d > %d (%s)\n", ip_hdr->src.s_addr, ip_hdr->dst.s_addr, (new_packet->incoming)? "incoming":"outgoing");
-		printf("ID number: %u\n", htonl(ip_hdr->id));
-		printf("Sequence number: %u\n", htonl(tcp_hdr->sequence_num));
-		printf("Acknowledgement number: %u\n", htonl(tcp_hdr->ack_num));
-		printf("Length: %d\n", new_packet->data_len);*/
 
 	}
 	

+ 10 - 3
server/flow.h

@@ -5,6 +5,7 @@
 #include <openssl/bn.h>
 #include <openssl/ssl.h>
 #include "ptwist.h"
+#include "slitheen.h"
 
 #define MAX_FLOWS 10
 
@@ -29,6 +30,13 @@ struct packet_st{
 	int incoming; //0 for outgoing, 1 for incoming
 };
 
+typedef struct queue_block_st{
+	int32_t len;
+	int32_t offset;
+	uint8_t *data;
+	struct queue_block_st *next;
+} queue_block;
+
 typedef struct packet_st packet;
 
 typedef struct flow_st {
@@ -43,8 +51,7 @@ typedef struct flow_st {
 	int out_encrypted;		/* indicates whether outgoing flow is encrypted */
 	int application; /* indicates handshake is complete */
 	packet *packet_chain; /* currently held data */
-	uint8_t *censored_queue;
-	uint32_t censored_length;
+	queue_block *censored_queue;
 	DH *dh;
 
 	uint8_t handshake_hash[EVP_MAX_MD_SIZE];
@@ -82,6 +89,6 @@ int remove_flow(int index);
 int check_flow(flow observed);
 flow *get_flow(int index);
 
-int add_packet(flow *f, uint8_t *data);
+int add_packet(flow *f, struct packet_info *info);
 
 #endif /* __RELAY_H__ */

+ 4 - 1
server/ptwist168.c

@@ -104,6 +104,7 @@ typedef coord point[3];
 #include <stdio.h>
 #include <stdlib.h>
 
+/*
 static void dump_coord(const char *label, const coord c)
 {
     if (label) fprintf(stderr, "%s: ", label);
@@ -117,6 +118,7 @@ static void dump_point(const char *label, point p)
     dump_coord(" y", p[1]);
     dump_coord(" z", p[2]);
 }
+*/
 
 /* Field element represented as a byte arrary.
  * 21*8 = 168 bits is also the group order size for the elliptic curve.  */
@@ -840,7 +842,7 @@ static void point_add(fslice x3[3], fslice y3[3], fslice z3[3],
 	copy_conditional(zout, z2, 3, z1_is_zero);
 	select_conditional(z3, zout, z1, 3, z2_is_zero);
 	}
-
+/*
 static void affine(point P)
 {
     coord z1, z2, xin, yin;
@@ -857,6 +859,7 @@ static void affine(point P)
     memset(P[2], 0, sizeof(coord));
     P[2][0] = 1;
 }
+*/
 
 static void affine_x(coord out, point P)
 {

+ 158 - 219
server/relay.c

@@ -13,95 +13,71 @@
 #include "crypto.h"
 
 
-int replace_packet(flow *f, uint8_t *packet){
-	const struct ip_header *ip_hdr;
-	const struct tcp_header *tcp_hdr;
+int replace_packet(flow *f, struct packet_info *info){
 
-	uint8_t *p = packet;
-
-	p += ETHER_HEADER_LEN; //skip ethernet header
-	ip_hdr = (struct ip_header*) p;
-	int size_ip = IP_HEADER_LEN(ip_hdr);
-
-	if (ip_hdr->proto != IPPROTO_TCP){
+	if (info->tcp_hdr == NULL){
 		return 0;
 	}
 
-	p += size_ip;	//skip IP header
-
-	tcp_hdr = (struct tcp_header*) p;
-	int size_tcp = TCP_HEADER_LEN(tcp_hdr);
+#ifdef DEBUG
+	fprintf(stderr,"Flow: %d > %d (%s)\n", info->ip_hdr->src.s_addr, info->ip_hdr->dst.s_addr, (info->ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
+	fprintf(stderr,"ID number: %u\n", htonl(info->ip_hdr->id));
+	fprintf(stderr,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
+	fprintf(stderr,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
+#endif
 
-	/*fprintf(stderr,"Flow: %d > %d (%s)\n", ip_hdr->src.s_addr, ip_hdr->dst.s_addr, (ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
-	fprintf(stderr,"ID number: %u\n", htonl(ip_hdr->id));
-	fprintf(stderr,"Sequence number: %u\n", htonl(tcp_hdr->sequence_num));
-	fprintf(stderr,"Acknowledgement number: %u\n", htonl(tcp_hdr->ack_num));*/
-	int32_t app_data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
-	printf("app_data length: %u\n", app_data_len);
-	if(app_data_len <= 0){
+	if(info->app_data_len <= 0){
 		return 0;
 	}
 
 	/* if outgoing, decrypt and look at header */
-	if(ip_hdr->src.s_addr == f->src_ip.s_addr){
-		read_header(f, packet);
+	if(info->ip_hdr->src.s_addr == f->src_ip.s_addr){
+		read_header(f, info);
 		return 0;
 	} else {
+
+#ifdef DEBUG
 		printf("Current sequence number: %d\n", f->seq_num);
 		printf("Received sequence number: %d\n", htonl(tcp_hdr->sequence_num));
-		uint32_t offset = htonl(tcp_hdr->sequence_num) - f->seq_num;
+#endif
+
+		uint32_t offset = htonl(info->tcp_hdr->sequence_num) - f->seq_num;
 		if(offset == 0)
-			f->seq_num += app_data_len;
+			f->seq_num += info->app_data_len;
 		/* if incoming, replace with data from queue */
 		//if(htonl(tcp_hdr->sequence_num) >= f->seq_num){
-			replace_contents(f, p, app_data_len, offset, ip_hdr->src, ip_hdr->dst);
+			replace_contents(f, offset, info);
 		//}//TODO: need to do something about replaying packets (maybe store previously sent data??
 
-		p = packet + ETHER_HEADER_LEN;
-#ifdef DEBUG
-		fprintf(stdout, "ip hdr length: %d\n", htons(ip_hdr->len));
+
+#ifdef DEBUG //TODO: fix
+		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");
-		for(int i=0; i< htons(ip_hdr->len); i++){
+		for(int i=0; i< htons(info->ip_hdr->len); i++){
 			fprintf(stdout, "%02x ", p[i]);
 		}
 		fprintf(stdout, "\n");
 		fflush(stdout);
 #endif
+
 	}
 	return 0;
 
 }
 
-int read_header(flow *f, uint8_t *packet){
-	const struct ip_header *ip_hdr;
-	const struct tcp_header *tcp_hdr;
-
-	uint8_t *p = packet;
-
-	p += ETHER_HEADER_LEN; //skip ethernet header
-	ip_hdr = (struct ip_header*) p;
-	int size_ip = IP_HEADER_LEN(ip_hdr);
+int read_header(flow *f, struct packet_info *info){
+	uint8_t *p = info->app_data;
 
-	if (ip_hdr->proto != IPPROTO_TCP){
+	if (info->tcp_hdr == NULL){
 		return 0;
 	}
 
-	p += size_ip;	//skip IP header
-
-	tcp_hdr = (struct tcp_header*) p;
-	int size_tcp = TCP_HEADER_LEN(tcp_hdr);
-	p += size_tcp;
-	int app_data_len = htons(ip_hdr->len) - (size_ip + size_tcp);
-
 	struct record_header *record_hdr = (struct record_header*) p;
 	uint32_t record_length = RECORD_LEN(record_hdr);
-	uint8_t *decrypted_data = calloc(1, app_data_len);
 
-	/*fprintf(stderr,"record:\n");
-	for(int i=0; i< RECORD_HEADER_LEN; i++){
-		fprintf(stderr,"%02x ", p[i]);
-	}
-	fprintf(stderr,"\n");*/
+	uint8_t *decrypted_data = calloc(1, info->app_data_len);
+
 	p+= RECORD_HEADER_LEN;
 
 	memcpy(decrypted_data, p, record_length);
@@ -109,15 +85,8 @@ int read_header(flow *f, uint8_t *packet){
 	if(!encrypt(f, decrypted_data, decrypted_data, record_length, 0, record_hdr->type, 0)){
 		fprintf(stdout,"decryption failed\n");
 		return 0;
-	} else {
-		fprintf(stdout, "decryption succeeded!\n");
-		if(record_hdr->type == 0x17){
-			decrypted_data+= EVP_GCM_TLS_EXPLICIT_IV_LEN;
-			fprintf(stdout, "request:");
-			fprintf(stdout,"%s\n ", decrypted_data);
-		}
-		
 	}
+
 	if(record_hdr->type == 0x15){
 		printf("received alert\n");
 		for(int i=0; i<record_length; i++){
@@ -128,8 +97,8 @@ int read_header(flow *f, uint8_t *packet){
 
 	/* search through decrypted data for x-ignore */
 	regex_t r;
-	const uint8_t *regex_text = "x-ignore";
-	const uint8_t *match = decrypted_data;
+	const char *regex_text = "x-ignore";
+	const char *match = (char *) decrypted_data;
 	if(regcomp(&r, regex_text, REG_EXTENDED|REG_NEWLINE)){
 		printf("could not compile regex\n");
 		return 0;
@@ -137,7 +106,6 @@ int read_header(flow *f, uint8_t *packet){
 
 	regmatch_t m;
 	if(regexec(&r, match, 1, &m, 0)){
-		printf("no x-ignore found\n");
 		return 0;
 	} 
 	uint8_t *message = decrypted_data;
@@ -157,8 +125,8 @@ int read_header(flow *f, uint8_t *packet){
 	message = decrypted_data;
 
 	regex_t r2;
-	const uint8_t *regex_text2 = "host";
-	const uint8_t *match2 = decrypted_data;
+	const char *regex_text2 = "host";
+	const char *match2 = (char *) decrypted_data;
 	regmatch_t m2;
 	if(regcomp(&r2, regex_text2, REG_EXTENDED|REG_NEWLINE)){
 		printf("could not compile regex\n");
@@ -194,65 +162,86 @@ int read_header(flow *f, uint8_t *packet){
 		printf("error: constructing socket failed\n");
 		return 0;
 	}
-	printf("constructed socket\n");
+	
 	struct sockaddr_in dest;
 	dest.sin_family = AF_INET;
 	dest.sin_port = htons(80);
 	dest.sin_addr = *((struct in_addr *) host->h_addr);
 	bzero (&(dest.sin_zero), 8);
-	printf("connecting...");
+	
 	int32_t error = connect (handle, (struct sockaddr *) &dest, sizeof (struct sockaddr));
-	printf(" done\n");
+	
 	if(error <0){
 		printf("error connecting\n");
 		return 0;
 	}
-	int32_t bytes_sent = send(handle, message, strlen(message), 0);
+	int32_t bytes_sent = send(handle, message, strlen((const char *) message), 0);
 	if( bytes_sent < 0){
 		printf("error sending request\n");
 		close(handle);
 		return 0;
-	} else if (bytes_sent < strlen(message)){
-		printf("send partial request\n");
+	} else if (bytes_sent < strlen((const char *) message)){
 		close(handle);
 		return 0;
 	}
 
-	printf("sent request!\n");
-	//change this to realloc and loop later
-	uint8_t *buf = calloc(1, 2048);
-	memset(buf, 0, 2048);
-	int32_t bytes_read = recv(handle, buf, 2048, 0);
-	printf("Received message:\n %s\n", buf);
-	for(int i=0; i< bytes_read; i++){
-		f->censored_queue[i] = buf[i];
+	
+	int32_t bytes_read;
+	for(int i=0; i<3; i++){
+		uint8_t *buf = calloc(1, BUFSIZ);
+		bytes_read = recv(handle, buf, BUFSIZ, 0);
+		if(bytes_read <= 0) break;
+
+		//make a new queue block
+		queue_block *new_block = calloc(1, sizeof(queue_block));
+		new_block->len = bytes_read;
+		new_block->offset = 0;
+		new_block->data = buf;
+		new_block->next = NULL;
+		if(f->censored_queue == NULL)
+			f->censored_queue = new_block;
+		else{
+			queue_block *last = f->censored_queue;
+			while(last->next != NULL)
+				last = last->next;
+			last->next = new_block;
+		}
 	}
-	f->censored_length = bytes_read;
 
-	//for now, just close socket
 	close(handle);
 
 	return 0;
 
 }
 
-int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, struct in_addr src, struct in_addr dst){
-
-	printf("Replacing contents...\n");
-	uint8_t *p = data;
+/** Replaces downstream record contents with data from the
+ *  censored queue, padding with garbage bytes if no more
+ *  censored data exists.
+ *
+ *  Inputs: 
+ *  	f: the tagged flow
+ *  	data: a pointer to the received packet's application
+ *  		data
+ *  	data_len: the length of the	packet's application data
+ *  	offset: if the packet is misordered, the number of
+ *  		application-level bytes in missing packets
+ *
+ *  Output:
+ *  	Returns 0 on sucess 
+ */
+int replace_contents(flow *f, int32_t offset, struct packet_info *info){
 
-	struct tcp_header *tcp_hdr = (struct tcp_header*) p;
-	int size_tcp = TCP_HEADER_LEN(tcp_hdr);
-	p += size_tcp;
+	uint8_t *p = info->app_data;
 
-	int32_t tmp_len = data_len;
+	int32_t tmp_len = info->app_data_len;
 
 	//step 1: replace record contents
 	//note: encrypted message will be original message size + EVP_GCM_TLS_EXPLICIT_IV_LEN + 16 byte pad
 	//first check to see if there's anything in the outbox
 	if(f->outbox_len > 0){
-		printf("Printing from outbox\n");
-		if(f->outbox_len < data_len){
+
+#ifdef DEBUG
+		if(f->outbox_len < info->app_data_len){
 			printf("Next record:\n");
 			for(int i=0; i< RECORD_HEADER_LEN; i++){
 				printf("%02x ", p[f->outbox_len+i]);
@@ -261,6 +250,7 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
 		} else {
 			printf("Outbox takes up entire packet\n");
 		}
+#endif
 
 		if(tmp_len >= f->outbox_len){
 			memcpy(p, f->outbox, f->outbox_len);
@@ -269,16 +259,13 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
 			tmp_len -= f->outbox_len;
 			f->outbox_len = 0;
 			free(f->outbox);
-			printf("outbox now empty\n");
 		} else {
-			printf("Outbox has %d - %d bytes\n", f->outbox_len, tmp_len);
 			memcpy(p, f->outbox, tmp_len);
 			uint8_t *tmp = calloc(1, f->outbox_len - tmp_len);
 			f->outbox_len -= tmp_len;
 			memcpy(tmp, f->outbox + tmp_len, f->outbox_len);
 			free(f->outbox);
 			f->outbox = tmp;
-			printf(" = %d bytes left in outbox\n", f->outbox_len);
 			tmp_len -= tmp_len;
 		}
 	}
@@ -287,11 +274,14 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
 
 		struct record_header *record_hdr = (struct record_header*) p;
 		uint32_t record_length = RECORD_LEN(record_hdr);
+
+#ifdef DEBUG
 		fprintf(stdout, "Record:\n");
 		for(int i=0; i< RECORD_HEADER_LEN; i++){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
+#endif
 
 		p += RECORD_HEADER_LEN;
 		if(record_hdr->type != 0x17){
@@ -306,128 +296,72 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
 		memcpy(new_record, p, record_length);
 		uint8_t *tmp_p = new_record;
 
-
-		/*// BEGIN TEST CODE //
-
-		//Print original record
-		printf("Original record (%d bytes):\n", record_length);
-		for(int i=0; i< record_length; i++){
-			printf("%02x ", p[i]);
-		}
-		printf("\n");
-
-		//print few bytes of next record (if present)
-		if(data_len > record_length + RECORD_HEADER_LEN){
-			printf("Next record:\n");
-			for(int i=0; i< RECORD_HEADER_LEN; i++){
-				printf("%02x ", p[record_length+i]);
-			}
-			printf("\n");
-		} else {
-			printf("No extra record: %d = %d + %d\n", data_len, record_length, RECORD_HEADER_LEN);
-		}
-
-
-		//Decrypt record
-		printf("Decrypting record... ");
-		int n;
-		if(!(n = encrypt(f, p, p, record_length, 1, 0x17, 0))){
-			fprintf(stderr,"failed\n");
-			return 0;
-		} else {
-			fprintf(stderr, "succeeded!\n");
-			printf("Decrypted record:\n");
-			for(int i=0; i< record_length; i++){
-				printf("%02x ", p[i]);
-			}
-			printf("\n");
-			printf("%s\n", p+ EVP_GCM_TLS_EXPLICIT_IV_LEN);
-		}
-
-		//return seq to what it was
-		for(int i=7; i>=0; i--){
-			--f->read_seq[i];
-			if(f->read_seq[i] >= 0)
-				break;
-			else
-				f->read_seq[i] = 0;
-		}
-		printf("seq reverted (%s): ", "read");
-		for(int i=0; i<8; i++){
-			printf("%02x ", f->read_seq[i]);
-		}
-		printf("\n");
-
-		//Now reposition it to be fed into encrypt function
-		//memcpy(p, p+ EVP_GCM_TLS_EXPLICIT_IV_LEN, n);
-
-		// END TEST CODE */
-
-		//step 2: figure out what happens if we don't have data
 		tmp_p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 		
 		struct slitheen_header *sl_hdr = (struct slitheen_header *) tmp_p;
 		sl_hdr->marker = 0x01;
 		sl_hdr->version = 0x01;
+		sl_hdr->len = 0x00;
 		int32_t remaining = record_length - (SLITHEEN_HEADER_LEN
 				+ EVP_GCM_TLS_EXPLICIT_IV_LEN + 16);
-		fprintf(stdout, "filling with censored queue data (%d out of %d) at offset %d\n", remaining, f->censored_length-offset, offset);
-		if(remaining > 0){
-			if(remaining+offset <= f->censored_length){
-				fprintf(stdout, "We have enough data to fill the record\n");
-				for(int i = 0; i< remaining; i++){
-					tmp_p[SLITHEEN_HEADER_LEN+i] = f->censored_queue[i + offset];
-				}
-				//TODO: when I restructure this for more data, figure out freeing these pointers
-				f->censored_queue += remaining;
-				f->censored_length -= remaining;
-				sl_hdr->len = htons(remaining);
-				fprintf(stdout, "copied %d data\n", ntohs(sl_hdr->len));
+		tmp_p += SLITHEEN_HEADER_LEN;
+		//Fill as much as we can from the censored_queue
+		while((remaining > 0) && f->censored_queue != NULL){
+			int32_t block_length = f->censored_queue->len;
+			int32_t offset = f->censored_queue->offset;
 
+#ifdef DEBUG
+			printf("Censored queue is at %p.\n", f->censored_queue);
+			printf("This block as %d bytes left\n", block_length - offset);
+			printf("We need %d bytes\n", remaining);
+#endif
+			
+			if(block_length > offset + remaining){
+				//use part of the block, update offset
+				memcpy(tmp_p, f->censored_queue->data+offset, remaining);
+				f->censored_queue->offset += remaining;
+				tmp_p += remaining;
+				sl_hdr->len += remaining;
+				remaining -= remaining;
 			} else {
-				int32_t dummy_offset = f->censored_length - offset;
-				if(dummy_offset < 0) dummy_offset = 0;
-				fprintf(stdout, "Not enough data (%d bytes)\n", dummy_offset);
-				for(int i = 0; i< dummy_offset; i++){
-					tmp_p[SLITHEEN_HEADER_LEN+i] = f->censored_queue[i + offset];
-				}
-				//TODO: note, we may also be receiving misordered packets. Take Ian's suggestion into account here
-				f->censored_queue += dummy_offset;
-				f->censored_length -= dummy_offset;
-				sl_hdr->len = htons(dummy_offset);
-				//TODO: should i < record_length or remaining??
-				for(int i = dummy_offset; i< remaining; i++){
-					tmp_p[SLITHEEN_HEADER_LEN+i] = 'A';
-				}
-				fprintf(stdout, "copied %d data and %d garbage bytes\n", ntohs(sl_hdr->len), remaining - dummy_offset);
+				//use all of the block and free it
+				memcpy(tmp_p, f->censored_queue->data+offset, block_length - offset);
+
+				free(f->censored_queue->data);
+				f->censored_queue = f->censored_queue->next;
+
+				tmp_p += (block_length - offset);
+				sl_hdr->len += (block_length - offset);
+				remaining -= (block_length - offset);
 			}
-			printf("Slitheen header\n");
-			for(int i=0; i<4; i++)
-				printf("%02x ", tmp_p[i]);
-			printf("\n");
 		}
-		tmp_p -= EVP_GCM_TLS_EXPLICIT_IV_LEN;
+		sl_hdr->len = htons(sl_hdr->len);
+		//now, if we need more data, fill with garbage
+		if(remaining >0 ){
+			//TODO: note, we may also be receiving misordered packets. Take Ian's suggestion into account here
+			memset(tmp_p, 'A', remaining);
+		}
+
+		tmp_p = new_record;
+
+#ifdef DEBUG
+		fprintf(stdout, "copied %d data and %d garbage bytes\n", ntohs(sl_hdr->len), remaining);
+		printf("Slitheen header\n");
+		for(int i=0; i<4; i++)
+			printf("%02x ", tmp_p[EVP_GCM_TLS_EXPLICIT_IV_LEN+i]);
+		printf("\n");
+#endif
+
 		//step 3: encrypt new record
-		//fprintf(stderr, "computing mac\n");
-		//int32_t mac_size = mac(f, p, p+(record_length - (EVP_GCM_TLS_EXPLICIT_IV_LEN + 16)), record_length - (EVP_GCM_TLS_EXPLICIT_IV_LEN + 16), 1, 0x17, 1); 
-		//printf(stderr, "mac size: %d\n", mac_size);
-		//fprintf(stderr, "encrypting\n");
 		int32_t success;
 		if((success = encrypt(f, tmp_p, tmp_p, record_length-16, 1, 0x17, 1))< 0){
 			fprintf(stdout,"encryption failed\n");
 			return 0;
-		} else {
-			fprintf(stdout, "encryption succeeded!\n");
-			//printf("Encrypted data:\n");
-			//for(int i=0; i< success; i++){
-			//	printf("%02x ", tmp_p[i]);
-			//}
-			//printf("\n");
 		}
+
 		//copy new record into packet
 		if(record_length +RECORD_HEADER_LEN > tmp_len){
 			//We have a partial record
-			printf("Warning: partial record\n");
 			memcpy(p, new_record, tmp_len - RECORD_HEADER_LEN);
 			f->outbox_len = record_length - (tmp_len - RECORD_HEADER_LEN);
 			//save left-overs in outbox
@@ -435,15 +369,14 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
 			memcpy(f->outbox, new_record + (tmp_len - RECORD_HEADER_LEN),
 					f->outbox_len);
 			free(new_record);
-			printf("Outbox has %d = %d - %d bytes\n", f->outbox_len, record_length+RECORD_HEADER_LEN, tmp_len);
 		} else {
 			memcpy(p, new_record, record_length);
 			free(new_record);
 		}
 
-
+#ifdef DEBUG
 		//check to see if next record still exists
-		if(data_len > record_length + RECORD_HEADER_LEN){
+		if(info->app_data_len > record_length + RECORD_HEADER_LEN){
 			printf("Next record:\n");
 			for(int i=0; i< RECORD_HEADER_LEN; i++){
 				printf("%02x ", p[record_length+i]);
@@ -452,18 +385,14 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
 		} else {
 			printf("No extra record: %d <= %d + %d\n", data_len, record_length, RECORD_HEADER_LEN);
 		}
+#endif
+
 		tmp_len -= record_length+ RECORD_HEADER_LEN;
 		p += record_length;
 
 	}
 	//step 4: recompute TCP checksum
-	p = data;
-	p[16] = 0; p[17] = 0;//zero out checksum
-	uint16_t chksm = tcp_checksum(p, data_len, src, dst);
-	p[17] = chksm & 0xFF;
-	p[16] = chksm >> 8;
-	fprintf(stdout, "Checksum: 0x%0x%0x\n", p[16], p[17]);
-	fflush(stdout);
+	tcp_checksum(info);
 
 	return 0;
 }
@@ -483,16 +412,17 @@ int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, s
  *         |  zero  |  PTCL  |    TCP Length   |
  *         +--------+--------+--------+--------+
  */
-uint16_t tcp_checksum(uint8_t *data, int32_t data_len, struct in_addr src, struct in_addr dst){
+uint16_t tcp_checksum(struct packet_info *info){
 
-	uint8_t *p = data;
-
-	struct tcp_header *tcp_hdr = (struct tcp_header*) p;
-	int size_tcp = TCP_HEADER_LEN(tcp_hdr);
-	//Construct pseudo-header
-	uint16_t tcp_length = data_len + size_tcp;
+	uint16_t tcp_length = info->app_data_len + info->size_tcp_hdr;
+	struct in_addr src = info->ip_hdr->src;
+	struct in_addr dst = info->ip_hdr->dst;
 	uint8_t proto = IPPROTO_TCP;
-	fprintf(stdout, "summing pseudoheader\n");
+
+	//set the checksum to zero
+	info->tcp_hdr->chksum = 0;
+	
+	//sum pseudoheader
 	uint32_t sum = (ntohl(src.s_addr)) >> 16;
 	sum += (ntohl(src.s_addr)) &0xFFFF;
 	sum += (ntohl(dst.s_addr)) >> 16;
@@ -500,17 +430,26 @@ uint16_t tcp_checksum(uint8_t *data, int32_t data_len, struct in_addr src, struc
 	sum += proto;
 	sum += tcp_length;
 
-	//now sum the text
-	for(int i=0; i< tcp_length-1; i+=2){
+	//sum tcp header (with zero-d checksum)
+	uint8_t *p = (uint8_t *) info->tcp_hdr;
+	for(int i=0; i < info->size_tcp_hdr; i+=2){
 		sum += (uint16_t) ((p[i] << 8) + p[i+1]);
+	}
 
+	//now sum the application data
+	p = info->app_data;
+	for(int i=0; i< info->app_data_len-1; i+=2){
+		sum += (uint16_t) ((p[i] << 8) + p[i+1]);
 	}
-	if(tcp_length %2 != 0){
-		sum += (uint16_t) (p[tcp_length - 1]) << 8;
+	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);
 	//now subtract from 0xFF
 	sum = 0xFFFF - sum;
+
+	//set chksum to calculated value
+	info->tcp_hdr->chksum = ntohs(sum);
 	return (uint16_t) sum;
 }

+ 4 - 4
server/relay.h

@@ -4,9 +4,9 @@
 #include "flow.h"
 #include <stdint.h>
 
-int replace_packet(flow *f, uint8_t *packet);
-int replace_contents(flow *f, uint8_t *data, int32_t data_len, int32_t offset, struct in_addr src, struct in_addr dst);
-int read_header(flow *f, uint8_t *packet);
-uint16_t tcp_checksum(uint8_t *data, int32_t data_len, struct in_addr src, struct in_addr dst);
+int replace_packet(flow *f, struct packet_info *info);
+int replace_contents(flow *f, int32_t offset, struct packet_info *info);
+int read_header(flow *f, struct packet_info *info);
+uint16_t tcp_checksum(struct packet_info *info);
 
 #endif /* _RELAY_H_ */

+ 95 - 74
server/slitheen-proxy.c

@@ -12,9 +12,10 @@
 #include "relay.h"
 
 void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet);
-void check_handshake(const struct tcp_header *tcp_hdr, flow f, unsigned char *p, u_short length);
+void check_handshake(struct packet_info *info, flow f);
 void *sniff_packets(void *);
-void process_packet(const u_char *packet);
+void process_packet(uint8_t *packet, struct packet_info *info);
+void extract_packet_headers(const uint8_t *packet, struct packet_info *info);
 
 /** Checks a handshake message to see if it is tagged or a
  *  recognized flow.
@@ -22,23 +23,20 @@ void process_packet(const u_char *packet);
  *  a pointer to the handshake header, and the length of
  *  the record.
  */
-void check_handshake(const struct tcp_header *tcp_hdr, flow f, unsigned char *ptr, u_short length){
+void check_handshake(struct packet_info *info, flow f){
 
 	FILE *fp;
 	int res, i, code;
-	//u_int size_hs;
-	unsigned char *p;
-	unsigned char *hello_rand;
+	uint8_t *hello_rand;
 	const struct handshake_header *handshake_hdr;
 
     byte privkey[PTWIST_BYTES];
 	byte key[16];
 
-	p = ptr;
+	uint8_t *p = info->app_data + RECORD_HEADER_LEN;
 	handshake_hdr = (struct handshake_header*) p;
 
 	code = handshake_hdr->type;
-	//size_hs = HANDSHAKE_MESSAGE_LEN(handshake_hdr);
 
 	if (code == 0x01){
 		p += CLIENT_HELLO_HEADER_LEN;
@@ -91,11 +89,6 @@ void check_handshake(const struct tcp_header *tcp_hdr, flow f, unsigned char *pt
 				flow_ptr->key[i] = key[i];
 			}
 
-			/*printf("KEY \n");
-			for(int i=0; i< 16; i++){
-				printf("%02x ", flow_ptr->key[i]);
-			}
-			printf("\n");*/
 			memcpy(flow_ptr->client_random, hello_rand, SSL3_RANDOM_SIZE);
 			
 			printf("Saved new flow\n");
@@ -107,48 +100,41 @@ void check_handshake(const struct tcp_header *tcp_hdr, flow f, unsigned char *pt
 
 void got_packet(u_char *args, const struct pcap_pkthdr *header, const u_char *packet){
 	pcap_t *handle = (pcap_t *) args;
-	unsigned char *p;
 
-	const struct ip_header *ip_hdr;
-	//const struct tcp_header *tcp_hdr;
-	p = (unsigned char *) packet;
-	p += ETHER_HEADER_LEN; //skip ethernet header
-	ip_hdr = (struct ip_header*) p;
-	p += IP_HEADER_LEN(ip_hdr);//TODO: remove
-	//tcp_hdr = (struct tcp_header*) p;//TODO: remove
+	//might modify packet, copy to new pointer
+	//uint8_t *modified_packet = calloc(1, header->len);
+	//memcpy(modified_packet, packet, header->len);
+
+	struct packet_info *info = calloc(1, sizeof(struct packet_info));
+	extract_packet_headers(packet, info);
 
 	// Check to make sure it is an IP packet 
-	if( (ip_hdr->versionihl >>4) != 4)
+	if(info->ip_hdr == NULL)
 		goto end;
 
-	// Packet may be split over multiple frames. In this case,
+	/* Packet may be split over multiple frames. In this case,
 	 // reconstruct the packet before trying to read TLS records
-	 //
-	if((htons(ip_hdr->flagsoff)&MF) || (htons(ip_hdr->flagsoff) &0x1fff) ){ /* this is a fragment */
-		printf("MF: %d, OFF: %d.\n", htons(ip_hdr->flagsoff)&MF, htons(ip_hdr->flagsoff)&0x1fff);
+	if((htons(info->ip_hdr->flagsoff)&MF) || (htons(info->ip_hdr->flagsoff) &0x1fff) ){ // this is a fragment 
+		printf("MF: %d, OFF: %d.\n", htons(info->ip_hdr->flagsoff)&MF, htons(info->ip_hdr->flagsoff)&0x1fff);
 		printf("Received packet fragment.\n");
-		printf("%d packet bytes: \n", IP_HEADER_LEN(ip_hdr));
-		for(int i=0; i< IP_HEADER_LEN(ip_hdr); i++){
-			printf("%02x ", p[i]);
-		}
-		printf("\n");
 		u_char *complete_packet;
 		//save packet fragment
 		complete_packet = malloc(65535);
 
 		int success = report_fragment(p, complete_packet, header->len);
 		if(success){
-			process_packet(complete_packet);
+			process_packet(complete_packet, info);
 		}
-		/* TODO: handle errors */
+		// TODO: handle errors 
 		
-	} else { /*not a fragment, add to packet chain */
-		process_packet(packet);
-	}
+	} else { //not a fragment, add to packet chain */
+	process_packet(packet, info);
+
 end:
 	if((pcap_inject(handle, packet, header->len)) < 0 ){
 		fprintf(stderr, "Error: %s\n", pcap_geterr(handle));
 	}
+	free(info);//Note: don't free this while a thread is using it
 #ifdef DEBUG
 	fprintf(stderr, "injected the following packet:\n");
 	for(int i=0; i< header->len; i++){
@@ -156,6 +142,8 @@ end:
 	}
 	fprintf(stderr, "\n");
 #endif
+
+	//free(modified_packet);
 }
 
 void usage(void){
@@ -258,45 +246,25 @@ void *sniff_packets(void *args){
 /* This function receives a full ip packet and then:
  * 	1) identifies the flow
  * 	2) adds the packet to the flow's data chain
- * 	3) updates the packet's state
+ * 	3) updates the flow's state
  */
-void process_packet(const u_char *packet){
-	unsigned char *p;
+void process_packet(uint8_t *packet, struct packet_info *info){
 	int index;
 
-	const struct ip_header *ip_hdr;
-	const struct tcp_header *tcp_hdr;
-	const struct record_header *record_hdr;
-
-	u_int size_ip;
-	u_int size_tcp;
-
 	flow newFlow;
 
-	p = (unsigned char *) packet;
-	p += ETHER_HEADER_LEN; //skip ethernet header
-	ip_hdr = (struct ip_header*) p;
-	size_ip = IP_HEADER_LEN(ip_hdr);
-
-	if (ip_hdr->proto == IPPROTO_TCP){
-		p += size_ip;	//skip IP header
-
-		tcp_hdr = (struct tcp_header*) p;
-		size_tcp = TCP_HEADER_LEN(tcp_hdr);
-		p += size_tcp;
+	if (info->tcp_hdr != NULL){
 
-		newFlow.src_ip = ip_hdr->src;
-		newFlow.dst_ip = ip_hdr->dst;
-		newFlow.src_port = tcp_hdr->src_port;
-		newFlow.dst_port = tcp_hdr->dst_port;
+		newFlow.src_ip = info->ip_hdr->src;
+		newFlow.dst_ip = info->ip_hdr->dst;
+		newFlow.src_port = info->tcp_hdr->src_port;
+		newFlow.dst_port = info->tcp_hdr->dst_port;
 
-		newFlow.seq_num = tcp_hdr->sequence_num;
-		record_hdr = (struct record_header*) p;
+		newFlow.seq_num = info->tcp_hdr->sequence_num;
 
 		/* Checks to see if this is a possibly tagged hello msg */
-		if (record_hdr->type == HS){ /* This is a TLS handshake */
-			p += RECORD_HEADER_LEN;
-			check_handshake(tcp_hdr, newFlow, p, RECORD_LEN(record_hdr));
+		if ((info->record_hdr != NULL) && (info->record_hdr->type == HS)){ /* This is a TLS handshake */
+			check_handshake(info, newFlow);
 		}
 	}
 
@@ -305,26 +273,21 @@ void process_packet(const u_char *packet){
 		flow *observed = get_flow(index-1);
 	
 		if(observed->application){
-			replace_packet(observed, packet);
+			replace_packet(observed, info);
 		} else {
 
 			/* Pass data to packet chain */
-			add_packet(observed, packet);
+			add_packet(observed, info);
 
 			/* Update flow state */
 			if(observed->packet_chain != NULL){
-				//fork off a thread to update the flow
-				//pid_t pid = fork();
-				//if(pid == 0){//child
 					update_flow(observed);
-				//	exit(0);
-				//}
 
 			}
 		}
 
 		/* Update TCP state */
-		if(tcp_hdr->flags & (FIN | RST) ){
+		if(info->tcp_hdr->flags & (FIN | RST) ){
 			/* Remove flow from table, connection ended */
 			remove_flow(index);
 		}
@@ -332,3 +295,61 @@ void process_packet(const u_char *packet){
 	}
 
 }
+
+/** This function extracts the ip, tcp, and tls record headers
+ * 	from a received packet (if they exist), and put them in 
+ * 	a packet_info struct
+ * 	
+ */
+void extract_packet_headers(const uint8_t *packet, struct packet_info *info){
+
+	/* First fill in IP header */
+	const uint8_t *p = packet;
+	p += ETHER_HEADER_LEN; //skip ethernet header
+	info->ip_hdr = (struct ip_header*) p;
+	info->size_ip_hdr = IP_HEADER_LEN(info->ip_hdr);
+	
+	/* Verify this is an IP packet */
+	if( (info->ip_hdr->versionihl >>4) != 4){
+		info->ip_hdr = NULL;
+		info->size_ip_hdr = 0;
+		info->tcp_hdr = NULL;
+		info->size_tcp_hdr = 0;
+		info->record_hdr = NULL;
+		return;
+	}
+
+	/* If this is a TCP segment, fill in TCP header */
+	if (info->ip_hdr->proto == IPPROTO_TCP){
+		p += info->size_ip_hdr;	//skip IP header
+
+		info->tcp_hdr = (struct tcp_header*) p;
+		info->size_tcp_hdr = TCP_HEADER_LEN(info->tcp_hdr);
+		p += info->size_tcp_hdr;
+	} else {
+		info->tcp_hdr = NULL;
+		info->size_tcp_hdr = 0;
+		info->record_hdr = NULL;
+		return;
+	}
+
+
+	/* If the application data contains a TLS record, fill in hdr */
+	info->app_data_len = htons(info->ip_hdr->len) - (info->size_ip_hdr + info->size_tcp_hdr);
+	if(info->app_data_len > 0){
+		info->app_data = p;
+		info->record_hdr = (struct tls_header*) p;
+		
+		//check to see if this is a valid record
+		if((info->record_hdr->type < 0x14) || (info->record_hdr->type > 0x18)){
+			info->record_hdr = NULL;
+		}
+
+	} else {
+		info->record_hdr = NULL;
+		info->app_data = NULL;
+	}
+
+	return;
+
+}

+ 12 - 0
server/slitheen.h

@@ -57,6 +57,18 @@ struct tls_header {
 #define RECORD_HEADER_LEN 5
 #define CLIENT_HELLO_HEADER_LEN 6
 
+struct packet_info {
+	const struct ip_header *ip_hdr;
+	struct tcp_header *tcp_hdr;
+	const struct tls_header *record_hdr;
+
+	uint32_t size_tcp_hdr;
+	uint32_t size_ip_hdr;
+
+	uint8_t *app_data;
+	uint32_t app_data_len;
+};
+
 struct slitheen_header {
 	u_char marker; /* 0x01 means censored data, 0x02 means dummy data */
 	u_char version; /* For now 0x01 */