|
@@ -1055,7 +1055,8 @@ directory_request_set_payload(directory_request_t *req,
|
|
|
const char *payload,
|
|
|
size_t payload_len)
|
|
|
{
|
|
|
- tor_assert(DIR_PURPOSE_IS_UPLOAD(req->dir_purpose));
|
|
|
+
|
|
|
+ tor_assert(DIR_PURPOSE_IS_UPLOAD(req->dir_purpose) || req->dir_purpose == DIR_PURPOSE_FETCH_HSDESC);
|
|
|
|
|
|
req->payload = payload;
|
|
|
req->payload_len = payload_len;
|
|
@@ -1540,7 +1541,7 @@ directory_send_command(dir_connection_t *conn,
|
|
|
|
|
|
Will be decorated with brackets around it if it is ipv6. */
|
|
|
char decorated_address[128];
|
|
|
- smartlist_t *headers = smartlist_new();
|
|
|
+ smartlist_t *headers;
|
|
|
char *url;
|
|
|
char *accept_encoding;
|
|
|
size_t url_len;
|
|
@@ -1555,6 +1556,21 @@ directory_send_command(dir_connection_t *conn,
|
|
|
if (resource)
|
|
|
conn->requested_resource = tor_strdup(resource);
|
|
|
|
|
|
+
|
|
|
+ * ensure that the PIR query is constructed before continuing. */
|
|
|
+ if (purpose == DIR_PURPOSE_FETCH_HSDESC) {
|
|
|
+ HSClientPIRParams *pirparams =
|
|
|
+ hs_client_pirparams_lookup(req->routerstatus->identity_digest);
|
|
|
+ if (pirparams && pirparams->size > 0 && req->payload == NULL) {
|
|
|
+
|
|
|
+ * request and call back to us when it's ready. */
|
|
|
+ hs_client_pir_create(directory_send_command, conn);
|
|
|
+ return;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ headers = smartlist_new();
|
|
|
+
|
|
|
|
|
|
if (strchr(conn->base_.address, ':')) {
|
|
|
copy_ipv6_address(decorated_address, conn->base_.address,
|
|
@@ -1691,11 +1707,18 @@ directory_send_command(dir_connection_t *conn,
|
|
|
case DIR_PURPOSE_FETCH_HSDESC:
|
|
|
tor_assert(resource);
|
|
|
tor_assert(strlen(resource) <= ED25519_BASE64_LEN);
|
|
|
- tor_assert(!payload);
|
|
|
if (getenv("PIR_CLIENT_PATH")) {
|
|
|
- HSClientPIRParams *pirparams =
|
|
|
+ if (payload) {
|
|
|
+ conn->pirclient_state = PIRCLIENT_STATE_AWAITING_PIRREPLY;
|
|
|
+ httpcommand = "POST";
|
|
|
+ tor_asprintf(&url, "/tor/pironion/query");
|
|
|
+ log_info(LD_DIR, "PIRCLIENT Performing PIR query to %s",
|
|
|
+ safe_str_client(routerstatus_describe(req->routerstatus)));
|
|
|
+ break;
|
|
|
+ } else {
|
|
|
+ HSClientPIRParams *pirparams =
|
|
|
hs_client_pirparams_lookup(req->routerstatus->identity_digest);
|
|
|
- if (!pirparams) {
|
|
|
+ if (!pirparams) {
|
|
|
|
|
|
* but don't have them yet. */
|
|
|
conn->pirclient_state = PIRCLIENT_STATE_AWAITING_PARAMS;
|
|
@@ -1704,16 +1727,7 @@ directory_send_command(dir_connection_t *conn,
|
|
|
log_info(LD_DIR, "PIRCLIENT Fetching params from %s",
|
|
|
safe_str_client(routerstatus_describe(req->routerstatus)));
|
|
|
break;
|
|
|
- } else if (pirparams->size > 0) {
|
|
|
-
|
|
|
-
|
|
|
- * privately. */
|
|
|
-
|
|
|
- httpcommand = "GET";
|
|
|
- tor_asprintf(&url, "/tor/hs/3/%s", resource);
|
|
|
- log_info(LD_DIR, "PIRCLIENT PIR query (well, not yet) to %s",
|
|
|
- safe_str_client(routerstatus_describe(req->routerstatus)));
|
|
|
- break;
|
|
|
+ }
|
|
|
}
|
|
|
}
|
|
|
|
|
@@ -2736,6 +2750,13 @@ handle_response_upload_signatures(dir_connection_t *conn,
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+struct connection_dir_client_conninfo_st {
|
|
|
+ char *address;
|
|
|
+ uint16_t port;
|
|
|
+ char identity_digest[DIGEST_LEN];
|
|
|
+ struct hs_ident_dir_conn_t *hs_ident;
|
|
|
+};
|
|
|
+
|
|
|
|
|
|
* Handler function: processes a response to a request for a v3 hidden service
|
|
|
* descriptor.
|
|
@@ -2788,38 +2809,67 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
|
|
|
safe_str_client(routerstatus_describe(req->routerstatus)));
|
|
|
directory_initiate_request(req);
|
|
|
directory_request_free(req);
|
|
|
+ } else {
|
|
|
+
|
|
|
+ * hsdesc fetching process should be retried with another hsdir. */
|
|
|
+ return -1;
|
|
|
}
|
|
|
|
|
|
return 0;
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ * (handle_response_fetch_hsdesc_v3) completes, so we have to save
|
|
|
+ * anything in it we'll need in
|
|
|
+ * connection_dir_client_hsdesc_v3_received. */
|
|
|
+ connection_dir_client_conninfo_t conninfo =
|
|
|
+ tor_malloc_zero(sizeof(struct connection_dir_client_conninfo_st));
|
|
|
+ conninfo->address = tor_strdup(TO_CONN(conn)->address);
|
|
|
+ conninfo->port = TO_CONN(conn)->port;
|
|
|
+ memmove(conninfo->identity_digest, conn->identity_digest,
|
|
|
+ sizeof(conninfo->identity_digest));
|
|
|
+ conninfo->hs_ident = hs_ident_dir_conn_dup(conn->hs_ident);
|
|
|
+
|
|
|
|
|
|
- if (conn->pirclient_state == PIRCLIENT_STATE_AWAITING_PIRREPLY) {
|
|
|
-
|
|
|
- log_info(LD_REND,"PIRCLIENT received PIR reply from %s",
|
|
|
- safe_str_client(routerstatus_describe(rstat)));
|
|
|
+ if (conn->pirclient_state == PIRCLIENT_STATE_AWAITING_PIRREPLY
|
|
|
+ && status_code == 200) {
|
|
|
+ log_info(LD_REND,"PIRCLIENT received PIR reply from %s statuscode %d",
|
|
|
+ safe_str_client(routerstatus_describe(rstat)), status_code);
|
|
|
+ hs_client_pir_extract(conninfo, conn->pirclient_queryid, body, body_len);
|
|
|
+ return 0;
|
|
|
}
|
|
|
|
|
|
log_info(LD_REND,"PIRCLIENT received hsdesc from %s",
|
|
|
safe_str_client(routerstatus_describe(rstat)));
|
|
|
|
|
|
+ return connection_dir_client_hsdesc_v3_received(conninfo, body,
|
|
|
+ status_code, reason);
|
|
|
+}
|
|
|
+
|
|
|
+int
|
|
|
+connection_dir_client_hsdesc_v3_received(
|
|
|
+ connection_dir_client_conninfo_t conninfo,
|
|
|
+ const char *body, int status_code, const char *reason)
|
|
|
+{
|
|
|
switch (status_code) {
|
|
|
case 200:
|
|
|
|
|
|
- if (hs_cache_store_as_client(body, &conn->hs_ident->identity_pk) < 0) {
|
|
|
+ if (hs_cache_store_as_client(body, &conninfo->hs_ident->identity_pk) < 0) {
|
|
|
log_info(LD_REND, "Failed to store hidden service descriptor");
|
|
|
|
|
|
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_failed(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
"BAD_DESC");
|
|
|
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_content(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
NULL);
|
|
|
} else {
|
|
|
log_info(LD_REND, "Stored hidden service descriptor successfully.");
|
|
|
- TO_CONN(conn)->purpose = DIR_PURPOSE_HAS_FETCHED_HSDESC;
|
|
|
- hs_client_desc_has_arrived(conn->hs_ident);
|
|
|
+
|
|
|
+ * this function completes (or even before) */
|
|
|
+
|
|
|
+ hs_client_desc_has_arrived(conninfo->hs_ident);
|
|
|
|
|
|
- hs_control_desc_event_received(conn->hs_ident, conn->identity_digest);
|
|
|
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_received(conninfo->hs_ident, conninfo->identity_digest);
|
|
|
+ hs_control_desc_event_content(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
body);
|
|
|
}
|
|
|
break;
|
|
@@ -2829,9 +2879,9 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
|
|
|
log_info(LD_REND, "Fetching hidden service v3 descriptor not found: "
|
|
|
"Retrying at another directory.");
|
|
|
|
|
|
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_failed(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
"NOT_FOUND");
|
|
|
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_content(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
NULL);
|
|
|
break;
|
|
|
case 400:
|
|
@@ -2840,25 +2890,29 @@ handle_response_fetch_hsdesc_v3(dir_connection_t *conn,
|
|
|
"query? Retrying at another directory.",
|
|
|
escaped(reason));
|
|
|
|
|
|
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_failed(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
"QUERY_REJECTED");
|
|
|
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_content(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
NULL);
|
|
|
break;
|
|
|
default:
|
|
|
log_warn(LD_REND, "Fetching v3 hidden service descriptor failed: "
|
|
|
"http status %d (%s) response unexpected from HSDir server "
|
|
|
"'%s:%d'. Retrying at another directory.",
|
|
|
- status_code, escaped(reason), TO_CONN(conn)->address,
|
|
|
- TO_CONN(conn)->port);
|
|
|
+ status_code, escaped(reason), conninfo->address,
|
|
|
+ conninfo->port);
|
|
|
|
|
|
- hs_control_desc_event_failed(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_failed(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
"UNEXPECTED");
|
|
|
- hs_control_desc_event_content(conn->hs_ident, conn->identity_digest,
|
|
|
+ hs_control_desc_event_content(conninfo->hs_ident, conninfo->identity_digest,
|
|
|
NULL);
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
+ tor_free(conninfo->address);
|
|
|
+ hs_ident_dir_conn_free(conninfo->hs_ident);
|
|
|
+ tor_free(conninfo);
|
|
|
+
|
|
|
return 0;
|
|
|
}
|
|
|
|