public Authorization Authenticate(string challenge, WebRequest webRequest, ICredentials credentials)
{
GlobalLog.Print("KerberosClient::Authenticate(): " + challenge);
GlobalLog.Assert(credentials != null, "KerberosClient::Authenticate() credentials==null", "");
if (credentials == null)
{
return(null);
}
HttpWebRequest httpWebRequest = webRequest as HttpWebRequest;
GlobalLog.Assert(httpWebRequest != null, "KerberosClient::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);
}
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);
}
NTAuthentication authSession = sessions[httpWebRequest.CurrentAuthenticationState] as NTAuthentication;
GlobalLog.Print("KerberosClient::Authenticate() key:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState) + " retrieved authSession:" + ValidationHelper.HashString(authSession));
if (authSession == null)
{
NetworkCredential NC = credentials.GetCredential(httpWebRequest.ChallengedUri, Signature);
GlobalLog.Print("KerberosClient::Authenticate() GetCredential() returns:" + ValidationHelper.ToString(NC));
if (NC == null)
{
return(null);
}
string username = NC.UserName;
if (username == null || (username.Length == 0 && !(NC is SystemNetworkCredential)))
{
return(null);
}
if (httpWebRequest.ChallengedSpn == null)
{
string host = httpWebRequest.ChallengedUri.Host;
if (httpWebRequest.ChallengedUri.HostNameType != UriHostNameType.IPv6 && httpWebRequest.ChallengedUri.HostNameType != UriHostNameType.IPv4 && host.IndexOf('.') == -1)
{
// only do the DNS lookup for short names, no form of IP addess
(new DnsPermission(PermissionState.Unrestricted)).Assert();
try {
host = Dns.GetHostByName(host).HostName;
GlobalLog.Print("KerberosClient::Authenticate() Dns returned host:" + ValidationHelper.ToString(host));
}
catch (Exception exception) {
GlobalLog.Print("KerberosClient::Authenticate() GetHostByName(host) failed:" + ValidationHelper.ToString(exception));
}
finally {
DnsPermission.RevertAssert();
}
}
// CONSIDER V.NEXT
// for now avoid appending the non default port to the
// SPN, sometime in the future we'll have to do this.
// httpWebRequest.ChallengedSpn = httpWebRequest.ChallengedUri.IsDefaultPort ? host : host + ":" + httpWebRequest.ChallengedUri.Port;
httpWebRequest.ChallengedSpn = host;
}
GlobalLog.Print("KerberosClient::Authenticate() ChallengedSpn:" + ValidationHelper.ToString(httpWebRequest.ChallengedSpn));
authSession =
new NTAuthentication(
AuthType,
NC,
"HTTP/" + httpWebRequest.ChallengedSpn,
httpWebRequest.DelegationFix);
GlobalLog.Print("KerberosClient::Authenticate() adding authSession:" + ValidationHelper.HashString(authSession) + " for:" + ValidationHelper.HashString(httpWebRequest.CurrentAuthenticationState));
sessions.Add(httpWebRequest.CurrentAuthenticationState, authSession);
}
bool handshakeComplete;
string clientResponse = authSession.GetOutgoingBlob(incoming, out handshakeComplete);
if (clientResponse == null)
{
return(null);
}
return(new Authorization(AuthType + " " + clientResponse, false, string.Empty));
}