prop224: Directory function to upload descriptor

This commit adds a directory command function to make an upload directory
request for a service descriptor.

It is not used yet, just the groundwork.

Signed-off-by: David Goulet <dgoulet@torproject.org>
This commit is contained in:
David Goulet 2017-04-19 14:36:53 -04:00 committed by Nick Mathewson
parent 0bcc9ad58d
commit bce0c6caad
3 changed files with 103 additions and 6 deletions

View file

@ -186,6 +186,8 @@ purpose_needs_anonymity(uint8_t dir_purpose, uint8_t router_purpose,
case DIR_PURPOSE_HAS_FETCHED_RENDDESC_V2:
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
case DIR_PURPOSE_FETCH_RENDDESC_V2:
case DIR_PURPOSE_FETCH_HSDESC:
case DIR_PURPOSE_UPLOAD_HSDESC:
return 1;
case DIR_PURPOSE_SERVER:
default:
@ -244,6 +246,10 @@ dir_conn_purpose_to_string(int purpose)
return "hidden-service v2 descriptor fetch";
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
return "hidden-service v2 descriptor upload";
case DIR_PURPOSE_FETCH_HSDESC:
return "hidden-service descriptor fetch";
case DIR_PURPOSE_UPLOAD_HSDESC:
return "hidden-service descriptor upload";
case DIR_PURPOSE_FETCH_MICRODESC:
return "microdescriptor fetch";
}
@ -1034,11 +1040,12 @@ struct directory_request_t {
size_t payload_len;
/** Value to send in an if-modified-since header, or 0 for none. */
time_t if_modified_since;
/** Hidden-service-specific information */
/** Hidden-service-specific information v2. */
const rend_data_t *rend_query;
/** Extra headers to append to the request */
config_line_t *additional_headers;
/** */
/** Hidden-service-specific information for v3+. */
const hs_ident_dir_conn_t *hs_ident;
/** Used internally to directory.c: gets informed when the attempt to
* connect to the directory succeeds or fails, if that attempt bears on the
* directory's usability as a directory guard. */
@ -1268,6 +1275,21 @@ directory_request_set_rend_query(directory_request_t *req,
}
req->rend_query = query;
}
/**
* Set an object containing HS connection identifier to be associated with
* this request. Note that only an alias to <b>ident</b> is stored, so the
* <b>ident</b> object must outlive the request.
*/
void
directory_request_set_hs_ident(directory_request_t *req,
const hs_ident_dir_conn_t *ident)
{
if (ident) {
tor_assert(req->dir_purpose == DIR_PURPOSE_FETCH_HSDESC ||
req->dir_purpose == DIR_PURPOSE_UPLOAD_HSDESC);
}
req->hs_ident = ident;
}
/** Set a static circuit_guard_state_t object to affliate with the request in
* <b>req</b>. This object will receive notification when the attempt to
* connect to the guard either succeeds or fails. */
@ -1389,6 +1411,7 @@ directory_initiate_request,(directory_request_t *request))
const dir_indirection_t indirection = request->indirection;
const char *resource = request->resource;
const rend_data_t *rend_query = request->rend_query;
const hs_ident_dir_conn_t *hs_ident = request->hs_ident;
circuit_guard_state_t *guard_state = request->guard_state;
tor_assert(or_addr_port->port || dir_addr_port->port);
@ -1476,8 +1499,16 @@ directory_initiate_request,(directory_request_t *request))
conn->dirconn_direct = !anonymized_connection;
/* copy rendezvous data, if any */
if (rend_query)
if (rend_query) {
/* We can't have both v2 and v3+ identifier. */
tor_assert_nonfatal(!hs_ident);
conn->rend_data = rend_data_dup(rend_query);
}
if (hs_ident) {
/* We can't have both v2 and v3+ identifier. */
tor_assert_nonfatal(!rend_query);
conn->hs_ident = hs_ident_dir_conn_dup(hs_ident);
}
if (!anonymized_connection && !use_begindir) {
/* then we want to connect to dirport directly */
@ -1835,6 +1866,12 @@ directory_send_command(dir_connection_t *conn,
httpcommand = "POST";
url = tor_strdup("/tor/rendezvous2/publish");
break;
case DIR_PURPOSE_UPLOAD_HSDESC:
tor_assert(resource);
tor_assert(payload);
httpcommand = "POST";
tor_asprintf(&url, "/tor/hs/%s/publish", resource);
break;
default:
tor_assert(0);
return;
@ -2189,6 +2226,8 @@ static int handle_response_fetch_renddesc_v2(dir_connection_t *,
const response_handler_args_t *);
static int handle_response_upload_renddesc_v2(dir_connection_t *,
const response_handler_args_t *);
static int handle_response_upload_hsdesc(dir_connection_t *,
const response_handler_args_t *);
static int
dir_client_decompress_response_body(char **bodyp, size_t *bodylenp,
@ -2489,6 +2528,9 @@ connection_dir_client_reached_eof(dir_connection_t *conn)
case DIR_PURPOSE_UPLOAD_RENDDESC_V2:
rv = handle_response_upload_renddesc_v2(conn, &args);
break;
case DIR_PURPOSE_UPLOAD_HSDESC:
rv = handle_response_upload_hsdesc(conn, &args);
break;
default:
tor_assert_nonfatal_unreached();
rv = -1;
@ -3180,6 +3222,52 @@ handle_response_upload_renddesc_v2(dir_connection_t *conn,
return 0;
}
/**
* Handler function: processes a response to a POST request to upload an
* hidden service descriptor.
**/
static int
handle_response_upload_hsdesc(dir_connection_t *conn,
const response_handler_args_t *args)
{
const int status_code = args->status_code;
const char *reason = args->reason;
tor_assert(conn);
tor_assert(conn->base_.purpose == DIR_PURPOSE_UPLOAD_HSDESC);
log_info(LD_REND, "Uploaded hidden service descriptor (status %d "
"(%s))",
status_code, escaped(reason));
/* For this directory response, it MUST have an hidden service identifier on
* this connection. */
tor_assert(conn->hs_ident);
switch (status_code) {
case 200:
log_info(LD_REND, "Uploading hidden service descriptor: "
"finished with status 200 (%s)", escaped(reason));
/* XXX: Trigger control event. */
break;
case 400:
log_warn(LD_REND, "Uploading hidden service descriptor: http "
"status 400 (%s) response from dirserver "
"'%s:%d'. Malformed hidden service descriptor?",
escaped(reason), conn->base_.address, conn->base_.port);
/* XXX: Trigger control event. */
break;
default:
log_warn(LD_REND, "Uploading hidden service descriptor: http "
"status %d (%s) response unexpected (server "
"'%s:%d').",
status_code, escaped(reason), conn->base_.address,
conn->base_.port);
/* XXX: Trigger control event. */
break;
}
return 0;
}
/** Called when a directory connection reaches EOF. */
int
connection_dir_reached_eof(dir_connection_t *conn)

View file

@ -12,6 +12,8 @@
#ifndef TOR_DIRECTORY_H
#define TOR_DIRECTORY_H
#include "hs_ident.h"
int directories_have_accepted_server_descriptor(void);
void directory_post_to_dirservers(uint8_t dir_purpose, uint8_t router_purpose,
dirinfo_type_t type, const char *payload,
@ -71,6 +73,8 @@ void directory_request_set_if_modified_since(directory_request_t *req,
time_t if_modified_since);
void directory_request_set_rend_query(directory_request_t *req,
const rend_data_t *query);
void directory_request_set_hs_ident(directory_request_t *req,
const hs_ident_dir_conn_t *ident);
void directory_request_set_routerstatus(directory_request_t *req,
const routerstatus_t *rs);

View file

@ -421,15 +421,20 @@ typedef enum {
#define DIR_PURPOSE_FETCH_RENDDESC_V2 18
/** A connection to a directory server: download a microdescriptor. */
#define DIR_PURPOSE_FETCH_MICRODESC 19
#define DIR_PURPOSE_MAX_ 19
/** A connetion to a hidden service directory: upload a descriptor. */
#define DIR_PURPOSE_UPLOAD_HSDESC 20
/** A connetion to a hidden service directory: fetch a descriptor. */
#define DIR_PURPOSE_FETCH_HSDESC 21
#define DIR_PURPOSE_MAX_ 21
/** True iff <b>p</b> is a purpose corresponding to uploading
* data to a directory server. */
#define DIR_PURPOSE_IS_UPLOAD(p) \
((p)==DIR_PURPOSE_UPLOAD_DIR || \
(p)==DIR_PURPOSE_UPLOAD_VOTE || \
(p)==DIR_PURPOSE_UPLOAD_SIGNATURES || \
(p)==DIR_PURPOSE_UPLOAD_RENDDESC_V2)
(p)==DIR_PURPOSE_UPLOAD_SIGNATURES || \
(p)==DIR_PURPOSE_UPLOAD_RENDDESC_V2 || \
(p)==DIR_PURPOSE_UPLOAD_HSDESC)
#define EXIT_PURPOSE_MIN_ 1
/** This exit stream wants to do an ordinary connect. */