瀏覽代碼

checked returns, added comments cleaned up code

cecylia 7 年之前
父節點
當前提交
7e9c313fdc
共有 8 個文件被更改,包括 345 次插入324 次删除
  1. 3 3
      server/Makefile
  2. 67 71
      server/crypto.c
  3. 1 1
      server/crypto.h
  4. 175 39
      server/flow.c
  5. 51 35
      server/relay.c
  6. 26 8
      server/slitheen-proxy.c
  7. 14 142
      server/util.c
  8. 8 25
      server/util.h

+ 3 - 3
server/Makefile

@@ -4,12 +4,12 @@ TARGETS=slitheen-proxy
 
 all: $(TARGETS)
 
-slitheen-proxy.o flow.o rserv.o ptwist168.o util.o crypto.o relay.o cryptothread.o :: ptwist.h rserv.h flow.h slitheen.h util.h crypto.h relay.h cryptothread.h
+slitheen-proxy.o flow.o rserv.o ptwist168.o crypto.o relay.o cryptothread.o util.o:: ptwist.h rserv.h flow.h slitheen.h crypto.h relay.h cryptothread.h util.h
 
 rserv: rserv.o ptwist168.o
 	gcc -g -ggdb -o $@ $^ -lssl -lcrypto
 
-slitheen-proxy: slitheen-proxy.o flow.o rserv.o ptwist168.o crypto.o relay.o cryptothread.o relay.h crypto.h ptwist.h rserv.h flow.h slitheen.h cryptothread.h
+slitheen-proxy: slitheen-proxy.o flow.o rserv.o ptwist168.o crypto.o relay.o cryptothread.o util.o relay.h crypto.h ptwist.h rserv.h flow.h slitheen.h cryptothread.h
 	gcc -g -ggdb -o $@ $^ -I/home/slitheen/Documents/include/openssl libssl.a libcrypto.a -lpcap -lpthread -ldl
 
 clean:
@@ -18,7 +18,7 @@ clean:
 veryclean: clean
 	-rm $(TARGETS)
 
-#DEPS=ptwist.h rserv.h flow.h slitheen.h util.h
+#DEPS=ptwist.h rserv.h flow.h slitheen.h 
 #
 #%.o: %.c $(DEPS)
 #	gcc -g -Wall -std=c99 -c -o $@ $<

+ 67 - 71
server/crypto.c

@@ -1,13 +1,18 @@
+/* crypto.c by Cecylia Bocovich <cbocovic@uwaterloo.ca> based on:*/
+/*TODO: openssl attribution */
+
 #include <openssl/evp.h>
 #include <openssl/dh.h>
 #include <openssl/bn.h>
 #include <openssl/err.h>
 #include <openssl/rand.h>
 #include <openssl/ssl.h>
+
 #include "rserv.h"
 #include "crypto.h"
 #include "flow.h"
 #include "slitheen.h"
+#include "util.h"
 
 #define NID_sect163k1           721
 #define NID_sect163r1           722
