[tor-commits] [tor/master] Add support for STATUS messages from Pluggable Transports.

nickm at torproject.org nickm at torproject.org
Thu Dec 20 21:42:40 UTC 2018


commit 4efe4cc2f918ce45075b010d2cdc09ec7791ac6b
Author: Alexander Færøy <ahf at torproject.org>
Date:   Thu Dec 20 03:55:02 2018 +0100

    Add support for STATUS messages from Pluggable Transports.
    
    This patch adds support for the new STATUS message that PT's can emit
    from their standard out. The STATUS message uses the `config_line_t` K/V
    format that was recently added in Tor.
    
    See: https://bugs.torproject.org/28846
---
 src/feature/client/transports.c | 60 ++++++++++++++++++++++++++++++++++++++---
 src/feature/client/transports.h |  1 +
 src/feature/control/control.c   | 10 +++++++
 src/feature/control/control.h   |  4 ++-
 src/test/test_pt.c              | 21 +++++++++++++++
 5 files changed, 92 insertions(+), 4 deletions(-)

diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 6a3479a47..45dbd0c88 100644
--- a/src/feature/client/transports.c
+++ b/src/feature/client/transports.c
@@ -130,6 +130,7 @@ static void parse_method_error(const char *line, int is_server_method);
 #define PROTO_PROXY_DONE "PROXY DONE"
 #define PROTO_PROXY_ERROR "PROXY-ERROR"
 #define PROTO_LOG "LOG"
+#define PROTO_STATUS "STATUS"
 
 /** The first and only supported - at the moment - configuration
     protocol version. */
@@ -912,12 +913,16 @@ handle_proxy_line(const char *line, managed_proxy_t *mp)
     parse_proxy_error(line);
     goto err;
 
-    /* We check for the additional " " after the PROTO_LOG string to make sure
-     * we can later extend this big if/else-if table with something that begins
-     * with "LOG" without having to get the order right. */
+    /* We check for the additional " " after the PROTO_LOG * PROTO_STATUS
+     * string to make sure we can later extend this big if/else-if table with
+     * something that begins with "LOG" without having to get the order right.
+     * */
   } else if (!strcmpstart(line, PROTO_LOG " ")) {
     parse_log_line(line, mp);
     return;
+  } else if (!strcmpstart(line, PROTO_STATUS " ")) {
+    parse_status_line(line, mp);
+    return;
   }
 
   log_notice(LD_GENERAL, "Unknown line received by managed proxy (%s).", line);
@@ -1205,6 +1210,55 @@ parse_log_line(const char *line, managed_proxy_t *mp)
   tor_free(log_message);
 }
 
+/** Parses a STATUS <b>line</b> and emit control events accordingly. */
+STATIC void
+parse_status_line(const char *line, managed_proxy_t *mp)
+{
+  tor_assert(line);
+  tor_assert(mp);
+
+  config_line_t *values = NULL;
+  char *status_message = NULL;
+
+  if (strlen(line) < (strlen(PROTO_STATUS) + 1)) {
+    log_warn(LD_PT, "Managed proxy sent us a %s line "
+                    "with missing argument.", PROTO_STATUS);
+    goto done;
+  }
+
+  const char *data = line + strlen(PROTO_STATUS) + 1;
+
+  values = kvline_parse(data, KV_QUOTED);
+
+  if (! values) {
+    log_warn(LD_PT, "Managed proxy \"%s\" wrote an invalid "
+             "STATUS message: %s", mp->argv[0], data);
+    goto done;
+  }
+
+  /* We check if we received the TYPE parameter, which is the only *required*
+   * value. */
+  const config_line_t *type = config_line_find(values, "TYPE");
+
+  if (! type) {
+    log_warn(LD_PT, "Managed proxy \"%s\" wrote a STATUS line without "
+                    "TYPE: %s", mp->argv[0], data);
+    goto done;
+  }
+
+  /* Prepend the PT name. */
+  config_line_prepend(&values, "PT", mp->argv[0]);
+  status_message = kvline_encode(values, KV_QUOTED);
+
+  /* We have checked that TYPE is there, we can now emit the STATUS event via
+   * the control port. */
+  control_event_pt_status(status_message);
+
+ done:
+  config_free_lines(values);
+  tor_free(status_message);
+}
+
 /** Return a newly allocated string that tor should place in
  * TOR_PT_SERVER_TRANSPORT_OPTIONS while configuring the server
  * manged proxy in <b>mp</b>. Return NULL if no such options are found. */
diff --git a/src/feature/client/transports.h b/src/feature/client/transports.h
index b8d1bb008..1a910ae82 100644
--- a/src/feature/client/transports.h
+++ b/src/feature/client/transports.h
@@ -129,6 +129,7 @@ STATIC void parse_env_error(const char *line);
 STATIC void parse_proxy_error(const char *line);
 STATIC void handle_proxy_line(const char *line, managed_proxy_t *mp);
 STATIC void parse_log_line(const char *line, managed_proxy_t *mp);
