예제 #1
0
 public SocksProxyToken(IPAddress address, string hostname, 
     int port, IpClientType clientType, bool ipv6, 
     DataAdapterToStream adapter, int version)
     : base(address, hostname, port, clientType, ipv6)
 {
     Adapter = adapter;
     Version = version;
 }
예제 #2
0
 public HttpProxyToken(string hostname, int port, bool connect, string[] headers, Uri url, DataAdapterToStream adapter)
     : base(null, hostname, port, IpClientType.Tcp, false)
 {
     Connect = connect;
     Headers = headers;
     Url = url;
     Adapter = adapter;
 }
예제 #3
0
            public HttpProxyServerAdapter(DataAdapterToStream stm, HttpRequestHeader initialRequest, Logger logger)
            {
                _stm = stm;
                _writer = new DataWriter(_stm);
                _request = initialRequest;
                _config = new HttpParserConfig();
                _config.StreamBody = true;
                _logger = logger;

                Description = stm.Description;
            }
예제 #4
0
        private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, IEnumerable<KeyDataPair<string>> sendHeaders, DataAdapterToStream stm)
        {
            if (request != null)
            {
                FlushRequest(request);
            }

            HttpResponseDataChunk response = new HttpResponseDataChunk();

            if (_config.Version10Proxy && !version.IsVersionUnknown)
            {
                response.Version = HttpVersion.Version10;
            }
            else
            {
                response.Version = version;
            }

            response.ResponseCode = responseCode;
            response.Message = message;
            response.FinalChunk = true;
            response.Body = new byte[0];

            List<KeyDataPair<string>> headers = new List<KeyDataPair<string>>(sendHeaders);

            headers.Add(new KeyDataPair<string>("X-Proxy-Server", "CANAPE"));

            if (response.Body.Length > 0)
            {
                headers.Add(new KeyDataPair<string>("Content-Type", "text/html"));
            }

            response.Headers = headers.ToArray();

            if (method.Equals("HEAD", StringComparison.OrdinalIgnoreCase))
            {
                response.HeadResponse = true;
            }
            else if (method.Equals("CONNECT", StringComparison.OrdinalIgnoreCase))
            {
                response.ConnectResponse = true;
            }

            response.WriteChunk(new DataWriter(stm));
        }
예제 #5
0
 private void ReturnResponse(HttpRequestHeader request, int responseCode, string message, string method, HttpVersion version, DataAdapterToStream stm)
 {
     ReturnResponse(request, responseCode, message, method, version, new KeyDataPair<string>[0], stm);
 }
예제 #6
0
        private ProxyToken HandleOtherRequest(HttpRequestHeader header, DataAdapterToStream stm, ProxyNetworkService service)
        {
            Uri url;

            if (Uri.TryCreate(header.Path, UriKind.Absolute, out url))
            {
                // Use generic token so filters don't get used
                ProxyToken ret = new ProxyToken();

                ret.State.Add("url", url);
                ret.State.Add("stm", stm);
                ret.State.Add("header", header);

                ret.Client = new HttpProxyDummyClient(this, service);
                ret.Graph = _factory;

                return ret;
            }
            else
            {
                _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidUrl, header.Path);

                // TODO: Put in some decent error codes
                ReturnResponse(null, 400, "Bad Request", header.Method, header.Version, stm);

                return null;
            }
        }
예제 #7
0
        private bool HandleV5Auth(DataAdapterToStream stm)
        {
            int authCount = stm.ReadByte();
            bool foundAuth = false;

            if (authCount > 0)
            {
                byte[] authModes = GeneralUtils.ReadBytes(stm, authCount);
                foreach (byte b in authModes)
                {
                    if (b == 0)
                    {
                        foundAuth = true;
                        break;
                    }
                }
            }

            byte[] ret = new byte[2];

            ret[0] = 5;
            if (foundAuth)
            {
                ret[1] = 0;
            }
            else
            {
                ret[1] = 0xFF;
            }

            stm.Write(ret, 0, ret.Length);

            return foundAuth;
        }
