tor-commits
Threads by month
- ----- 2025 -----
- 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] transmit_room() now takes 3 arguments and the chopper produces exactly what is asked for. As a side-effect this made HTTP reliable under automated test.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 9a6de8ce32c36d04fd96e48194230dfcdc1132cf
Author: Zack Weinberg <zackw(a)panix.com>
Date: Sun Apr 1 14:23:17 2012 -0700
transmit_room() now takes 3 arguments and the chopper produces exactly what is asked for. As a side-effect this made HTTP reliable under automated test.
---
src/protocol/chop.cc | 106 ++++++++++++++++++++++++++---------------
src/steg.h | 66 +++++++++++++++-----------
src/steg/embed.cc | 5 ++-
src/steg/http.cc | 124 ++++++++++++++++++++-----------------------------
src/steg/nosteg.cc | 4 +-
src/steg/nosteg_rr.cc | 4 +-
6 files changed, 165 insertions(+), 144 deletions(-)
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index a46d0ac..ad8ac9f 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -73,6 +73,8 @@ const size_t SECTION_LEN = UINT16_MAX;
const size_t MIN_BLOCK_SIZE = HEADER_LEN + TRAILER_LEN;
const size_t MAX_BLOCK_SIZE = MIN_BLOCK_SIZE + SECTION_LEN*2;
+const size_t HANDSHAKE_LEN = sizeof(uint32_t);
+
enum opcode_t
{
op_DAT = 0, // Pass data section along to upstream
@@ -729,16 +731,18 @@ chop_circuit_t::send_special(opcode_t f, struct evbuffer *payload)
size_t blocksize;
log_assert(d <= SECTION_LEN);
chop_conn_t *conn = pick_connection(d, &blocksize);
+ size_t lo = MIN_BLOCK_SIZE + ((conn && !conn->sent_handshake)
+ ? HANDSHAKE_LEN : 0);
- if (!conn || (blocksize - MIN_BLOCK_SIZE < d)) {
+ if (!conn || (blocksize - lo < d)) {
log_warn("no usable connection for special block "
"(opcode %02x, need %lu bytes, have %lu)",
- (unsigned int)f, (unsigned long)(d + MIN_BLOCK_SIZE),
+ (unsigned int)f, (unsigned long)(d + lo),
(unsigned long)blocksize);
return -1;
}
- return send_targeted(conn, d, (blocksize - MIN_BLOCK_SIZE) - d, f, payload);
+ return send_targeted(conn, d, (blocksize - lo) - d, f, payload);
}
int
@@ -749,33 +753,47 @@ chop_circuit_t::send_targeted(chop_conn_t *conn)
avail = SECTION_LEN;
avail += MIN_BLOCK_SIZE;
- 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,
- (unsigned long)MIN_BLOCK_SIZE);
- return -1;
+ // If we have any data to transmit, ensure we do not send a block
+ // that contains no data at all.
+ size_t lo = MIN_BLOCK_SIZE + (avail == MIN_BLOCK_SIZE ? 0 : 1);
+
+ // If this connection has not yet sent a handshake, it will need to.
+ size_t hi = MAX_BLOCK_SIZE;
+ if (!conn->sent_handshake) {
+ lo += HANDSHAKE_LEN;
+ hi += HANDSHAKE_LEN;
+ avail += HANDSHAKE_LEN;
}
- log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room,
- conn->steg->cfg()->name());
- if (room < avail)
- avail = room;
+ size_t room = conn->steg->transmit_room(avail, lo, hi);
+ if (room == 0)
+ log_abort(conn, "must send but cannot send");
+ if (room < lo || room >= hi)
+ log_abort(conn, "steg size request (%lu) out of range [%lu, %lu]",
+ (unsigned long)room, (unsigned long)lo, (unsigned long)hi);
- return send_targeted(conn, avail);
+ log_debug(conn, "requests %lu bytes (%s)", (unsigned long)room,
+ conn->steg->cfg()->name());
+
+ return send_targeted(conn, room);
}
int
chop_circuit_t::send_targeted(chop_conn_t *conn, size_t blocksize)
{
- log_assert(blocksize >= MIN_BLOCK_SIZE && blocksize <= MAX_BLOCK_SIZE);
+ size_t lo = MIN_BLOCK_SIZE, hi = MAX_BLOCK_SIZE;
+ if (!conn->sent_handshake) {
+ lo += HANDSHAKE_LEN;
+ hi += HANDSHAKE_LEN;
+ }
+ log_assert(blocksize >= lo && blocksize <= hi);
struct evbuffer *xmit_pending = bufferevent_get_input(up_buffer);
size_t avail = evbuffer_get_length(xmit_pending);
opcode_t op = op_DAT;
- if (avail > blocksize - MIN_BLOCK_SIZE)
- avail = blocksize - MIN_BLOCK_SIZE;
+ if (avail > blocksize - lo)
+ avail = blocksize - lo;
else if (avail > SECTION_LEN)
avail = SECTION_LEN;
else if (upstream_eof && !sent_fin)
@@ -783,7 +801,7 @@ chop_circuit_t::send_targeted(chop_conn_t *conn, size_t blocksize)
// this direction; mark it as such
op = op_FIN;
- return send_targeted(conn, avail, (blocksize - MIN_BLOCK_SIZE) - avail,
+ return send_targeted(conn, avail, (blocksize - lo) - avail,
op, xmit_pending);
}
@@ -868,6 +886,10 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize)
desired += MIN_BLOCK_SIZE;
+ // If we have any data to transmit, ensure we do not send a block
+ // that contains no data at all.
+ size_t lo = MIN_BLOCK_SIZE + (desired == MIN_BLOCK_SIZE ? 0 : 1);
+
log_debug(this, "target block size %lu bytes", (unsigned long)desired);
// Find the best fit for the desired transmission from all the
@@ -880,18 +902,25 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize)
continue;
}
- size_t room = conn->steg->transmit_room();
-
- if (room <= MIN_BLOCK_SIZE)
- room = 0;
+ size_t shake = conn->sent_handshake ? 0 : HANDSHAKE_LEN;
+ size_t room = conn->steg->transmit_room(desired + shake, lo + shake,
+ MAX_BLOCK_SIZE + shake);
+ if (room == 0) {
+ log_debug(conn, "offers 0 bytes (%s)",
+ conn->steg->cfg()->name());
+ continue;
+ }
- if (room > MAX_BLOCK_SIZE)
- room = MAX_BLOCK_SIZE;
+ if (room < lo + shake || room >= MAX_BLOCK_SIZE + shake)
+ log_abort(conn, "steg size request (%lu) out of range [%lu, %lu]",
+ (unsigned long)room,
+ (unsigned long)(lo + shake),
+ (unsigned long)(MAX_BLOCK_SIZE + shake));
log_debug(conn, "offers %lu bytes (%s)", (unsigned long)room,
conn->steg->cfg()->name());
- if (room >= desired) {
+ if (room >= desired + shake) {
if (room < minabove) {
minabove = room;
targabove = conn;
@@ -915,7 +944,7 @@ chop_circuit_t::pick_connection(size_t desired, size_t *blocksize)
// their initial values, so we'll return NULL and set blocksize to 0,
// which callers know how to handle.
if (targabove) {
- *blocksize = desired;
+ *blocksize = minabove;
return targabove;
} else {
*blocksize = maxbelow;
@@ -1086,7 +1115,7 @@ chop_conn_t::send(struct evbuffer *block)
upstream ? '+' : '-',
upstream ? upstream->circuit_id : 0);
if (evbuffer_prepend(block, (void *)&upstream->circuit_id,
- sizeof(upstream->circuit_id))) {
+ HANDSHAKE_LEN)) {
log_warn(this, "failed to prepend handshake to first block");
return -1;
}
@@ -1332,29 +1361,28 @@ chop_conn_t::send()
} else {
log_debug(this, "must send (no upstream)");
- 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,
- (unsigned long)MIN_BLOCK_SIZE);
- conn_do_flush(this);
- return;
- }
+ size_t room = steg->transmit_room(MIN_BLOCK_SIZE, MIN_BLOCK_SIZE,
+ MAX_BLOCK_SIZE);
+ if (room < MIN_BLOCK_SIZE || room >= MAX_BLOCK_SIZE)
+ log_abort(this, "steg size request (%lu) out of range [%lu, %lu]",
+ (unsigned long)room,
+ (unsigned long)MIN_BLOCK_SIZE,
+ (unsigned long)MAX_BLOCK_SIZE);
// Since we have no upstream, we can't encrypt anything; instead,
// generate random bytes and feed them straight to steg_transmit.
struct evbuffer *chaff = evbuffer_new();
struct evbuffer_iovec v;
- if (!chaff || evbuffer_reserve_space(chaff, MIN_BLOCK_SIZE, &v, 1) != 1 ||
- v.iov_len < MIN_BLOCK_SIZE) {
+ if (!chaff || evbuffer_reserve_space(chaff, room, &v, 1) != 1 ||
+ v.iov_len < room) {
log_warn(this, "memory allocation failed");
if (chaff)
evbuffer_free(chaff);
conn_do_flush(this);
return;
}
- v.iov_len = MIN_BLOCK_SIZE;
- rng_bytes((uint8_t *)v.iov_base, MIN_BLOCK_SIZE);
+ v.iov_len = room;
+ rng_bytes((uint8_t *)v.iov_base, room);
if (evbuffer_commit_space(chaff, &v, 1)) {
log_warn(this, "evbuffer_commit_space failed");
if (chaff)
diff --git a/src/steg.h b/src/steg.h
index a044afb..ad6b829 100644
--- a/src/steg.h
+++ b/src/steg.h
@@ -52,11 +52,22 @@ struct 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
- 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() = 0;
+ /** The protocol using this steg module would like to transmit PREF
+ bytes on your connection. Return an adjusted number of bytes;
+ you may adjust down to indicate that you cannot transmit all of
+ the available data, or up to indicate that it should be padded.
+
+ Returning zero indicates that your connection cannot transmit at
+ all right now; if you do this, transmit() will not be called.
+ Returning any nonzero value indicates that you want to transmit
+ exactly that number of bytes. The protocol may or may not call
+ transmit() after you return a nonzero value, but if it does, it
+ will provide the number of bytes you requested.
+
+ If you return a nonzero value, it MUST be greater than or equal
+ to MIN, and less than or equal to MAX. PREF is guaranteed to be
+ in this range already. */
+ virtual size_t transmit_room(size_t pref, size_t min, size_t max) = 0;
/** Consume all of the data in SOURCE, disguise it, and write it to
the outbound buffer for your connection. Return 0 on success, -1
@@ -94,32 +105,33 @@ 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_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 \
+#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_CONFIG_DECLARE_METHODS(mod) \
- mod##_steg_config_t(config_t *cfg); \
- virtual ~mod##_steg_config_t(); \
- virtual const char *name(); \
- virtual steg_t *steg_create(conn_t *conn) \
+#define STEG_CONFIG_DECLARE_METHODS(mod) \
+ mod##_steg_config_t(config_t *); \
+ virtual ~mod##_steg_config_t(); \
+ virtual const char *name(); \
+ virtual steg_t *steg_create(conn_t *) \
/* 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) \
+#define STEG_DECLARE_METHODS(mod) \
+ virtual ~mod##_steg_t(); \
+ virtual steg_config_t *cfg(); \
+ virtual size_t transmit_room(size_t, size_t, size_t); \
+ virtual int transmit(struct evbuffer *); \
+ virtual int receive(struct evbuffer *) \
/* deliberate absence of semicolon */
#endif
diff --git a/src/steg/embed.cc b/src/steg/embed.cc
index f24c210..d301620 100644
--- a/src/steg/embed.cc
+++ b/src/steg/embed.cc
@@ -163,7 +163,7 @@ embed_steg_t::cfg()
}
size_t
-embed_steg_t::transmit_room()
+embed_steg_t::transmit_room(size_t, size_t lo, size_t hi)
{
if (is_finished() || !is_outgoing()) return 0;
@@ -173,6 +173,9 @@ embed_steg_t::transmit_room()
// 2 bytes for data length, 4 bytes for the index of a new trace
size_t room = get_pkt_size() - 2;
if (cur_pkt == 0) room -= 4;
+
+ if (room < lo) room = lo;
+ if (room > hi) room = hi;
return room;
}
diff --git a/src/steg/http.cc b/src/steg/http.cc
index 77ea859..a4fd790 100644
--- a/src/steg/http.cc
+++ b/src/steg/http.cc
@@ -36,6 +36,8 @@ OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
#include "connections.h"
#include "protocol.h"
#include "steg.h"
+#include "rng.h"
+
#include "payloads.h"
#include "cookies.h"
#include "swfSteg.h"
@@ -184,64 +186,59 @@ http_steg_t::cfg()
return config;
}
-size_t
-http_steg_t::transmit_room()
+static size_t
+clamp(size_t val, size_t lo, size_t hi)
{
- unsigned int mjc;
+ if (val < lo) return lo;
+ if (val > hi) return hi;
+ return val;
+}
+size_t
+http_steg_t::transmit_room(size_t pref, size_t lo, size_t hi)
+{
if (have_transmitted)
/* can't send any more on this connection */
return 0;
-
if (config->is_clientside) {
- return (MIN_COOKIE_SIZE + rand() % (MAX_COOKIE_SIZE - MIN_COOKIE_SIZE)) / 4;
+ // MIN_COOKIE_SIZE and MAX_COOKIE_SIZE are *after* base64'ing
+ if (lo < MIN_COOKIE_SIZE*3/4)
+ lo = MIN_COOKIE_SIZE*3/4;
+
+ if (hi > MAX_COOKIE_SIZE*3/4)
+ hi = MAX_COOKIE_SIZE*3/4;
}
else {
-
if (!have_received)
return 0;
switch (type) {
-
case HTTP_CONTENT_SWF:
- return 1024;
+ if (hi >= 1024)
+ hi = 1024;
+ break;
case HTTP_CONTENT_JAVASCRIPT:
- 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);
- // fprintf(stderr, "returning rval %d, mjc %d\n", rval, mjc);
- return rval;
- }
- log_warn("js capacity too small\n");
- exit(-1);
+ if (hi >= config->pl.max_JS_capacity / 2)
+ hi = config->pl.max_JS_capacity / 2;
+ break;
case HTTP_CONTENT_HTML:
- 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);
- // fprintf(stderr, "returning rval %d, mjc %d\n", rval, mjc);
- return rval;
- }
- log_warn("js capacity too small\n");
- exit(-1);
+ if (hi >= config->pl.max_HTML_capacity / 2)
+ hi = config->pl.max_HTML_capacity / 2;
+ break;
case HTTP_CONTENT_PDF:
- // return 1024 + rand()%(get_max_PDF_capacity() - 1024)
- return PDF_MIN_AVAIL_SIZE;
+ if (hi >= PDF_MIN_AVAIL_SIZE)
+ hi = PDF_MIN_AVAIL_SIZE;
+ break;
}
-
- return SIZE_MAX;
}
-}
-
-
-
-
+ log_assert(hi >= lo);
+ return clamp(pref + rng_range_geom(hi - lo, 8), lo, hi);
+}
int
lookup_peer_name_from_ip(const char* p_ip, char* p_name) {
@@ -346,7 +343,7 @@ http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source,
// substitute / with _, + with ., = with - that maybe inserted anywhere in the middle
sanitize_b64(data2, len);
-
+
cookie_len = gen_b64_cookie_field(cookiebuf, data2, len);
cookiebuf[cookie_len] = 0;
@@ -356,7 +353,10 @@ http_client_cookie_transmit (http_steg_t *s, struct evbuffer *source,
log_debug("cookie generation failed\n");
return -1;
}
-
+ log_debug(conn, "cookie input %ld encoded %d final %d",
+ sbuflen, len, cookie_len);
+ log_debug(conn, "cookie encoded: %s", data2);
+ log_debug(conn, "cookie final: %s", cookiebuf);
// add uri field
rval = evbuffer_add(dest, buf, strstr(buf, "\r\n") - buf + 2);
@@ -657,28 +657,27 @@ http_server_receive(http_steg_t *s, conn_t *conn, struct evbuffer *dest, struct
char *p;
char *pend;
- char outbuf[MAX_COOKIE_SIZE];
+ char outbuf[MAX_COOKIE_SIZE * 3/2];
char outbuf2[MAX_COOKIE_SIZE];
int sofar = 0;
//int cookie_mode = 0;
if (s2.pos == -1) {
- log_debug("Did not find end of request %d", (int) evbuffer_get_length(source));
- // evbuffer_dump(source, stderr);
+ log_debug(conn, "Did not find end of request %d",
+ (int) evbuffer_get_length(source));
return RECV_INCOMPLETE;
}
- log_debug("SERVER received request header of length %d", (int)s2.pos);
+ log_debug(conn, "SERVER received request header of length %d", (int)s2.pos);
data = (char*) evbuffer_pullup(source, s2.pos+4);
if (data == NULL) {
- log_debug("SERVER evbuffer_pullup fails");
+ log_debug(conn, "SERVER evbuffer_pullup fails");
return RECV_BAD;
}
-
data[s2.pos+3] = 0;
type = find_uri_type((char *)data, s2.pos+4);
@@ -691,19 +690,14 @@ http_server_receive(http_steg_t *s, conn_t *conn, struct evbuffer *dest, struct
p = data + sizeof "GET /" -1;
pend = strstr(p, "\r\n");
-
- if (pend == NULL || (pend - p > MAX_COOKIE_SIZE)) {
- fprintf(stderr, "incorrect cookie recovery \n");
- exit(-1);
-
- }
-
-
+ log_assert(pend);
+ if (pend - p > MAX_COOKIE_SIZE * 3/2)
+ log_abort(conn, "cookie too big: %lu (max %lu)",
+ (unsigned long)(pend - p), (unsigned long)MAX_COOKIE_SIZE);
bzero(outbuf, sizeof(outbuf));
int cookielen = unwrap_b64_cookie((char*) p, (char*) outbuf, pend - p);
-
desanitize_b64(outbuf, cookielen);
outbuf[cookielen] = '\n';
bzero(outbuf2, sizeof(outbuf2));
@@ -711,25 +705,19 @@ http_server_receive(http_steg_t *s, conn_t *conn, struct evbuffer *dest, struct
base64::decoder D;
sofar = D.decode(outbuf, cookielen+1, outbuf2);
+ if (sofar <= 0)
+ log_warn(conn, "base64 decode failed\n");
- if (sofar <= 0)
- log_warn("decode failed\n");
-
-
- if (sofar >= MAX_COOKIE_SIZE) {
- log_warn("cookie buffer overflow????\n");
- exit(-1);
- }
-
+ if (sofar >= MAX_COOKIE_SIZE)
+ log_abort(conn, "cookie decode buffer overflow\n");
if (evbuffer_add(dest, outbuf2, sofar)) {
- log_debug("Failed to transfer buffer");
+ log_debug(conn, "Failed to transfer buffer");
return RECV_BAD;
}
evbuffer_drain(source, s2.pos + sizeof("\r\n\r\n") - 1);
} while (evbuffer_get_length(source));
-
s->have_received = 1;
s->type = type;
@@ -737,16 +725,6 @@ http_server_receive(http_steg_t *s, conn_t *conn, struct evbuffer *dest, struct
return RECV_GOOD;
}
-
-
-
-
-
-
-
-
-
-
int
http_steg_t::receive(struct evbuffer *dest)
{
diff --git a/src/steg/nosteg.cc b/src/steg/nosteg.cc
index df80c89..328a1d6 100644
--- a/src/steg/nosteg.cc
+++ b/src/steg/nosteg.cc
@@ -87,9 +87,9 @@ nosteg_steg_t::cfg()
}
size_t
-nosteg_steg_t::transmit_room()
+nosteg_steg_t::transmit_room(size_t pref, size_t, size_t)
{
- return SIZE_MAX;
+ return pref;
}
int
diff --git a/src/steg/nosteg_rr.cc b/src/steg/nosteg_rr.cc
index 8b316bb..adde6c8 100644
--- a/src/steg/nosteg_rr.cc
+++ b/src/steg/nosteg_rr.cc
@@ -93,9 +93,9 @@ nosteg_rr_steg_t::cfg()
}
size_t
-nosteg_rr_steg_t::transmit_room()
+nosteg_rr_steg_t::transmit_room(size_t pref, size_t, size_t)
{
- return can_transmit ? SIZE_MAX : 0;
+ return can_transmit ? pref : 0;
}
int
1
0

[stegotorus/master] Merge branch 'master' of https://git.safdef.isc.org/git/stegotorus
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 092842af7faace09e0b6325f7ae40b112367c8e6
Merge: 5513c95 00d4889
Author: Zack Weinberg <zackw(a)panix.com>
Date: Wed Apr 4 18:01:44 2012 -0700
Merge branch 'master' of https://git.safdef.isc.org/git/stegotorus
src/steg/http.cc | 6 +++++-
src/steg/payloads.cc | 4 +---
2 files changed, 6 insertions(+), 4 deletions(-)
1
0

[stegotorus/master] Remove a hack from the configure script and a reference to Crypto++ from the README.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 5513c95762305224973d614cd6f4e839ef948cc3
Author: Zack Weinberg <zackw(a)panix.com>
Date: Wed Apr 4 18:01:27 2012 -0700
Remove a hack from the configure script and a reference to Crypto++ from the README.
---
README | 2 +-
configure.ac | 8 +-------
2 files changed, 2 insertions(+), 8 deletions(-)
diff --git a/README b/README
index b3b82b4..e1f45b3 100644
--- a/README
+++ b/README
@@ -1,6 +1,6 @@
This doesn't work yet.
-It requires Crypto++ 5.6.0 or later.
+It requires OpenSSL 1.0.1 or later.
It requires Libevent 2.0 or later.
diff --git a/configure.ac b/configure.ac
index 69f4150..87cb713 100644
--- a/configure.ac
+++ b/configure.ac
@@ -5,12 +5,6 @@ AC_LANG([C++])
AM_INIT_AUTOMAKE([foreign nostdinc silent-rules subdir-objects])
AM_MAINTAINER_MODE([enable])
-dnl The stock definition of AC_INCLUDES_DEFAULT performs a whole bunch
-dnl of completely unnecessary checks *even if* you override its
-dnl mostly-useless default header list at invocation time.
-dnl Replace it with a version that does nothing unless requested.
-m4_pushdef([AC_INCLUDES_DEFAULT], [$1])
-
### Programs ###
AC_PROG_CXX
@@ -64,7 +58,7 @@ LIBS="$LIBS $ws32_LIBS"
### Language features ###
-AC_CHECK_HEADERS([execinfo.h],,, [AC_INCLUDES_DEFAULT()])
+AC_CHECK_HEADERS([execinfo.h],,,[/**/])
AX_CXXFLAGS_STDCXX_11([ext])
AX_CXX_DELETE_METHOD
1
0
commit 8140b7a818a799dfa43f47c13edeb74f1f0daa20
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Mon Apr 16 14:49:44 2012 -0700
Add a cast to make gcc 4.4 happy.
---
src/protocol/chop.cc | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)
diff --git a/src/protocol/chop.cc b/src/protocol/chop.cc
index ad8ac9f..dac4ea2 100644
--- a/src/protocol/chop.cc
+++ b/src/protocol/chop.cc
@@ -1158,7 +1158,7 @@ chop_conn_t::recv_handshake()
sizeof circuit_id) != sizeof circuit_id)
return -1;
- chop_circuit_table::value_type in(circuit_id, 0);
+ chop_circuit_table::value_type in(circuit_id, (chop_circuit_t *)0);
std::pair<chop_circuit_table::iterator, bool> out
= this->config->circuits.insert(in);
chop_circuit_t *ck;
1
0

