slitheen-proxy.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643
  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 save_packet(flow *f, struct packet_info *info);
  22. void update_window_expiration(flow *f, struct packet_info *info);
  23. void retransmit(flow *f, struct packet_info *info, uint32_t data_to_fill);
  24. void usage(void){
  25. printf("Usage: slitheen-proxy [internal network interface] [NAT interface]\n");
  26. }
  27. int main(int argc, char *argv[]){
  28. pthread_t t1, t2;
  29. char *dev1 = NULL; /* Device that leads to the internal network */
  30. char *dev2 = NULL; /* Device that leads out to the world */
  31. struct sniff_args outbound;
  32. struct sniff_args inbound;
  33. if (argc != 3) {
  34. usage();
  35. return(2);
  36. }
  37. dev1 = argv[1];
  38. dev2 = argv[2];
  39. if(init_tables()){
  40. exit(1);
  41. }
  42. if(init_session_cache()){
  43. exit(1);
  44. }
  45. init_crypto_locks();
  46. /* Create threads */
  47. outbound.readdev = dev1;
  48. outbound.writedev = dev2;
  49. inbound.readdev = dev2;
  50. inbound.writedev = dev1;
  51. pthread_create(&t1, NULL, sniff_packets, (void *) &outbound);
  52. pthread_create(&t2, NULL, sniff_packets, (void *) &inbound);
  53. pthread_join(t1, NULL);
  54. pthread_join(t2, NULL);
  55. pthread_exit(NULL);
  56. crypto_locks_cleanup();
  57. return(0);
  58. }
  59. void *sniff_packets(void *args){
  60. pcap_t *rd_handle;
  61. pcap_t *wr_handle;
  62. char rd_errbuf[BUFSIZ];
  63. char wr_errbuf[BUFSIZ];
  64. bpf_u_int32 mask;
  65. bpf_u_int32 net;
  66. char *readdev, *writedev;
  67. struct sniff_args *arg_st = (struct sniff_args *) args;
  68. readdev = arg_st->readdev;
  69. writedev = arg_st->writedev;
  70. if (pcap_lookupnet(readdev, &net, &mask, rd_errbuf) == -1){
  71. fprintf(stderr, "Can't get netmask for device %s\n", readdev);
  72. exit(2);
  73. }
  74. rd_handle = pcap_open_live(readdev, BUFSIZ, 1, 0, rd_errbuf);
  75. if (rd_handle == NULL){
  76. fprintf(stderr, "Couldn't open device %s: %s\n", readdev, rd_errbuf);
  77. }
  78. if(pcap_datalink(rd_handle) != DLT_EN10MB) {
  79. fprintf(stderr, "Device %s does not provide Ethernet headers - not supported\n", readdev);
  80. exit(2);
  81. }
  82. if(pcap_setdirection(rd_handle, PCAP_D_IN)){
  83. fprintf(stderr, "Platform does not support write direction. Update filters with MAC address\n");
  84. exit(2);
  85. }
  86. wr_handle = pcap_open_live(writedev, BUFSIZ, 1, 0, wr_errbuf);
  87. if (wr_handle == NULL){
  88. fprintf(stderr, "Couldn't open device %s: %s\n", writedev, wr_errbuf);
  89. }
  90. /*callback function*/
  91. pcap_loop(rd_handle, -1, got_packet, (unsigned char *) wr_handle);
  92. /*Sniff a packet*/
  93. pcap_close(rd_handle);
  94. return NULL;
  95. }
  96. /*
  97. * Injects a packet back out the opposite interface
  98. */
  99. void inject_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *packet){
  100. if((pcap_inject(handle, packet, header->len)) < 0 ){
  101. fprintf(stderr, "Error: %s\n", pcap_geterr(handle));
  102. }
  103. #ifdef DEBUG
  104. fprintf(stderr, "injected the following packet:\n");
  105. for(int i=0; i< header->len; i++){
  106. fprintf(stderr, "%02x ", packet[i]);
  107. }
  108. fprintf(stderr, "\n");
  109. #endif
  110. free(packet);
  111. }
  112. /**
  113. * Runs when pcap_loop receives a packet from the specified interface
  114. * If the received packet is a tcp packet, processes it and then writes it back out
  115. * to the interface
  116. *
  117. */
  118. void got_packet(uint8_t *args, const struct pcap_pkthdr *header, const uint8_t *packet){
  119. pcap_t *handle = (pcap_t *) args;
  120. uint8_t *tmp_packet = emalloc(header->len);
  121. memcpy(tmp_packet, packet, header->len);
  122. process_packet(handle, header, tmp_packet);
  123. }
  124. /* This function receives a full ip packet and then:
  125. * 1) identifies the flow
  126. * 2) adds the packet to the flow's data chain
  127. * 3) updates the flow's state
  128. */
  129. void process_packet(pcap_t *handle, const struct pcap_pkthdr *header, uint8_t *packet){
  130. struct packet_info *info = emalloc(sizeof(struct packet_info));
  131. extract_packet_headers(packet, info);
  132. //Ignore non-TCP packets (shouldn't actually get any)
  133. if((info->ip_hdr == NULL) || (info->tcp_hdr == NULL))
  134. goto err;
  135. /* Checks to see if this is a possibly tagged hello msg */
  136. if ((info->record_hdr != NULL) && (info->record_hdr->type == HS)){ /* This is a TLS handshake */
  137. check_handshake(info);
  138. }
  139. /* Now if flow is in table, update state */
  140. flow *observed;
  141. if((observed = check_flow(info)) != NULL){
  142. #ifdef DEBUG
  143. /*Check sequence number and replay application data if necessary*/
  144. 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");
  145. fprintf(stdout,"ID number: %u\n", htonl(info->ip_hdr->id));
  146. fprintf(stdout,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
  147. fprintf(stdout,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
  148. #endif
  149. uint8_t incoming = (info->ip_hdr->src.s_addr != observed->src_ip.s_addr)? 1 : 0;
  150. uint32_t seq_num = htonl(info->tcp_hdr->sequence_num);
  151. uint32_t expected_seq = (incoming)? observed->downstream_seq_num : observed->upstream_seq_num;
  152. #ifdef DEBUG
  153. fprintf(stdout,"Expected sequence number: %u\n", expected_seq);
  154. #endif
  155. /* Remove acknowledged data from queue after TCP window is exceeded */
  156. update_window_expiration(observed, info);
  157. /* fill with retransmit data, process new data */
  158. uint32_t data_to_fill;
  159. uint32_t data_to_process;
  160. if(seq_num > expected_seq){
  161. data_to_process = info->app_data_len;
  162. data_to_fill = 0;
  163. } else if (seq_num + info->app_data_len > expected_seq){
  164. data_to_fill = expected_seq - seq_num;
  165. data_to_process = seq_num + info->app_data_len - expected_seq;
  166. } else {
  167. data_to_fill = info->app_data_len;
  168. data_to_process = 0;
  169. }
  170. uint8_t *p = info->app_data;
  171. if(data_to_fill){ //retransmit
  172. retransmit(observed, info, data_to_fill);
  173. }
  174. p += data_to_fill;
  175. if(data_to_process){
  176. if(p != info->app_data){
  177. printf("UH OH something weird might happen\n");
  178. }
  179. if(observed->application){
  180. if(seq_num > expected_seq){
  181. //For now, enters into FORFEIT state
  182. //TODO: change upstream behaviour to try to mask slitheen hdr
  183. //printf("ERROR: future packet in app data, forfeiting flow\n");
  184. remove_flow(observed);
  185. goto err;
  186. }
  187. replace_packet(observed, info);
  188. } else {
  189. //We're still in the TLS handshake; hold packets misordered packets
  190. if(seq_num > expected_seq){
  191. //Delay and process later
  192. frame *new_frame = ecalloc(1, sizeof(frame));
  193. new_frame->handle = handle;
  194. new_frame->packet = packet;
  195. new_frame->header = header;
  196. new_frame->seq_num = seq_num;
  197. new_frame->next = NULL;
  198. frame_queue *queue = (incoming) ? observed->ds_frame_queue : observed->us_frame_queue;
  199. printf("Used frame queue\n");
  200. //add to end of list
  201. if(queue->first_frame == NULL){
  202. queue->first_frame = new_frame;
  203. } else {
  204. frame *last = queue->first_frame;
  205. while(last->next != NULL){
  206. last = last->next;
  207. }
  208. last->next = new_frame;
  209. }
  210. free(info);
  211. observed->ref_ctr--;
  212. return; //TODO: fix terrible spaghetti returns
  213. }
  214. /* Pass data to packet chain */
  215. if(observed->stall){
  216. }
  217. if(add_packet(observed, info)){//removed_flow
  218. goto err;
  219. }
  220. }
  221. /* Update TCP state */
  222. if(info->tcp_hdr->flags & (FIN | RST) ){
  223. /* Remove flow from table, connection ended */
  224. remove_flow(observed);
  225. goto err;
  226. }
  227. /* add packet to application data queue */
  228. save_packet(observed, info);
  229. }
  230. /*process and release held frames with current sequence numbers*/
  231. frame_queue *queue = (incoming) ? observed->ds_frame_queue : observed->us_frame_queue;
  232. frame *first = queue->first_frame;
  233. frame *prev = queue->first_frame;
  234. expected_seq = (incoming)? observed->downstream_seq_num : observed->upstream_seq_num;
  235. while (first != NULL){
  236. if(first->seq_num <= expected_seq){
  237. //remove from queue and process
  238. if(first == queue->first_frame) {
  239. queue->first_frame = first->next;
  240. } else {
  241. prev->next = first->next;
  242. }
  243. process_packet(handle, first->header, first->packet);
  244. free(first);
  245. first = queue->first_frame;
  246. prev = queue->first_frame;
  247. } else {
  248. prev = first;
  249. first = first->next;
  250. }
  251. }
  252. observed->ref_ctr--;
  253. }
  254. err:
  255. free(info);//Note: don't free this while a thread is using it
  256. inject_packet(handle, header, packet);
  257. return;
  258. }
  259. //TODO: rewrite this function to remove bloat
  260. void save_packet(flow *f, struct packet_info *info){
  261. uint8_t incoming = (info->ip_hdr->src.s_addr != f->src_ip.s_addr)? 1 : 0;
  262. uint32_t seq_num = htonl(info->tcp_hdr->sequence_num);
  263. //add new app block
  264. packet *new_block = ecalloc(1, sizeof(packet));
  265. new_block->seq_num = htonl(info->tcp_hdr->sequence_num);
  266. new_block->data = ecalloc(1, info->app_data_len);
  267. memcpy(new_block->data, info->app_data, info->app_data_len);
  268. new_block->len = info->app_data_len;
  269. new_block->next = NULL;
  270. new_block->expiration = 0;
  271. packet *saved_data = (incoming)? f->downstream_app_data->first_packet :
  272. f->upstream_app_data->first_packet;
  273. //put app data block in queue
  274. if(saved_data == NULL){
  275. if(incoming){
  276. f->downstream_app_data->first_packet = new_block;
  277. if(new_block->seq_num ==
  278. f->downstream_seq_num){
  279. f->downstream_seq_num += new_block->len;
  280. #ifdef DEBUG
  281. printf("Updated downstream expected seqnum to %u\n",
  282. f->downstream_seq_num );
  283. #endif
  284. }
  285. } else {
  286. f->upstream_app_data->first_packet = new_block;
  287. if(new_block->seq_num ==
  288. f->upstream_seq_num){
  289. f->upstream_seq_num += new_block->len;
  290. #ifdef DEBUG
  291. printf("Updated upstream expected seqnum to %u\n",
  292. f->upstream_seq_num );
  293. #endif
  294. }
  295. }
  296. } else {
  297. uint8_t saved = 0;
  298. while(saved_data->next != NULL){
  299. if(!saved && (saved_data->next->seq_num > seq_num)){
  300. new_block->next = saved_data->next;
  301. saved_data->next = new_block;
  302. saved = 1;
  303. }
  304. //update expected sequence number
  305. if(incoming){
  306. if(saved_data->next->seq_num ==
  307. f->downstream_seq_num){
  308. f->downstream_seq_num += saved_data->next->len;
  309. #ifdef DEBUG
  310. printf("Updated downstream expected seqnum to %u\n",
  311. f->downstream_seq_num );
  312. #endif
  313. }
  314. } else {//outgoing
  315. if(saved_data->next->seq_num ==
  316. f->upstream_seq_num){
  317. f->upstream_seq_num += saved_data->next->len;
  318. #ifdef DEBUG
  319. printf("Updated upstream expected seqnum to %u\n",
  320. f->upstream_seq_num );
  321. #endif
  322. }
  323. }
  324. saved_data = saved_data->next;
  325. }
  326. if(!saved){
  327. saved_data->next = new_block;
  328. //update expected sequence number
  329. if(incoming){
  330. if(saved_data->next->seq_num ==
  331. f->downstream_seq_num){
  332. f->downstream_seq_num += saved_data->next->len;
  333. #ifdef DEBUG
  334. printf("Updated downstream expected seqnum to %u\n",
  335. f->downstream_seq_num );
  336. #endif
  337. }
  338. } else {//outgoing
  339. if(saved_data->next->seq_num ==
  340. f->upstream_seq_num){
  341. f->upstream_seq_num += saved_data->next->len;
  342. #ifdef DEBUG
  343. printf("Updated upstream expected seqnum to %u\n",
  344. f->upstream_seq_num );
  345. #endif
  346. }
  347. }
  348. }
  349. }
  350. }
  351. /**
  352. * This function cleans up data that has been acked, after the TCP window of the recipient has been
  353. * exceeded. This ensures that a retransmisson of the data will no longer occur.
  354. *
  355. * Sets the expiration for recent data base on the TCP window
  356. */
  357. void update_window_expiration(flow *f, struct packet_info *info){
  358. uint8_t incoming = (info->ip_hdr->src.s_addr != f->src_ip.s_addr)? 1 : 0;
  359. uint32_t ack_num = htonl(info->tcp_hdr->ack_num);
  360. uint32_t end_seq = htonl(info->tcp_hdr->sequence_num) + info->app_data_len - 1;
  361. uint32_t window = ack_num + htons(info->tcp_hdr->win_size);
  362. #ifdef DEBUG
  363. printf("Received sequence number %u\n", htonl(info->tcp_hdr->sequence_num));
  364. printf("Acknowledged up to %u with window expiring at %u\n", ack_num, window);
  365. printf("Removing all packets up to %u\n", end_seq);
  366. #endif
  367. packet *saved_data = (incoming)? f->downstream_app_data->first_packet :
  368. f->upstream_app_data->first_packet;
  369. while((saved_data != NULL) && (saved_data->expiration != 0) && (end_seq > saved_data->expiration)){
  370. //remove entire block
  371. if(incoming){
  372. f->downstream_app_data->first_packet = saved_data->next;
  373. } else {
  374. f->upstream_app_data->first_packet = saved_data->next;
  375. }
  376. free(saved_data->data);
  377. free(saved_data);
  378. saved_data = (incoming)? f->downstream_app_data->first_packet :
  379. f->upstream_app_data->first_packet;
  380. #ifdef DEBUG
  381. if(saved_data != NULL){
  382. printf("Currently saved seq_num is now %u\n", saved_data->seq_num);
  383. } else {
  384. printf("Acked all data, queue is empty\n");
  385. }
  386. #endif
  387. }
  388. /* Update expiration for packets based on TCP window size */
  389. saved_data = (incoming)? f->upstream_app_data->first_packet :
  390. f->downstream_app_data->first_packet;
  391. while((saved_data != NULL) && (ack_num > saved_data->seq_num)){
  392. //update window
  393. if(ack_num >= saved_data->seq_num + saved_data->len){
  394. //remove entire block
  395. saved_data->expiration = window;
  396. }
  397. saved_data = saved_data->next;
  398. }
  399. }
  400. /**
  401. * This function retransmits previously sent (and possibly modified) data
  402. *
  403. */
  404. void retransmit(flow *f, struct packet_info *info, uint32_t data_to_fill){
  405. uint8_t *p = info->app_data;
  406. uint32_t seq_num = htonl(info->tcp_hdr->sequence_num);
  407. uint8_t incoming = (info->ip_hdr->src.s_addr != f->src_ip.s_addr)? 1 : 0;
  408. packet *saved_data = (incoming)? f->downstream_app_data->first_packet :
  409. f->upstream_app_data->first_packet;
  410. while(data_to_fill > 0){
  411. if(saved_data == NULL){
  412. //have already acked all data
  413. p += data_to_fill;
  414. seq_num += data_to_fill;
  415. data_to_fill -= data_to_fill;
  416. continue;
  417. }
  418. if(seq_num < saved_data->seq_num){
  419. //we are missing a block. Use what was given
  420. if(saved_data->seq_num - seq_num > data_to_fill){
  421. //skip the rest
  422. p += data_to_fill;
  423. seq_num += data_to_fill;
  424. data_to_fill -= data_to_fill;
  425. } else {
  426. p += saved_data->seq_num - seq_num;
  427. data_to_fill -= saved_data->seq_num - seq_num;
  428. seq_num += saved_data->seq_num - seq_num;
  429. }
  430. } else if ( seq_num == saved_data->seq_num) {
  431. if(data_to_fill >= saved_data->len){
  432. //exhaust this block and move onto next one
  433. memcpy(p, saved_data->data, saved_data->len);
  434. p += saved_data->len;
  435. seq_num += saved_data->len;
  436. data_to_fill -= saved_data->len;
  437. saved_data = saved_data->next;
  438. } else {
  439. //fill with partial block
  440. memcpy(p, saved_data->data, data_to_fill);
  441. p += data_to_fill;
  442. seq_num += data_to_fill;
  443. data_to_fill -= data_to_fill;
  444. }
  445. } else { //seq_num > saved_data->seq_num
  446. uint32_t offset = seq_num - saved_data->seq_num;
  447. if(offset > saved_data->len){
  448. saved_data = saved_data->next;
  449. offset -= saved_data->len;
  450. } else {
  451. if(data_to_fill > saved_data->len - offset){
  452. memcpy(p, saved_data->data + offset, saved_data->len - offset);
  453. p += saved_data->len - offset;
  454. seq_num += saved_data->len - offset;
  455. data_to_fill -= saved_data->len - offset;
  456. saved_data = saved_data->next;
  457. } else {
  458. memcpy(p, saved_data->data + offset, data_to_fill);
  459. p += data_to_fill;
  460. seq_num += data_to_fill;
  461. data_to_fill -= data_to_fill;
  462. }
  463. }
  464. }
  465. }
  466. tcp_checksum(info);//update checksum
  467. }
  468. /** This function extracts the ip, tcp, and tls record headers
  469. * from a received packet (if they exist), and put them in
  470. * a packet_info struct
  471. *
  472. */
  473. void extract_packet_headers(uint8_t *packet, struct packet_info *info){
  474. /* First fill in IP header */
  475. uint8_t *p = packet;
  476. p += ETHER_HEADER_LEN; //skip ethernet header
  477. info->ip_hdr = (struct ip_header*) p;
  478. info->size_ip_hdr = IP_HEADER_LEN(info->ip_hdr);
  479. /* Verify this is an IP packet */
  480. if( (info->ip_hdr->versionihl >>4) != 4){
  481. info->ip_hdr = NULL;
  482. info->size_ip_hdr = 0;
  483. info->tcp_hdr = NULL;
  484. info->size_tcp_hdr = 0;
  485. info->record_hdr = NULL;
  486. return;
  487. }
  488. /* If this is a TCP segment, fill in TCP header */
  489. if (info->ip_hdr->proto == IPPROTO_TCP){
  490. p += info->size_ip_hdr; //skip IP header
  491. info->tcp_hdr = (struct tcp_header*) p;
  492. info->size_tcp_hdr = TCP_HEADER_LEN(info->tcp_hdr);
  493. p += info->size_tcp_hdr;
  494. } else {
  495. info->tcp_hdr = NULL;
  496. info->size_tcp_hdr = 0;
  497. info->record_hdr = NULL;
  498. return;
  499. }
  500. /* If the application data contains a TLS record, fill in hdr */
  501. info->app_data_len = htons(info->ip_hdr->len) - (info->size_ip_hdr + info->size_tcp_hdr);
  502. if(info->app_data_len > 0){
  503. info->app_data = p;
  504. info->record_hdr = (struct tls_header*) p;
  505. //check to see if this is a valid record
  506. if((info->record_hdr->type < 0x14) || (info->record_hdr->type > 0x18)){
  507. info->record_hdr = NULL;
  508. }
  509. } else {
  510. info->record_hdr = NULL;
  511. info->app_data = NULL;
  512. }
  513. return;
  514. }
  515. /** Copies a packet_info structure and returns a pointer to the duplicate.
  516. */
  517. struct packet_info *copy_packet_info(struct packet_info *src_info){
  518. struct packet_info *dst_info = emalloc(sizeof(struct packet_info));
  519. dst_info->ip_hdr = src_info->ip_hdr;
  520. dst_info->tcp_hdr = src_info->tcp_hdr;
  521. dst_info->size_tcp_hdr = src_info->size_tcp_hdr;
  522. dst_info->size_ip_hdr = src_info->size_ip_hdr;
  523. dst_info->app_data = src_info->app_data;
  524. dst_info->app_data_len = src_info->app_data_len;
  525. return dst_info;
  526. }