예제 #8
0
        private ProxyToken HandleSocksv4Request(DataAdapterToStream stm)
        {
            SocksProxyToken ret = null;

            int req = stm.ReadByte();
            ushort port = ReadUShort(stm);
            byte[] addrBytes = GeneralUtils.ReadBytes(stm, 4);
            IPAddress addr = new IPAddress(addrBytes);
            string addrName = addr.ToString();

            // Discard username
            ReadZString(stm);

            if ((addrBytes[0] == 0) && (addrBytes[1] == 0) && (addrBytes[2] == 0) && (addrBytes[3] != 0))
            {
                StringBuilder builder = new StringBuilder();
                _logger.LogVerbose(CANAPE.Net.Properties.Resources.SocksProxyServer_V4AUsed);
                addrName = ReadZString(stm);
                addr = null;
            }

            if (req == 1)
            {
                _logger.LogVerbose(CANAPE.Net.Properties.Resources.SocksProxyServer_V4ConnectionLog, addrName, port);
                ret = new SocksProxyToken(addr, addrName, port, IpProxyToken.IpClientType.Tcp, false, stm, 4);
            }

            return ret;
        }
예제 #9
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="adapter"></param>
        /// <param name="globalMeta"></param>
        /// <param name="meta"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public override ProxyToken Accept(IDataAdapter adapter, MetaDictionary meta, MetaDictionary globalMeta, ProxyNetworkService service)
        {
            DataAdapterToStream stm = new DataAdapterToStream(adapter);

            return HandleConnectRequest(stm);
        }
예제 #10
0
        private HttpProxyToken HandleConnect(string host, string[] headers, DataAdapterToStream stm)
        {
            string hostName = null;
            int port = 80;
            string[] connectHeader = host.Split(':');
            HttpProxyToken ret = null;

            if (connectHeader.Length > 0)
            {
                hostName = connectHeader[0];
                if (connectHeader.Length > 1)
                {
                    if (!int.TryParse(connectHeader[1], out port))
                    {
                        _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidConnect, connectHeader[1]);
                        port = 0;
                    }
                }

                if (port > 0)
                {
                    UriBuilder builder = new UriBuilder(GetProbableProtocol(port), hostName);
                    builder.Port = port;

                    ret = new HttpProxyToken(hostName, port, true, headers, builder.Uri, stm);
                }
                else
                {
                    // TODO: Put in some decent error codes
                    ReturnResponse(500, "Server Error", stm);
                }
            }

            return ret;
        }
예제 #11
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="adapter"></param>
        /// <param name="meta"></param>
        /// <param name="globalMeta"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public override ProxyToken Accept(IDataAdapter adapter, MetaDictionary meta, MetaDictionary globalMeta, ProxyNetworkService service)
        {
            ProxyToken token = null;

            if (_config.SslConfig.Enabled)
            {
                IDataAdapter client = null;
                INetworkLayer ssl = new SslNetworkLayer(_config.SslConfig);

                ssl.Negotiate(ref adapter, ref client, null, _logger, null, null,
                      new PropertyBag("Root"), NetworkLayerBinding.Server);
            }

            if (adapter is HttpProxyDataAdapter)
            {
                HttpProxyDataAdapter proxyAdapter = (HttpProxyDataAdapter)adapter;

                token = new FullHttpProxyToken(proxyAdapter.Url.Host, proxyAdapter.Url.Port);

                token.State.Add("adapter", adapter);
            }
            else
            {
                DataAdapterToStream stm = new DataAdapterToStream(adapter);
                DataReader reader = new DataReader(stm);

                try
                {
                    HttpRequestHeader header = HttpParser.ReadRequestHeader(reader, false, _logger);

                    if (HandleProxyAuthentication(reader, stm, ref header))
                    {
                        // We just have a connect
                        if (header.IsConnect)
                        {
                            token = HandleConnect(header, stm);
                        }
                        else
                        {
                            token = HandleOtherRequest(header, stm, service);
                        }
                    }
                }
                catch (HttpStreamParserException ex)
                {
                    _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidRequest, ex.Message);

                    // TODO: Put in some decent error codes
                    ReturnResponse(null, 400, "Bad Request", "GET", HttpVersion.Version11, stm);
                }
                catch (EndOfStreamException)
                {
                    token = null;
                }
            }

            return token;
        }
