Ejemplo n.º 1
0
        private async Task <HttpResponseMessage> SendWithProxyAsync(
            Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (proxyUri.Scheme != UriScheme.Http)
            {
                throw new InvalidOperationException(SR.net_http_invalid_proxy_scheme);
            }

            HttpResponseMessage response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false);

            // Handle proxy authentication
            if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired)
            {
                foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate)
                {
                    if (h.Scheme == AuthenticationHelper.Basic)
                    {
                        NetworkCredential credential =
                            _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Basic) ??
                            _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Basic);

                        if (credential != null)
                        {
                            // TODO #23156: Drain response before disposing.
                            response.Dispose();

                            request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(AuthenticationHelper.Basic,
                                                                                               AuthenticationHelper.GetBasicTokenForCredential(credential));

                            response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false);
                        }

                        break;
                    }
                    else if (h.Scheme == AuthenticationHelper.Digest)
                    {
                        NetworkCredential credential =
                            _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Digest) ??
                            _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Digest);

                        if (credential != null)
                        {
                            // Update digest response with new parameter from Proxy-Authenticate
                            AuthenticationHelper.DigestResponse digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter);

                            if (await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false))
                            {
                                // TODO #23156: Drain response before disposing.
                                response.Dispose();
                                response = await GetConnectionAndSendAsync(request, proxyUri, cancellationToken).ConfigureAwait(false);

                                // Retry in case of nonce timeout in server.
                                if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired)
                                {
                                    foreach (AuthenticationHeaderValue ahv in response.Headers.ProxyAuthenticate)
                                    {
                                        if (ahv.Scheme == AuthenticationHelper.Digest)
                                        {
                                            digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter);
                                            if (AuthenticationHelper.IsServerNonceStale(digestResponse) &&
                                                await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false))
                                            {
                                                response.Dispose();
                                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                                            }

                                            break;
                                        }
                                    }
                                }
                            }

                            break;
                        }
                    }
                }
            }

            return(response);
        }
Ejemplo n.º 2
0
        protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (_preAuthenticate)
            {
                // Try using previous digest response WWWAuthenticate header
                if (_digestResponse != null)
                {
                    await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, _digestResponse);
                }
                else
                {
                    AuthenticationHelper.TrySetBasicAuthToken(request, _credentials);
                }
            }

            HttpResponseMessage response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

            if (!_preAuthenticate && response.StatusCode == HttpStatusCode.Unauthorized)
            {
                HttpHeaderValueCollection <AuthenticationHeaderValue> authenticateValues = response.Headers.WwwAuthenticate;

                foreach (AuthenticationHeaderValue h in authenticateValues)
                {
                    // We only support Basic and digest auth, ignore others
                    if (h.Scheme == AuthenticationHelper.Basic)
                    {
                        if (AuthenticationHelper.TrySetBasicAuthToken(request, _credentials))
                        {
                            response.Dispose();
                            response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                            break;
                        }
                    }
                    else if (h.Scheme == AuthenticationHelper.Digest)
                    {
                        // Update digest response with new parameter from WWWAuthenticate
                        _digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter);
                        if (await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, _digestResponse))
                        {
                            response.Dispose();
                            response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                            // Retry in case of nonce timeout in server.
                            if (response.StatusCode == HttpStatusCode.Unauthorized)
                            {
                                foreach (AuthenticationHeaderValue ahv in response.Headers.WwwAuthenticate)
                                {
                                    if (ahv.Scheme == AuthenticationHelper.Digest)
                                    {
                                        _digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter);
                                        string stale;
                                        if (_digestResponse.Parameters.TryGetValue("stale", out stale) && stale == "true" &&
                                            await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, _digestResponse))
                                        {
                                            response.Dispose();
                                            response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                                        }

                                        break;
                                    }
                                }
                            }

                            break;
                        }
                    }
                }
            }

            return(response);
        }
