Skip to content

Commit fda35a1

Browse files
committed
Simplification
1 parent d2cc5f9 commit fda35a1

File tree

1 file changed

+51
-28
lines changed

1 file changed

+51
-28
lines changed

src/MongoDB.Driver/Core/Connections/Socks5Helper.cs

Lines changed: 51 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -87,6 +87,9 @@ internal static class Socks5Helper
8787

8888
private const int BufferSize = 512;
8989

90+
//TODO Maybe need to change the name of the ReadMethods... It's more like interpret
91+
//Need to specify all create request methods return the bytes of the message
92+
9093
public static void PerformSocks5Handshake(Stream stream, EndPoint endPoint, Socks5AuthenticationSettings authenticationSettings, CancellationToken cancellationToken)
9194
{
9295
var (targetHost, targetPort) = endPoint.GetHostAndPort();
@@ -98,13 +101,23 @@ public static void PerformSocks5Handshake(Stream stream, EndPoint endPoint, Sock
98101
var greetingRequestLength = CreateGreetingRequest(buffer, useAuth);
99102
stream.Write(buffer, 0, greetingRequestLength);
100103

101-
ReadGreetingResponse(stream, buffer, useAuth, authenticationSettings, cancellationToken);
104+
stream.ReadBytes(buffer, 0, 2, cancellationToken);
105+
ProcessGreetingResponse(buffer, useAuth, authenticationSettings, cancellationToken);
106+
107+
if (useAuth)
108+
{
109+
var authenticationRequestLength = CreateAuthenticationRequest(buffer, authenticationSettings, cancellationToken);
110+
stream.Write(buffer, 0, authenticationRequestLength);
111+
112+
stream.ReadBytes(buffer, 0, 2, cancellationToken);
113+
ProcessAuthenticationResponse(buffer);
114+
}
102115

103-
var addressLength = CreateConnectRequest(buffer, targetHost, targetPort);
104-
stream.Write(buffer, 0, addressLength + 6);
116+
var connectRequestLength = CreateConnectRequest(buffer, targetHost, targetPort);
117+
stream.Write(buffer, 0, connectRequestLength);
105118

106119
stream.ReadBytes(buffer, 0, 5, cancellationToken);
107-
var skip = ReadConnectResponse(buffer);
120+
var skip = ProcessConnectResponse(buffer);
108121
stream.ReadBytes(buffer, 0, skip, cancellationToken);
109122
}
110123
finally
@@ -124,13 +137,22 @@ public static async Task PerformSocks5HandshakeAsync(Stream stream, EndPoint end
124137
var greetingRequestLength = CreateGreetingRequest(buffer, useAuth);
125138
await stream.WriteAsync(buffer, 0, greetingRequestLength, cancellationToken).ConfigureAwait(false);
126139

127-
await ReadGreetingResponseAsync(stream, buffer, useAuth, authenticationSettings, cancellationToken).ConfigureAwait(false);
140+
ProcessGreetingResponse(buffer, useAuth, authenticationSettings, cancellationToken);
128141

129-
var addressLength = CreateConnectRequest(buffer, targetHost, targetPort);
130-
await stream.WriteAsync(buffer, 0, addressLength + 6, cancellationToken).ConfigureAwait(false);
142+
if (useAuth)
143+
{
144+
var authenticationRequestLength = CreateAuthenticationRequest(buffer, authenticationSettings, cancellationToken);
145+
await stream.WriteAsync(buffer, 0, authenticationRequestLength, cancellationToken).ConfigureAwait(false);
146+
147+
await stream.ReadBytesAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
148+
ProcessAuthenticationResponse(buffer);
149+
}
150+
151+
var connectRequestLength = CreateConnectRequest(buffer, targetHost, targetPort);
152+
await stream.WriteAsync(buffer, 0, connectRequestLength, cancellationToken).ConfigureAwait(false);
131153

132154
await stream.ReadBytesAsync(buffer, 0, 5, cancellationToken).ConfigureAwait(false);
133-
var skip = ReadConnectResponse(buffer);
155+
var skip = ProcessConnectResponse(buffer);
134156
await stream.ReadBytesAsync(buffer, 0, skip, cancellationToken).ConfigureAwait(true);
135157
}
136158
finally
@@ -156,9 +178,8 @@ private static int CreateGreetingRequest(byte[] buffer, bool useAuth)
156178
return 4;
157179
}
158180

