Пример #1
0
        //
        // this method computes the response-value according to the
        // rules described in RFC2831 section 2.1.2.1
        //
        private static string responseValue(HttpDigestChallenge challenge, string username, string password)
        {
            string secretString = computeSecret(challenge, username, password);

            if (secretString == null)
            {
                return(null);
            }

            string dataString = computeData(challenge);

            if (dataString == null)
            {
                return(null);
            }

            string secret = hashString(secretString, challenge.MD5provider);
            string hexMD2 = hashString(dataString, challenge.MD5provider);

            string data =
                challenge.Nonce + ":" +
                (challenge.QopPresent ?
                 challenge.NonceCount.ToString("x8") + ":" +
                 challenge.ClientNonce + ":" +
                 challenge.QualityOfProtection + ":" +
                 hexMD2
                        :
                 hexMD2);

            return(hashString(secret + ":" + data, challenge.MD5provider));
        }
        private static string createUpgradedNonce(HttpDigestChallenge digestChallenge)
        {
            string s = digestChallenge.ServiceName + ":" + digestChallenge.ChannelBinding;

            byte[] rawbytes = digestChallenge.MD5provider.ComputeHash(Encoding.ASCII.GetBytes(s));
            return("+Upgraded+v1" + hexEncode(rawbytes) + createNonce(0x20));
        }
Пример #3
0
 private static string computeData(HttpDigestChallenge challenge)
 {
     // we only support "auth" QualityOfProtection. if it's not what the server wants we'll throw:
     // the case in which the server sends no qop directive defaults to "auth" QualityOfProtection.
     if (challenge.QopPresent)
     {
         int index = 0;
         while (index >= 0)
         {
             // find the next occurence of "auth"
             index = challenge.QualityOfProtection.IndexOf(SupportedQuality, index);
             if (index < 0)
             {
                 throw new NotSupportedException(SR.GetString(SR.net_QOPNotSupportedException, challenge.QualityOfProtection));
             }
             // if it's a whole word we're done
             if ((index == 0 || ValidSeparator.IndexOf(challenge.QualityOfProtection[index - 1]) >= 0) &&
                 (index + SupportedQuality.Length == challenge.QualityOfProtection.Length || ValidSeparator.IndexOf(challenge.QualityOfProtection[index + SupportedQuality.Length]) >= 0))
             {
                 break;
             }
             index += SupportedQuality.Length;
         }
     }
     return(challenge.Method + ":" + challenge.Uri);
 }
Пример #4
0
        private static string RefineDigestChallenge(string challenge, int index)
        {
            string str = null;
            int    num4;

            if ((challenge == null) || (index >= challenge.Length))
            {
                throw new ArgumentOutOfRangeException("challenge", challenge);
            }
            int startIndex = index + SignatureSize;

            if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
            {
                startIndex++;
            }
            else
            {
                index = -1;
            }
            if ((index < 0) || (challenge.Length <= startIndex))
            {
                throw new ArgumentOutOfRangeException("challenge", challenge);
            }
            str = challenge.Substring(startIndex);
            int  num3 = 0;
            bool flag = true;
            HttpDigestChallenge challenge2 = new HttpDigestChallenge();

Label_0070:
            num4  = num3;
            index = AuthenticationManager.SplitNoQuotes(str, ref num4);
            if (num4 >= 0)
            {
                string str3;
                string name = str.Substring(num3, num4 - num3);
                if (index < 0)
                {
                    str3 = HttpDigest.unquote(str.Substring(num4 + 1));
                }
                else
                {
                    str3 = HttpDigest.unquote(str.Substring(num4 + 1, (index - num4) - 1));
                }
                flag = challenge2.defineAttribute(name, str3);
                if ((index >= 0) && flag)
                {
                    num3 = ++index;
                    goto Label_0070;
                }
            }
            if ((!flag || (num4 < 0)) && (num3 < str.Length))
            {
                str = (num3 > 0) ? str.Substring(0, num3 - 1) : "";
            }
            return(str);
        }
Пример #5
0
        public HttpDigestChallenge CopyAndIncrementNonce()
        {
            HttpDigestChallenge challengeCopy = null;

            lock (this) {
                challengeCopy = this.MemberwiseClone() as HttpDigestChallenge;
                ++NonceCount;
            }
            challengeCopy.MD5provider = new MD5CryptoServiceProvider();
            return(challengeCopy);
        }
Пример #6
0
        internal HttpDigestChallenge CopyAndIncrementNonce()
        {
            HttpDigestChallenge challenge = null;

            lock (this)
            {
                challenge = base.MemberwiseClone() as HttpDigestChallenge;
                this.NonceCount++;
            }
            challenge.MD5provider = new MD5CryptoServiceProvider();
            return(challenge);
        }
Пример #7
0
        private static string computeSecret(HttpDigestChallenge challenge, string username, string password)
        {
            if (challenge.Algorithm == null || string.Compare(challenge.Algorithm, "md5", true, CultureInfo.InvariantCulture) == 0)
            {
                return(username + ":" + challenge.Realm + ":" + password);
            }
            else if (string.Compare(challenge.Algorithm, "md5-sess", true, CultureInfo.InvariantCulture) == 0)
            {
                return(hashString(username + ":" + challenge.Realm + ":" + password, challenge.MD5provider) + ":" + challenge.Nonce + ":" + challenge.ClientNonce);
            }

            throw new NotSupportedException(SR.GetString(SR.net_HashAlgorithmNotSupportedException, challenge.Algorithm));
        }
 private static string computeSecret(HttpDigestChallenge challenge, string username, string password)
 {
     if ((challenge.Algorithm == null) || (string.Compare(challenge.Algorithm, "md5", StringComparison.OrdinalIgnoreCase) == 0))
     {
         return(username + ":" + challenge.Realm + ":" + password);
     }
     if (string.Compare(challenge.Algorithm, "md5-sess", StringComparison.OrdinalIgnoreCase) == 0)
     {
         return(hashString(username + ":" + challenge.Realm + ":" + password, challenge.MD5provider) + ":" + challenge.Nonce + ":" + challenge.ClientNonce);
     }
     if (Logging.On)
     {
         Logging.PrintError(Logging.Web, SR.GetString("net_log_digest_hash_algorithm_not_supported", new object[] { challenge.Algorithm }));
     }
     return(null);
 }