Ejemplo n.º 3
0
        protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (_preAuthenticate)
            {
                AuthenticationHelper.TrySetBasicAuthToken(request, _credentials);
            }

            HttpResponseMessage response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

            if (response.StatusCode == HttpStatusCode.Unauthorized)
            {
                AuthenticationHeaderValue selectedAuth = GetSupportedAuthScheme(response.Headers.WwwAuthenticate);
                if (selectedAuth != null)
                {
                    switch (selectedAuth.Scheme)
                    {
                    case AuthenticationHelper.Digest:
                        // Update digest response with new parameter from WWWAuthenticate
                        var digestResponse = new AuthenticationHelper.DigestResponse(selectedAuth.Parameter);
                        if (await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false))
                        {
                            response.Dispose();
                            response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                            // Retry in case of nonce timeout in server.
                            if (response.StatusCode == HttpStatusCode.Unauthorized)
                            {
                                foreach (AuthenticationHeaderValue ahv in response.Headers.WwwAuthenticate)
                                {
                                    if (ahv.Scheme == AuthenticationHelper.Digest)
                                    {
                                        digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter);
                                        if (AuthenticationHelper.IsServerNonceStale(digestResponse) &&
                                            await AuthenticationHelper.TrySetDigestAuthToken(request, _credentials, digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false))
                                        {
                                            response.Dispose();
                                            response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                                        }

                                        break;
                                    }
                                }
                            }
                        }
                        break;

                    case AuthenticationHelper.Basic:
                        if (_preAuthenticate)
                        {
                            // We already tried these credentials via preauthentication, so no need to try again
                            break;
                        }

                        if (AuthenticationHelper.TrySetBasicAuthToken(request, _credentials))
                        {
                            response.Dispose();
                            response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                        }
                        break;
                    }
                }
            }

            return(response);
        }
Ejemplo n.º 4
0
        private async Task <HttpResponseMessage> SendWithProxyAsync(
            Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (proxyUri.Scheme != UriScheme.Http)
            {
                throw new InvalidOperationException(SR.net_http_invalid_proxy_scheme);
            }

            if (!HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme))
            {
                // TODO #23136: Implement SSL tunneling through proxy
                throw new NotImplementedException("no support for SSL tunneling through proxy");
            }

            HttpConnection connection = await GetOrCreateConnection(request, proxyUri).ConfigureAwait(false);

            HttpResponseMessage response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false);

            // Handle proxy authentication
            if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired)
            {
                foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate)
                {
                    // We only support Basic auth, ignore others
                    if (h.Scheme == AuthenticationHelper.Basic)
                    {
                        NetworkCredential credential =
                            _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Basic) ??
                            _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Basic);

                        if (credential != null)
                        {
                            response.Dispose();

                            request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(AuthenticationHelper.Basic,
                                                                                               AuthenticationHelper.GetBasicTokenForCredential(credential));

                            connection = await GetOrCreateConnection(request, proxyUri).ConfigureAwait(false);

                            response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false);
                        }

                        break;
                    }
                    else if (h.Scheme == AuthenticationHelper.Digest)
                    {
                        NetworkCredential credential =
                            _proxy.Credentials?.GetCredential(proxyUri, AuthenticationHelper.Digest) ??
                            _defaultCredentials?.GetCredential(proxyUri, AuthenticationHelper.Digest);

                        if (credential != null)
                        {
                            // Update digest response with new parameter from Proxy-Authenticate
                            AuthenticationHelper.DigestResponse digestResponse = new AuthenticationHelper.DigestResponse(h.Parameter);

                            if (await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false))
                            {
                                response.Dispose();
                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                                // Retry in case of nonce timeout in server.
                                if (response.StatusCode == HttpStatusCode.Unauthorized)
                                {
                                    foreach (AuthenticationHeaderValue ahv in response.Headers.ProxyAuthenticate)
                                    {
                                        if (ahv.Scheme == AuthenticationHelper.Digest)
                                        {
                                            digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter);
                                            if (AuthenticationHelper.IsServerNonceStale(digestResponse) &&
                                                await AuthenticationHelper.TrySetDigestAuthToken(request, credential, digestResponse, HttpKnownHeaderNames.ProxyAuthorization).ConfigureAwait(false))
                                            {
                                                response.Dispose();
                                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                                            }

                                            break;
                                        }
                                    }
                                }
                            }

                            break;
                        }
                    }
                }
            }

            return(response);
        }
Ejemplo n.º 5
0
        private async Task <HttpResponseMessage> SendWithProxyAsync(
            Uri proxyUri, HttpRequestMessage request, CancellationToken cancellationToken)
        {
            if (proxyUri.Scheme != UriScheme.Http)
            {
                throw new InvalidOperationException($"invalid scheme {proxyUri.Scheme} for proxy");
            }

            if (request.RequestUri.Scheme == UriScheme.Https)
            {
                // TODO #21452: Implement SSL tunneling through proxy
                throw new NotImplementedException("no support for SSL tunneling through proxy");
            }

            HttpConnection connection = await GetOrCreateConnection(request, proxyUri).ConfigureAwait(false);

            HttpResponseMessage response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false);

            // Handle proxy authentication
            if (response.StatusCode == HttpStatusCode.ProxyAuthenticationRequired)
            {
                foreach (AuthenticationHeaderValue h in response.Headers.ProxyAuthenticate)
                {
                    // We only support Basic auth, ignore others
                    const string Basic = "Basic";
                    if (h.Scheme == Basic)
                    {
                        NetworkCredential credential =
                            _proxy.Credentials?.GetCredential(proxyUri, Basic) ??
                            _defaultCredentials?.GetCredential(proxyUri, Basic);

                        if (credential != null)
                        {
                            response.Dispose();

                            request.Headers.ProxyAuthorization = new AuthenticationHeaderValue(Basic,
                                                                                               AuthenticationHelper.GetBasicTokenForCredential(credential));

                            connection = await GetOrCreateConnection(request, proxyUri).ConfigureAwait(false);

                            response = await connection.SendAsync(request, cancellationToken).ConfigureAwait(false);
                        }

                        break;
                    }
                }
            }

            return(response);
        }
