Преглед изворни кода

added Slitheen ID functionality

cecylia пре 8 година
родитељ
комит
1110af0d6d
6 измењених фајлова са 144 додато и 46 уклоњено
  1. 1 0
      server/crypto.c
  2. 16 16
      server/flow.c
  3. 13 2
      server/flow.h
  4. 93 18
      server/relay.c
  5. 13 10
      server/relay.h
  6. 8 0
      server/slitheen-proxy.c

+ 1 - 0
server/crypto.c

@@ -1056,3 +1056,4 @@ void check_handshake(struct packet_info *info){
 		}
 	}
 }
+

+ 16 - 16
server/flow.c

@@ -13,7 +13,7 @@
 static flow_table *table;
 static session_cache *sessions;
 data_queue *downstream_queue;
-stream_table *streams;
+client_table *clients;
 
 sem_t flow_table_lock;
 
@@ -26,11 +26,8 @@ int init_tables(void) {
 
 	sem_init(&flow_table_lock, 0, 1);
 
-	downstream_queue = calloc(1, sizeof(data_queue));
-	downstream_queue->first_block = NULL;
-	
-	streams = calloc(1, sizeof(stream_table));
-	streams->first = NULL;
+	clients = calloc(1, sizeof(client_table));
+	clients->first = NULL;
 	printf("initialized downstream queue\n");
 
 	return 0;
@@ -54,6 +51,9 @@ flow *add_flow(struct packet_info *info) {
 	new_flow->upstream_seq_num = ntohl(info->tcp_hdr->sequence_num);
 	new_flow->downstream_seq_num = 0;
 
+	new_flow->streams=NULL;
+	new_flow->downstream_queue=NULL;
+
 	sem_init(&(new_flow->flow_lock), 0, 1);
 	new_flow->state = TLS_CLNT_HELLO;
 	new_flow->in_encrypted = 0;
@@ -173,12 +173,12 @@ int update_flow(flow *f) {
 			p += RECORD_HEADER_LEN;
 
 			if((incoming && f->in_encrypted) || (!incoming && f->out_encrypted)){
-				printf("Decrypting finished (%d bytes) (%x:%d -> %x:%d)\n", record_len - RECORD_HEADER_LEN, f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+				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));
 				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, f->src_port, f->dst_ip.s_addr, f->dst_port);
+					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));
 				}
