commit 3d85a235c6a6729eeac92413c2fcb982d4578a57 Author: George Kadianakis desnacked@gmail.com Date: Sat Aug 20 16:28:13 2011 +0200
Dump the silly get_other_conn() hack; use configurable circuits.
* Introduce (*circuit_create) and (*circuit_free) which allow the module writer to configure his circuits. * Put the obfs2 state in a circuit instead of a connection. --- src/network.c | 13 ++++++++-- src/protocol.c | 24 +++++++++++++++++++++ src/protocol.h | 12 ++++++++++ src/protocols/dummy.c | 19 ++++++++++++++++ src/protocols/dummy.h | 4 +++ src/protocols/obfs2.c | 51 +++++++++++++++++++++++++++----------------- src/protocols/obfs2.h | 6 ++++- src/test/unittest_obfs2.c | 51 ++++++++++++++++++++++++++++++++++---------- 8 files changed, 144 insertions(+), 36 deletions(-)
diff --git a/src/network.c b/src/network.c index 0fd5e4d..91b1237 100644 --- a/src/network.c +++ b/src/network.c @@ -378,7 +378,9 @@ circuit_create(conn_t *up, conn_t *down) if (!up || !down) return -1;
- circuit_t *r = xzalloc(sizeof(circuit_t)); + obfs_assert(up->cfg == down->cfg); + + circuit_t *r = proto_circuit_create(up->cfg); r->upstream = up; r->downstream = down; up->circuit = r; @@ -391,7 +393,7 @@ circuit_create_socks(conn_t *up) { obfs_assert(up);
- circuit_t *r = xzalloc(sizeof(circuit_t)); + circuit_t *r = proto_circuit_create(up->cfg); r->upstream = up; r->socks_state = socks_state_new(); up->circuit = r; @@ -410,6 +412,10 @@ circuit_add_down(circuit_t *circuit, conn_t *down) static void circuit_free(circuit_t *circuit) { + /* keep the cfg so that we can use its vtable for proto_circuit_free() */ + config_t *cfg = circuit->upstream->cfg; + obfs_assert(cfg); + /* break the circular references before deallocating each side */ circuit->upstream->circuit = NULL; conn_free(circuit->upstream); @@ -419,7 +425,8 @@ circuit_free(circuit_t *circuit) } if (circuit->socks_state) socks_state_free(circuit->socks_state); - free(circuit); + + proto_circuit_free(circuit, cfg); }
/** diff --git a/src/protocol.c b/src/protocol.c index 14437e6..81fd454 100644 --- a/src/protocol.c +++ b/src/protocol.c @@ -165,3 +165,27 @@ proto_conn_free(conn_t *conn) { obfs_assert(conn->cfg->vtable->conn_free); conn->cfg->vtable->conn_free(conn); } + +/** + This protocol is called everytime a circuit has to be created. + Return a circuit_t on success or a NULL on fail. +*/ +circuit_t * +proto_circuit_create(config_t *cfg) +{ + obfs_assert(cfg); + obfs_assert(cfg->vtable); + obfs_assert(cfg->vtable->circuit_create); + return cfg->vtable->circuit_create(cfg); +} + +/** + This function destroys 'circuit', using the vtable off 'cfg'. +*/ +void +proto_circuit_free(circuit_t *circuit, config_t *cfg) { + obfs_assert(cfg); + obfs_assert(cfg->vtable); + obfs_assert(cfg->vtable->circuit_free); + cfg->vtable->circuit_free(circuit); +} diff --git a/src/protocol.h b/src/protocol.h index ede91f1..d360594 100644 --- a/src/protocol.h +++ b/src/protocol.h @@ -62,6 +62,12 @@ struct protocol_vtable /** Destroy per-connection, protocol-specific state. */ void (*conn_free)(conn_t *state);
+ /** A 'circuit_t' needs to be created. */ + circuit_t *(*circuit_create)(config_t *cfg); + + /** Destroy a 'circuit_t'. */ + void (*circuit_free)(circuit_t *circuit); + /** Perform a connection handshake. Not all protocols have a handshake. */ int (*handshake)(conn_t *state, struct evbuffer *buf);
@@ -92,6 +98,8 @@ struct protocol_vtable name##_config_get_target_addr, \ name##_conn_create, \ name##_conn_free, \ + name##_circuit_create, \ + name##_circuit_free, \ name##_handshake, name##_send, name##_recv \ }
@@ -107,6 +115,10 @@ struct evutil_addrinfo *config_get_target_addr(config_t *cfg); conn_t *proto_conn_create(config_t *cfg); void proto_conn_free(conn_t *conn);
+circuit_t *proto_circuit_create(config_t *cfg); +void proto_circuit_free(circuit_t *conn, config_t *cfg); + + int proto_handshake(conn_t *conn, void *buf); int proto_send(conn_t *conn, void *source, void *dest); enum recv_ret proto_recv(conn_t *conn, void *source, void *dest); diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c index 27e6340..21fd3ca 100644 --- a/src/protocols/dummy.c +++ b/src/protocols/dummy.c @@ -22,6 +22,12 @@ downcast_conn(conn_t *p) return DOWNCAST(dummy_conn_t, super, p); }
+static inline dummy_circuit_t * +downcast_circuit(circuit_t *p) +{ + return DOWNCAST(dummy_circuit_t, super, p); +} + /** Helper: Parses 'options' and fills 'cfg'. */ @@ -174,6 +180,19 @@ dummy_conn_free(conn_t *proto) free(downcast_conn(proto)); }
+static circuit_t * +dummy_circuit_create(config_t *cfg) +{ + dummy_circuit_t *circuit = xzalloc(sizeof(dummy_circuit_t)); + return &circuit->super; +} + +static void +dummy_circuit_free(circuit_t *circ) +{ + free(downcast_circuit(circ)); +} + /** Dummy has no handshake */ static int dummy_handshake(conn_t *proto, struct evbuffer *buf) diff --git a/src/protocols/dummy.h b/src/protocols/dummy.h index d243f06..3dc1995 100644 --- a/src/protocols/dummy.h +++ b/src/protocols/dummy.h @@ -33,6 +33,10 @@ typedef struct dummy_conn_t { conn_t super; } dummy_conn_t;
+typedef struct dummy_circuit_t { + circuit_t super; +} dummy_circuit_t; + #endif
#endif diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c index 42a1c04..6e241c3 100644 --- a/src/protocols/obfs2.c +++ b/src/protocols/obfs2.c @@ -22,6 +22,13 @@ downcast_conn(conn_t *p) return DOWNCAST(obfs2_conn_t, super, p); }
+static inline obfs2_circuit_t * +downcast_circuit(circuit_t *p) +{ + return DOWNCAST(obfs2_circuit_t, super, p); +} + + static int parse_and_set_options(int n_options, const char *const *options, obfs2_config_t *params); @@ -44,20 +51,10 @@ shared_seed_nonzero(const uchar *seed) return memcmp(seed, SHARED_ZERO_SEED, SHARED_SECRET_LENGTH) != 0; }
-/** - Stupid temporary function returning the other conn of a circuit. - For example, if 'conn' is the downstream connection on a circuit, - this function returns the upstream connection. -*/ -static inline conn_t * -get_other_conn(conn_t *conn) +static inline obfs2_state_t * +get_state_from_conn(conn_t *conn) { - if (conn->circuit->upstream == conn) { - return conn->circuit->downstream; - } else { - obfs_assert(conn->circuit->downstream == conn); - return conn->circuit->upstream; - } + return downcast_circuit(conn->circuit)->state; }
static void @@ -246,7 +243,6 @@ obfs2_conn_create(config_t *cfg) obfs2_conn_t *conn = xzalloc(sizeof(obfs2_conn_t)); conn->super.cfg = cfg; conn->super.mode = downcast_config(cfg)->mode; - conn->state = state_create(cfg);
return &conn->super; } @@ -254,10 +250,25 @@ obfs2_conn_create(config_t *cfg) static void obfs2_conn_free(conn_t *conn) { - obfs2_conn_t *obfs2_conn = downcast_conn(conn); + free(downcast_conn(conn)); +} + +static circuit_t * +obfs2_circuit_create(config_t *cfg) +{ + obfs2_circuit_t *circuit = xzalloc(sizeof(obfs2_circuit_t)); + circuit->state = state_create(cfg); + + return &circuit->super; +} + +static void +obfs2_circuit_free(circuit_t *circuit) +{ + obfs2_circuit_t *obfs2_circuit = downcast_circuit(circuit);
- obfs2_destroy(obfs2_conn->state); - free(obfs2_conn); + obfs2_destroy(obfs2_circuit->state); + free(obfs2_circuit); }
/** @@ -402,7 +413,7 @@ obfs2_destroy(obfs2_state_t *state) static int obfs2_handshake(conn_t *s, struct evbuffer *buf) { - obfs2_state_t *state = downcast_conn(s)->state; + obfs2_state_t *state = get_state_from_conn(s);
uint32_t magic = htonl(OBFUSCATE_MAGIC_VALUE), plength, send_plength; uchar msg[OBFUSCATE_MAX_PADDING + OBFUSCATE_SEED_LENGTH + 8]; @@ -474,7 +485,7 @@ static int obfs2_send(conn_t *s, struct evbuffer *source, struct evbuffer *dest) { - obfs2_state_t *state = downcast_conn(get_other_conn(s))->state; + obfs2_state_t *state = get_state_from_conn(s);
if (state->send_crypto) { /* First of all, send any data that we've been waiting to send. */ @@ -554,7 +565,7 @@ static enum recv_ret obfs2_recv(conn_t *s, struct evbuffer *source, struct evbuffer *dest) { - obfs2_state_t *state = downcast_conn(s)->state; + obfs2_state_t *state = get_state_from_conn(s);
if (state->state == ST_WAIT_FOR_KEY) { /* We're waiting for the first OBFUSCATE_SEED_LENGTH+8 bytes to show up diff --git a/src/protocols/obfs2.h b/src/protocols/obfs2.h index a8fe2cc..fb07407 100644 --- a/src/protocols/obfs2.h +++ b/src/protocols/obfs2.h @@ -79,9 +79,13 @@ typedef struct obfs2_config_t {
typedef struct obfs2_conn_t { conn_t super; - obfs2_state_t *state; } obfs2_conn_t;
+typedef struct obfs2_circuit_t { + circuit_t super; + obfs2_state_t *state; +} obfs2_circuit_t; + #endif
#endif diff --git a/src/test/unittest_obfs2.c b/src/test/unittest_obfs2.c index 6e14b1e..7037788 100644 --- a/src/test/unittest_obfs2.c +++ b/src/test/unittest_obfs2.c @@ -21,6 +21,18 @@ downcast(conn_t *proto) return DOWNCAST(obfs2_conn_t, super, proto); }
+static inline obfs2_circuit_t * +downcast_circuit(circuit_t *p) +{ + return DOWNCAST(obfs2_circuit_t, super, p); +} + +static inline obfs2_state_t * +get_state_from_conn(conn_t *conn) +{ + return downcast_circuit(conn->circuit)->state; +} + static void test_obfs2_option_parsing(void *unused) { @@ -81,7 +93,9 @@ struct test_obfs2_state config_t *cfg_client; config_t *cfg_server; conn_t *conn_client; + conn_t *conn2_client; /* dummy conn to build a circuit */ conn_t *conn_server; + conn_t *conn2_server; /* dummy conn to build a circuit */ struct evbuffer *output_buffer; struct evbuffer *dummy_buffer; }; @@ -91,10 +105,17 @@ cleanup_obfs2_state(const struct testcase_t *unused, void *state) { struct test_obfs2_state *s = (struct test_obfs2_state *)state;
+ proto_circuit_free(s->conn_client->circuit, s->cfg_client); if (s->conn_client) proto_conn_free(s->conn_client); + if (s->conn2_client) + proto_conn_free(s->conn2_client); + + proto_circuit_free(s->conn_server->circuit, s->cfg_server); if (s->conn_server) proto_conn_free(s->conn_server); + if (s->conn2_server) + proto_conn_free(s->conn2_server);
if (s->cfg_client) config_free(s->cfg_client); @@ -136,6 +157,15 @@ setup_obfs2_state(const struct testcase_t *unused) s->conn_server = proto_conn_create(s->cfg_server); tt_assert(s->conn_server);
+ s->conn2_client = proto_conn_create(s->cfg_client); + tt_assert(s->conn2_client); + + s->conn2_server = proto_conn_create(s->cfg_server); + tt_assert(s->conn2_server); + + tt_assert(!(circuit_create(s->conn_client, s->conn2_client)<0)); + tt_assert(!(circuit_create(s->conn_server, s->conn2_server)<0)); + s->output_buffer = evbuffer_new(); tt_assert(s->output_buffer);
@@ -156,8 +186,8 @@ static void test_obfs2_handshake(void *state) { struct test_obfs2_state *s = (struct test_obfs2_state *)state; - obfs2_state_t *client_state = downcast(s->conn_client)->state; - obfs2_state_t *server_state = downcast(s->conn_server)->state; + obfs2_state_t *client_state = get_state_from_conn(s->conn_client); + obfs2_state_t *server_state = get_state_from_conn(s->conn_server);
/* We create a client handshake message and pass it to output_buffer */ tt_int_op(0, <=, proto_handshake(s->conn_client, s->output_buffer)); @@ -167,6 +197,7 @@ test_obfs2_handshake(void *state) tt_assert(RECV_GOOD == proto_recv(s->conn_server, s->output_buffer, s->dummy_buffer));
+ /* Now, we create the server's handshake and pass it to output_buffer */ tt_int_op(0, <=, proto_handshake(s->conn_server, s->output_buffer));
@@ -193,10 +224,6 @@ test_obfs2_transfer(void *state) int n; struct evbuffer_iovec v[2];
- /* evil trick to bypass get_other_conn() */ - circuit_create(s->conn_client, s->conn_client); - circuit_create(s->conn_server, s->conn_server); - /* Handshake */ tt_int_op(0, <=, proto_handshake(s->conn_client, s->output_buffer)); tt_assert(RECV_GOOD == proto_recv(s->conn_server, s->output_buffer, @@ -254,8 +281,8 @@ static void test_obfs2_split_handshake(void *state) { struct test_obfs2_state *s = (struct test_obfs2_state *)state; - obfs2_state_t *client_state = downcast(s->conn_client)->state; - obfs2_state_t *server_state = downcast(s->conn_server)->state; + obfs2_state_t *client_state = get_state_from_conn(s->conn_client); + obfs2_state_t *server_state = get_state_from_conn(s->conn_server);
uint32_t magic = htonl(OBFUSCATE_MAGIC_VALUE); uint32_t plength1, plength1_msg1, plength1_msg2, send_plength1; @@ -372,8 +399,8 @@ static void test_obfs2_wrong_handshake_magic(void *state) { struct test_obfs2_state *s = (struct test_obfs2_state *)state; - obfs2_state_t *client_state = downcast(s->conn_client)->state; - obfs2_state_t *server_state = downcast(s->conn_server)->state; + obfs2_state_t *client_state = get_state_from_conn(s->conn_client); + obfs2_state_t *server_state = get_state_from_conn(s->conn_server);
uint32_t wrong_magic = 0xD15EA5E;
@@ -411,8 +438,8 @@ static void test_obfs2_wrong_handshake_plength(void *state) { struct test_obfs2_state *s = (struct test_obfs2_state *)state; - obfs2_state_t *client_state = downcast(s->conn_client)->state; - obfs2_state_t *server_state = downcast(s->conn_server)->state; + obfs2_state_t *client_state = get_state_from_conn(s->conn_client); + obfs2_state_t *server_state = get_state_from_conn(s->conn_server);
uchar msg[OBFUSCATE_MAX_PADDING + OBFUSCATE_SEED_LENGTH + 8 + 1]; uint32_t magic = htonl(OBFUSCATE_MAGIC_VALUE);