slitheen-proxy.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532
  1. /* Name: slitheen-proxy.c
  2. * Author: Cecylia Bocovich
  3. *
  4. * This code runs the main functions for the Slitheen relay station to tap and
  5. * modify data.
  6. *
  7. */
  8. #include <pcap.h>
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <unistd.h>
  12. #include <string.h>
  13. #include <pthread.h>
  14. #include <openssl/ssl.h>
  15. #include "util.h"
  16. #include "flow.h"
  17. #include "slitheen.h"
  18. #include "relay.h"
  19. #include "crypto.h"
  20. #include "cryptothread.h"
  21. void usage(void){
  22. printf("Usage: slitheen-proxy [internal network interface] [NAT interface]\n");
  23. }
  24. int main(int argc, char *argv[]){
  25. pthread_t t1, t2;
  26. char *dev1 = NULL; /* Device that leads to the internal network */
  27. char *dev2 = NULL; /* Device that leads out to the world */
  28. struct sniff_args outbound;
  29. struct sniff_args inbound;
  30. if (argc != 3) {
  31. usage();
  32. return(2);
  33. }
  34. dev1 = argv[1];
  35. dev2 = argv[2];
  36. if(init_tables()){
  37. exit(1);
  38. }
  39. if(init_session_cache()){
  40. exit(1);
  41. }
  42. init_crypto_locks();
  43. /* Create threads */
  44. outbound.readdev = dev1;
  45. outbound.writedev = dev2;
  46. inbound.readdev = dev2;
  47. inbound.writedev = dev1;
  48. pthread_create(&t1, NULL, sniff_packets, (void *) &outbound);
  49. pthread_create(&t2, NULL, sniff_packets, (void *) &inbound);
  50. pthread_join(t1, NULL);
  51. pthread_join(t2, NULL);
  52. pthread_exit(NULL);
  53. crypto_locks_cleanup();
  54. return(0);
  55. }
  56. void *sniff_packets(void *args){
  57. pcap_t *rd_handle;
  58. pcap_t *wr_handle;
  59. char rd_errbuf[BUFSIZ];
  60. char wr_errbuf[BUFSIZ];
  61. bpf_u_int32 mask;
  62. bpf_u_int32 net;
  63. char *readdev, *writedev;
  64. struct sniff_args *arg_st = (struct sniff_args *) args;
  65. readdev = arg_st->readdev;
  66. writedev = arg_st->writedev;
  67. if (pcap_lookupnet(readdev, &net, &mask, rd_errbuf) == -1){
  68. fprintf(stderr, "Can't get netmask for device %s\n", readdev);
  69. exit(2);
  70. }
  71. rd_handle = pcap_open_live(readdev, BUFSIZ, 1, 0, rd_errbuf);
  72. if (rd_handle == NULL){
  73. fprintf(stderr, "Couldn't open device %s: %s\n", readdev, rd_errbuf);
  74. }
  75. if(pcap_datalink(rd_handle) != DLT_EN10MB) {
  76. fprintf(stderr, "Device %s does not provide Ethernet headers - not supported\n", readdev);
  77. exit(2);
  78. }
  79. if(pcap_setdirection(rd_handle, PCAP_D_IN)){
  80. fprintf(stderr, "Platform does not support write direction. Update filters with MAC address\n");
  81. exit(2);
  82. }
  83. wr_handle = pcap_open_live(writedev, BUFSIZ, 1, 0, wr_errbuf);
  84. if (wr_handle == NULL){
  85. fprintf(stderr, "Couldn't open device %s: %s\n", writedev, wr_errbuf);
  86. }
  87. /*callback function*/
  88. pcap_loop(rd_handle, -1, got_packet, (unsigned char *) wr_handle);
  89. /*Sniff a packet*/
  90. pcap_close(rd_handle);
  91. return NULL;
  92. }
  93. /**
  94. * Runs when pcap_loop receives a packet from the specified interface
  95. * If the received packet is a tcp packet, processes it and then writes it back out
  96. * to the interface
  97. *
  98. */
  99. void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *packet){
  100. pcap_t *handle = (pcap_t *) args;
  101. struct packet_info *info = emalloc(sizeof(struct packet_info));
  102. uint8_t *tmp_packet = emalloc(header->len);
  103. //printf("Allocated %d bytes to %p\n", header->len, tmp_packet);
  104. memcpy(tmp_packet, packet, header->len);
  105. extract_packet_headers(tmp_packet, info);
  106. // Check to make sure it is a TCP packet
  107. if((info->ip_hdr == NULL) || (info->tcp_hdr == NULL))
  108. goto end;
  109. process_packet(info);
  110. end:
  111. if((pcap_inject(handle, tmp_packet, header->len)) < 0 ){
  112. fprintf(stderr, "Error: %s\n", pcap_geterr(handle));
  113. }
  114. #ifdef DEBUG
  115. fprintf(stderr, "injected the following packet:\n");
  116. for(int i=0; i< header->len; i++){
  117. fprintf(stderr, "%02x ", packet[i]);
  118. }
  119. fprintf(stderr, "\n");
  120. if((info->tcp_hdr != NULL) && (info->ip_hdr != NULL)){
  121. 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));
  122. fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
  123. fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
  124. fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
  125. fflush(stdout);
  126. }
  127. #endif
  128. free(info);//Note: don't free this while a thread is using it
  129. free(tmp_packet);
  130. }
  131. /* This function receives a full ip packet and then:
  132. * 1) identifies the flow
  133. * 2) adds the packet to the flow's data chain
  134. * 3) updates the flow's state
  135. */
  136. void process_packet(struct packet_info *info){
  137. /* Checks to see if this is a possibly tagged hello msg */
  138. if ((info->record_hdr != NULL) && (info->record_hdr->type == HS)){ /* This is a TLS handshake */
  139. check_handshake(info);
  140. }
  141. /* Now if flow is in table, update state */
  142. flow *observed;
  143. if((observed = check_flow(info)) != NULL){
  144. #ifdef DEBUG
  145. /*Check sequence number and replay application data if necessary*/
  146. 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 != observed->src_ip.s_addr)? "incoming":"outgoing");
  147. fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
  148. fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
  149. fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
  150. #endif
  151. uint8_t incoming = (info->ip_hdr->src.s_addr != observed->src_ip.s_addr)? 1 : 0;
  152. uint32_t seq_num = htonl(info->tcp_hdr->sequence_num);
  153. uint32_t expected_seq = (incoming)? observed->downstream_seq_num : observed->upstream_seq_num;
  154. #ifdef DEBUG
  155. fprintf(stdout,"Expected sequence number: %u\n", expected_seq);
  156. #endif
  157. /* Remove acknknowledged data from queue after TCP window is exceeded */
  158. uint32_t ack_num = htonl(info->tcp_hdr->ack_num);
  159. uint32_t end_seq = seq_num + info->app_data_len - 1;
  160. uint32_t window = ack_num + htons(info->tcp_hdr->win_size);
  161. #ifdef DEBUG
  162. printf("Received sequence number %u\n", seq_num);
  163. printf("Acknowledged up to %u with window expiring at %u\n", ack_num, window);
  164. printf("Removing all packets up to %u\n", end_seq);
  165. #endif
  166. packet *saved_data = (incoming)? observed->downstream_app_data->first_packet :
  167. observed->upstream_app_data->first_packet;
  168. while((saved_data != NULL) && (saved_data->expiration != 0) && (end_seq > saved_data->expiration)){
  169. //remove entire block
  170. if(incoming){
  171. observed->downstream_app_data->first_packet = saved_data->next;
  172. } else {
  173. observed->upstream_app_data->first_packet = saved_data->next;
  174. }
  175. free(saved_data->data);
  176. free(saved_data);
  177. saved_data = (incoming)? observed->downstream_app_data->first_packet :
  178. observed->upstream_app_data->first_packet;
  179. #ifdef DEBUG
  180. if(saved_data != NULL){
  181. printf("Currently saved seq_num is now %u\n", saved_data->seq_num);
  182. } else {
  183. printf("Acked all data, queue is empty\n");
  184. }
  185. #endif
  186. }
  187. /* Update expiration for packets based on TCP window size */
  188. saved_data = (incoming)? observed->upstream_app_data->first_packet :
  189. observed->downstream_app_data->first_packet;
  190. while((saved_data != NULL) && (ack_num > saved_data->seq_num)){
  191. //update window
  192. if(ack_num >= saved_data->seq_num + saved_data->len){
  193. //remove entire block
  194. saved_data->expiration = window;
  195. }
  196. saved_data = saved_data->next;
  197. }
  198. //fill with retransmit data, process new data
  199. uint32_t data_to_fill;
  200. uint32_t data_to_process;
  201. if(seq_num > expected_seq){
  202. data_to_process = info->app_data_len;
  203. data_to_fill = 0;
  204. } else if (seq_num + info->app_data_len > expected_seq){
  205. data_to_fill = expected_seq - seq_num;
  206. data_to_process = seq_num + info->app_data_len - expected_seq;
  207. } else {
  208. data_to_fill = info->app_data_len;
  209. data_to_process = 0;
  210. }
  211. uint8_t *p = info->app_data;
  212. if(data_to_fill){ //retransmit
  213. packet *saved_data = (incoming)? observed->downstream_app_data->first_packet :
  214. observed->upstream_app_data->first_packet;
  215. while(data_to_fill > 0){
  216. if(saved_data == NULL){
  217. //have already acked all data
  218. p += data_to_fill;
  219. seq_num += data_to_fill;
  220. data_to_fill -= data_to_fill;
  221. continue;
  222. }
  223. if(seq_num < saved_data->seq_num){
  224. //we are missing a block. Use what was given
  225. if(saved_data->seq_num - seq_num > data_to_fill){
  226. //skip the rest
  227. p += data_to_fill;
  228. seq_num += data_to_fill;
  229. data_to_fill -= data_to_fill;
  230. } else {
  231. p += saved_data->seq_num - seq_num;
  232. data_to_fill -= saved_data->seq_num - seq_num;
  233. seq_num += saved_data->seq_num - seq_num;
  234. }
  235. } else if ( seq_num == saved_data->seq_num) {
  236. if(data_to_fill >= saved_data->len){
  237. //exhaust this block and move onto next one
  238. memcpy(p, saved_data->data, saved_data->len);
  239. p += saved_data->len;
  240. seq_num += saved_data->len;
  241. data_to_fill -= saved_data->len;
  242. saved_data = saved_data->next;
  243. } else {
  244. //fill with partial block
  245. memcpy(p, saved_data->data, data_to_fill);
  246. p += data_to_fill;
  247. seq_num += data_to_fill;
  248. data_to_fill -= data_to_fill;
  249. }
  250. } else { //seq_num > saved_data->seq_num
  251. uint32_t offset = seq_num - saved_data->seq_num;
  252. if(offset > saved_data->len){
  253. saved_data = saved_data->next;
  254. offset -= saved_data->len;
  255. } else {
  256. if(data_to_fill > saved_data->len - offset){
  257. memcpy(p, saved_data->data + offset, saved_data->len - offset);
  258. p += saved_data->len - offset;
  259. seq_num += saved_data->len - offset;
  260. data_to_fill -= saved_data->len - offset;
  261. saved_data = saved_data->next;
  262. } else {
  263. memcpy(p, saved_data->data + offset, data_to_fill);
  264. p += data_to_fill;
  265. seq_num += data_to_fill;
  266. data_to_fill -= data_to_fill;
  267. }
  268. }
  269. }
  270. }
  271. }
  272. tcp_checksum(info);//update checksum
  273. if(data_to_process){
  274. if(p != info->app_data){
  275. printf("UH OH something weird might happen\n");
  276. }
  277. if(observed->application){
  278. replace_packet(observed, info);
  279. } else {
  280. /* Pass data to packet chain */
  281. if(add_packet(observed, info)){//removed_flow
  282. return;
  283. }
  284. }
  285. /* Update TCP state */
  286. if(info->tcp_hdr->flags & (FIN | RST) ){
  287. /* Remove flow from table, connection ended */
  288. remove_flow(observed);
  289. return;
  290. }
  291. /* add packet to application data queue */
  292. //add new app block
  293. packet *new_block = ecalloc(1, sizeof(packet));
  294. new_block->seq_num = seq_num;
  295. new_block->data = ecalloc(1, info->app_data_len);
  296. memcpy(new_block->data, info->app_data, info->app_data_len);
  297. new_block->len = info->app_data_len;
  298. new_block->next = NULL;
  299. new_block->expiration = 0;
  300. packet *saved_data = (incoming)? observed->downstream_app_data->first_packet :
  301. observed->upstream_app_data->first_packet;
  302. //put app data block in queue
  303. if(saved_data == NULL){
  304. if(incoming){
  305. observed->downstream_app_data->first_packet = new_block;
  306. if(new_block->seq_num ==
  307. observed->downstream_seq_num){
  308. observed->downstream_seq_num += new_block->len;
  309. #ifdef DEBUG
  310. printf("Updated downstream expected seqnum to %u\n",
  311. observed->downstream_seq_num );
  312. #endif
  313. }
  314. } else {
  315. observed->upstream_app_data->first_packet = new_block;
  316. if(new_block->seq_num ==
  317. observed->upstream_seq_num){
  318. observed->upstream_seq_num += new_block->len;
  319. #ifdef DEBUG
  320. printf("Updated upstream expected seqnum to %u\n",
  321. observed->upstream_seq_num );
  322. #endif
  323. }
  324. }
  325. }
  326. else{
  327. uint8_t saved = 0;
  328. while(saved_data->next != NULL){
  329. if(!saved && (saved_data->next->seq_num > seq_num)){
  330. new_block->next = saved_data->next;
  331. saved_data->next = new_block;
  332. saved = 1;
  333. }
  334. //update expected sequence number
  335. if(incoming){
  336. if(saved_data->next->seq_num ==
  337. observed->downstream_seq_num){
  338. observed->downstream_seq_num += saved_data->next->len;
  339. #ifdef DEBUG
  340. printf("Updated downstream expected seqnum to %u\n",
  341. observed->downstream_seq_num );
  342. #endif
  343. }
  344. } else {//outgoing
  345. if(saved_data->next->seq_num ==
  346. observed->upstream_seq_num){
  347. observed->upstream_seq_num += saved_data->next->len;
  348. #ifdef DEBUG
  349. printf("Updated upstream expected seqnum to %u\n",
  350. observed->upstream_seq_num );
  351. #endif
  352. }
  353. }
  354. saved_data = saved_data->next;
  355. }
  356. if(!saved){
  357. saved_data->next = new_block;
  358. //update expected sequence number
  359. if(incoming){
  360. if(saved_data->next->seq_num ==
  361. observed->downstream_seq_num){
  362. observed->downstream_seq_num += saved_data->next->len;
  363. #ifdef DEBUG
  364. printf("Updated downstream expected seqnum to %u\n",
  365. observed->downstream_seq_num );
  366. #endif
  367. }
  368. } else {//outgoing
  369. if(saved_data->next->seq_num ==
  370. observed->upstream_seq_num){
  371. observed->upstream_seq_num += saved_data->next->len;
  372. #ifdef DEBUG
  373. printf("Updated upstream expected seqnum to %u\n",
  374. observed->upstream_seq_num );
  375. #endif
  376. }
  377. }
  378. }
  379. }
  380. }
  381. observed->ref_ctr--;
  382. }
  383. }
  384. /** This function extracts the ip, tcp, and tls record headers
  385. * from a received packet (if they exist), and put them in
  386. * a packet_info struct
  387. *
  388. */
  389. void extract_packet_headers(uint8_t *packet, struct packet_info *info){
  390. /* First fill in IP header */
  391. uint8_t *p = packet;
  392. p += ETHER_HEADER_LEN; //skip ethernet header
  393. info->ip_hdr = (struct ip_header*) p;
  394. info->size_ip_hdr = IP_HEADER_LEN(info->ip_hdr);
  395. /* Verify this is an IP packet */
  396. if( (info->ip_hdr->versionihl >>4) != 4){
  397. info->ip_hdr = NULL;
  398. info->size_ip_hdr = 0;
  399. info->tcp_hdr = NULL;
  400. info->size_tcp_hdr = 0;
  401. info->record_hdr = NULL;
  402. return;
  403. }
  404. /* If this is a TCP segment, fill in TCP header */
  405. if (info->ip_hdr->proto == IPPROTO_TCP){
  406. p += info->size_ip_hdr; //skip IP header
  407. info->tcp_hdr = (struct tcp_header*) p;
  408. info->size_tcp_hdr = TCP_HEADER_LEN(info->tcp_hdr);
  409. p += info->size_tcp_hdr;
  410. } else {
  411. info->tcp_hdr = NULL;
  412. info->size_tcp_hdr = 0;
  413. info->record_hdr = NULL;
  414. return;
  415. }
  416. /* If the application data contains a TLS record, fill in hdr */
  417. info->app_data_len = htons(info->ip_hdr->len) - (info->size_ip_hdr + info->size_tcp_hdr);
  418. if(info->app_data_len > 0){
  419. info->app_data = p;
  420. info->record_hdr = (struct tls_header*) p;
  421. //check to see if this is a valid record
  422. if((info->record_hdr->type < 0x14) || (info->record_hdr->type > 0x18)){
  423. info->record_hdr = NULL;
  424. }
  425. } else {
  426. info->record_hdr = NULL;
  427. info->app_data = NULL;
  428. }
  429. return;
  430. }
  431. /** Copies a packet_info structure and returns a pointer to the duplicate.
  432. */
  433. struct packet_info *copy_packet_info(struct packet_info *src_info){
  434. struct packet_info *dst_info = emalloc(sizeof(struct packet_info));
  435. dst_info->ip_hdr = src_info->ip_hdr;
  436. dst_info->tcp_hdr = src_info->tcp_hdr;
  437. dst_info->size_tcp_hdr = src_info->size_tcp_hdr;
  438. dst_info->size_ip_hdr = src_info->size_ip_hdr;
  439. dst_info->app_data = src_info->app_data;
  440. dst_info->app_data_len = src_info->app_data_len;
  441. return dst_info;
  442. }