예제 #12
0
            public HttpProxyServerAdapter(FullHttpProxyServer server, DataAdapterToStream stm, HttpRequestHeader initialRequest, Logger logger)
            {
                _server = server;
                _stm = stm;
                _writer = new DataWriter(_stm);
                _request = initialRequest;
                ProcessProxyRequestHeaders(_request);
                _config = new HttpParserConfig();
                _config.StreamBody = true;
                _logger = logger;
                _requestQueue = new Queue<HttpRequestHeader>();
                _requestQueue.Enqueue(_request);

                Description = stm.Description;
            }
예제 #13
0
        private bool HandleProxyAuthentication(DataReader reader, DataAdapterToStream stm, ref HttpRequestHeader request)
        {
            if (_config.RequireAuth)
            {
                bool auth = ProcessProxyAuth(request);

                if (!auth)
                {
                    ReturnResponse(request, 407, "Proxy Authentication Required", request.Method, request.Version,
                        new KeyDataPair<string>[] { new KeyDataPair<string>("Proxy-Authenticate",
                            String.Format("Basic realm=\"{0}\"", _config.AuthRealm ?? "canape.local")) }, stm);

                    if (!MustCloseConnection(request))
                    {
                        // If version 1.1 server we can assume connection will probably stay up so re-read request
                        // Only give it one chance to get it right though
                        request = HttpParser.ReadRequestHeader(reader, false, _logger);

                        auth = ProcessProxyAuth(request);
                    }
                }

                return auth;
            }
            else
            {
                return true;
            }
        }
예제 #14
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="adapter"></param>
        /// <param name="meta"></param>
        /// <param name="globalMeta"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public override ProxyToken Accept(IDataAdapter adapter, MetaDictionary meta, MetaDictionary globalMeta, ProxyNetworkService service)
        {
            ProxyToken token = null;

            TcpClientDataAdapter tcpAdapter = adapter as TcpClientDataAdapter;

            if (_config.SslConfig.Enabled)
            {
                IDataAdapter client = null;
                INetworkLayer ssl = new SslNetworkLayer(_config.SslConfig);

                ssl.Negotiate(ref adapter, ref client, null, _logger, null, null,
                      new PropertyBag("Root"), NetworkLayerBinding.Server);
            }

            DataAdapterToStream stm = new DataAdapterToStream(adapter);
            DataReader reader = new DataReader(stm);

            try
            {
                HttpRequestHeader header = HttpParser.ReadRequestHeader(reader, false, _logger);

                token = HandleOtherRequest(header, stm, tcpAdapter);
            }
            catch (HttpStreamParserException ex)
            {
                _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidRequest, ex.Message);

                // TODO: Put in some decent error codes
                ReturnResponse(null, 400, "Bad Request", "GET", HttpVersion.Version11, stm);
            }
            catch (EndOfStreamException)
            {
                token = null;
            }

            return token;
        }
예제 #15
0
        private HttpProxyToken HandleOtherRequest(string host, string[] headers, DataAdapterToStream stm)
        {
            Uri url;

            if(Uri.TryCreate(host, UriKind.Absolute, out url))
            {
                return new HttpProxyToken(url.Host, url.Port, false, headers, url, stm);
            }
            else
            {
                _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidUrl, host);

                // TODO: Put in some decent error codes
                ReturnResponse(500, "Server Error", stm);

                return null;
            }
        }