-				printf("Finished decrypted: (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+				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));
 				p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 				
 				printf("record:\n");
@@ -199,12 +199,12 @@ int update_flow(flow *f) {
 
 			switch(f->state){
 				case TLS_CLNT_HELLO: 
-					printf("Received tagged client hello (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+					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));
 					break;
 				case TLS_SERV_HELLO:
-					printf("Received server hello (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+					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));
 					if(f->resume_session){
 						verify_session_id(f,p);
 					} else {
@@ -249,7 +249,7 @@ int update_flow(flow *f) {
 					update_finish_hash(f, p);
 					break;
 				case TLS_FINISHED:
-					printf("Received finished (%x:%d -> %x:%d)\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+					printf("Received finished (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
 					verify_finish_hash(f,p, incoming);
 					update_finish_hash(f, p);
 					if((f->in_encrypted == 2) && (f->out_encrypted == 2)){
@@ -270,7 +270,7 @@ int update_flow(flow *f) {
 					}
 					break;
 				default:
-					printf("Error? (%x:%d -> %x:%d)...\n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+					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));
 					break;
 			}
 			break;
@@ -278,7 +278,7 @@ int update_flow(flow *f) {
 			printf("Application Data\n");
 			break;
 		case CCS:
-			printf("CCS (%x:%d -> %x:%d) \n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port);
+			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));
 			/*Initialize ciphers */
 			if ((!f->in_encrypted) && (!f->out_encrypted)){
 				init_ciphers(f);
@@ -298,14 +298,14 @@ int update_flow(flow *f) {
 				encrypt(f, p, p, record_len - RECORD_HEADER_LEN, incoming, 0x16, 0);
 				p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
 			}
-			printf("Alert (%x:%d -> %x:%d) %02x %02x \n", f->src_ip.s_addr, f->src_port, f->dst_ip.s_addr, f->dst_port, p[0], p[1]);
+			printf("Alert (%x:%d -> %x:%d) %02x %02x \n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port), p[0], p[1]);
 			fflush(stdout);
 			break;
 		case HB:
 			printf("Heartbeat\n");
 			break;
 		default:
-			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);
+			printf("Error: Not a Record (%x:%d -> %x:%d)\n", f->src_ip.s_addr, ntohs(f->src_port), f->dst_ip.s_addr, ntohs(f->dst_port));
 			fflush(stdout);
 			//TODO: later figure this out, for now delete
 			packet *tmp = f->packet_chain;

+ 13 - 2
server/flow.h

@@ -9,6 +9,7 @@
 #include "slitheen.h"
 
 #define MAX_FLOWS 10
+#define SLITHEEN_ID_LEN 10
 
 #define TLS_HELLO_REQ 0x00
 #define TLS_CLNT_HELLO 0x01
@@ -22,6 +23,16 @@
 #define TLS_CLNT_KEYEX 0x10
 #define TLS_FINISHED 0x14
 
+typedef struct stream_st {
+	uint8_t stream_id;
+	int32_t pipefd;
+	struct stream_st *next;
+} stream;
+
+typedef struct stream_table_st {
+	stream *first;
+} stream_table;
+
 struct packet_st{
 	uint32_t seq_num;
 	uint16_t len;
@@ -43,8 +54,6 @@ typedef struct data_queue_st {
 	queue_block *first_block;
 } data_queue;
 
-extern data_queue *downstream_queue;
-
 typedef struct packet_st packet;
 
 typedef struct session_st {
@@ -78,6 +87,8 @@ typedef struct flow_st {
 	int out_encrypted;		/* indicates whether outgoing flow is encrypted */
 	int application; /* indicates handshake is complete */
 	int resume_session;
+	stream_table *streams;
+	data_queue *downstream_queue;
 
 	packet *packet_chain; /* currently held data */
 	sem_t packet_chain_lock;

+ 93 - 18
server/relay.c

@@ -39,10 +39,11 @@ int replace_packet(flow *f, struct packet_info *info){
 	}
 
 #ifdef DEBUG
-	fprintf(stdout,"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(stdout,"Flow: %x:%d > %x:%d (%s)\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), (info->ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
 	fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
 	fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
 	fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
+	fflush(stdout);
 #endif
 
 	if(info->app_data_len <= 0){
@@ -212,7 +213,7 @@ int read_header(flow *f, struct packet_info *info){
 	}
 
 #ifdef DEBUG
-	printf("Upstream data: (%x:%d > %x:%d )\n",info->ip_hdr->src.s_addr,info->tcp_hdr->src_port, info->ip_hdr->dst.s_addr, info->tcp_hdr->dst_port);
+	printf("Upstream data: (%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));
 	printf("%s\n", decrypted_data+EVP_GCM_TLS_EXPLICIT_IV_LEN);
 #endif
 
@@ -233,11 +234,17 @@ int read_header(flow *f, struct packet_info *info){
 #ifdef DEBUG
 	printf("UPSTREAM: Found x-slitheen header\n");
 	fflush(stdout);
-	fprintf(stdout,"UPSTREAM Flow: %x:%d > %x:%d (%s)\n", info->ip_hdr->src.s_addr,info->tcp_hdr->src_port, info->ip_hdr->dst.s_addr, info->tcp_hdr->dst_port,(info->ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
+	fprintf(stdout,"UPSTREAM Flow: %x:%d > %x:%d (%s)\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) ,(info->ip_hdr->src.s_addr != f->src_ip.s_addr)? "incoming":"outgoing");
 	fprintf(stdout, "Sequence number: %d\n", ntohs(info->tcp_hdr->sequence_num));
 #endif
 
 	header_ptr += strlen("X-Slitheen: ");
+	
+	if(*header_ptr == '\r' || *header_ptr == '\0'){
+		printf("No messages\n");
+		return 0;
+	}
+	
 	int32_t num_messages = 1;
 	char *messages[50]; //TODO:make not just 10?
 	messages[0] = header_ptr;
@@ -282,15 +289,77 @@ int read_header(flow *f, struct packet_info *info){
 
 #ifdef DEBUG
 		printf("Decoded to get %d bytes:\n", output_len);
-		for(int i=0; i< output_len; i++){
-			printf("%02x ", upstream_data[i]);
+		for(int j=0; j< output_len; j++){
+			printf("%02x ", upstream_data[j]);
 		}
 		printf("\n");
 		fflush(stdout);
 #endif
-
 		p = upstream_data;
 
+		if(i== 0){
+			//this is the Slitheen ID
+			printf("Slitheen ID:");
+			for(int j=0; j< output_len; j++){
+				printf("%02x ", p[j]);
+			}
+			printf("\n");
+
+			//find stream table or create new one
+
+			client *last = clients->first;
+			while(last != NULL){
+				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;
+				} else {
+					for(int j=0; j< output_len; j++){
+						printf("%02x ", last->slitheen_id[j]);
+					}
+					printf(" != ");
+					for(int j=0; j< output_len; j++){
+						printf("%02x ", p[j]);
+					}
+					printf("\n");
+				}
+				last = last->next;
+			}
+
+			if(f->streams == NULL){
+				printf("Making new client\n");
+				//create new client
+				client *new_client = calloc(1, sizeof(client));
+				memcpy(new_client->slitheen_id, p, output_len);
+				new_client->streams = calloc(1, sizeof(stream_table));
+				new_client->streams->first = NULL;
+				new_client->downstream_queue = calloc(1, sizeof(data_queue));
+				new_client->downstream_queue->first_block = NULL;
+	
+				new_client->next = NULL;
+
+				//add to client table
+				if(clients->first == NULL){
+					clients->first = new_client;
+				} else {
+					client *last = clients->first;
+					while(last->next != NULL){
+						last = last->next;
+					}
+					last->next = new_client;
+				}
+				
+				//set f's stream table
+				f->streams = new_client->streams;
+				f->downstream_queue = new_client->downstream_queue;
+
+			}
+
+			free(upstream_data);
+			continue;
+		}
+
 		while(output_len > 0){
 			struct sl_up_hdr *sl_hdr = (struct sl_up_hdr *) p;
 			uint8_t stream_id = sl_hdr->stream_id;
@@ -299,6 +368,7 @@ int read_header(flow *f, struct packet_info *info){
 			p += sizeof(struct sl_up_hdr);
 			output_len -= sizeof(struct sl_up_hdr);
 
+			stream_table *streams = f->streams;
 
 			//If a thread for this stream id exists, get the thread info and pipe data
 			int32_t stream_pipe = -1;
@@ -356,7 +426,8 @@ int read_header(flow *f, struct packet_info *info){
 				thread_data->initial_len = stream_len;
 				thread_data->stream_id = stream_id;
 				thread_data->pipefd = pipefd[0];
-				
+				thread_data->streams = f->streams;
+				thread_data->downstream_queue = f->downstream_queue;
 				
 				pthread_create(&proxy_thread, NULL, proxy_covert_site, (void *) thread_data);
 
@@ -423,6 +494,9 @@ void *proxy_covert_site(void *data){
 
 	int32_t bytes_sent;
 
+	stream_table *streams = thread_data->streams;
+	data_queue *downstream_queue = thread_data->downstream_queue;
+
 	struct socks_req *clnt_req = (struct socks_req *) p;
 	p += 4;
 	data_len -= 4;
@@ -661,7 +735,7 @@ void *proxy_covert_site(void *data){
 	pthread_exit(NULL);
 	return 0;
 err:
-	//remove self from list 
+	//remove self from list
 	last = streams->first;
 	prev = last;
 	if(streams->first != NULL){
@@ -803,7 +877,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 					f->outbox = calloc(1, record_len+1);
 					f->outbox_len = record_len;
 					f->outbox_offset = 0;
-					fill_with_downstream(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
+					fill_with_downstream(f, f->outbox + EVP_GCM_TLS_EXPLICIT_IV_LEN , record_len - (EVP_GCM_TLS_EXPLICIT_IV_LEN+ 16)); //for now hard coded length of padding. TODO: fix this
 					//encrypt
 					int32_t n = encrypt(f, f->outbox, f->outbox,
 									record_len - 16, 1,
@@ -843,7 +917,6 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 
 
 		//now decrypt the record
-		printf("Decrypting %d bytes at %p\n", record_len, record_ptr);
 		int32_t n = encrypt(f, record_ptr, record_ptr, record_len, 1,
 						record_hdr->type, 0);
 		if(n < 0){
@@ -856,7 +929,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 		}
 		changed = 1;
 
-#ifdef DEBUG
+#ifdef DEBUG_DOWNSTREAM
 		printf("Decryption succeeded\n");
 		printf("Bytes:\n");
 		for(int i=0; i< n; i++){
@@ -934,7 +1007,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 					//check if content is replaceable
 					if(f->remaining_response_len > remaining_record_len){
 						if(f->replace_response){
-							fill_with_downstream(p, remaining_record_len);
+							fill_with_downstream(f, p, remaining_record_len);
 
 #ifdef DEBUG
 							printf("Replaced with:\n");
@@ -951,7 +1024,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						remaining_record_len = 0;
 					} else {
 						if(f->replace_response){
-							fill_with_downstream(p, remaining_record_len);
+							fill_with_downstream(f, p, remaining_record_len);
 
 #ifdef DEBUG
 							printf("Replaced with:\n");
@@ -992,7 +1065,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 				case MID_CHUNK:
 					if(f->remaining_response_len > remaining_record_len){
 						if(f->replace_response){
-							fill_with_downstream(p, remaining_record_len);
+							fill_with_downstream(f, p, remaining_record_len);
 
 #ifdef DEBUG
 							printf("Replaced with:\n");
@@ -1008,7 +1081,7 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
 						remaining_record_len = 0;
 					} else {
 						if(f->replace_response){
-							fill_with_downstream(p, f->remaining_response_len);
+							fill_with_downstream(f, p, f->remaining_response_len);
 
 #ifdef DEBUG
 							printf("Replaced with:\n");
@@ -1099,12 +1172,14 @@ int process_downstream(flow *f, int32_t offset, struct packet_info *info){
  *
  */
 
-int fill_with_downstream(uint8_t *data, int32_t length){
+int fill_with_downstream(flow *f, uint8_t *data, int32_t length){
 
 	uint8_t *p = data;
 	int32_t remaining = length;
 	struct slitheen_header *sl_hdr;
 
+	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){
 		queue_block *first_block = downstream_queue->first_block;
@@ -1145,7 +1220,7 @@ int fill_with_downstream(uint8_t *data, int32_t length){
 		}
 		sl_hdr->len = htons(sl_hdr->len);
 
-//#ifdef DEBUG
+#ifdef DEBUG
 		printf("DWNSTRM: slitheen header: ");
 		for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
 			printf("%02x ",((uint8_t *) sl_hdr)[i]);
@@ -1156,7 +1231,7 @@ int fill_with_downstream(uint8_t *data, int32_t length){
 			printf("%02x ", ((uint8_t *) sl_hdr)[i+SLITHEEN_HEADER_LEN]);
 		}
 		printf("\n");
-//#endif
+#endif
 	}
 	//now, if we need more data, fill with garbage
 	if(remaining > SLITHEEN_HEADER_LEN ){

+ 13 - 10
server/relay.h

@@ -9,19 +9,22 @@ struct proxy_thread_data {
 	uint16_t initial_len;
 	uint8_t stream_id;
 	int32_t pipefd;
+	stream_table *streams;
+	data_queue *downstream_queue;
 };
 
-typedef struct stream_st {
-	uint8_t stream_id;
-	int32_t pipefd;
-	struct stream_st *next;
-} stream;
+typedef struct client_st {
+	uint8_t slitheen_id[SLITHEEN_ID_LEN];
+	stream_table *streams;
+	data_queue *downstream_queue;
+	struct client_st *next;
+} client;
 
-typedef struct stream_table_st {
-	stream *first;
-} stream_table;
+typedef struct client_table_st {
+	client *first;
+} client_table;
 
-extern stream_table *streams;
+extern client_table *clients;
 
 struct socks_req {
 	uint8_t version;
@@ -39,7 +42,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(uint8_t *data, int32_t length);
+int fill_with_downstream(flow *f, uint8_t *data, int32_t length);
 uint16_t tcp_checksum(struct packet_info *info);
 
 void *proxy_covert_site(void *data);

+ 8 - 0
server/slitheen-proxy.c

@@ -142,6 +142,14 @@ end:
 	}
 	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));
+	fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
+	fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
+	fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
+	fflush(stdout);
+	}
 	free(tmp_packet);
 
 }