public Authorization PreAuthenticate(WebRequest webRequest, ICredentials credentials)
        {
            GlobalLog.Print("DigestClient::PreAuthenticate()");

#if XP_WDIGEST
            if (ComNetOS.IsPostWin2K)
            {
                return(XPDigestClient.PreAuthenticate(webRequest, credentials));
            }
#endif // #if XP_WDIGEST

            GlobalLog.Assert(credentials != null, "DigestClient::PreAuthenticate() credentials==null", "");
            if (credentials == null || credentials is SystemNetworkCredential)
            {
                return(null);
            }

            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;
            GlobalLog.Assert(httpWebRequest != null, "DigestClient::PreAuthenticate() httpWebRequest==null", "");
            if (httpWebRequest == null)
            {
                return(null);
            }

            HttpDigestChallenge storedHDC = (HttpDigestChallenge)challengeCache.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri);
            if (storedHDC == null)
            {
                return(null);
            }

            HttpDigestChallenge modifiedHDC = storedHDC.CopyAndIncrementNonce();
            modifiedHDC.HostName = httpWebRequest.ChallengedUri.Host;
            modifiedHDC.Method   = httpWebRequest.CurrentMethod;
            // Consider:
            // I have also tried PathAndQuery against both IIS 5.0 and IIS 6.0 servers.
            // it didn't make a difference. PathAndQuery is a more complete piece of information
            // investigate with Kevin Damour if WDigest.dll wants the quesry string or not.
            modifiedHDC.Uri           = httpWebRequest.Address.AbsolutePath;
            modifiedHDC.ChallengedUri = httpWebRequest.ChallengedUri;

            Authorization digestResponse = HttpDigest.Authenticate(modifiedHDC, credentials);

            return(digestResponse);
        }
        public Authorization Authenticate(string challenge, WebRequest webRequest, ICredentials credentials)
        {
            GlobalLog.Print("DigestClient::Authenticate(): " + challenge);

#if XP_WDIGEST
            if (ComNetOS.IsPostWin2K)
            {
                return(XPDigestClient.Authenticate(challenge, webRequest, credentials));
            }
#endif // #if XP_WDIGEST

            GlobalLog.Assert(credentials != null, "DigestClient::Authenticate() credentials==null", "");
            if (credentials == null || credentials is SystemNetworkCredential)
            {
                return(null);
            }

            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;

            GlobalLog.Assert(httpWebRequest != null, "DigestClient::Authenticate() httpWebRequest==null", "");
            if (httpWebRequest == null || httpWebRequest.ChallengedUri == null)
            {
                //
                // there has been no challenge:
                // 1) the request never went on the wire
                // 2) somebody other than us is calling into AuthenticationManager
                //
                return(null);
            }

            int index = AuthenticationManager.FindSubstringNotInQuotes(challenge.ToLower(CultureInfo.InvariantCulture), Signature);
            if (index < 0)
            {
                return(null);
            }

            string[] prefixes = null;
            string   rootPath = httpWebRequest.ChallengedUri.Scheme + "://" + httpWebRequest.ChallengedUri.Host;

            HttpDigestChallenge digestChallenge = HttpDigest.Interpret(challenge, index, httpWebRequest);
            if (digestChallenge == null)
            {
                return(null);
            }

            if (digestChallenge.Domain == null)
            {
                challengeCache.Add(rootPath, digestChallenge);
            }
            else
            {
                prefixes = digestChallenge.Domain.Split(" ".ToCharArray());
                for (int i = 0; i < prefixes.Length; i++)
                {
                    challengeCache.Add(prefixes[i], digestChallenge);
                }
            }

            Authorization digestResponse = HttpDigest.Authenticate(digestChallenge, credentials);
            if (digestResponse != null)
            {
                if (prefixes == null)
                {
                    digestResponse.ProtectionRealm    = new string[1];
                    digestResponse.ProtectionRealm[0] = rootPath;
                }
                else
                {
                    digestResponse.ProtectionRealm = prefixes;
                }
            }

            return(digestResponse);
        }
        public bool Update(string challenge, WebRequest webRequest)
        {
            GlobalLog.Print("DigestClient::Update(): [" + challenge + "]");

#if XP_WDIGEST
            if (ComNetOS.IsPostWin2K)
            {
                return(XPDigestClient.Update(challenge, webRequest));
            }
#endif // #if XP_WDIGEST

            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;

            GlobalLog.Assert(httpWebRequest != null, "DigestClient::Update() httpWebRequest==null", "");
            GlobalLog.Assert(httpWebRequest.ChallengedUri != null, "DigestClient::Update() httpWebRequest.ChallengedUri==null", "");

            // here's how we know if the handshake is complete when we get the response back,
            // (keeping in mind that we need to support stale credentials):
            // !40X - complete & success
            // 40X & stale=false - complete & failure
            // 40X & stale=true - !complete

            if (httpWebRequest.ResponseStatusCode != httpWebRequest.CurrentAuthenticationState.StatusCodeMatch)
            {
                GlobalLog.Print("DigestClient::Update(): no status code match. returning true");
                return(true);
            }

            int index = challenge == null ? -1 : AuthenticationManager.FindSubstringNotInQuotes(challenge.ToLower(CultureInfo.InvariantCulture), Signature);
            if (index < 0)
            {
                GlobalLog.Print("DigestClient::Update(): no challenge. returning true");
                return(true);
            }

            int    blobBegin = index + SignatureSize;
            string incoming  = null;

            //
            // there may be multiple challenges. If the next character after the
            // package name is not a comma then it is challenge data
            //
            if (challenge.Length > blobBegin && challenge[blobBegin] != ',')
            {
                ++blobBegin;
            }
            else
            {
                index = -1;
            }
            if (index >= 0 && challenge.Length > blobBegin)
            {
                incoming = challenge.Substring(blobBegin);
            }

            HttpDigestChallenge digestChallenge = HttpDigest.Interpret(challenge, index, httpWebRequest);
            if (digestChallenge == null)
            {
                GlobalLog.Print("DigestClient::Update(): not a valid digest challenge. returning true");
                return(true);
            }

            GlobalLog.Print("DigestClient::Update(): returning digestChallenge.Stale:" + digestChallenge.Stale.ToString());

            return(!digestChallenge.Stale);
        }