[tor-commits] [stegotorus/master] initial commit for 'embed' steg module, needs chopper changes to work

zwol at torproject.org zwol at torproject.org
Fri Jul 20 23:17:06 UTC 2012


commit a43ae4dc1ce5475d6a1265af3fc318b4921bf36b
Author: Jeffrey Wang <jeffreyw at stanford.edu>
Date:   Sun Dec 4 08:24:11 2011 +0000

    initial commit for 'embed' steg module, needs chopper changes to work
    
    git-svn-id: svn+ssh://spartan.csl.sri.com/svn/private/DEFIANCE@169 a58ff0ac-194c-e011-a152-003048836090
---
 src/steg/embed.cc |  234 +++++++++++++++++++++++++++++++++++++++++++++++++++++
 1 files changed, 234 insertions(+), 0 deletions(-)

diff --git a/src/steg/embed.cc b/src/steg/embed.cc
new file mode 100644
index 0000000..1e3c34c
--- /dev/null
+++ b/src/steg/embed.cc
@@ -0,0 +1,234 @@
+#include "util.h"
+#include "connections.h"
+#include "steg.h"
+
+#include <event2/buffer.h>
+#include <event2/event.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <time.h>
+
+typedef struct trace_t {
+  int num_pkt;              // number of packets in trace
+  short *pkt_sizes;         // packet sizes (positive = client->server)
+  int *pkt_times;           // packet inter-arrival times
+} trace_t;
+
+namespace {
+  struct embed : steg_t {
+    int cur_idx;              // current trace index
+    trace_t *cur;             // current trace
+    int cur_pkt;              // current packet in the trace
+    struct timeval last_pkt;  // time at which last packet was sent/received
+
+    STEG_DECLARE_METHODS(embed);
+  };
+}
+
+static int embed_init = 0;      // whether traces are initialized
+static int embed_num_traces;    // number of traces
+static trace_t *embed_traces;   // global array of all traces
+
+STEG_DEFINE_MODULE(embed, 1024, 1024, 1, 1);
+
+int millis_since(struct timeval *last) {
+  struct timeval cur;
+  int diff = 0;
+  gettimeofday(&cur, NULL);
+
+  diff += (cur.tv_sec - last->tv_sec) * 1000;
+  diff += (cur.tv_usec - last->tv_usec) / 1000;
+  return diff;
+}
+
+void init_embed_traces() {
+  // read in traces to use for connections
+  FILE *trace_file = fopen("traces/embed.txt", "r");
+  fscanf(trace_file, "%d", &embed_num_traces);
+  embed_traces = (trace_t *)xmalloc(sizeof(trace_t) * embed_num_traces);
+  for (int i = 0; i < embed_num_traces; i++) {
+    int num_pkt;
+    fscanf(trace_file, "%d", &num_pkt);
+    embed_traces[i].num_pkt = num_pkt;
+    embed_traces[i].pkt_sizes = (short *)xmalloc(sizeof(short) * num_pkt);
+    embed_traces[i].pkt_times = (int *)xmalloc(sizeof(int) * num_pkt);
+    for (int j = 0; j < embed_traces[i].num_pkt; j++) {
+      fscanf(trace_file, "%hd %d",
+	     &embed_traces[i].pkt_sizes[j],
+	     &embed_traces[i].pkt_times[j]);
+    }
+  }
+  log_debug("read %d traces to use", embed_num_traces);
+
+  srand(time(NULL));
+  embed_init = 1;
+}
+
+int get_random_trace() {
+  return rand() % embed_num_traces;
+}
+
+bool advance_packet(embed *state) {
+  state->cur_pkt++;
+  return state->cur_pkt == state->cur->num_pkt;
+}
+
+short get_pkt_size(embed *state) {
+  return abs(state->cur->pkt_sizes[state->cur_pkt]);
+}
+
+bool is_outgoing(embed *state) {
+  return (state->cur->pkt_sizes[state->cur_pkt] < 0) ^ (state->is_clientside);
+}
+
+int get_pkt_time(embed *state) {
+  return state->cur->pkt_times[state->cur_pkt];
+}
+
+bool is_finished(embed *state) {
+  if (state->cur_idx == -1) return true;
+  return state->cur_pkt >= state->cur->num_pkt;
+}
+
+embed::embed() {
+  if (!embed_init) init_embed_traces();
+  cur_idx = -1;
+  gettimeofday(&last_pkt, NULL);
+}
+
+embed::~embed() { }
+
+bool embed::detect(conn_t * /* conn */) {
+  return 1;
+}
+
+size_t embed::transmit_room(conn_t * /* conn */) {
+  if (cur_idx == -1 && is_clientside) {
+    cur_idx = get_random_trace();
+    cur = &embed_traces[cur_idx];
+    cur_pkt = 0;
+  }
+
+  int time_diff = millis_since(&last_pkt);
+  size_t room;
+
+  if (is_finished(this) || !is_outgoing(this)) return 0;
+  if (get_pkt_time(this) > time_diff+10) return 0;
+
+  // 24 bytes for chop header, 2 bytes for data length
+  // 4 bytes for the index of a new trace
+  room = get_pkt_size(this) - 26;
+  if (cur_pkt == 0) {
+    room -= 4;
+  }
+  return room;
+}
+
+int embed::transmit(struct evbuffer *source, conn_t *conn) {
+  struct evbuffer *dest = conn_get_outbound(conn);
+  short src_len = evbuffer_get_length(source);
+  short pkt_size = get_pkt_size(this);
+  short used = src_len + 2;
+
+  // starting a new trace, send the index
+  if (cur_pkt == 0) {
+    if (evbuffer_add(dest, &cur_idx, 4) == -1) return -1;
+    used += 4;
+    log_debug("sending trace %d", cur_idx);
+  }
+
+  log_debug("sending packet %d of trace %d", cur_pkt, cur_idx);
+
+  // add the data length and data to the dest buffer
+  if (evbuffer_add(dest, &src_len, 2) == -1) return -1;
+  if (evbuffer_add_buffer(dest, source) == -1) return -1;
+  log_debug("sending data with length %d", src_len);
+
+  // if there is more space in the packet, pad it
+  if (pkt_size > used) {
+    size_t padding = pkt_size - used;
+    unsigned char zero[padding];
+    memset(zero, 0, padding);
+    evbuffer_add(dest, zero, padding);
+  }
+
+  // check if this trace is finished and whether we need to send again
+  if (advance_packet(this)) {
+    log_debug("send finished trace");
+    conn_close_after_transmit(conn);
+  } else if (is_outgoing(this)) {
+    log_debug("sending again in %d ms", get_pkt_time(this));
+    conn_transmit_soon(conn, get_pkt_time(this));
+  }
+
+  // update last time
+  gettimeofday(&last_pkt, NULL);
+  return 0;
+}
+
+int embed::receive(conn_t *conn, struct evbuffer *dest) {
+  struct evbuffer *source = conn_get_inbound(conn);
+  short src_len = evbuffer_get_length(source);
+  short pkt_size = 0;
+
+  log_debug("receiving buffer of length %d", src_len);
+  
+  // if we are receiving the first packet of the trace, read the index
+  if (cur_idx == -1) {
+    if (evbuffer_remove(source, &cur_idx, 4) != 4) return -1;
+    cur = &embed_traces[cur_idx];
+    cur_pkt = 0;
+    pkt_size += 4;
+
+    log_debug("detected trace %d", cur_idx);
+  }
+
+  // keep reading data and padding from the source, advancing the packet
+  // in the trace when we have read enough bytes
+  while (1) {
+    // the next full packet is not in the source buffer yet
+    int exp_pkt_size = get_pkt_size(this);
+    if (src_len < exp_pkt_size) break;
+
+    // read data
+    short data_len;
+    if (evbuffer_remove(source, &data_len, 2) != 2) return -1;
+    if (data_len > 0) {
+      if (evbuffer_remove_buffer(source, dest, data_len) != data_len) {
+	return -1;
+      }
+    }
+    pkt_size += data_len + 2;
+    
+    // read padding
+    if (exp_pkt_size > pkt_size) {
+      size_t padding = exp_pkt_size - pkt_size;
+      if (evbuffer_drain(source, padding) == -1) return -1;
+    }
+    
+    src_len -= exp_pkt_size;
+    pkt_size = 0;
+
+    log_debug("received packet %d of trace %d",
+	      cur_pkt, cur_idx);
+    
+    // advance packet; if done with trace, sender should close connection
+    if (advance_packet(this)) {
+      conn_cease_transmission(conn);
+      conn_expect_close(conn);
+      log_debug("received last packet in trace");
+      return 0;
+    }
+  }
+
+  if (is_outgoing(this)) {
+    log_debug("preparing to send in %d ms", get_pkt_time(this));
+    conn_transmit_soon(conn, get_pkt_time(this));
+  }
+
+  log_debug("remaining source length: %d", src_len);
+
+  // update last time
+  gettimeofday(&last_pkt, NULL);
+  return 0;
+}





More information about the tor-commits mailing list