Пример #9
0
        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);
        }
 internal static bool CheckQOP(HttpDigestChallenge challenge)
 {
     if (challenge.QopPresent)
     {
         for (int i = 0; i >= 0; i += "auth".Length)
         {
             i = challenge.QualityOfProtection.IndexOf("auth", i);
             if (i < 0)
             {
                 return false;
             }
             if (((i == 0) || (", \"'\t\r\n".IndexOf(challenge.QualityOfProtection[i - 1]) >= 0)) && (((i + "auth".Length) == challenge.QualityOfProtection.Length) || (", \"'\t\r\n".IndexOf(challenge.QualityOfProtection[i + "auth".Length]) >= 0)))
             {
                 break;
             }
         }
     }
     return true;
 }
Пример #11
0
 internal static bool CheckQOP(HttpDigestChallenge challenge)
 {
     if (challenge.QopPresent)
     {
         for (int i = 0; i >= 0; i += "auth".Length)
         {
             i = challenge.QualityOfProtection.IndexOf("auth", i);
             if (i < 0)
             {
                 return(false);
             }
             if (((i == 0) || (", \"'\t\r\n".IndexOf(challenge.QualityOfProtection[i - 1]) >= 0)) && (((i + "auth".Length) == challenge.QualityOfProtection.Length) || (", \"'\t\r\n".IndexOf(challenge.QualityOfProtection[i + "auth".Length]) >= 0)))
             {
                 break;
             }
         }
     }
     return(true);
 }
Пример #12
0
        public bool Update(string challenge, WebRequest webRequest)
        {
            HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;

            if (httpWebRequest.CurrentAuthenticationState.GetSecurityContext(this) != null)
            {
                return(this.XPUpdate(challenge, httpWebRequest));
            }
            if (httpWebRequest.ResponseStatusCode != httpWebRequest.CurrentAuthenticationState.StatusCodeMatch)
            {
                ChannelBinding channelBinding = null;
                if (httpWebRequest.CurrentAuthenticationState.TransportContext != null)
                {
                    channelBinding = httpWebRequest.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
                }
                httpWebRequest.ServicePoint.SetCachedChannelBinding(httpWebRequest.ChallengedUri, channelBinding);
                return(true);
            }
            int startingPoint = (challenge == null) ? -1 : AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);

            if (startingPoint < 0)
            {
                return(true);
            }
            int startIndex = startingPoint + SignatureSize;

            if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
            {
                startIndex++;
            }
            else
            {
                startingPoint = -1;
            }
            if ((startingPoint >= 0) && (challenge.Length > startIndex))
            {
                challenge.Substring(startIndex);
            }
            HttpDigestChallenge challenge2 = HttpDigest.Interpret(challenge, startingPoint, httpWebRequest);

            return((challenge2 == null) || !challenge2.Stale);
        }
        private static string responseValue(HttpDigestChallenge challenge, string username, string password)
        {
            string myString = computeSecret(challenge, username, password);

            if (myString == null)
            {
                return(null);
            }
            string str2 = challenge.Method + ":" + challenge.Uri;

            if (str2 == null)
            {
                return(null);
            }
            string str3 = hashString(myString, challenge.MD5provider);
            string str4 = hashString(str2, challenge.MD5provider);
            string str5 = challenge.Nonce + ":" + (challenge.QopPresent ? (challenge.NonceCount.ToString("x8", NumberFormatInfo.InvariantInfo) + ":" + challenge.ClientNonce + ":auth:" + str4) : str4);

            return(hashString(str3 + ":" + str5, challenge.MD5provider));
        }