예제 #16
0
        private void CloneCertChain(Uri url, string destination)
        {
            IProxyClientFactory factory = proxyClientControl.Client;

            if (factory == null)
            {
                factory = new IpProxyClientFactory();
            }

            ProxyClient client = factory.Create(new Logger());
            collection = new X509Certificate2Collection();

            using (IDataAdapter adapter = client.Connect(new IpProxyToken(null, url.Host, url.Port, IpProxyToken.IpClientType.Tcp, false),
                new Logger(), new Nodes.MetaDictionary(), new Nodes.MetaDictionary(), new PropertyBag(), new Security.CredentialsManagerService()))
            {
                DataAdapterToStream stm = new DataAdapterToStream(adapter);

                using (SslStream ssl = new SslStream(stm, false, VerifyCallback))
                {
                    ssl.AuthenticateAsClient(url.Host);
                }
            }

            if (collection.Count > 0)
            {
                File.WriteAllBytes(Path.Combine(destination, String.Format("certchain_{0}.pfx", url.Host)), collection.Export(X509ContentType.Pfx));
                int count = 1;

                foreach (X509Certificate2 cert in collection)
                {
                    string path = Path.Combine(destination, String.Format("cert_{0}_{1}.cer", url.Host, count++));

                    File.WriteAllText(path, CertificateUtils.ExportToPEM(cert) +
                        CertificateUtils.ExportToPEM((RSA)cert.PrivateKey, null));
                }
            }
        }
예제 #17
0
 private void ReturnResponse(int no, string description, DataAdapterToStream stm)
 {
     byte[] response = Encoding.ASCII.GetBytes(String.Format("HTTP/1.0 {0} {1}\r\n\r\n", no, description));
     stm.Write(response, 0, response.Length);
 }
예제 #18
0
        private ProxyToken HandleConnectRequest(DataAdapterToStream stm)
        {
            ProxyToken ret = null;
            int version = stm.ReadByte();

            if (IsSupported(version))
            {
                if (version == 4)
                {
                    _logger.LogVerbose(CANAPE.Net.Properties.Resources.SocksProxyServer_NewV4ConnectionLog);
                    ret = HandleSocksv4Request(stm);
                }
                else if (version == 5)
                {
                    _logger.LogVerbose(CANAPE.Net.Properties.Resources.SocksProxyServer_NewV5ConnectionLog);
                    ret = HandleSocksv5Request(stm);
                }
            }
            else
            {
                _logger.LogError(CANAPE.Net.Properties.Resources.SocksProxyServer_UnsupportedVersionLog, version);
            }

            return ret;
        }
예제 #19
0
        /// <summary>
        /// 
        /// </summary>
        /// <param name="adapter"></param>
        /// <param name="globalMeta"></param>
        /// <param name="meta"></param>
        /// <param name="service"></param>
        /// <returns></returns>
        public override ProxyToken Accept(IDataAdapter adapter, MetaDictionary meta, MetaDictionary globalMeta, ProxyNetworkService service)
        {
            HttpProxyToken token = null;

            if (_ssl != null)
            {
                IDataAdapter client = null;

                _ssl.Negotiate(ref adapter, ref client, null, _logger, null, null,
                    new PropertyBag("Root"), NetworkLayerBinding.Server);
            }

            DataAdapterToStream stm = new DataAdapterToStream(adapter);

            List<string> headers = new List<string>();

            // Read out HTTP headers
            try
            {
                while (true)
                {
                    string nextLine = GeneralUtils.ReadLine(stm);

                    headers.Add(nextLine);

                    if (nextLine.Trim('\r', '\n').Length == 0)
                    {
                        break;
                    }
                }
            }
            catch (EndOfStreamException)
            {
                // Pass on the exception if we got killed half way through
                if (headers.Count > 0)
                {
                    throw;
                }
            }

            if (headers.Count > 0)
            {
                string[] reqValues = headers[0].Trim().Split(new char[] { ' ' }, StringSplitOptions.RemoveEmptyEntries);

                // Check it at least has a VERB and a PATH
                if (reqValues.Length > 1)
                {
                    if (reqValues[0].Equals("CONNECT", StringComparison.OrdinalIgnoreCase))
                    {
                        token = HandleConnect(reqValues[1], headers.ToArray(), stm);
                    }
                    else
                    {
                        token = HandleOtherRequest(reqValues[1], headers.ToArray(), stm);
                    }
                }
                else
                {
                    _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidRequest, headers[0]);

                    // TODO: Put in some decent error codes
                    ReturnResponse(500, "Server Error", stm);
                }
            }

            return token;
        }
