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; }
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; }
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; }
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)); }
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); }
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; } }
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; }
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; }
/// <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); }
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; }
/// <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; }
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; }
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; } }
/// <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; }
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; } }
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)); } } }
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); }
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; }
/// <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; }
private ProxyToken HandleSocksv5Request(DataAdapterToStream stm) { if (HandleV5Auth(stm)) { return HandleV5RequestData(stm); } return null; }
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; } }
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; }
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; }