Пример #14
0
        //
        // this method parses the challenge and breaks it into the
        // fundamental pieces that Digest defines and understands
        //
        internal static HttpDigestChallenge Interpret(string challenge, int startingPoint, HttpWebRequest httpWebRequest) {
            HttpDigestChallenge digestChallenge = new HttpDigestChallenge();
            digestChallenge.SetFromRequest(httpWebRequest);
            //
            // define the part of the challenge we really care about
            //
            startingPoint = startingPoint==-1 ? 0 : startingPoint + DigestClient.SignatureSize;

            bool valid;
            int start, offset, index;
            string name, value;

            // forst time parse looking for a charset="utf-8" directive
            // not too bad, IIS 6.0, by default, sends this as the first directive.
            // if the server does not send this we'll end up parsing twice.
            start = startingPoint;
            for (;;) {
                offset = start;
                index = AuthenticationManager.SplitNoQuotes(challenge, ref offset);
                if (offset<0) {
                    break;
                }
                name = challenge.Substring(start, offset-start);
                if (string.Compare(name, DA_charset, StringComparison.OrdinalIgnoreCase)==0) {
                    if (index<0) {
                        value = unquote(challenge.Substring(offset+1));
                    }
                    else {
                        value = unquote(challenge.Substring(offset+1, index-offset-1));
                    }
                    GlobalLog.Print("HttpDigest::Interpret() server provided a hint to use [" + value + "] encoding");
                    if (string.Compare(value, "utf-8", StringComparison.OrdinalIgnoreCase)==0) {
                        digestChallenge.UTF8Charset = true;
                        break;
                    }
                }
                if (index<0) {
                    break;
                }
                start = ++index;
            }

            // this time go through the directives, parse them and call defineAttribute()
            start = startingPoint;
            for (;;) {
                offset = start;
                index = AuthenticationManager.SplitNoQuotes(challenge, ref offset);
                GlobalLog.Print("HttpDigest::Interpret() SplitNoQuotes() returning index:" + index.ToString() + " offset:" + offset.ToString());
                if (offset<0) {
                    break;
                }
                name = challenge.Substring(start, offset-start);
                if (index<0) {
                    value = unquote(challenge.Substring(offset+1));
                }
                else {
                    value = unquote(challenge.Substring(offset+1, index-offset-1));
                }
                if (digestChallenge.UTF8Charset) {
                    bool isAscii = true;
                    for (int i=0; i<value.Length; i++) {
                        if (value[i]>(char)0x7F) {
                            isAscii = false;
                            break;
                        }
                    }
                    if (!isAscii) {
                        GlobalLog.Print("HttpDigest::Interpret() UTF8 decoding required value:[" + value + "]");
                        byte[] bytes = new byte[value.Length];
                        for (int i=0; i<value.Length; i++) {
                            bytes[i] = (byte)value[i];
                        }
                        value = Encoding.UTF8.GetString(bytes);
                        GlobalLog.Print("HttpDigest::Interpret() UTF8 decoded value:[" + value + "]");
                    }
                    else {
                        GlobalLog.Print("HttpDigest::Interpret() no need for special encoding");
                    }
                }
                valid = digestChallenge.defineAttribute(name, value);
                GlobalLog.Print("HttpDigest::Interpret() defineAttribute(" + name + ", " + value + ") returns " + valid.ToString());
                if (index<0 || !valid) {
                    break;
                }
                start = ++index;
            }
            // We must absolutely have a nonce for Digest to work.
            if (digestChallenge.Nonce == null) {
                if (Logging.On)
                    Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_digest_requires_nonce));
                return null;
            }

            return digestChallenge;
        }
Пример #15
0
        //
        // Extract digest relevant part from a raw server blob
        //
        private static string RefineDigestChallenge(string challenge, int index)
        {
            string incoming = null;

            Debug.Assert(challenge != null);
            Debug.Assert(index >= 0 && index < challenge.Length);

            int blobBegin = index + SignatureSize;

            //
            // 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);
            }
            else
            {
                Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_auth_invalid_challenge, DigestClient.AuthType));
                return String.Empty; // Error, no valid digest challenge, no further processing required
            }

            // now make sure there's nothing at the end of the challenge that is not part of the digest challenge
            // this would happen if I have a Digest challenge followed by another challenge like ",NTLM,Negotiate"
            // use this DCR when avaialble to do this without parsing:
            // 762116   2   WDigest should ignore directives that do not have a value
            int startingPoint = 0;
            int start = startingPoint;
            int offset;
            bool valid = true;
            string name, value;
            HttpDigestChallenge digestChallenge = new HttpDigestChallenge();
            for (;;) {
                offset = start;
                index = AuthenticationManager.SplitNoQuotes(incoming, ref offset);
                GlobalLog.Print("DigestClient::XPDoAuthenticate() SplitNoQuotes() returning index:" + index + " offset:" + offset);
                if (offset<0) {
                    break;
                }
                name = incoming.Substring(start, offset-start);
                if (index<0) {
                    value = HttpDigest.unquote(incoming.Substring(offset+1));
                }
                else {
                    value = HttpDigest.unquote(incoming.Substring(offset+1, index-offset-1));
                }
                valid = digestChallenge.defineAttribute(name, value);
                GlobalLog.Print("DigestClient::XPDoAuthenticate() defineAttribute(" + name + ", " + value + ") returns " + valid);
                if (index<0 || !valid) {
                    break;
                }
                start = ++index;
            }
            GlobalLog.Print("DigestClient::XPDoAuthenticate() start:" + start + " offset:" + offset + " index:" + index + " valid:" + valid + " incoming.Length:" + incoming.Length + " incoming:" + incoming);
            if ((!valid || offset<0) && start<incoming.Length) {
                incoming = start > 0 ? incoming.Substring(0, start-1) : ""; // First parameter might have been invalid, leaving start at 0
            }
            return incoming;
        }
Пример #16
0
 internal static bool CheckQOP(HttpDigestChallenge challenge) {
     // our internal implementatoin only support "auth" QualityOfProtection.
     // if it's not what the server wants we'll have to throw:
     // the case in which the server sends no qop directive we default to "auth"
     if (challenge.QopPresent) {
         int index = 0;
         while (index>=0) {
             // find the next occurence of "auth"
             index = challenge.QualityOfProtection.IndexOf(HttpDigest.SupportedQuality, index);
             if (index<0) {
                 return false;
             }
             // if it's a whole word we're done
             if ((index==0 || HttpDigest.ValidSeparator.IndexOf(challenge.QualityOfProtection[index - 1])>=0) &&
                 (index+HttpDigest.SupportedQuality.Length==challenge.QualityOfProtection.Length || HttpDigest.ValidSeparator.IndexOf(challenge.QualityOfProtection[index + HttpDigest.SupportedQuality.Length])>=0) ) {
                 break;
             }
             index += HttpDigest.SupportedQuality.Length;
         }
     }
     return true;
 }
Пример #17
0
        private static string createUpgradedNonce(HttpDigestChallenge digestChallenge)
        {
            string hashMe = digestChallenge.ServiceName + ":" + digestChallenge.ChannelBinding;
            byte[] hash = digestChallenge.MD5provider.ComputeHash(Encoding.ASCII.GetBytes(hashMe));

            return UpgradedV1 + hexEncode(hash) + createNonce(32);
        }
