summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAlexander Færøy <ahf@torproject.org>2018-12-20 03:55:02 +0100
committerAlexander Færøy <ahf@torproject.org>2018-12-20 03:55:02 +0100
commit4efe4cc2f918ce45075b010d2cdc09ec7791ac6b (patch)
treecde7a4670aa361d00aa3a6c251ed19b572d018d5
parent426c52b377057dc5f4428c664ee56ca77d648c9e (diff)
downloadtor-4efe4cc2f918ce45075b010d2cdc09ec7791ac6b.tar.gz
tor-4efe4cc2f918ce45075b010d2cdc09ec7791ac6b.zip
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
-rw-r--r--src/feature/client/transports.c60
-rw-r--r--src/feature/client/transports.h1
-rw-r--r--src/feature/control/control.c10
-rw-r--r--src/feature/control/control.h4
-rw-r--r--src/test/test_pt.c21
5 files changed, 92 insertions, 4 deletions
diff --git a/src/feature/client/transports.c b/src/feature/client/transports.c
index 6a3479a470..45dbd0c888 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 b8d1bb0081..1a910ae82c 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 849f11707e..4ef550c919 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 b3a2707672..d78ce4d87c 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 271d74f26a..8de687c866 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();