< Summary

Information
Class: Renci.SshNet.Connection.Socks4Connector
Assembly: Renci.SshNet
File(s): \home\appveyor\projects\ssh-net\src\Renci.SshNet\Connection\Socks4Connector.cs
Line coverage
86%
Covered lines: 59
Uncovered lines: 9
Coverable lines: 68
Total lines: 135
Line coverage: 86.7%
Branch coverage
46%
Covered branches: 6
Total branches: 13
Branch coverage: 46.1%
Method coverage

Feature is only available for sponsors

Upgrade to PRO version

Metrics

MethodBranch coverage Cyclomatic complexity Line coverage
.ctor(...)100%1100%
HandleProxyConnect(...)42.85%768.75%
CreateSocks4ConnectionRequest(...)100%1100%
GetSocks4DestinationAddress(...)50%481.81%
GetProxyUserBytes(...)50%266.66%

File(s)

\home\appveyor\projects\ssh-net\src\Renci.SshNet\Connection\Socks4Connector.cs

#LineLine coverage
 1using System;
 2using System.Net.Sockets;
 3using System.Text;
 4
 5using Renci.SshNet.Abstractions;
 6using Renci.SshNet.Common;
 7
 8namespace Renci.SshNet.Connection
 9{
 10    /// <summary>
 11    /// Establishes a tunnel via a SOCKS4 proxy server.
 12    /// </summary>
 13    /// <remarks>
 14    /// https://www.openssh.com/txt/socks4.protocol.
 15    /// </remarks>
 16    internal sealed class Socks4Connector : ProxyConnector
 17    {
 18        public Socks4Connector(ISocketFactory socketFactory)
 9619            : base(socketFactory)
 9620        {
 9621        }
 22
 23        /// <summary>
 24        /// Establishes a connection to the server via a SOCKS5 proxy.
 25        /// </summary>
 26        /// <param name="connectionInfo">The connection information.</param>
 27        /// <param name="socket">The <see cref="Socket"/>.</param>
 28        protected override void HandleProxyConnect(IConnectionInfo connectionInfo, Socket socket)
 7229        {
 7230            var connectionRequest = CreateSocks4ConnectionRequest(connectionInfo.Host, (ushort)connectionInfo.Port, conn
 7231            SocketAbstraction.Send(socket, connectionRequest);
 32
 33            // Read reply version
 7234            if (SocketReadByte(socket, connectionInfo.Timeout) != 0x00)
 035            {
 036                throw new ProxyException("SOCKS4: Null is expected.");
 37            }
 38
 39            // Read response code
 5740            var code = SocketReadByte(socket, connectionInfo.Timeout);
 41
 4242            switch (code)
 43            {
 44                case 0x5a:
 3045                    break;
 46                case 0x5b:
 1247                    throw new ProxyException("SOCKS4: Connection rejected.");
 48                case 0x5c:
 049                    throw new ProxyException("SOCKS4: Client is not running identd or not reachable from the server.");
 50                case 0x5d:
 051                    throw new ProxyException("SOCKS4: Client's identd could not confirm the user ID string in the reques
 52                default:
 053                    throw new ProxyException("SOCKS4: Not valid response.");
 54            }
 55
 3056            var destBuffer = new byte[6]; // destination port and IP address should be ignored
 3057            _ = SocketRead(socket, destBuffer, 0, destBuffer.Length, connectionInfo.Timeout);
 1558        }
 59
 60        private static byte[] CreateSocks4ConnectionRequest(string hostname, ushort port, string username)
 7261        {
 7262            var addressBytes = GetSocks4DestinationAddress(hostname);
 7263            var proxyUserBytes = GetProxyUserBytes(username);
 64
 7265            var connectionRequest = new byte[// SOCKS version number
 7266                                             1 +
 7267
 7268                                             // Command code
 7269                                             1 +
 7270
 7271                                             // Port number
 7272                                             2 +
 7273
 7274                                             // IP address
 7275                                             addressBytes.Length +
 7276
 7277                                             // Username
 7278                                             proxyUserBytes.Length +
 7279
 7280                                             // Null terminator
 7281                                             1];
 82
 7283            var index = 0;
 84
 85            // SOCKS version number
 7286            connectionRequest[index++] = 0x04;
 87
 88            // Command code
 7289            connectionRequest[index++] = 0x01; // establish a TCP/IP stream connection
 90
 91            // Port number
 7292            Pack.UInt16ToBigEndian(port, connectionRequest, index);
 7293            index += 2;
 94
 95            // Address
 7296            Buffer.BlockCopy(addressBytes, 0, connectionRequest, index, addressBytes.Length);
 7297            index += addressBytes.Length;
 98
 99            // User name
 72100            Buffer.BlockCopy(proxyUserBytes, 0, connectionRequest, index, proxyUserBytes.Length);
 72101            index += proxyUserBytes.Length;
 102
 103            // Null terminator
 72104            connectionRequest[index] = 0x00;
 105
 72106            return connectionRequest;
 72107        }
 108
 109        private static byte[] GetSocks4DestinationAddress(string hostname)
 72110        {
 72111            var addresses = DnsAbstraction.GetHostAddresses(hostname);
 112
 144113            for (var i = 0; i < addresses.Length; i++)
 72114            {
 72115                var address = addresses[i];
 72116                if (address.AddressFamily == AddressFamily.InterNetwork)
 72117                {
 72118                    return address.GetAddressBytes();
 119                }
 0120            }
 121
 0122            throw new ProxyException(string.Format("SOCKS4 only supports IPv4. No such address found for '{0}'.", hostna
 72123        }
 124
 125        private static byte[] GetProxyUserBytes(string proxyUser)
 72126        {
 72127            if (proxyUser == null)
 0128            {
 0129                return Array.Empty<byte>();
 130            }
 131
 72132            return Encoding.ASCII.GetBytes(proxyUser);
 72133        }
 134    }
 135}