mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-10 21:23:58 +01:00
prop224: Directory support for v3 descriptor publishing
Closes #19205 Signed-off-by: David Goulet <dgoulet@torproject.org> Signed-off-by: George Kadianakis <desnacked@riseup.net>
This commit is contained in:
parent
1aeaba4906
commit
45a72356cb
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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),
|
||||
|
Loading…
Reference in New Issue
Block a user