diff options
Diffstat (limited to 'src/feature/hs')
-rw-r--r-- | src/feature/hs/hs_common.c | 5 | ||||
-rw-r--r-- | src/feature/hs/hs_config.c | 48 | ||||
-rw-r--r-- | src/feature/hs/hs_ident.h | 4 | ||||
-rw-r--r-- | src/feature/hs/hs_service.c | 13 | ||||
-rw-r--r-- | src/feature/hs/hs_service.h | 15 |
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 |