Browse Source

commiting memory fixes again

cecylia 8 years ago
parent
commit
7f7fedd11b
8 changed files with 209 additions and 627 deletions
  1. 22 4
      server/crypto.c
  2. 3 2
      server/crypto.h
  3. 112 67
      server/flow.c
  4. 6 1
      server/flow.h
  5. 58 545
      server/relay.c
  6. 1 2
      server/relay.h
  7. 6 4
      server/slitheen-proxy.c
  8. 1 2
      server/slitheen.h

+ 22 - 4
server/crypto.c

@@ -227,6 +227,8 @@ int verify_finish_hash(flow *f, uint8_t *p, int32_t incoming){
 		printf("VERIFY PASSED\n");
 	}
 
+	free(output);
+	EVP_MD_CTX_cleanup(&ctx);
 	return 0;
 }
 
@@ -260,7 +262,7 @@ int compute_master_secret(flow *f){
     uint8_t *buf = (uint8_t *)OPENSSL_malloc(bytes);
     if (buf == NULL){
         BNerr(BN_F_BNRAND, ERR_R_MALLOC_FAILURE);
-        return 1;
+		goto err;
     }
 
 	pub_key = BN_new();
@@ -285,7 +287,7 @@ int compute_master_secret(flow *f){
 //#endif
 
     if (!BN_bin2bn(buf, bytes, priv_key))
-		return 1;
+		goto err;
 
     {
         BIGNUM *prk;
@@ -293,8 +295,7 @@ int compute_master_secret(flow *f){
 		prk = priv_key;
 
         if (!dh_clnt->meth->bn_mod_exp(dh_clnt, pub_key, dh_clnt->g, prk, dh_clnt->p, ctx, mont)){
-			printf("FAIL\n");
-            return 1;
+			goto err;
 		}
     }
 
@@ -325,6 +326,16 @@ int compute_master_secret(flow *f){
 	//remove pre_master_secret from memory
 	memset(pre_master_secret, 0, PRE_MASTER_MAX_LEN);
 
+err:
+	if((pub_key != NULL) && (dh_srvr == NULL)){
+		BN_free(pub_key);
+	}
+	if((priv_key != NULL) && (dh_clnt == NULL)){
+		BN_free(priv_key);
+	}
+	BN_CTX_free(ctx);
+
+	OPENSSL_free(buf);
 	free(pre_master_secret);
 	DH_free(dh_srvr);
 	DH_free(dh_clnt);
@@ -440,6 +451,12 @@ int PRF(uint8_t *secret, int32_t secret_len,
 			remaining -= remaining;
 		}
 	}
+
+	EVP_PKEY_free(mac_key);
+	EVP_MD_CTX_cleanup(&ctx);
+	EVP_MD_CTX_cleanup(&ctx_tmp);
+	EVP_MD_CTX_cleanup(&ctx_init);
+	OPENSSL_cleanse(A, sizeof(A));
 	return 0;
 }
 
@@ -576,6 +593,7 @@ int init_ciphers(flow *f){
 	f->srvr_read_ctx = r_ctx_srvr;
 	f->srvr_write_ctx = w_ctx_srvr;
 
+	free(key_block);
 	return 0;
 }
 

+ 3 - 2
server/crypto.h

@@ -1,8 +1,9 @@
 #ifndef _CRYPTO_H_
 #define _CRYPTO_H_
+
 #include "flow.h"
 
-# define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
+#define n2s(c,s)        ((s=(((unsigned int)(c[0]))<< 8)| \
 							(((unsigned int)(c[1]))    )),c+=2)
 
 int extract_parameters(flow *f, uint8_t *hs);
@@ -28,4 +29,4 @@ void check_handshake(struct packet_info *info, flow f);
 #define SLITHEEN_KEYGEN_CONST "SLITHEEN_KEYGEN"
 #define SLITHEEN_KEYGEN_CONST_SIZE 15
 
-#endif /* _CRYPTO_H_ */
+#endif

+ 112 - 67
server/flow.c

@@ -3,6 +3,8 @@
 #include <stdint.h>
 #include <pthread.h>
 #include <errno.h>
+#include <semaphore.h>
+
 #include "flow.h"
 #include "crypto.h"
 #include "slitheen.h"
@@ -13,6 +15,8 @@ static session_cache *sessions;
 data_queue *downstream_queue;
 stream_table *streams;
 