Пример #18
0
 private static string computeSecret(HttpDigestChallenge challenge, string username, string password) {
     if (challenge.Algorithm==null || string.Compare(challenge.Algorithm, "md5" ,StringComparison.OrdinalIgnoreCase)==0) {
         return username + ":" + challenge.Realm + ":" + password;
     }
     else if (string.Compare(challenge.Algorithm, "md5-sess" ,StringComparison.OrdinalIgnoreCase)==0) {
         return hashString(username + ":" + challenge.Realm + ":" + password, challenge.MD5provider) + ":" + challenge.Nonce + ":" + challenge.ClientNonce;
     }
     if (Logging.On)
         Logging.PrintError(Logging.Web, SR.GetString(SR.net_log_digest_hash_algorithm_not_supported, challenge.Algorithm));
     return null;
 }
        internal static Authorization Authenticate(HttpDigestChallenge digestChallenge, NetworkCredential NC, string spn, ChannelBinding binding)
        {
            string userName = NC.InternalGetUserName();

            if (ValidationHelper.IsBlankString(userName))
            {
                return(null);
            }
            string password = NC.InternalGetPassword();
            bool   flag     = IsUpgraded(digestChallenge.Nonce, binding);

            if (flag)
            {
                digestChallenge.ServiceName    = spn;
                digestChallenge.ChannelBinding = hashChannelBinding(binding, digestChallenge.MD5provider);
            }
            if (digestChallenge.QopPresent)
            {
                if ((digestChallenge.ClientNonce == null) || digestChallenge.Stale)
                {
                    if (flag)
                    {
                        digestChallenge.ClientNonce = createUpgradedNonce(digestChallenge);
                    }
                    else
                    {
                        digestChallenge.ClientNonce = createNonce(0x20);
                    }
                    digestChallenge.NonceCount = 1;
                }
                else
                {
                    digestChallenge.NonceCount++;
                }
            }
            StringBuilder builder = new StringBuilder();
            Charset       charset = DetectCharset(userName);

            if (!digestChallenge.UTF8Charset && (charset == Charset.UTF8))
            {
                return(null);
            }
            Charset charset2 = DetectCharset(password);

            if (!digestChallenge.UTF8Charset && (charset2 == Charset.UTF8))
            {
                return(null);
            }
            if (digestChallenge.UTF8Charset)
            {
                builder.Append(pair("charset", "utf-8", false));
                builder.Append(",");
                if (charset == Charset.UTF8)
                {
                    userName = CharsetEncode(userName, Charset.UTF8);
                    builder.Append(pair("username", userName, true));
                    builder.Append(",");
                }
                else
                {
                    builder.Append(pair("username", CharsetEncode(userName, Charset.UTF8), true));
                    builder.Append(",");
                    userName = CharsetEncode(userName, charset);
                }
            }
            else
            {
                userName = CharsetEncode(userName, charset);
                builder.Append(pair("username", userName, true));
                builder.Append(",");
            }
            password = CharsetEncode(password, charset2);
            builder.Append(pair("realm", digestChallenge.Realm, true));
            builder.Append(",");
            builder.Append(pair("nonce", digestChallenge.Nonce, true));
            builder.Append(",");
            builder.Append(pair("uri", digestChallenge.Uri, true));
            if (digestChallenge.QopPresent)
            {
                if (digestChallenge.Algorithm != null)
                {
                    builder.Append(",");
                    builder.Append(pair("algorithm", digestChallenge.Algorithm, true));
                }
                builder.Append(",");
                builder.Append(pair("cnonce", digestChallenge.ClientNonce, true));
                builder.Append(",");
                builder.Append(pair("nc", digestChallenge.NonceCount.ToString("x8", NumberFormatInfo.InvariantInfo), false));
                builder.Append(",");
                builder.Append(pair("qop", "auth", true));
                if (flag)
                {
                    builder.Append(",");
                    builder.Append(pair("hashed-dirs", "service-name,channel-binding", true));
                    builder.Append(",");
                    builder.Append(pair("service-name", digestChallenge.ServiceName, true));
                    builder.Append(",");
                    builder.Append(pair("channel-binding", digestChallenge.ChannelBinding, true));
                }
            }
            string str3 = responseValue(digestChallenge, userName, password);

            if (str3 == null)
            {
                return(null);
            }
            builder.Append(",");
            builder.Append(pair("response", str3, true));
            if (digestChallenge.Opaque != null)
            {
                builder.Append(",");
                builder.Append(pair("opaque", digestChallenge.Opaque, true));
            }
            return(new Authorization("Digest " + builder.ToString(), false));
        }
