[tor-commits] [obfsproxy/master] Implements the protocol side of the new CLI.

nickm at torproject.org nickm at torproject.org
Thu Jun 9 21:05:16 UTC 2011


commit 67a106ad3bbafe83f1917d8060a1c78bf6d43ff6
Author: George Kadianakis <desnacked at gmail.com>
Date:   Sun May 29 04:04:32 2011 +0200

    Implements the protocol side of the new CLI.
---
 src/network.c         |   60 ++++++----------------
 src/network.h         |   14 +++--
 src/protocol.c        |   29 ++++++-----
 src/protocol.h        |   37 ++++++++------
 src/protocols/dummy.c |   70 ++++++++++++++++++++++++-
 src/protocols/dummy.h |    5 +-
 src/protocols/obfs2.c |  135 ++++++++++++++++++++++++++++++++++++++++++++++---
 src/protocols/obfs2.h |    5 +-
 src/socks.h           |    1 -
 9 files changed, 262 insertions(+), 94 deletions(-)

diff --git a/src/network.c b/src/network.c
index cfdd398..1c4b853 100644
--- a/src/network.c
+++ b/src/network.c
@@ -16,20 +16,11 @@
 #include <stdlib.h>
 #include <string.h>
 
-#include <event2/buffer.h>
-#include <event2/bufferevent.h>
-#include <event2/listener.h>
-#include <event2/event.h>
-
 #include <errno.h>
 #include <event2/util.h>
 
 struct listener_t {
   struct evconnlistener *listener;
-  struct sockaddr_storage target_address;
-  int target_address_len;
-  int mode;
-  int proto; /* Protocol that this listener can speak. */
   protocol_params_t *proto_params;
 };
 
