[tor-commits] [tor/master] prop224: Directory support for v3 descriptor publishing
nickm at torproject.org
nickm at torproject.org
Fri Nov 4 18:48:12 UTC 2016
commit 45a72356cbf085f02d92edcbd9f5a3ed129216cc
Author: David Goulet <dgoulet at torproject.org>
Date: Thu Aug 11 15:21:54 2016 -0400
prop224: Directory support for v3 descriptor publishing
Closes #19205
Signed-off-by: David Goulet <dgoulet at torproject.org>
Signed-off-by: George Kadianakis <desnacked at riseup.net>
---
src/or/directory.c | 99 +++++++++++++++++++++++++++++++++++++++++++++++++++++
src/or/directory.h | 3 ++
src/or/hs_cache.c | 4 +--
src/or/hs_common.h | 2 ++
src/test/test_dir.c | 62 +++++++++++++++++++++++++++++++++
5 files changed, 168 insertions(+), 2 deletions(-)
diff --git a/src/or/directory.c b/src/or/directory.c
index 49efeef..8abdc45 100644
--- a/src/or/directory.c
+++ b/src/or/directory.c
@@ -16,6 +16,7 @@
#include "dirvote.h"
#include "entrynodes.h"
#include "geoip.h"
+#include "hs_cache.h"
#include "hs_common.h"
#include "main.h"
#include "microdesc.h"
@@ -3443,6 +3444,90 @@ handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
return 0;
}
+/* Given the <b>url</b> from a POST request, try to extract the version number
+ * using the provided <b>prefix</b>. The version should be after the prefix and
+ * ending with the seperator "/". For instance:
+ * /tor/hs/3/publish
+ *
+ * On success, <b>end_pos</b> points to the position right after the version
+ * was found. On error, it is set to NULL.
+ *
+ * Return version on success else negative value. */
+STATIC int
+parse_hs_version_from_post(const char *url, const char *prefix,
+ const char **end_pos)
+{
+ int ok;
+ unsigned long version;
+ const char *start;
+ char *end = NULL;
+
+ tor_assert(url);
+ tor_assert(prefix);
+ tor_assert(end_pos);
+
+ /* Check if the prefix does start the url. */
+ if (strcmpstart(url, prefix)) {
+ goto err;
+ }
+ /* Move pointer to the end of the prefix string. */
+ start = url + strlen(prefix);
+ /* Try this to be the HS version and if we are still at the separator, next
+ * will be move to the right value. */
+ version = tor_parse_long(start, 10, 0, INT_MAX, &ok, &end);
+ if (!ok) {
+ goto err;
+ }
+
+ *end_pos = end;
+ return (int) version;
+ err:
+ *end_pos = NULL;
+ return -1;
+}
+
+/* Handle the POST request for a hidden service descripror. The request is in
+ * <b>url</b>, the body of the request is in <b>body</b>. Return 200 on success
+ * else return 400 indicating a bad request. */
+static int
+handle_post_hs_descriptor(const char *url, const char *body)
+{
+ int version;
+ const char *end_pos;
+
+ tor_assert(url);
+ tor_assert(body);
+
+ version = parse_hs_version_from_post(url, "/tor/hs/", &end_pos);
+ if (version < 0) {
+ goto err;
+ }
+
+ /* We have a valid version number, now make sure it's a publish request. Use
+ * the end position just after the version and check for the command. */
+ if (strcmpstart(end_pos, "/publish")) {
+ goto err;
+ }
+
+ switch (version) {
+ case HS_VERSION_THREE:
+ if (hs_cache_store_as_dir(body) < 0) {
+ goto err;
+ }
+ log_info(LD_REND, "Publish request for HS descriptor handled "
+ "successfully.");
+ break;
+ default:
+ /* Unsupported version, return a bad request. */
+ goto err;
+ }
+
+ return 200;
+ err:
+ /* Bad request. */
+ return 400;
+}
+
/** Helper function: called when a dirserver gets a complete HTTP POST
* request. Look for an uploaded server descriptor or rendezvous
* service descriptor. On finding one, process it and write a
@@ -3487,6 +3572,20 @@ directory_handle_command_post(dir_connection_t *conn, const char *headers,
goto done;
}
+ /* Handle HS descriptor publish request. */
+ /* XXX: This should be disabled with a consensus param until we want to
+ * the prop224 be deployed and thus use. */
+ if (connection_dir_is_encrypted(conn) && !strcmpstart(url, "/tor/hs/")) {
+ const char *msg = "HS descriptor stored successfully.";
+ /* We most probably have a publish request for an HS descriptor. */
+ int code = handle_post_hs_descriptor(url, body);
+ if (code != 200) {
+ msg = "Invalid HS descriptor. Rejected.";
+ }
+ write_http_status_line(conn, code, msg);
+ goto done;
+ }
+
if (!authdir_mode(options)) {
/* we just provide cached directories; we don't want to
* receive anything. */
diff --git a/src/or/directory.h b/src/or/directory.h
index f04e7ab..a6c33d7 100644
--- a/src/or/directory.h
+++ b/src/or/directory.h
@@ -160,6 +160,9 @@ STATIC void find_dl_min_and_max_delay(download_status_t *dls,
int *min, int *max);
STATIC int next_random_exponential_delay(int delay, int max_delay);
+STATIC int parse_hs_version_from_post(const char *url, const char *prefix,
+ const char **end_pos);
+
#endif
#endif
diff --git a/src/or/hs_cache.c b/src/or/hs_cache.c
index 40730bd..9b68045 100644
--- a/src/or/hs_cache.c
+++ b/src/or/hs_cache.c
@@ -249,7 +249,7 @@ hs_cache_store_as_dir(const char *desc)
* we are sure that the descriptor's version is supported else the
* decoding would have failed. */
switch (dir_desc->plaintext_data->version) {
- case 3:
+ case HS_VERSION_THREE:
default:
if (cache_store_v3_as_dir(dir_desc) < 0) {
goto err;
@@ -279,7 +279,7 @@ hs_cache_lookup_as_dir(uint32_t version, const char *query,
tor_assert(hs_desc_is_supported_version(version));
switch (version) {
- case 3:
+ case HS_VERSION_THREE:
default:
found = cache_lookup_v3_as_dir(query, desc_out);
break;
diff --git a/src/or/hs_common.h b/src/or/hs_common.h
index a3edf61..824e540 100644
--- a/src/or/hs_common.h
+++ b/src/or/hs_common.h
@@ -14,6 +14,8 @@
/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
* this adds a clearer semantic to the value when used. */
#define HS_VERSION_TWO 2
+/* Version 3 of the protocol (prop224). */
+#define HS_VERSION_THREE 3
void rend_data_free(rend_data_t *data);
rend_data_t *rend_data_dup(const rend_data_t *data);
diff --git a/src/test/test_dir.c b/src/test/test_dir.c
index 51a5eca..4a2538b 100644
--- a/src/test/test_dir.c
+++ b/src/test/test_dir.c
@@ -5345,6 +5345,67 @@ test_dir_find_dl_schedule(void* data)
mock_options = NULL;
}
+static void
+test_dir_post_parsing(void *arg)
+{
+ (void) arg;
+
+ /* Test the version parsing from an HS descriptor publish request. */
+ {
+ const char *end;
+ const char *prefix = "/tor/hs/";
+ int version = parse_hs_version_from_post("/tor/hs//publish", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/a/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/3/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, 3);
+ tt_str_op(end, OP_EQ, "/publish");
+ version = parse_hs_version_from_post("/tor/hs/42/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, 42);
+ tt_str_op(end, OP_EQ, "/publish");
+ version = parse_hs_version_from_post("/tor/hs/18163/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, 18163);
+ tt_str_op(end, OP_EQ, "/publish");
+ version = parse_hs_version_from_post("JUNKJUNKJUNK", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/3/publish", "blah", &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ /* Missing the '/' at the end of the prefix. */
+ version = parse_hs_version_from_post("/tor/hs/3/publish", "/tor/hs", &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/random/blah/tor/hs/3/publish",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ version = parse_hs_version_from_post("/tor/hs/3/publish/random/junk",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, 3);
+ tt_str_op(end, OP_EQ, "/publish/random/junk");
+ version = parse_hs_version_from_post("/tor/hs/-1/publish", prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ /* INT_MAX */
+ version = parse_hs_version_from_post("/tor/hs/2147483647/publish",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, INT_MAX);
+ tt_str_op(end, OP_EQ, "/publish");
+ /* INT_MAX + 1*/
+ version = parse_hs_version_from_post("/tor/hs/2147483648/publish",
+ prefix, &end);
+ tt_int_op(version, OP_EQ, -1);
+ tt_ptr_op(end, OP_EQ, NULL);
+ }
+
+ done:
+ ;
+}
+
#define DIR_LEGACY(name) \
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
@@ -5378,6 +5439,7 @@ struct testcase_t dir_tests[] = {
DIR(fmt_control_ns, 0),
DIR(dirserv_set_routerstatus_testing, 0),
DIR(http_handling, 0),
+ DIR(post_parsing, 0),
DIR(purpose_needs_anonymity, 0),
DIR(fetch_type, 0),
DIR(packages, 0),
More information about the tor-commits
mailing list