diff options
author | George Kadianakis <desnacked@riseup.net> | 2018-09-12 14:40:19 +0300 |
---|---|---|
committer | George Kadianakis <desnacked@riseup.net> | 2018-09-15 16:31:22 +0300 |
commit | 27d7491f5a761c58fc687f0b816b80ff9f7a1a1d (patch) | |
tree | 33fdb6c5bfc4e55f917c9cf298df545008827910 /src | |
parent | be142194cd447a5e31836128c9166f8a592a1649 (diff) | |
download | tor-27d7491f5a761c58fc687f0b816b80ff9f7a1a1d.tar.gz tor-27d7491f5a761c58fc687f0b816b80ff9f7a1a1d.zip |
Introduce per-service HiddenServiceExportCircuitID torrc option.
Moves code to a function, better viewed with --color-moved.
Diffstat (limited to 'src')
-rw-r--r-- | src/app/config/config.c | 1 | ||||
-rw-r--r-- | src/core/or/connection_edge.c | 52 | ||||
-rw-r--r-- | src/feature/hs/hs_config.c | 20 | ||||
-rw-r--r-- | src/feature/hs/hs_service.c | 13 | ||||
-rw-r--r-- | src/feature/hs/hs_service.h | 5 |
5 files changed, 70 insertions, 21 deletions
diff --git a/src/app/config/config.c b/src/app/config/config.c index 1adeb75c98..13421f1033 100644 --- a/src/app/config/config.c +++ b/src/app/config/config.c @@ -457,6 +457,7 @@ static config_var_t option_vars_[] = { VAR("HiddenServiceMaxStreams",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceMaxStreamsCloseCircuit",LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceNumIntroductionPoints", LINELIST_S, RendConfigLines, NULL), + VAR("HiddenServiceExportCircuitID", LINELIST_S, RendConfigLines, NULL), VAR("HiddenServiceStatistics", BOOL, HiddenServiceStatistics_option, "1"), V(HidServAuth, LINELIST, NULL), V(ClientOnionAuthDir, FILENAME, NULL), diff --git a/src/core/or/connection_edge.c b/src/core/or/connection_edge.c index a85419376f..8b333a6f49 100644 --- a/src/core/or/connection_edge.c +++ b/src/core/or/connection_edge.c @@ -597,6 +597,33 @@ connected_cell_format_payload(uint8_t *payload_out, return connected_payload_len; } +/* DOCDOCDOC */ +static void +send_ha_proxy_header(const edge_connection_t *edge_conn, + connection_t *conn) +{ + char buf[512]; + char dst_ipv6[39] = "::1"; + /* See RFC4193 regarding fc00::/7 */ + char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:"; + /* TODO: retain virtual port and use as destination port */ + uint16_t dst_port = 443; + uint16_t src_port = 0; + uint32_t gid = 0; + + if (edge_conn->on_circuit != NULL) { + gid = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit)->global_identifier; + src_port = gid & 0x0000ffff; + } + + gid = (gid == 0) ? 1 : gid; + src_port = (src_port == 0) ? 1 : src_port; + + tor_snprintf(buf, sizeof(buf), "PROXY TCP6 %s:%x %s %d %d\r\n", + src_ipv6_prefix, gid, dst_ipv6, src_port, dst_port); + connection_buf_add(buf, strlen(buf), conn); +} + /** Connected handler for exit connections: start writing pending * data, deliver 'CONNECTED' relay cells as appropriate, and check * any pending data that may have been received. */ @@ -618,28 +645,13 @@ connection_edge_finished_connecting(edge_connection_t *edge_conn) conn->state = EXIT_CONN_STATE_OPEN; - /* Include Proxy Protocol header. */ - char buf[512]; - char dst_ipv6[39] = "::1"; - /* See RFC4193 regarding fc00::/7 */ - char src_ipv6_prefix[34] = "fc00:dead:beef:4dad:"; - /* TODO: retain virtual port and use as destination port */ - uint16_t dst_port = 443; - uint16_t src_port = 0; - uint32_t gid = 0; - - if (edge_conn->on_circuit != NULL) { - gid = TO_ORIGIN_CIRCUIT(edge_conn->on_circuit)->global_identifier; - src_port = gid & 0x0000ffff; + /* If it's an onion service connection, we might want to include the proxy + * protocol header */ + if (edge_conn->hs_ident && + hs_service_exports_circuit_id(&edge_conn->hs_ident->identity_pk)) { + send_ha_proxy_header(edge_conn, conn); } - gid = (gid == 0) ? 1 : gid; - src_port = (src_port == 0) ? 1 : src_port; - - tor_snprintf(buf, sizeof(buf), "PROXY TCP6 %s:%x %s %d %d\r\n", - src_ipv6_prefix, gid, dst_ipv6, src_port, dst_port); - connection_buf_add(buf, strlen(buf), conn); - connection_watch_events(conn, READ_EVENT); /* stop writing, keep reading */ if (connection_get_outbuf_len(conn)) /* in case there are any queued relay * cells */ diff --git a/src/feature/hs/hs_config.c b/src/feature/hs/hs_config.c index eaeb58829a..16bfe7c544 100644 --- a/src/feature/hs/hs_config.c +++ b/src/feature/hs/hs_config.c @@ -188,6 +188,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 +201,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 +267,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 +294,18 @@ config_service_v3(const config_line_t *line_, have_num_ip = 1; continue; } + if (!strcasecmp(line->key, "HiddenServiceExportCircuitID")) { + config->export_circuit_id = + (unsigned int) helper_parse_uint64(line->key, line->value, 0, 1, &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_service.c b/src/feature/hs/hs_service.c index 30d23eb771..75d7cb75ed 100644 --- a/src/feature/hs/hs_service.c +++ b/src/feature/hs/hs_service.c @@ -3762,6 +3762,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? */ +bool +hs_service_exports_circuit_id(const ed25519_public_key_t *pk) +{ + hs_service_t *service = find_service(hs_service_map, pk); + if (!service) { + return 0; + } + + return service->config.export_circuit_id; +} + /* 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..e541cb28b9 100644 --- a/src/feature/hs/hs_service.h +++ b/src/feature/hs/hs_service.h @@ -210,6 +210,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? */ + bool export_circuit_id; } hs_service_config_t; /* Service state. */ @@ -316,6 +319,8 @@ void hs_service_upload_desc_to_dir(const char *encoded_desc, const ed25519_public_key_t *blinded_pk, const routerstatus_t *hsdir_rs); +bool hs_service_exports_circuit_id(const ed25519_public_key_t *pk); + #ifdef HS_SERVICE_PRIVATE #ifdef TOR_UNIT_TESTS |