@@ -49,46 +40,29 @@ static void output_event_cb(struct bufferevent *bev, short what, void *arg);
 
 listener_t *
 listener_new(struct event_base *base,
-             int mode, int protocol,
-             const struct sockaddr *on_address, int on_address_len,
-             const struct sockaddr *target_address, int target_address_len,
-             const char *shared_secret, size_t shared_secret_len)
+             int n_options, char **options)
 {
   const unsigned flags =
     LEV_OPT_CLOSE_ON_FREE|LEV_OPT_CLOSE_ON_EXEC|LEV_OPT_REUSEABLE;
-  listener_t *lsn = calloc(1, sizeof(listener_t));
 
-  assert(mode == LSN_SIMPLE_CLIENT || mode == LSN_SIMPLE_SERVER ||
-         mode == LSN_SOCKS_CLIENT);
-
-  if (set_up_protocol(protocol)<0) {
-    printf("This is just terrible. We can't even set up a protocol! Exiting.\n");
-    exit(1);
-  }
-
-  lsn->proto = protocol;
-  lsn->mode = mode;
+  listener_t *lsn = calloc(1, sizeof(listener_t));
+  if (!lsn)
+    return NULL;
 
   protocol_params_t *proto_params = calloc(1, sizeof(protocol_params_t));
-  proto_params->is_initiator = mode != LSN_SIMPLE_SERVER;
-  proto_params->shared_secret = shared_secret; 
-  proto_params->shared_secret_len = shared_secret_len;
-
   lsn->proto_params = proto_params;
-
-  if (target_address) {
-    assert(target_address_len <= sizeof(struct sockaddr_storage));
-    memcpy(&lsn->target_address, target_address, target_address_len);
-    lsn->target_address_len = target_address_len;
-  } else {
-    assert(lsn->mode == LSN_SOCKS_CLIENT);
+  
+  if (set_up_protocol(n_options,options,lsn->proto_params)<0) {
+    listener_free(lsn);
+    return NULL;
   }
 
   lsn->listener = evconnlistener_new_bind(base, simple_listener_cb, lsn,
                                           flags,
                                           -1,
-                                          on_address,
-                                          on_address_len);
+                                          &lsn->proto_params->on_address,
+                                          lsn->proto_params->on_address_len);
+
   if (!lsn->listener) {
     listener_free(lsn);
     return NULL;
@@ -101,8 +75,9 @@ static void
 protocol_params_free(protocol_params_t *params)
 {
   assert(params);
+
   if (params->shared_secret)
-    free(&params->shared_secret);
+    free(params->shared_secret);
   free(params);
 }
 
@@ -129,10 +104,9 @@ simple_listener_cb(struct evconnlistener *evcl,
 
   dbg(("Got a connection\n"));
 
-  conn->mode = lsn->mode;
+  conn->mode = lsn->proto_params->mode;
 
-  conn->proto = proto_new(lsn->proto,
-                          lsn->proto_params);
+  conn->proto = proto_new(lsn->proto_params);
   if (!conn->proto) {
     printf("Creation of protocol object failed! Closing connection.\n");
     goto err;
@@ -194,8 +168,8 @@ simple_listener_cb(struct evconnlistener *evcl,
   if (conn->mode == LSN_SIMPLE_SERVER || conn->mode == LSN_SIMPLE_CLIENT) {
     /* Launch the connect attempt. */
     if (bufferevent_socket_connect(conn->output,
-                                   (struct sockaddr *) &lsn->target_address,
-                                   lsn->target_address_len)<0)
+                                   (struct sockaddr*)&lsn->proto_params->target_address,
+                                   lsn->proto_params->target_address_len)<0)
       goto err;
 
     bufferevent_enable(conn->output, EV_READ|EV_WRITE);
diff --git a/src/network.h b/src/network.h
index 619e45f..5537680 100644
--- a/src/network.h
+++ b/src/network.h
@@ -10,6 +10,12 @@
 
 #include <stdlib.h>
 
+#include <event2/buffer.h>
+#include <event2/bufferevent.h>
+#include <event2/listener.h>
+#include <event2/event.h>
+
+
 typedef struct listener_t *listener;
 
 struct sockaddr;
@@ -23,12 +29,8 @@ struct socks_state_t;
 typedef struct listener_t listener_t;
 struct addrinfo;
 
-listener_t *listener_new(
-                         struct event_base *base,
-                         int mode, int protocol,
-                         const struct sockaddr *on_address, int on_address_len,
-                         const struct sockaddr *target_address, int target_address_len,
-                         const char *shared_secret, size_t shared_secret_len);
+listener_t *listener_new(struct event_base *base,
+                         int n_options, char **options);
 void listener_free(listener_t *listener);
 
 #ifdef NETWORK_PRIVATE
diff --git a/src/protocol.c b/src/protocol.c
index 8fff6a3..ce96f86 100644
--- a/src/protocol.c
+++ b/src/protocol.c
@@ -1,6 +1,7 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <assert.h>
+#include <string.h>
 
 #include "protocol.h"
 #include "network.h"
@@ -13,15 +14,18 @@
    It's called once in the runtime of the program for each proto.
 */
 int
-set_up_protocol(int protocol) {
-  if (protocol == OBFS2_PROTOCOL)
-    obfs2_init();
-  else if (protocol == DUMMY_PROTOCOL)
-    dummy_init();
+set_up_protocol(int n_options, char **options, 
+                struct protocol_params_t *params)
+{
+  char **name = options;
+  while (!strncmp(*name,"--",2))
+         name++;
+  if (!strcmp(*name,"dummy"))
+    return dummy_init(n_options, options, params);
+  else if (!strcmp(*name,"obfs2"))
+    return obfs2_init(n_options, options, params);
   else
     return -1;
-
-  return 1;
 }
 
 /**
@@ -31,7 +35,7 @@ set_up_protocol(int protocol) {
    Return the protocol_t if successful, NULL otherwise.
 */
 struct protocol_t *
-proto_new(int protocol, protocol_params_t *params) {
+proto_new(protocol_params_t *params) {
   struct protocol_t *proto = calloc(1, sizeof(struct protocol_t));
   if (!proto)
     return NULL;
@@ -40,11 +44,9 @@ proto_new(int protocol, protocol_params_t *params) {
   if (!proto->vtable)
     return NULL;
 
-  if (protocol == OBFS2_PROTOCOL) {
-    proto->proto = protocol;
+  if (params->proto == OBFS2_PROTOCOL) {
     proto->state = obfs2_new(proto, params);
-  } else if (protocol == DUMMY_PROTOCOL) {
-    proto->proto = protocol;
+  } else if (params->proto == DUMMY_PROTOCOL) {
     proto->state = dummy_new(proto, NULL);
   }
 
@@ -81,7 +83,8 @@ proto_recv(struct protocol_t *proto, void *source, void *dest) {
     return -1;
 }
 
-void proto_destroy(struct protocol_t *proto) {
+void 
+proto_destroy(struct protocol_t *proto) {
   assert(proto);
   assert(proto->state);
 
diff --git a/src/protocol.h b/src/protocol.h
index e4c3e0f..646bf7c 100644
--- a/src/protocol.h
+++ b/src/protocol.h
@@ -1,3 +1,5 @@
+#include <event2/buffer.h>
+
 #ifndef PROTOCOL_H
 #define PROTOCOL_H
 
@@ -5,6 +7,7 @@
 #define OBFS2_PROTOCOL      1
 
 struct evbuffer;
+struct listener_t;
 
 /**
   This struct defines parameters of the protocol per-listener basis.
@@ -15,15 +18,17 @@ struct evbuffer;
 */
 typedef struct protocol_params_t {
   int is_initiator;
-  
-  const char *shared_secret;
+  struct sockaddr_storage target_address;
+  int target_address_len;
+  struct sockaddr on_address;
+  int on_address_len;
+  int mode;
+  int proto; /* Protocol that this listener can speak. */
+  char *shared_secret;
   size_t shared_secret_len;
 } protocol_params_t;
 
 struct protocol_t {
-  /* protocol */
-  int proto;
-
   /* protocol vtable */
   struct protocol_vtable *vtable;
   
@@ -39,17 +44,25 @@ struct protocol_t {
   */
   void *state;
 };
+int set_up_protocol(int n_options, char **options, 
+                    struct protocol_params_t *params);
+struct protocol_t *proto_new(struct protocol_params_t *params);
+void proto_destroy(struct protocol_t *proto);
+int proto_handshake(struct protocol_t *proto, void *buf);
+int proto_send(struct protocol_t *proto, void *source, void *dest);
+int proto_recv(struct protocol_t *proto, void *source, void *dest);
 
 
 typedef struct protocol_vtable {
   /* Initialization function: Fills in the protocol vtable. */
-  int (*init)(struct protocol_t *self);
+  int (*init)(int n_options, char **options, 
+              struct protocol_params_t *params);
   /* Destructor: Destroys the protocol state.  */
   void (*destroy)(void *state);
 
   /* Constructor: Creates a protocol object. */
-  void *(*create)(struct protocol_t *proto_struct,
-                  protocol_params_t *parameters);
+  void *(*create)(struct protocol_t *proto_params, 
+                  struct protocol_params_t *parameters);
 
   /* does handshake. Not all protocols have a handshake. */
   int (*handshake)(void *state,
@@ -67,12 +80,4 @@ typedef struct protocol_vtable {
 
 } protocol_vtable;
 
-int set_up_protocol(int protocol);
-struct protocol_t *proto_new(int protocol,
-                             protocol_params_t *params);
-void proto_destroy(struct protocol_t *proto);
-int proto_handshake(struct protocol_t *proto, void *buf);
-int proto_send(struct protocol_t *proto, void *source, void *dest);
-int proto_recv(struct protocol_t *proto, void *source, void *dest);
-
 #endif
diff --git a/src/protocols/dummy.c b/src/protocols/dummy.c
index 482c927..2a24b56 100644
--- a/src/protocols/dummy.c
+++ b/src/protocols/dummy.c
@@ -9,6 +9,7 @@
 #include <event2/buffer.h>
 
 #include "dummy.h"
+#include "../network.h"
 #include "../util.h"
 #include "../protocol.h"
 
@@ -17,11 +18,55 @@ static int dummy_send(void *nothing,
                struct evbuffer *source, struct evbuffer *dest);
 static int dummy_recv(void *nothing, struct evbuffer *source,
                struct evbuffer *dest);
+static void usage(void);
 
 static protocol_vtable *vtable=NULL;
 
+/**
+   This function sets up the protocol and populates 'listner'
+   according to 'options'.
+
+   'options' is an array like this:
+   {"dummy","socks","127.0.0.1:6666"}
+*/   
 int
-dummy_init(void) {
+dummy_init(int n_options, char **options, 
+           struct protocol_params_t *params)
+{
+  struct sockaddr_storage ss_listen;
+  int sl_listen;
+  const char* defport;
+  
+  if (n_options != 3)
+    goto err;
+
+  assert(!strcmp(options[0],"dummy"));
+  params->proto = DUMMY_PROTOCOL;
+
+  if (!strcmp(options[1], "client")) {
+    defport = "48988"; /* bf5c */
+    params->mode = LSN_SIMPLE_CLIENT;
+  } else if (!strcmp(options[1], "socks")) {
+    defport = "23548"; /* 5bf5 */
+    params->mode = LSN_SOCKS_CLIENT;
+  } else if (!strcmp(options[1], "server")) {
+    defport = "11253"; /* 2bf5 */
+    params->mode = LSN_SIMPLE_SERVER;
+  } else
+    goto err;
+
+  if (resolve_address_port(options[2], 1, 1, 
+                           &ss_listen, &sl_listen, defport) < 0) {
+    printf("addr\n");
+    goto err;
+  }
+  assert(sl_listen <= sizeof(struct sockaddr_storage));
+  struct sockaddr *sa_listen=NULL;
+  sa_listen = (struct sockaddr *)&ss_listen;
+  memcpy(&params->on_address, sa_listen, sl_listen);
+  params->on_address_len = sl_listen;
+  
+  /* XXX memleak. */
   vtable = calloc(1, sizeof(protocol_vtable));
   if (!vtable)
     return -1;
@@ -33,11 +78,30 @@ dummy_init(void) {
   vtable->recv = dummy_recv;
 
   return 1;
+
+ err:
+  usage();
+  return -1;
 }
 
+static void
+usage(void)
+{
+  printf("Great... You can't even form a dummy protocol line:\n"
+         "dummy syntax:\n"
+         "\tdummy dummy_opts\n"
+         "\t'dummy_opts':\n"
+         "\t\tmode ~ server|client|socks\n"
+         "\t\tlisten address ~ host:port\n"
+         "Example:\n"
+         "\tobfsproxy dummy socks 127.0.0.1:5000\n");
+}
+    
+
+
 void *
-dummy_new(struct protocol_t *proto_struct, 
-          protocol_params_t *params)
+dummy_new(struct protocol_t *proto_struct,
+          struct protocol_params_t *params)
 {
   proto_struct->vtable = vtable;
 
diff --git a/src/protocols/dummy.h b/src/protocols/dummy.h
index 1ee0e02..a00248f 100644
--- a/src/protocols/dummy.h
+++ b/src/protocols/dummy.h
@@ -5,7 +5,8 @@ struct protocol_t;
 struct evbuffer;
 struct protocol_params_t;
 
-int dummy_init(void);
-void *dummy_new(struct protocol_t *proto_struct, struct protocol_params_t *params);
+int dummy_init(int n_options, char **options, struct protocol_params_t *lsn);
+void *dummy_new(struct protocol_t *proto_struct,
+                struct protocol_params_t *params);
 
 #endif
diff --git a/src/protocols/obfs2.c b/src/protocols/obfs2.c
index a8f9155..41a97aa 100644
--- a/src/protocols/obfs2.c
+++ b/src/protocols/obfs2.c
@@ -17,6 +17,7 @@
 
 #include "obfs2_crypt.h"
 #include "obfs2.h"
+#include "../network.h"
 #include "../util.h"
 #include "../protocol.h"
 
@@ -30,6 +31,9 @@ static void *obfs2_state_new(protocol_params_t *params);
 static int obfs2_state_set_shared_secret(void *s,
                                          const char *secret,
                                          size_t secretlen);
+static int set_up_vtable(void);
+static void usage(void);
+
 
 static protocol_vtable *vtable=NULL;
 
@@ -38,22 +42,136 @@ static protocol_vtable *vtable=NULL;
    Returns 0 on success, -1 on fail.
 */
 int
-obfs2_init(void) {
+obfs2_init(int n_options, char **options, 
+           struct protocol_params_t *params)
+{
+  struct sockaddr_storage ss_listen;
+  int sl_listen;
+  int got_dest=0;
+  int got_ss=0;
+  const char* defport;
+
+  if ((n_options < 3) || (n_options > 5)) {
+    printf("wrong options number: %d\n", n_options);
+    goto err;
+  }
+
+  assert(!strcmp(*options,"obfs2"));
+  params->proto = OBFS2_PROTOCOL;
+  options++;
+
+  /* Now parse the optional arguments */
+  while (!strncmp(*options,"--",2)) {
+      if (!strncmp(*options,"--dest=",7)) {
+        if (got_dest)
+          goto err;
+        struct sockaddr_storage ss_target;
+        struct sockaddr *sa_target=NULL;
+        int sl_target=0;
+        if (resolve_address_port(*options+7, 1, 0, 
+                                 &ss_target, &sl_target, NULL) < 0)
+          goto err;
+        assert(sl_target <= sizeof(struct sockaddr_storage));
+        sa_target = (struct sockaddr *)&ss_target;
+        memcpy(&params->target_address, sa_target, sl_target);
+        params->target_address_len = sl_target;
+        got_dest=1;
+      } else if (!strncmp(*options,"--shared-secret=",16)) {
+        if (got_ss)
+          goto err;
+        /* this is freed in protocol_params_free() */
+        params->shared_secret = strdup(*options+16);
+        params->shared_secret_len = strlen(*options+16);
+        got_ss=1;
+      } else {
+        printf("Unknown argument.\n");
+        goto err;
+      }
+      options++;
+    }
+
+    if (!strcmp(*options, "client")) {
+      defport = "48988"; /* bf5c */
+      params->mode = LSN_SIMPLE_CLIENT;
+    } else if (!strcmp(*options, "socks")) {
+      defport = "23548"; /* 5bf5 */
+      params->mode = LSN_SOCKS_CLIENT;
+    } else if (!strcmp(*options, "server")) {
+      defport = "11253"; /* 2bf5 */
+      params->mode = LSN_SIMPLE_SERVER;
+    } else {
+      printf("only client/socks/server modes supported.\n");
+      goto err;
+    }
+    options++;
+
+    params->is_initiator = (params->mode != LSN_SIMPLE_SERVER);
+
+    if (resolve_address_port(*options, 1, 1, 
+                             &ss_listen, &sl_listen, defport) < 0)
+      goto err;
+    assert(sl_listen <= sizeof(struct sockaddr_storage));
+    struct sockaddr *sa_listen=NULL;
+    sa_listen = (struct sockaddr *)&ss_listen;
+    memcpy(&params->on_address, sa_listen, sl_listen);
+    params->on_address_len = sl_listen;
+
+    /* Validate option selection. */
+    if (got_dest && (params->mode == LSN_SOCKS_CLIENT)) {
+      printf("You can't be on socks mode and have --dest.\n");
+      goto err;
+    }
+
+    if (!got_dest && (params->mode != LSN_SOCKS_CLIENT)) {
+      printf("client/server mode needs --dest.\n");
+      goto err;
+    }
+  
+    if (!set_up_vtable())
+      return -1;
+
+    if (initialize_crypto() < 0) {
+      fprintf(stderr, "Can't initialize crypto; failing\n");
+      return -1;
+    }
+
+    return 1;
+ err:
+    usage();
+    return -1;
+}
+
+static void
+usage(void)
+{
+  printf("You failed at creating an understandable command.\n"
+         "obfs2 syntax:\n"
+         "\tobfs2 [obfs2_args] obfs2_opts\n"
+         "\t'obfs2_opts':\n"
+         "\t\tmode ~ server|client|socks\n"
+         "\t\tlisten address ~ host:port\n"
+         "\t'obfs2_args':\n"
+         "\t\tDestination Address ~ --dest=host:port\n"
+         "\t\tShared Secret ~ --shared-secret=<secret>\n"
+         "\tExample:\n"
+         "\tobfsproxy --dest=127.0.0.1:666 --shared-secret=himitsu "
+         "\tobfs2 server 127.0.0.1:1026\n");
+}
+
+static int
+set_up_vtable(void)
+{
+  /* XXX memleak. */
   vtable = calloc(1, sizeof(protocol_vtable));
   if (!vtable)
-    return -1;
+    return 0;
   
   vtable->destroy = obfs2_state_free;
   vtable->create = obfs2_new;
   vtable->handshake = obfs2_send_initial_message;
   vtable->send = obfs2_send;
   vtable->recv = obfs2_recv;
-
-  if (initialize_crypto() < 0) {
-    fprintf(stderr, "Can't initialize crypto; failing\n");
-    return -1;
-  }
-
+  
   return 1;
 }
 
@@ -205,6 +323,7 @@ obfs2_state_set_shared_secret(void *s, const char *secret,
   uchar buf[SHARED_SECRET_LENGTH];
   obfs2_state_t *state = s;
 
+  /* ASN we must say in spec that we hash command line shared secret. */
   digest_t *c = digest_new();
   digest_update(c, (uchar*)secret, secretlen);
   digest_getdigest(c, buf, sizeof(buf));
diff --git a/src/protocols/obfs2.h b/src/protocols/obfs2.h
index 0d70144..7747330 100644
--- a/src/protocols/obfs2.h
+++ b/src/protocols/obfs2.h
@@ -14,11 +14,12 @@ typedef struct obfs2_state_t obfs2_state_t;
 struct evbuffer;
 struct protocol_t;
 struct protocol_params_t;
+struct listener_t;
 
 #define SHARED_SECRET_LENGTH SHA256_LENGTH
 
-int obfs2_init(void);
-void *obfs2_new(struct protocol_t *proto_struct, 
+int obfs2_init(int n_options, char **options, struct protocol_params_t *params);
+void *obfs2_new(struct protocol_t *proto_struct,
                 struct protocol_params_t *params);
 
 
diff --git a/src/socks.h b/src/socks.h
index 7b35cb5..20fd610 100644
--- a/src/socks.h
+++ b/src/socks.h
@@ -102,7 +102,6 @@ int socks5_send_reply(struct evbuffer *reply_dest, socks_state_t *state,
                       int status);
 enum req_status socks5_handle_request(struct evbuffer *source, struct parsereq *parsereq);
 
-
 int socks4_read_request(struct evbuffer *source, socks_state_t *state);
 int socks4_send_reply(struct evbuffer *dest, 
                       socks_state_t *state, int status);





More information about the tor-commits mailing list