Ejemplo n.º 1
0
        private static async ValueTask <bool> TrySetDigestAuthToken(HttpRequestMessage request, NetworkCredential credential, DigestResponse digestResponse, bool isProxyAuth)
        {
            string?parameter = await GetDigestTokenForCredential(credential, request, digestResponse).ConfigureAwait(false);

            // Any errors in obtaining parameter return false and we don't proceed with auth
            if (string.IsNullOrEmpty(parameter))
            {
                if (NetEventSource.IsEnabled)
                {
                    NetEventSource.AuthenticationError(request.RequestUri, $"Unable to find 'Digest' authentication token when authenticating with {(isProxyAuth ? "proxy" : "server")}");
                }
                return(false);
            }

            var headerValue = new AuthenticationHeaderValue(DigestScheme, parameter);

            SetRequestAuthenticationHeaderValue(request, headerValue, isProxyAuth);
            return(true);
        }
Ejemplo n.º 2
0
        private static async ValueTask <HttpResponseMessage> SendWithAuthAsync(HttpRequestMessage request, Uri authUri, bool async, ICredentials credentials, bool preAuthenticate, bool isProxyAuth, bool doRequestAuth, HttpConnectionPool pool, CancellationToken cancellationToken)
        {
            // If preauth is enabled and this isn't proxy auth, try to get a basic credential from the
            // preauth credentials cache, and if successful, set an auth header for it onto the request.
            // Currently we only support preauth for Basic.
            bool performedBasicPreauth = false;

            if (preAuthenticate)
            {
                Debug.Assert(pool.PreAuthCredentials != null);
                NetworkCredential?credential;
                lock (pool.PreAuthCredentials)
                {
                    // Just look for basic credentials.  If in the future we support preauth
                    // for other schemes, this will need to search in order of precedence.
                    Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, NegotiateScheme) == null);
                    Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, NtlmScheme) == null);
                    Debug.Assert(pool.PreAuthCredentials.GetCredential(authUri, DigestScheme) == null);
                    credential = pool.PreAuthCredentials.GetCredential(authUri, BasicScheme);
                }

                if (credential != null)
                {
                    SetBasicAuthToken(request, credential, isProxyAuth);
                    performedBasicPreauth = true;
                }
            }

            HttpResponseMessage response = await InnerSendAsync(request, async, isProxyAuth, doRequestAuth, pool, cancellationToken).ConfigureAwait(false);

            if (TryGetAuthenticationChallenge(response, isProxyAuth, authUri, credentials, out AuthenticationChallenge challenge))
            {
                switch (challenge.AuthenticationType)
                {
                case AuthenticationType.Digest:
                    var digestResponse = new DigestResponse(challenge.ChallengeData);
                    if (await TrySetDigestAuthToken(request, challenge.Credential, digestResponse, isProxyAuth).ConfigureAwait(false))
                    {
                        response.Dispose();
                        response = await InnerSendAsync(request, async, isProxyAuth, doRequestAuth, pool, cancellationToken).ConfigureAwait(false);

                        // Retry in case of nonce timeout in server.
                        if (TryGetRepeatedChallenge(response, challenge.SchemeName, isProxyAuth, out string?challengeData))
                        {
                            digestResponse = new DigestResponse(challengeData);
                            if (IsServerNonceStale(digestResponse) &&
                                await TrySetDigestAuthToken(request, challenge.Credential, digestResponse, isProxyAuth).ConfigureAwait(false))
                            {
                                response.Dispose();
                                response = await InnerSendAsync(request, async, isProxyAuth, doRequestAuth, pool, cancellationToken).ConfigureAwait(false);
                            }
                        }
                    }
                    break;

                case AuthenticationType.Basic:
                    if (performedBasicPreauth)
                    {
                        if (NetEventSource.IsEnabled)
                        {
                            NetEventSource.AuthenticationError(authUri, $"Pre-authentication with {(isProxyAuth ? "proxy" : "server")} failed.");
                        }
                        break;
                    }

                    response.Dispose();
                    SetBasicAuthToken(request, challenge.Credential, isProxyAuth);
                    response = await InnerSendAsync(request, async, isProxyAuth, doRequestAuth, pool, cancellationToken).ConfigureAwait(false);

                    if (preAuthenticate)
                    {
                        switch (response.StatusCode)
                        {
                        case HttpStatusCode.ProxyAuthenticationRequired:
                        case HttpStatusCode.Unauthorized:
                            if (NetEventSource.IsEnabled)
                            {
                                NetEventSource.AuthenticationError(authUri, $"Pre-authentication with {(isProxyAuth ? "proxy" : "server")} failed.");
                            }
                            break;

                        default:
                            lock (pool.PreAuthCredentials !)
                            {
                                try
                                {
                                    if (NetEventSource.IsEnabled)
                                    {
                                        NetEventSource.Info(pool.PreAuthCredentials, $"Adding Basic credential to cache, uri={authUri}, username={challenge.Credential.UserName}");
                                    }
                                    pool.PreAuthCredentials.Add(authUri, BasicScheme, challenge.Credential);
                                }
                                catch (ArgumentException)
                                {
                                    // The credential already existed.
                                    if (NetEventSource.IsEnabled)
                                    {
                                        NetEventSource.Info(pool.PreAuthCredentials, $"Basic credential present in cache, uri={authUri}, username={challenge.Credential.UserName}");
                                    }
                                }
                            }
                            break;
                        }
                    }
                    break;
                }
            }

            if (NetEventSource.IsEnabled && response.StatusCode == HttpStatusCode.Unauthorized)
            {
                NetEventSource.AuthenticationError(authUri, $"{(isProxyAuth ? "Proxy" : "Server")} authentication failed.");
            }

            return(response);
        }