|  | @@ -431,7 +431,23 @@ namespace Renci.SshNet
 | 
	
		
			
				|  |  |                      //  Build list of available messages while connecting
 | 
	
		
			
				|  |  |                      this._messagesMetadata = GetMessagesMetadata();
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -                    this.SocketConnect();
 | 
	
		
			
				|  |  | +                    switch (this.ConnectionInfo.ProxyType)
 | 
	
		
			
				|  |  | +                    {
 | 
	
		
			
				|  |  | +                        case ProxyTypes.None:
 | 
	
		
			
				|  |  | +                            this.SocketConnect(this.ConnectionInfo.Host, this.ConnectionInfo.Port);
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case ProxyTypes.Socks4:
 | 
	
		
			
				|  |  | +                            this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
 | 
	
		
			
				|  |  | +                            this.ConnectSocks4(this._socket);
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        case ProxyTypes.Socks5:
 | 
	
		
			
				|  |  | +                            this.SocketConnect(this.ConnectionInfo.ProxyHost, this.ConnectionInfo.ProxyPort);
 | 
	
		
			
				|  |  | +                            this.ConnectSocks5(this._socket);
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                        default:
 | 
	
		
			
				|  |  | +                            break;
 | 
	
		
			
				|  |  | +                    }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |                      Match versionMatch = null;
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1531,7 +1547,7 @@ namespace Renci.SshNet
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          partial void ExecuteThread(Action action);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | -        partial void SocketConnect();
 | 
	
		
			
				|  |  | +        partial void SocketConnect(string host, int port);
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  |          partial void SocketDisconnect();
 | 
	
		
			
				|  |  |  
 | 
	
	
		
			
				|  | @@ -1572,6 +1588,249 @@ namespace Renci.SshNet
 | 
	
		
			
				|  |  |              }
 | 
	
		
			
				|  |  |          }
 | 
	
		
			
				|  |  |  
 | 
	
		
			
				|  |  | +        private byte SocketReadByte()
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            byte[] buffer = null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            this.SocketRead(1, ref buffer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            return buffer[0];
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private void SocketWriteByte(byte data)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            this.SocketWrite(new byte[] { data });
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private void ConnectSocks4(Socket socket)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            //  Send socks version number
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x04);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send command code
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x01);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send port
 | 
	
		
			
				|  |  | +            this.SocketWriteByte((byte)(this.ConnectionInfo.Port / 0xFF));
 | 
	
		
			
				|  |  | +            this.SocketWriteByte((byte)(this.ConnectionInfo.Port % 0xFF));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send IP
 | 
	
		
			
				|  |  | +            IPAddress ipAddress;
 | 
	
		
			
				|  |  | +#if SILVERLIGHT
 | 
	
		
			
				|  |  | +            if (!IPAddress.TryParse(this.ConnectionInfo.Host, out ipAddress))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new ProxyException("SOCKS4: Silverlight supports only IP addresses.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +            ipAddress = Dns.GetHostAddresses(this.ConnectionInfo.Host).First();
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +            this.SocketWrite(ipAddress.GetAddressBytes());
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send username
 | 
	
		
			
				|  |  | +            var username = new Renci.SshNet.Common.ASCIIEncoding().GetBytes(this.ConnectionInfo.ProxyUsername);
 | 
	
		
			
				|  |  | +            this.SocketWrite(username);
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x00);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read 0
 | 
	
		
			
				|  |  | +            if (this.SocketReadByte() != 0)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new ProxyException("SOCKS4: Null is expected.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read response code
 | 
	
		
			
				|  |  | +            var code = this.SocketReadByte();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            switch (code)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                case 0x5a:
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case 0x5b:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS4: Connection rejected.");
 | 
	
		
			
				|  |  | +                case 0x5c:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS4: Client is not running identd or not reachable from the server.");
 | 
	
		
			
				|  |  | +                case 0x5d:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS4: Client's identd could not confirm the user ID string in the request.");
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS4: Not valid response.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            byte[] dummyBuffer = null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read 2 bytes to be ignored
 | 
	
		
			
				|  |  | +            this.SocketRead(2, ref dummyBuffer);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read 4 bytes to be ignored
 | 
	
		
			
				|  |  | +            this.SocketRead(4, ref dummyBuffer);
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        private void ConnectSocks5(Socket socket)
 | 
	
		
			
				|  |  | +        {
 | 
	
		
			
				|  |  | +            //  Send socks version number
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x05);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send number of supported authentication methods
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x02);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send supported authentication methods
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x00); //  No authentication
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x02); //  Username/Password
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var socksVersion = this.SocketReadByte();
 | 
	
		
			
				|  |  | +            if (socksVersion != 0x05)
 | 
	
		
			
				|  |  | +                throw new ProxyException(string.Format("SOCKS Version '{0}' is not supported.", socksVersion));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var authenticationMethod = this.SocketReadByte();
 | 
	
		
			
				|  |  | +            switch (authenticationMethod)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                case 0x00:
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case 0x02:
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    //  Send version
 | 
	
		
			
				|  |  | +                    this.SocketWriteByte(0x01);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var encoding = new Renci.SshNet.Common.ASCIIEncoding();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var username = encoding.GetBytes(this.ConnectionInfo.ProxyUsername);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (username.Length > byte.MaxValue)
 | 
	
		
			
				|  |  | +                        throw new ProxyException("Proxy username is too long.");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    //  Send username length
 | 
	
		
			
				|  |  | +                    this.SocketWriteByte((byte)username.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    //  Send username
 | 
	
		
			
				|  |  | +                    this.SocketWrite(username);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var password = encoding.GetBytes(this.ConnectionInfo.ProxyPassword);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (password.Length > byte.MaxValue)
 | 
	
		
			
				|  |  | +                        throw new ProxyException("Proxy password is too long.");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    //  Send username length
 | 
	
		
			
				|  |  | +                    this.SocketWriteByte((byte)password.Length);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    //  Send username
 | 
	
		
			
				|  |  | +                    this.SocketWrite(password);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var serverVersion = this.SocketReadByte();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    if (serverVersion != 1)
 | 
	
		
			
				|  |  | +                        throw new ProxyException("SOCKS5: Server authentication version is not valid.");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    var statusCode = this.SocketReadByte();
 | 
	
		
			
				|  |  | +                    if (statusCode != 0)
 | 
	
		
			
				|  |  | +                        throw new ProxyException("SOCKS5: Username/Password authentication failed.");
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case 0xFF:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: No acceptable authentication methods were offered.");
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send socks version number
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x05);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send command code
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x01); //  establish a TCP/IP stream connection
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send reserved, must be 0x00
 | 
	
		
			
				|  |  | +            this.SocketWriteByte(0x00);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            IPAddress ip;
 | 
	
		
			
				|  |  | +#if SILVERLIGHT
 | 
	
		
			
				|  |  | +            if (!IPAddress.TryParse(this.ConnectionInfo.Host, out ip))
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new ProxyException("SOCKS4: Silverlight supports only IP addresses.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +#else
 | 
	
		
			
				|  |  | +            ip = Dns.GetHostAddresses(this.ConnectionInfo.Host).First();
 | 
	
		
			
				|  |  | +#endif
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send address type and address
 | 
	
		
			
				|  |  | +            if (ip.AddressFamily == AddressFamily.InterNetwork)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                this.SocketWriteByte(0x01);
 | 
	
		
			
				|  |  | +                var address = ip.GetAddressBytes();
 | 
	
		
			
				|  |  | +                this.SocketWrite(address);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else if (ip.AddressFamily == AddressFamily.InterNetworkV6)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                this.SocketWriteByte(0x04);
 | 
	
		
			
				|  |  | +                var address = ip.GetAddressBytes();
 | 
	
		
			
				|  |  | +                this.SocketWrite(address);
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +            else
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new ProxyException(string.Format("SOCKS5: IP address '{0}' is not supported.", ip));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Send port
 | 
	
		
			
				|  |  | +            this.SocketWriteByte((byte)(this.ConnectionInfo.Port / 0xFF));
 | 
	
		
			
				|  |  | +            this.SocketWriteByte((byte)(this.ConnectionInfo.Port % 0xFF));
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read Server SOCKS5 version
 | 
	
		
			
				|  |  | +            if (this.SocketReadByte() != 5)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new ProxyException("SOCKS5: Version 5 is expected.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read response code
 | 
	
		
			
				|  |  | +            var status = this.SocketReadByte();
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            switch (status)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                case 0x00:
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case 0x01:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: General failure.");
 | 
	
		
			
				|  |  | +                case 0x02:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: Connection not allowed by ruleset.");
 | 
	
		
			
				|  |  | +                case 0x03:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: Network unreachable.");
 | 
	
		
			
				|  |  | +                case 0x04:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: Host unreachable.");
 | 
	
		
			
				|  |  | +                case 0x05:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: Connection refused by destination host.");
 | 
	
		
			
				|  |  | +                case 0x06:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: TTL expired.");
 | 
	
		
			
				|  |  | +                case 0x07:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: Command not supported or protocol error.");
 | 
	
		
			
				|  |  | +                case 0x08:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS5: Address type not supported.");
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    throw new ProxyException("SOCKS4: Not valid response.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read 0
 | 
	
		
			
				|  |  | +            if (this.SocketReadByte() != 0)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                throw new ProxyException("SOCKS5: 0 byte is expected.");
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            var addressType = this.SocketReadByte();
 | 
	
		
			
				|  |  | +            byte[] responseIp = null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            switch (addressType)
 | 
	
		
			
				|  |  | +            {
 | 
	
		
			
				|  |  | +                case 0x01:
 | 
	
		
			
				|  |  | +                    this.SocketRead(4, ref responseIp);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                case 0x04:
 | 
	
		
			
				|  |  | +                    this.SocketRead(16, ref responseIp);
 | 
	
		
			
				|  |  | +                    break;
 | 
	
		
			
				|  |  | +                default:
 | 
	
		
			
				|  |  | +                    throw new ProxyException(string.Format("Address type '{0}' is not supported.", addressType));
 | 
	
		
			
				|  |  | +            }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            byte[] port = null;
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +            //  Read 2 bytes to be ignored
 | 
	
		
			
				|  |  | +            this.SocketRead(2, ref port);
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  | +        }
 | 
	
		
			
				|  |  | +
 | 
	
		
			
				|  |  |          /// <summary>
 | 
	
		
			
				|  |  |          /// Raises the <see cref="ErrorOccured"/> event.
 | 
	
		
			
				|  |  |          /// </summary>
 |