Пример #20
0
        //
        // this method parses the challenge and breaks it into the
        // fundamental pieces that Digest defines and understands
        //
        public static HttpDigestChallenge Interpret(string challenge, int startingPoint, HttpWebRequest httpWebRequest)
        {
            HttpDigestChallenge hdc = new HttpDigestChallenge();

            hdc.HostName      = httpWebRequest.ChallengedUri.Host;
            hdc.Method        = httpWebRequest.CurrentMethod;
            hdc.Uri           = httpWebRequest.Address.AbsolutePath;
            hdc.ChallengedUri = httpWebRequest.ChallengedUri;

            //
            // define the part of the challenge we really care about
            //
            startingPoint += DigestClient.SignatureSize;

            bool   valid;
            int    start, offset, index;
            string name, value;

            // forst time parse looking for a charset="utf-8" directive
            // not too bad, IIS 6.0, by default, sends this as the first directive.
            // if the server does not send this we'll end up parsing twice.
            start = startingPoint;
            for (;;)
            {
                offset = start;
                index  = AuthenticationManager.SplitNoQuotes(challenge, ref offset);
                if (offset < 0)
                {
                    break;
                }
                name = challenge.Substring(start, offset - start);
                if (string.Compare(name, DA_charset, true, CultureInfo.InvariantCulture) == 0)
                {
                    if (index < 0)
                    {
                        value = unquote(challenge.Substring(offset + 1));
                    }
                    else
                    {
                        value = unquote(challenge.Substring(offset + 1, index - offset - 1));
                    }
                    GlobalLog.Print("HttpDigest::Interpret() server provided a hint to use [" + value + "] encoding");
                    if (string.Compare(value, "utf-8", true, CultureInfo.InvariantCulture) == 0)
                    {
                        hdc.UTF8Charset = true;
                        break;
                    }
                }
                if (index < 0)
                {
                    break;
                }
                start = ++index;
            }

            // this time go through the directives, parse them and call defineAttribute()
            start = startingPoint;
            for (;;)
            {
                offset = start;
                index  = AuthenticationManager.SplitNoQuotes(challenge, ref offset);
                GlobalLog.Print("HttpDigest::Interpret() SplitNoQuotes() returning index:" + index.ToString() + " offset:" + offset.ToString());
                if (offset < 0)
                {
                    break;
                }
                name = challenge.Substring(start, offset - start);
                if (index < 0)
                {
                    value = unquote(challenge.Substring(offset + 1));
                }
                else
                {
                    value = unquote(challenge.Substring(offset + 1, index - offset - 1));
                }
                if (hdc.UTF8Charset)
                {
                    bool isAscii = true;
                    for (int i = 0; i < value.Length; i++)
                    {
                        if (value[i] > (char)0x7F)
                        {
                            isAscii = false;
                            break;
                        }
                    }
                    if (!isAscii)
                    {
                        GlobalLog.Print("HttpDigest::Interpret() UTF8 decoding required value:[" + value + "]");
                        byte[] bytes = new byte[value.Length];
                        for (int i = 0; i < value.Length; i++)
                        {
                            bytes[i] = (byte)value[i];
                        }
                        value = Encoding.UTF8.GetString(bytes);
                        GlobalLog.Print("HttpDigest::Interpret() UTF8 decoded value:[" + value + "]");
                    }
                    else
                    {
                        GlobalLog.Print("HttpDigest::Interpret() no need for special encoding");
                    }
                }
                valid = hdc.defineAttribute(name, value);
                GlobalLog.Print("HttpDigest::Interpret() defineAttribute(" + name + ", " + value + ") returns " + valid.ToString());
                if (index < 0 || !valid)
                {
                    break;
                }
                start = ++index;
            }

            return(hdc);
        }
Пример #21
0
        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);
        }
Пример #22
0
        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);
        }