예제 #20
0
        private ProxyToken HandleSocksv5Request(DataAdapterToStream stm)
        {
            if (HandleV5Auth(stm))
            {
                return HandleV5RequestData(stm);
            }

            return null;
        }
예제 #21
0
        private ProxyToken HandleOtherRequest(HttpRequestHeader header, DataAdapterToStream stm, TcpClientDataAdapter tcpAdapter)
        {
            string host = null;

            foreach (KeyDataPair<string> pair in header.Headers)
            {
                if (pair.Name.Equals("host", StringComparison.OrdinalIgnoreCase))
                {
                    host = pair.Value;
                }
            }

            Uri url = GetUri(host, tcpAdapter);

            if (url != null)
            {
                // Use generic token so filters don't get used
                IpProxyToken ret = new IpProxyToken(null, url.Host, url.Port, IpProxyToken.IpClientType.Tcp, false);

                if(_config.SslConfig.Enabled)
                {
                    ret.Layers = new INetworkLayer[1];
                    ret.Layers[0] = new SslNetworkLayer(new SslNetworkLayerConfig(false, true) { Enabled = true });
                }

                ret.State.Add("url", url);
                ret.State.Add("stm", stm);
                ret.State.Add("header", header);

                return ret;
            }
            else
            {
                _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidUrl, header.Path);

                ReturnResponse(null, 400, "Bad Request", header.Method, header.Version, stm);

                return null;
            }
        }
예제 #22
0
        private ProxyToken HandleV5RequestData(DataAdapterToStream stm)
        {
            SocksProxyToken ret = null;
            IPAddress addr = null;
            string addrName = null;
            bool ipv6 = false;
            ushort port = 0;

            int ver = stm.ReadByte();
            int code = stm.ReadByte();
            stm.ReadByte(); // Reserved
            int type = stm.ReadByte();

            if ((ver == 5) && (code == 1))
            {
                byte[] data = null;

                switch (type)
                {
                    case 1: // IPv4
                        {
                            data = GeneralUtils.ReadBytes(stm, 4);
                            addr = new IPAddress(data);
                            addrName = addr.ToString();
                        }
                        break;
                    case 3: // Domain name
                        {
                            int nameLen = stm.ReadByte();
                            if (nameLen > 0)
                            {
                                data = GeneralUtils.ReadBytes(stm, nameLen);
                                addrName = Encoding.ASCII.GetString(data);
                            }
                        }
                        break;
                    case 4: // IPv6
                        data = GeneralUtils.ReadBytes(stm, 16);
                        addr = new IPAddress(data);
                        addrName = addr.ToString();
                        ipv6 = true;
                        break;
                    default:
                        break;
                }

                port = ReadUShort(stm);

                if ((addrName != null) && (port > 0))
                {
                    _logger.LogVerbose(CANAPE.Net.Properties.Resources.SocksProxyServer_V5ConnectionLog, addrName, port);
                    ret = new SocksProxyToken(addr, addrName, port, IpProxyToken.IpClientType.Tcp, ipv6, stm, 5);
                }
            }

            return ret;
        }
예제 #23
0
        private IpProxyToken HandleConnect(HttpRequestHeader header, DataAdapterToStream stm)
        {
            string hostName = null;
            int port = 80;
            string[] connectHeader = header.Path.Split(':');
            IpProxyToken ret = null;

            if (connectHeader.Length > 0)
            {
                hostName = connectHeader[0];
                if (connectHeader.Length > 1)
                {
                    if (!int.TryParse(connectHeader[1], out port))
                    {
                        _logger.LogError(CANAPE.Net.Properties.Resources.HttpProxyServer_InvalidConnect, connectHeader[1]);
                        port = 0;
                    }
                }

                if (port > 0)
                {
                    ret = new IpProxyToken(null, hostName, port, IpProxyToken.IpClientType.Tcp, false);

                    ret.State.Add("stm", stm);
                    ret.State.Add("header", header);
                }
                else
                {
                    ReturnResponse(null, 400, "Bad Request", header.Method, header.Version, stm);
                }
            }

            return ret;
        }