summaryrefslogtreecommitdiff
path: root/src/feature/hs
diff options
context:
space:
mode:
authorNick Mathewson <nickm@torproject.org>2018-09-21 09:40:16 -0400
committerNick Mathewson <nickm@torproject.org>2018-09-21 09:40:16 -0400
commit0e4c42a912d020888e811b748925362e1b3dc67b (patch)
tree90a9e0e682a06bdf1af1ea9b0940dd81e20786e2 /src/feature/hs
parenta1b0283040723474377a5746dbd01782a9b7eaa7 (diff)
parent03ef4ec466fd7f1de097a7b0244ca5bc8cc32b18 (diff)
downloadtor-0e4c42a912d020888e811b748925362e1b3dc67b.tar.gz
tor-0e4c42a912d020888e811b748925362e1b3dc67b.zip
Merge remote-tracking branch 'ahf-github/asn/bugs4700_2'
Diffstat (limited to 'src/feature/hs')
-rw-r--r--src/feature/hs/hs_common.c5
-rw-r--r--src/feature/hs/hs_config.c48
-rw-r--r--src/feature/hs/hs_ident.h4
-rw-r--r--src/feature/hs/hs_service.c13
-rw-r--r--src/feature/hs/hs_service.h15
5 files changed, 84 insertions, 1 deletions
diff --git a/src/feature/hs/hs_common.c b/src/feature/hs/hs_common.c
index 12405a79cb..c36892e0f8 100644
--- a/src/feature/hs/hs_common.c
+++ b/src/feature/hs/hs_common.c
@@ -882,6 +882,11 @@ hs_set_conn_addr_port(const smartlist_t *ports, edge_connection_t *conn)
smartlist_free(matching_ports);
if (chosen_port) {
if (!(chosen_port->is_unix_addr)) {
+ /* save the original destination before we overwrite it */
+ if (conn->hs_ident) {
+ conn->hs_ident->orig_virtual_port = TO_CONN(conn)->port;
+ }
+
/* Get a non-AF_UNIX connection ready for connection_exit_connect() */
tor_addr_copy(&TO_CONN(conn)->addr, &chosen_port->real_addr);
TO_CONN(conn)->port = chosen_port->real_port;
diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c
index eaeb58829a..93d7403dfb 100644
--- a/src/feature/hs/hs_config.c
+++ b/src/feature/hs/hs_config.c
@@ -145,6 +145,34 @@ helper_parse_uint64(const char *opt, const char *value, uint64_t min,
return ret;
}
+/** Helper function: Given a configuration option and its value, parse the
+ * value as a hs_circuit_id_protocol_t. On success, ok is set to 1 and ret is
+ * the parse value. On error, ok is set to 0 and the "none"
+ * hs_circuit_id_protocol_t is returned. This function logs on error. */
+static hs_circuit_id_protocol_t
+helper_parse_circuit_id_protocol(const char *key, const char *value, int *ok)
+{
+ tor_assert(value);
+ tor_assert(ok);
+
+ hs_circuit_id_protocol_t ret = HS_CIRCUIT_ID_PROTOCOL_NONE;
+ *ok = 0;
+
+ if (! strcasecmp(value, "haproxy")) {
+ *ok = 1;
+ ret = HS_CIRCUIT_ID_PROTOCOL_HAPROXY;
+ } else if (! strcasecmp(value, "none")) {
+ *ok = 1;
+ ret = HS_CIRCUIT_ID_PROTOCOL_NONE;
+ } else {
+ log_warn(LD_CONFIG, "%s must be 'haproxy' or 'none'.", key);
+ goto err;
+ }
+
+ err:
+ return ret;
+}
+
/* Return the service version by trying to learn it from the key on disk if
* any. If nothing is found, the current service configured version is
* returned. */
@@ -188,6 +216,11 @@ config_has_invalid_options(const config_line_t *line_,
NULL /* End marker. */
};
+ const char *opts_exclude_v2[] = {
+ "HiddenServiceExportCircuitID",
+ NULL /* End marker. */
+ };
+
/* Defining the size explicitly allows us to take advantage of the compiler
* which warns us if we ever bump the max version but forget to grow this
* array. The plus one is because we have a version 0 :). */
@@ -196,7 +229,7 @@ config_has_invalid_options(const config_line_t *line_,
} exclude_lists[HS_VERSION_MAX + 1] = {
{ NULL }, /* v0. */
{ NULL }, /* v1. */
- { NULL }, /* v2 */
+ { opts_exclude_v2 }, /* v2 */
{ opts_exclude_v3 }, /* v3. */
};
@@ -262,6 +295,7 @@ config_service_v3(const config_line_t *line_,
hs_service_config_t *config)
{
int have_num_ip = 0;
+ bool export_circuit_id = false; /* just to detect duplicate options */
const char *dup_opt_seen = NULL;
const config_line_t *line;
@@ -288,6 +322,18 @@ config_service_v3(const config_line_t *line_,
have_num_ip = 1;
continue;
}
+ if (!strcasecmp(line->key, "HiddenServiceExportCircuitID")) {
+ config->circuit_id_protocol =
+ helper_parse_circuit_id_protocol(line->key, line->value, &ok);
+ if (!ok || export_circuit_id) {
+ if (export_circuit_id) {
+ dup_opt_seen = line->key;
+ }
+ goto err;
+ }
+ export_circuit_id = true;
+ continue;
+ }
}
/* We do not load the key material for the service at this stage. This is
diff --git a/src/feature/hs/hs_ident.h b/src/feature/hs/hs_ident.h
index 92d15b0523..ab87d16d17 100644
--- a/src/feature/hs/hs_ident.h
+++ b/src/feature/hs/hs_ident.h
@@ -111,6 +111,10 @@ typedef struct hs_ident_edge_conn_t {
* in the onion address. */
ed25519_public_key_t identity_pk;
+ /* The original virtual port that was used by the client to access the onion
+ * service, regardless of the internal port forwarding that might have
+ * happened on the service-side. */
+ uint16_t orig_virtual_port;
/* XXX: Client authorization. */
} hs_ident_edge_conn_t;
diff --git a/src/feature/hs/hs_service.c b/src/feature/hs/hs_service.c
index 28e3f73340..643240fb68 100644
--- a/src/feature/hs/hs_service.c
+++ b/src/feature/hs/hs_service.c
@@ -3767,6 +3767,19 @@ hs_service_set_conn_addr_port(const origin_circuit_t *circ,
return -1;
}
+/** Does the service with identity pubkey <b>pk</b> export the circuit IDs of
+ * its clients? */
+hs_circuit_id_protocol_t
+hs_service_exports_circuit_id(const ed25519_public_key_t *pk)
+{
+ hs_service_t *service = find_service(hs_service_map, pk);
+ if (!service) {
+ return HS_CIRCUIT_ID_PROTOCOL_NONE;
+ }
+
+ return service->config.circuit_id_protocol;
+}
+
/* Add to file_list every filename used by a configured hidden service, and to
* dir_list every directory path used by a configured hidden service. This is
* used by the sandbox subsystem to whitelist those. */
diff --git a/src/feature/hs/hs_service.h b/src/feature/hs/hs_service.h
index 735266071f..6fb15b9d37 100644
--- a/src/feature/hs/hs_service.h
+++ b/src/feature/hs/hs_service.h
@@ -161,6 +161,15 @@ typedef struct hs_service_authorized_client_t {
curve25519_public_key_t client_pk;
} hs_service_authorized_client_t;
+/** Which protocol to use for exporting HS client circuit ID. */
+typedef enum {
+ /** Don't expose the circuit id. */
+ HS_CIRCUIT_ID_PROTOCOL_NONE,
+
+ /** Use the HAProxy proxy protocol. */
+ HS_CIRCUIT_ID_PROTOCOL_HAPROXY
+} hs_circuit_id_protocol_t;
+
/* Service configuration. The following are set from the torrc options either
* set by the configuration file or by the control port. Nothing else should
* change those values. */
@@ -210,6 +219,9 @@ typedef struct hs_service_config_t {
/* Is this service ephemeral? */
unsigned int is_ephemeral : 1;
+
+ /* Does this service export the circuit ID of its clients? */
+ hs_circuit_id_protocol_t circuit_id_protocol;
} hs_service_config_t;
/* Service state. */
@@ -316,6 +328,9 @@ void hs_service_upload_desc_to_dir(const char *encoded_desc,
const ed25519_public_key_t *blinded_pk,
const routerstatus_t *hsdir_rs);
+hs_circuit_id_protocol_t
+hs_service_exports_circuit_id(const ed25519_public_key_t *pk);
+
#ifdef HS_SERVICE_PRIVATE
#ifdef TOR_UNIT_TESTS