Пример #23
0
        //
        // CONSIDER V.NEXT
        // creating a static hashtable for server nonces and keep track of nonce count
        //
        internal static Authorization Authenticate(HttpDigestChallenge digestChallenge, NetworkCredential NC, string spn, ChannelBinding binding) {

            string username = NC.InternalGetUserName();
            if (ValidationHelper.IsBlankString(username)) {
                return null;
            }
            string password = NC.InternalGetPassword();

            bool upgraded = IsUpgraded(digestChallenge.Nonce, binding);
            if (upgraded)
            {
                digestChallenge.ServiceName = spn;
                digestChallenge.ChannelBinding = hashChannelBinding(binding, digestChallenge.MD5provider);
            }

            if (digestChallenge.QopPresent) {
                if (digestChallenge.ClientNonce==null || digestChallenge.Stale) {
                    GlobalLog.Print("HttpDigest::Authenticate() QopPresent:True, need new nonce. digestChallenge.ClientNonce:" + ValidationHelper.ToString(digestChallenge.ClientNonce) + " digestChallenge.Stale:" + digestChallenge.Stale.ToString());

                    if (upgraded)
                    {
                        digestChallenge.ClientNonce = createUpgradedNonce(digestChallenge);
                    }
                    else
                    {
                        digestChallenge.ClientNonce = createNonce(32);
                    }

                    digestChallenge.NonceCount = 1;
                }
                else {
                    GlobalLog.Print("HttpDigest::Authenticate() QopPresent:True, reusing nonce. digestChallenge.NonceCount:" + digestChallenge.NonceCount.ToString());
                    digestChallenge.NonceCount++;
                }
            }

            StringBuilder authorization = new StringBuilder();

            //
            // look at username & password, if it's not ASCII we need to attempt some
            // kind of encoding because we need to calculate the hash on byte[]
            //
            Charset usernameCharset = DetectCharset(username);
            if (!digestChallenge.UTF8Charset && usernameCharset==Charset.UTF8) {
                GlobalLog.Print("HttpDigest::Authenticate() can't authenticate with UNICODE username. failing auth.");
                return null;
            }
            Charset passwordCharset = DetectCharset(password);
            if (!digestChallenge.UTF8Charset && passwordCharset==Charset.UTF8) {
                GlobalLog.Print("HttpDigest::Authenticate() can't authenticate with UNICODE password. failing auth.");
                return null;
            }
            if (digestChallenge.UTF8Charset) {
                // on the wire always use UTF8 when the server supports it
                authorization.Append(pair(DA_charset, "utf-8", false));
                authorization.Append(",");
                if (usernameCharset==Charset.UTF8) {
                    username = CharsetEncode(username, Charset.UTF8);
                    authorization.Append(pair(DA_username, username, true));
                    authorization.Append(",");
                }
                else {
                    authorization.Append(pair(DA_username, CharsetEncode(username, Charset.UTF8), true));
                    authorization.Append(",");
                    username = CharsetEncode(username, usernameCharset);
                }
            }
            else {
                // otherwise UTF8 is not required
                username = CharsetEncode(username, usernameCharset);
                authorization.Append(pair(DA_username, username, true));
                authorization.Append(",");
            }

            password = CharsetEncode(password, passwordCharset);

            // no special encoding for the realm since we're just going to echo it back (encoding must have happened on the server).
            authorization.Append(pair(DA_realm, digestChallenge.Realm, true));
            authorization.Append(",");
            authorization.Append(pair(DA_nonce, digestChallenge.Nonce, true));
            authorization.Append(",");
            authorization.Append(pair(DA_uri, digestChallenge.Uri, true));

            if (digestChallenge.QopPresent) {
                if (digestChallenge.Algorithm!=null) {
                    // consider: should we default to "MD5" here? IE does
                    authorization.Append(",");
                    authorization.Append(pair(DA_algorithm, digestChallenge.Algorithm, true)); // IE sends quotes - IIS needs them
                }
                authorization.Append(",");
                authorization.Append(pair(DA_cnonce, digestChallenge.ClientNonce, true));
                authorization.Append(",");
                authorization.Append(pair(DA_nc, digestChallenge.NonceCount.ToString("x8", NumberFormatInfo.InvariantInfo), false));
                // RAID#47397
                // send only the QualityOfProtection we're using
                // since we support only "auth" that's what we will send out
                authorization.Append(",");
                authorization.Append(pair(DA_qop, SupportedQuality, true)); // IE sends quotes - IIS needs them

                if (upgraded)
                {
                    authorization.Append(",");
                    authorization.Append(pair(DA_hasheddirs, HashedDirs, true));
                    authorization.Append(",");
                    authorization.Append(pair(DA_servicename, digestChallenge.ServiceName, true));
                    authorization.Append(",");
                    authorization.Append(pair(DA_channelbinding, digestChallenge.ChannelBinding, true));
                }
            }

            // warning: this must be computed here
            string responseValue = HttpDigest.responseValue(digestChallenge, username, password);
            if (responseValue==null) {
                return null;
            }

            authorization.Append(",");
            authorization.Append(pair(DA_response, responseValue, true)); // IE sends quotes - IIS needs them

            if (digestChallenge.Opaque!=null) {
                authorization.Append(",");
                authorization.Append(pair(DA_opaque, digestChallenge.Opaque, true));
            }

            GlobalLog.Print("HttpDigest::Authenticate() digestChallenge.Stale:" + digestChallenge.Stale.ToString());

            // completion is decided in Update()
            Authorization finalAuthorization = new Authorization(DigestClient.AuthType + " " + authorization.ToString(), false);

            return finalAuthorization;
        }
        internal static HttpDigestChallenge Interpret(string challenge, int startingPoint, HttpWebRequest httpWebRequest)
        {
            int    num2;
            string str2;
            HttpDigestChallenge challenge2 = new HttpDigestChallenge();

            challenge2.SetFromRequest(httpWebRequest);
            startingPoint = (startingPoint == -1) ? 0 : (startingPoint + DigestClient.SignatureSize);
            int startIndex = startingPoint;

Label_001F:
            num2 = startIndex;
            int num3 = AuthenticationManager.SplitNoQuotes(challenge, ref num2);

            if (num2 >= 0)
            {
                if (string.Compare(challenge.Substring(startIndex, num2 - startIndex), "charset", StringComparison.OrdinalIgnoreCase) == 0)
                {
                    if (num3 < 0)
                    {
                        str2 = unquote(challenge.Substring(num2 + 1));
                    }
                    else
                    {
                        str2 = unquote(challenge.Substring(num2 + 1, (num3 - num2) - 1));
                    }
                    if (string.Compare(str2, "utf-8", StringComparison.OrdinalIgnoreCase) == 0)
                    {
                        challenge2.UTF8Charset = true;
                        goto Label_009E;
                    }
                }
                if (num3 >= 0)
                {
                    startIndex = ++num3;
                    goto Label_001F;
                }
            }
Label_009E:
            startIndex = startingPoint;
Label_00A0:
            num2 = startIndex;
            num3 = AuthenticationManager.SplitNoQuotes(challenge, ref num2);
            if (num2 >= 0)
            {
                string name = challenge.Substring(startIndex, num2 - startIndex);
                if (num3 < 0)
                {
                    str2 = unquote(challenge.Substring(num2 + 1));
                }
                else
                {
                    str2 = unquote(challenge.Substring(num2 + 1, (num3 - num2) - 1));
                }
                if (challenge2.UTF8Charset)
                {
                    bool flag2 = true;
                    for (int i = 0; i < str2.Length; i++)
                    {
                        if (str2[i] > '\x007f')
                        {
                            flag2 = false;
                            break;
                        }
                    }
                    if (!flag2)
                    {
                        byte[] bytes = new byte[str2.Length];
                        for (int j = 0; j < str2.Length; j++)
                        {
                            bytes[j] = (byte)str2[j];
                        }
                        str2 = Encoding.UTF8.GetString(bytes);
                    }
                }
                bool flag = challenge2.defineAttribute(name, str2);
                if ((num3 >= 0) && flag)
                {
                    startIndex = ++num3;
                    goto Label_00A0;
                }
            }
            if (challenge2.Nonce != null)
            {
                return(challenge2);
            }
            if (Logging.On)
            {
                Logging.PrintError(Logging.Web, SR.GetString("net_log_digest_requires_nonce"));
            }
            return(null);
        }
 private static string RefineDigestChallenge(string challenge, int index)
 {
     string str = null;
     int num4;
     if ((challenge == null) || (index >= challenge.Length))
     {
         throw new ArgumentOutOfRangeException("challenge", challenge);
     }
     int startIndex = index + SignatureSize;
     if ((challenge.Length > startIndex) && (challenge[startIndex] != ','))
     {
         startIndex++;
     }
     else
     {
         index = -1;
     }
     if ((index < 0) || (challenge.Length <= startIndex))
     {
         throw new ArgumentOutOfRangeException("challenge", challenge);
     }
     str = challenge.Substring(startIndex);
     int num3 = 0;
     bool flag = true;
     HttpDigestChallenge challenge2 = new HttpDigestChallenge();
 Label_0070:
     num4 = num3;
     index = AuthenticationManager.SplitNoQuotes(str, ref num4);
     if (num4 >= 0)
     {
         string str3;
         string name = str.Substring(num3, num4 - num3);
         if (index < 0)
         {
             str3 = HttpDigest.unquote(str.Substring(num4 + 1));
         }
         else
         {
             str3 = HttpDigest.unquote(str.Substring(num4 + 1, (index - num4) - 1));
         }
         flag = challenge2.defineAttribute(name, str3);
         if ((index >= 0) && flag)
         {
             num3 = ++index;
             goto Label_0070;
         }
     }
     if ((!flag || (num4 < 0)) && (num3 < str.Length))
     {
         str = (num3 > 0) ? str.Substring(0, num3 - 1) : "";
     }
     return str;
 }
