mirror of
https://gitlab.torproject.org/tpo/core/tor.git
synced 2024-11-13 06:33:44 +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 "dirvote.h"
|
||||||
#include "entrynodes.h"
|
#include "entrynodes.h"
|
||||||
#include "geoip.h"
|
#include "geoip.h"
|
||||||
|
#include "hs_cache.h"
|
||||||
#include "hs_common.h"
|
#include "hs_common.h"
|
||||||
#include "main.h"
|
#include "main.h"
|
||||||
#include "microdesc.h"
|
#include "microdesc.h"
|
||||||
@ -3443,6 +3444,90 @@ handle_get_robots(dir_connection_t *conn, const get_handler_args_t *args)
|
|||||||
return 0;
|
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
|
/** Helper function: called when a dirserver gets a complete HTTP POST
|
||||||
* request. Look for an uploaded server descriptor or rendezvous
|
* request. Look for an uploaded server descriptor or rendezvous
|
||||||
* service descriptor. On finding one, process it and write a
|
* 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;
|
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)) {
|
if (!authdir_mode(options)) {
|
||||||
/* we just provide cached directories; we don't want to
|
/* we just provide cached directories; we don't want to
|
||||||
* receive anything. */
|
* receive anything. */
|
||||||
|
@ -160,6 +160,9 @@ STATIC void find_dl_min_and_max_delay(download_status_t *dls,
|
|||||||
int *min, int *max);
|
int *min, int *max);
|
||||||
STATIC int next_random_exponential_delay(int delay, int max_delay);
|
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
|
||||||
|
|
||||||
#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
|
* we are sure that the descriptor's version is supported else the
|
||||||
* decoding would have failed. */
|
* decoding would have failed. */
|
||||||
switch (dir_desc->plaintext_data->version) {
|
switch (dir_desc->plaintext_data->version) {
|
||||||
case 3:
|
case HS_VERSION_THREE:
|
||||||
default:
|
default:
|
||||||
if (cache_store_v3_as_dir(dir_desc) < 0) {
|
if (cache_store_v3_as_dir(dir_desc) < 0) {
|
||||||
goto err;
|
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));
|
tor_assert(hs_desc_is_supported_version(version));
|
||||||
|
|
||||||
switch (version) {
|
switch (version) {
|
||||||
case 3:
|
case HS_VERSION_THREE:
|
||||||
default:
|
default:
|
||||||
found = cache_lookup_v3_as_dir(query, desc_out);
|
found = cache_lookup_v3_as_dir(query, desc_out);
|
||||||
break;
|
break;
|
||||||
|
@ -14,6 +14,8 @@
|
|||||||
/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
|
/* Protocol version 2. Use this instead of hardcoding "2" in the code base,
|
||||||
* this adds a clearer semantic to the value when used. */
|
* this adds a clearer semantic to the value when used. */
|
||||||
#define HS_VERSION_TWO 2
|
#define HS_VERSION_TWO 2
|
||||||
|
/* Version 3 of the protocol (prop224). */
|
||||||
|
#define HS_VERSION_THREE 3
|
||||||
|
|
||||||
void rend_data_free(rend_data_t *data);
|
void rend_data_free(rend_data_t *data);
|
||||||
rend_data_t *rend_data_dup(const 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;
|
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) \
|
#define DIR_LEGACY(name) \
|
||||||
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
|
{ #name, test_dir_ ## name , TT_FORK, NULL, NULL }
|
||||||
|
|
||||||
@ -5378,6 +5439,7 @@ struct testcase_t dir_tests[] = {
|
|||||||
DIR(fmt_control_ns, 0),
|
DIR(fmt_control_ns, 0),
|
||||||
DIR(dirserv_set_routerstatus_testing, 0),
|
DIR(dirserv_set_routerstatus_testing, 0),
|
||||||
DIR(http_handling, 0),
|
DIR(http_handling, 0),
|
||||||
|
DIR(post_parsing, 0),
|
||||||
DIR(purpose_needs_anonymity, 0),
|
DIR(purpose_needs_anonymity, 0),
|
||||||
DIR(fetch_type, 0),
|
DIR(fetch_type, 0),
|
||||||
DIR(packages, 0),
|
DIR(packages, 0),
|
||||||
|
Loading…
Reference in New Issue
Block a user