public static bool TryCreate(out IWebProxy proxy) { // This will get basic proxy setting from system using existing // WinInetProxyHelper functions. If no proxy is enabled, it will return null. SafeWinHttpHandle sessionHandle = null; proxy = null; WinInetProxyHelper proxyHelper = new WinInetProxyHelper(); if (!proxyHelper.ManualSettingsOnly && !proxyHelper.AutoSettingsUsed) { return(false); } if (proxyHelper.AutoSettingsUsed) { sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, Interop.WinHttp.WINHTTP_NO_PROXY_NAME, Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); if (sessionHandle.IsInvalid) { // Proxy failures are currently ignored by managed handler. return(false); } } proxy = new HttpSystemProxy(proxyHelper, sessionHandle); return(true); }
private HttpSystemProxy(WinInetProxyHelper proxyHelper, SafeWinHttpHandle sessionHandle) { _proxyHelper = proxyHelper; _sessionHandle = sessionHandle; if (proxyHelper.ManualSettingsOnly) { _proxyUri = GetUriFromString(proxyHelper.Proxy); if (!string.IsNullOrWhiteSpace(proxyHelper.ProxyBypass)) { // Process bypass list for manual setting. string[] list = proxyHelper.ProxyBypass.Split(';'); List <string> tmpList = new List <string>(); foreach (string value in list) { string tmp = value.Trim(); if (tmp == "<local>") { _bypassLocal = true; continue; } if (tmp.Length > 0) { tmpList.Add(tmp); } } if (tmpList.Count > 0) { _bypass = tmpList.ToArray(); } } } }
public static bool TryCreate([NotNullWhen(true)] out IWebProxy?proxy) { // This will get basic proxy setting from system using existing // WinInetProxyHelper functions. If no proxy is enabled, it will return null. SafeWinHttpHandle?sessionHandle = null; proxy = null; WinInetProxyHelper proxyHelper = new WinInetProxyHelper(); if (!proxyHelper.ManualSettingsOnly && !proxyHelper.AutoSettingsUsed) { return(false); } if (proxyHelper.AutoSettingsUsed) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(proxyHelper, $"AutoSettingsUsed, calling {nameof(Interop.WinHttp.WinHttpOpen)}"); } sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, Interop.WinHttp.WINHTTP_NO_PROXY_NAME, Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); if (sessionHandle.IsInvalid) { // Proxy failures are currently ignored by managed handler. if (NetEventSource.Log.IsEnabled()) { NetEventSource.Error(proxyHelper, $"{nameof(Interop.WinHttp.WinHttpOpen)} returned invalid handle"); } sessionHandle.Dispose(); return(false); } } proxy = new HttpWindowsProxy(proxyHelper, sessionHandle); return(true); }
private void EnsureSessionHandleExists(RequestState state) { if (_sessionHandle == null) { lock (_lockObject) { if (_sessionHandle == null) { uint accessType; // If a custom proxy is specified and it is really the system web proxy // (initial WebRequest.DefaultWebProxy) then we need to update the settings // since that object is only a sentinel. if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy) { Debug.Assert(state.Proxy != null); try { state.Proxy.GetProxy(state.RequestMessage.RequestUri); } catch (PlatformNotSupportedException) { // This is the system web proxy. state.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy; state.Proxy = null; } } if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.DoNotUseProxy || state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy) { // Either no proxy at all or a custom IWebProxy proxy is specified. // For a custom IWebProxy, we'll need to calculate and set the proxy // on a per request handle basis using the request Uri. For now, // we set the session handle to have no proxy. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY; } else if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinHttpProxy) { // Use WinHTTP per-machine proxy settings which are set using the "netsh winhttp" command. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; } else { // Use WinInet per-user proxy settings. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; } _sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, accessType, Interop.WinHttp.WINHTTP_NO_PROXY_NAME, Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, 0); if (!_sessionHandle.IsInvalid) { return; } int lastError = Marshal.GetLastWin32Error(); if (lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER) { throw new HttpRequestException( SR.net_http_client_execution_error, WinHttpException.CreateExceptionUsingError(lastError)); } // We must be running on a platform earlier than Win8.1/Win2K12R2 which doesn't support // WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY. So, we'll need to read the Wininet style proxy // settings ourself using our WinInetProxyHelper object. _proxyHelper = new WinInetProxyHelper(); _sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, _proxyHelper.ManualSettingsOnly ? Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY : Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, _proxyHelper.ManualSettingsOnly ? _proxyHelper.Proxy : Interop.WinHttp.WINHTTP_NO_PROXY_NAME, _proxyHelper.ManualSettingsOnly ? _proxyHelper.ProxyBypass : Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, 0); if (_sessionHandle.IsInvalid) { throw new HttpRequestException( SR.net_http_client_execution_error, WinHttpException.CreateExceptionUsingLastError()); } } } } }
private HttpSystemProxy(WinInetProxyHelper proxyHelper, SafeWinHttpHandle sessionHandle) { _proxyHelper = proxyHelper; _sessionHandle = sessionHandle; if (proxyHelper.ManualSettingsOnly) { ParseProxyConfig(proxyHelper.Proxy, out _insecureProxyUri, out _secureProxyUri); if (!string.IsNullOrWhiteSpace(proxyHelper.ProxyBypass)) { int idx = 0; int start = 0; string tmp; // Process bypass list for manual setting. // Initial list size is best guess based on string length assuming each entry is at least 5 characters on average. _bypass = new List <Regex>(proxyHelper.ProxyBypass.Length / 5); while (idx < proxyHelper.ProxyBypass.Length) { // Strip leading spaces and scheme if any. while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == ' ') { idx += 1; } ; if (string.Compare(proxyHelper.ProxyBypass, idx, "http://", 0, 7, StringComparison.OrdinalIgnoreCase) == 0) { idx += 7; } else if (string.Compare(proxyHelper.ProxyBypass, idx, "https://", 0, 8, StringComparison.OrdinalIgnoreCase) == 0) { idx += 8; } if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == '[') { // Strip [] from IPv6 so we can use IdnHost laster for matching. idx += 1; } start = idx; while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ' ' && proxyHelper.ProxyBypass[idx] != ';' && proxyHelper.ProxyBypass[idx] != ']') { idx += 1; } ; if (idx == start) { // Empty string. tmp = null; } else if (string.Compare(proxyHelper.ProxyBypass, start, "<local>", 0, 7, StringComparison.OrdinalIgnoreCase) == 0) { _bypassLocal = true; tmp = null; } else { tmp = proxyHelper.ProxyBypass.Substring(start, idx - start); } // Skip trailing characters if any. if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ';') { // Got stopped at space or ']'. Strip until next ';' or end. while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ';') { idx += 1; } ; } if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == ';') { idx++; } if (tmp == null) { continue; } try { // Escape any special characters and unescape * to get wildcard pattern match. Regex re = new Regex(Regex.Escape(tmp).Replace("\\*", ".*?") + "$", RegexOptions.Compiled | RegexOptions.IgnoreCase | RegexOptions.CultureInvariant); _bypass.Add(re); } catch { if (NetEventSource.IsEnabled) { NetEventSource.Info(this, "Failed to process " + tmp + " from bypass list."); } } } if (_bypass.Count == 0) { // Bypass string only had garbage we did not parse. _bypass = null; } } if (_bypassLocal) { _localIp = new List <IPAddress>(); foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) { IPInterfaceProperties ipProps = netInterface.GetIPProperties(); foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) { _localIp.Add(addr.Address); } } } } }
private void EnsureSessionHandleExists(WinHttpRequestState state) { if (_sessionHandle == null) { lock (_lockObject) { if (_sessionHandle == null) { uint accessType; // If a custom proxy is specified and it is really the system web proxy // (initial WebRequest.DefaultWebProxy) then we need to update the settings // since that object is only a sentinel. if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy) { Debug.Assert(state.Proxy != null); try { state.Proxy.GetProxy(state.RequestMessage.RequestUri); } catch (PlatformNotSupportedException) { // This is the system web proxy. state.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy; state.Proxy = null; } } if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.DoNotUseProxy || state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy) { // Either no proxy at all or a custom IWebProxy proxy is specified. // For a custom IWebProxy, we'll need to calculate and set the proxy // on a per request handle basis using the request Uri. For now, // we set the session handle to have no proxy. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY; } else if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinHttpProxy) { // Use WinHTTP per-machine proxy settings which are set using the "netsh winhttp" command. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; } else { // Use WinInet per-user proxy settings. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; } _sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, accessType, Interop.WinHttp.WINHTTP_NO_PROXY_NAME, Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); if (_sessionHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); if (lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER) { ThrowOnInvalidHandle(_sessionHandle); } // We must be running on a platform earlier than Win8.1/Win2K12R2 which doesn't support // WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY. So, we'll need to read the Wininet style proxy // settings ourself using our WinInetProxyHelper object. _proxyHelper = new WinInetProxyHelper(); _sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, _proxyHelper.ManualSettingsOnly ? Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY : Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, _proxyHelper.ManualSettingsOnly ? _proxyHelper.Proxy : Interop.WinHttp.WINHTTP_NO_PROXY_NAME, _proxyHelper.ManualSettingsOnly ? _proxyHelper.ProxyBypass : Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); ThrowOnInvalidHandle(_sessionHandle); } uint optionAssuredNonBlockingTrue = 1; // TRUE if (!Interop.WinHttp.WinHttpSetOption( _sessionHandle, Interop.WinHttp.WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS, ref optionAssuredNonBlockingTrue, (uint)Marshal.SizeOf <uint>())) { // This option is not available on downlevel Windows versions. While it improves // performance, we can ignore the error that the option is not available. int lastError = Marshal.GetLastWin32Error(); if (lastError != Interop.WinHttp.ERROR_WINHTTP_INVALID_OPTION) { throw WinHttpException.CreateExceptionUsingError(lastError); } } } } } }
private void EnsureSessionHandleExists(WinHttpRequestState state) { if (_sessionHandle == null) { lock (_lockObject) { if (_sessionHandle == null) { SafeWinHttpHandle sessionHandle; uint accessType; // If a custom proxy is specified and it is really the system web proxy // (initial WebRequest.DefaultWebProxy) then we need to update the settings // since that object is only a sentinel. if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy) { Debug.Assert(state.Proxy != null); try { state.Proxy.GetProxy(state.RequestMessage.RequestUri); } catch (PlatformNotSupportedException) { // This is the system web proxy. state.WindowsProxyUsePolicy = WindowsProxyUsePolicy.UseWinInetProxy; state.Proxy = null; } } if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.DoNotUseProxy || state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseCustomProxy) { // Either no proxy at all or a custom IWebProxy proxy is specified. // For a custom IWebProxy, we'll need to calculate and set the proxy // on a per request handle basis using the request Uri. For now, // we set the session handle to have no proxy. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY; } else if (state.WindowsProxyUsePolicy == WindowsProxyUsePolicy.UseWinHttpProxy) { // Use WinHTTP per-machine proxy settings which are set using the "netsh winhttp" command. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_DEFAULT_PROXY; } else { // Use WinInet per-user proxy settings. accessType = Interop.WinHttp.WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY; } WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: proxy accessType={0}", accessType); sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, accessType, Interop.WinHttp.WINHTTP_NO_PROXY_NAME, Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); if (sessionHandle.IsInvalid) { int lastError = Marshal.GetLastWin32Error(); WinHttpTraceHelper.Trace("WinHttpHandler.EnsureSessionHandleExists: error={0}", lastError); if (lastError != Interop.WinHttp.ERROR_INVALID_PARAMETER) { ThrowOnInvalidHandle(sessionHandle); } // We must be running on a platform earlier than Win8.1/Win2K12R2 which doesn't support // WINHTTP_ACCESS_TYPE_AUTOMATIC_PROXY. So, we'll need to read the Wininet style proxy // settings ourself using our WinInetProxyHelper object. _proxyHelper = new WinInetProxyHelper(); sessionHandle = Interop.WinHttp.WinHttpOpen( IntPtr.Zero, _proxyHelper.ManualSettingsOnly ? Interop.WinHttp.WINHTTP_ACCESS_TYPE_NAMED_PROXY : Interop.WinHttp.WINHTTP_ACCESS_TYPE_NO_PROXY, _proxyHelper.ManualSettingsOnly ? _proxyHelper.Proxy : Interop.WinHttp.WINHTTP_NO_PROXY_NAME, _proxyHelper.ManualSettingsOnly ? _proxyHelper.ProxyBypass : Interop.WinHttp.WINHTTP_NO_PROXY_BYPASS, (int)Interop.WinHttp.WINHTTP_FLAG_ASYNC); ThrowOnInvalidHandle(sessionHandle); } uint optionAssuredNonBlockingTrue = 1; // TRUE if (!Interop.WinHttp.WinHttpSetOption( sessionHandle, Interop.WinHttp.WINHTTP_OPTION_ASSURED_NON_BLOCKING_CALLBACKS, ref optionAssuredNonBlockingTrue, (uint)Marshal.SizeOf<uint>())) { // This option is not available on downlevel Windows versions. While it improves // performance, we can ignore the error that the option is not available. int lastError = Marshal.GetLastWin32Error(); if (lastError != Interop.WinHttp.ERROR_WINHTTP_INVALID_OPTION) { throw WinHttpException.CreateExceptionUsingError(lastError); } } SetSessionHandleOptions(sessionHandle); _sessionHandle = sessionHandle; } } } }
private HttpWindowsProxy(WinInetProxyHelper proxyHelper, SafeWinHttpHandle?sessionHandle) { _proxyHelper = proxyHelper; _sessionHandle = sessionHandle; if (proxyHelper.ManualSettingsUsed) { if (NetEventSource.Log.IsEnabled()) { NetEventSource.Info(proxyHelper, $"ManualSettingsUsed, {proxyHelper.Proxy}"); } _secureProxy = MultiProxy.Parse(_failedProxies, proxyHelper.Proxy, true); _insecureProxy = MultiProxy.Parse(_failedProxies, proxyHelper.Proxy, false); if (!string.IsNullOrWhiteSpace(proxyHelper.ProxyBypass)) { int idx = 0; string?tmp; // Process bypass list for manual setting. // Initial list size is best guess based on string length assuming each entry is at least 5 characters on average. _bypass = new List <string>(proxyHelper.ProxyBypass.Length / 5); while (idx < proxyHelper.ProxyBypass.Length) { // Strip leading spaces and scheme if any. while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == ' ') { idx += 1; } ; if (string.Compare(proxyHelper.ProxyBypass, idx, "http://", 0, 7, StringComparison.OrdinalIgnoreCase) == 0) { idx += 7; } else if (string.Compare(proxyHelper.ProxyBypass, idx, "https://", 0, 8, StringComparison.OrdinalIgnoreCase) == 0) { idx += 8; } if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == '[') { // Strip [] from IPv6 so we can use IdnHost laster for matching. idx += 1; } int start = idx; while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ' ' && proxyHelper.ProxyBypass[idx] != ';' && proxyHelper.ProxyBypass[idx] != ']') { idx += 1; } ; if (idx == start) { // Empty string. tmp = null; } else if (string.Compare(proxyHelper.ProxyBypass, start, "<local>", 0, 7, StringComparison.OrdinalIgnoreCase) == 0) { _bypassLocal = true; tmp = null; } else { tmp = proxyHelper.ProxyBypass.Substring(start, idx - start); } // Skip trailing characters if any. if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ';') { // Got stopped at space or ']'. Strip until next ';' or end. while (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] != ';') { idx += 1; } ; } if (idx < proxyHelper.ProxyBypass.Length && proxyHelper.ProxyBypass[idx] == ';') { idx++; } if (tmp == null) { continue; } _bypass.Add(tmp); } if (_bypass.Count == 0) { // Bypass string only had garbage we did not parse. _bypass = null; } } if (_bypassLocal) { _localIp = new List <IPAddress>(); foreach (NetworkInterface netInterface in NetworkInterface.GetAllNetworkInterfaces()) { IPInterfaceProperties ipProps = netInterface.GetIPProperties(); foreach (UnicastIPAddressInformation addr in ipProps.UnicastAddresses) { _localIp.Add(addr.Address); } } } } }