public bool AllowAPICall(string method, OSHttpRequest request, OSHttpResponse response)
{
Dictionary<string, string> authorization = authorizationHeader(request);
if (authorization != null)
{
string storednonce;
if (
authorization.ContainsKey("username") &&
authorization.ContainsKey("realm") &&
authorization.ContainsKey("uri") &&
authorization.ContainsKey("qop") &&
authorization.ContainsKey("nonce") &&
authorization.ContainsKey("nc") &&
authorization.ContainsKey("cnonce") &&
authorization.ContainsKey("opaque") &&
m_authNonces.TryGetValue(authorization["opaque"], out storednonce) &&
authorization["nonce"] == storednonce
)
{
m_authNonces.Remove(authorization["opaque"]);
UUID accountID = authUser(request);
if (accountID == UUID.Zero)
{
response.StatusCode = 403;
response.StatusDescription = "Forbidden";
MainConsole.Instance.DebugFormat("[WebAPI]: {0} is not permitted to use WebAPI", authorization["username"], method);
}
else
{
string password = Utils.MD5String(m_connector.GetAccessToken(accountID).ToString());
string HA1 = Util.Md5Hash(string.Join(":", new string[]{
authorization["username"],
Name,
password
}));
string HA2 = Util.Md5Hash(request.HttpMethod + ":" + authorization["uri"]);
string expectedDigestResponse = (authorization.ContainsKey("qop") && authorization["qop"] == "auth") ? Util.Md5Hash(string.Join(":", new string[]{
HA1,
storednonce,
authorization["nc"],
authorization["cnonce"],
"auth",
HA2
})) : Util.Md5Hash(string.Join(":", new string[]{
HA1,
storednonce,
HA2
}));
if (expectedDigestResponse == authorization["response"])
{
if (m_connector.AllowAPICall(accountID, method))
{
m_connector.LogAPICall(accountID, method);
return true;
}
else if (m_connector.GetRateLimit(accountID, method) == null)
{
response.StatusCode = 403;
response.StatusDescription = "Forbidden";
MainConsole.Instance.DebugFormat("[WebAPI]: {0} is not permitted to use API method {1}", authorization["username"], method);
}
else if (m_connector.RateLimitExceed(accountID, method))
{
response.StatusCode = 429;
response.StatusDescription = "Too Many Requests";
MainConsole.Instance.DebugFormat("[WebAPI]: {0} exceeded their hourly rate limit for API method {1}", authorization["username"], method);
}
else
{
response.StatusCode = 500;
MainConsole.Instance.DebugFormat("[WebAPI]: {0} cannotuse API method {1}, although we're not sure why.", authorization["username"], method);
}
}
else
{
MainConsole.Instance.DebugFormat("[WebAPI]: API authentication failed for {0}", authorization["username"]);
}
}
}
}
else
{
string opaque = UUID.Random().ToString();
string nonce = UUID.Random().ToString();
m_authNonces.Add(opaque, nonce, 5);
response.StatusCode = 401;
response.StatusDescription = "Unauthorized";
string digestHeader = "Digest " + string.Join(", ", new string[]{
"realm=\"" + Name + "\"",
"qop=\"auth\"",
"nonce=\"" + nonce + "\"",
"opaque=\"" + opaque + "\""
});
response.AddHeader("WWW-Authenticate", digestHeader);
}
return false;
}