Пример #26
0
        //
        // this method computes the response-value according to the
        // rules described in RFC2831 section 2.1.2.1
        //
        private static string responseValue(HttpDigestChallenge challenge, string username, string password) {
            string secretString = computeSecret(challenge, username, password);
            if (secretString == null) {
                return null;
            }

            // we assume auth here, since it's the only one we support, the check happened earlier
            string dataString = challenge.Method + ":" + challenge.Uri;
            if (dataString == null) {
                return null;
            }

            string secret = hashString(secretString, challenge.MD5provider);
            string hexMD2 = hashString(dataString, challenge.MD5provider);

            string data =
                challenge.Nonce + ":" +
                    (challenge.QopPresent ?
                        challenge.NonceCount.ToString("x8", NumberFormatInfo.InvariantInfo) + ":" +
                        challenge.ClientNonce + ":" +
                        SupportedQuality + ":" + // challenge.QualityOfProtection + ":" +
                        hexMD2
                        :
                        hexMD2);

            return hashString(secret + ":" + data, challenge.MD5provider);
        }
Пример #27
0
        //
        // CONSIDER V.NEXT
        // creating a static hashtable for server nonces and keep track of nonce count
        //
        public static Authorization Authenticate(HttpDigestChallenge digestChallenge, ICredentials credentials)
        {
            NetworkCredential NC = credentials.GetCredential(digestChallenge.ChallengedUri, DigestClient.Signature);

            GlobalLog.Print("HttpDigest::Authenticate() GetCredential() returns:" + ValidationHelper.ToString(NC));

            if (NC == null)
            {
                return(null);
            }
            string username = NC.UserName;

            if (ValidationHelper.IsBlankString(username))
            {
                return(null);
            }
            string password = NC.Password;

            if (digestChallenge.QopPresent)
            {
                if (digestChallenge.ClientNonce == null || digestChallenge.Stale)
                {
                    GlobalLog.Print("HttpDigest::Authenticate() QopPresent:True, need new nonce. digestChallenge.ClientNonce:" + ValidationHelper.ToString(digestChallenge.ClientNonce) + " digestChallenge.Stale:" + digestChallenge.Stale.ToString());
                    digestChallenge.ClientNonce = createNonce(32);
                    digestChallenge.NonceCount  = 1;
                }
                else
                {
                    GlobalLog.Print("HttpDigest::Authenticate() QopPresent:True, reusing nonce. digestChallenge.NonceCount:" + digestChallenge.NonceCount.ToString());
                    digestChallenge.NonceCount++;
                }
            }

            StringBuilder authorization = new StringBuilder();

            //
            // look at username & password, if it's not ASCII we need to attempt some
            // kind of encoding because we need to calculate the hash on byte[]
            //
            Charset usernameCharset = DetectCharset(username);

            if (!digestChallenge.UTF8Charset && usernameCharset == Charset.UTF8)
            {
                GlobalLog.Print("HttpDigest::Authenticate() can't authenticate with UNICODE username. failing auth.");
                return(null);
            }
            Charset passwordCharset = DetectCharset(password);

            if (!digestChallenge.UTF8Charset && passwordCharset == Charset.UTF8)
            {
                GlobalLog.Print("HttpDigest::Authenticate() can't authenticate with UNICODE password. failing auth.");
                return(null);
            }
            if (digestChallenge.UTF8Charset)
            {
                // on the wire always use UTF8 when the server supports it
                authorization.Append(pair(DA_charset, "utf-8", false));
                authorization.Append(",");
                if (usernameCharset == Charset.UTF8)
                {
                    username = CharsetEncode(username, Charset.UTF8);
                    authorization.Append(pair(DA_username, username, true));
                    authorization.Append(",");
                }
                else
                {
                    authorization.Append(pair(DA_username, CharsetEncode(username, Charset.UTF8), true));
                    authorization.Append(",");
                    username = CharsetEncode(username, usernameCharset);
                }
            }
            else
            {
                // otherwise UTF8 is not required
                username = CharsetEncode(username, usernameCharset);
                authorization.Append(pair(DA_username, username, true));
                authorization.Append(",");
            }

            password = CharsetEncode(password, passwordCharset);

            // no special encoding for the realm since we're just going to echo it back (encoding must have happened on the server).
            authorization.Append(pair(DA_realm, digestChallenge.Realm, true));
            authorization.Append(",");
            authorization.Append(pair(DA_nonce, digestChallenge.Nonce, true));
            authorization.Append(",");
            authorization.Append(pair(DA_uri, digestChallenge.Uri, true));

            if (digestChallenge.QopPresent)
            {
                //
                // RAID#47397
                // send only the QualityOfProtection we're using
                // since we support only "auth" that's what we will send out
                //
                if (digestChallenge.Algorithm != null)
                {
                    //
                    // consider: should we default to "MD5" here? IE does
                    //
                    authorization.Append(",");
                    authorization.Append(pair(DA_algorithm, digestChallenge.Algorithm, true)); // IE sends quotes - IIS needs them
                }
                authorization.Append(",");
                authorization.Append(pair(DA_cnonce, digestChallenge.ClientNonce, true));
                authorization.Append(",");
                authorization.Append(pair(DA_nc, digestChallenge.NonceCount.ToString("x8"), false));
                authorization.Append(",");
                authorization.Append(pair(DA_qop, SupportedQuality, true)); // IE sends quotes - IIS needs them
            }

            // warning: this must be computed here
            string responseValue = HttpDigest.responseValue(digestChallenge, username, password);

            if (responseValue == null)
            {
                return(null);
            }

            authorization.Append(",");
            authorization.Append(pair(DA_response, responseValue, true)); // IE sends quotes - IIS needs them

            if (digestChallenge.Opaque != null)
            {
                authorization.Append(",");
                authorization.Append(pair(DA_opaque, digestChallenge.Opaque, true));
            }

            GlobalLog.Print("HttpDigest::Authenticate() digestChallenge.Stale:" + digestChallenge.Stale.ToString());

            // completion is decided in Update()
            Authorization finalAuthorization = new Authorization(DigestClient.AuthType + " " + authorization.ToString(), false);

            return(finalAuthorization);
        }
