[tor-commits] [obfsproxy/master] Dump the silly get_other_conn() hack; use configurable circuits.

nickm at torproject.org nickm at torproject.org
Fri Sep 9 17:08:59 UTC 2011


commit 3d85a235c6a6729eeac92413c2fcb982d4578a57
Author: George Kadianakis <desnacked at 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);





More information about the tor-commits mailing list