159-
private static void ReadGreetingResponse(Stream stream, byte[] buffer, bool useAuth, Socks5AuthenticationSettings authenticationSettings, CancellationToken cancellationToken)
181+
private static void ProcessGreetingResponse(byte[] buffer, bool useAuth, Socks5AuthenticationSettings authenticationSettings, CancellationToken cancellationToken)
160182
{
161-
stream.ReadBytes(buffer, 0, 2, cancellationToken);
162183
VerifyProtocolVersion(buffer[0]);
163184
var method = buffer[1];
164185
if (method == MethodUsernamePassword)
@@ -167,30 +188,33 @@ private static void ReadGreetingResponse(Stream stream, byte[] buffer, bool useA
167188
{
168189
throw new IOException("SOCKS5 proxy requires authentication, but no credentials were provided.");
169190
}
170-
PerformUsernamePasswordAuth(stream, buffer, authenticationSettings, cancellationToken);
171191
}
172192
else if (method != MethodNoAuth)
173193
{
174194
throw new IOException("SOCKS5 proxy requires unsupported authentication method.");
175195
}
176196
}
177197

178-
private static async Task ReadGreetingResponseAsync(Stream stream, byte[] buffer, bool useAuth, Socks5AuthenticationSettings authenticationSettings, CancellationToken cancellationToken)
198+
private static int CreateAuthenticationRequest(byte[] buffer, Socks5AuthenticationSettings authenticationSettings, CancellationToken cancellationToken)
179199
{
180-
await stream.ReadBytesAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
181-
VerifyProtocolVersion(buffer[0]);
182-
var method = buffer[1];
183-
if (method == MethodUsernamePassword)
184-
{
185-
if (!useAuth)
186-
{
187-
throw new IOException("SOCKS5 proxy requires authentication, but no credentials were provided.");
188-
}
189-
await PerformUsernamePasswordAuthAsync(stream, buffer, authenticationSettings, cancellationToken).ConfigureAwait(false);
190-
}
191-
else if (method != MethodNoAuth)
200+
var usernamePasswordAuthenticationSettings = (Socks5AuthenticationSettings.UsernamePasswordAuthenticationSettings)authenticationSettings;
201+
var proxyUsername = usernamePasswordAuthenticationSettings.Username;
202+
var proxyPassword = usernamePasswordAuthenticationSettings.Password;
203+
204+
buffer[0] = SubnegotiationVersion;
205+
var usernameLength = EncodeString(proxyUsername, buffer, 2, nameof(proxyUsername));
206+
buffer[1] = usernameLength;
207+
var passwordLength = EncodeString(proxyPassword, buffer, 3 + usernameLength, nameof(proxyPassword));
208+
buffer[2 + usernameLength] = passwordLength;
209+
210+
return 3 + usernameLength + passwordLength;
211+
}
212+
213+
private static void ProcessAuthenticationResponse(byte[] buffer)
214+
{
215+
if (buffer[0] != SubnegotiationVersion || buffer[1] != Socks5Success)
192216
{
193-
throw new IOException("SOCKS5 proxy requires unsupported authentication method.");
217+
throw new IOException("SOCKS5 authentication failed.");
194218
}
195219
}
196220

@@ -231,7 +255,6 @@ private static async Task PerformUsernamePasswordAuthAsync(Stream stream, byte[]
231255
var authLength = 3 + usernameLength + passwordLength;
232256
await stream.WriteAsync(buffer, 0, authLength, cancellationToken).ConfigureAwait(false);
233257

234-
235258
await stream.ReadBytesAsync(buffer, 0, 2, cancellationToken).ConfigureAwait(false);
236259
if (buffer[0] != SubnegotiationVersion || buffer[1] != Socks5Success)
237260
{
@@ -274,11 +297,11 @@ private static int CreateConnectRequest(byte[] buffer, string targetHost, int ta
274297

275298
BinaryPrimitives.WriteUInt16BigEndian(buffer.AsSpan(addressLength + 4), (ushort)targetPort);
276299

277-
return addressLength;
300+
return addressLength + 6;
278301
}
279302

280303
// Reads the SOCKS5 connect response and returns the number of bytes to skip in the buffer.
281-
private static int ReadConnectResponse(byte[] buffer)
304+
private static int ProcessConnectResponse(byte[] buffer)
282305
{
283306
VerifyProtocolVersion(buffer[0]);
284307

0 commit comments

Comments
 (0)