[stegotorus/master] Don't enable reading and writing on half-open sockets.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit fc44f29e5cf79b6db5171cb42c9efa5f498b0bd9
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Mon Apr 16 15:02:31 2012 -0700
Don't enable reading and writing on half-open sockets.
---
src/network.cc | 3 ---
1 files changed, 0 insertions(+), 3 deletions(-)
diff --git a/src/network.cc b/src/network.cc
index 55944fe..f312067 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -674,7 +674,6 @@ circuit_open_upstream(circuit_t *ckt)
return -1;
success:
- bufferevent_enable(buf, EV_READ|EV_WRITE);
circuit_add_upstream(ckt, buf, peername);
return 0;
}
@@ -717,7 +716,6 @@ create_one_outbound_connection(circuit_t *ckt, struct evutil_addrinfo *addr,
bufferevent_setcb(buf, downstream_read_cb, downstream_flush_cb,
is_socks ? downstream_socks_connect_cb
: downstream_connect_cb, conn);
- bufferevent_enable(buf, EV_READ|EV_WRITE);
return true;
}
@@ -790,7 +788,6 @@ create_outbound_connections_socks(circuit_t *ckt)
ckt->add_downstream(conn);
bufferevent_setcb(buf, downstream_read_cb, downstream_flush_cb,
downstream_socks_connect_cb, conn);
- bufferevent_enable(buf, EV_READ|EV_WRITE);
return;
failure:
1
0

