tor-spec, rend-spec: Clarify handling of strange linkspec sequences
There are three places in Tor (AFAICR) where a party receives a list of link-specifiers:
- When handling an EXTEND2 message. (
extend_cell_from_extend2_cell_body()
) - When handling an HsDesc. (
hs_get_extend_info_from_lspecs()
, called bydesc_intro_point_to_extend_info()
) - When handling an INTRODUCE2 message. (
hs_get_extend_info_from_lspecs()
, called bylaunch_rendezvous_point_circuit()
)
In each of these cases, the C tor implementation converts the list of link-specifiers into an extend_cell_t
or extend_info_t
. But there are inconsistencies and weird behaviors!
Problem 1: Handling duplicate identity types.
What should happen if two RSA identities or two Ed25519 identities are included?
- In EXTEND2 messages, this causes the message to be rejected.
- In HsDescs and INTRODUCE2 messages, we use whichever identity appears last.
Problem 2: Handling unrecognized link specifiers
What should happen if we see a link specifier that we don't recognize?
In all cases right now, in C tor, we ignore that link specifier. (We also re-order the ones that we do see, and discard extra IP addresses.) That's not what the spec says we should do for onion service code, however. By my reading of the spec, we are supposed to pass the link specifier list verbatim when we're using it to make an EXTEND2 message to our final hop. The spec says:
[In 2.5.2.2:]
The client SHOULD NOT reject any LSTYPE fields which it doesn't
recognize; instead, it should use them verbatim in its EXTEND
request to the introduction point.
[In 3.3:]
The hidden service should handle invalid or unrecognised link specifiers
the same way as clients do in section 2.5.2.2. In particular, services
MAY perform basic validity checks on link specifiers, and SHOULD NOT
reject unrecognised link specifiers, to avoid information leaks.
Is that actually a good idea? If we pass the linkspecs verbatim, it would make it easier for parties to make a weird link specifier list that could distinguish attempts to use their onion services or rendezvous points. (But they can already do that by choosing an unlisted relay.)
If we don't pass linkspecs verbatim, then it's harder for us to make our protocol extensible in the future, by adding additional identity types or connection types.
Problem 3: What linkspecs are required?
Our C tor code treats "Legacy identity" linkspec as required. This isn't documented in the spec afaict.
For Extend2 cells, we treat ipv4 or ipv6 as required.
For onion service purposes, we seem to treat Ipv4 as required unless we're about to attempt a direct connection as a non-anonymous onion service, in which case we accept IPv6 also.
Problem 4: Do we add additional information if we have it?
Tor-spec says that we should do the following for EXTEND2 messages, and C tor does:
If only one identity key is provided, but the extending OR knows
the other (from directory information), then the OR SHOULD also
enforce that key.
But rend-spec neither allows nor prohibits a similar behavior (adding additional identity information from the directory, or enforcing consistency with the directory). We should be explicit here.