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); }
// // 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; }
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); }