[stegotorus/master] fixed race condition in connection establishment
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 83c892603a3953829a88a40c1ead3fa1088494b3
Author: Steven Cheung <steven.cheung(a)sri.com>
Date: Mon Apr 16 16:25:21 2012 -0700
fixed race condition in connection establishment
---
src/connections.h | 3 ++-
src/network.cc | 20 +++++++++++++++-----
2 files changed, 17 insertions(+), 6 deletions(-)
diff --git a/src/connections.h b/src/connections.h
index 9b51ce5..ddf787a 100644
--- a/src/connections.h
+++ b/src/connections.h
@@ -19,8 +19,9 @@ struct conn_t {
unsigned int serial;
bool connected : 1;
bool flushing : 1;
+ bool ever_received : 1;
- conn_t() : connected(false), flushing(false) {}
+ conn_t() : connected(false), flushing(false), ever_received(false) {}
/** Close and deallocate a connection. If the connection is part of a
circuit, disconnect it from the circuit; this may cause the circuit
diff --git a/src/network.cc b/src/network.cc
index f312067..fb17e99 100644
--- a/src/network.cc
+++ b/src/network.cc
@@ -312,6 +312,8 @@ downstream_read_cb(struct bufferevent *bev, void *arg)
{
conn_t *down = (conn_t *)arg;
+ down->ever_received = 1;
+
log_debug(down, "%lu bytes available",
(unsigned long)evbuffer_get_length(bufferevent_get_input(bev)));
@@ -375,6 +377,11 @@ downstream_event_cb(struct bufferevent *bev, short what, void *arg)
{
conn_t *conn = (conn_t *)arg;
+ log_debug(conn, "what=%04hx enabled=%x inbound=%ld outbound=%ld",
+ what, bufferevent_get_enabled(bev),
+ evbuffer_get_length(bufferevent_get_input(bev)),
+ evbuffer_get_length(bufferevent_get_output(bev)));
+
if (what & (BEV_EVENT_ERROR|BEV_EVENT_EOF|BEV_EVENT_TIMEOUT)) {
if (what & BEV_EVENT_ERROR)
log_info(conn, "network error in %s: %s",
@@ -393,7 +400,8 @@ downstream_event_cb(struct bufferevent *bev, short what, void *arg)
/* Peer is done sending us data. */
conn->recv_eof();
if (bufferevent_get_enabled(bev) ||
- evbuffer_get_length(bufferevent_get_input(bev)) > 0) {
+ evbuffer_get_length(bufferevent_get_input(bev)) > 0 ||
+ evbuffer_get_length(bufferevent_get_output(bev)) > 0) {
log_debug(conn, "acknowledging EOF downstream");
shutdown(bufferevent_getfd(bev), SHUT_RD);
} else {
@@ -444,14 +452,15 @@ 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%s",
+ log_debug(conn, "%lu bytes still to transmit%s%s%s%s",
(unsigned long)remain,
conn->connected ? "" : " (not connected)",
conn->flushing ? "" : " (not flushing)",
- conn->circuit() ? "" : " (no circuit)");
+ conn->circuit() ? "" : " (no circuit)",
+ conn->ever_received ? "" : " (never received)");
if (remain == 0 && ((conn->flushing && conn->connected)
- || !conn->circuit())) {
+ || (!conn->circuit() && conn->ever_received))) {
bufferevent_disable(bev, EV_WRITE);
if (bufferevent_get_enabled(bev)) {
log_debug(conn, "sending EOF downstream");
@@ -822,5 +831,6 @@ conn_do_flush(conn_t *conn)
if (remain == 0)
downstream_flush_cb(conn->buffer, conn);
else
- log_debug(conn, "flushing %lu bytes to peer", (unsigned long)remain);
+ log_debug(conn, "flushing %lu bytes to peer [enabled=%x]", (unsigned long)remain,
+ bufferevent_get_enabled(conn->buffer));
}
1
0

[stegotorus/master] Thorough spring-cleaning on pdfSteg.cc; less thorough on swfSteg.cc and some other headers.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 0538c5a704adaf8149b3a78c84200a77dc657506
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Mon Apr 23 14:49:52 2012 -0700
Thorough spring-cleaning on pdfSteg.cc; less thorough on swfSteg.cc and some other headers.
---
Makefile.am | 1 +
src/steg/pdfSteg.cc | 389 ++++++++++++++------------------------------
src/steg/pdfSteg.h | 38 +++--
src/steg/swfSteg.cc | 18 +--
src/steg/swfSteg.h | 23 +---
src/steg/zpack.h | 11 +-
src/test/tinytest_macros.h | 8 +-
src/util.cc | 3 -
src/util.h | 3 +
9 files changed, 167 insertions(+), 327 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 6ba1b51..86ed489 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,7 @@ stegotorus_SOURCES = \
UTGROUPS = \
src/test/unittest_crypt.cc \
+ src/test/unittest_pdfsteg.cc \
src/test/unittest_socks.cc \
src/test/unittest_config.cc \
src/test/unittest_transfer.cc
diff --git a/src/steg/pdfSteg.cc b/src/steg/pdfSteg.cc
index c67b0f8..3b4bbf0 100644
--- a/src/steg/pdfSteg.cc
+++ b/src/steg/pdfSteg.cc
@@ -1,7 +1,13 @@
-#include "payloads.h"
+#include "util.h"
#include "pdfSteg.h"
+#include "connections.h"
+#include "payloads.h"
+#include <event2/buffer.h>
+
+/* pdfSteg: A PDF-based steganography module */
-void buf_dump(unsigned char* buf, int len, FILE *out);
+#define PDF_DELIMITER '?'
+#define PDF_DELIMITER2 '.'
#define STREAM_BEGIN ">>stream"
#define STREAM_BEGIN_SIZE 8
@@ -10,45 +16,42 @@ void buf_dump(unsigned char* buf, int len, FILE *out);
#define DEBUG
-
/*
- * pdfSteg: A PDF-based steganography module
- *
- */
-
-
-/*
- * addDelimiter processes the input buffer (inbuf) of length inbuflen,
- * copies it to output buffer (outbuf) of size outbufsize,
+ * pdf_add_delimiter processes the input buffer (inbuf) of length
+ * inbuflen, copies it to output buffer (outbuf) of size outbufsize,
* and adds a two-char-long, end-of-data pattern at the end of outbuf
* based on delimiter1 and delimiter2.
*
* The end-of-data pattern consists of delimiter1 followed by a char
* that is not delimiter1. Thus, delimiter1 and delimiter2 must be
* different.
- *
- * If delimiter1 appears in the input buffer, addDelimiter puts two
- * delimiter1 char in output buffer (to enable removeDelimiter to perform
- * the back transformation)
*
- * addDelimiter returns the length of the data written to outbuf, including
- * the end-of-data pattern, if the transformation succeeds;
- * otherwise, it returns -1
+ * If delimiter1 appears in the input buffer, pdf_add_delimiter puts two
+ * delimiter1 characters in the output buffer, so that the transformation
+ * is reversible.
+ *
+ * pdf_add_delimiter returns the length of the data written to outbuf,
+ * including the end-of-data pattern, if the transformation succeeds;
+ * otherwise, it returns -1.
*
*/
-int
-addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
- const char delimiter1, const char delimiter2)
+ssize_t
+pdf_add_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ const char delimiter1, const char delimiter2)
{
- int cnt;
- char *ibp, ic, rc;
+ size_t cnt;
+ const char *ibp;
+ char ic, rc;
- if (delimiter1 == delimiter2) return -1;
+ log_assert(delimiter1 != delimiter2);
+ if (inbuflen > SIZE_T_CEILING || outbuflen > SIZE_T_CEILING)
+ return -1;
cnt = 0;
ibp = inbuf;
- while ((ibp-inbuf)<inbuflen && cnt<(outbuflen-2)) {
- ic = *(ibp++);
+ while (size_t(ibp-inbuf) < inbuflen && cnt < outbuflen-2) {
+ ic = *ibp++;
if (ic != delimiter1) {
outbuf[cnt++] = ic;
} else {
@@ -57,8 +60,9 @@ addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
}
}
- // error if outbuf is no large enough for storing the resulting data
- if (cnt >= (outbuflen-2)) return -1;
+ // error if outbuf is not large enough for storing the resulting data
+ if (cnt >= outbuflen-2)
+ return -1;
// put delimiter1 and a char that is not a delimiter1
// as the end-of-data pattern at the end of outbuf
@@ -75,8 +79,9 @@ addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
/*
- * removeDelimiter performs the reverse transformation of addDelimiter.
- *
+ * pdf_remove_delimiter performs the reverse transformation of
+ * pdf_add_delimiter.
+ *
* returns the length of data written to outbuf, if succeed;
* otherwise, it returns -1
*
@@ -84,20 +89,23 @@ addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
* delimiter1 followed by non-delimiter1) is detected
*
* escape indicates if a dangling delimiter1 has been
- * seen in the previous invocation of removeDelimiter
+ * seen in the previous invocation of pdf_remove_delimiter
*/
-int
-removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
- const char delimiter1, int *endFlag, int *escape)
+ssize_t
+pdf_remove_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ char delimiter1, bool *endFlag, bool *escape)
{
- int cnt;
- char *ibp, ic1, ic2;
+ size_t cnt;
+ const char *ibp;
+ char ic1, ic2;
cnt = 0;
- *endFlag = 0;
+ *endFlag = false;
ibp = inbuf;
- if (inbuflen <= 0) return -1;
+ if (inbuflen > SIZE_T_CEILING || outbuflen > SIZE_T_CEILING)
+ return -1;
// special case: 2-char, end-of-data pattern could be in two buffers
// if *escape == true, we need to see if
@@ -113,9 +121,9 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
}
}
- *escape = 0;
- while ((ibp-inbuf+1)<inbuflen && cnt<outbuflen) {
- ic1 = *(ibp++);
+ *escape = false;
+ while (size_t(ibp-inbuf+1) < inbuflen && cnt < outbuflen) {
+ ic1 = *ibp++;
if (ic1 != delimiter1) {
outbuf[cnt++] = ic1;
} else {
@@ -125,13 +133,14 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
if (ic2 == delimiter1) {
outbuf[cnt++] = delimiter1; ibp++;
} else { // end-of-data pattern detected
- *endFlag = 1;
+ *endFlag = true;
return cnt;
}
}
}
- if (ibp-inbuf == inbuflen) return cnt;
+ if (size_t(ibp-inbuf) == inbuflen)
+ return cnt;
// handling the last char in inbuf, if needed
ic1 = *ibp;
@@ -139,40 +148,46 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
outbuf[cnt++] = ic1;
} else {
// look at the next stream obj to handle the special cases
- *escape = 1;
+ *escape = true;
}
return cnt;
}
-
-
/*
- * pdfWrap embeds data of length dlen inside the stream objects of the PDF
+ * pdf_wrap embeds data of length dlen inside the stream objects of the PDF
* document (length plen) that appears in the body of a HTTP msg, and
* stores the result in the output buffer of size outsize
*
- * pdfWrap returns the length of the pdf document with the data embedded
+ * pdf_wrap returns the length of the pdf document with the data embedded
* inside, if succeed; otherwise, it returns -1 to indicate an error
- *
- */
-int
-pdfWrap (char *data, unsigned int dlen,
- char *pdfTemplate, unsigned int plen,
- char *outbuf, unsigned int outbufsize)
+ *
+ */
+ssize_t
+pdf_wrap(const char *data, size_t dlen,
+ const char *pdfTemplate, size_t plen,
+ char *outbuf, size_t outbufsize)
{
char data2[dlen*2+2];
- char *tp, *dp, *op, *streamStart, *streamEnd, *plimit;
- int data2len, cnt, size, size2;
+ const char *tp, *dp, *plimit;
+ char *op, *streamStart, *streamEnd;
+ size_t data2len, cnt, size, size2;
+ ssize_t rv;
- // assumption: pdfWrap is length-preserving
- if (outbufsize < plen) return -1;
+ if (dlen > SIZE_T_CEILING || plen > SIZE_T_CEILING ||
+ outbufsize > SIZE_T_CEILING)
+ return -1;
- data2len = addDelimiter(data, dlen, data2, HTTP_MSG_BUF_SIZE, PDF_DELIMITER, PDF_DELIMITER2);
- if (data2len < 1) return -1;
+ // assumption: pdf_wrap is length-preserving
+ if (outbufsize < plen) return -1;
+ rv = pdf_add_delimiter(data, dlen, data2, HTTP_MSG_BUF_SIZE,
+ PDF_DELIMITER, PDF_DELIMITER2);
+ if (rv < 1)
+ return -1;
+ data2len = rv;
- op = outbuf; // current pointer for output buffer
+ op = outbuf; // current pointer for output buffer
tp = pdfTemplate; // current pointer for http msg template
dp = data2; // current pointer for data2
cnt = 0; // number of data char encoded
@@ -185,7 +200,7 @@ pdfWrap (char *data, unsigned int dlen,
log_warn("Cannot find stream in pdf");
return -1;
}
-
+
// copy everything between tp and "stream" (inclusive) to outbuf
size = streamStart - tp + STREAM_BEGIN_SIZE;
memcpy(op, tp, size);
@@ -206,18 +221,17 @@ pdfWrap (char *data, unsigned int dlen,
size2 = data2len - cnt;
if (size < size2) {
memcpy(op, dp, size);
- op += size; tp += size; dp += size;
+ op += size; tp += size; dp += size;
memcpy(op, tp, STREAM_END_SIZE);
op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
cnt += size;
} else { // done encoding data
memcpy(op, dp, size2);
- op += size2; tp += size2; dp += size2;
+ op += size2; tp += size2; dp += size2;
cnt += size2;
- // printf("Encoded %d char in pdf. Done encoding\n", size2);
break;
}
- log_debug("Encoded %d char in pdf", size);
+ log_debug("Encoded %lu bytes in pdf", (unsigned long)size);
} else { // empty stream
memcpy(op, tp, STREAM_END_SIZE);
op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
@@ -228,25 +242,27 @@ pdfWrap (char *data, unsigned int dlen,
// copy the rest of pdfTemplate to outbuf
size = plimit-tp;
- log_debug("copying the rest of pdfTemplate to outbuf (size %d)", size);
+ log_debug("copying the rest of pdfTemplate to outbuf (size %lu)",
+ (unsigned long)size);
memcpy(op, tp, size);
op += size;
return (op-outbuf);
}
-
-
-
/*
- * pdfUnwrap is the inverse operation of pdfWrap
+ * pdf_unwrap is the inverse operation of pdf_wrap
*/
-int
-pdfUnwrap (char *data, unsigned int dlen,
- char *outbuf, unsigned int outbufsize)
+ssize_t
+pdf_unwrap(const char *data, size_t dlen,
+ char *outbuf, size_t outbufsize)
{
- char *dp, *op, *streamStart, *streamEnd, *dlimit, *olimit;
- int cnt, size, size2, endFlag;
- int escape = 0;
+ const char *dp, *dlimit;
+ char *op, *streamStart, *streamEnd, *olimit;
+ size_t cnt, size, size2;
+ bool endFlag, escape = false;
+
+ if (dlen > SIZE_T_CEILING || outbufsize > SIZE_T_CEILING)
+ return -1;
dp = data; // current pointer for data
op = outbuf; // current pointer for outbuf
@@ -272,11 +288,13 @@ pdfUnwrap (char *data, unsigned int dlen,
// count the number of usable char between tp and streamEnd
size = streamEnd-dp;
- if (size > 0) {
- size2 = removeDelimiter(dp, size, op, olimit-op, PDF_DELIMITER, &endFlag, &escape);
- if (size2 < 0) {
+ if (size > 0) {
+ ssize_t rv = pdf_remove_delimiter(dp, size, op, olimit-op, PDF_DELIMITER,
+ &endFlag, &escape);
+ if (rv < 0)
return -1;
- }
+
+ size2 = rv;
cnt += size2;
if (endFlag) { // Done decoding
break;
@@ -292,22 +310,16 @@ pdfUnwrap (char *data, unsigned int dlen,
return cnt;
}
-
-
-
-
int
-http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
- conn_t *conn)
+http_server_PDF_transmit(payloads &pl, struct evbuffer *source,
+ conn_t *conn)
{
-
struct evbuffer *dest = conn->outbound();
size_t sbuflen = evbuffer_get_length(source);
unsigned int mpdf;
char *pdfTemplate = NULL, *hend;
int pdfTemplateSize = 0;
- // char data1[HTTP_MSG_BUF_SIZE];
- char data1[(int) sbuflen];
+ char data1[sbuflen];
char outbuf[HTTP_MSG_BUF_SIZE];
int cnt, hLen, outbuflen, i;
@@ -317,10 +329,6 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
struct evbuffer_iovec *iv;
int nv;
- // for debugging pdfWrap and pdfUnwrap
- // char data2[(int) sbuflen];
- // int data2len;
-
log_debug("Entering SERVER PDF transmit with sbuflen %d", (int)sbuflen);
nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
@@ -357,8 +365,10 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
return -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);
+ 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");
return -1;
@@ -371,39 +381,19 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
}
hLen = hend+4-pdfTemplate;
-
- log_debug("SERVER calling pdfWrap for data1 with length %d", cnt);
- outbuflen = pdfWrap(data1, cnt, hend+4, pdfTemplateSize-hLen, outbuf, HTTP_MSG_BUF_SIZE);
+
+ log_debug("SERVER calling pdf_wrap for data1 with length %d", cnt);
+ outbuflen = pdf_wrap(data1, cnt, hend+4, pdfTemplateSize-hLen, outbuf,
+ HTTP_MSG_BUF_SIZE);
if (outbuflen < 0) {
- log_warn("SERVER pdfWrap fails");
+ log_warn("SERVER pdf_wrap fails");
return -1;
}
- log_debug("SERVER pdfSteg sends resp with hdr len %d body len %d", hLen, outbuflen);
-
-
- // debugging
- // buf_dump((unsigned char *)data1, cnt, stderr);
-
- // data2len = pdfUnwrap(outbuf, outbuflen, data2, sbuflen);
- // if ((int)sbuflen == data2len) {
- // log_warn("sbuflen == data2len == %d", (int)sbuflen);
- // if (memcmp(data1, data2, sbuflen) == 0) {
- // log_warn("data1 and data2 match");
- // } else {
- // log_warn("data1 and data2 DO NOT match!! Dumping data1 ...");
- // buf_dump((unsigned char *)data1, cnt, stderr);
- // log_warn("data1 and data2 DO NOT match!! Dumping data2...");
- // buf_dump((unsigned char *)data2, data2len, stderr);
- // }
- // } else {
- // log_warn("*** sbuflen = %d, data2len = %d *** Dumping data1 ...", (int)sbuflen, data2len);
- // buf_dump((unsigned char *)data1, cnt, stderr);
- // log_warn("*** sbuflen = %d, data2len = %d *** Dumping data2 ...", (int)sbuflen, data2len);
- // buf_dump((unsigned char *)data2, data2len, stderr);
- // }
-
-
- newHdrLen = gen_response_header((char*) "application/pdf", 0, outbuflen, newHdr, sizeof(newHdr));
+ log_debug("SERVER pdfSteg sends resp with hdr len %d body len %d",
+ hLen, outbuflen);
+
+ newHdrLen = gen_response_header((char*) "application/pdf", 0,
+ outbuflen, newHdr, sizeof(newHdr));
if (newHdrLen < 0) {
log_warn("SERVER ERROR: gen_response_header fails for pdfSteg");
return -1;
@@ -413,10 +403,6 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
log_warn("SERVER ERROR: evbuffer_add() fails for newHdr");
return -1;
}
- // if (evbuffer_add(dest, pdfTemplate, hLen)) {
- // log_warn("SERVER ERROR: evbuffer_add() fails for pdfTemplate");
- // return -1;
- // }
if (evbuffer_add(dest, outbuf, outbuflen)) {
log_warn("SERVER ERROR: evbuffer_add() fails for outbuf");
@@ -426,14 +412,13 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
evbuffer_drain(source, sbuflen);
conn->cease_transmission();
- // downcast_steg(s)->have_transmitted = 1;
return 0;
}
-
-
int
-http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest,
+ struct evbuffer* source)
+{
struct evbuffer_ptr s2;
unsigned int response_len = 0, hdrLen;
char outbuf[HTTP_MSG_BUF_SIZE];
@@ -444,8 +429,8 @@ http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest, st
s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
if (s2.pos == -1) {
- log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
- // evbuffer_dump(source, stderr);
+ log_warn("CLIENT Did not find end of HTTP header %d",
+ (int) evbuffer_get_length(source));
return RECV_INCOMPLETE;
}
@@ -480,154 +465,26 @@ http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest, st
return RECV_BAD;
}
-
httpBody = httpHdr + hdrLen;
-
- outbuflen = pdfUnwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
+ outbuflen = pdf_unwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
if (outbuflen < 0) {
- log_warn("CLIENT ERROR: pdfUnwrap fails\n");
+ log_warn("CLIENT ERROR: pdf_unwrap fails\n");
return RECV_BAD;
}
log_debug("CLIENT unwrapped data of length %d:", outbuflen);
-
if (evbuffer_add(dest, outbuf, outbuflen)) {
log_warn("CLIENT ERROR: evbuffer_add to dest fails\n");
return RECV_BAD;
}
- // log_debug("Drained source for %d char\n", response_len);
if (evbuffer_drain(source, response_len) == -1) {
log_warn("CLIENT ERROR: failed to drain source\n");
return RECV_BAD;
}
- // downcast_steg(s)->have_received = 1;
conn->expect_close();
return RECV_GOOD;
}
-
-
-
-
-/*****
-int main() {
- char data1[] = "this is a test?? yes!";
- char data2[100];
- char data3[100];
- int dlen1, dlen2, dlen3, end;
- char last = ' ';
- printf("hello world\n");
-
- dlen2 = addDelimiter(data1, strlen(data1), data2, 100, '?', '.');
- printf("dlen2 = %d\n", dlen2);
- dlen3 = removeDelimiter(data2, dlen2, data3, 100, '?', &end, &last);
- printf("endflag = %d", end);
- printf("dlen3 = %d\n", dlen3);
- if (memcmp(data1, data3, dlen3) == 0) {
- data1[dlen3] = 0;
- printf("removeDelimiter(addDelimiter(x)) == x for |%s|\n", data1);
- } else {
- printf("removeDelimiter(addDelimiter(x)) != x for |%s|\n", data1);
- }
- return 1;
-}
- *****/
-
-/*****
-int main() {
- char data1[] = "12345";
- char data2[] = "123456789012";
- char data3[] = "12345678901";
- char data4[] = "1234567890?";
- char pdf1[] = "[PDFHDR][STUFFS1]>>streamABCDEFGHIJYYendstream[STUFFS2]>>streamABCDEFGHIJYYendstream[STUFF3][PDFTRAILER]";
- char out[200];
- char orig[200];
- int r1, r2;
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data1);
- printf("strlen(pdf1) = %d\n", (int)strlen(pdf1));
- r1 = pdfWrap(data1, strlen(data1), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data2);
- r1 = pdfWrap(data2, strlen(data2), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data3);
- r1 = pdfWrap(data3, strlen(data3), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data4);
- r1 = pdfWrap(data4, strlen(data4), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- return 0;
-}
- *****/
diff --git a/src/steg/pdfSteg.h b/src/steg/pdfSteg.h
index 3d494e1..0bd3a43 100644
--- a/src/steg/pdfSteg.h
+++ b/src/steg/pdfSteg.h
@@ -1,29 +1,31 @@
#ifndef _PDFSTEG_H
#define _PDFSTEG_H
+struct payloads;
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-#include <event2/buffer.h>
+// These are the public interface.
-struct payloads;
+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);
-#define PDF_DELIMITER '?'
-#define PDF_DELIMITER2 '.'
+// These are exposed only for the sake of unit tests.
-int pdfWrap (char *data, unsigned int dlen, char *pdfTemplate, unsigned int plen, char *outbuf, unsigned int outbufsize);
-int pdfUnwrap (char *data, unsigned int dlen, char *outbuf, unsigned int outbufsize);
+ssize_t pdf_add_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ char delimiter1, char delimiter2);
-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);
+ssize_t pdf_remove_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ char delimiter1, bool *endFlag, bool *escape);
-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);
+ssize_t pdf_wrap(const char *data, size_t dlen,
+ const char *pdfTemplate, size_t plen,
+ char *outbuf, size_t outbufsize);
-#endif
+ssize_t pdf_unwrap(const char *data, size_t dlen,
+ char *outbuf, size_t outbufsize);
+#endif
diff --git a/src/steg/swfSteg.cc b/src/steg/swfSteg.cc
index cd371f3..c8a18c1 100644
--- a/src/steg/swfSteg.cc
+++ b/src/steg/swfSteg.cc
@@ -1,5 +1,11 @@
+#include "util.h"
#include "swfSteg.h"
+#include "connections.h"
+#include "payloads.h"
+#include "zlib.h"
+#include "zpack.h"
+#include <event2/buffer.h>
static const char http_response_1[] =
"HTTP/1.1 200 OK\r\n"
@@ -9,17 +15,7 @@ static const char http_response_1[] =
"Content-Type: application/x-shockwave-flash\r\n"
"Content-Length: ";
-
-
-
-
-
-
-
-
-
-
-unsigned int
+unsigned int
swf_wrap(payloads& pl, char* inbuf, int in_len, char* outbuf, int out_sz) {
char* swf;
diff --git a/src/steg/swfSteg.h b/src/steg/swfSteg.h
index 712a3a3..b8336b2 100644
--- a/src/steg/swfSteg.h
+++ b/src/steg/swfSteg.h
@@ -1,38 +1,21 @@
#ifndef _SWFSTEG_H
#define _SWFSTEG_H
-
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-#include "payloads.h"
-#include "cookies.h"
-#include "pdfSteg.h"
-#include "zpack.h"
-
-
-#include <event2/buffer.h>
-#include <stdio.h>
-
struct payloads;
#define SWF_SAVE_HEADER_LEN 1500
#define SWF_SAVE_FOOTER_LEN 1500
-
-unsigned int
+unsigned int
swf_wrap(payloads& pl, char* inbuf, int in_len, char* outbuf, int out_sz);
-unsigned int
+unsigned int
swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz);
-int
+int
http_server_SWF_transmit(payloads& pl, struct evbuffer *source, conn_t *conn);
-
int
http_handle_client_SWF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
#endif
-
-
diff --git a/src/steg/zpack.h b/src/steg/zpack.h
index 65cd28d..d0e5cb2 100644
--- a/src/steg/zpack.h
+++ b/src/steg/zpack.h
@@ -1,10 +1,5 @@
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <stdlib.h>
-#include "zlib.h"
-
+#ifndef _ZPACK_H
+#define _ZPACK_H
int def(char *source, int slen, char *dest, int dlen, int level);
int inf(char *source, int slen, char *dest, int dlen);
@@ -12,3 +7,5 @@ void zerr(int ret);
int gzInflate(char *source, int slen, char *dest, int dlen);
int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime);
unsigned int generate_crc32c(char *buffer, size_t length);
+
+#endif
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index 40d17e2..cf5a2a2 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -168,6 +168,10 @@
tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
(_val1 op _val2),"%p")
+#define tt_char_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,int, \
+ (_val1 op _val2),"'%c'")
+
#define tt_str_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
(strcmp(_val1,_val2) op 0),"<%s>")
@@ -176,7 +180,7 @@
tt_assert_test_fmt_type(a,b,#a" "#op" "#b, \
const char *, \
(strncmp(_val1, _val2, len) op 0), \
- char *, "%s", \
+ char *, "<%s>", \
{ _print = xstrndup(_value, len); }, \
{ free(_print); } \
);
@@ -185,7 +189,7 @@
tt_assert_test_fmt_type(a,b,#a" "#op" "#b, \
const char *, \
(memcmp(_val1, _val2, len) op 0), \
- char *, "%s", \
+ char *, "<%s>", \
{ _print = tt_base16_encode(_value, len); }, \
{ free(_print); } \
);
diff --git a/src/util.cc b/src/util.cc
index b813ae9..a667abd 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -17,9 +17,6 @@
#include <sys/un.h>
#endif
-/** Any size_t larger than this amount is likely to be an underflow. */
-#define SIZE_T_CEILING (SIZE_MAX/2 - 16)
-
/**************************** Memory Allocation ******************************/
static void ATTR_NORETURN
diff --git a/src/util.h b/src/util.h
index 05bc6d0..167af8e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -57,6 +57,9 @@ struct event_base;
/***** Memory allocation. *****/
+/** Any size_t larger than this amount is likely to be an underflow. */
+#define SIZE_T_CEILING (SIZE_MAX/2 - 16)
+
/* Because this isn't Tor and functions named "tor_whatever" would be
confusing, I am instead following the GNU convention of naming
allocate-memory-or-crash functions "xwhatever". Also, at this time
1
0

[stegotorus/master] Const- and size_t-correctness, minor other cleanups for crc32 and zpack.
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 343d961f4055f69a61bd9749d498e61234339bfc
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Mon Apr 23 15:40:28 2012 -0700
Const- and size_t-correctness, minor other cleanups for crc32 and zpack.
---
src/steg/crc32.cc | 7 +-
src/steg/crc32.h | 18 +----
src/steg/zpack.cc | 235 ++++++++++++++++-------------------------------------
src/steg/zpack.h | 13 ++--
4 files changed, 83 insertions(+), 190 deletions(-)
diff --git a/src/steg/crc32.cc b/src/steg/crc32.cc
index 7fdc847..1b18544 100644
--- a/src/steg/crc32.cc
+++ b/src/steg/crc32.cc
@@ -1,3 +1,4 @@
+#include "util.h"
#include "crc32.h"
#define CRC32C(c,d) (c=(c>>8)^crc_c[(c^(d))&0xFF])
@@ -69,8 +70,9 @@ static const unsigned int crc_c[256] = {
0xb40bbe37, 0xc30c8ea1, 0x5a05df1b, 0x2d02ef8d,
};
-
-unsigned int generate_crc32c(char *buffer, size_t length) {
+unsigned int
+generate_crc32c(const char *buffer, size_t length)
+{
size_t i;
unsigned int crc32 = ~0L;
@@ -79,4 +81,3 @@ unsigned int generate_crc32c(char *buffer, size_t length) {
}
return ~crc32;
}
-
diff --git a/src/steg/crc32.h b/src/steg/crc32.h
index 780e7bd..0a1ee03 100644
--- a/src/steg/crc32.h
+++ b/src/steg/crc32.h
@@ -1,18 +1,6 @@
-#ifndef __crc32cr_table_h__
-#define __crc32cr_table_h__
+#ifndef _CRC32_H
+#define _CRC32_H
-#ifdef HAVE_CONFIG_H
-# include "config.h"
-#endif
-
-#include <sys/types.h>
-
-#if defined HAVE_STDINT_H
-# include <stdint.h>
-#elif defined HAVE_INTTYPES_H
-# include <inttypes.h>
-#endif
-
-unsigned int generate_crc32c(char *string, size_t length);
+unsigned int generate_crc32c(const char *string, size_t length);
#endif
diff --git a/src/steg/zpack.cc b/src/steg/zpack.cc
index 63aa412..c3c650f 100644
--- a/src/steg/zpack.cc
+++ b/src/steg/zpack.cc
@@ -1,19 +1,7 @@
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <stdlib.h>
-#include "zlib.h"
+#include "util.h"
#include "zpack.h"
-
-
-#if defined(MSDOS) || defined(OS2) || defined(WIN32) || defined(__CYGWIN__)
-# include <fcntl.h>
-# include <io.h>
-# define SET_BINARY_MODE(file) setmode(fileno(file), O_BINARY)
-#else
-# define SET_BINARY_MODE(file)
-#endif
+#include "zlib.h"
+#include "crc32.h"
#define CHUNK 16384
@@ -24,15 +12,18 @@
version of the library linked do not match, or Z_ERRNO if there is
an error reading or writing the files. */
-
-int def(char *source, int slen, char *dest, int dlen, int level)
+ssize_t
+def(const char *source, size_t slen, char *dest, size_t dlen, int level)
{
int ret, flush;
- unsigned have;
+ size_t have;
z_stream strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
- int dlen_orig = dlen;
+ size_t dlen_orig = dlen;
+
+ if (slen > SIZE_T_CEILING || dlen > SIZE_T_CEILING)
+ return -1;
/* allocate deflate state */
strm.zalloc = Z_NULL;
@@ -44,7 +35,6 @@ int def(char *source, int slen, char *dest, int dlen, int level)
/* compress until end of file */
do {
-
if (slen > CHUNK)
strm.avail_in = CHUNK;
else
@@ -63,30 +53,28 @@ int def(char *source, int slen, char *dest, int dlen, int level)
strm.avail_out = CHUNK;
strm.next_out = out;
ret = deflate(&strm, flush); /* no bad return value */
- assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+ log_assert(ret != Z_STREAM_ERROR); /* state not clobbered */
have = CHUNK - strm.avail_out;
- if ((unsigned int) dlen < have) {
- fprintf(stderr, "dest buf too small!\n");
- return Z_ERRNO;
+ if (dlen < have) {
+ log_warn("dest buf too small - have %lu, need %lu",
+ (unsigned long)dlen, (unsigned long)have);
+ return Z_ERRNO;
}
memcpy(dest, out, have);
dest += have;
dlen = dlen - have;
} while (strm.avail_out == 0);
- assert(strm.avail_in == 0); /* all input will be used */
+ log_assert(strm.avail_in == 0); /* all input will be used */
/* done when last data in file processed */
} while (flush != Z_FINISH);
- assert(ret == Z_STREAM_END); /* stream will be complete */
+ log_assert(ret == Z_STREAM_END); /* stream will be complete */
/* clean up and return */
- (void)deflateEnd(&strm);
-
- printf("hello here...\n");
+ deflateEnd(&strm);
return (dlen_orig - dlen);
- // return Z_OK;
}
/* Decompress from file source to file dest until stream ends or EOF.
@@ -96,18 +84,18 @@ int def(char *source, int slen, char *dest, int dlen, int level)
the version of the library linked do not match, or Z_ERRNO if there
is an error reading or writing the files. */
-
-
-
-int inf(char *source, int slen, char *dest, int dlen)
+ssize_t
+inf(const char *source, size_t slen, char *dest, size_t dlen)
{
int ret;
- unsigned have;
+ size_t have;
z_stream strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
- int dlen_orig = dlen;
+ size_t dlen_orig = dlen;
+ if (slen > SIZE_T_CEILING || dlen > SIZE_T_CEILING)
+ return -1;
/* allocate inflate state */
strm.zalloc = Z_NULL;
@@ -121,10 +109,9 @@ int inf(char *source, int slen, char *dest, int dlen)
/* decompress until deflate stream ends or end of file */
do {
-
if (slen == 0)
break;
-
+
if (slen > CHUNK)
strm.avail_in = CHUNK;
else
@@ -133,9 +120,6 @@ int inf(char *source, int slen, char *dest, int dlen)
memcpy(in, source, strm.avail_in);
slen = slen - strm.avail_in;
source = source + strm.avail_in;
-
-
-
strm.next_in = in;
/* run inflate() on input until output buffer not full */
@@ -143,21 +127,20 @@ int inf(char *source, int slen, char *dest, int dlen)
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
- assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+ log_assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
- ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
- (void)inflateEnd(&strm);
- return ret;
+ inflateEnd(&strm);
+ return ret;
}
have = CHUNK - strm.avail_out;
-
- if ((unsigned int) dlen < have) {
- fprintf(stderr, "dest buf too small!\n");
- return Z_ERRNO;
+ if (dlen < have) {
+ log_warn("dest buf too small - have %lu, need %lu",
+ (unsigned long)dlen, (unsigned long)have);
+ return Z_ERRNO;
}
memcpy(dest, out, have);
@@ -170,57 +153,27 @@ int inf(char *source, int slen, char *dest, int dlen)
} while (ret != Z_STREAM_END);
/* clean up and return */
- (void)inflateEnd(&strm);
+ inflateEnd(&strm);
if (ret == Z_STREAM_END)
return dlen_orig - dlen;
return Z_DATA_ERROR;
}
-/* report a zlib or i/o error */
-void zerr(int ret)
-
-{
- fputs("zpipe: ", stderr);
- switch (ret) {
- case Z_ERRNO:
- if (ferror(stdin))
- fputs("error reading stdin\n", stderr);
- if (ferror(stdout))
- fputs("error writing stdout\n", stderr);
- break;
- case Z_STREAM_ERROR:
- fputs("invalid compression level\n", stderr);
- break;
- case Z_DATA_ERROR:
- fputs("invalid or incomplete deflate data\n", stderr);
- break;
- case Z_MEM_ERROR:
- fputs("out of memory\n", stderr);
- break;
- case Z_VERSION_ERROR:
- fputs("zlib version mismatch!\n", stderr);
- }
-}
-
-
-
-
-
-
-
-
/* assumes that we know there is exactly 10 bytes of gzip header */
-int gzInflate(char *source, int slen, char *dest, int dlen)
+ssize_t
+gzInflate(const char *source, size_t slen, char *dest, size_t dlen)
{
int ret;
- unsigned have;
+ size_t have;
z_stream strm;
unsigned char in[CHUNK];
unsigned char out[CHUNK];
- int dlen_orig = dlen;
+ size_t dlen_orig = dlen;
+ if (slen > SIZE_T_CEILING || dlen > SIZE_T_CEILING)
+ return -1;
/* allocate inflate state */
strm.zalloc = Z_NULL;
@@ -229,7 +182,6 @@ int gzInflate(char *source, int slen, char *dest, int dlen)
strm.avail_in = 0;
strm.next_in = Z_NULL;
-
ret = inflateInit2(&strm, -MAX_WBITS);
if (ret != Z_OK)
return ret;
@@ -239,10 +191,9 @@ int gzInflate(char *source, int slen, char *dest, int dlen)
/* decompress until deflate stream ends or end of file */
do {
-
if (slen == 0)
break;
-
+
if (slen > CHUNK)
strm.avail_in = CHUNK;
else
@@ -251,9 +202,6 @@ int gzInflate(char *source, int slen, char *dest, int dlen)
memcpy(in, source, strm.avail_in);
slen = slen - strm.avail_in;
source = source + strm.avail_in;
-
-
-
strm.next_in = in;
/* run inflate() on input until output buffer not full */
@@ -261,20 +209,21 @@ int gzInflate(char *source, int slen, char *dest, int dlen)
strm.avail_out = CHUNK;
strm.next_out = out;
ret = inflate(&strm, Z_NO_FLUSH);
- assert(ret != Z_STREAM_ERROR); /* state not clobbered */
+ log_assert(ret != Z_STREAM_ERROR); /* state not clobbered */
switch (ret) {
case Z_NEED_DICT:
- ret = Z_DATA_ERROR; /* and fall through */
+ ret = Z_DATA_ERROR; /* and fall through */
case Z_DATA_ERROR:
case Z_MEM_ERROR:
- (void)inflateEnd(&strm);
- return ret;
+ inflateEnd(&strm);
+ return ret;
}
have = CHUNK - strm.avail_out;
- if ((unsigned int) dlen < have) {
- fprintf(stderr, "dest buf too small!\n");
- return Z_ERRNO;
+ if (dlen < have) {
+ log_warn("dest buf too small - have %lu, need %lu",
+ (unsigned long)dlen, (unsigned long)have);
+ return Z_ERRNO;
}
memcpy(dest, out, have);
@@ -287,45 +236,43 @@ int gzInflate(char *source, int slen, char *dest, int dlen)
} while (ret != Z_STREAM_END);
/* clean up and return */
- (void)inflateEnd(&strm);
+ inflateEnd(&strm);
if (ret == Z_STREAM_END)
return dlen_orig - dlen;
return Z_DATA_ERROR;
}
-
-
-
-
-
-
-int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime) {
+ssize_t
+gzDeflate(const char *source, size_t slen, char *dest, size_t dlen,
+ time_t mtime)
+{
unsigned char *c;
unsigned long crc;
z_stream z;
+ if (slen > SIZE_T_CEILING || dlen > SIZE_T_CEILING)
+ return -1;
+
z.zalloc = Z_NULL;
z.zfree = Z_NULL;
z.opaque = Z_NULL;
if (Z_OK != deflateInit2(&z,
- Z_DEFAULT_COMPRESSION,
- Z_DEFLATED,
- -MAX_WBITS, /* supress zlib-header */
- 8,
- Z_DEFAULT_STRATEGY)) {
+ Z_DEFAULT_COMPRESSION,
+ Z_DEFLATED,
+ -MAX_WBITS, /* supress zlib-header */
+ 8,
+ Z_DEFAULT_STRATEGY))
return -1;
- }
- z.next_in = (unsigned char *)start;
- z.avail_in = insz;
+ z.next_in = (Bytef *)source;
+ z.avail_in = slen;
z.total_in = 0;
-
/* write gzip header */
- c = (unsigned char *) buf;
+ c = (unsigned char *)dest;
c[0] = 0x1f;
c[1] = 0x8b;
c[2] = Z_DEFLATED;
@@ -338,19 +285,17 @@ int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime) {
c[9] = 0x03; /* UNIX */
z.next_out = c + 10;
- z.avail_out = outsz - 10 - 8;
+ z.avail_out = dlen - 10 - 8;
z.total_out = 0;
- if (Z_STREAM_END != deflate(&z, Z_FINISH)) {
+ if (deflate(&z, Z_FINISH) != Z_STREAM_END) {
deflateEnd(&z);
return -1;
}
+ crc = generate_crc32c(source, slen);
- crc = generate_crc32c(start, insz);
-
- c = (unsigned char *)buf + 10 + z.total_out;
-
+ c = (unsigned char *)dest + 10 + z.total_out;
c[0] = (crc >> 0) & 0xff;
c[1] = (crc >> 8) & 0xff;
c[2] = (crc >> 16) & 0xff;
@@ -360,49 +305,7 @@ int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime) {
c[6] = (z.total_in >> 16) & 0xff;
c[7] = (z.total_in >> 24) & 0xff;
-
-
- if (Z_OK != deflateEnd(&z)) {
+ if (deflateEnd(&z) != Z_OK)
return -1;
- }
-
return 10 + z.total_out + 8;
-
}
-
-
-
-
-
-/* compress or decompress from stdin to stdout */
-/* int main(int argc, char **argv) */
-/* { */
-/* int ret; */
-/* char buf1[32] = "abcasdfadfadfadf23fasdfa23sdfsdf"; */
-/* char buf2[100]; */
-/* char buf3[100]; */
-/* int i; */
-
-/* bzero(buf2, sizeof(buf2)); */
-/* bzero(buf3, sizeof(buf3)); */
-
-
-/* // ret = def(buf1, 3, buf2, 100, Z_DEFAULT_COMPRESSION); */
-/* ret = gzDeflate(buf1, sizeof(buf1), buf2, sizeof(buf2), time(NULL)); */
-/* if (ret <= 0) */
-/* zerr(ret); */
-
-/* /\* for (i=0; i < ret; i++) */
-/* putc(buf2[i], stdout); */
-/* *\/ */
-
-
-/* // printf("len = %d\n", ret); */
-
-/* ret = gzInflate(buf2, ret, buf3, 100); */
-/* if (ret <= 0) */
-/* zerr(ret); */
-/* printf("hello %s\n", buf3); */
-
-
-/* } */
diff --git a/src/steg/zpack.h b/src/steg/zpack.h
index d0e5cb2..5d3f82f 100644
--- a/src/steg/zpack.h
+++ b/src/steg/zpack.h
@@ -1,11 +1,12 @@
#ifndef _ZPACK_H
#define _ZPACK_H
-int def(char *source, int slen, char *dest, int dlen, int level);
-int inf(char *source, int slen, char *dest, int dlen);
-void zerr(int ret);
-int gzInflate(char *source, int slen, char *dest, int dlen);
-int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime);
-unsigned int generate_crc32c(char *buffer, size_t length);
+ssize_t def(const char *source, size_t slen, char *dest, size_t dlen,
+ int level);
+ssize_t inf(const char *source, size_t slen, char *dest, size_t dlen);
+
+ssize_t gzInflate(const char *source, size_t slen, char *dest, size_t dlen);
+ssize_t gzDeflate(const char *source, size_t slen, char *dest, size_t dlen,
+ time_t mtime);
#endif
1
0