Ejemplo n.º 6
0
        protected internal override async Task <HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
        {
            HttpResponseMessage response;
            uint redirectCount = 0;

            while (true)
            {
                // Just as with WinHttpHandler and CurlHandler, for security reasons, we drop the server credential if it is
                // anything other than a CredentialCache on redirection. We allow credentials in a CredentialCache since they
                // are specifically tied to URIs.
                ICredentials currentCredential = redirectCount > 0 ? _credentials as CredentialCache : _credentials;

                if (currentCredential != null && _preAuthenticate)
                {
                    AuthenticationHelper.TrySetBasicAuthToken(request, currentCredential);
                }

                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                if (currentCredential != null && response.StatusCode == HttpStatusCode.Unauthorized)
                {
                    AuthenticationHeaderValue selectedAuth = GetSupportedAuthScheme(response.Headers.WwwAuthenticate);
                    if (selectedAuth != null)
                    {
                        switch (selectedAuth.Scheme)
                        {
                        case AuthenticationHelper.Digest:
                            // Update digest response with new parameter from WWWAuthenticate
                            var digestResponse = new AuthenticationHelper.DigestResponse(selectedAuth.Parameter);
                            if (await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false))
                            {
                                response.Dispose();
                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);

                                // Retry in case of nonce timeout in server.
                                if (response.StatusCode == HttpStatusCode.Unauthorized)
                                {
                                    foreach (AuthenticationHeaderValue ahv in response.Headers.WwwAuthenticate)
                                    {
                                        if (ahv.Scheme == AuthenticationHelper.Digest)
                                        {
                                            digestResponse = new AuthenticationHelper.DigestResponse(ahv.Parameter);
                                            if (AuthenticationHelper.IsServerNonceStale(digestResponse) &&
                                                await AuthenticationHelper.TrySetDigestAuthToken(request, currentCredential, digestResponse, HttpKnownHeaderNames.Authorization).ConfigureAwait(false))
                                            {
                                                response.Dispose();
                                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                                            }

                                            break;
                                        }
                                    }
                                }
                            }
                            break;

                        case AuthenticationHelper.Basic:
                            if (_preAuthenticate)
                            {
                                // We already tried these credentials via preauthentication, so no need to try again
                                break;
                            }

                            if (AuthenticationHelper.TrySetBasicAuthToken(request, currentCredential))
                            {
                                response.Dispose();
                                response = await _innerHandler.SendAsync(request, cancellationToken).ConfigureAwait(false);
                            }
                            break;
                        }
                    }
                }

                if (!RequestNeedsRedirect(response))
                {
                    break;
                }

                // Clear the authorization header, if the request requires redirect.
                request.Headers.Authorization = null;

                Uri location = response.Headers.Location;
                if (location == null)
                {
                    // No location header. Nothing to redirect to.
                    break;
                }

                if (!location.IsAbsoluteUri)
                {
                    location = new Uri(request.RequestUri, location);
                }

                // Disallow automatic redirection from secure to non-secure schemes
                bool allowed =
                    (HttpUtilities.IsSupportedNonSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedScheme(location.Scheme)) ||
                    (HttpUtilities.IsSupportedSecureScheme(request.RequestUri.Scheme) && HttpUtilities.IsSupportedSecureScheme(location.Scheme));
                if (!allowed)
                {
                    if (NetEventSource.IsEnabled)
                    {
                        NetEventSource.Info(this, $"Insecure https to http redirect from {request.RequestUri} to {location} blocked.");
                    }
                    break;
                }

                redirectCount++;
                if (redirectCount > _maxAutomaticRedirections)
                {
                    throw new HttpRequestException(SR.net_http_max_redirects);
                }

                // Set up for the automatic redirect
                request.RequestUri = location;

                if (RequestRequiresForceGet(response.StatusCode, request.Method))
                {
                    request.Method  = HttpMethod.Get;
                    request.Content = null;
                }

                // Do the redirect.
                response.Dispose();
            }

            return(response);
        }