Пример #28
0
        private Authorization XPDoAuthenticate(string challenge, HttpWebRequest httpWebRequest, ICredentials credentials, bool preAuthenticate)
        {
            NTAuthentication securityContext = null;
            string           incomingBlob    = null;
            SecurityStatus   status;

            if (!preAuthenticate)
            {
                int index = AuthenticationManager.FindSubstringNotInQuotes(challenge, Signature);
                if (index < 0)
                {
                    return(null);
                }
                securityContext = httpWebRequest.CurrentAuthenticationState.GetSecurityContext(this);
                incomingBlob    = RefineDigestChallenge(challenge, index);
            }
            else
            {
                HttpDigestChallenge challenge2 = challengeCache.Lookup(httpWebRequest.ChallengedUri.AbsoluteUri) as HttpDigestChallenge;
                if (challenge2 == null)
                {
                    return(null);
                }
                challenge2 = challenge2.CopyAndIncrementNonce();
                challenge2.SetFromRequest(httpWebRequest);
                incomingBlob = challenge2.ToBlob();
            }
            UriComponents uriParts = 0;

            if (httpWebRequest.CurrentMethod.ConnectRequest)
            {
                uriParts = UriComponents.HostAndPort;
            }
            else if (httpWebRequest.UsesProxySemantics)
            {
                uriParts = UriComponents.HttpRequestUrl;
            }
            else
            {
                uriParts = UriComponents.PathAndQuery;
            }
            string parts = httpWebRequest.GetRemoteResourceUri().GetParts(uriParts, UriFormat.UriEscaped);

            if (securityContext == null)
            {
                NetworkCredential credential = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature);
                if ((credential == null) || (!(credential is SystemNetworkCredential) && (credential.InternalGetUserName().Length == 0)))
                {
                    return(null);
                }
                ICredentialPolicy credentialPolicy = AuthenticationManager.CredentialPolicy;
                if ((credentialPolicy != null) && !credentialPolicy.ShouldSendCredential(httpWebRequest.ChallengedUri, httpWebRequest, credential, this))
                {
                    return(null);
                }
                string         computeSpn     = httpWebRequest.CurrentAuthenticationState.GetComputeSpn(httpWebRequest);
                ChannelBinding channelBinding = null;
                if (httpWebRequest.CurrentAuthenticationState.TransportContext != null)
                {
                    channelBinding = httpWebRequest.CurrentAuthenticationState.TransportContext.GetChannelBinding(ChannelBindingKind.Endpoint);
                }
                securityContext = new NTAuthentication("WDigest", credential, computeSpn, httpWebRequest, channelBinding);
                httpWebRequest.CurrentAuthenticationState.SetSecurityContext(securityContext, this);
            }
            string str4 = securityContext.GetOutgoingDigestBlob(incomingBlob, httpWebRequest.CurrentMethod.Name, parts, null, false, false, out status);

            if (str4 == null)
            {
                return(null);
            }
            Authorization authorization = new Authorization("Digest " + str4, securityContext.IsCompleted, string.Empty, securityContext.IsMutualAuthFlag);

            if (!preAuthenticate && httpWebRequest.PreAuthenticate)
            {
                HttpDigestChallenge challenge3 = HttpDigest.Interpret(incomingBlob, -1, httpWebRequest);
                string[]            strArray   = (challenge3.Domain == null) ? new string[] { httpWebRequest.ChallengedUri.GetParts(UriComponents.SchemeAndServer, UriFormat.UriEscaped) } : challenge3.Domain.Split(singleSpaceArray);
                authorization.ProtectionRealm = (challenge3.Domain == null) ? null : strArray;
                for (int i = 0; i < strArray.Length; i++)
                {
                    challengeCache.Add(strArray[i], challenge3);
                }
            }
            return(authorization);
        }