@@ -154,15 +159,11 @@ int extract_parameters(flow *f, uint8_t *hs){
 
 		if((ecdh = EC_KEY_new()) == NULL) {
 			SSLerr(SSL_F_SSL3_GET_KEY_EXCHANGE, ERR_R_MALLOC_FAILURE);
-			printf("HERE1\n");
-			fflush(stdout);
 			goto err;
 		}
 
 
 		if(p[0] != 0x03){//not a named curve
-			printf("HERE2\n");
-			fflush(stdout);
 			goto err;
 		}
 
@@ -170,8 +171,6 @@ int extract_parameters(flow *f, uint8_t *hs){
 		int curve_id = *(p+2);
 		if((curve_id < 0) || ((unsigned int)curve_id >
 						            sizeof(nid_list) / sizeof(nid_list[0]))){
-			printf("HERE3\n");
-			fflush(stdout);
 			goto err;
 		}
 			
@@ -193,39 +192,28 @@ int extract_parameters(flow *f, uint8_t *hs){
 		ngroup = EC_GROUP_new_by_curve_name(curve_nid);
 
 		if(ngroup == NULL){
-			printf("HERE4\n");
-			fflush(stdout);
 			goto err;
 		}
 		if(EC_KEY_set_group(ecdh, ngroup) == 0){
-			printf("HERE5\n");
-			fflush(stdout);
 			goto err;
 		}
 		EC_GROUP_free(ngroup);
 
 		group = EC_KEY_get0_group(ecdh);
-		printf("Curve name is %d\n", EC_GROUP_get_curve_name(group));
 
 		p += 3;
 
 		/* Get EC point */
 		if (((srvr_ecpoint = EC_POINT_new(group)) == NULL) || 
 				((bn_ctx = BN_CTX_new()) == NULL)) {
-			printf("HERE6\n");
-			fflush(stdout);
 			goto err;
 		}
 
 		encoded_pt_len = *p;
 		p += 1;
 
-		printf("point len: %d, message len: %x %x %x\n",encoded_pt_len, hs[1], hs[2], hs[3]);
-
 		if(EC_POINT_oct2point(group, srvr_ecpoint, p, encoded_pt_len, 
 					bn_ctx) == 0){
-			printf("HERE7\n");
-			fflush(stdout);
 			goto err;
 		}
 
@@ -256,28 +244,6 @@ err:
 	return ok;
 }
 
-/** 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 header[13];
-	int32_t md_size;
-
-    header[8] = type;
-    header[9] = 0x03;//TODO: update for different versions
-    header[10] = 0x03;
-    header[11] = (len) >> 8;
-    header[12] = (len) & 0xff;
-
-	EVP_DigestSignUpdate(f->read_mac_ctx, header, sizeof(header));
-	EVP_DigestSignUpdate(f->read_mac_ctx, input, len);
-	EVP_DigestSignFinal(f->read_mac_ctx, output, &md_size);
-
-	return md_size;
-
-}*/
-
 /* Encrypt/Decrypt a TLS record
  *
  *  Inputs:
@@ -337,7 +303,6 @@ 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("pad: %d\n", pad);
 
 	if(enc)
 		len += pad;
@@ -387,7 +352,8 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 	EVP_DigestFinal_ex(&ctx, hash, &hash_len);
 
 	//now use pseudorandom function
-	uint8_t *output = calloc(1, fin_length);
+	uint8_t *output = ecalloc(1, fin_length);
+
 	if(incoming){
 		PRF(f, 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 {
@@ -397,16 +363,18 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 	//now compare
 	if(CRYPTO_memcmp(p, output, fin_length) != 0){
 		printf("VERIFY FAILED\n");
-		free(output);
-		EVP_MD_CTX_cleanup(&ctx);
-		return 1;
-	} else {
-		printf("VERIFY PASSED\n");
+		goto err;
 	}
 
 	free(output);
 	EVP_MD_CTX_cleanup(&ctx);
 	return 0;
+
+err:
+	if(output != NULL)
+		free(output);
+	EVP_MD_CTX_cleanup(&ctx);
+	return 1;
 }
 
 /** Computes the TLS master secret from the decoy server's
@@ -420,7 +388,9 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
  *  	0 on success, 1 on failure
  */
 int compute_master_secret(flow *f){
+#ifdef DEBUG_HS
 	printf("Computing master secret (%x:%d -> %x:%d)...\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+#endif
 
 	DH *dh_srvr = NULL;
 	DH *dh_clnt = NULL;
@@ -432,7 +402,8 @@ int compute_master_secret(flow *f){
 
 	int ok =1;
 
-	uint8_t *pre_master_secret = calloc(1, PRE_MASTER_MAX_LEN);//TODO: find right length
+	uint8_t *pre_master_secret = ecalloc(1, PRE_MASTER_MAX_LEN);//TODO: find right length
+
 	int32_t pre_master_len;
 	uint32_t l;
 	int32_t bytes;
@@ -449,7 +420,6 @@ int compute_master_secret(flow *f){
 
 		l = dh_clnt->length ? dh_clnt->length : BN_num_bits(dh_clnt->p) - 1;
 		bytes = (l+7) / 8;
-		printf("length of dh param: %d\n", bytes);
 
 		buf = (uint8_t *)OPENSSL_malloc(bytes);
 		if (buf == NULL){
@@ -459,24 +429,25 @@ int compute_master_secret(flow *f){
 
 		pub_key = BN_new();
 		priv_key = BN_new();
-
+#ifdef DEBUG
 		printf("key =");
 		for(int i=0; i< 16; i++)
 			printf(" %02x", f->key[i]);
 		printf("\n");
+#endif
 
 		PRF(f, f->key, 16,
 			(uint8_t *) SLITHEEN_KEYGEN_CONST, SLITHEEN_KEYGEN_CONST_SIZE,
 			NULL, 0, NULL, 0, NULL, 0,
 			buf, bytes);
 
-	//#ifdef DEBUG
+	#ifdef DEBUG
 		printf("Generated the following rand bytes: ");
 		for(int i=0; i< bytes; i++){
 			printf(" %02x ", buf[i]);
 		}
 		printf("\n");
-	//#endif
+	#endif
 
 		if (!BN_bin2bn(buf, bytes, priv_key))
 			goto err;
@@ -549,24 +520,20 @@ int compute_master_secret(flow *f){
 		PRF(f, f->key, 16, (uint8_t *) SLITHEEN_KEYGEN_CONST, SLITHEEN_KEYGEN_CONST_SIZE,
 				NULL, 0, NULL, 0, NULL, 0, buf, bytes);
 
-		//#ifdef DEBUG
+#ifdef DEBUG
 		printf("Generated the following rand bytes: ");
 		for(int i=0; i< bytes; i++){
 			printf("%02x ", buf[i]);
 		}
 		printf("\n");
-//#endif
+#endif
 		
 		if(!BN_bin2bn(buf, bytes, priv_key)){
 			goto err;
 		}
 
-		if(EC_KEY_get0_public_key(clnt_ecdh) == NULL){
-			if((e_pub_key = EC_POINT_new(srvr_group)) == NULL){
-				goto err;
-			}
-		} else {
-			e_pub_key = EC_KEY_get0_public_key(clnt_ecdh);
+		if((e_pub_key = EC_POINT_new(srvr_group)) == NULL){
+			goto err;
 		}
 
 		if(!EC_POINT_mul(EC_KEY_get0_group(clnt_ecdh), e_pub_key, priv_key, NULL, NULL, ctx)){
@@ -645,10 +612,11 @@ err:
 	}
 
 
-///???
-	if(priv_key != NULL){
+//TODO:
+//This is causing seg faults sometimes O.o commenting out atm (might cause memleaks)
+	/*if(priv_key != NULL){
 		BN_free(priv_key);
-	}
+	}*/
 
 	return ok;
 }
@@ -660,9 +628,9 @@ err:
  *  	hs: a pointer to the beginning of the server hello msg
  *  
  *  Output:
- *  	none
+ *  	0 on success, 1 on failure
  */
-void extract_server_random(flow *f, uint8_t *hs){
+int extract_server_random(flow *f, uint8_t *hs){
 
 	uint8_t *p;
 
@@ -679,33 +647,43 @@ void extract_server_random(flow *f, uint8_t *hs){
 	p += id_len;
 
 	//now extract ciphersuite
+#ifdef DEBUG_HS
 	printf("Checking cipher\n");
+#endif
 
 	if(((p[0] <<8) + p[1]) == 0x9E){
 
+#ifdef DEBUG_HS
 		printf("USING DHE-RSA-AES128-GCM-SHA256\n");
+		fflush(stdout);
+#endif
 		f->keyex_alg = 1;
 		f->cipher = EVP_aes_128_gcm();
 		f->message_digest = EVP_sha256();
-		fflush(stdout);
 
 	} else if(((p[0] <<8) + p[1]) == 0x9F){
+#ifdef DEBUG_HS
 		printf("USING DHE-RSA-AES256-GCM-SHA384\n");
 		fflush(stdout);
+#endif
 		f->keyex_alg = 1;
 		f->cipher = EVP_aes_256_gcm();
 		f->message_digest = EVP_sha384();
 
 	} else if(((p[0] <<8) + p[1]) == 0xC02F){
+#ifdef DEBUG_HS
 		printf("USING ECDHE-RSA-AES128-GCM-SHA256\n");
 		fflush(stdout);
+#endif
 		f->keyex_alg = 2;
 		f->cipher = EVP_aes_128_gcm();
 		f->message_digest = EVP_sha256();
 
 	} else if(((p[0] <<8) + p[1]) == 0xC030){
+#ifdef DEBUG_HS
 		printf("USING ECDHE-RSA-AES256-GCM-SHA384\n");
 		fflush(stdout);
+#endif
 		f->keyex_alg = 2;
 		f->cipher = EVP_aes_256_gcm();
 		f->message_digest = EVP_sha384();
@@ -714,8 +692,11 @@ void extract_server_random(flow *f, uint8_t *hs){
 		printf("%x %x = %x\n", p[0], p[1], ((p[0] <<8) + p[1]));
 		printf("Error: unsupported cipher\n");
 		fflush(stdout);
+		return 1;
 	}
 
+	return 0;
+
 }
 
 /** PRF using sha384, as defined in RFC 5246
@@ -831,6 +812,13 @@ int init_ciphers(flow *f){
 	EVP_CIPHER_CTX *r_ctx_srvr;
 	const EVP_CIPHER *c = f->cipher;
 
+	if(c == NULL){
+		/*This *shouldn't* happen, but might if a serverHello msg isn't received
+		 * or if a session is resumed in a strange way */
+		remove_flow(f);
+		return 0;
+	}
+
 	/* Generate Keys */
 	uint8_t *write_key, *write_iv;
 	uint8_t *read_key, *read_iv;
@@ -841,7 +829,7 @@ int init_ciphers(flow *f){
 	mac_len = EVP_MD_size(f->message_digest);
 	int32_t total_len = key_len + iv_len + mac_len;
 	total_len *= 2;
-	uint8_t *key_block = calloc(1, total_len);
+	uint8_t *key_block = ecalloc(1, total_len);
 
 	PRF(f, f->master_secret, SSL3_MASTER_SECRET_SIZE,
 			(uint8_t *) TLS_MD_KEY_EXPANSION_CONST, TLS_MD_KEY_EXPANSION_CONST_SIZE,
@@ -963,7 +951,8 @@ int init_ciphers(flow *f){
 // 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);
+	uint8_t *output = ecalloc(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.
@@ -997,7 +986,7 @@ void update_context(flow *f, uint8_t *input, int32_t len, int32_t incoming, int3
 void check_handshake(struct packet_info *info){
 
 	FILE *fp;
-	int res, i, code;
+	int res, code;
 	uint8_t *hello_rand;
 	const struct handshake_header *handshake_hdr;
 
@@ -1029,29 +1018,36 @@ void check_handshake(struct packet_info *info){
 
 		/* check tag*/ 
 		res = check_tag(key, privkey, p, (const byte *)"context", 7);
-		if (res) {
-			printf("Untagged\n");
-		} else {
+		if (!res) {
 
+#ifdef DEBUG
 			printf("Received tagged flow! (key =");
 			for(i=0; i<16;i++){
 			    printf(" %02x", key[i]);
 			}
 			printf(")\n");
+#endif
 
 			/* Save flow in table */
 			flow *flow_ptr = add_flow(info);
+			if(flow_ptr == NULL){
+				fprintf(stderr, "Memory failure\n");
+				return;
+			}
+
 			for(int i=0; i<16; i++){
 				flow_ptr->key[i] = key[i];
 			}
 
 			memcpy(flow_ptr->client_random, hello_rand, SSL3_RANDOM_SIZE);
+#ifdef DEBUG
 			for(int i=0; i< SSL3_RANDOM_SIZE; i++){
 				printf("%02x ", hello_rand[i]);
 			}
 			printf("\n");
 			
 			printf("Saved new flow\n");
+#endif
 
 		}
 	}

+ 1 - 1
server/crypto.h

@@ -11,7 +11,7 @@
 
 int extract_parameters(flow *f, uint8_t *hs);
 int encrypt(flow *f, uint8_t *input, uint8_t *output, int32_t len, int32_t incoming, int32_t type, int32_t enc);
-void extract_server_random(flow *f, uint8_t *hs);
+int extract_server_random(flow *f, uint8_t *hs);
 int compute_master_secret(flow *f);
 
 int PRF(flow *f, uint8_t *secret, int32_t secret_len,

+ 175 - 39
server/flow.c

@@ -1,3 +1,7 @@
+/* flow.c by Cecylia Bocovich <cbocovic@uwaterloo.ca>*/
+
+/* Defines and modifies the flow structure. */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -9,6 +13,7 @@
 #include "crypto.h"
 #include "slitheen.h"
 #include "relay.h"
+#include "util.h"
 
 static flow_table *table;
 static session_cache *sessions;
@@ -20,13 +25,13 @@ sem_t flow_table_lock;
 /* Initialize the table of tagged flows */
 int init_tables(void) {
 
-	table = calloc(1, sizeof(flow_table));
+	table = emalloc(sizeof(flow_table));
 	table->first_entry = NULL;
 	table->len = 0;
 
 	sem_init(&flow_table_lock, 0, 1);
 
-	clients = calloc(1, sizeof(client_table));
+	clients = emalloc(sizeof(client_table));
 	clients->first = NULL;
 	printf("initialized downstream queue\n");
 
@@ -36,13 +41,13 @@ int init_tables(void) {
 
 /* Add a new flow to the tagged flow table */
 flow *add_flow(struct packet_info *info) {
-	flow_entry *entry = calloc(1, sizeof(flow_entry));
-	flow *new_flow = calloc(1, sizeof(flow));
+	flow_entry *entry = emalloc(sizeof(flow_entry));
+
+	flow *new_flow = emalloc(sizeof(flow));
+
 	entry->f = new_flow;
 	entry->next = NULL;
 
-	printf("there are %d flows in the table\n", table->len);
-
 	new_flow->src_ip = info->ip_hdr->src;
 	new_flow->dst_ip = info->ip_hdr->dst;
 	new_flow->src_port = info->tcp_hdr->src_port;
@@ -62,12 +67,14 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->resume_session = 0;
 	new_flow->current_session = NULL;
 
-	new_flow->us_packet_chain = calloc(1, sizeof(packet_chain));
+	new_flow->us_packet_chain = emalloc(sizeof(packet_chain));
+	
 	new_flow->us_packet_chain->expected_seq_num = ntohl(info->tcp_hdr->sequence_num);
 	new_flow->us_packet_chain->record_len = 0;
 	new_flow->us_packet_chain->remaining_record_len = 0;
 	new_flow->us_packet_chain->first_packet = NULL;
-	new_flow->ds_packet_chain = calloc(1, sizeof(packet_chain));
+	new_flow->ds_packet_chain = emalloc(sizeof(packet_chain));
+
 	new_flow->ds_packet_chain->expected_seq_num = ntohl(info->tcp_hdr->ack_num);
 	new_flow->ds_packet_chain->record_len = 0;
 	new_flow->ds_packet_chain->remaining_record_len = 0;
@@ -117,6 +124,7 @@ flow *add_flow(struct packet_info *info) {
 	sem_post(&flow_table_lock);
 
 	return new_flow;
+
 }
 
 /** Observes TLS handshake messages and updates the state of
@@ -145,19 +153,25 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 			p += RECORD_HEADER_LEN;
 
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
+#ifdef DEBUG_HS
 				printf("Decrypting finished (%d bytes) (%x:%d -> %x:%d)\n", record_len - RECORD_HEADER_LEN, f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
+#endif
 				int32_t n = encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16, 0);
 				if(n<=0){
 					printf("Error decrypting finished  (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
 				}
+#ifdef DEBUG_HS
 				printf("Finished decrypted: (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
+#endif
 				p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 				
+#ifdef DEBUG_HS
 				printf("record:\n");
 				for(int i=0; i< n; i++){
 					printf("%02x ", p[i]);
 				}
 				printf("\n");
+#endif
 				if(p[0] != 0x14){
 					p[0] = 0x20; //trigger error
 				}
@@ -171,66 +185,160 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 
 			switch(f->state){
 				case TLS_CLNT_HELLO: 
+#ifdef DEBUG_HS
 					printf("Received tagged client hello (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
-					update_finish_hash(f, p);
-					check_session(f, p, HANDSHAKE_MESSAGE_LEN(handshake_hdr));
+#endif
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish has with CLNT_HELLO msg\n");
+						remove_flow(f);
+						goto err;
+					}
+					if(check_session(f, p, HANDSHAKE_MESSAGE_LEN(handshake_hdr))){
+						fprintf(stderr, "Error checking session, might cause problems\n");
+					}
+
 					break;
 				case TLS_SERV_HELLO:
+#ifdef DEBUG_HS
 					printf("Received server hello (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
+#endif
 					if(f->resume_session){
-						verify_session_id(f,p);
+						if(verify_session_id(f,p)){
+							fprintf(stderr, "Failed to verify session id\n");
+						}
 					} else {
-						save_session_id(f,p);
+						if(save_session_id(f,p)){
+							fprintf(stderr, "Failed to save session id\n");
+						}
+					}
+					if(extract_server_random(f, p)){
+						fprintf(stderr, "Failed to extract server random nonce\n");
+						remove_flow(f);
+						goto err;
+					}
+
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with SRVR_HELLO msg\n");
+						remove_flow(f);
+						goto err;
 					}
-					extract_server_random(f, p);
-					update_finish_hash(f, p);
 					break;
 				case TLS_NEW_SESS:
+#ifdef DEBUG_HS
 					printf("Received new session\n");
-					save_session_ticket(f, p, HANDSHAKE_MESSAGE_LEN(handshake_hdr));
-					update_finish_hash(f, p);
+#endif
+					if(save_session_ticket(f, p, HANDSHAKE_MESSAGE_LEN(handshake_hdr))){
+						fprintf(stderr, "Failed to save session ticket\n");
+					}
+					
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with NEW_SESS msg\n");
+						remove_flow(f);
+						goto err;
+					}
+					
 					break;
 				case TLS_CERT:
+#ifdef DEBUG_HS
 					printf("Received cert\n");
-					update_finish_hash(f, p);
+#endif
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with CERT msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					break;
 				case TLS_SRVR_KEYEX:
+#ifdef DEBUG_HS
 					printf("Received server keyex\n");
-					update_finish_hash(f, p);
+#endif
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with SRVR_KEYEX msg\n");
+						remove_flow(f);
+						goto err;
+					}
 
 					if(extract_parameters(f, p)){
 						printf("Error extracting params\n");
+						remove_flow(f);
+						goto err;
 					}
+
 					if(compute_master_secret(f)){
 						printf("Error computing master secret\n");
+						remove_flow(f);
+						goto err;
+
 					}
+
 					break;
+
 				case TLS_CERT_REQ:
-					update_finish_hash(f, p);
+
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with CERT_REQ msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					break;
 				case TLS_SRVR_HELLO_DONE:
+#ifdef DEBUG_HS
 					printf("Received server hello done\n");
-					update_finish_hash(f, p);
+#endif
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with HELLO_DONE msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					break;
 				case TLS_CERT_VERIFY:
+#ifdef DEBUG_HS
 					printf("received cert verify\n");
-					update_finish_hash(f, p);
+#endif
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with CERT_VERIFY msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					break;
+
 				case TLS_CLNT_KEYEX:
+#ifdef DEBUG_HS
 					printf("Received client key exchange\n");
-					update_finish_hash(f, p);
+#endif
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with CLNT_KEYEX msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					break;
 				case TLS_FINISHED:
+#ifdef DEBUG_HS
 					printf("Received finished (%d) (%x:%d -> %x:%d)\n", incoming, f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
+#endif
 					verify_finish_hash(f,p, incoming);
-					update_finish_hash(f, p);
+					
+					if(update_finish_hash(f, p)){
+						fprintf(stderr, "Error updating finish hash with FINISHED msg\n");
+						remove_flow(f);
+						goto err;
+					}
+
 					if((f->in_encrypted == 2) && (f->out_encrypted == 2)){
 						printf("Handshake complete!\n");
 						f->application = 1;
 					}
+
 					break;
 				default:
 					printf("Error? (%x:%d -> %x:%d)...\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
+					remove_flow(f);
+					goto err;
 					break;
 			}
 			break;
@@ -238,10 +346,16 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 			printf("Application Data (%x:%d -> %x:%d)...\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
 			break;
 		case CCS:
+#ifdef DEBUG_HS
 			printf("CCS (%x:%d -> %x:%d) \n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
+#endif
 			/*Initialize ciphers */
 			if ((!f->in_encrypted) && (!f->out_encrypted)){
-				init_ciphers(f);
+				if(init_ciphers(f)){
+					fprintf(stderr, "Failed to initialize ciphers\n");
+					remove_flow(f);
+					goto err;
+				}
 			}
 
 			if(incoming){
@@ -269,10 +383,12 @@ int update_flow(flow *f, uint8_t *record, uint8_t incoming) {
 			fflush(stdout);
 			goto err;
 	}
+	free(record);
+	return 0;
 
 err:
 	free(record);
-	return 0;
+	return 1;
 }
 
 /** Removes the tagged flow from the flow table: happens when
@@ -287,7 +403,9 @@ err:
 int remove_flow(flow *f) {
 
 	EVP_MD_CTX_cleanup(f->finish_md_ctx);
-	EVP_MD_CTX_destroy(f->finish_md_ctx);
+	if(f->finish_md_ctx != NULL){
+		EVP_MD_CTX_destroy(f->finish_md_ctx);
+	}
 	//Clean up cipher ctxs
 	if(f->clnt_read_ctx != NULL){
 		EVP_CIPHER_CTX_cleanup(f->clnt_read_ctx);
@@ -467,7 +585,8 @@ flow *check_flow(struct packet_info *info){
 }
 
 int init_session_cache(void){
-	sessions = malloc(sizeof(session_cache));
+	sessions = emalloc(sizeof(session_cache));
+
 	sessions->length = 0;
 	sessions->first_session = NULL;
 
@@ -497,19 +616,22 @@ int verify_session_id(flow *f, uint8_t *hs){
 	//check to see if it matches flow's session id set by ClientHello
 	if(f->current_session != NULL && f->current_session->session_id_len > 0 && !memcmp(f->current_session->session_id, p, id_len)){
 		//if it matched, update flow with master secret :D
+#ifdef DEBUG_HS
 		printf("Session id matched!\n");
 		printf("First session id (%p->%p):", sessions, sessions->first_session);
+#endif
 		session *last = sessions->first_session;
 		int found = 0;
 		for(int i=0; ((i<sessions->length) && (!found)); i++){
+#ifdef DEBUG_HS
 			printf("Checking saved session id: ");
 			for (int j=0; j< last->session_id_len; j++){
 				printf("%02x ", last->session_id[j]);
 			}
 			printf("\n");
+#endif
 			if(!memcmp(last->session_id, f->current_session->session_id, id_len)){
 				memcpy(f->master_secret, last->master_secret, SSL3_MASTER_SECRET_SIZE);
-				printf("Found session id number!\n");
 				found = 1;
 			}
 			last = last->next;
@@ -517,14 +639,18 @@ int verify_session_id(flow *f, uint8_t *hs){
 		if((!found) && (f->current_session->session_ticket_len > 0)){
 			last = sessions->first_session;
 			for(int i=0; ((i<sessions->length) && (!found)); i++){
+				if(last->session_ticket_len == f->current_session->session_ticket_len){
 				if(!memcmp(last->session_ticket, f->current_session->session_ticket, f->current_session->session_ticket_len)){
 					memcpy(f->master_secret, last->master_secret, SSL3_MASTER_SECRET_SIZE);
 					found = 1;
+#ifdef DEBUG_HS
 					printf("Found new session ticket (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
 					for(int i=0; i< last->session_ticket_len; i++){
 						printf("%02x ", last->session_ticket[i]);
 					}
 					printf("\n");
+#endif
+				}
 				}
 				last = last->next;
 			}
@@ -556,7 +682,7 @@ int check_session(flow *f, uint8_t *hs, uint32_t len){
 	p += 2; //skip version
 	p += SSL3_RANDOM_SIZE; //skip random
 
-	session *new_session = calloc(1, sizeof(session));
+	session *new_session = emalloc(sizeof(session));
 	new_session->session_id_len = (uint8_t) p[0];
 	new_session->session_ticket_len = 0;
 	p  ++;
@@ -565,12 +691,14 @@ int check_session(flow *f, uint8_t *hs, uint32_t len){
 		f->resume_session = 1;
 		memcpy(new_session->session_id, p, new_session->session_id_len);
 		new_session->next = NULL;
+#ifdef DEBUG_HS
 		printf("Requested new session (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
 		printf("session id: \n");
 		for(int i=0; i< new_session->session_id_len; i++){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
+#endif
 
 		f->current_session = new_session;
 	}
@@ -603,7 +731,7 @@ int check_session(flow *f, uint8_t *hs, uint32_t len){
 			if(ext_len > 0){
 				f->resume_session = 1;
 				new_session->session_ticket_len = ext_len;
-				new_session->session_ticket = calloc(1, ext_len);
+				new_session->session_ticket = emalloc(ext_len);
 				memcpy(new_session->session_ticket, p, ext_len);
 				f->current_session = new_session;
 			}
@@ -632,14 +760,14 @@ int check_session(flow *f, uint8_t *hs, uint32_t len){
  *  	0 if success, 1 if failed
  */
 int save_session_id(flow *f, uint8_t *hs){
-	printf("saving session id\n");
 
 	//increment pointer to point to sessionid
 	uint8_t *p = hs + HANDSHAKE_HEADER_LEN;
 	p += 2; //skip version
 	p += SSL3_RANDOM_SIZE; //skip random
 	
-	session *new_session = calloc(1, sizeof(session));
+	session *new_session = emalloc(sizeof(session));
+
 	new_session->session_id_len = (uint8_t) p[0];
 	if(new_session->session_id_len <= 0){
 		//if this value is zero, the session is non-resumable or the
@@ -702,22 +830,24 @@ int save_session_id(flow *f, uint8_t *hs){
  *  	0 if success, 1 if failed
  */
 int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
+#ifdef DEBUG_HS
 	printf("TICKET HDR:");
 	for(int i=0; i< HANDSHAKE_HEADER_LEN; i++){
 		printf("%02x ", hs[i]);
 	}
 	printf("\n");
+#endif
 	uint8_t *p = hs + HANDSHAKE_HEADER_LEN;
 	p += 4; //skip lifetime TODO: add to session struct
-	session *new_session = calloc(1,sizeof(session));
+	session *new_session = emalloc(sizeof(session));
+
 	new_session->session_id_len = 0;
 	
 	new_session->session_ticket_len = (p[0] << 8) + p[1];
-	printf("saving ticket of size %d (msg size %d)\n", new_session->session_ticket_len, len);
-	fflush(stdout);
 	p += 2;
 
-	uint8_t *ticket = calloc(1, new_session->session_ticket_len);
+	uint8_t *ticket = emalloc(new_session->session_ticket_len);
+
 	memcpy(ticket, p, new_session->session_ticket_len);
 	new_session->session_ticket = ticket;
 	memcpy(new_session->master_secret, f->master_secret, SSL3_MASTER_SECRET_SIZE);
@@ -739,6 +869,7 @@ int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
 
 	sessions->length ++;
 
+#ifdef DEBUG_HS
 	printf("Saved session ticket:");
 	for(int i=0; i< new_session->session_ticket_len; i++){
 		printf(" %02x", p[i]);
@@ -755,22 +886,25 @@ int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
 
 	printf("THERE ARE NOW %d saved sessions\n", sessions->length);
 	fflush(stdout);
+#endif
 
 	return 0;
 }
 
 /* Adds a packet the flow's packet chain. If it can complete a record, gives
  * this record to update_flow */
+//TODO: check all returns and figure out what to do if there is a mem failure
 int add_packet(flow *f, struct packet_info *info){
 	if (info->tcp_hdr == NULL || info->app_data_len <= 0){
 		return 0;
 	}
 
-	packet *new_packet = calloc(1, sizeof(packet));
+	packet *new_packet = emalloc(sizeof(packet));
+
 	new_packet->seq_num = ntohl(info->tcp_hdr->sequence_num);
 	new_packet->len = info->app_data_len;
 
-	uint8_t *packet_data = calloc(1, new_packet->len);
+	uint8_t *packet_data = emalloc(new_packet->len);
 	memcpy(packet_data, info->app_data, new_packet->len);
 
 	new_packet->data = packet_data;
@@ -823,7 +957,7 @@ int add_packet(flow *f, struct packet_info *info){
 				//if full record, give to update_flow
 				if(chain->remaining_record_len <= new_packet->len){
 					chain->remaining_record_len = 0;
-					uint8_t *record = calloc(1, chain->record_len);
+					uint8_t *record = emalloc(chain->record_len);
 					uint32_t record_len = chain->record_len;
 					uint32_t tmp_len = chain->record_len;
 					packet *next = chain->first_packet;
@@ -847,8 +981,10 @@ int add_packet(flow *f, struct packet_info *info){
 							const struct record_header *record_hdr = (struct record_header *) next->data;
 							chain->record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
 							chain->remaining_record_len = chain->record_len;
+#ifdef DEBUG
 							printf("Found record of type %d\n", record_hdr->type);
 							fflush(stdout);
+#endif
 
 						}
 					}

+ 51 - 35
server/relay.c

@@ -1,3 +1,9 @@
+/* relay.c by Cecylia Bocovich <cbocovic@uwaterloo.ca>
+ *
+ * Once a flow has been tagged, this code will extract covert data from the header
+ * of HTTP GET requests and insert downstream data into leaf resources
+ */
+
 #include <stdio.h>
 #include <stdlib.h>
 #include <stdint.h>
@@ -17,8 +23,7 @@
 #include "slitheen.h"
 #include "flow.h"
 #include "crypto.h"
-
-#define DEBUG
+#include "util.h"
 
 /** Called when a TLS application record is received for a
  *  tagged flow. Upstream packets will be checked for covert
@@ -92,9 +97,6 @@ int replace_packet(flow *f, struct packet_info *info){
  *  request to the indicated site and saves the response to
  *  the censored queue
  *
- *  TODO: change this to take SOCKS5 proxy connection and then relay data
- *  	based on stream ID
- *
  *  Inputs:
  *  	f: the tagged flow
  *  	info: the processed received packet
@@ -116,8 +118,9 @@ int read_header(flow *f, struct packet_info *info){
 	//check to see whether the previous record has finished
 		if(f->upstream_remaining > info->app_data_len){
 			//ignore entire packet for now
-			queue_block *new_block = calloc(1, sizeof(queue_block));
-			uint8_t *block_data = calloc(1, info->app_data_len);
+			queue_block *new_block = emalloc(sizeof(queue_block));
+
+			uint8_t *block_data = emalloc(info->app_data_len);
 			memcpy(block_data, p, info->app_data_len);
 
 			new_block->len = info->app_data_len;
@@ -143,7 +146,8 @@ int read_header(flow *f, struct packet_info *info){
 			//process what we have
 			record_hdr = (struct record_header*) f->upstream_queue->data;
 			record_length = RECORD_LEN(record_hdr);
-			record_ptr = calloc(1, record_length+ RECORD_HEADER_LEN);
+			record_ptr = emalloc(record_length+ RECORD_HEADER_LEN);
+				
 			queue_block *current = f->upstream_queue;
 			int32_t offset =0;
 			while(f->upstream_queue != NULL){
@@ -166,8 +170,10 @@ int read_header(flow *f, struct packet_info *info){
 		if(record_length > info->app_data_len){
 
 			//add info to upstream queue
-			queue_block *new_block = calloc(1, sizeof(queue_block));
-			uint8_t *block_data = calloc(1, info->app_data_len);
+			queue_block *new_block = emalloc(sizeof(queue_block));
+
+			uint8_t *block_data = emalloc(info->app_data_len);
+
 			memcpy(block_data, p, info->app_data_len);
 
 			new_block->len = info->app_data_len;
@@ -192,7 +198,7 @@ int read_header(flow *f, struct packet_info *info){
 	}
 
 	p+= RECORD_HEADER_LEN;
-	uint8_t *decrypted_data = calloc(1, record_length);
+	uint8_t *decrypted_data = emalloc(record_length);
 
 	memcpy(decrypted_data, p, record_length);
 
@@ -241,7 +247,9 @@ int read_header(flow *f, struct packet_info *info){
 	header_ptr += strlen("X-Slitheen: ");
 	
 	if(*header_ptr == '\r' || *header_ptr == '\0'){
+#ifdef DEBUG
 		printf("No messages\n");
+#endif
 		free(decrypted_data);
 		return 0;
 	}
@@ -260,10 +268,11 @@ int read_header(flow *f, struct packet_info *info){
 	}
 	c++;
 	*c = '\0';
+#ifdef DEBUG
 	printf("UPSTREAM: Found %d messages\n", num_messages);
+#endif
 
 	for(int i=0; i< num_messages-1; i++){
-		printf("Decoding message: %s\n", messages[i]);
 		char *message = messages[i];
 
 		//b64 decode the data
@@ -276,7 +285,7 @@ int read_header(flow *f, struct packet_info *info){
 			decode_len = decode_len*3/4;
 		}
 
-		upstream_data = calloc(1, decode_len + 1);
+		upstream_data = emalloc(decode_len + 1);
 
 		BIO *bio, *b64;
 		bio = BIO_new_mem_buf(message, -1);
@@ -300,11 +309,13 @@ int read_header(flow *f, struct packet_info *info){
 
 		if(i== 0){
 			//this is the Slitheen ID
+#ifdef DEBUG
 			printf("Slitheen ID:");
 			for(int j=0; j< output_len; j++){
 				printf("%02x ", p[j]);
 			}
 			printf("\n");
+#endif
 
 			//find stream table or create new one
 
@@ -313,8 +324,8 @@ int read_header(flow *f, struct packet_info *info){
 				if(!memcmp(last->slitheen_id, p, output_len)){
 					f->streams = last->streams;
 					f->downstream_queue = last->downstream_queue;
-					printf("Found client in table!\n");
 					break;
+#ifdef DEBUG
 				} else {
 					for(int j=0; j< output_len; j++){
 						printf("%02x ", last->slitheen_id[j]);
@@ -324,18 +335,21 @@ int read_header(flow *f, struct packet_info *info){
 						printf("%02x ", p[j]);
 					}
 					printf("\n");
+#endif
 				}
 				last = last->next;
 			}
 
 			if(f->streams == NULL){
-				printf("Making new client\n");
 				//create new client
-				client *new_client = calloc(1, sizeof(client));
+				client *new_client = emalloc(sizeof(client));
+
 				memcpy(new_client->slitheen_id, p, output_len);
-				new_client->streams = calloc(1, sizeof(stream_table));
+				new_client->streams = emalloc(sizeof(stream_table));
+
 				new_client->streams->first = NULL;
-				new_client->downstream_queue = calloc(1, sizeof(data_queue));
+				new_client->downstream_queue = emalloc(sizeof(data_queue));
+
 				new_client->downstream_queue->first_block = NULL;
 	
 				new_client->next = NULL;
@@ -407,7 +421,9 @@ int read_header(flow *f, struct packet_info *info){
 					close(stream_pipe);
 					break;
 				}
+#ifdef DEBUG
 				printf("Found stream id %d\n", last->stream_id);
+#endif
 				int32_t bytes_sent = write(stream_pipe, p, stream_len);
 				if(bytes_sent < 0){
 					printf("Error sending bytes to stream pipe\n");
@@ -416,7 +432,6 @@ int read_header(flow *f, struct packet_info *info){
 			} else if(stream_len > 0){
 
 				/*Else, spawn a thread to handle the proxy to this site*/
-				printf("creating new thread for stream id %d\n", stream_id);
 				pthread_t proxy_thread;
 				int32_t pipefd[2];
 				if(pipe(pipefd) < 0){
@@ -425,11 +440,12 @@ int read_header(flow *f, struct packet_info *info){
 						free(record_ptr);
 					return 1;
 				}
-				uint8_t *initial_data = calloc(1,stream_len);
+				uint8_t *initial_data = emalloc(stream_len);
+				//TODO: ended here. create macro that just exits
 				memcpy(initial_data, p, stream_len);
 
 				struct proxy_thread_data *thread_data = 
-					calloc(1, sizeof(struct proxy_thread_data));
+					emalloc(sizeof(struct proxy_thread_data));
 				thread_data->initial_data = initial_data;
 				thread_data->initial_len = stream_len;
 				thread_data->stream_id = stream_id;
@@ -441,7 +457,7 @@ int read_header(flow *f, struct packet_info *info){
 
 				pthread_detach(proxy_thread);
 				//add stream to table
-				stream *new_stream = calloc(1, sizeof(stream));
+				stream *new_stream = emalloc(sizeof(stream));
 				new_stream->stream_id = stream_id;
 				new_stream->pipefd = pipefd[1];
 				new_stream->next = NULL;
@@ -533,7 +549,7 @@ void *proxy_covert_site(void *data){
 		domain_len = p[0];
 		p++;
 		data_len --;
-		uint8_t *domain_name = calloc(1, domain_len+1);
+		uint8_t *domain_name = emalloc(domain_len+1);
 		memcpy(domain_name, p, domain_len);
 		domain_name[domain_len] = '\0';
 		struct hostent *host;
@@ -570,10 +586,9 @@ void *proxy_covert_site(void *data){
     }
 
 	getsockname(handle, (struct sockaddr *) &my_addr, &my_addr_len);
-	printf("Bound to %x:%d\n", my_addr.sin_addr.s_addr, ntohs(my_addr.sin_port));
 
 #ifdef OLD
-	uint8_t *response = calloc(1, 11);
+	uint8_t *response = emalloc(11);
 	//now send the reply to the client
 	response[0] = 0x05;
 	response[1] = 0x00;//TODO: make this accurate
@@ -590,7 +605,7 @@ void *proxy_covert_site(void *data){
 	fflush(stdout);
 
 	//No longer need to send response
-	queue_block *new_block = calloc(1, sizeof(queue_block));
+	queue_block *new_block = emalloc(sizeof(queue_block));
 	new_block->len = 10;
 	new_block->offset = 0;
 	new_block->data = response;
@@ -609,12 +624,14 @@ void *proxy_covert_site(void *data){
 
 	//see if there were extra upstream bytes
 	if(data_len > 0){
+#ifdef DEBUG
 		printf("Data len is %d\n", data_len);
 		printf("Upstream bytes: ");
 		for(int i=0; i< data_len; i++){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
+#endif
 		bytes_sent = send(handle, p,
 				data_len, 0);
 		if( bytes_sent <= 0){
@@ -622,7 +639,7 @@ void *proxy_covert_site(void *data){
 		}
 	}
 
-	uint8_t *buffer = calloc(1, BUFSIZ);
+	uint8_t *buffer = emalloc(BUFSIZ);
 	int32_t buffer_len = BUFSIZ;
 	//now select on reading from the pipe and from the socket
 	for(;;){
@@ -679,7 +696,7 @@ void *proxy_covert_site(void *data){
 			int32_t bytes_read;
 			bytes_read = recv(handle, buffer, buffer_len, 0);
 			if(bytes_read > 0){
-				uint8_t *new_data = calloc(1, bytes_read);
+				uint8_t *new_data = emalloc(bytes_read);
 				memcpy(new_data, buffer, bytes_read);
 #ifdef DEBUG
 				printf("PROXY (id %d): read %d bytes from censored site\n",stream_id, bytes_read);
@@ -690,7 +707,7 @@ void *proxy_covert_site(void *data){
 #endif
 
 				//make a new queue block
-				queue_block *new_block = calloc(1, sizeof(queue_block));
+				queue_block *new_block = emalloc(sizeof(queue_block));
 				new_block->len = bytes_read;
 				new_block->offset = 0;
 				new_block->data = new_data;
@@ -798,7 +815,6 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 	uint8_t *p = info->app_data;
 	uint32_t remaining_packet_len = info->app_data_len;
-	printf("Application data length: %d at %p\n", info->app_data_len, info->app_data);
 
 
 	if(f->remaining_record_len > 0){
@@ -839,7 +855,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 			printf("\n");
 			fflush(stdout);
 #endif
-			f->partial_record_header = calloc(1, RECORD_HEADER_LEN);
+			f->partial_record_header = emalloc(RECORD_HEADER_LEN);
 			memcpy(f->partial_record_header, p, remaining_packet_len);
 			f->partial_record_header_len = remaining_packet_len;
 			remaining_packet_len -= remaining_packet_len;
@@ -886,7 +902,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 				if(f->remaining_response_len >= 0 && f->replace_response){
 //#ifdef nothing
 					//make a huge record, encrypt it, and then place it in the outbox
-					f->outbox = calloc(1, record_len+1);
+					f->outbox = emalloc(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
@@ -1193,7 +1209,7 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 	data_queue *downstream_queue = f->downstream_queue;
 
 	//Fill as much as we can from the censored_queue
-	while((remaining > SLITHEEN_HEADER_LEN) && downstream_queue->first_block != NULL){
+	while((remaining > SLITHEEN_HEADER_LEN) && downstream_queue != NULL && downstream_queue->first_block != NULL){
 		queue_block *first_block = downstream_queue->first_block;
 		int32_t block_length = first_block->len;
 		int32_t offset = first_block->offset;
@@ -1254,13 +1270,13 @@ int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 		sl_hdr->len = htons(remaining);
 		sl_hdr->garbage = htons(remaining);
 
-//#ifdef DEBUG
+#ifdef DEBUG
 		printf("DWNSTRM: slitheen header: ");
 		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 			printf("%02x ", p[i]);
 		}
 		printf("\n");
-//#endif
+#endif
 
 		p += SLITHEEN_HEADER_LEN;
 		memset(p, 'A', remaining);

+ 26 - 8
server/slitheen-proxy.c

@@ -1,3 +1,5 @@
+/* slitheen-proxy.c by Cecylia Bocovich */
+
 #include <pcap.h>
 #include <stdio.h>
 #include <stdlib.h>
@@ -5,6 +7,8 @@
 #include <string.h>
 #include <pthread.h>
 #include <openssl/ssl.h>
+
+#include "util.h"
 #include "flow.h"
 #include "slitheen.h"
 #include "relay.h"
@@ -17,8 +21,8 @@ void usage(void){
 
 int main(int argc, char *argv[]){
 	pthread_t t1, t2;
-	char *filter1 = calloc(1, 33);
-	char *filter2 = calloc(1, 33);
+	char *filter1 = ecalloc(1, 33);
+	char *filter2 = ecalloc(1, 33);
 
 	char *dev1 = NULL; /* Device that leads to the internal network */
 	char *dev2 = NULL; /* Device that leads out to the world */
@@ -36,8 +40,12 @@ int main(int argc, char *argv[]){
 	snprintf(filter1, 33, "ether src host %s", macaddr1);
 	snprintf(filter2, 33, "ether src host %s", macaddr2);
 
-	init_tables();
-	init_session_cache();
+	if(init_tables()){
+		exit(1);
+	}
+	if(init_session_cache()){
+		exit(1);
+	}
 	init_crypto_locks();
 
 	/* Create threads */
@@ -115,11 +123,17 @@ void *sniff_packets(void *args){
 	return NULL;
 }
 
+/**
+ * Runs when pcap_loop receives a packet from the specified interface
+ * If the received packet is a tcp packet, processes it and then writes it back out
+ * to the interface
+ *
+ */
 void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *packet){
 	pcap_t *handle = (pcap_t *) args;
 
-	struct packet_info *info = calloc(1, sizeof(struct packet_info));
-	uint8_t *tmp_packet = calloc(1, header->len);
+	struct packet_info *info = emalloc(sizeof(struct packet_info));
+	uint8_t *tmp_packet = emalloc(header->len);
 	//printf("Allocated %d bytes to %p\n", header->len, tmp_packet);
 	memcpy(tmp_packet, packet, header->len);
 	extract_packet_headers(tmp_packet, info);
@@ -140,7 +154,6 @@ end:
 		fprintf(stderr, "%02x ", packet[i]);
 	}
 	fprintf(stderr, "\n");
-#endif
 
 	if((info->tcp_hdr != NULL) && (info->ip_hdr != NULL)){
 	fprintf(stdout,"Injected packet: %x:%d > %x:%d\n", info->ip_hdr->src.s_addr, ntohs(info->tcp_hdr->src_port), info->ip_hdr->dst.s_addr, ntohs(info->tcp_hdr->dst_port));
@@ -149,6 +162,7 @@ end:
 	fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
 	fflush(stdout);
 	}
+#endif
 	free(info);//Note: don't free this while a thread is using it
 	free(tmp_packet);
 
@@ -247,8 +261,10 @@ void extract_packet_headers(uint8_t *packet, struct packet_info *info){
 
 }
 
+/** Copies a packet_info structure and returns a pointer to the duplicate.
+ */
 struct packet_info *copy_packet_info(struct packet_info *src_info){
-	struct packet_info *dst_info = calloc(1, sizeof(struct packet_info));
+	struct packet_info *dst_info = emalloc(sizeof(struct packet_info));
 
 	dst_info->ip_hdr = src_info->ip_hdr;
 	dst_info->tcp_hdr = src_info->tcp_hdr;
@@ -261,3 +277,5 @@ struct packet_info *copy_packet_info(struct packet_info *src_info){
 
 	return dst_info;
 }
+
+

+ 14 - 142
server/util.c

@@ -1,153 +1,25 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include "util.h"
-#include "slitheen.h"
 
-static fragment_table *frag_table;
-
-/**
- * This function takes as argument a packet fragment. It checks
- * to see if there are other pending packets. If so, it
- * looks for matching identification numbers and attempts
- * to reconstruct a packet. If the packet reconstruction was
- * complete, returns a 1 and the input packet will point to
- * the completely reassembled ip packet. If the reconstruction
- * requires more fragments, it returns a 0. Returns -1 on error
- */
-int report_fragment(const u_char *data, u_char *packet, u_int length){
-	int i, ret;
-	unsigned char *partial_packet;
-	const struct ip_header *ip_hdr;
-
-	ip_hdr = (struct ip_header*) data;
-	printf("fragment reported.\n");
-	/* First check to see if this belongs to a partial packet */
-	for (i=0; i<frag_table->len; i++){
-		printf("checking fragments.\n");
-		fragment *candidate = frag_table->table+i;
-		if (candidate->id == ip_hdr->id){
-			/*update fragment in table with new data */
-			printf("Matches existing packet.\n");
-			ret = update_fragment(i, data, length);
-			if(ret == 1){
-				/* Complete, copy into packet ptr */
-				printf("Successfully reconstructed packet!\n");
-				for(i=0; i<ip_hdr->len; i++){
-					packet[i] = candidate->data[i];
-				}
-			}
-			return ret;
-		}
+//malloc macro that exits on error
+void *emalloc(size_t size){
+	void *ptr = malloc(size);
+	if (ptr == NULL){
+		fprintf(stderr, "Memory failure. Exiting...\n");
+		exit(1);
 	}
-
-	printf("Creating new partial packet.\n");
-	/* New packet, create a new table entry */
-	fragment new_fragment;
-	new_fragment.id = ip_hdr->id;
-	new_fragment.ip_len = ip_hdr->len;
-	partial_packet = malloc(65535);
-	new_fragment.data = partial_packet;
-	if(add_fragment(new_fragment))
-		return -1;
-
-	/* Now add data into fragment */
-	printf("New partial packet created.\n");
-	return update_fragment(frag_table->len -1, data, length);
-
-}
-
-/**
- * Initializes the table of all partialy reconstructed
- * packets. Sets the maximum length to defined MAX_FRAGMENTS
- */
-int init_fragment_table(void) {
-
-	frag_table = malloc(sizeof(fragment_table));
 	
-	frag_table->table = (fragment *) malloc(sizeof(fragment)*MAX_FRAGMENTS);
-	if( frag_table->table == NULL){
-		fprintf(stderr, "malloc failed.\n");
-		return 1;
-	}
-	frag_table->len = 0;
-	frag_table->max_len = MAX_FRAGMENTS;
-
-	return 0;
+	return ptr;
 }
 
-/**
- * Adds a new fragment to the table of partial packets.
- */
-int add_fragment(fragment new_fragment){
-	fragment *ptr;
-
-	if(frag_table->len == frag_table->max_len){
-		//grow_table();
-		return(1);
-	}
-
-	ptr = frag_table->table + frag_table->len;
-	*ptr = new_fragment;
-
-	frag_table->len ++;
-
-	return 0;
-}
-
-/**
- * Updates an existing partial packet by copying data into
- * packet. returns a 1 if reconstruction is complete, 0 if not,
- * and -1 on error.
- */
-int update_fragment(int index, const u_char *data, u_int length){
-	int i, data_length;
-	unsigned char *src, *dest;
-	const struct ip_header *ip_hdr;
-	u_short offset;
-	fragment *ptr;
-	u_int size_ip_hdr;
-
-	ip_hdr = (struct ip_header*) data;
-	offset = ip_hdr->flagsoff & 0x1fff;
-	size_ip_hdr = IP_HEADER_LEN(ip_hdr);
-
-	ptr = (fragment *) frag_table->table+index;
-	dest = ptr->data + offset;
-	src = (unsigned char *) data + size_ip_hdr;
-
-	/* Copy all but the last 4 bytes to partial packet
-	 * these belong to the ethernet footer */
-	data_length = length - size_ip_hdr - 4;
-
-	for(i=0; i< data_length; i++){
-		dest[i] = src[i];
-	}
-
-	if(i== ip_hdr->len){
-		/* return a 1! */
-		printf("Filled fragment %d from %d to %d.\n", ip_hdr->id, offset, offset + data_length);
-		return 1;
-	}
-
-	printf("Filled fragment %d from %d to %d.\n", ip_hdr->id, offset, offset+data_length);
-	printf("Still need %d to %d.\n", offset + data_length, ip_hdr->len);
-
-	return 0;
-}
-
-void remove_fragment(int index){
-	/* free ptr to data */
-
-	/* remove reference in table to fragment */
-	int i;
-	fragment *ptr;
-
-	ptr = frag_table->table + index;
-	
-	for(i=0; i< frag_table->len - index-1; i++){
-		*ptr = *(ptr + 1);
-		ptr += i;
+//calloc macro that exits on error
+void *ecalloc(size_t nmemb, size_t size){
+	void *ptr = calloc(nmemb, size);
+	if(ptr == NULL){
+		fprintf(stderr, "Memory failure. Exiting...\n");
+		exit(1);
 	}
-	frag_table->len --;
 
+	return ptr;
 }

+ 8 - 25
server/util.h

@@ -1,29 +1,12 @@
+/* until.h by Cecylia Bocovich <cbocovic@uwaterloo.ca>
+ *
+ * Macros and wrapper functions
+ */
+
 #ifndef _UTIL_H_
 #define _UTIL_H_
 
-#include <stdlib.h>
-
-#define MAX_FRAGMENTS 10
-
-/* Depreciated */
-
-typedef struct fragment_st {
-	u_char *data;
-	u_short ip_len; /* Length of complete packet */
-	u_short id; /* Length of the IPv4 ID number*/
-
-} fragment;
-
-typedef struct fragment_table_st {
-	fragment *table;
-	int len;
-	int max_len;
-} fragment_table;
-
-int report_fragment(const u_char *fragment, u_char *packet, u_int length);
-int init_fragment_table(void);
-int add_fragment(fragment new_fragment);
-void remove_fragment(int index);
-int update_fragment(int index, const u_char *data, u_int length);
+void *emalloc(size_t size);
+void *ecalloc(size_t nmemb, size_t size);
 
-#endif /* _UTIL_H_ */
+#endif /*_UTIL_H_*/