Client's choice of rend point can leak info about hidden service's guard relay
Imagine the scenario where the attacking client picks a rendezvous point that happens to be the hidden service's primary (first) entry guard. Then
- The hidden service will look through its preemptively built circuits to see if it can extend any of them. circuit_find_to_cannibalize() will decide that none of the existing circuits are suitable, because they would cause a duplicate hop.
- So the hidden service decides to make a new circuit. In populate_live_entry_guards() it compares node to chosen_exit and then exit_family, and skips it if there's overlap.
So the result is that even when NumEntryGuards is 1, the hidden service will end up using its second entry guard for this circuit. Surprising. This isn't terrible, since I don't see any way to induce it to contact a third entry guard, but still, two is more than one, especially when you thought you were getting only one. (Imagine an attack where the adversary has you rendezvous with every relay that has the Guard flag -- now you're guaranteed to step over to your second guard at least once.)
Where it gets messy is if the user explicitly set EntryNodes, like some hidden service operators think is wise, so they can use an entry node they trust. In that case entry_list_is_constrained() is true, so populate_live_entry_guards() will happily return an empty list if your one choice is inappropriate, resulting in choose_random_entry_impl() returning NULL. The external behavior is that if you send the hidden service the right rendezvous point, it never connects. That's kind of bad, especially since some people argue setting an explicit EntryNode is a wise move.
Now, learning about the hidden service's choice of primary guard isn't the end of the world, because there are other reasonably straightforward ways to enumerate the entry guard of a hidden service currently, e.g. the predecessor attack (run a middle relay, rendezvous with the hidden service many times, and see which prior hop shows up in the circuit the most times). But we'd like to fix those, e.g. by moving to a layered entry guard design, and if we do, this issue will remain.
Reported by 'ghetto' on irc.