relay.c 28 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070
  1. #include <stdio.h>
  2. #include <stdlib.h>
  3. #include <stdint.h>
  4. #include <regex.h>
  5. #include <sys/socket.h>
  6. #include <sys/types.h>
  7. #include <netinet/in.h>
  8. #include <netdb.h>
  9. #include <unistd.h>
  10. #include <pthread.h>
  11. #include <string.h>
  12. #include <openssl/bio.h>
  13. #include <openssl/evp.h>
  14. #include "relay.h"
  15. #include "slitheen.h"
  16. #include "flow.h"
  17. #include "crypto.h"
  18. /** Called when a TLS application record is received for a
  19. * tagged flow. Upstream packets will be checked for covert
  20. * requests to censored sites, downstream packets will be
  21. * replaced with data from the censored queue or with garbage
  22. *
  23. * Inputs:
  24. * f: the tagged flow
  25. * info: the processed received application packet
  26. *
  27. * Output:
  28. * 0 on success, 1 on failure
  29. */
  30. int replace_packet(flow *f, struct packet_info *info){
  31. if (info == NULL || info->tcp_hdr == NULL){
  32. return 0;
  33. }
  34. #ifdef DEBUG
  35. fprintf(stderr,"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");
  36. fprintf(stderr,"ID number: %u\n", htonl(info->ip_hdr->id));
  37. fprintf(stderr,"Sequence number: %u\n", htonl(info->tcp_hdr->sequence_num));
  38. fprintf(stderr,"Acknowledgement number: %u\n", htonl(info->tcp_hdr->ack_num));
  39. #endif
  40. if(info->app_data_len <= 0){
  41. return 0;
  42. }
  43. /* if outgoing, decrypt and look at header */
  44. if(info->ip_hdr->src.s_addr == f->src_ip.s_addr){
  45. read_header(f, info);
  46. return 0;
  47. } else {
  48. #ifdef DEBUG
  49. printf("Current sequence number: %d\n", f->seq_num);
  50. printf("Received sequence number: %d\n", htonl(tcp_hdr->sequence_num));
  51. #endif
  52. uint32_t offset = htonl(info->tcp_hdr->sequence_num) - f->seq_num;
  53. if(offset == 0)
  54. f->seq_num += info->app_data_len;
  55. /* if incoming, replace with data from queue */
  56. //if(htonl(tcp_hdr->sequence_num) >= f->seq_num){
  57. process_downstream(f, offset, info);
  58. //}//TODO: need to do something about replaying packets (maybe store previously sent data??
  59. #ifdef DEBUG //TODO: fix
  60. uint8_t *p = (uint8_t *) info->tcp_hdr;
  61. fprintf(stdout, "ip hdr length: %d\n", htons(info->ip_hdr->len));
  62. fprintf(stdout, "Injecting the following packet:\n");
  63. for(int i=0; i< htons(info->ip_hdr->len); i++){
  64. fprintf(stdout, "%02x ", p[i]);
  65. }
  66. fprintf(stdout, "\n");
  67. fflush(stdout);
  68. #endif
  69. }
  70. return 0;
  71. }
  72. /** Reads the HTTP header of upstream data and searches for
  73. * a covert request in an x-slitheen header. Sends this
  74. * request to the indicated site and saves the response to
  75. * the censored queue
  76. *
  77. * TODO: change this to take SOCKS5 proxy connection and then relay data
  78. * based on stream ID
  79. *
  80. * Inputs:
  81. * f: the tagged flow
  82. * info: the processed received packet
  83. *
  84. * Ouput:
  85. * 0 on success, 1 on failure
  86. */
  87. int read_header(flow *f, struct packet_info *info){
  88. uint8_t *p = info->app_data;
  89. if (info->tcp_hdr == NULL){
  90. return 0;
  91. }
  92. uint8_t *record_ptr = NULL;
  93. struct record_header *record_hdr;
  94. uint32_t record_length;
  95. if(f->upstream_remaining > 0){
  96. //check to see whether the previous record has finished
  97. if(f->upstream_remaining > info->app_data_len){
  98. //ignore entire packet for now
  99. queue_block *new_block = calloc(1, sizeof(queue_block));
  100. uint8_t *block_data = calloc(1, info->app_data_len);
  101. memcpy(block_data, p, info->app_data_len);
  102. new_block->len = info->app_data_len;
  103. new_block->offset = 0;
  104. new_block->data = block_data;
  105. new_block->next = NULL;
  106. //add block to upstream data chain
  107. if(f->upstream_queue == NULL){
  108. f->upstream_queue = new_block;
  109. } else {
  110. queue_block *last = f->upstream_queue;
  111. while(last->next != NULL){
  112. last = last->next;
  113. }
  114. last->next = new_block;
  115. }
  116. f->upstream_remaining -= info->app_data_len;
  117. return 0;
  118. } else {
  119. //process what we have
  120. printf("US: %d bytes of packet unused\n", info->app_data_len - f->upstream_remaining);
  121. record_hdr = (struct record_header*) f->upstream_queue->data;
  122. record_length = RECORD_LEN(record_hdr);
  123. record_ptr = calloc(1, record_length+ RECORD_HEADER_LEN);
  124. queue_block *current = f->upstream_queue;
  125. int32_t offset =0;
  126. while(f->upstream_queue != NULL){
  127. memcpy(record_ptr+offset, current->data, current->len);
  128. offset += current->len;
  129. free(current->data);
  130. f->upstream_queue = current->next;
  131. free(current);
  132. }
  133. memcpy(record_ptr+offset, p, f->upstream_remaining);
  134. p = record_ptr;
  135. f->upstream_remaining = 0;
  136. }
  137. } else {
  138. //check to see if the new record is too long
  139. record_hdr = (struct record_header*) p;
  140. record_length = RECORD_LEN(record_hdr);
  141. if(record_length > info->app_data_len){
  142. //add info to upstream queue
  143. queue_block *new_block = calloc(1, sizeof(queue_block));
  144. uint8_t *block_data = calloc(1, info->app_data_len);
  145. memcpy(block_data, p, info->app_data_len);
  146. new_block->len = info->app_data_len - RECORD_HEADER_LEN;
  147. new_block->offset = record_length; //re-appropriate this for len of record
  148. new_block->data = block_data;
  149. new_block->next = NULL;
  150. //add block to upstream queue
  151. if(f->upstream_queue == NULL){
  152. f->upstream_queue = new_block;
  153. } else {
  154. queue_block *last = f->upstream_queue;
  155. while(last->next != NULL){
  156. last = last->next;
  157. }
  158. last->next = new_block;
  159. }
  160. f->upstream_remaining = record_length - new_block->len;
  161. return 0;
  162. }
  163. }
  164. p+= RECORD_HEADER_LEN;
  165. uint8_t *decrypted_data = calloc(1, record_length);
  166. memcpy(decrypted_data, p, record_length);
  167. int32_t decrypted_len = encrypt(f, decrypted_data, decrypted_data, record_length, 0, record_hdr->type, 0);
  168. if(decrypted_len<0){
  169. if(record_ptr != NULL)
  170. free(record_ptr);
  171. free(decrypted_data);
  172. return 0;
  173. }
  174. if(record_hdr->type == 0x15){
  175. printf("received alert\n");
  176. for(int i=0; i<record_length; i++){
  177. printf("%02x ", decrypted_data[i]);
  178. }
  179. fflush(stdout);
  180. }
  181. #ifdef DEBUG
  182. printf("Upstream data:\n");
  183. printf("%s\n", decrypted_data+EVP_GCM_TLS_EXPLICIT_IV_LEN);
  184. #endif
  185. //TODO: re-write this to take a SOCKS connection request
  186. /* search through decrypted data for x-ignore */
  187. char *header_ptr = strstr((const char *) decrypted_data, "X-Slitheen");
  188. uint8_t *upstream_data;
  189. if(header_ptr == NULL){
  190. if(record_ptr != NULL)
  191. free(record_ptr);
  192. free(decrypted_data);
  193. return 0;
  194. }
  195. #ifdef DEBUG
  196. printf("UPSTREAM: Found x-slitheen header\n");
  197. fprintf(stdout,"UPSTREAM Flow: %x > %x (%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");
  198. fprintf(stdout, "Sequence number: %d\n", info->tcp_hdr->sequence_num);
  199. #endif
  200. header_ptr += strlen("X-Slitheen: ");
  201. int32_t num_messages = 1;
  202. char *messages[50]; //TODO:make not just 10?
  203. messages[0] = header_ptr;
  204. char *c = header_ptr;
  205. while(*c != '\r' && *c != '\0'){
  206. if(*c == ' '){
  207. *c = '\0';
  208. messages[num_messages] = c+1;
  209. num_messages ++;
  210. }
  211. c++;
  212. }
  213. c++;
  214. *c = '\0';
  215. for(int i=0; i< num_messages-1; i++){
  216. char *message = messages[i];
  217. //b64 decode the data
  218. int32_t decode_len = strlen(message);
  219. if(message[decode_len-2] == '='){
  220. decode_len = decode_len*3/4 - 2;
  221. } else if(message[decode_len-1] == '='){
  222. decode_len = decode_len*3/4 - 1;
  223. } else {
  224. decode_len = decode_len*3/4;
  225. }
  226. upstream_data = calloc(1, decode_len + 1);
  227. BIO *bio, *b64;
  228. bio = BIO_new_mem_buf(message, -1);
  229. b64 = BIO_new(BIO_f_base64());
  230. bio = BIO_push(b64, bio);
  231. BIO_set_flags(bio, BIO_FLAGS_BASE64_NO_NL);
  232. int32_t output_len = BIO_read(bio, upstream_data, strlen(message));
  233. BIO_free_all(bio);
  234. if(output_len != decode_len)
  235. printf("UH OH, lens dont match\n. %d != %d", decode_len, output_len);
  236. #ifdef DEBUG
  237. printf("Decoded to get %d bytes:\n", output_len);
  238. for(int i=0; i< output_len; i++){
  239. printf("%02x ", upstream_data[i]);
  240. }
  241. printf("\n");
  242. fflush(stdout);
  243. #endif
  244. p = upstream_data;
  245. while(output_len > 0){
  246. struct sl_up_hdr *sl_hdr = (struct sl_up_hdr *) p;
  247. uint8_t stream_id = sl_hdr->stream_id;
  248. uint16_t stream_len = ntohs(sl_hdr->len);
  249. p += sizeof(struct sl_up_hdr);
  250. output_len -= sizeof(struct sl_up_hdr);
  251. //If a thread for this stream id exists, get the thread info and pipe data
  252. int32_t stream_pipe = -1;
  253. if(streams->first != NULL){
  254. stream *last = streams->first;
  255. if(last->stream_id == stream_id){
  256. stream_pipe = last->pipefd;
  257. }
  258. while(last->next != NULL){
  259. last = last->next;
  260. if(last->stream_id == stream_id){
  261. stream_pipe = last->pipefd;
  262. break;
  263. }
  264. }
  265. }
  266. if(stream_pipe != -1){
  267. int32_t bytes_sent = write(stream_pipe, p, stream_len);
  268. if(bytes_sent < 0){
  269. printf("Error writing to stream pipe\n");
  270. fflush(stdout);
  271. }
  272. } else {
  273. /*Else, spawn a thread to handle the proxy to this site*/
  274. pthread_t *proxy_thread = calloc(1, sizeof(pthread_t));
  275. int32_t pipefd[2];
  276. if(pipe(pipefd) < 0){
  277. printf("Failed to create pipe for new thread\n");
  278. free(decrypted_data);
  279. if(record_ptr != NULL)
  280. free(record_ptr);
  281. return 1;
  282. }
  283. uint8_t *initial_data = calloc(1,stream_len);
  284. memcpy(initial_data, p, stream_len);
  285. struct proxy_thread_data *thread_data =
  286. calloc(1, sizeof(struct proxy_thread_data));
  287. thread_data->initial_data = initial_data;
  288. thread_data->initial_len = stream_len;
  289. thread_data->stream_id = stream_id;
  290. thread_data->pipefd = pipefd[0];
  291. pthread_create(proxy_thread, NULL, proxy_covert_site, (void *) thread_data);
  292. //add stream to table
  293. stream *new_stream = calloc(1, sizeof(stream));
  294. new_stream->stream_id = stream_id;
  295. new_stream->pipefd = pipefd[1];
  296. if(streams->first == NULL){
  297. streams->first = new_stream;
  298. } else {
  299. stream *last = streams->first;
  300. while(last->next != NULL){
  301. last = last->next;
  302. }
  303. last->next = new_stream;
  304. }
  305. }
  306. output_len -= stream_len;
  307. p += stream_len;
  308. }
  309. free(upstream_data);
  310. }
  311. //save a reference to the proxy threads in a global table
  312. free(decrypted_data);
  313. if(record_ptr != NULL)
  314. free(record_ptr);
  315. return 0;
  316. }
  317. /** Called by spawned pthreads in read_header to send upstream
  318. * data to the censored site and receive responses. Downstream
  319. * data is stored in the slitheen id's downstream_queue. Function and
  320. * thread will terminate when the client closes the connection
  321. * to the covert destination
  322. *
  323. * Input:
  324. * A struct that contains the following information:
  325. * - the tagged flow
  326. * - the initial upstream data (including connect request)
  327. * - the read end of the pipe
  328. *
  329. */
  330. void *proxy_covert_site(void *data){
  331. struct proxy_thread_data *thread_data =
  332. (struct proxy_thread_data *) data;
  333. uint8_t *p = thread_data->initial_data;
  334. uint8_t stream_id = thread_data->stream_id;
  335. struct socks_req *clnt_req = (struct socks_req *) p;
  336. p += 4;
  337. //see if it's a connect request
  338. if(clnt_req->cmd != 0x01){
  339. goto err;
  340. }
  341. struct sockaddr_in dest;
  342. dest.sin_family = AF_INET;
  343. uint8_t domain_len;
  344. switch(clnt_req->addr_type){
  345. case 0x01:
  346. //IPv4
  347. dest.sin_addr.s_addr = *((uint32_t*) p);
  348. p += 4;
  349. break;
  350. case 0x03:
  351. //domain name
  352. domain_len = p[0];
  353. p++;
  354. uint8_t *domain_name = calloc(1, domain_len+1);
  355. memcpy(domain_name, p, domain_len);
  356. domain_name[domain_len] = '\0';
  357. struct hostent *host;
  358. host = gethostbyname((const char *) domain_name);
  359. dest.sin_addr = *((struct in_addr *) host->h_addr);
  360. p += domain_len;
  361. free(domain_name);
  362. break;
  363. case 0x04:
  364. //IPv6
  365. goto err;//TODO: fix this
  366. break;
  367. }
  368. //now set the port
  369. dest.sin_port = *((uint16_t *) p);
  370. int32_t handle = socket(AF_INET, SOCK_STREAM, 0);
  371. if(handle < 0){
  372. goto err;
  373. }
  374. struct sockaddr_in my_addr;
  375. socklen_t my_addr_len = sizeof(my_addr);
  376. int32_t error = connect (handle, (struct sockaddr *) &dest, sizeof (struct sockaddr));
  377. if(error <0){
  378. goto err;
  379. }
  380. getsockname(handle, (struct sockaddr *) &my_addr, &my_addr_len);
  381. uint8_t *response = calloc(1, 11);
  382. //now send the reply to the client
  383. response[0] = 0x05;
  384. response[1] = 0x00;//TODO: make this accurate
  385. response[2] = 0x00;
  386. response[3] = 0x01;
  387. *((uint32_t *) (response + 4)) = my_addr.sin_addr.s_addr;
  388. *((uint16_t *) (response + 8)) = my_addr.sin_port;
  389. #ifdef DEBUG
  390. printf("Bound to %x:%d\n", my_addr.sin_addr.s_addr, ntohs(my_addr.sin_port));
  391. printf("Downstream response:\n");
  392. for(int i=0; i< 10; i++){
  393. printf("%02x ", response[i]);
  394. }
  395. printf("\n");
  396. fflush(stdout);
  397. #endif
  398. queue_block *new_block = calloc(1, sizeof(queue_block));
  399. new_block->len = 10;
  400. new_block->offset = 0;
  401. new_block->data = response;
  402. new_block->next = NULL;
  403. new_block->stream_id = stream_id;
  404. if(downstream_queue->first_block == NULL){
  405. downstream_queue->first_block = new_block;
  406. }
  407. else{
  408. queue_block *last = downstream_queue->first_block;
  409. while(last->next != NULL)
  410. last = last->next;
  411. last->next = new_block;
  412. }
  413. uint8_t *buffer = calloc(1, BUFSIZ);
  414. int32_t buffer_len = BUFSIZ;
  415. //now select on reading from the pipe and from the socket
  416. for(;;){
  417. fd_set readfds;
  418. fd_set writefds;
  419. int32_t nfds = (handle > thread_data->pipefd) ?
  420. handle +1 : thread_data->pipefd + 1;
  421. FD_ZERO(&readfds);
  422. FD_ZERO(&writefds);
  423. FD_SET(thread_data->pipefd, &readfds);
  424. FD_SET(handle, &readfds);
  425. FD_SET(handle, &writefds);
  426. if (select(nfds, &readfds, &writefds, NULL, NULL) < 0){
  427. printf("select error\n");
  428. break;
  429. }
  430. if(FD_ISSET(thread_data->pipefd, &readfds) && FD_ISSET(handle, &writefds)){
  431. //we have upstream data ready for writing
  432. int32_t bytes_read = read(thread_data->pipefd, buffer, buffer_len);
  433. if(bytes_read > 0){
  434. int32_t bytes_sent = send(handle, buffer,
  435. bytes_read, 0);
  436. if( bytes_sent <= 0){
  437. printf("error sending request\n");
  438. break;
  439. } else if (bytes_sent < bytes_read){
  440. //TODO: should update buffer and keep
  441. //track of length of upstream data
  442. printf("sent less than full upstream bytes\n");
  443. break;
  444. }
  445. }
  446. }
  447. if (FD_ISSET(handle, &readfds)){
  448. //we have downstream data read for saving
  449. int32_t bytes_read;
  450. bytes_read = recv(handle, buffer, buffer_len, 0);
  451. if(bytes_read <= 0){
  452. break;
  453. }
  454. if(bytes_read > 0){
  455. uint8_t *new_data = calloc(1, bytes_read);
  456. memcpy(new_data, buffer, bytes_read);
  457. //make a new queue block
  458. new_block = calloc(1, sizeof(queue_block));
  459. new_block->len = bytes_read;
  460. new_block->offset = 0;
  461. new_block->data = new_data;
  462. new_block->next = NULL;
  463. new_block->stream_id = stream_id;
  464. if(downstream_queue->first_block == NULL){
  465. downstream_queue->first_block = new_block;
  466. }
  467. else{
  468. queue_block *last = downstream_queue->first_block;
  469. while(last->next != NULL)
  470. last = last->next;
  471. last->next = new_block;
  472. }
  473. } else {
  474. printf("read 0 bytes\n");
  475. break;
  476. }
  477. }
  478. }
  479. free(thread_data);
  480. free(buffer);
  481. close(handle);
  482. return 0;
  483. err:
  484. if(thread_data->initial_data != NULL){
  485. free(thread_data->initial_data);
  486. }
  487. close(handle);
  488. return 0;
  489. }
  490. /** Replaces downstream record contents with data from the
  491. * censored queue, padding with garbage bytes if no more
  492. * censored data exists.
  493. *
  494. * Inputs:
  495. * f: the tagged flow
  496. * data: a pointer to the received packet's application
  497. * data
  498. * data_len: the length of the packet's application data
  499. * offset: if the packet is misordered, the number of
  500. * application-level bytes in missing packets
  501. *
  502. * Output:
  503. * Returns 0 on sucess
  504. */
  505. int process_downstream(flow *f, int32_t offset, struct packet_info *info){
  506. uint8_t changed = 0;
  507. uint8_t *p = info->app_data;
  508. uint32_t remaining_packet_len = info->app_data_len;
  509. if(f->remaining_record_len > 0){
  510. //ignore bytes until the end of the record
  511. if(f->remaining_record_len > remaining_packet_len){ //ignore entire packet
  512. if(f->outbox_len > 0){
  513. changed = 1;
  514. memcpy(p, f->outbox + f->outbox_offset, remaining_packet_len);
  515. f->outbox_len -= remaining_packet_len;
  516. f->outbox_offset += remaining_packet_len;
  517. }
  518. f->remaining_record_len -= remaining_packet_len;
  519. remaining_packet_len -= remaining_packet_len;
  520. } else {
  521. if(f->outbox_len > 0){
  522. changed = 1;
  523. memcpy(p, f->outbox + f->outbox_offset, f->remaining_record_len);
  524. f->outbox_len = 0;
  525. f->outbox_offset=0;
  526. free(f->outbox);
  527. }
  528. p += f->remaining_record_len;
  529. remaining_packet_len -= f->remaining_record_len;
  530. f->remaining_record_len = 0;
  531. }
  532. }
  533. while(remaining_packet_len > 0){ //while bytes remain in the packet
  534. struct record_header *record_hdr = (struct record_header*) p;
  535. uint32_t record_len = RECORD_LEN(record_hdr);
  536. #ifdef DEBUG
  537. fprintf(stdout, "Record:\n");
  538. for(int i=0; i< RECORD_HEADER_LEN; i++){
  539. printf("%02x ", p[i]);
  540. }
  541. printf("\n");
  542. #endif
  543. p += RECORD_HEADER_LEN;
  544. remaining_packet_len -= RECORD_HEADER_LEN;
  545. uint8_t *record_ptr = p; //points to the beginning of record data
  546. uint32_t remaining_record_len = record_len;
  547. if(record_len > remaining_packet_len){
  548. f->remaining_record_len = record_len - remaining_packet_len;
  549. if(f->httpstate == PARSE_HEADER || f->httpstate == BEGIN_CHUNK || f->httpstate == END_CHUNK){
  550. f->httpstate = FORFEIT_REST;
  551. } else if( f->httpstate == MID_CONTENT || f->httpstate == MID_CHUNK){
  552. f->remaining_response_len -= record_len - 24; //len of IV and padding
  553. if(f->remaining_response_len >= 0 && f->replace_response){
  554. //#ifdef nothing
  555. //make a huge record, encrypt it, and then place it in the outbox
  556. f->outbox = calloc(1, record_len+1);
  557. f->outbox_len = record_len;
  558. f->outbox_offset = 0;
  559. 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
  560. //encrypt
  561. int32_t n = encrypt(f, f->outbox, f->outbox,
  562. record_len - 16, 1,
  563. record_hdr->type, 1);
  564. if(n < 0){
  565. fprintf(stdout,"outbox encryption failed\n");
  566. } else {
  567. memcpy(p, f->outbox, remaining_packet_len);
  568. changed = 1;
  569. f->outbox_len -= remaining_packet_len;
  570. f->outbox_offset += remaining_packet_len;
  571. }
  572. //#endif
  573. }
  574. if(f->remaining_response_len == 0){
  575. if(f->httpstate == MID_CHUNK)
  576. f->httpstate = END_CHUNK;
  577. else {
  578. f->httpstate = PARSE_HEADER;
  579. }
  580. }
  581. if(f->remaining_response_len < 0){
  582. f->remaining_response_len = 0;
  583. f->httpstate = FORFEIT_REST;
  584. }
  585. }
  586. remaining_packet_len -= remaining_packet_len;
  587. break;
  588. }
  589. //now decrypt the record
  590. int32_t n = encrypt(f, record_ptr, record_ptr, record_len, 1,
  591. record_hdr->type, 0);
  592. if(n < 0){
  593. //do something smarter here
  594. return 0;
  595. }
  596. changed = 1;
  597. #ifdef DEBUG
  598. printf("Decryption succeeded\n");
  599. printf("Bytes:\n");
  600. for(int i=0; i< n; i++){
  601. printf("%02x ", record_ptr[EVP_GCM_TLS_EXPLICIT_IV_LEN+i]);
  602. }
  603. printf("\n");
  604. printf("Text:\n");
  605. printf("%s\n", record_ptr+EVP_GCM_TLS_EXPLICIT_IV_LEN);
  606. #endif
  607. p += EVP_GCM_TLS_EXPLICIT_IV_LEN;
  608. char *len_ptr, *needle;
  609. remaining_record_len = n;
  610. while(remaining_record_len > 0){
  611. switch(f->httpstate){
  612. case PARSE_HEADER:
  613. //determine whether it's transfer encoded or otherwise
  614. //figure out what the content-type is
  615. len_ptr = strstr((const char *) p, "Content-Type: image");
  616. if(len_ptr != NULL){
  617. f->replace_response = 1;
  618. memcpy(len_ptr + 14, "slitheen", 8);
  619. char *c = len_ptr + 14+8;
  620. while(c[0] != '\r'){
  621. c[0] = ' ';
  622. c++;
  623. }
  624. } else {
  625. f->replace_response = 0;
  626. }
  627. len_ptr = strstr((const char *) p, "Transfer-Encoding");
  628. if(len_ptr != NULL){
  629. if(!memcmp(len_ptr + 19, "chunked", 7)){
  630. //now find end of header
  631. len_ptr = strstr((const char *) p, "\r\n\r\n");
  632. if(len_ptr != NULL){
  633. f->httpstate = BEGIN_CHUNK;
  634. remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
  635. p = (uint8_t *) len_ptr + 4;
  636. }
  637. }
  638. } else {
  639. len_ptr = strstr((const char *) p, "Content-Length");
  640. if(len_ptr != NULL){
  641. len_ptr += 15;
  642. f->remaining_response_len = strtol((const char *) len_ptr, NULL, 10);
  643. len_ptr = strstr((const char *) p, "\r\n\r\n");
  644. if(len_ptr != NULL){
  645. f->httpstate = MID_CONTENT;
  646. remaining_record_len -= (((uint8_t *)len_ptr - p) + 4);
  647. p = (uint8_t *) len_ptr + 4;
  648. } else {
  649. remaining_record_len = 0;
  650. f->httpstate = FORFEIT_REST;
  651. }
  652. } else {
  653. f->httpstate = FORFEIT_REST;
  654. remaining_record_len = 0;
  655. }
  656. }
  657. break;
  658. case MID_CONTENT:
  659. //check if content is replaceable
  660. if(f->remaining_response_len > remaining_record_len){
  661. if(f->replace_response){
  662. fill_with_downstream(p, remaining_record_len);
  663. #ifdef DEBUG
  664. printf("Replaced with:\n");
  665. for(int i=0; i< remaining_record_len; i++){
  666. printf("%02x ", p[i]);
  667. }
  668. printf("\n");
  669. #endif
  670. }
  671. f->remaining_response_len -= remaining_record_len;
  672. p += remaining_record_len;
  673. remaining_record_len = 0;
  674. } else {
  675. if(f->replace_response){
  676. fill_with_downstream(p, remaining_record_len);
  677. #ifdef DEBUG
  678. printf("Replaced with:\n");
  679. for(int i=0; i< remaining_record_len; i++){
  680. printf("%02x ", p[i]);
  681. }
  682. printf("\n");
  683. #endif
  684. }
  685. remaining_record_len -= f->remaining_response_len;
  686. p += f->remaining_response_len;
  687. f->httpstate = PARSE_HEADER;
  688. f->remaining_response_len = 0;
  689. }
  690. break;
  691. case BEGIN_CHUNK:
  692. {
  693. int32_t chunk_size = strtol((const char *) p, NULL, 16);
  694. if(chunk_size == 0){
  695. f->httpstate = END_BODY;
  696. } else {
  697. f->httpstate = MID_CHUNK;
  698. }
  699. f->remaining_response_len = chunk_size;
  700. needle = strstr((const char *) p, "\r\n");
  701. if(needle != NULL){
  702. remaining_record_len -= ((uint8_t *) needle - p + 2);
  703. p = (uint8_t *) needle + 2;
  704. } else {
  705. remaining_record_len = 0;
  706. f->httpstate = FORFEIT_REST;
  707. }
  708. }
  709. break;
  710. case MID_CHUNK:
  711. if(f->remaining_response_len > remaining_record_len){
  712. if(f->replace_response){
  713. fill_with_downstream(p, remaining_record_len);
  714. #ifdef DEBUG
  715. printf("Replaced with:\n");
  716. for(int i=0; i< remaining_record_len; i++){
  717. printf("%02x ", p[i]);
  718. }
  719. printf("\n");
  720. #endif
  721. }
  722. f->remaining_response_len -= remaining_record_len;
  723. p += remaining_record_len;
  724. remaining_record_len = 0;
  725. } else {
  726. if(f->replace_response){
  727. fill_with_downstream(p, remaining_record_len);
  728. #ifdef DEBUG
  729. printf("Replaced with:\n");
  730. for(int i=0; i< remaining_record_len; i++){
  731. printf("%02x ", p[i]);
  732. }
  733. printf("\n");
  734. #endif
  735. }
  736. remaining_record_len -= f->remaining_response_len;
  737. p += f->remaining_response_len;
  738. f->httpstate = END_CHUNK;
  739. }
  740. break;
  741. case END_CHUNK:
  742. needle = strstr((const char *) p, "\r\n");
  743. if(needle != NULL){
  744. f->httpstate = BEGIN_CHUNK;
  745. p += 2;
  746. remaining_record_len -= 2;
  747. } else {
  748. remaining_record_len = 0;
  749. f->httpstate = FORFEIT_REST;
  750. }
  751. break;
  752. case END_BODY:
  753. needle = strstr((const char *) p, "\r\n");
  754. if(needle != NULL){
  755. f->httpstate = PARSE_HEADER;
  756. p += 2;
  757. remaining_record_len -= 2;
  758. } else {
  759. remaining_record_len = 0;
  760. f->httpstate = FORFEIT_REST;
  761. }
  762. break;
  763. case FORFEIT_REST:
  764. case USE_REST:
  765. remaining_record_len = 0;
  766. break;
  767. default:
  768. break;
  769. }
  770. }
  771. if((n = encrypt(f, record_ptr, record_ptr,
  772. n + EVP_GCM_TLS_EXPLICIT_IV_LEN, 1, record_hdr->type,
  773. 1)) < 0){
  774. return 0;
  775. }
  776. p = record_ptr + record_len;
  777. remaining_packet_len -= record_len;
  778. }
  779. if(changed){
  780. tcp_checksum(info);
  781. }
  782. return 0;
  783. }
  784. /** Fills a given pointer with downstream data of the specified length. If no downstream data
  785. * exists, pads it with garbage bytes. All downstream data is accompanied by a stream id and
  786. * lengths of both the downstream data and garbage data
  787. *
  788. * Inputs:
  789. * data: a pointer to where the downstream data should be entered
  790. * length: The length of the downstream data required
  791. *
  792. */
  793. int fill_with_downstream(uint8_t *data, int32_t length){
  794. uint8_t *p = data;
  795. int32_t remaining = length;
  796. struct slitheen_header *sl_hdr;
  797. //Fill as much as we can from the censored_queue
  798. while((remaining > SLITHEEN_HEADER_LEN) && downstream_queue->first_block != NULL){
  799. queue_block *first_block = downstream_queue->first_block;
  800. int32_t block_length = first_block->len;
  801. int32_t offset = first_block->offset;
  802. #ifdef DEBUG
  803. printf("Censored queue is at %p.\n", first_block);
  804. printf("This block has %d bytes left\n", block_length - offset);
  805. printf("We need %d bytes\n", remaining - SLITHEEN_HEADER_LEN);
  806. #endif
  807. sl_hdr = (struct slitheen_header *) p;
  808. sl_hdr->stream_id = first_block->stream_id;
  809. sl_hdr->len = 0x00;
  810. sl_hdr->garbage = 0x00;
  811. p += SLITHEEN_HEADER_LEN;
  812. remaining -= SLITHEEN_HEADER_LEN;
  813. if(block_length > offset + remaining){
  814. //use part of the block, update offset
  815. memcpy(p, first_block->data+offset, remaining);
  816. first_block->offset += remaining;
  817. p += remaining;
  818. sl_hdr->len = remaining;
  819. remaining -= remaining;
  820. } else {
  821. //use all of the block and free it
  822. memcpy(p, first_block->data+offset, block_length - offset);
  823. free(first_block->data);
  824. downstream_queue->first_block = first_block->next;
  825. free(first_block);
  826. p += (block_length - offset);
  827. sl_hdr->len = (block_length - offset);
  828. remaining -= (block_length - offset);
  829. }
  830. sl_hdr->len = htons(sl_hdr->len);
  831. #ifdef DEBUG
  832. printf("DWNSTRM: slitheen header: ");
  833. for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
  834. printf("%02x ",((uint8_t *) sl_hdr)[i]);
  835. }
  836. printf("\n");
  837. #endif
  838. }
  839. //now, if we need more data, fill with garbage
  840. if(remaining > SLITHEEN_HEADER_LEN ){
  841. //TODO: note, we may also be receiving misordered packets. Take Ian's suggestion into account here
  842. sl_hdr = (struct slitheen_header *) p;
  843. sl_hdr->stream_id = 0x00;
  844. remaining -= SLITHEEN_HEADER_LEN;
  845. sl_hdr->len = htons(remaining);
  846. sl_hdr->garbage = htons(remaining);
  847. #ifdef DEBUG
  848. printf("DWNSTRM: slitheen header: ");
  849. for(int i=0; i< SLITHEEN_HEADER_LEN; i++){
  850. printf("%02x ", p[i]);
  851. }
  852. printf("\n");
  853. #endif
  854. p += SLITHEEN_HEADER_LEN;
  855. memset(p, 'A', remaining);
  856. }
  857. return 0;
  858. }
  859. /** Computes the TCP checksum of the data according to RFC 793
  860. * sum all 16-bit words in the segment, pad the last word if
  861. * needed
  862. *
  863. * there is a pseudo-header prefixed to the segment and
  864. * included in the checksum:
  865. *
  866. * +--------+--------+--------+--------+
  867. * | Source Address |
  868. * +--------+--------+--------+--------+
  869. * | Destination Address |
  870. * +--------+--------+--------+--------+
  871. * | zero | PTCL | TCP Length |
  872. * +--------+--------+--------+--------+
  873. */
  874. uint16_t tcp_checksum(struct packet_info *info){
  875. uint16_t tcp_length = info->app_data_len + info->size_tcp_hdr;
  876. struct in_addr src = info->ip_hdr->src;
  877. struct in_addr dst = info->ip_hdr->dst;
  878. uint8_t proto = IPPROTO_TCP;
  879. //set the checksum to zero
  880. info->tcp_hdr->chksum = 0;
  881. //sum pseudoheader
  882. uint32_t sum = (ntohl(src.s_addr)) >> 16;
  883. sum += (ntohl(src.s_addr)) &0xFFFF;
  884. sum += (ntohl(dst.s_addr)) >> 16;
  885. sum += (ntohl(dst.s_addr)) & 0xFFFF;
  886. sum += proto;
  887. sum += tcp_length;
  888. //sum tcp header (with zero-d checksum)
  889. uint8_t *p = (uint8_t *) info->tcp_hdr;
  890. for(int i=0; i < info->size_tcp_hdr; i+=2){
  891. sum += (uint16_t) ((p[i] << 8) + p[i+1]);
  892. }
  893. //now sum the application data
  894. p = info->app_data;
  895. for(int i=0; i< info->app_data_len-1; i+=2){
  896. sum += (uint16_t) ((p[i] << 8) + p[i+1]);
  897. }
  898. if(info->app_data_len %2 != 0){
  899. sum += (uint16_t) (p[info->app_data_len - 1]) << 8;
  900. }
  901. //now add most significant to last significant bits
  902. sum = (sum >> 16) + (sum & 0xFFFF);
  903. sum += sum >>16;
  904. //now subtract from 0xFF
  905. sum = 0xFFFF - sum;
  906. //set chksum to calculated value
  907. info->tcp_hdr->chksum = ntohs(sum);
  908. return (uint16_t) sum;
  909. }