tor-commits
Threads by month
- ----- 2025 -----
- July
- June
- May
- April
- March
- February
- January
- ----- 2024 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2023 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2022 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2021 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2020 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2019 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2018 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2017 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2016 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2015 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2014 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2013 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2012 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
- January
- ----- 2011 -----
- December
- November
- October
- September
- August
- July
- June
- May
- April
- March
- February
July 2012
- 14 participants
- 949 discussions

[stegotorus/master] Revert yesterday's disabling of the static_assert in rng.cc.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit efed3c6908bc5351a655545bb898b7be7cb0507c
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Wed Mar 28 09:02:09 2012 -0700
Revert yesterday's disabling of the static_assert in rng.cc.
---
src/rng.cc | 3 +--
1 files changed, 1 insertions(+), 2 deletions(-)
diff --git a/src/rng.cc b/src/rng.cc
index 149363e..cfddd87 100644
--- a/src/rng.cc
+++ b/src/rng.cc
@@ -128,10 +128,9 @@ rng_double()
unsigned int n;
};
-#if 0
static_assert(sizeof(double) == sizeof(uint64_t),…
[View More]
"this code works only with 64-bit, IEEE double");
-#endif
+
union ieee754_double {
double d;
uint64_t i;
[View Less]
1
0

[stegotorus/master] Add option to timestamp all logs. Fix some deadlocks in itestlib.py.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 99efcadc17b1d082589e2e8509be6555576b9301
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Wed Mar 28 19:12:45 2012 -0700
Add option to timestamp all logs. Fix some deadlocks in itestlib.py.
---
src/audit-globals.sh | 2 +
src/main.cc | 22 +++++++++---
src/test/itestlib.py | 94 +++++++++++++++++++++++++++----------------------
src/util.cc | 66 ++++++++++++++++++-----------------
src/util.h | 7 +++-
5 files changed, 111 insertions(+), …
[View More]80 deletions(-)
diff --git a/src/audit-globals.sh b/src/audit-globals.sh
index ec08b21..99739b3 100644
--- a/src/audit-globals.sh
+++ b/src/audit-globals.sh
@@ -39,6 +39,8 @@ sed '
/^rng rng$/d
/^util log_dest$/d
/^util log_min_sev$/d
+ /^util log_timestamps$/d
+ /^util log_ts_base$/d
/^util the_evdns_base$/d
/^crypt log_crypto()::initialized$/d
/^crypt init_crypto()::initialized$/d
diff --git a/src/main.cc b/src/main.cc
index db338af..1c8e55f 100644
--- a/src/main.cc
+++ b/src/main.cc
@@ -176,6 +176,7 @@ usage(void)
"--log-file=<file> ~ set logfile\n"
"--log-min-severity=warn|info|debug ~ set minimum logging severity\n"
"--no-log ~ disable logging\n"
+ "--timestamp-logs ~ add timestamps to all log messages\n"
"--allow-kqueue ~ allow use of kqueue(2) (may be buggy)\n");
exit(1);
@@ -188,6 +189,8 @@ usage(void)
If it succeeds it returns the number of argv arguments its caller
should skip to get past the optional arguments we already handled.
If it fails, it exits the program.
+
+ Note: this function should NOT use log_* to print diagnostics.
*/
static int
handle_generic_args(const char *const *argv)
@@ -195,28 +198,30 @@ handle_generic_args(const char *const *argv)
bool logmethod_set = false;
bool logsev_set = false;
bool allow_kq_set = false;
+ bool timestamps_set = false;
int i = 1;
while (argv[i] &&
!strncmp(argv[i],"--",2)) {
if (!strncmp(argv[i], "--log-file=", 11)) {
if (logmethod_set) {
- log_warn("you've already set a log file!");
+ fprintf(stderr, "you've already set a log file!\n");
exit(1);
}
if (log_set_method(LOG_METHOD_FILE,
(char *)argv[i]+11) < 0) {
- log_warn("failed creating logfile");
+ fprintf(stderr, "failed to open logfile '%s': %s\n", argv[i]+11,
+ strerror(errno));
exit(1);
}
logmethod_set=1;
} else if (!strncmp(argv[i], "--log-min-severity=", 19)) {
if (logsev_set) {
- log_warn("you've already set a min. log severity!");
+ fprintf(stderr, "you've already set a min. log severity!\n");
exit(1);
}
if (log_set_min_severity((char *)argv[i]+19) < 0) {
- log_warn("error at setting logging severity");
+ fprintf(stderr, "error at setting logging severity");
exit(1);
}
logsev_set = true;
@@ -230,6 +235,13 @@ handle_generic_args(const char *const *argv)
exit(1);
}
logsev_set = true;
+ } else if (!strcmp(argv[i], "--timestamp-logs")) {
+ if (timestamps_set) {
+ fprintf(stderr, "you've already asked for timestamps!\n");
+ exit(1);
+ }
+ log_enable_timestamps();
+ timestamps_set = true;
} else if (!strcmp(argv[i], "--allow-kqueue")) {
if (allow_kq_set) {
fprintf(stderr, "you've already allowed kqueue!\n");
@@ -238,7 +250,7 @@ handle_generic_args(const char *const *argv)
allow_kq = true;
allow_kq_set = true;
} else {
- log_warn("unrecognizable argument '%s'", argv[i]);
+ fprintf(stderr, "unrecognizable argument '%s'", argv[i]);
exit(1);
}
i++;
diff --git a/src/test/itestlib.py b/src/test/itestlib.py
index 60d082e..1c483f3 100644
--- a/src/test/itestlib.py
+++ b/src/test/itestlib.py
@@ -10,6 +10,8 @@ import subprocess
import threading
import time
+TIMEOUT_LEN = 5 # seconds
+
# Helper: stick "| " at the beginning of each line of |s|.
def indent(s):
@@ -39,9 +41,13 @@ def diff(label, expected, received):
# elsewhere. Mode 2 is "abort immediately, without flooding
# /dev/tty with useless diagnostics" (the documentation SAYS
# they go to stderr, but they don't).
+
+# there is an as-yet-not-pinned-down bug, probably in libevent, that
+# causes deadlocks on OSX when kqueue is allowed.
stegotorus_env = {}
stegotorus_env.update(os.environ)
stegotorus_env['MALLOC_CHECK_'] = '2'
+stegotorus_env['EVENT_NOKQUEUE'] = '1'
# check for a grinder
if 'GRINDER' in stegotorus_env:
@@ -52,7 +58,8 @@ else:
class Stegotorus(subprocess.Popen):
def __init__(self, *args, **kwargs):
argv = stegotorus_grindv[:]
- argv.extend(("./stegotorus", "--log-min-severity=debug"))
+ argv.extend(("./stegotorus", "--log-min-severity=debug",
+ "--timestamp-logs"))
if len(args) == 1 and (isinstance(args[0], list) or
isinstance(args[0], tuple)):
@@ -69,23 +76,30 @@ class Stegotorus(subprocess.Popen):
**kwargs)
# wait for startup completion, which is signaled by
# the subprocess closing its stdout
- self.stdout.read()
+ self.output = self.stdout.read()
+ # read stderr in a separate thread, since we will
+ # have several processes outstanding at the same time
+ self.communicator = threading.Thread(target=self.run_communicate)
+ self.communicator.start()
+ self.timeout = threading.Timer(TIMEOUT_LEN, self.stop)
+ self.timeout.start()
severe_error_re = re.compile(
r"\[(?:warn|err(?:or)?)\]|ERROR SUMMARY: [1-9]|LEAK SUMMARY:")
- def check_completion(self, label, force_stderr=False):
+ def stop(self):
if self.poll() is None:
- # subprocess.communicate has no timeout; arrange to blow
- # the process away if it doesn't respond to the initial
- # shutdown request in a timely fashion.
- timeout = threading.Thread(target=self.stop, args=(1.0,))
- timeout.daemon = True
- timeout.start()
-
- # this will close the subprocess's stdin as its first act, which
- # will trigger a clean shutdown
- (out, err) = self.communicate()
+ self.terminate()
+
+ def run_communicate(self):
+ self.errput = self.stderr.read()
+
+ def check_completion(self, label, force_stderr=False):
+ self.stdin.close()
+ self.communicator.join()
+ self.timeout.cancel()
+ self.timeout.join()
+ self.poll()
report = ""
@@ -96,25 +110,18 @@ class Stegotorus(subprocess.Popen):
report += label + " killed: signal %d\n" % -self.returncode
# there should be nothing on stdout
- if out != "":
- report += label + " stdout:\n%s\n" % indent(out)
+ if self.output != "":
+ report += label + " stdout:\n%s\n" % indent(self.output)
# there will be debugging messages on stderr, but there should be
# no [warn], [err], or [error] messages.
if (force_stderr or
- self.severe_error_re.search(err) or
+ self.severe_error_re.search(self.errput) or
self.returncode != 0):
- report += label + " stderr:\n%s\n" % indent(err)
+ report += label + " stderr:\n%s\n" % indent(self.errput)
return report
- def stop(self, delay=None):
- if self.poll() is None:
- if delay is not None:
- time.sleep(delay)
- if self.poll() is not None: return
- self.terminate()
-
# As above, but for the 'tltester' test helper rather than for
# stegotorus itself.
class Tltester(subprocess.Popen):
@@ -129,37 +136,40 @@ class Tltester(subprocess.Popen):
env=stegotorus_env,
close_fds=True,
**kwargs)
-
- def stop(self, delay=None):
+ # invoke communicate() in a separate thread, since we will
+ # have several processes outstanding at the same time
+ self.communicator = threading.Thread(target=self.run_communicate)
+ self.communicator.start()
+ self.timeout = threading.Timer(TIMEOUT_LEN, self.stop)
+ self.timeout.start()
+
+ def stop(self):
if self.poll() is None:
- if delay is not None:
- time.sleep(delay)
- if self.poll() is not None: return
self.terminate()
- def check_completion(self, label):
- if self.poll() is None:
- # subprocess.communicate has no timeout; arrange to blow
- # the process away if it doesn't finish what it's doing in
- # a timely fashion.
- timeout = threading.Thread(target=self.stop, args=(2.0,))
- timeout.daemon = True
- timeout.start()
-
+ def run_communicate(self):
(out, err) = self.communicate()
+ self.output = out
+ self.errput = err
+
+ def check_completion(self, label):
+ self.communicator.join()
+ self.timeout.cancel()
+ self.timeout.join()
+ self.poll()
# exit status should be zero, and there should be nothing on
# stderr
- if self.returncode != 0 or err != "":
+ if self.returncode != 0 or self.errput != "":
report = ""
# exit status should be zero
if self.returncode > 0:
report += label + " exit code: %d\n" % self.returncode
elif self.returncode < 0:
report += label + " killed: signal %d\n" % -self.returncode
- if err != "":
- report += label + " stderr:\n%s\n" % indent(err)
+ if self.errput != "":
+ report += label + " stderr:\n%s\n" % indent(self.errput)
raise AssertionError(report)
# caller will crunch the output
- return out
+ return self.output
diff --git a/src/util.cc b/src/util.cc
index 7273671..b813ae9 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -402,6 +402,9 @@ ascii_strlower(char *s)
static FILE *log_dest;
/* minimum logging severity */
static int log_min_sev = LOG_SEV_INFO;
+/* whether timestamps are wanted */
+static bool log_timestamps = false;
+static struct timeval log_ts_base = { 0, 0 };
/** Helper: map a log severity to descriptive string. */
static const char *
@@ -473,7 +476,7 @@ log_open(const char *filename)
Ignores errors.
*/
void
-log_close(void)
+log_close()
{
if (log_dest && log_dest != stderr)
fclose(log_dest);
@@ -523,11 +526,19 @@ log_set_min_severity(const char* sev_string)
return 0;
}
+/** Enable timestamps on all log messages. */
+void
+log_enable_timestamps()
+{
+ log_timestamps = true;
+ gettimeofday(&log_ts_base, 0);
+}
+
/** True if the minimum log severity is "debug". Used in a few places
to avoid some expensive formatting work if we are going to ignore the
result. */
int
-log_do_debug(void)
+log_do_debug()
{
return log_min_sev == LOG_SEV_DEBUG;
}
@@ -550,7 +561,7 @@ logv(int severity, const char *format, va_list ap)
putc('\n', log_dest);
}
-static void
+static bool
logpfx(int severity, const char *fn)
{
if (!sev_is_valid(severity))
@@ -558,48 +569,39 @@ logpfx(int severity, const char *fn)
/* See if the user is interested in this log message. */
if (!log_dest || severity < log_min_sev)
- return;
+ return false;
+
+ if (log_timestamps) {
+ struct timeval now, delta;
+ gettimeofday(&now, 0);
+ timeval_subtract(&now, &log_ts_base, &delta);
+ fprintf(log_dest, "%.4f ",
+ delta.tv_sec + double(delta.tv_usec) / 1e6);
+ }
fprintf(log_dest, "[%s] ", sev_to_string(severity));
if (log_min_sev == LOG_SEV_DEBUG && fn)
fprintf(log_dest, "%s: ", fn);
+ return true;
}
static void
logpfx(int severity, const char *fn, circuit_t *ckt)
{
- if (!sev_is_valid(severity))
- abort();
-
- /* See if the user is interested in this log message. */
- if (!log_dest || severity < log_min_sev)
- return;
-
- fprintf(log_dest, "[%s] ", sev_to_string(severity));
- if (log_min_sev == LOG_SEV_DEBUG && fn)
- fprintf(log_dest, "%s: ", fn);
- if (ckt)
- fprintf(log_dest, "<%u> ", ckt->serial);
+ if (logpfx(severity, fn))
+ if (ckt)
+ fprintf(log_dest, "<%u> ", ckt->serial);
}
static void
logpfx(int severity, const char *fn, conn_t *conn)
{
- if (!sev_is_valid(severity))
- abort();
-
- /* See if the user is interested in this log message. */
- if (!log_dest || severity < log_min_sev)
- return;
-
- fprintf(log_dest, "[%s] ", sev_to_string(severity));
- if (log_min_sev == LOG_SEV_DEBUG && fn)
- fprintf(log_dest, "%s: ", fn);
- if (conn) {
- circuit_t *ckt = conn->circuit();
- unsigned int ckt_serial = ckt ? ckt->serial : 0;
- fprintf(log_dest, "<%u.%u> ", ckt_serial, conn->serial);
- }
+ if (logpfx(severity, fn))
+ if (conn) {
+ circuit_t *ckt = conn->circuit();
+ unsigned int ckt_serial = ckt ? ckt->serial : 0;
+ fprintf(log_dest, "<%u.%u> ", ckt_serial, conn->serial);
+ }
}
/**** Public logging API. ****/
@@ -722,7 +724,7 @@ int timeval_subtract(struct timeval *x, struct timeval *y,
y->tv_sec -= nsec;
}
- /* Compute the time remaining to wait.
+ /* Compute the time remaining to wait.
tv_usec is certainly positive. */
result->tv_sec = x->tv_sec - y->tv_sec;
result->tv_usec = x->tv_usec - y->tv_usec;
diff --git a/src/util.h b/src/util.h
index 32750c1..05bc6d0 100644
--- a/src/util.h
+++ b/src/util.h
@@ -171,7 +171,12 @@ int log_set_method(int method, const char *filename);
'sev_string' may be "warn", "info", or "debug" (case-insensitively). */
int log_set_min_severity(const char* sev_string);
-/** True if debug messages are being logged. */
+/** Request timestamps on all log messages. */
+void log_enable_timestamps();
+
+/** True if debug messages are being logged. Guard expensive debugging
+ checks with this, to avoid doing useless work when the messages are
+ just going to be thrown away anyway. */
int log_do_debug(void);
/** Close the logfile if it's open. Ignores errors. */
[View Less]
1
0