+STATIC void parse_status_line(const char *line, managed_proxy_t *mp);
 STATIC char *get_transport_options_for_server_proxy(const managed_proxy_t *mp);
 
 STATIC void managed_proxy_destroy(managed_proxy_t *mp,
diff --git a/src/feature/control/control.c b/src/feature/control/control.c
index 849f11707..4ef550c91 100644
--- a/src/feature/control/control.c
+++ b/src/feature/control/control.c
@@ -7043,6 +7043,16 @@ control_event_pt_log(const char *log)
                      log);
 }
 
+/** A pluggable transport has emitted a STATUS message found in
+ * <b>status</b>. */
+void
+control_event_pt_status(const char *status)
+{
+  send_control_event(EVENT_PT_STATUS,
+                     "650 PT_STATUS %s\r\n",
+                     status);
+}
+
 /** Convert rendezvous auth type to string for HS_DESC control events
  */
 const char *
diff --git a/src/feature/control/control.h b/src/feature/control/control.h
index b3a270767..d78ce4d87 100644
--- a/src/feature/control/control.h
+++ b/src/feature/control/control.h
@@ -208,6 +208,7 @@ void control_event_transport_launched(const char *mode,
                                       const char *transport_name,
                                       tor_addr_t *addr, uint16_t port);
 void control_event_pt_log(const char *log);
+void control_event_pt_status(const char *status);
 const char *rend_auth_type_to_string(rend_auth_type_t auth_type);
 MOCK_DECL(const char *, node_describe_longname_by_id,(const char *id_digest));
 void control_event_hs_descriptor_requested(const char *onion_address,
@@ -297,7 +298,8 @@ void control_free_all(void);
 #define EVENT_HS_DESC_CONTENT         0x0022
 #define EVENT_NETWORK_LIVENESS        0x0023
 #define EVENT_PT_LOG                  0x0024
-#define EVENT_MAX_                    0x0024
+#define EVENT_PT_STATUS               0x0025
+#define EVENT_MAX_                    0x0025
 
 /* sizeof(control_connection_t.event_mask) in bits, currently a uint64_t */
 #define EVENT_CAPACITY_               0x0040
diff --git a/src/test/test_pt.c b/src/test/test_pt.c
index 271d74f26..8de687c86 100644
--- a/src/test/test_pt.c
+++ b/src/test/test_pt.c
@@ -316,6 +316,10 @@ process_read_stdout_replacement(process_t *process, buf_t *buffer)
     buf_add_string(buffer, "LOG SEVERITY=notice MESSAGE=\"notice msg\"\n");
     buf_add_string(buffer, "LOG SEVERITY=info MESSAGE=\"info msg\"\n");
     buf_add_string(buffer, "LOG SEVERITY=debug MESSAGE=\"debug msg\"\n");
+  } else if (times_called <= 8) {
+    buf_add_string(buffer, "STATUS TYPE=a K_1=a K_2=b K_3=\"foo bar\"\n");
+    buf_add_string(buffer, "STATUS TYPE=b K_1=a K_2=b K_3=\"foo bar\"\n");
+    buf_add_string(buffer, "STATUS TYPE=c K_1=a K_2=b K_3=\"foo bar\"\n");
   }
 
   return (int)buf_datalen(buffer);
@@ -440,6 +444,23 @@ test_pt_configure_proxy(void *arg)
             "650 PT_LOG PT=<testcase> SEVERITY=debug "
             "MESSAGE=\"debug msg\"\r\n");
 
+  /* Get the STATUS messages out. */
+  process_notify_event_stdout(mp->process);
+
+  tt_int_op(controlevent_n, OP_EQ, 13);
+  tt_int_op(controlevent_event, OP_EQ, EVENT_PT_STATUS);
+  tt_int_op(smartlist_len(controlevent_msgs), OP_EQ, 13);
+
+  tt_str_op(smartlist_get(controlevent_msgs, 10), OP_EQ,
+            "650 PT_STATUS "
+            "PT=<testcase> TYPE=a K_1=a K_2=b K_3=\"foo bar\"\r\n");
+  tt_str_op(smartlist_get(controlevent_msgs, 11), OP_EQ,
+            "650 PT_STATUS "
+            "PT=<testcase> TYPE=b K_1=a K_2=b K_3=\"foo bar\"\r\n");
+  tt_str_op(smartlist_get(controlevent_msgs, 12), OP_EQ,
+            "650 PT_STATUS "
+            "PT=<testcase> TYPE=c K_1=a K_2=b K_3=\"foo bar\"\r\n");
+
   { /* check that the transport info were saved properly in the tor state */
     config_line_t *transport_in_state = NULL;
     smartlist_t *transport_info_sl = smartlist_new();





More information about the tor-commits mailing list