Pass username & password even for NoAuthenticationRequired
MODIFY
WalletWasabi/Tor/Socks5/TorTcpConnectionFactory.cs
WalletWasabi/Tor/Socks5/TorTcpConnectionFactory.cs
@@ -136,6 +136,7 @@ public class TorTcpConnectionFactory
/// <seealso href="https://www.torproject.org/docs/tor-manual.html.en"/>
/// <seealso href="https://linux.die.net/man/1/tor">For <c>IsolateSOCKSAuth</c> option explanation.</seealso>
/// <seealso href="https://gitweb.torproject.org/torspec.git/tree/socks-extensions.txt#n35"/>
+ /// <seealso href="https://github.com/torproject/torspec/blob/79da008392caed38736c73d839df7aa80628b645/socks-extensions.txt#L49-L51">Explains why we pass username and password even for <see cref="MethodField.NoAuthenticationRequired"/>.</seealso>
/// <exception cref="NotSupportedException">When authentication fails due to unsupported authentication method.</exception>
/// <exception cref="InvalidOperationException">When authentication fails due to invalid credentials.</exception>
private async Task HandshakeAsync(TcpClient tcpClient, ICircuit circuit, CancellationToken cancellationToken)
@@ -161,13 +162,13 @@ public class TorTcpConnectionFactory
// client are acceptable, and the client MUST close the connection.
throw new NotSupportedException("Tor's SOCKS5 proxy does not support any of the client's authentication methods.");
}
- else if (methodSelection.Method == MethodField.UsernamePassword)
+ else if (methodSelection.Method == MethodField.UsernamePassword || methodSelection.Method == MethodField.NoAuthenticationRequired)
{
- // https://tools.ietf.org/html/rfc1929#section-2
- // Once the SOCKS V5 server has started, and the client has selected the
- // Username / Password Authentication protocol, the Username / Password
- // sub-negotiation begins. This begins with the client producing a
- // Username / Password request:
+ // Regarding NoAuthenticationRequired: Tor spec explicitly mentions that username & password can be passed even if no authentication is required.
+ // Tor does that to allow broken clients to work. However, for us, it is important to mark Tor streams somehow so that we know when the streams are
+ // closed. Unfortunately, using a non-standard Tor SOCKS5 feature is the easiest way to do it. Otherwise, the implementation would get much more hairy.
+ // That is probably the reason why Tor control protocol is not intended to be a part of Tor (rust) implementation.
+
UNameField uName = new(uName: circuit.Name);
PasswdField passwd = new(password: circuit.Name);
UsernamePasswordRequest usernamePasswordRequest = new(uName, passwd);

Pass username & password even for NoAuthenticationRequired