[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