[stegotorus/master] * Downgrade "connection reset" from log_warn to log_info.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 38e21c79e997422cad8117ed3b9e48bc0b4e4d33
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Wed Mar 28 20:34:04 2012 -0700
* Downgrade "connection reset" from log_warn to log_info.
* Do not allow a nosteg_rr connection to become usable again after it has
transmitted, just because its receive method gets called again.
---
src/network.cc | 4 ++--
src/steg/nosteg_rr.cc | 7 +++++--
2 files changed, 7 insertions(+), 4 deletions(-)
diff --git a/src/network.cc …
[View More]b/src/network.cc
index 794e4e2..7eac64d 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -333,7 +333,7 @@ upstream_event_cb(struct bufferevent *bev, short what, void *arg)
if (what & (BEV_EVENT_ERROR|BEV_EVENT_EOF|BEV_EVENT_TIMEOUT)) {
if (what & BEV_EVENT_ERROR)
- log_warn(ckt, "network error in %s: %s",
+ log_info(ckt, "network error in %s: %s",
(what & BEV_EVENT_READING) ? "read" : "write",
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
else if (what & BEV_EVENT_EOF)
@@ -377,7 +377,7 @@ downstream_event_cb(struct bufferevent *bev, short what, void *arg)
if (what & (BEV_EVENT_ERROR|BEV_EVENT_EOF|BEV_EVENT_TIMEOUT)) {
if (what & BEV_EVENT_ERROR)
- log_warn(conn, "network error in %s: %s",
+ log_info(conn, "network error in %s: %s",
(what & BEV_EVENT_READING) ? "read" : "write",
evutil_socket_error_to_string(EVUTIL_SOCKET_ERROR()));
else if (what & BEV_EVENT_EOF)
diff --git a/src/steg/nosteg_rr.cc b/src/steg/nosteg_rr.cc
index a586d0a..70e376e 100644
--- a/src/steg/nosteg_rr.cc
+++ b/src/steg/nosteg_rr.cc
@@ -42,6 +42,7 @@ namespace {
struct nosteg_rr : steg_t
{
bool can_transmit : 1;
+ bool did_transmit : 1;
STEG_DECLARE_METHODS(nosteg_rr);
};
}
@@ -50,7 +51,8 @@ STEG_DEFINE_MODULE(nosteg_rr);
nosteg_rr::nosteg_rr(bool is_clientside)
: steg_t(is_clientside),
- can_transmit(is_clientside)
+ can_transmit(is_clientside),
+ did_transmit(false)
{
}
@@ -79,6 +81,7 @@ nosteg_rr::transmit(struct evbuffer *source, conn_t *conn)
return -1;
}
+ did_transmit = true;
can_transmit = false;
conn->cease_transmission();
@@ -101,7 +104,7 @@ nosteg_rr::receive(conn_t *conn, struct evbuffer *dest)
if (is_clientside) {
conn->expect_close();
- } else {
+ } else if (!did_transmit) {
can_transmit = true;
conn->transmit_soon(100);
}
[View Less]
1
0

[stegotorus/master] More tiny bugfixes - test suite now reliable on OSX
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 2021bfe0d20eab807bd3a8276ef0cccc9c106a73
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Thu Mar 29 09:06:27 2012 -0700
More tiny bugfixes - test suite now reliable on OSX
---
src/protocol/chop.cc | 12 +++++++-----
src/protocol/null.cc | 9 ++++++++-
2 files changed, 15 insertions(+), 6 deletions(-)
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index 44e79a3..cf64e6c 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -236,6 +236,8 @@ public:
{…
[View More]
reassembly_elt rv = { 0, op_DAT };
uint8_t front = next_to_process & 0xFF;
+ log_debug("next_to_process=%d data=%p op=%02x",
+ next_to_process, cbuf[front].data, cbuf[front].op);
if (cbuf[front].data) {
rv = cbuf[front];
cbuf[front].data = 0;
@@ -255,14 +257,14 @@ public:
insert(uint32_t seqno, opcode_t op, evbuffer *data, conn_t *conn)
{
if (seqno - window() > 255) {
- log_warn(conn, "block outside receive window");
+ log_info(conn, "block outside receive window");
evbuffer_free(data);
return false;
}
uint8_t front = next_to_process & 0xFF;
uint8_t pos = front + (seqno - window());
if (cbuf[pos].data) {
- log_warn(conn, "duplicate block");
+ log_info(conn, "duplicate block");
evbuffer_free(data);
return false;
}
@@ -1193,7 +1195,7 @@ chop_conn_t::recv()
block_header hdr(recv_pending, *upstream->recv_hdr_crypt);
if (!hdr.valid(upstream->recv_queue.window())) {
const uint8_t *c = hdr.cleartext();
- log_warn(this, "invalid block header: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
+ log_info(this, "invalid block header: %02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x%02x",
c[0], c[1], c[2], c[3], c[4], c[5], c[6], c[7],
c[8], c[9], c[10], c[11], c[12], c[13], c[14], c[15]);
return -1;
@@ -1214,11 +1216,11 @@ chop_conn_t::recv()
if (upstream->recv_crypt->decrypt(decodebuf,
decodebuf, hdr.total_len() - HEADER_LEN,
hdr.nonce(), HEADER_LEN)) {
- log_warn("MAC verification failure");
+ log_info("MAC verification failure");
return -1;
}
- log_debug(this, "receiving block %u <d=%lu p=%lu f=%u>",
+ log_debug(this, "receiving block %u <d=%lu p=%lu f=%02x>",
hdr.seqno(), (unsigned long)hdr.dlen(), (unsigned long)hdr.plen(),
(unsigned int)hdr.opcode());
diff --git a/src/protocol/null.cc b/src/protocol/null.cc
index 989ffd4..277eb59 100644
--- a/src/protocol/null.cc
+++ b/src/protocol/null.cc
@@ -137,7 +137,10 @@ null_circuit_t::~null_circuit_t()
/* break the circular reference before deallocating the
downstream connection */
downstream->upstream = NULL;
- delete downstream;
+ if (evbuffer_get_length(downstream->outbound()) > 0)
+ conn_do_flush(downstream);
+ else
+ delete downstream;
}
}
@@ -191,6 +194,9 @@ null_circuit_t::drop_downstream(conn_t *cn)
int
null_circuit_t::send()
{
+ log_debug(this, "sending %lu bytes",
+ evbuffer_get_length(bufferevent_get_input(this->up_buffer)));
+
return evbuffer_add_buffer(this->downstream->outbound(),
bufferevent_get_input(this->up_buffer));
}
@@ -261,6 +267,7 @@ int
null_conn_t::recv()
{
log_assert(this->upstream);
+ log_debug(this, "receiving %lu bytes", evbuffer_get_length(this->inbound()));
return evbuffer_add_buffer(bufferevent_get_output(this->upstream->up_buffer),
this->inbound());
}
[View Less]
1
0

[stegotorus/master] Split up steg_t into per-connection and per-listener state objects.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 0448e1cc8aaaa5b4d71277b9738cfa5b33268212
Author: Zack Weinberg <zackw(a)panix.com>
Date: Thu Mar 29 17:45:25 2012 -0700
Split up steg_t into per-connection and per-listener state objects.
This will facilitate the removal of the global variables in embed and http
so that they work in multi-listener mode, and the addition of configurable
parameters to steg modules (such as the location of the trace files).
---
src/protocol/chop.cc | 26 +++++-----
src/steg.…
[View More]cc | 13 +++--
src/steg.h | 126 +++++++++++++++++++++++++++++++-----------------
src/steg/embed.cc | 122 ++++++++++++++++++++++++++++++++++-------------
src/steg/http.cc | 83 ++++++++++++++++++++++++---------
src/steg/nosteg.cc | 50 +++++++++++++++----
src/steg/nosteg_rr.cc | 62 ++++++++++++++++++------
7 files changed, 339 insertions(+), 143 deletions(-)
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index cf64e6c..06346b7 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -371,7 +371,7 @@ struct chop_config_t : config_t
{
struct evutil_addrinfo *up_address;
vector<struct evutil_addrinfo *> down_addresses;
- vector<const char *> steg_targets;
+ vector<steg_config_t *> steg_targets;
chop_circuit_table circuits;
CONFIG_DECLARE_METHODS(chop);
@@ -392,7 +392,9 @@ chop_config_t::~chop_config_t()
i != down_addresses.end(); i++)
evutil_freeaddrinfo(*i);
- // The strings in steg_targets are not on the heap.
+ for (vector<steg_config_t *>::iterator i = steg_targets.begin();
+ i != steg_targets.end(); i++)
+ delete *i;
for (chop_circuit_table::iterator i = circuits.begin();
i != circuits.end(); i++)
@@ -454,7 +456,7 @@ chop_config_t::init(int n_options, const char *const *options)
log_warn("chop: steganographer '%s' not supported", options[i]);
goto usage;
}
- steg_targets.push_back(options[i]);
+ steg_targets.push_back(steg_new(options[i], this));
}
return true;
@@ -744,7 +746,7 @@ chop_circuit_t::send_targeted(chop_conn_t *conn)
avail = SECTION_LEN;
avail += MIN_BLOCK_SIZE;
- size_t room = conn->steg->transmit_room(conn);
+ size_t room = conn->steg->transmit_room();
if (room < MIN_BLOCK_SIZE) {
log_warn(conn, "send() called without enough transmit room "
"(have %lu, need %lu)", (unsigned long)room,
@@ -752,7 +754,7 @@ chop_circuit_t::send_targeted(chop_conn_t *conn)
return -1;
}
log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room,
- conn->steg->name());
+ conn->steg->cfg()->name());
if (room < avail)
avail = room;
@@ -868,7 +870,7 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize)
if (conn->steg) {
// Find the connections whose transmit rooms are closest to the
// desired transmission length from both directions.
- size_t room = conn->steg->transmit_room(conn);
+ size_t room = conn->steg->transmit_room();
if (room <= MIN_BLOCK_SIZE)
room = 0;
@@ -877,7 +879,7 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize)
room = MAX_BLOCK_SIZE;
log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room,
- conn->steg->name());
+ conn->steg->cfg()->name());
if (room >= desired) {
if (room < minabove) {
@@ -1029,7 +1031,7 @@ chop_config_t::conn_create(size_t index)
{
chop_conn_t *conn = new chop_conn_t;
conn->config = this;
- conn->steg = steg_new(steg_targets.at(index), mode != LSN_SIMPLE_SERVER);
+ conn->steg = steg_targets.at(index)->steg_create(conn);
if (!conn->steg) {
free(conn);
return 0;
@@ -1082,7 +1084,7 @@ chop_conn_t::send(struct evbuffer *block)
}
}
- if (steg->transmit(block, this)) {
+ if (steg->transmit(block)) {
log_warn(this, "failed to transmit block");
return -1;
}
@@ -1154,7 +1156,7 @@ chop_conn_t::recv_handshake()
int
chop_conn_t::recv()
{
- if (steg->receive(this, recv_pending))
+ if (steg->receive(recv_pending))
return -1;
if (!upstream) {
@@ -1320,7 +1322,7 @@ chop_conn_t::send()
} else {
log_debug(this, "must send (no upstream)");
- size_t room = steg->transmit_room(this);
+ size_t room = steg->transmit_room();
if (room < MIN_BLOCK_SIZE) {
log_warn(this, "send() called without enough transmit room "
"(have %lu, need %lu)", (unsigned long)room,
@@ -1351,7 +1353,7 @@ chop_conn_t::send()
return;
}
- if (steg->transmit(chaff, this))
+ if (steg->transmit(chaff))
conn_do_flush(this);
evbuffer_free(chaff);
diff --git a/src/steg.cc b/src/steg.cc
index 8db5498..12ea291 100644
--- a/src/steg.cc
+++ b/src/steg.cc
@@ -18,16 +18,17 @@ steg_is_supported(const char *name)
}
/* Instantiate a steg module by name. */
-steg_t *
-steg_new(const char *name, bool is_clientside)
+steg_config_t *
+steg_new(const char *name, config_t *cfg)
{
const steg_module *const *s;
for (s = supported_stegs; *s; s++)
if (!strcmp(name, (**s).name))
- return (**s).new_(is_clientside);
- return NULL;
+ return (**s).new_(cfg);
+ return 0;
}
-/* Define this here rather than in the class definition so that the
- vtable will be emitted in only one place. */
+/* Define these here rather than in the class definition so that the
+ vtables will be emitted in only one place. */
+steg_config_t::~steg_config_t() {}
steg_t::~steg_t() {}
diff --git a/src/steg.h b/src/steg.h
index dab44e5..a044afb 100644
--- a/src/steg.h
+++ b/src/steg.h
@@ -5,42 +5,73 @@
#ifndef STEG_H
#define STEG_H
-/** A steganography instance must define a private subclass of this
- type, that implements all of the methods below, plus a descendant
- constructor. The subclass must have exactly the same name that
- you use for the module name in STEG_DEFINE_MODULE, and should be
- declared inside an anonymous namespace. Use STEG_DECLARE_METHODS
- in the declaration. */
-struct steg_t
+/** A 'steg_config_t' is analogous to a 'config_t' (see protocol.h);
+ it defines cross-connection state for a steganography module.
+ (A 'config_t' may be associated with several 'steg_config_t's.)
+
+ A steganography module must define a private subclass of this
+ type, that implements all the methods below, plus a descendant
+ constructor. The subclass must have the name MODULE_steg_config_t,
+ where MODULE is the module name you use in STEG_DEFINE_MODULE.
+ It should be declared inside an anonymous namespace.
+ Use STEG_CONFIG_DECLARE_METHODS in the declaration. */
+
+struct steg_t;
+
+struct steg_config_t
{
- bool is_clientside : 1;
+ struct config_t *cfg;
- steg_t(bool is_clientside) : is_clientside(is_clientside) {}
- virtual ~steg_t();
+ steg_config_t(config_t *c) : cfg(c) {}
+ virtual ~steg_config_t();
/** Report the name of this steg module. You do not have to define
this method in your subclass, STEG_DEFINE_MODULE does it for you. */
virtual const char *name() = 0;
+ /** Create an extended 'steg_t' object (see below) from this
+ configuration, associated with connection CONN. */
+ virtual steg_t *steg_create(conn_t *conn) = 0;
+};
+
+/** A 'steg_t' object handles the actual steganography for one
+ connection, and is responsible for tracking per-connection
+ state for the cover protocol, if any.
+
+ Again, a steganography module must define a private subclass of
+ this type, that implements all of the methods below, plus a
+ descendant constructor. The subclass must have the name
+ MODULE_steg_t, where MODULE is the module name you use in
+ STEG_DEFINE_MODULE. It should be declared inside an anonymous
+ namespace. Use STEG_DECLARE_METHODS in the declaration. */
+struct steg_t
+{
+ steg_t() {}
+ virtual ~steg_t();
+
+ /** Return the steg_config_t from which this steg_t was created. */
+ virtual steg_config_t *cfg() = 0;
+
/** Report the maximum number of bytes that could be transmitted on
- connection CONN at this time. You must be prepared to handle a
+ your connection at this time. You must be prepared to handle a
subsequent request to transmit any _smaller_ number of bytes on
this connection. */
- virtual size_t transmit_room(conn_t *conn) = 0;
+ virtual size_t transmit_room() = 0;
/** Consume all of the data in SOURCE, disguise it, and write it to
- the outbound buffer for CONN. Return 0 on success, -1 on failure. */
- virtual int transmit(struct evbuffer *source, conn_t *conn) = 0;
-
- /** The data in CONN's inbound buffer should have been disguised by
- the peer instance to STATE. Unmask it and write it to DEST.
- Return 0 on success, -1 on failure. If more data needs to come
- over the wire before anything can be unmasked, that is *not* a
- failure condition; return 0, but do not consume any data or
- write anything to DEST. It is *preferable*, but not currently
- *required*, for this method to not consume any data or write
- anything to DEST in a failure situation. */
- virtual int receive(conn_t *conn, struct evbuffer *dest) = 0;
+ the outbound buffer for your connection. Return 0 on success, -1
+ on failure. */
+ virtual int transmit(struct evbuffer *source) = 0;
+
+ /** Unmask as much of the data in your connection's inbound buffer
+ as possible, and write it to DEST. Return 0 on success, -1 on
+ failure. If more data needs to come over the wire before
+ anything can be unmasked, that is *not* a failure condition;
+ return 0, but do not consume any data or write anything to DEST.
+ It is *preferable*, but not currently *required*, for this
+ method to not consume any data or write anything to DEST in a
+ failure situation. */
+ virtual int receive(struct evbuffer *dest) = 0;
};
/** STEG_DEFINE_MODULE defines an object with this type, plus the
@@ -52,38 +83,43 @@ struct steg_module
/** Name of the steganography module. Must be a valid C identifier. */
const char *name;
- /** Create an appropriate steg_t subclass for this module.
- More arguments may be added later. */
- steg_t *(*new_)(bool is_clientside);
+ /** Create an appropriate steg_config_t subclass for this module. */
+ steg_config_t *(*new_)(config_t *cfg);
};
extern const steg_module *const supported_stegs[];
int steg_is_supported(const char *name);
-steg_t *steg_new(const char *name, bool is_clientside);
+steg_config_t *steg_new(const char *name, config_t *cfg);
/* Macros for use in defining steg modules. */
-#define STEG_DEFINE_MODULE(mod) \
- /* new_ dispatchers */ \
- static steg_t *mod##_new(bool is_clientside) \
- { return new mod(is_clientside); } \
- \
- /* canned methods */ \
- const char *mod::name() { return #mod; } \
- \
- /* module object */ \
- extern const steg_module s_mod_##mod = { \
- #mod, mod##_new \
+#define STEG_DEFINE_MODULE(mod) \
+ /* new_ dispatchers */ \
+ static steg_config_t *mod##_new(config_t *cfg) \
+ { return new mod##_steg_config_t(cfg); } \
+ \
+ /* canned methods */ \
+ const char *mod##_steg_config_t::name() { return #mod; } \
+ \
+ /* module object */ \
+ extern const steg_module s_mod_##mod = { \
+ #mod, mod##_new \
} /* deliberate absence of semicolon */
-#define STEG_DECLARE_METHODS(mod) \
- mod(bool is_clientside); \
- virtual ~mod(); \
+#define STEG_CONFIG_DECLARE_METHODS(mod) \
+ mod##_steg_config_t(config_t *cfg); \
+ virtual ~mod##_steg_config_t(); \
virtual const char *name(); \
- virtual size_t transmit_room(conn_t *conn); \
- virtual int transmit(struct evbuffer *source, conn_t *conn); \
- virtual int receive(conn_t *conn, struct evbuffer *dest) \
+ virtual steg_t *steg_create(conn_t *conn) \
+ /* deliberate absence of semicolon */
+
+#define STEG_DECLARE_METHODS(mod) \
+ virtual ~mod##_steg_t(); \
+ virtual steg_config_t *cfg(); \
+ virtual size_t transmit_room(); \
+ virtual int transmit(struct evbuffer *source); \
+ virtual int receive(struct evbuffer *dest) \
/* deliberate absence of semicolon */
#endif
diff --git a/src/steg/embed.cc b/src/steg/embed.cc
index e2f12a0..6559bf7 100644
--- a/src/steg/embed.cc
+++ b/src/steg/embed.cc
@@ -1,5 +1,6 @@
#include "util.h"
#include "connections.h"
+#include "protocol.h"
#include "steg.h"
#include "rng.h"
@@ -9,19 +10,30 @@
#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 {
+ 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
+ };
+
+ struct embed_steg_config_t : steg_config_t {
+ bool is_clientside;
+
+ STEG_CONFIG_DECLARE_METHODS(embed);
+ };
+
+ struct embed_steg_t : steg_t {
+ embed_steg_config_t *config;
+ conn_t *conn;
+
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
+ embed_steg_t(embed_steg_config_t *cf, conn_t *cn);
+
STEG_DECLARE_METHODS(embed);
bool advance_packet();
@@ -32,13 +44,15 @@ namespace {
};
}
+STEG_DEFINE_MODULE(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);
-
-int millis_since(struct timeval *last) {
+static int
+millis_since(struct timeval *last)
+{
struct timeval cur;
int diff = 0;
gettimeofday(&cur, NULL);
@@ -48,13 +62,31 @@ int millis_since(struct timeval *last) {
return diff;
}
-void init_embed_traces() {
+embed_steg_config_t::embed_steg_config_t(config_t *cfg)
+ : steg_config_t(cfg),
+ is_clientside(cfg->mode != LSN_SIMPLE_SERVER)
+{
+}
+
+embed_steg_config_t::~embed_steg_config_t()
+{
+}
+
+steg_t *
+embed_steg_config_t::steg_create(conn_t *conn)
+{
+ return new embed_steg_t(this, conn);
+}
+
+static void
+init_embed_traces()
+{
// read in traces to use for connections
FILE *trace_file = fopen("traces/embed.txt", "r");
if (fscanf(trace_file, "%d", &embed_num_traces) < 1) {
log_abort("couldn't read number of traces to use -- exiting");
exit(1);
- }
+ }
embed_traces = (trace_t *)xmalloc(sizeof(trace_t) * embed_num_traces);
for (int i = 0; i < embed_num_traces; i++) {
int num_pkt;
@@ -67,10 +99,10 @@ void init_embed_traces() {
embed_traces[i].pkt_times = (int *)xmalloc(sizeof(int) * num_pkt);
for (int j = 0; j < embed_traces[i].num_pkt; j++) {
if (fscanf(trace_file, "%hd %d",
- &embed_traces[i].pkt_sizes[j],
- &embed_traces[i].pkt_times[j]) < 1) {
- log_abort("couldn't read numbers of packet size and times to use -- exiting");
- exit(1);
+ &embed_traces[i].pkt_sizes[j],
+ &embed_traces[i].pkt_times[j]) < 1) {
+ log_abort("couldn't read numbers of packet size and times to use -- exiting");
+ exit(1);
}
}
}
@@ -79,39 +111,51 @@ void init_embed_traces() {
embed_init = 1;
}
-int get_random_trace() {
+static int
+get_random_trace()
+{
return rng_int(embed_num_traces);
}
-bool embed::advance_packet() {
+bool
+embed_steg_t::advance_packet()
+{
cur_pkt++;
return cur_pkt == cur->num_pkt;
}
-short embed::get_pkt_size() {
+short
+embed_steg_t::get_pkt_size()
+{
return abs(cur->pkt_sizes[cur_pkt]);
}
-bool embed::is_outgoing() {
- return (cur->pkt_sizes[cur_pkt] < 0) ^ is_clientside;
+bool
+embed_steg_t::is_outgoing()
+{
+ return (cur->pkt_sizes[cur_pkt] < 0) ^ config->is_clientside;
}
-int embed::get_pkt_time() {
+int
+embed_steg_t::get_pkt_time()
+{
return cur->pkt_times[cur_pkt];
}
-bool embed::is_finished() {
+bool
+embed_steg_t::is_finished()
+{
if (cur_idx == -1) return true;
return cur_pkt >= cur->num_pkt;
}
-embed::embed(bool is_clientside)
- : steg_t(is_clientside)
+embed_steg_t::embed_steg_t(embed_steg_config_t *cf, conn_t *cn)
+ : config(cf), conn(cn)
{
if (!embed_init) init_embed_traces();
cur_idx = -1;
- if (is_clientside) {
+ if (config->is_clientside) {
cur_idx = get_random_trace();
cur = &embed_traces[cur_idx];
cur_pkt = 0;
@@ -119,11 +163,19 @@ embed::embed(bool is_clientside)
gettimeofday(&last_pkt, NULL);
}
-embed::~embed()
+embed_steg_t::~embed_steg_t()
+{
+}
+
+steg_config_t *
+embed_steg_t::cfg()
{
+ return config;
}
-size_t embed::transmit_room(conn_t * /* conn */) {
+size_t
+embed_steg_t::transmit_room()
+{
if (is_finished() || !is_outgoing()) return 0;
int time_diff = millis_since(&last_pkt);
@@ -135,7 +187,9 @@ size_t embed::transmit_room(conn_t * /* conn */) {
return room;
}
-int embed::transmit(struct evbuffer *source, conn_t *conn) {
+int
+embed_steg_t::transmit(struct evbuffer *source)
+{
struct evbuffer *dest = conn->outbound();
short src_len = evbuffer_get_length(source);
short pkt_size = get_pkt_size();
@@ -177,13 +231,15 @@ int embed::transmit(struct evbuffer *source, conn_t *conn) {
return 0;
}
-int embed::receive(conn_t *conn, struct evbuffer *dest) {
+int
+embed_steg_t::receive(struct evbuffer *dest)
+{
struct evbuffer *source = conn->inbound();
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;
@@ -206,7 +262,7 @@ int embed::receive(conn_t *conn, struct evbuffer *dest) {
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;
+return -1;
}
}
pkt_size += data_len + 2;
@@ -221,7 +277,7 @@ int embed::receive(conn_t *conn, struct evbuffer *dest) {
pkt_size = 0;
log_debug("received packet %d of trace %d",
- cur_pkt, cur_idx);
+ cur_pkt, cur_idx);
// advance packet; if done with trace, sender should close connection
if (advance_packet()) {
diff --git a/src/steg/http.cc b/src/steg/http.cc
index 5a78ffe..05ab940 100644
--- a/src/steg/http.cc
+++ b/src/steg/http.cc
@@ -34,6 +34,7 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "util.h"
#include "connections.h"
+#include "protocol.h"
#include "steg.h"
#include "payloads.h"
#include "cookies.h"
@@ -60,20 +61,48 @@ static int has_peer_name = 0;
static char peername[512];
namespace {
-struct http : steg_t
-{
- bool have_transmitted : 1;
- bool have_received : 1;
- int type;
+ struct http_steg_config_t : steg_config_t
+ {
+ bool is_clientside : 1;
+
+ STEG_CONFIG_DECLARE_METHODS(http);
+ };
+
+ struct http_steg_t : steg_t
+ {
+ http_steg_config_t *config;
+ conn_t *conn;
+
+ bool have_transmitted : 1;
+ bool have_received : 1;
+ int type;
- STEG_DECLARE_METHODS(http);
-};
+ http_steg_t(http_steg_config_t *cf, conn_t *cn);
+ STEG_DECLARE_METHODS(http);
+ };
}
STEG_DEFINE_MODULE(http);
-int http_client_uri_transmit (steg_t *s, struct evbuffer *source, conn_t *conn);
-int http_client_cookie_transmit (steg_t *s, struct evbuffer *source, conn_t *conn);
+http_steg_config_t::http_steg_config_t(config_t *cfg)
+ : steg_config_t(cfg),
+ is_clientside(cfg->mode != LSN_SIMPLE_SERVER)
+{
+}
+
+http_steg_config_t::~http_steg_config_t()
+{
+}
+
+steg_t *
+http_steg_config_t::steg_create(conn_t *conn)
+{
+ return new http_steg_t(this, conn);
+}
+
+
+int http_client_uri_transmit (http_steg_t *s, struct evbuffer *source, conn_t *conn);
+int http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source, conn_t *conn);
void evbuffer_dump(struct evbuffer *buf, FILE *out);
void buf_dump(unsigned char* buf, int len, FILE *out);
@@ -128,11 +157,11 @@ buf_dump(unsigned char* buf, int len, FILE *out)
}
-http::http(bool is_clientside)
- : steg_t(is_clientside),
+http_steg_t::http_steg_t(http_steg_config_t *cf, conn_t *cn)
+ : config(cf), conn(cn),
have_transmitted(false), have_received(false)
{
- if (is_clientside)
+ if (config->is_clientside)
load_payloads("traces/client.out");
else {
load_payloads("traces/server.out");
@@ -144,12 +173,18 @@ http::http(bool is_clientside)
}
}
-http::~http()
+http_steg_t::~http_steg_t()
{
}
+steg_config_t *
+http_steg_t::cfg()
+{
+ return config;
+}
+
size_t
-http::transmit_room(conn_t *)
+http_steg_t::transmit_room()
{
unsigned int mjc;
@@ -158,7 +193,7 @@ http::transmit_room(conn_t *)
return 0;
- if (is_clientside) {
+ if (config->is_clientside) {
return (MIN_COOKIE_SIZE + rand() % (MAX_COOKIE_SIZE - MIN_COOKIE_SIZE)) / 4;
}
else {
@@ -251,7 +286,9 @@ lookup_peer_name_from_ip(char* p_ip, char* p_name) {
int
-http_client_cookie_transmit (http *s, struct evbuffer *source, conn_t *conn) {
+http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source,
+ conn_t *conn)
+{
/* On the client side, we have to embed the data in a GET query somehow;
the only plausible places to put it are the URL and cookies. This
@@ -455,7 +492,9 @@ int gen_uri_field(char* uri, unsigned int uri_sz, char* data, int datalen) {
int
-http_client_uri_transmit (http *s, struct evbuffer *source, conn_t *conn) {
+http_client_uri_transmit (http_steg_t *s,
+ struct evbuffer *source, conn_t *conn)
+{
struct evbuffer *dest = conn->outbound();
@@ -558,7 +597,7 @@ http_client_uri_transmit (http *s, struct evbuffer *source, conn_t *conn) {
int
-http::transmit(struct evbuffer *source, conn_t *conn)
+http_steg_t::transmit(struct evbuffer *source)
{
// struct evbuffer *dest = conn_get_outbound(conn);
@@ -566,7 +605,7 @@ http::transmit(struct evbuffer *source, conn_t *conn)
- if (is_clientside) {
+ if (config->is_clientside) {
/* On the client side, we have to embed the data in a GET query somehow;
the only plausible places to put it are the URL and cookies. */
@@ -609,7 +648,7 @@ http::transmit(struct evbuffer *source, conn_t *conn)
int
-http_server_receive(http *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+http_server_receive(http_steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
char* data;
int type;
@@ -710,14 +749,14 @@ http_server_receive(http *s, conn_t *conn, struct evbuffer *dest, struct evbuffe
int
-http::receive(conn_t *conn, struct evbuffer *dest)
+http_steg_t::receive(struct evbuffer *dest)
{
struct evbuffer *source = conn->inbound();
// unsigned int type;
int rval = RECV_BAD;
- if (is_clientside) {
+ if (config->is_clientside) {
switch(type) {
case HTTP_CONTENT_SWF:
diff --git a/src/steg/nosteg.cc b/src/steg/nosteg.cc
index 02d2e10..df80c89 100644
--- a/src/steg/nosteg.cc
+++ b/src/steg/nosteg.cc
@@ -39,31 +39,61 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <event2/buffer.h>
namespace {
-struct nosteg : steg_t
-{
- STEG_DECLARE_METHODS(nosteg);
-};
+ struct nosteg_steg_config_t : steg_config_t
+ {
+ STEG_CONFIG_DECLARE_METHODS(nosteg);
+ };
+
+ struct nosteg_steg_t : steg_t
+ {
+ nosteg_steg_config_t *config;
+ conn_t *conn;
+
+ nosteg_steg_t(nosteg_steg_config_t *cf, conn_t *cn);
+ STEG_DECLARE_METHODS(nosteg);
+ };
}
STEG_DEFINE_MODULE(nosteg);
-nosteg::nosteg(bool is_clientside)
- : steg_t(is_clientside)
+nosteg_steg_config_t::nosteg_steg_config_t(config_t *cfg)
+ : steg_config_t(cfg)
+{
+}
+
+nosteg_steg_config_t::~nosteg_steg_config_t()
+{
+}
+
+steg_t *
+nosteg_steg_config_t::steg_create(conn_t *conn)
+{
+ return new nosteg_steg_t(this, conn);
+}
+
+nosteg_steg_t::nosteg_steg_t(nosteg_steg_config_t *cf, conn_t *cn)
+ : config(cf), conn(cn)
+{
+}
+
+nosteg_steg_t::~nosteg_steg_t()
{
}
-nosteg::~nosteg()
+steg_config_t *
+nosteg_steg_t::cfg()
{
+ return config;
}
size_t
-nosteg::transmit_room(conn_t *)
+nosteg_steg_t::transmit_room()
{
return SIZE_MAX;
}
int
-nosteg::transmit(struct evbuffer *source, conn_t *conn)
+nosteg_steg_t::transmit(struct evbuffer *source)
{
struct evbuffer *dest = conn->outbound();
@@ -79,7 +109,7 @@ nosteg::transmit(struct evbuffer *source, conn_t *conn)
}
int
-nosteg::receive(conn_t *conn, struct evbuffer *dest)
+nosteg_steg_t::receive(struct evbuffer *dest)
{
struct evbuffer *source = conn->inbound();
diff --git a/src/steg/nosteg_rr.cc b/src/steg/nosteg_rr.cc
index 70e376e..8b316bb 100644
--- a/src/steg/nosteg_rr.cc
+++ b/src/steg/nosteg_rr.cc
@@ -39,35 +39,67 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include <event2/buffer.h>
namespace {
-struct nosteg_rr : steg_t
-{
- bool can_transmit : 1;
- bool did_transmit : 1;
- STEG_DECLARE_METHODS(nosteg_rr);
-};
+ struct nosteg_rr_steg_config_t : steg_config_t
+ {
+ STEG_CONFIG_DECLARE_METHODS(nosteg_rr);
+ };
+
+ struct nosteg_rr_steg_t : steg_t
+ {
+ nosteg_rr_steg_config_t *config;
+ conn_t *conn;
+
+ bool can_transmit : 1;
+ bool did_transmit : 1;
+
+ nosteg_rr_steg_t(nosteg_rr_steg_config_t *cf, conn_t *cn);
+ STEG_DECLARE_METHODS(nosteg_rr);
+ };
}
STEG_DEFINE_MODULE(nosteg_rr);
-nosteg_rr::nosteg_rr(bool is_clientside)
- : steg_t(is_clientside),
- can_transmit(is_clientside),
+nosteg_rr_steg_config_t::nosteg_rr_steg_config_t(config_t *cfg)
+ : steg_config_t(cfg)
+{
+}
+
+nosteg_rr_steg_config_t::~nosteg_rr_steg_config_t()
+{
+}
+
+steg_t *
+nosteg_rr_steg_config_t::steg_create(conn_t *conn)
+{
+ return new nosteg_rr_steg_t(this, conn);
+}
+
+nosteg_rr_steg_t::nosteg_rr_steg_t(nosteg_rr_steg_config_t *cf,
+ conn_t *cn)
+ : config(cf), conn(cn),
+ can_transmit(cf->cfg->mode != LSN_SIMPLE_SERVER),
did_transmit(false)
{
}
-nosteg_rr::~nosteg_rr()
+nosteg_rr_steg_t::~nosteg_rr_steg_t()
+{
+}
+
+steg_config_t *
+nosteg_rr_steg_t::cfg()
{
+ return config;
}
size_t
-nosteg_rr::transmit_room(conn_t *)
+nosteg_rr_steg_t::transmit_room()
{
return can_transmit ? SIZE_MAX : 0;
}
int
-nosteg_rr::transmit(struct evbuffer *source, conn_t *conn)
+nosteg_rr_steg_t::transmit(struct evbuffer *source)
{
log_assert(can_transmit);
@@ -89,12 +121,12 @@ nosteg_rr::transmit(struct evbuffer *source, conn_t *conn)
}
int
-nosteg_rr::receive(conn_t *conn, struct evbuffer *dest)
+nosteg_rr_steg_t::receive(struct evbuffer *dest)
{
struct evbuffer *source = conn->inbound();
log_debug(conn, "%s-side receiving %lu bytes",
- is_clientside ? "client" : "server",
+ config->cfg->mode == LSN_SIMPLE_SERVER ? "server" : "client",
(unsigned long)evbuffer_get_length(source));
if (evbuffer_add_buffer(dest, source)) {
@@ -102,7 +134,7 @@ nosteg_rr::receive(conn_t *conn, struct evbuffer *dest)
return -1;
}
- if (is_clientside) {
+ if (config->cfg->mode != LSN_SIMPLE_SERVER) {
conn->expect_close();
} else if (!did_transmit) {
can_transmit = true;
[View Less]
1
0

20 Jul '12
commit d64fb4c98988346538013981343fbec3c959661a
Author: Zack Weinberg <zackw(a)panix.com>
Date: Thu Mar 29 19:19:04 2012 -0700
Make HTTP-steg 'peername' per-connection.
---
src/audit-globals.sh | 2 --
src/steg/http.cc | 28 ++++++++++++----------------
2 files changed, 12 insertions(+), 18 deletions(-)
diff --git a/src/audit-globals.sh b/src/audit-globals.sh
index 1768640..3c21643 100644
--- a/src/audit-globals.sh
+++ b/src/audit-globals.sh
@@ -46,8 +46,6 @@ sed '
/^…
[View More]crypt init_crypto()::initialized$/d
# These are grandfathered; they need to be removed.
- /^steg\/http has_peer_name$/d
- /^steg\/http peername$/d
/^steg\/payloads payload_count$/d
/^steg\/payloads payload_hdrs$/d
/^steg\/payloads payloads$/d
diff --git a/src/steg/http.cc b/src/steg/http.cc
index 05ab940..1ee4254 100644
--- a/src/steg/http.cc
+++ b/src/steg/http.cc
@@ -54,12 +54,9 @@ int
http_server_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
int
-lookup_peer_name_from_ip(char* p_ip, char* p_name);
+lookup_peer_name_from_ip(const char* p_ip, char* p_name);
-static int has_peer_name = 0;
-static char peername[512];
-
namespace {
struct http_steg_config_t : steg_config_t
{
@@ -72,6 +69,7 @@ namespace {
{
http_steg_config_t *config;
conn_t *conn;
+ char peer_dnsname[512];
bool have_transmitted : 1;
bool have_received : 1;
@@ -161,6 +159,8 @@ http_steg_t::http_steg_t(http_steg_config_t *cf, conn_t *cn)
: config(cf), conn(cn),
have_transmitted(false), have_received(false)
{
+ memset(peer_dnsname, 0, sizeof peer_dnsname);
+
if (config->is_clientside)
load_payloads("traces/client.out");
else {
@@ -243,7 +243,7 @@ http_steg_t::transmit_room()
int
-lookup_peer_name_from_ip(char* p_ip, char* p_name) {
+lookup_peer_name_from_ip(const char* p_ip, char* p_name) {
struct addrinfo* ailist;
struct addrinfo* aip;
struct addrinfo hint;
@@ -330,9 +330,8 @@ http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source,
}
buf[payload_len] = 0;
- if (has_peer_name == 0 && lookup_peer_name_from_ip((char*) conn->peername, peername))
- has_peer_name = 1;
-
+ if (s->peer_dnsname[0] == '\0')
+ lookup_peer_name_from_ip(conn->peername, s->peer_dnsname);
bzero(data2, sbuflen*4);
E.encode((char*) data, sbuflen, (char*) data2);
@@ -370,8 +369,8 @@ http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source,
goto err;
}
- rval = evbuffer_add(dest, peername, strlen(peername));
- if (rval) {
+ rval = evbuffer_add(dest, s->peer_dnsname, strlen(s->peer_dnsname));
+ if (rval) {
log_warn("error adding peername field\n");
goto err;
}
@@ -515,11 +514,8 @@ http_client_uri_transmit (http_steg_t *s,
int len =0;
char buf[10000];
-
- if (has_peer_name == 0 && lookup_peer_name_from_ip((char*) conn->peername, peername))
- has_peer_name = 1;
-
-
+ if (s->peer_dnsname[0] == '\0')
+ lookup_peer_name_from_ip(conn->peername, s->peer_dnsname);
nv = evbuffer_peek(source, slen, NULL, NULL, 0);
iv = (evbuffer_iovec *)xzalloc(sizeof(struct evbuffer_iovec) * nv);
@@ -560,7 +556,7 @@ http_client_uri_transmit (http_steg_t *s,
if (evbuffer_add(dest, outbuf, datalen) || // add uri field
evbuffer_add(dest, "HTTP/1.1\r\nHost: ", 19) ||
- evbuffer_add(dest, peername, strlen(peername)) ||
+ evbuffer_add(dest, s->peer_dnsname, strlen(s->peer_dnsname)) ||
evbuffer_add(dest, strstr(buf, "\r\n"), len - (unsigned int) (strstr(buf, "\r\n") - buf)) || // add everything but first line
evbuffer_add(dest, "\r\n", 2)) {
log_debug("error ***********************");
[View Less]
1
0

[stegotorus/master] Candidate fixes for bugs exposed by running the automated tests on HTTP steg. Not 100% working yet.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit eb200a8333b4cbb4b239b2fcfbaeeb3874c298ac
Author: Zack Weinberg <zackw(a)panix.com>
Date: Sun Apr 1 11:34:27 2012 -0700
Candidate fixes for bugs exposed by running the automated tests on HTTP steg. Not 100% working yet.
---
src/network.cc | 8 ++-
src/protocol/chop.cc | 120 ++++++++++++++++++++++++++-----------------------
src/steg/jsSteg.cc | 4 +-
src/steg/payloads.cc | 12 ++---
src/test/test_tl.py | 9 +++-
5 files changed, 81 insertions(+), 72 …
[View More]deletions(-)
diff --git a/src/network.cc b/src/network.cc
index 7eac64d..55944fe 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -444,12 +444,14 @@ downstream_flush_cb(struct bufferevent *bev, void *arg)
{
conn_t *conn = (conn_t *)arg;
size_t remain = evbuffer_get_length(bufferevent_get_output(bev));
- log_debug(conn, "%lu bytes still to transmit%s%s",
+ log_debug(conn, "%lu bytes still to transmit%s%s%s",
(unsigned long)remain,
conn->connected ? "" : " (not connected)",
- conn->flushing ? "" : " (not flushing)");
+ conn->flushing ? "" : " (not flushing)",
+ conn->circuit() ? "" : " (no circuit)");
- if (remain == 0 && conn->flushing && conn->connected) {
+ if (remain == 0 && ((conn->flushing && conn->connected)
+ || !conn->circuit())) {
bufferevent_disable(bev, EV_WRITE);
if (bufferevent_get_enabled(bev)) {
log_debug(conn, "sending EOF downstream");
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index 27e03ab..a46d0ac 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -667,46 +667,49 @@ chop_circuit_t::send()
{
circuit_disarm_flush_timer(this);
- if (downstreams.empty()) {
- // We have no connections, but we must send. If we're the client,
- // reopen our outbound connections; the on-connection event will
- // bring us back here. If we're the server, we have to just
- // twiddle our thumbs and hope the client reconnects.
- log_debug(this, "no downstream connections");
- if (config->mode != LSN_SIMPLE_SERVER)
- circuit_reopen_downstreams(this);
- else
- circuit_arm_axe_timer(this, axe_interval());
- return 0;
- }
-
struct evbuffer *xmit_pending = bufferevent_get_input(up_buffer);
size_t avail = evbuffer_get_length(xmit_pending);
size_t avail0 = avail;
- // Send at least one block, even if there is no real data to send.
- do {
- log_debug(this, "%lu bytes to send", (unsigned long)avail);
- size_t blocksize;
- chop_conn_t *target = pick_connection(avail, &blocksize);
- if (!target) {
- // this is not an error; it can happen e.g. when the server has
- // something to send immediately and the client hasn't spoken yet
- log_debug(this, "no target connection available");
- break;
- }
+ if (downstreams.empty()) {
+ log_debug(this, "no downstream connections");
+ } else {
+ // Send at least one block, even if there is no real data to send.
+ do {
+ log_debug(this, "%lu bytes to send", (unsigned long)avail);
+ size_t blocksize;
+ chop_conn_t *target = pick_connection(avail, &blocksize);
+ if (!target) {
+ // this is not an error; it can happen e.g. when the server has
+ // something to send immediately and the client hasn't spoken yet
+ log_debug(this, "no target connection available");
+ break;
+ }
- if (send_targeted(target, blocksize))
- return -1;
+ if (send_targeted(target, blocksize))
+ return -1;
- avail = evbuffer_get_length(xmit_pending);
- } while (avail > 0);
+ avail = evbuffer_get_length(xmit_pending);
+ } while (avail > 0);
+ }
- if (avail0 > avail) // we transmitted some real data
- dead_cycles = 0;
- else {
+ if (avail0 == avail) { // no forward progress
dead_cycles++;
log_debug(this, "%u dead cycles", dead_cycles);
+
+ // If there was real data and we didn't make any progress on it,
+ // or if there are no downstream connections at all, and we're the
+ // client, try opening new connections. If we're the server, we
+ // have to just twiddle our thumbs and hope the client does that.
+ // Note that due to the sliding window of receive blocks, there is
+ // a hard upper limit of 127 outstanding connections (that is,
+ // half the receive window).
+ if ((avail0 > 0 && downstreams.size() < 127) || downstreams.empty()) {
+ if (config->mode != LSN_SIMPLE_SERVER)
+ circuit_reopen_downstreams(this);
+ else
+ circuit_arm_axe_timer(this, axe_interval());
+ }
}
return check_for_eof();
@@ -843,6 +846,10 @@ chop_circuit_t::send_targeted(chop_conn_t *conn, size_t d, size_t p, opcode_t f,
send_seq++;
if (f == op_FIN)
sent_fin = true;
+ if ((f == op_DAT || f == op_FIN) && d > 0)
+ // We are making forward progress if we are _either_ sending or
+ // receiving data.
+ dead_cycles = 0;
return 0;
}
@@ -868,34 +875,32 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize)
for (unordered_set<chop_conn_t *>::iterator i = downstreams.begin();
i != downstreams.end(); i++) {
chop_conn_t *conn = *i;
- // We can only use candidates that have a steg target already.
- if (conn->steg) {
- // Find the connections whose transmit rooms are closest to the
- // desired transmission length from both directions.
- size_t room = conn->steg->transmit_room();
+ if (!conn->steg) {
+ log_debug(conn, "offers 0 bytes (no steg)");
+ continue;
+ }
- if (room <= MIN_BLOCK_SIZE)
- room = 0;
+ size_t room = conn->steg->transmit_room();
- if (room > MAX_BLOCK_SIZE)
- room = MAX_BLOCK_SIZE;
+ if (room <= MIN_BLOCK_SIZE)
+ room = 0;
- log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room,
- conn->steg->cfg()->name());
+ if (room > MAX_BLOCK_SIZE)
+ room = MAX_BLOCK_SIZE;
- if (room >= desired) {
- if (room < minabove) {
- minabove = room;
- targabove = conn;
- }
- } else {
- if (room > maxbelow) {
- maxbelow = room;
- targbelow = conn;
- }
+ log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room,
+ conn->steg->cfg()->name());
+
+ if (room >= desired) {
+ if (room < minabove) {
+ minabove = room;
+ targabove = conn;
}
} else {
- log_debug(conn, "offers 0 bytes (no steg)");
+ if (room > maxbelow) {
+ maxbelow = room;
+ targbelow = conn;
+ }
}
}
@@ -943,6 +948,9 @@ chop_circuit_t::process_queue()
log_info(this, "protocol error: data after FIN");
pending_error = true;
} else {
+ // We are making forward progress if we are _either_ sending or
+ // receiving data.
+ dead_cycles = 0;
if (evbuffer_add_buffer(bufferevent_get_output(up_buffer),
blk.data)) {
log_warn(this, "buffer transfer failure");
@@ -989,8 +997,6 @@ chop_circuit_t::process_queue()
}
log_debug(this, "processed %u blocks", count);
- if (count > 0)
- dead_cycles = 0;
if (sent_error)
return -1;
@@ -1318,8 +1324,10 @@ chop_conn_t::send()
// comes in for a stale circuit.
if (upstream) {
log_debug(this, "must send");
- if (upstream->send_targeted(this))
+ if (upstream->send_targeted(this)) {
+ upstream->drop_downstream(this);
conn_do_flush(this);
+ }
} else {
log_debug(this, "must send (no upstream)");
diff --git a/src/steg/jsSteg.cc b/src/steg/jsSteg.cc
index 60893ef..06d31e4 100644
--- a/src/steg/jsSteg.cc
+++ b/src/steg/jsSteg.cc
@@ -778,11 +778,9 @@ http_server_JS_transmit (payloads& pl, struct evbuffer *source, conn_t *conn,
free(iv);
- log_debug("SERVER encoded data in hex string (len %d):", datalen);
+ //log_debug("SERVER encoded data in hex string (len %d):", datalen);
// buf_dump((unsigned char*)data, datalen, stderr);
-
-
if (get_payload(pl, content_type, datalen, &jsTemplate, &jsLen) == 1) {
log_debug("SERVER found the applicable HTTP response template with size %d", jsLen);
} else {
diff --git a/src/steg/payloads.cc b/src/steg/payloads.cc
index d9546d2..8a766c5 100644
--- a/src/steg/payloads.cc
+++ b/src/steg/payloads.cc
@@ -1158,10 +1158,7 @@ int init_JS_payload_pool(payloads& pl, int len, int type, int minCapacity) {
}
}
-
pl.max_JS_capacity = maxPayloadCap;
-
-
pl.initTypePayload[contentType] = 1;
pl.typePayloadCount[contentType] = cnt;
log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
@@ -1243,10 +1240,8 @@ int init_HTML_payload_pool(payloads& pl, int len, int type, int minCapacity) {
}
}
-
pl.max_HTML_capacity = maxPayloadCap;
-
-
+ pl.initTypePayload[contentType] = 1;
pl.typePayloadCount[contentType] = cnt;
log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
contentType, pl.typePayloadCount[contentType]);
@@ -1436,8 +1431,9 @@ int get_next_payload (payloads& pl, int contentType, char** buf,
int get_payload (payloads& pl, int contentType, int cap, char** buf, int* size) {
int r, i, cnt, found = 0, numCandidate = 0, first, best, current;
- log_debug("get_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
- contentType, pl.initTypePayload[contentType], pl.typePayloadCount[contentType]);
+ log_debug("contentType = %d, initTypePayload = %d, typePayloadCount = %d",
+ contentType, pl.initTypePayload[contentType],
+ pl.typePayloadCount[contentType]);
if (contentType <= 0 ||
contentType >= MAX_CONTENT_TYPE ||
diff --git a/src/test/test_tl.py b/src/test/test_tl.py
index 9987c7d..eb61f31 100644
--- a/src/test/test_tl.py
+++ b/src/test/test_tl.py
@@ -87,8 +87,13 @@ class TimelineTest(object):
# "127.0.0.1:5010","embed",
# ))
- # NOTE: 'http' steg presently cannot be tested using this system
- # because the trace pools are process-global rather than per-listener.
+ def test_http(self):
+ self.doTest("chop",
+ ("chop", "server", "127.0.0.1:5001",
+ "127.0.0.1:5010","http","127.0.0.1:5011","http",
+ "chop", "client", "127.0.0.1:4999",
+ "127.0.0.1:5010","http","127.0.0.1:5011","http",
+ ))
# Synthesize TimelineTest+TestCase subclasses for every 'tl_*' file in
# the test directory.
[View Less]
1
0
commit 00d4889e52789fdce2bbe376b932392df6929d55
Author: Steven Cheung <steven.cheung(a)sri.com>
Date: Mon Apr 2 12:15:29 2012 -0700
removed a noisy debug statement
---
src/steg/http.cc | 6 +++++-
src/steg/payloads.cc | 4 +---
2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/src/steg/http.cc b/src/steg/http.cc
index a4fd790..a41afb8 100644
--- a/src/steg/http.cc
+++ b/src/steg/http.cc
@@ -236,7 +236,11 @@ http_steg_t::transmit_room(size_t pref, size_t lo, …
[View More]size_t hi)
}
}
- log_assert(hi >= lo);
+ if (hi < lo)
+ log_abort("hi<lo: client=%d type=%d hi=%ld lo=%ld",
+ config->is_clientside, type,
+ (unsigned long)hi, (unsigned long)lo);
+
return clamp(pref + rng_range_geom(hi - lo, 8), lo, hi);
}
diff --git a/src/steg/payloads.cc b/src/steg/payloads.cc
index 8a766c5..f5f35b8 100644
--- a/src/steg/payloads.cc
+++ b/src/steg/payloads.cc
@@ -1050,17 +1050,15 @@ unsigned int capacityPDF (char* buf, int len) {
while (bp < (buf+len)) {
streamStart = strInBinary("stream", 6, bp, (buf+len)-bp);
- // streamStart = strstr(bp, "stream");
if (streamStart == NULL) break;
bp = streamStart+6;
streamEnd = strInBinary("endstream", 9, bp, (buf+len)-bp);
- // streamEnd = strstr(bp, "endstream");
if (streamEnd == NULL) break;
// count the number of char between streamStart+6 and streamEnd
size = streamEnd - (streamStart+6) - 2; // 2 for \r\n before streamEnd
if (size > 0) {
cnt = cnt + size;
- log_debug("capacity of pdf increase by %d", size);
+ // log_debug("capacity of pdf increase by %d", size);
}
bp += 9;
}
[View Less]
1
0

[stegotorus/master] Make 'embed' testable with test_tl (removing globals).
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 7d121a79b8acbaf1f42807266bac91da1774edd0
Author: Zack Weinberg <zackw(a)panix.com>
Date: Thu Mar 29 18:54:28 2012 -0700
Make 'embed' testable with test_tl (removing globals).
It still doesn't *work*, but now we have a chance of pinning down why.
One bug flushed out of chop.cc already.
---
Makefile.am | 1 +
src/audit-globals.sh | 3 -
src/protocol/chop.cc | 4 +-
src/steg/embed.cc | 101 ++++++++++++++++++++++---------------------------
…
[View More]src/test/test_tl.py | 10 ++++-
5 files changed, 57 insertions(+), 62 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 377e37f..6ba1b51 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -131,6 +131,7 @@ check-local:
$(AM_V_at) ./unittests
if INTEGRATION_TESTS
@echo --- Integration tests ---
+ [ -e traces ] || ln -s $(srcdir)/traces .
$(AM_V_at) $(PYTHON) -m unittest discover -s $(srcdir)/src/test -p 'test_*.py' -v
else
@echo !!! Integration tests skipped !!!
diff --git a/src/audit-globals.sh b/src/audit-globals.sh
index 99739b3..1768640 100644
--- a/src/audit-globals.sh
+++ b/src/audit-globals.sh
@@ -46,9 +46,6 @@ sed '
/^crypt init_crypto()::initialized$/d
# These are grandfathered; they need to be removed.
- /^steg\/embed embed_init$/d
- /^steg\/embed embed_num_traces$/d
- /^steg\/embed embed_traces$/d
/^steg\/http has_peer_name$/d
/^steg\/http peername$/d
/^steg\/payloads payload_count$/d
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index 06346b7..27e03ab 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -771,7 +771,9 @@ chop_circuit_t::send_targeted(chop_conn_t *conn, size_t blocksize)
size_t avail = evbuffer_get_length(xmit_pending);
opcode_t op = op_DAT;
- if (avail > SECTION_LEN)
+ if (avail > blocksize - MIN_BLOCK_SIZE)
+ avail = blocksize - MIN_BLOCK_SIZE;
+ else if (avail > SECTION_LEN)
avail = SECTION_LEN;
else if (upstream_eof && !sent_fin)
// this block will carry the last byte of real data to be sent in
diff --git a/src/steg/embed.cc b/src/steg/embed.cc
index 6559bf7..f24c210 100644
--- a/src/steg/embed.cc
+++ b/src/steg/embed.cc
@@ -4,32 +4,34 @@
#include "steg.h"
#include "rng.h"
+#include <errno.h>
#include <event2/buffer.h>
-#include <event2/event.h>
-#include <stdio.h>
-#include <unistd.h>
-#include <time.h>
+#include <vector>
+
+using std::vector;
namespace {
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
+ vector<short> pkt_sizes; // packet sizes (positive = client->server)
+ vector<int> pkt_times; // packet inter-arrival times
};
struct embed_steg_config_t : steg_config_t {
bool is_clientside;
+ vector<trace_t> traces;
STEG_CONFIG_DECLARE_METHODS(embed);
+
+ size_t get_random_trace() const;
};
struct embed_steg_t : steg_t {
embed_steg_config_t *config;
conn_t *conn;
- int cur_idx; // current trace index
+ int cur_idx; // current trace index
trace_t *cur; // current trace
- int cur_pkt; // current packet in the trace
+ int cur_pkt; // current packet in the trace
struct timeval last_pkt; // time at which last packet was sent/received
embed_steg_t(embed_steg_config_t *cf, conn_t *cn);
@@ -46,10 +48,6 @@ namespace {
STEG_DEFINE_MODULE(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
-
static int
millis_since(struct timeval *last)
{
@@ -66,6 +64,32 @@ embed_steg_config_t::embed_steg_config_t(config_t *cfg)
: steg_config_t(cfg),
is_clientside(cfg->mode != LSN_SIMPLE_SERVER)
{
+ // read in traces to use for connections
+ FILE *trace_file = fopen("traces/embed.txt", "r");
+ if (!trace_file)
+ log_abort("opening traces/embed.txt: %s", strerror(errno));
+
+ int num_traces;
+ if (fscanf(trace_file, "%d", &num_traces) < 1)
+ log_abort("couldn't read number of traces");
+
+ traces.resize(num_traces);
+
+ for (vector<trace_t>::iterator p = traces.begin(); p != traces.end(); ++p) {
+ int num_pkt;
+ if (fscanf(trace_file, "%d", &num_pkt) < 1)
+ log_abort("couldn't read number of packets in trace %ld",
+ p - traces.begin());
+
+ p->pkt_sizes.resize(num_pkt);
+ p->pkt_times.resize(num_pkt);
+ for (int i = 0; i < num_pkt; i++)
+ if (fscanf(trace_file, "%hd %d", &p->pkt_sizes[i], &p->pkt_times[i]) < 1)
+ log_abort("couldn't read trace entry %ld/%d",
+ p - traces.begin(), i);
+ }
+
+ log_debug("read %d traces", num_traces);
}
embed_steg_config_t::~embed_steg_config_t()
@@ -78,50 +102,17 @@ embed_steg_config_t::steg_create(conn_t *conn)
return new embed_steg_t(this, conn);
}
-static void
-init_embed_traces()
-{
- // read in traces to use for connections
- FILE *trace_file = fopen("traces/embed.txt", "r");
- if (fscanf(trace_file, "%d", &embed_num_traces) < 1) {
- log_abort("couldn't read number of traces to use -- exiting");
- exit(1);
- }
- embed_traces = (trace_t *)xmalloc(sizeof(trace_t) * embed_num_traces);
- for (int i = 0; i < embed_num_traces; i++) {
- int num_pkt;
- if (fscanf(trace_file, "%d", &num_pkt) < 1) {
- log_abort("couldn't read number of packets to use -- exiting");
- exit(1);
- }
- 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++) {
- if (fscanf(trace_file, "%hd %d",
- &embed_traces[i].pkt_sizes[j],
- &embed_traces[i].pkt_times[j]) < 1) {
- log_abort("couldn't read numbers of packet size and times to use -- exiting");
- exit(1);
- }
- }
- }
- log_debug("read %d traces to use", embed_num_traces);
-
- embed_init = 1;
-}
-
-static int
-get_random_trace()
+size_t
+embed_steg_config_t::get_random_trace() const
{
- return rng_int(embed_num_traces);
+ return rng_int(traces.size());
}
bool
embed_steg_t::advance_packet()
{
cur_pkt++;
- return cur_pkt == cur->num_pkt;
+ return cur_pkt == int(cur->pkt_sizes.size());
}
short
@@ -146,18 +137,16 @@ bool
embed_steg_t::is_finished()
{
if (cur_idx == -1) return true;
- return cur_pkt >= cur->num_pkt;
+ return cur_pkt >= int(cur->pkt_sizes.size());
}
embed_steg_t::embed_steg_t(embed_steg_config_t *cf, conn_t *cn)
: config(cf), conn(cn)
{
- if (!embed_init) init_embed_traces();
-
cur_idx = -1;
if (config->is_clientside) {
- cur_idx = get_random_trace();
- cur = &embed_traces[cur_idx];
+ cur_idx = config->get_random_trace();
+ cur = &config->traces[cur_idx];
cur_pkt = 0;
}
gettimeofday(&last_pkt, NULL);
@@ -243,7 +232,7 @@ embed_steg_t::receive(struct evbuffer *dest)
// 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 = &config->traces[cur_idx];
cur_pkt = 0;
pkt_size += 4;
diff --git a/src/test/test_tl.py b/src/test/test_tl.py
index 6d632f8..9987c7d 100644
--- a/src/test/test_tl.py
+++ b/src/test/test_tl.py
@@ -78,8 +78,14 @@ class TimelineTest(object):
"127.0.0.1:5010","nosteg_rr","127.0.0.1:5011","nosteg_rr",
))
- # NOTE: 'embed' steg presently cannot be tested using this system
- # because it runs out of trace data before any of the tests complete.
+ # buggy, disabled
+ #def test_embed(self):
+ # self.doTest("chop",
+ # ("chop", "server", "127.0.0.1:5001",
+ # "127.0.0.1:5010","embed",
+ # "chop", "client", "127.0.0.1:4999",
+ # "127.0.0.1:5010","embed",
+ # ))
# NOTE: 'http' steg presently cannot be tested using this system
# because the trace pools are process-global rather than per-listener.
[View Less]
1
0

[stegotorus/master] Make payload data per-steg configuration. It *should* now be possible to
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit b9452572f1dfdb6473f3f6308a99c5723a842238
Author: Zack Weinberg <zackw(a)panix.com>
Date: Thu Mar 29 19:49:00 2012 -0700
Make payload data per-steg configuration. It *should* now be possible to
run the automated tests on HTTP steg.
---
src/steg/http.cc | 41 +++++----
src/steg/jsSteg.cc | 12 ++-
src/steg/jsSteg.h | 3 +-
src/steg/payloads.cc | 248 +++++++++++++++++++-------------------------------
src/steg/payloads.h | 34 +++++--
src/steg/pdfSteg.…
[View More]cc | 9 +-
src/steg/pdfSteg.h | 4 +-
src/steg/swfSteg.cc | 15 +--
src/steg/swfSteg.h | 10 +--
9 files changed, 166 insertions(+), 210 deletions(-)
diff --git a/src/steg/http.cc b/src/steg/http.cc
index 1ee4254..77ea859 100644
--- a/src/steg/http.cc
+++ b/src/steg/http.cc
@@ -61,6 +61,7 @@ namespace {
struct http_steg_config_t : steg_config_t
{
bool is_clientside : 1;
+ payloads pl;
STEG_CONFIG_DECLARE_METHODS(http);
};
@@ -86,6 +87,17 @@ http_steg_config_t::http_steg_config_t(config_t *cfg)
: steg_config_t(cfg),
is_clientside(cfg->mode != LSN_SIMPLE_SERVER)
{
+
+ if (is_clientside)
+ load_payloads(this->pl, "traces/client.out");
+ else {
+ load_payloads(this->pl, "traces/server.out");
+ init_JS_payload_pool(this->pl, HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE);
+ // init_JS_payload_pool(this, HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE, HTTP_CONTENT_HTML);
+ init_HTML_payload_pool(this->pl, HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, HTML_MIN_AVAIL_SIZE);
+ init_PDF_payload_pool(this->pl, HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, PDF_MIN_AVAIL_SIZE);
+ init_SWF_payload_pool(this->pl, HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, 0);
+ }
}
http_steg_config_t::~http_steg_config_t()
@@ -160,17 +172,6 @@ http_steg_t::http_steg_t(http_steg_config_t *cf, conn_t *cn)
have_transmitted(false), have_received(false)
{
memset(peer_dnsname, 0, sizeof peer_dnsname);
-
- if (config->is_clientside)
- load_payloads("traces/client.out");
- else {
- load_payloads("traces/server.out");
- init_JS_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE);
- // init_JS_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, JS_MIN_AVAIL_SIZE, HTTP_CONTENT_HTML);
- init_HTML_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, HTML_MIN_AVAIL_SIZE);
- init_PDF_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, PDF_MIN_AVAIL_SIZE);
- init_SWF_payload_pool(HTTP_MSG_BUF_SIZE, TYPE_HTTP_RESPONSE, 0);
- }
}
http_steg_t::~http_steg_t()
@@ -207,7 +208,7 @@ http_steg_t::transmit_room()
return 1024;
case HTTP_CONTENT_JAVASCRIPT:
- mjc = get_max_JS_capacity() / 2;
+ mjc = config->pl.max_JS_capacity / 2;
if (mjc > 1024) {
// it should be 1024 + ...., but seems like we need to be a little bit smaller (chopper bug?)
int rval = 512 + rand()%(mjc - 1024);
@@ -218,7 +219,7 @@ http_steg_t::transmit_room()
exit(-1);
case HTTP_CONTENT_HTML:
- mjc = get_max_HTML_capacity() / 2;
+ mjc = config->pl.max_HTML_capacity / 2;
if (mjc > 1024) {
// it should be 1024 + ...., but seems like we need to be a little bit smaller (chopper bug?)
int rval = 512 + rand()%(mjc - 1024);
@@ -323,7 +324,8 @@ http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source,
// retry up to 10 times
while (!payload_len) {
- payload_len = find_client_payload(buf, bufsize, TYPE_HTTP_REQUEST);
+ payload_len = find_client_payload(s->config->pl, buf, bufsize,
+ TYPE_HTTP_REQUEST);
if (cnt++ == 10) {
goto err;
}
@@ -547,7 +549,8 @@ http_client_uri_transmit (http_steg_t *s,
// retry up to 10 times
while (!len) {
- len = find_client_payload(buf, sizeof(buf), TYPE_HTTP_REQUEST);
+ len = find_client_payload(s->config->pl, buf, sizeof(buf),
+ TYPE_HTTP_REQUEST);
if (cnt++ == 10) return -1;
}
@@ -617,19 +620,19 @@ http_steg_t::transmit(struct evbuffer *source)
switch(type) {
case HTTP_CONTENT_SWF:
- rval = http_server_SWF_transmit(this, source, conn);
+ rval = http_server_SWF_transmit(this->config->pl, source, conn);
break;
case HTTP_CONTENT_JAVASCRIPT:
- rval = http_server_JS_transmit(this, source, conn, HTTP_CONTENT_JAVASCRIPT);
+ rval = http_server_JS_transmit(this->config->pl, source, conn, HTTP_CONTENT_JAVASCRIPT);
break;
case HTTP_CONTENT_HTML:
- rval = http_server_JS_transmit(this, source, conn, HTTP_CONTENT_HTML);
+ rval = http_server_JS_transmit(this->config->pl, source, conn, HTTP_CONTENT_HTML);
break;
case HTTP_CONTENT_PDF:
- rval = http_server_PDF_transmit(this, source, conn);
+ rval = http_server_PDF_transmit(this->config->pl, source, conn);
break;
}
diff --git a/src/steg/jsSteg.cc b/src/steg/jsSteg.cc
index 335b78e..60893ef 100644
--- a/src/steg/jsSteg.cc
+++ b/src/steg/jsSteg.cc
@@ -706,8 +706,10 @@ int testDecode2(char *inBuf, char *outBuf,
}
-int
-http_server_JS_transmit (steg_t*, struct evbuffer *source, conn_t *conn, unsigned int content_type) {
+int
+http_server_JS_transmit (payloads& pl, struct evbuffer *source, conn_t *conn,
+ unsigned int content_type)
+{
struct evbuffer_iovec *iv;
int nv;
@@ -742,9 +744,9 @@ http_server_JS_transmit (steg_t*, struct evbuffer *source, conn_t *conn, unsigne
}
if (content_type == HTTP_CONTENT_JAVASCRIPT) {
- mjs = get_max_JS_capacity();
+ mjs = pl.max_JS_capacity;
} else if (content_type == HTTP_CONTENT_HTML) {
- mjs = get_max_HTML_capacity();
+ mjs = pl.max_HTML_capacity;
}
if (mjs <= 0) {
@@ -781,7 +783,7 @@ http_server_JS_transmit (steg_t*, struct evbuffer *source, conn_t *conn, unsigne
- if (get_payload(content_type, datalen, &jsTemplate, &jsLen) == 1) {
+ if (get_payload(pl, content_type, datalen, &jsTemplate, &jsLen) == 1) {
log_debug("SERVER found the applicable HTTP response template with size %d", jsLen);
} else {
log_warn("SERVER couldn't find the applicable HTTP response template");
diff --git a/src/steg/jsSteg.h b/src/steg/jsSteg.h
index 8a351cc..709ceb0 100644
--- a/src/steg/jsSteg.h
+++ b/src/steg/jsSteg.h
@@ -18,6 +18,7 @@
// controlling content gzipping for jsSteg
#define JS_GZIP_RESP 1
+struct payloads;
int encodeHTTPBody(char *data, char *jTemplate, char *jData,unsigned int dlen,
unsigned int jtlen, unsigned int jdlen, int mode);
@@ -62,7 +63,7 @@ int testDecode2(char *inBuf, char *outBuf,
int
-http_server_JS_transmit (steg_t* s, struct evbuffer *source, conn_t *conn, unsigned int content_type);
+http_server_JS_transmit (payloads& pl, struct evbuffer *source, conn_t *conn, unsigned int content_type);
int
http_handle_client_JS_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
diff --git a/src/steg/payloads.cc b/src/steg/payloads.cc
index c7e2638..d9546d2 100644
--- a/src/steg/payloads.cc
+++ b/src/steg/payloads.cc
@@ -2,38 +2,6 @@
#include "payloads.h"
#include "swfSteg.h"
-
-/* These variables below are write-once, hence they should be race-safe */
-
-static int initTypePayload[MAX_CONTENT_TYPE];
-static int typePayloadCount[MAX_CONTENT_TYPE];
-static int typePayload[MAX_CONTENT_TYPE][MAX_PAYLOADS];
-static int typePayloadCap[MAX_CONTENT_TYPE][MAX_PAYLOADS];
-
-
-static unsigned int max_JS_capacity = 0;
-static unsigned int max_HTML_capacity = 0;
-static unsigned int max_PDF_capacity = 0;
-
-static pentry_header payload_hdrs[MAX_PAYLOADS];
-static char* payloads[MAX_PAYLOADS];
-static int payload_count = 0;
-
-
-unsigned int get_max_JS_capacity() {
- return max_JS_capacity;
-}
-
-unsigned int get_max_HTML_capacity() {
- return max_HTML_capacity;
-}
-
-unsigned int get_max_PDF_capacity() {
- return max_PDF_capacity;
-}
-
-
-
/*
* fixContentLen corrects the Content-Length for an HTTP msg that
* has been ungzipped, and removes the "Content-Encoding: gzip"
@@ -208,7 +176,8 @@ log_debug("new: hdrLen = %d, bodyLen = %d, payloadLen = %d", hdrLen, bodyLen, hd
return -1;
}
-void load_payloads(const char* fname) {
+void load_payloads(payloads& pl, const char* fname)
+{
FILE* f;
char buf[HTTP_MSG_BUF_SIZE];
char buf2[HTTP_MSG_BUF_SIZE];
@@ -216,9 +185,6 @@ void load_payloads(const char* fname) {
int pentryLen;
int r;
- if (payload_count != 0)
- return;
-
srand(time(NULL));
f = fopen(fname, "r");
if (f == NULL) {
@@ -226,9 +192,10 @@ void load_payloads(const char* fname) {
exit(1);
}
- bzero(payload_hdrs, sizeof(payload_hdrs));
+ bzero(pl.payload_hdrs, sizeof(pl.payload_hdrs));
+ pl.payload_count = 0;
- while (payload_count < MAX_PAYLOADS) {
+ while (pl.payload_count < MAX_PAYLOADS) {
if (fread(&pentry, 1, sizeof(pentry_header), f) < sizeof(pentry_header)) {
break;
@@ -270,22 +237,21 @@ void load_payloads(const char* fname) {
// }
if (r < 0) {
- payloads[payload_count] = (char *)xmalloc(pentry.length + 1);
- memcpy(payloads[payload_count], buf, pentry.length);
+ pl.payloads[pl.payload_count] = (char *)xmalloc(pentry.length + 1);
+ memcpy(pl.payloads[pl.payload_count], buf, pentry.length);
} else {
pentry.length = r;
- payloads[payload_count] = (char *)xmalloc(pentry.length + 1);
- memcpy(payloads[payload_count], buf2, pentry.length);
+ pl.payloads[pl.payload_count] = (char *)xmalloc(pentry.length + 1);
+ memcpy(pl.payloads[pl.payload_count], buf2, pentry.length);
}
- payload_hdrs[payload_count] = pentry;
- payloads[payload_count][pentry.length] = 0;
- payload_count++;
+ pl.payload_hdrs[pl.payload_count] = pentry;
+ pl.payloads[pl.payload_count][pentry.length] = 0;
+ pl.payload_count++;
} // while
-#ifdef DEBUG
- printf("loading payload count = %d\n", payload_count);
-#endif
-
+
+ log_debug("loaded %d payloads from %s\n", pl.payload_count, fname);
+
fclose(f);
}
@@ -561,18 +527,16 @@ find_uri_type(char* buf) {
-unsigned int find_client_payload(char* buf, int len, int type) {
- int r = rand() % payload_count;
+unsigned int find_client_payload(payloads& pl, char* buf, int len, int type) {
+ int r = rand() % pl.payload_count;
int cnt = 0;
char* inbuf;
-#ifdef DEBUG
- fprintf(stderr, "TRYING payload %d \n", r);
-#endif
+ log_debug("trying payload %d", r);
while (1) {
- pentry_header* p = &payload_hdrs[r];
+ pentry_header* p = &pl.payload_hdrs[r];
if (p->ptype == type) {
- inbuf = payloads[r];
+ inbuf = pl.payloads[r];
if (find_uri_type(inbuf, p->length) != HTTP_CONTENT_SWF &&
find_uri_type(inbuf, p->length) != HTTP_CONTENT_HTML &&
find_uri_type(inbuf, p->length) != HTTP_CONTENT_JAVASCRIPT &&
@@ -588,12 +552,11 @@ unsigned int find_client_payload(char* buf, int len, int type) {
break;
}
next:
- r = (r+1) % payload_count;
-
+ r = (r+1) % pl.payload_count;
// no matching payloads...
- if (cnt++ == payload_count) {
- fprintf(stderr, "NO MATCHING PAYLOADS... \n");
+ if (cnt++ == pl.payload_count) {
+ log_warn("no matching payloads");
return 0;
}
}
@@ -602,7 +565,6 @@ unsigned int find_client_payload(char* buf, int len, int type) {
// clean up the buffer...
return parse_client_headers(inbuf, buf, len);
-
}
@@ -1132,10 +1094,9 @@ unsigned int capacityPDF (char* buf, int len) {
-int init_JS_payload_pool(int len, int type, int minCapacity) {
-
+int init_JS_payload_pool(payloads& pl, int len, int type, int minCapacity) {
// stat for usable payload
- int minPayloadSize = 0, maxPayloadSize = 0;
+ int minPayloadSize = 0, maxPayloadSize = 0;
int sumPayloadSize = 0;
int minPayloadCap = 0, maxPayloadCap = 0;
int sumPayloadCap = 0;
@@ -1149,40 +1110,35 @@ int init_JS_payload_pool(int len, int type, int minCapacity) {
int cap;
int mode;
-
-
- if (payload_count == 0) {
+ if (pl.payload_count == 0) {
log_debug("payload_count == 0; forgot to run load_payloads()?\n");
return 0;
}
-
- if (initTypePayload[contentType] != 0) return 1; // init is done already
-
- for (r = 0; r < payload_count; r++) {
- p = &payload_hdrs[r];
+ for (r = 0; r < pl.payload_count; r++) {
+ p = &pl.payload_hdrs[r];
if (p->ptype != type || p->length > len) {
continue;
}
- msgbuf = payloads[r];
+ msgbuf = pl.payloads[r];
mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_JAVASCRIPT);
if (mode == CONTENT_JAVASCRIPT) {
-
+
cap = capacityJS3(msgbuf, p->length, mode);
- if (cap < JS_DELIMITER_SIZE)
+ if (cap < JS_DELIMITER_SIZE)
continue;
cap = (cap - JS_DELIMITER_SIZE)/2;
if (cap > minCapacity) {
- typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
+ pl.typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
// because we use 2 hex char to encode every data byte, the available
// capacity for encoding data is divided by 2
- typePayload[contentType][cnt] = r;
+ pl.typePayload[contentType][cnt] = r;
cnt++;
-
+
// update stat
if (cnt == 1) {
minPayloadSize = p->length; maxPayloadSize = p->length;
@@ -1203,13 +1159,13 @@ int init_JS_payload_pool(int len, int type, int minCapacity) {
}
- max_JS_capacity = maxPayloadCap;
+ pl.max_JS_capacity = maxPayloadCap;
- initTypePayload[contentType] = 1;
- typePayloadCount[contentType] = cnt;
+ pl.initTypePayload[contentType] = 1;
+ pl.typePayloadCount[contentType] = cnt;
log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
- contentType, typePayloadCount[contentType]);
+ contentType, pl.typePayloadCount[contentType]);
log_debug("minPayloadSize = %d", minPayloadSize);
log_debug("maxPayloadSize = %d", maxPayloadSize);
log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt);
@@ -1220,7 +1176,7 @@ int init_JS_payload_pool(int len, int type, int minCapacity) {
}
-int init_HTML_payload_pool(int len, int type, int minCapacity) {
+int init_HTML_payload_pool(payloads& pl, int len, int type, int minCapacity) {
// stat for usable payload
int minPayloadSize = 0, maxPayloadSize = 0;
@@ -1239,21 +1195,18 @@ int init_HTML_payload_pool(int len, int type, int minCapacity) {
- if (payload_count == 0) {
+ if (pl.payload_count == 0) {
log_debug("payload_count == 0; forgot to run load_payloads()?\n");
return 0;
}
-
- if (initTypePayload[contentType] != 0) return 1; // init is done already
-
- for (r = 0; r < payload_count; r++) {
- p = &payload_hdrs[r];
+ for (r = 0; r < pl.payload_count; r++) {
+ p = &pl.payload_hdrs[r];
if (p->ptype != type || p->length > len) {
continue;
}
- msgbuf = payloads[r];
+ msgbuf = pl.payloads[r];
mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_HTML);
if (mode == CONTENT_HTML_JAVASCRIPT) {
@@ -1265,10 +1218,10 @@ int init_HTML_payload_pool(int len, int type, int minCapacity) {
cap = (cap - JS_DELIMITER_SIZE)/2;
if (cap > minCapacity) {
- typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
+ pl.typePayloadCap[contentType][cnt] = cap; // (cap-JS_DELIMITER_SIZE)/2;
// because we use 2 hex char to encode every data byte, the available
// capacity for encoding data is divided by 2
- typePayload[contentType][cnt] = r;
+ pl.typePayload[contentType][cnt] = r;
cnt++;
// update stat
@@ -1291,13 +1244,12 @@ int init_HTML_payload_pool(int len, int type, int minCapacity) {
}
- max_HTML_capacity = maxPayloadCap;
+ pl.max_HTML_capacity = maxPayloadCap;
- initTypePayload[contentType] = 1;
- typePayloadCount[contentType] = cnt;
+ pl.typePayloadCount[contentType] = cnt;
log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
- contentType, typePayloadCount[contentType]);
+ contentType, pl.typePayloadCount[contentType]);
log_debug("minPayloadSize = %d", minPayloadSize);
log_debug("maxPayloadSize = %d", maxPayloadSize);
log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt);
@@ -1307,14 +1259,9 @@ int init_HTML_payload_pool(int len, int type, int minCapacity) {
return 1;
}
-
-
-
-
-
-
-
-int init_PDF_payload_pool(int len, int type, int minCapacity) {
+int
+init_PDF_payload_pool(payloads& pl, int len, int type, int minCapacity)
+{
// stat for usable payload
int minPayloadSize = 0, maxPayloadSize = 0;
@@ -1331,21 +1278,18 @@ int init_PDF_payload_pool(int len, int type, int minCapacity) {
unsigned int contentType = HTTP_CONTENT_PDF;
- if (payload_count == 0) {
+ if (pl.payload_count == 0) {
fprintf(stderr, "payload_count == 0; forgot to run load_payloads()?\n");
return 0;
}
-
- if (initTypePayload[contentType] != 0) return 1; // init is done already
-
- for (r = 0; r < payload_count; r++) {
- p = &payload_hdrs[r];
+ for (r = 0; r < pl.payload_count; r++) {
+ p = &pl.payload_hdrs[r];
if (p->ptype != type || p->length > len) {
continue;
}
- msgbuf = payloads[r];
+ msgbuf = pl.payloads[r];
mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_PDF);
if (mode > 0) {
@@ -1356,8 +1300,8 @@ int init_PDF_payload_pool(int len, int type, int minCapacity) {
log_debug("got pdf (index %d) with capacity %d", r, cap);
if (cap > minCapacity) {
log_debug("pdf (index %d) greater than mincapacity %d", cnt, minCapacity);
- typePayloadCap[contentType][cnt] = (cap-PDF_DELIMITER_SIZE)/2;
- typePayload[contentType][cnt] = r;
+ pl.typePayloadCap[contentType][cnt] = (cap-PDF_DELIMITER_SIZE)/2;
+ pl.typePayload[contentType][cnt] = r;
cnt++;
// update stat
@@ -1376,11 +1320,11 @@ int init_PDF_payload_pool(int len, int type, int minCapacity) {
}
}
- max_PDF_capacity = maxPayloadCap;
- initTypePayload[contentType] = 1;
- typePayloadCount[contentType] = cnt;
+ pl.max_PDF_capacity = maxPayloadCap;
+ pl.initTypePayload[contentType] = 1;
+ pl.typePayloadCount[contentType] = cnt;
log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
- contentType, typePayloadCount[contentType]);
+ contentType, pl.typePayloadCount[contentType]);
log_debug("minPayloadSize = %d", minPayloadSize);
log_debug("maxPayloadSize = %d", maxPayloadSize);
log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt);
@@ -1390,12 +1334,9 @@ int init_PDF_payload_pool(int len, int type, int minCapacity) {
return 1;
}
-
-
-
-
-int init_SWF_payload_pool(int len, int type, int /*unused */) {
-
+int
+init_SWF_payload_pool(payloads& pl, int len, int type, int /*unused */)
+{
// stat for usable payload
int minPayloadSize = 0, maxPayloadSize = 0;
int sumPayloadSize = 0;
@@ -1408,26 +1349,23 @@ int init_SWF_payload_pool(int len, int type, int /*unused */) {
unsigned int contentType = HTTP_CONTENT_SWF;
- if (payload_count == 0) {
+ if (pl.payload_count == 0) {
fprintf(stderr, "payload_count == 0; forgot to run load_payloads()?\n");
return 0;
}
-
- if (initTypePayload[contentType] != 0) return 1; // init is done already
-
- for (r = 0; r < payload_count; r++) {
- p = &payload_hdrs[r];
+ for (r = 0; r < pl.payload_count; r++) {
+ p = &pl.payload_hdrs[r];
if (p->ptype != type || p->length > len) {
continue;
}
- msgbuf = payloads[r];
+ msgbuf = pl.payloads[r];
// found a payload corr to the specified contentType
mode = has_eligible_HTTP_content(msgbuf, p->length, HTTP_CONTENT_SWF);
if (mode > 0) {
- typePayload[contentType][cnt] = r;
+ pl.typePayload[contentType][cnt] = r;
cnt++;
// update stat
if (cnt == 1) {
@@ -1444,10 +1382,10 @@ int init_SWF_payload_pool(int len, int type, int /*unused */) {
}
}
- initTypePayload[contentType] = 1;
- typePayloadCount[contentType] = cnt;
+ pl.initTypePayload[contentType] = 1;
+ pl.typePayloadCount[contentType] = cnt;
log_debug("init_payload_pool: typePayloadCount for contentType %d = %d",
- contentType, typePayloadCount[contentType]);
+ contentType, pl.typePayloadCount[contentType]);
log_debug("minPayloadSize = %d", minPayloadSize);
log_debug("maxPayloadSize = %d", maxPayloadSize);
log_debug("avgPayloadSize = %f", (float)sumPayloadSize/(float)cnt);
@@ -1462,27 +1400,29 @@ int init_SWF_payload_pool(int len, int type, int /*unused */) {
-int get_next_payload (int contentType, char** buf, int* size, int* cap) {
+int get_next_payload (payloads& pl, int contentType, char** buf,
+ int* size, int* cap)
+{
int r;
log_debug("get_next_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
- contentType, initTypePayload[contentType], typePayloadCount[contentType]);
+ contentType, pl.initTypePayload[contentType], pl.typePayloadCount[contentType]);
if (contentType <= 0 ||
contentType >= MAX_CONTENT_TYPE ||
- initTypePayload[contentType] == 0 ||
- typePayloadCount[contentType] == 0)
+ pl.initTypePayload[contentType] == 0 ||
+ pl.typePayloadCount[contentType] == 0)
return 0;
- r = rand() % typePayloadCount[contentType];
+ r = rand() % pl.typePayloadCount[contentType];
// int r = 1;
// log_debug("SERVER: *** always choose the same payload ***");
log_debug("SERVER: picked payload with index %d", r);
- *buf = payloads[typePayload[contentType][r]];
- *size = payload_hdrs[typePayload[contentType][r]].length;
- *cap = typePayloadCap[contentType][r];
+ *buf = pl.payloads[pl.typePayload[contentType][r]];
+ *size = pl.payload_hdrs[pl.typePayload[contentType][r]].length;
+ *cap = pl.typePayloadCap[contentType][r];
return 1;
}
@@ -1493,20 +1433,20 @@ int get_next_payload (int contentType, char** buf, int* size, int* cap) {
-int get_payload (int contentType, int cap, char** buf, int* size) {
+int get_payload (payloads& pl, int contentType, int cap, char** buf, int* size) {
int r, i, cnt, found = 0, numCandidate = 0, first, best, current;
log_debug("get_payload: contentType = %d, initTypePayload = %d, typePayloadCount = %d",
- contentType, initTypePayload[contentType], typePayloadCount[contentType]);
+ contentType, pl.initTypePayload[contentType], pl.typePayloadCount[contentType]);
if (contentType <= 0 ||
contentType >= MAX_CONTENT_TYPE ||
- initTypePayload[contentType] == 0 ||
- typePayloadCount[contentType] == 0)
+ pl.initTypePayload[contentType] == 0 ||
+ pl.typePayloadCount[contentType] == 0)
return 0;
- cnt = typePayloadCount[contentType];
+ cnt = pl.typePayloadCount[contentType];
r = rand() % cnt;
best = r;
first = r;
@@ -1518,12 +1458,12 @@ int get_payload (int contentType, int cap, char** buf, int* size) {
i++;
current = (r+i)%cnt;
- if (typePayloadCap[contentType][current] <= cap)
+ if (pl.typePayloadCap[contentType][current] <= cap)
continue;
if (found) {
- if (payload_hdrs[typePayload[contentType][best]].length >
- payload_hdrs[typePayload[contentType][current]].length)
+ if (pl.payload_hdrs[pl.typePayload[contentType][best]].length >
+ pl.payload_hdrs[pl.typePayload[contentType][current]].length)
best = current;
} else {
first = current;
@@ -1535,11 +1475,11 @@ int get_payload (int contentType, int cap, char** buf, int* size) {
if (found) {
log_debug("first payload size=%d, best payload size=%d, num candidate=%d\n",
- payload_hdrs[typePayload[contentType][first]].length,
- payload_hdrs[typePayload[contentType][best]].length,
+ pl.payload_hdrs[pl.typePayload[contentType][first]].length,
+ pl.payload_hdrs[pl.typePayload[contentType][best]].length,
numCandidate);
- *buf = payloads[typePayload[contentType][best]];
- *size = payload_hdrs[typePayload[contentType][best]].length;
+ *buf = pl.payloads[pl.typePayload[contentType][best]];
+ *size = pl.payload_hdrs[pl.typePayload[contentType][best]].length;
return 1;
} else {
return 0;
diff --git a/src/steg/payloads.h b/src/steg/payloads.h
index 34e7edc..05a7307 100644
--- a/src/steg/payloads.h
+++ b/src/steg/payloads.h
@@ -120,22 +120,36 @@ typedef struct service_state {
int dir;
}state;
+struct payloads {
+ int initTypePayload[MAX_CONTENT_TYPE];
+ int typePayloadCount[MAX_CONTENT_TYPE];
+ int typePayload[MAX_CONTENT_TYPE][MAX_PAYLOADS];
+ int typePayloadCap[MAX_CONTENT_TYPE][MAX_PAYLOADS];
-#define HTTP_MSG_BUF_SIZE 100000
+ unsigned int max_JS_capacity;
+ unsigned int max_HTML_capacity;
+ unsigned int max_PDF_capacity;
+
+ pentry_header payload_hdrs[MAX_PAYLOADS];
+ char* payloads[MAX_PAYLOADS];
+ int payload_count;
+};
-void load_payloads(const char* fname);
-unsigned int find_client_payload(char* buf, int len, int type);
-unsigned int find_server_payload(char** buf, int len, int type, int contentType);
-int init_JS_payload_pool(int len, int type, int minCapacity);
-int init_SWF_payload_pool(int len, int type, int minCapacity);
-int init_PDF_payload_pool(int len, int type,int minCapacity);
-int init_HTML_payload_pool(int len, int type, int minCapacity);
+#define HTTP_MSG_BUF_SIZE 100000
+
+void load_payloads(payloads& pl, const char* fname);
+unsigned int find_client_payload(payloads& pl, char* buf, int len, int type);
+unsigned int find_server_payload(payloads& pl, char** buf, int len, int type, int contentType);
+int init_JS_payload_pool(payloads& pl, int len, int type, int minCapacity);
+int init_SWF_payload_pool(payloads& pl, int len, int type, int minCapacity);
+int init_PDF_payload_pool(payloads& pl, int len, int type,int minCapacity);
+int init_HTML_payload_pool(payloads& pl, int len, int type, int minCapacity);
-int get_next_payload (int contentType, char** buf, int* size, int* cap);
-int get_payload (int contentType, int cap, char** buf, int* size);
+int get_next_payload (payloads& pl, int contentType, char** buf, int* size, int* cap);
+int get_payload (payloads& pl, int contentType, int cap, char** buf, int* size);
int has_eligible_HTTP_content (char* buf, int len, int type);
int fixContentLen (char* payload, int payloadLen, char *buf, int bufLen);
diff --git a/src/steg/pdfSteg.cc b/src/steg/pdfSteg.cc
index 504c3d4..c67b0f8 100644
--- a/src/steg/pdfSteg.cc
+++ b/src/steg/pdfSteg.cc
@@ -296,7 +296,10 @@ pdfUnwrap (char *data, unsigned int dlen,
-int http_server_PDF_transmit (steg_t*, struct evbuffer *source, conn_t *conn) {
+int
+http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
+ conn_t *conn)
+{
struct evbuffer *dest = conn->outbound();
size_t sbuflen = evbuffer_get_length(source);
@@ -341,7 +344,7 @@ int http_server_PDF_transmit (steg_t*, struct evbuffer *source, conn_t *conn) {
log_debug("SERVER sbuflen = %d; cnt = %d", (int)sbuflen, cnt);
- mpdf = get_max_PDF_capacity();
+ mpdf = pl.max_PDF_capacity;
if (mpdf <= 0) {
log_warn("SERVER ERROR: No pdfTemplate found\n");
@@ -354,7 +357,7 @@ int http_server_PDF_transmit (steg_t*, struct evbuffer *source, conn_t *conn) {
return -1;
}
- if (get_payload(HTTP_CONTENT_PDF, sbuflen, &pdfTemplate, &pdfTemplateSize) == 1) {
+ if (get_payload(pl, HTTP_CONTENT_PDF, sbuflen, &pdfTemplate, &pdfTemplateSize) == 1) {
log_debug("SERVER found the next HTTP response template with size %d", pdfTemplateSize);
} else {
log_warn("SERVER couldn't find the next HTTP response template");
diff --git a/src/steg/pdfSteg.h b/src/steg/pdfSteg.h
index 3c7a4bd..3d494e1 100644
--- a/src/steg/pdfSteg.h
+++ b/src/steg/pdfSteg.h
@@ -10,7 +10,7 @@
#include "steg.h"
#include <event2/buffer.h>
-
+struct payloads;
#define PDF_DELIMITER '?'
#define PDF_DELIMITER2 '.'
@@ -21,7 +21,7 @@ int pdfUnwrap (char *data, unsigned int dlen, char *outbuf, unsigned int outbufs
int addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, const char delimiter1, const char delimiter2);
int removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen, const char delimiter1, int* endFlag, int* escape);
-int http_server_PDF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn);
+int http_server_PDF_transmit (payloads& pl, struct evbuffer *source, conn_t *conn);
int
http_handle_client_PDF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
diff --git a/src/steg/swfSteg.cc b/src/steg/swfSteg.cc
index d7c35ec..cd371f3 100644
--- a/src/steg/swfSteg.cc
+++ b/src/steg/swfSteg.cc
@@ -20,7 +20,7 @@ static const char http_response_1[] =
unsigned int
-swf_wrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
+swf_wrap(payloads& pl, char* inbuf, int in_len, char* outbuf, int out_sz) {
char* swf;
int in_swf_len;
@@ -38,7 +38,7 @@ swf_wrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
- if (!get_payload(HTTP_CONTENT_SWF, -1, &resp, &resp_len)) {
+ if (!get_payload(pl, HTTP_CONTENT_SWF, -1, &resp, &resp_len)) {
log_warn("swfsteg: no suitable payload found\n");
return -1;
}
@@ -118,12 +118,9 @@ swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz) {
return inf_len - SWF_SAVE_HEADER_LEN - SWF_SAVE_FOOTER_LEN;
}
-
-
-
-
-int
-http_server_SWF_transmit (steg_t*, struct evbuffer *source, conn_t *conn) {
+int
+http_server_SWF_transmit(payloads& pl, struct evbuffer *source, conn_t *conn)
+{
struct evbuffer *dest = conn->outbound();
size_t sbuflen = evbuffer_get_length(source);
@@ -141,7 +138,7 @@ http_server_SWF_transmit (steg_t*, struct evbuffer *source, conn_t *conn) {
outbuf = (char *)xmalloc(4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
// fprintf(stderr, "server wrapping swf len %d\n", (int) sbuflen);
- outlen = swf_wrap(inbuf, sbuflen, outbuf, 4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
+ outlen = swf_wrap(pl, inbuf, sbuflen, outbuf, 4*sbuflen + SWF_SAVE_FOOTER_LEN + SWF_SAVE_HEADER_LEN + 512);
if (outlen < 0) {
log_warn("swf_wrap failed\n");
diff --git a/src/steg/swfSteg.h b/src/steg/swfSteg.h
index 7be5207..712a3a3 100644
--- a/src/steg/swfSteg.h
+++ b/src/steg/swfSteg.h
@@ -14,24 +14,20 @@
#include <event2/buffer.h>
#include <stdio.h>
-
-
-
-
-
+struct payloads;
#define SWF_SAVE_HEADER_LEN 1500
#define SWF_SAVE_FOOTER_LEN 1500
unsigned int
-swf_wrap(char* inbuf, int in_len, char* outbuf, int out_sz);
+swf_wrap(payloads& pl, char* inbuf, int in_len, char* outbuf, int out_sz);
unsigned int
swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz);
int
-http_server_SWF_transmit (steg_t* s, struct evbuffer *source, conn_t *conn);
+http_server_SWF_transmit(payloads& pl, struct evbuffer *source, conn_t *conn);
int
[View Less]
1
0