+sem_t flow_table_lock;
+
 /* Initialize the table of tagged flows */
 int init_tables(void) {
 
@@ -20,6 +24,8 @@ int init_tables(void) {
 	table->first_entry = NULL;
 	table->len = 0;
 
+	sem_init(&flow_table_lock, 0, 1);
+
 	downstream_queue = calloc(1, sizeof(data_queue));
 	downstream_queue->first_block = NULL;
 	
@@ -40,6 +46,7 @@ flow *add_flow(flow newFlow) {
 
 	printf("there are %d flows in the table\n", table->len);
 
+	sem_init(&(newFlow.flow_lock), 0, 1);
 	newFlow.state = TLS_CLNT_HELLO;
 	newFlow.in_encrypted = 0;
 	newFlow.out_encrypted = 0;
@@ -47,7 +54,7 @@ flow *add_flow(flow newFlow) {
 	newFlow.resume_session = 0;
 	newFlow.current_session = NULL;
 	newFlow.packet_chain = NULL;
-	newFlow.censored_queue = NULL;
+	sem_init(&(newFlow.packet_chain_lock), 0, 1);
 	newFlow.upstream_queue = NULL;
 	newFlow.upstream_remaining = 0;
 	newFlow.outbox = NULL;
@@ -63,11 +70,17 @@ flow *add_flow(flow newFlow) {
 	const EVP_MD *md = EVP_sha384();
 	EVP_DigestInit_ex(newFlow.finish_md_ctx, md, NULL);
 
+	newFlow.clnt_read_ctx = NULL;
+	newFlow.clnt_write_ctx = NULL;
+	newFlow.srvr_read_ctx = NULL;
+	newFlow.srvr_write_ctx = NULL;
+
 	memset(newFlow.read_seq, 0, 8);
 	memset(newFlow.write_seq, 0, 8);
 
 	*ptr = newFlow;
 
+	sem_wait(&flow_table_lock);
 	flow_entry *last = table->first_entry;
 	if(last == NULL){
 		table->first_entry = entry;
@@ -78,6 +91,7 @@ flow *add_flow(flow newFlow) {
 		last->next = entry;
 	}
 	table->len ++;
+	sem_post(&flow_table_lock);
 
 	return ptr;
 }
@@ -96,17 +110,20 @@ int update_flow(flow *f) {
 	const struct record_header *record_hdr;
 	const struct handshake_header *handshake_hdr;
 
-	uint8_t *p = f->packet_chain->data;
+	sem_wait(&(f->packet_chain_lock));
 
+	if(f->packet_chain == NULL){
+		sem_post(&(f->packet_chain_lock));
+		return 0;
+	}
+	uint8_t *p = f->packet_chain->data;
 	record_hdr = (struct record_header*) p;
 	int record_len;
 	int data_len;
 
 	record_len = RECORD_LEN(record_hdr)+RECORD_HEADER_LEN;
 	data_len = f->packet_chain->data_len;
-	if(f->packet_chain == NULL){
-		return 0;
-	}
+
 	packet *current = f->packet_chain;
 	int incoming = current->incoming;
 	record = calloc(1, record_len);
@@ -117,13 +134,11 @@ int update_flow(flow *f) {
 
 	while(record_len > data_len) {
 		if(current->next == NULL){
-			free(record);
-			return 0;
+			goto err;
 		}
 		if(current->next->seq_num != current->seq_num + current->len){
 			printf("Missing packet: seq_num= %d, datalen= %d, nextseq= %d\n", current->seq_num, current->len, current->next->seq_num);
-			free(record);
-			return 0;
+			goto err;
 		}
 
 		current = current->next;
@@ -266,29 +281,53 @@ int update_flow(flow *f) {
 			printf("Error: Not a Record (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
 			fflush(stdout);
 			//TODO: later figure this out, for now delete
+			packet *tmp = f->packet_chain;
 			f->packet_chain = f->packet_chain->next;
-
+			free(tmp->data);
+			free(tmp);
+			
 			if( f->packet_chain != NULL){
+				sem_post(&(f->packet_chain_lock));
+				free(record);
 				update_flow(f);
+				return 0;
 			}
-			return 0;
+			goto err;
 	}
 
-	if(!f->application){
-	f->seq_num = current->seq_num;
-
-	if(record_len == data_len){
-		/* record ended on packet boundary */
-		f->packet_chain = current->next;
-	} else {
-		/* need to update data */
-		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);
-	}
-	}
+	//if(!f->application){
+		f->seq_num = current->seq_num;
+
+		if(record_len == data_len){
+			/* record ended on packet boundary */
+			current = current->next;
+			packet *tmp = f->packet_chain;
+			while(tmp != current){
+				f->packet_chain = tmp->next;
+				free(tmp->data);
+				free(tmp);
+				tmp = f->packet_chain;
+			}
+		} else {
+			/* need to update data */
+			packet *tmp = f->packet_chain;
+			while(tmp != current){
+				f->packet_chain = tmp->next;
+				free(tmp->data);
+				free(tmp);
+				tmp = f->packet_chain;
+			}
+			memmove(current->data, current->data + (current->data_len - (data_len - record_len)), data_len - record_len);
+			current->data_len = data_len - record_len;
+			sem_post(&(f->packet_chain_lock));
+			free(record);
+			update_flow(f);
+			return 0;
+		}
+	//}
 
+err:
+	sem_post(&(f->packet_chain_lock));
 	free(record);
 	return 0;
 }
@@ -304,6 +343,22 @@ int update_flow(flow *f) {
  */
 int remove_flow(flow *f) {
 
+	EVP_MD_CTX_destroy(f->finish_md_ctx);
+	//Clean up cipher ctxs
+	if(f->clnt_read_ctx != NULL){
+		EVP_CIPHER_CTX_free(f->clnt_read_ctx);
+	}
+	if(f->clnt_write_ctx != NULL){
+		EVP_CIPHER_CTX_free(f->clnt_write_ctx);
+	}
+	if(f->srvr_read_ctx != NULL){
+		EVP_CIPHER_CTX_free(f->srvr_read_ctx);
+	}
+	if(f->srvr_write_ctx != NULL){
+		EVP_CIPHER_CTX_free(f->srvr_write_ctx);
+	}
+
+	sem_wait(&flow_table_lock);
 	flow_entry *entry = table->first_entry;
 	if(entry->f == f){
 		table->first_entry = entry->next;
@@ -312,31 +367,31 @@ int remove_flow(flow *f) {
 		printf("flow removed!\n");
 		fflush(stdout);
 		table->len --;
-		return 0;
-	}
+	} else {
 
-	flow_entry *next;
-	for(int i=0; i< table->len; i++){
-		if(entry->next != NULL){
-			next = entry->next;
-		} else {
-			printf("Flow not in table\n");
-			return 1;
-		}
+		flow_entry *next;
+		for(int i=0; i< table->len; i++){
+			if(entry->next != NULL){
+				next = entry->next;
+			} else {
+				printf("Flow not in table\n");
+				break;
+			}
 
-		if(next->f == f){
-			entry->next = next->next;
-			free(next->f);
-			free(next);
-			printf("flow removed!\n");
-			table->len --;
-			return 0;
-		}
+			if(next->f == f){
+				entry->next = next->next;
+				free(next->f);
+				free(next);
+				printf("flow removed!\n");
+				table->len --;
+				break;
+			}
 
-		entry = next;
+			entry = next;
+		}
 	}
+	sem_post(&flow_table_lock);
 
-	printf("Should not get here!\n");
 	return 1;
 }
 
@@ -361,9 +416,11 @@ flow *check_flow(flow observed){
 	int i;
 	flow_entry *entry = table->first_entry;
 	flow *candidate;
+	flow *found = NULL;
 	if(entry == NULL)
 		return NULL;
 
+	sem_wait(&flow_table_lock);
 	/* Check first in this direction */
 	for(i=0; i<table->len; i++){
 		if(entry == NULL){
@@ -375,7 +432,7 @@ flow *check_flow(flow observed){
 			if(candidate->dst_ip.s_addr == observed.dst_ip.s_addr){
 				if(candidate->src_port == observed.src_port){
 					if(candidate->dst_port == observed.dst_port){
-						return candidate;
+						found = candidate;
 					}
 				}
 			}
@@ -396,32 +453,17 @@ flow *check_flow(flow observed){
 			if(candidate->dst_ip.s_addr == observed.src_ip.s_addr){
 				if(candidate->src_port == observed.dst_port){
 					if(candidate->dst_port == observed.src_port){
-						return candidate;
+						found = candidate;
 					}
 				}
 			}
 		}
 		entry = entry->next;
 	}
+	sem_post(&flow_table_lock);
 
-	return NULL;
-}
-
-/** Returns the flow in the flow table at a specified index
- *
- *  Input:
- *  	index: the desired index of the flow table
- *
- *  Output:
- *  	the flow at the specified index
-flow *get_flow(int index){
-	if(index < table->len){
-		return table->table+index;
-	} else {
-		return NULL;
-	}
+	return found;
 }
- */
 
 int init_session_cache(void){
 	sessions = malloc(sizeof(session_cache));
@@ -692,15 +734,18 @@ int save_session_ticket(flow *f, uint8_t *hs, uint32_t len){
 
 /* Adds a packet the flow's packet chain */
 int add_packet(flow *f, struct packet_info *info){
-	packet *new_packet = malloc(sizeof(packet));
-
 	if (info->tcp_hdr == NULL){
 		return 0;
 	}
 
+	packet *new_packet = calloc(1, sizeof(packet));
 	new_packet->seq_num = htonl(info->tcp_hdr->sequence_num);
 	new_packet->len = info->app_data_len;
-	new_packet->data = info->app_data;
+
+	uint8_t *packet_data = calloc(1, new_packet->len);
+	memcpy(packet_data, info->app_data, new_packet->len);
+
+	new_packet->data = packet_data;
 	new_packet->data_len = new_packet->len;
 	new_packet->next = NULL;
 	new_packet->incoming = 

+ 6 - 1
server/flow.h

@@ -2,6 +2,7 @@
 #define __RELAY_H__
 
 #include <netinet/in.h>
+#include <semaphore.h>
 #include <openssl/bn.h>
 #include <openssl/ssl.h>
 #include "ptwist.h"
@@ -63,6 +64,8 @@ typedef struct session_cache_st {
 } session_cache;
 
 typedef struct flow_st {
+	sem_t flow_lock;
+
 	struct in_addr src_ip, dst_ip; /* Source (client) and Destination (server) addresses */
 	uint16_t src_port, dst_port;	/* Source and Destination ports */
 
@@ -74,8 +77,10 @@ typedef struct flow_st {
 	int out_encrypted;		/* indicates whether outgoing flow is encrypted */
 	int application; /* indicates handshake is complete */
 	int resume_session;
+
 	packet *packet_chain; /* currently held data */
-	queue_block *censored_queue;
+	sem_t packet_chain_lock;
+
 	queue_block *upstream_queue;
 	uint32_t upstream_remaining;
 	DH *dh;

File diff suppressed because it is too large
+ 58 - 545
server/relay.c


+ 1 - 2
server/relay.h

@@ -5,7 +5,6 @@
 #include <stdint.h>
 
 struct proxy_thread_data {
-	flow *f;
 	uint8_t *initial_data;
 	uint16_t initial_len;
 	uint8_t stream_id;
@@ -40,7 +39,7 @@ int replace_packet(flow *f, struct packet_info *info);
 int process_downstream(flow *f, int32_t offset, struct packet_info *info);
 int read_header(flow *f, struct packet_info *info);
 uint32_t get_response_length(uint8_t *response);
-int fill_with_downstream(flow *f, uint8_t *data, int32_t length);
+int fill_with_downstream(uint8_t *data, int32_t length);
 uint16_t tcp_checksum(struct packet_info *info);
 
 void *proxy_covert_site(void *data);

+ 6 - 4
server/slitheen-proxy.c

@@ -32,8 +32,8 @@ int main(int argc, char *argv[]){
 	dev1 = argv[1];
 	dev2 = argv[2];
 
-	snprintf(filter1, 33, "ether src host %s", macaddr1);
-	snprintf(filter2, 33, "ether src host %s", macaddr2);
+	snprintf(filter1, 33, "ether src host %s", macaddr);
+	snprintf(filter2, 33, "ether dst host %s", macaddr);
 
 	init_tables();
 	init_session_cache();
@@ -50,7 +50,9 @@ int main(int argc, char *argv[]){
 
 	pthread_join(t1, NULL);
 	pthread_join(t2, NULL);
-	
+
+	pthread_exit(NULL);
+
 	return(0);
 }
 
@@ -133,6 +135,7 @@ end:
 	}
 	fprintf(stderr, "\n");
 #endif
+	free(tmp_packet);
 
 }
 
@@ -142,7 +145,6 @@ end:
  * 	3) updates the flow's state
  */
 void process_packet(struct packet_info *info){
-	int index;
 
 	flow newFlow;
 

+ 1 - 2
server/slitheen.h

@@ -4,8 +4,7 @@
 #include <netinet/in.h>
 #include <pcap.h>
 
-#define macaddr1 "00:25:90:5a:26:99"
-#define macaddr2 "00:25:90:c9:5a:09"
+#define macaddr "08:00:27:0e:89:ea"
 
 /* Ethernet addresses are 6 bytes */
 #define ETHER_ADDR_LEN	6

Some files were not shown because too many files changed in this diff