[stegotorus/master] Thorough spring-cleaning on pdfSteg.cc; less thorough on swfSteg.cc
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 177ba0f8b4265d09c321d6903eeab040faeca430
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Mon Apr 23 14:49:52 2012 -0700
Thorough spring-cleaning on pdfSteg.cc; less thorough on swfSteg.cc
and some other headers. Add beginnings of unit tests for pdfSteg.
---
Makefile.am | 1 +
src/steg/pdfSteg.cc | 389 +++++++++++++-----------------------------
src/steg/pdfSteg.h | 38 +++--
src/steg/swfSteg.cc | 18 +--
src/steg/swfSteg.h | 23 +---
src/steg/zpack.h | 11 +-
src/test/tinytest_macros.h | 8 +-
src/test/unittest_pdfsteg.cc | 82 +++++++++
src/util.cc | 3 -
src/util.h | 3 +
10 files changed, 249 insertions(+), 327 deletions(-)
diff --git a/Makefile.am b/Makefile.am
index 6ba1b51..86ed489 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -49,6 +49,7 @@ stegotorus_SOURCES = \
UTGROUPS = \
src/test/unittest_crypt.cc \
+ src/test/unittest_pdfsteg.cc \
src/test/unittest_socks.cc \
src/test/unittest_config.cc \
src/test/unittest_transfer.cc
diff --git a/src/steg/pdfSteg.cc b/src/steg/pdfSteg.cc
index c67b0f8..3b4bbf0 100644
--- a/src/steg/pdfSteg.cc
+++ b/src/steg/pdfSteg.cc
@@ -1,7 +1,13 @@
-#include "payloads.h"
+#include "util.h"
#include "pdfSteg.h"
+#include "connections.h"
+#include "payloads.h"
+#include <event2/buffer.h>
+
+/* pdfSteg: A PDF-based steganography module */
-void buf_dump(unsigned char* buf, int len, FILE *out);
+#define PDF_DELIMITER '?'
+#define PDF_DELIMITER2 '.'
#define STREAM_BEGIN ">>stream"
#define STREAM_BEGIN_SIZE 8
@@ -10,45 +16,42 @@ void buf_dump(unsigned char* buf, int len, FILE *out);
#define DEBUG
-
/*
- * pdfSteg: A PDF-based steganography module
- *
- */
-
-
-/*
- * addDelimiter processes the input buffer (inbuf) of length inbuflen,
- * copies it to output buffer (outbuf) of size outbufsize,
+ * pdf_add_delimiter processes the input buffer (inbuf) of length
+ * inbuflen, copies it to output buffer (outbuf) of size outbufsize,
* and adds a two-char-long, end-of-data pattern at the end of outbuf
* based on delimiter1 and delimiter2.
*
* The end-of-data pattern consists of delimiter1 followed by a char
* that is not delimiter1. Thus, delimiter1 and delimiter2 must be
* different.
- *
- * If delimiter1 appears in the input buffer, addDelimiter puts two
- * delimiter1 char in output buffer (to enable removeDelimiter to perform
- * the back transformation)
*
- * addDelimiter returns the length of the data written to outbuf, including
- * the end-of-data pattern, if the transformation succeeds;
- * otherwise, it returns -1
+ * If delimiter1 appears in the input buffer, pdf_add_delimiter puts two
+ * delimiter1 characters in the output buffer, so that the transformation
+ * is reversible.
+ *
+ * pdf_add_delimiter returns the length of the data written to outbuf,
+ * including the end-of-data pattern, if the transformation succeeds;
+ * otherwise, it returns -1.
*
*/
-int
-addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
- const char delimiter1, const char delimiter2)
+ssize_t
+pdf_add_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ const char delimiter1, const char delimiter2)
{
- int cnt;
- char *ibp, ic, rc;
+ size_t cnt;
+ const char *ibp;
+ char ic, rc;
- if (delimiter1 == delimiter2) return -1;
+ log_assert(delimiter1 != delimiter2);
+ if (inbuflen > SIZE_T_CEILING || outbuflen > SIZE_T_CEILING)
+ return -1;
cnt = 0;
ibp = inbuf;
- while ((ibp-inbuf)<inbuflen && cnt<(outbuflen-2)) {
- ic = *(ibp++);
+ while (size_t(ibp-inbuf) < inbuflen && cnt < outbuflen-2) {
+ ic = *ibp++;
if (ic != delimiter1) {
outbuf[cnt++] = ic;
} else {
@@ -57,8 +60,9 @@ addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
}
}
- // error if outbuf is no large enough for storing the resulting data
- if (cnt >= (outbuflen-2)) return -1;
+ // error if outbuf is not large enough for storing the resulting data
+ if (cnt >= outbuflen-2)
+ return -1;
// put delimiter1 and a char that is not a delimiter1
// as the end-of-data pattern at the end of outbuf
@@ -75,8 +79,9 @@ addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
/*
- * removeDelimiter performs the reverse transformation of addDelimiter.
- *
+ * pdf_remove_delimiter performs the reverse transformation of
+ * pdf_add_delimiter.
+ *
* returns the length of data written to outbuf, if succeed;
* otherwise, it returns -1
*
@@ -84,20 +89,23 @@ addDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
* delimiter1 followed by non-delimiter1) is detected
*
* escape indicates if a dangling delimiter1 has been
- * seen in the previous invocation of removeDelimiter
+ * seen in the previous invocation of pdf_remove_delimiter
*/
-int
-removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
- const char delimiter1, int *endFlag, int *escape)
+ssize_t
+pdf_remove_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ char delimiter1, bool *endFlag, bool *escape)
{
- int cnt;
- char *ibp, ic1, ic2;
+ size_t cnt;
+ const char *ibp;
+ char ic1, ic2;
cnt = 0;
- *endFlag = 0;
+ *endFlag = false;
ibp = inbuf;
- if (inbuflen <= 0) return -1;
+ if (inbuflen > SIZE_T_CEILING || outbuflen > SIZE_T_CEILING)
+ return -1;
// special case: 2-char, end-of-data pattern could be in two buffers
// if *escape == true, we need to see if
@@ -113,9 +121,9 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
}
}
- *escape = 0;
- while ((ibp-inbuf+1)<inbuflen && cnt<outbuflen) {
- ic1 = *(ibp++);
+ *escape = false;
+ while (size_t(ibp-inbuf+1) < inbuflen && cnt < outbuflen) {
+ ic1 = *ibp++;
if (ic1 != delimiter1) {
outbuf[cnt++] = ic1;
} else {
@@ -125,13 +133,14 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
if (ic2 == delimiter1) {
outbuf[cnt++] = delimiter1; ibp++;
} else { // end-of-data pattern detected
- *endFlag = 1;
+ *endFlag = true;
return cnt;
}
}
}
- if (ibp-inbuf == inbuflen) return cnt;
+ if (size_t(ibp-inbuf) == inbuflen)
+ return cnt;
// handling the last char in inbuf, if needed
ic1 = *ibp;
@@ -139,40 +148,46 @@ removeDelimiter(char *inbuf, int inbuflen, char *outbuf, int outbuflen,
outbuf[cnt++] = ic1;
} else {
// look at the next stream obj to handle the special cases
- *escape = 1;
+ *escape = true;
}
return cnt;
}
-
-
/*
- * pdfWrap embeds data of length dlen inside the stream objects of the PDF
+ * pdf_wrap embeds data of length dlen inside the stream objects of the PDF
* document (length plen) that appears in the body of a HTTP msg, and
* stores the result in the output buffer of size outsize
*
- * pdfWrap returns the length of the pdf document with the data embedded
+ * pdf_wrap returns the length of the pdf document with the data embedded
* inside, if succeed; otherwise, it returns -1 to indicate an error
- *
- */
-int
-pdfWrap (char *data, unsigned int dlen,
- char *pdfTemplate, unsigned int plen,
- char *outbuf, unsigned int outbufsize)
+ *
+ */
+ssize_t
+pdf_wrap(const char *data, size_t dlen,
+ const char *pdfTemplate, size_t plen,
+ char *outbuf, size_t outbufsize)
{
char data2[dlen*2+2];
- char *tp, *dp, *op, *streamStart, *streamEnd, *plimit;
- int data2len, cnt, size, size2;
+ const char *tp, *dp, *plimit;
+ char *op, *streamStart, *streamEnd;
+ size_t data2len, cnt, size, size2;
+ ssize_t rv;
- // assumption: pdfWrap is length-preserving
- if (outbufsize < plen) return -1;
+ if (dlen > SIZE_T_CEILING || plen > SIZE_T_CEILING ||
+ outbufsize > SIZE_T_CEILING)
+ return -1;
- data2len = addDelimiter(data, dlen, data2, HTTP_MSG_BUF_SIZE, PDF_DELIMITER, PDF_DELIMITER2);
- if (data2len < 1) return -1;
+ // assumption: pdf_wrap is length-preserving
+ if (outbufsize < plen) return -1;
+ rv = pdf_add_delimiter(data, dlen, data2, HTTP_MSG_BUF_SIZE,
+ PDF_DELIMITER, PDF_DELIMITER2);
+ if (rv < 1)
+ return -1;
+ data2len = rv;
- op = outbuf; // current pointer for output buffer
+ op = outbuf; // current pointer for output buffer
tp = pdfTemplate; // current pointer for http msg template
dp = data2; // current pointer for data2
cnt = 0; // number of data char encoded
@@ -185,7 +200,7 @@ pdfWrap (char *data, unsigned int dlen,
log_warn("Cannot find stream in pdf");
return -1;
}
-
+
// copy everything between tp and "stream" (inclusive) to outbuf
size = streamStart - tp + STREAM_BEGIN_SIZE;
memcpy(op, tp, size);
@@ -206,18 +221,17 @@ pdfWrap (char *data, unsigned int dlen,
size2 = data2len - cnt;
if (size < size2) {
memcpy(op, dp, size);
- op += size; tp += size; dp += size;
+ op += size; tp += size; dp += size;
memcpy(op, tp, STREAM_END_SIZE);
op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
cnt += size;
} else { // done encoding data
memcpy(op, dp, size2);
- op += size2; tp += size2; dp += size2;
+ op += size2; tp += size2; dp += size2;
cnt += size2;
- // printf("Encoded %d char in pdf. Done encoding\n", size2);
break;
}
- log_debug("Encoded %d char in pdf", size);
+ log_debug("Encoded %lu bytes in pdf", (unsigned long)size);
} else { // empty stream
memcpy(op, tp, STREAM_END_SIZE);
op += STREAM_END_SIZE; tp += STREAM_END_SIZE;
@@ -228,25 +242,27 @@ pdfWrap (char *data, unsigned int dlen,
// copy the rest of pdfTemplate to outbuf
size = plimit-tp;
- log_debug("copying the rest of pdfTemplate to outbuf (size %d)", size);
+ log_debug("copying the rest of pdfTemplate to outbuf (size %lu)",
+ (unsigned long)size);
memcpy(op, tp, size);
op += size;
return (op-outbuf);
}
-
-
-
/*
- * pdfUnwrap is the inverse operation of pdfWrap
+ * pdf_unwrap is the inverse operation of pdf_wrap
*/
-int
-pdfUnwrap (char *data, unsigned int dlen,
- char *outbuf, unsigned int outbufsize)
+ssize_t
+pdf_unwrap(const char *data, size_t dlen,
+ char *outbuf, size_t outbufsize)
{
- char *dp, *op, *streamStart, *streamEnd, *dlimit, *olimit;
- int cnt, size, size2, endFlag;
- int escape = 0;
+ const char *dp, *dlimit;
+ char *op, *streamStart, *streamEnd, *olimit;
+ size_t cnt, size, size2;
+ bool endFlag, escape = false;
+
+ if (dlen > SIZE_T_CEILING || outbufsize > SIZE_T_CEILING)
+ return -1;
dp = data; // current pointer for data
op = outbuf; // current pointer for outbuf
@@ -272,11 +288,13 @@ pdfUnwrap (char *data, unsigned int dlen,
// count the number of usable char between tp and streamEnd
size = streamEnd-dp;
- if (size > 0) {
- size2 = removeDelimiter(dp, size, op, olimit-op, PDF_DELIMITER, &endFlag, &escape);
- if (size2 < 0) {
+ if (size > 0) {
+ ssize_t rv = pdf_remove_delimiter(dp, size, op, olimit-op, PDF_DELIMITER,
+ &endFlag, &escape);
+ if (rv < 0)
return -1;
- }
+
+ size2 = rv;
cnt += size2;
if (endFlag) { // Done decoding
break;
@@ -292,22 +310,16 @@ pdfUnwrap (char *data, unsigned int dlen,
return cnt;
}
-
-
-
-
int
-http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
- conn_t *conn)
+http_server_PDF_transmit(payloads &pl, struct evbuffer *source,
+ conn_t *conn)
{
-
struct evbuffer *dest = conn->outbound();
size_t sbuflen = evbuffer_get_length(source);
unsigned int mpdf;
char *pdfTemplate = NULL, *hend;
int pdfTemplateSize = 0;
- // char data1[HTTP_MSG_BUF_SIZE];
- char data1[(int) sbuflen];
+ char data1[sbuflen];
char outbuf[HTTP_MSG_BUF_SIZE];
int cnt, hLen, outbuflen, i;
@@ -317,10 +329,6 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
struct evbuffer_iovec *iv;
int nv;
- // for debugging pdfWrap and pdfUnwrap
- // char data2[(int) sbuflen];
- // int data2len;
-
log_debug("Entering SERVER PDF transmit with sbuflen %d", (int)sbuflen);
nv = evbuffer_peek(source, sbuflen, NULL, NULL, 0);
@@ -357,8 +365,10 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
return -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);
+ 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");
return -1;
@@ -371,39 +381,19 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
}
hLen = hend+4-pdfTemplate;
-
- log_debug("SERVER calling pdfWrap for data1 with length %d", cnt);
- outbuflen = pdfWrap(data1, cnt, hend+4, pdfTemplateSize-hLen, outbuf, HTTP_MSG_BUF_SIZE);
+
+ log_debug("SERVER calling pdf_wrap for data1 with length %d", cnt);
+ outbuflen = pdf_wrap(data1, cnt, hend+4, pdfTemplateSize-hLen, outbuf,
+ HTTP_MSG_BUF_SIZE);
if (outbuflen < 0) {
- log_warn("SERVER pdfWrap fails");
+ log_warn("SERVER pdf_wrap fails");
return -1;
}
- log_debug("SERVER pdfSteg sends resp with hdr len %d body len %d", hLen, outbuflen);
-
-
- // debugging
- // buf_dump((unsigned char *)data1, cnt, stderr);
-
- // data2len = pdfUnwrap(outbuf, outbuflen, data2, sbuflen);
- // if ((int)sbuflen == data2len) {
- // log_warn("sbuflen == data2len == %d", (int)sbuflen);
- // if (memcmp(data1, data2, sbuflen) == 0) {
- // log_warn("data1 and data2 match");
- // } else {
- // log_warn("data1 and data2 DO NOT match!! Dumping data1 ...");
- // buf_dump((unsigned char *)data1, cnt, stderr);
- // log_warn("data1 and data2 DO NOT match!! Dumping data2...");
- // buf_dump((unsigned char *)data2, data2len, stderr);
- // }
- // } else {
- // log_warn("*** sbuflen = %d, data2len = %d *** Dumping data1 ...", (int)sbuflen, data2len);
- // buf_dump((unsigned char *)data1, cnt, stderr);
- // log_warn("*** sbuflen = %d, data2len = %d *** Dumping data2 ...", (int)sbuflen, data2len);
- // buf_dump((unsigned char *)data2, data2len, stderr);
- // }
-
-
- newHdrLen = gen_response_header((char*) "application/pdf", 0, outbuflen, newHdr, sizeof(newHdr));
+ log_debug("SERVER pdfSteg sends resp with hdr len %d body len %d",
+ hLen, outbuflen);
+
+ newHdrLen = gen_response_header((char*) "application/pdf", 0,
+ outbuflen, newHdr, sizeof(newHdr));
if (newHdrLen < 0) {
log_warn("SERVER ERROR: gen_response_header fails for pdfSteg");
return -1;
@@ -413,10 +403,6 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
log_warn("SERVER ERROR: evbuffer_add() fails for newHdr");
return -1;
}
- // if (evbuffer_add(dest, pdfTemplate, hLen)) {
- // log_warn("SERVER ERROR: evbuffer_add() fails for pdfTemplate");
- // return -1;
- // }
if (evbuffer_add(dest, outbuf, outbuflen)) {
log_warn("SERVER ERROR: evbuffer_add() fails for outbuf");
@@ -426,14 +412,13 @@ http_server_PDF_transmit (payloads& pl, struct evbuffer *source,
evbuffer_drain(source, sbuflen);
conn->cease_transmission();
- // downcast_steg(s)->have_transmitted = 1;
return 0;
}
-
-
int
-http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest, struct evbuffer* source) {
+http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest,
+ struct evbuffer* source)
+{
struct evbuffer_ptr s2;
unsigned int response_len = 0, hdrLen;
char outbuf[HTTP_MSG_BUF_SIZE];
@@ -444,8 +429,8 @@ http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest, st
s2 = evbuffer_search(source, "\r\n\r\n", sizeof ("\r\n\r\n") -1 , NULL);
if (s2.pos == -1) {
- log_warn("CLIENT Did not find end of HTTP header %d", (int) evbuffer_get_length(source));
- // evbuffer_dump(source, stderr);
+ log_warn("CLIENT Did not find end of HTTP header %d",
+ (int) evbuffer_get_length(source));
return RECV_INCOMPLETE;
}
@@ -480,154 +465,26 @@ http_handle_client_PDF_receive(steg_t *, conn_t *conn, struct evbuffer *dest, st
return RECV_BAD;
}
-
httpBody = httpHdr + hdrLen;
-
- outbuflen = pdfUnwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
+ outbuflen = pdf_unwrap(httpBody, content_len, outbuf, HTTP_MSG_BUF_SIZE);
if (outbuflen < 0) {
- log_warn("CLIENT ERROR: pdfUnwrap fails\n");
+ log_warn("CLIENT ERROR: pdf_unwrap fails\n");
return RECV_BAD;
}
log_debug("CLIENT unwrapped data of length %d:", outbuflen);
-
if (evbuffer_add(dest, outbuf, outbuflen)) {
log_warn("CLIENT ERROR: evbuffer_add to dest fails\n");
return RECV_BAD;
}
- // log_debug("Drained source for %d char\n", response_len);
if (evbuffer_drain(source, response_len) == -1) {
log_warn("CLIENT ERROR: failed to drain source\n");
return RECV_BAD;
}
- // downcast_steg(s)->have_received = 1;
conn->expect_close();
return RECV_GOOD;
}
-
-
-
-
-/*****
-int main() {
- char data1[] = "this is a test?? yes!";
- char data2[100];
- char data3[100];
- int dlen1, dlen2, dlen3, end;
- char last = ' ';
- printf("hello world\n");
-
- dlen2 = addDelimiter(data1, strlen(data1), data2, 100, '?', '.');
- printf("dlen2 = %d\n", dlen2);
- dlen3 = removeDelimiter(data2, dlen2, data3, 100, '?', &end, &last);
- printf("endflag = %d", end);
- printf("dlen3 = %d\n", dlen3);
- if (memcmp(data1, data3, dlen3) == 0) {
- data1[dlen3] = 0;
- printf("removeDelimiter(addDelimiter(x)) == x for |%s|\n", data1);
- } else {
- printf("removeDelimiter(addDelimiter(x)) != x for |%s|\n", data1);
- }
- return 1;
-}
- *****/
-
-/*****
-int main() {
- char data1[] = "12345";
- char data2[] = "123456789012";
- char data3[] = "12345678901";
- char data4[] = "1234567890?";
- char pdf1[] = "[PDFHDR][STUFFS1]>>streamABCDEFGHIJYYendstream[STUFFS2]>>streamABCDEFGHIJYYendstream[STUFF3][PDFTRAILER]";
- char out[200];
- char orig[200];
- int r1, r2;
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data1);
- printf("strlen(pdf1) = %d\n", (int)strlen(pdf1));
- r1 = pdfWrap(data1, strlen(data1), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data2);
- r1 = pdfWrap(data2, strlen(data2), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data3);
- r1 = pdfWrap(data3, strlen(data3), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- printf("********************\n");
- printf("pdfwrap for %s\n", data4);
- r1 = pdfWrap(data4, strlen(data4), pdf1, strlen(pdf1), out, (int)sizeof(out));
- if (r1 > 0) {
- printf("pdfWrap returns %d\n", r1);
- out[r1] = 0;
- printf("out[] contains |%s|\n", out);
- } else {
- printf("pdfWrap returns %d\n", r1);
- }
-
- r2 = pdfUnwrap(out, r1, orig, (int)sizeof(orig));
- if (r2 > 0) {
- printf("pdfUnwrap returns %d\n", r2);
- orig[r2] = 0;
- printf("orig[] contains |%s|\n", orig);
- } else {
- printf("pdfUnwrap returns %d\n", r2);
- }
-
- return 0;
-}
- *****/
diff --git a/src/steg/pdfSteg.h b/src/steg/pdfSteg.h
index 3d494e1..0bd3a43 100644
--- a/src/steg/pdfSteg.h
+++ b/src/steg/pdfSteg.h
@@ -1,29 +1,31 @@
#ifndef _PDFSTEG_H
#define _PDFSTEG_H
+struct payloads;
-#include <stdio.h>
-#include <string.h>
-#include <ctype.h>
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-#include <event2/buffer.h>
+// These are the public interface.
-struct payloads;
+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);
-#define PDF_DELIMITER '?'
-#define PDF_DELIMITER2 '.'
+// These are exposed only for the sake of unit tests.
-int pdfWrap (char *data, unsigned int dlen, char *pdfTemplate, unsigned int plen, char *outbuf, unsigned int outbufsize);
-int pdfUnwrap (char *data, unsigned int dlen, char *outbuf, unsigned int outbufsize);
+ssize_t pdf_add_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ char delimiter1, char delimiter2);
-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);
+ssize_t pdf_remove_delimiter(const char *inbuf, size_t inbuflen,
+ char *outbuf, size_t outbuflen,
+ char delimiter1, bool *endFlag, bool *escape);
-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);
+ssize_t pdf_wrap(const char *data, size_t dlen,
+ const char *pdfTemplate, size_t plen,
+ char *outbuf, size_t outbufsize);
-#endif
+ssize_t pdf_unwrap(const char *data, size_t dlen,
+ char *outbuf, size_t outbufsize);
+#endif
diff --git a/src/steg/swfSteg.cc b/src/steg/swfSteg.cc
index cd371f3..c8a18c1 100644
--- a/src/steg/swfSteg.cc
+++ b/src/steg/swfSteg.cc
@@ -1,5 +1,11 @@
+#include "util.h"
#include "swfSteg.h"
+#include "connections.h"
+#include "payloads.h"
+#include "zlib.h"
+#include "zpack.h"
+#include <event2/buffer.h>
static const char http_response_1[] =
"HTTP/1.1 200 OK\r\n"
@@ -9,17 +15,7 @@ static const char http_response_1[] =
"Content-Type: application/x-shockwave-flash\r\n"
"Content-Length: ";
-
-
-
-
-
-
-
-
-
-
-unsigned int
+unsigned int
swf_wrap(payloads& pl, char* inbuf, int in_len, char* outbuf, int out_sz) {
char* swf;
diff --git a/src/steg/swfSteg.h b/src/steg/swfSteg.h
index 712a3a3..b8336b2 100644
--- a/src/steg/swfSteg.h
+++ b/src/steg/swfSteg.h
@@ -1,38 +1,21 @@
#ifndef _SWFSTEG_H
#define _SWFSTEG_H
-
-#include "util.h"
-#include "connections.h"
-#include "steg.h"
-#include "payloads.h"
-#include "cookies.h"
-#include "pdfSteg.h"
-#include "zpack.h"
-
-
-#include <event2/buffer.h>
-#include <stdio.h>
-
struct payloads;
#define SWF_SAVE_HEADER_LEN 1500
#define SWF_SAVE_FOOTER_LEN 1500
-
-unsigned int
+unsigned int
swf_wrap(payloads& pl, char* inbuf, int in_len, char* outbuf, int out_sz);
-unsigned int
+unsigned int
swf_unwrap(char* inbuf, int in_len, char* outbuf, int out_sz);
-int
+int
http_server_SWF_transmit(payloads& pl, struct evbuffer *source, conn_t *conn);
-
int
http_handle_client_SWF_receive(steg_t *s, conn_t *conn, struct evbuffer *dest, struct evbuffer* source);
#endif
-
-
diff --git a/src/steg/zpack.h b/src/steg/zpack.h
index 65cd28d..d0e5cb2 100644
--- a/src/steg/zpack.h
+++ b/src/steg/zpack.h
@@ -1,10 +1,5 @@
-#include <stdio.h>
-#include <string.h>
-#include <assert.h>
-#include <time.h>
-#include <stdlib.h>
-#include "zlib.h"
-
+#ifndef _ZPACK_H
+#define _ZPACK_H
int def(char *source, int slen, char *dest, int dlen, int level);
int inf(char *source, int slen, char *dest, int dlen);
@@ -12,3 +7,5 @@ void zerr(int ret);
int gzInflate(char *source, int slen, char *dest, int dlen);
int gzDeflate(char* start, off_t insz, char *buf, off_t outsz, time_t mtime);
unsigned int generate_crc32c(char *buffer, size_t length);
+
+#endif
diff --git a/src/test/tinytest_macros.h b/src/test/tinytest_macros.h
index 40d17e2..cf5a2a2 100644
--- a/src/test/tinytest_macros.h
+++ b/src/test/tinytest_macros.h
@@ -168,6 +168,10 @@
tt_assert_test_type(a,b,#a" "#op" "#b,void*, \
(_val1 op _val2),"%p")
+#define tt_char_op(a,op,b) \
+ tt_assert_test_type(a,b,#a" "#op" "#b,int, \
+ (_val1 op _val2),"'%c'")
+
#define tt_str_op(a,op,b) \
tt_assert_test_type(a,b,#a" "#op" "#b,const char *, \
(strcmp(_val1,_val2) op 0),"<%s>")
@@ -176,7 +180,7 @@
tt_assert_test_fmt_type(a,b,#a" "#op" "#b, \
const char *, \
(strncmp(_val1, _val2, len) op 0), \
- char *, "%s", \
+ char *, "<%s>", \
{ _print = xstrndup(_value, len); }, \
{ free(_print); } \
);
@@ -185,7 +189,7 @@
tt_assert_test_fmt_type(a,b,#a" "#op" "#b, \
const char *, \
(memcmp(_val1, _val2, len) op 0), \
- char *, "%s", \
+ char *, "<%s>", \
{ _print = tt_base16_encode(_value, len); }, \
{ free(_print); } \
);
diff --git a/src/test/unittest_pdfsteg.cc b/src/test/unittest_pdfsteg.cc
new file mode 100644
index 0000000..cf9e97d
--- /dev/null
+++ b/src/test/unittest_pdfsteg.cc
@@ -0,0 +1,82 @@
+/* Copyright 2011, 2012 SRI International
+ See LICENSE for other credits and copying information */
+
+#include "util.h"
+#include "unittest.h"
+#include "../steg/pdfSteg.h"
+
+static void
+test_pdf_add_remove_delimiters(void *)
+{
+ const char *data1 = "this is a test?? yes!";
+ char data2[100];
+ char data3[100];
+ int dlen2, dlen3;
+ bool end = false, escape = false;
+
+ memset(data2, 0, sizeof data2);
+ memset(data3, 0, sizeof data3);
+
+ dlen2 = pdf_add_delimiter(data1, strlen(data1), data2, 100, '?', '.');
+ tt_int_op(dlen2, ==, 25);
+ tt_stn_op(data2, ==, "this is a test???? yes!?", 24);
+ tt_char_op(data2[24], !=, '?');
+
+ dlen3 = pdf_remove_delimiter(data2, dlen2, data3, 100, '?', &end, &escape);
+ tt_int_op(dlen3, ==, 21);
+ tt_str_op(data3, ==, data1);
+ tt_bool_op(end, ==, true);
+ tt_bool_op(escape, ==, false);
+
+ end:;
+}
+
+static void
+test_pdf_wrap_unwrap(void *)
+{
+ const char *pdf =
+ "[PDFHDR][STUFFS1]>>streamABCDEFGHIJYYendstream"
+ "[STUFFS2]>>streamABCDEFGHIJYYendstream[STUFF3][PDFTRAILER]";
+
+ const char *const tests[] = {
+ "12345",
+ "123456789012",
+ "12345678901",
+ "1234567890?",
+ 0
+ };
+
+ char out[200];
+ char orig[200];
+ int i;
+ size_t r1, r2;
+ ssize_t rv;
+
+ for (i = 0; tests[i]; i++) {
+ memset(out, 0, sizeof out);
+ memset(orig, 0, sizeof out);
+ rv = pdf_wrap(tests[i], strlen(tests[i]),
+ pdf, strlen(pdf),
+ out, sizeof out);
+ tt_int_op(rv, >, 0);
+ r1 = rv;
+ tt_int_op(r1, ==, strlen(pdf));
+
+ rv = pdf_unwrap(out, r1, orig, sizeof orig);
+ tt_int_op(rv, >, 0);
+ r2 = rv;
+ tt_int_op(r2, ==, strlen(tests[i]));
+ tt_stn_op(orig, ==, tests[i], r2);
+ }
+
+ end:;
+}
+
+#define T(name) \
+ { #name, test_pdf_##name, 0, 0, 0 }
+
+struct testcase_t pdf_tests[] = {
+ T(add_remove_delimiters),
+ T(wrap_unwrap),
+ END_OF_TESTCASES
+};
diff --git a/src/util.cc b/src/util.cc
index b813ae9..a667abd 100644
--- a/src/util.cc
+++ b/src/util.cc
@@ -17,9 +17,6 @@
#include <sys/un.h>
#endif
-/** Any size_t larger than this amount is likely to be an underflow. */
-#define SIZE_T_CEILING (SIZE_MAX/2 - 16)
-
/**************************** Memory Allocation ******************************/
static void ATTR_NORETURN
diff --git a/src/util.h b/src/util.h
index 05bc6d0..167af8e 100644
--- a/src/util.h
+++ b/src/util.h
@@ -57,6 +57,9 @@ struct event_base;
/***** Memory allocation. *****/
+/** Any size_t larger than this amount is likely to be an underflow. */
+#define SIZE_T_CEILING (SIZE_MAX/2 - 16)
+
/* Because this isn't Tor and functions named "tor_whatever" would be
confusing, I am instead following the GNU convention of naming
allocate-memory-or-crash functions "xwhatever". Also, at this time
1
0

[stegotorus/master] Merge branch 'master' of https://git.safdef.isc.org/git/stegotorus
by zwol@torproject.org 20 Jul '12
by zwol@torproject.org 20 Jul '12
20 Jul '12
commit 560b952671f90505ca7193371410c370c9769f62
Merge: 343d961 0538c5a
Author: Zack Weinberg <zackw(a)cmu.edu>
Date: Mon Apr 23 15:41:50 2012 -0700
Merge branch 'master' of https://git.safdef.isc.org/git/stegotorus
Conflicts:
src/steg/zpack.h
1
0