mirror of https://github.com/Icinga/icinga2.git
Only read body from authenticated connections
This means we are not allowing unauthenticated requests anymore
This commit is contained in:
parent
e1c46cedd1
commit
a46dc64e6a
|
@ -29,19 +29,22 @@
|
||||||
using namespace icinga;
|
using namespace icinga;
|
||||||
|
|
||||||
HttpRequest::HttpRequest(const Stream::Ptr& stream)
|
HttpRequest::HttpRequest(const Stream::Ptr& stream)
|
||||||
: Complete(false),
|
: CompleteHeaders(false),
|
||||||
|
CompleteBody(false),
|
||||||
ProtocolVersion(HttpVersion11),
|
ProtocolVersion(HttpVersion11),
|
||||||
Headers(new Dictionary()),
|
Headers(new Dictionary()),
|
||||||
m_Stream(stream),
|
m_Stream(stream),
|
||||||
m_State(HttpRequestStart)
|
m_State(HttpRequestStart)
|
||||||
{ }
|
{ }
|
||||||
|
|
||||||
bool HttpRequest::Parse(StreamReadContext& src, bool may_wait)
|
bool HttpRequest::ParseHeader(StreamReadContext& src, bool may_wait)
|
||||||
{
|
{
|
||||||
if (!m_Stream)
|
if (!m_Stream)
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if (m_State != HttpRequestBody) {
|
if (m_State != HttpRequestStart && m_State != HttpRequestHeaders)
|
||||||
|
return false;
|
||||||
|
|
||||||
String line;
|
String line;
|
||||||
StreamReadStatus srs = m_Stream->ReadLine(&line, src, may_wait);
|
StreamReadStatus srs = m_Stream->ReadLine(&line, src, may_wait);
|
||||||
|
|
||||||
|
@ -60,8 +63,7 @@ bool HttpRequest::Parse(StreamReadContext& src, bool may_wait)
|
||||||
if (line == "")
|
if (line == "")
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
std::vector<String> tokens;
|
std::vector<String> tokens = line.Split(" ");
|
||||||
boost::algorithm::split(tokens, line, boost::is_any_of(" "));
|
|
||||||
Log(LogDebug, "HttpRequest")
|
Log(LogDebug, "HttpRequest")
|
||||||
<< "line: " << line << ", tokens: " << tokens.size();
|
<< "line: " << line << ", tokens: " << tokens.size();
|
||||||
if (tokens.size() != 3)
|
if (tokens.size() != 3)
|
||||||
|
@ -78,16 +80,11 @@ bool HttpRequest::Parse(StreamReadContext& src, bool may_wait)
|
||||||
BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported HTTP version"));
|
BOOST_THROW_EXCEPTION(std::invalid_argument("Unsupported HTTP version"));
|
||||||
|
|
||||||
m_State = HttpRequestHeaders;
|
m_State = HttpRequestHeaders;
|
||||||
} else if (m_State == HttpRequestHeaders) {
|
return true;
|
||||||
|
} else { // m_State = HttpRequestHeaders
|
||||||
if (line == "") {
|
if (line == "") {
|
||||||
m_State = HttpRequestBody;
|
m_State = HttpRequestBody;
|
||||||
|
CompleteHeaders = true;
|
||||||
/* we're done if the request doesn't contain a message body */
|
|
||||||
if (!Headers->Contains("content-length") && !Headers->Contains("transfer-encoding"))
|
|
||||||
Complete = true;
|
|
||||||
else
|
|
||||||
m_Body = new FIFO();
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
|
@ -104,11 +101,27 @@ bool HttpRequest::Parse(StreamReadContext& src, bool may_wait)
|
||||||
|
|
||||||
if (key == "x-http-method-override")
|
if (key == "x-http-method-override")
|
||||||
RequestMethod = value;
|
RequestMethod = value;
|
||||||
|
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
VERIFY(!"Invalid HTTP request state.");
|
|
||||||
}
|
}
|
||||||
} else if (m_State == HttpRequestBody) {
|
}
|
||||||
|
|
||||||
|
bool HttpRequest::ParseBody(StreamReadContext& src, bool may_wait)
|
||||||
|
{
|
||||||
|
if (!m_Stream || m_State != HttpRequestBody)
|
||||||
|
return false;
|
||||||
|
|
||||||
|
/* we're done if the request doesn't contain a message body */
|
||||||
|
if (!Headers->Contains("content-length") && !Headers->Contains("transfer-encoding")) {
|
||||||
|
CompleteBody = true;
|
||||||
|
return true;
|
||||||
|
} else if (!m_Body)
|
||||||
|
m_Body = new FIFO();
|
||||||
|
|
||||||
|
if (CompleteBody)
|
||||||
|
return true;
|
||||||
|
|
||||||
if (Headers->Get("transfer-encoding") == "chunked") {
|
if (Headers->Get("transfer-encoding") == "chunked") {
|
||||||
if (!m_ChunkContext)
|
if (!m_ChunkContext)
|
||||||
m_ChunkContext = boost::make_shared<ChunkReadContext>(boost::ref(src));
|
m_ChunkContext = boost::make_shared<ChunkReadContext>(boost::ref(src));
|
||||||
|
@ -125,7 +138,7 @@ bool HttpRequest::Parse(StreamReadContext& src, bool may_wait)
|
||||||
delete [] data;
|
delete [] data;
|
||||||
|
|
||||||
if (size == 0) {
|
if (size == 0) {
|
||||||
Complete = true;
|
CompleteBody = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,10 +168,9 @@ bool HttpRequest::Parse(StreamReadContext& src, bool may_wait)
|
||||||
|
|
||||||
m_Body->Write(src.Buffer, length_indicator);
|
m_Body->Write(src.Buffer, length_indicator);
|
||||||
src.DropData(length_indicator);
|
src.DropData(length_indicator);
|
||||||
Complete = true;
|
CompleteBody = true;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -52,7 +52,8 @@ enum HttpRequestState
|
||||||
struct I2_REMOTE_API HttpRequest
|
struct I2_REMOTE_API HttpRequest
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
bool Complete;
|
bool CompleteHeaders;
|
||||||
|
bool CompleteBody;
|
||||||
|
|
||||||
String RequestMethod;
|
String RequestMethod;
|
||||||
Url::Ptr RequestUrl;
|
Url::Ptr RequestUrl;
|
||||||
|
@ -62,7 +63,8 @@ public:
|
||||||
|
|
||||||
HttpRequest(const Stream::Ptr& stream);
|
HttpRequest(const Stream::Ptr& stream);
|
||||||
|
|
||||||
bool Parse(StreamReadContext& src, bool may_wait);
|
bool ParseHeader(StreamReadContext& src, bool may_wait);
|
||||||
|
bool ParseBody(StreamReadContext& src, bool may_wait);
|
||||||
size_t ReadBody(char *data, size_t count);
|
size_t ReadBody(char *data, size_t count);
|
||||||
|
|
||||||
void AddHeader(const String& key, const String& value);
|
void AddHeader(const String& key, const String& value);
|
||||||
|
|
|
@ -92,7 +92,7 @@ bool HttpServerConnection::ProcessMessage(void)
|
||||||
bool res;
|
bool res;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
res = m_CurrentRequest.Parse(m_Context, false);
|
res = m_CurrentRequest.ParseHeader(m_Context, false);
|
||||||
} catch (const std::invalid_argument& ex) {
|
} catch (const std::invalid_argument& ex) {
|
||||||
HttpResponse response(m_Stream, m_CurrentRequest);
|
HttpResponse response(m_Stream, m_CurrentRequest);
|
||||||
response.SetStatus(400, "Bad request");
|
response.SetStatus(400, "Bad request");
|
||||||
|
@ -113,7 +113,7 @@ bool HttpServerConnection::ProcessMessage(void)
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (m_CurrentRequest.Complete) {
|
if (m_CurrentRequest.CompleteHeaders) {
|
||||||
m_RequestQueue.Enqueue(boost::bind(&HttpServerConnection::ProcessMessageAsync,
|
m_RequestQueue.Enqueue(boost::bind(&HttpServerConnection::ProcessMessageAsync,
|
||||||
HttpServerConnection::Ptr(this), m_CurrentRequest));
|
HttpServerConnection::Ptr(this), m_CurrentRequest));
|
||||||
|
|
||||||
|
@ -240,6 +240,16 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request)
|
||||||
String msg = "<h1>Unauthorized. Please check your user credentials.</h1>";
|
String msg = "<h1>Unauthorized. Please check your user credentials.</h1>";
|
||||||
response.WriteBody(msg.CStr(), msg.GetLength());
|
response.WriteBody(msg.CStr(), msg.GetLength());
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
bool res = true;
|
||||||
|
while (!request.CompleteBody)
|
||||||
|
res = request.ParseBody(m_Context, false);
|
||||||
|
if (!res) {
|
||||||
|
Log(LogCritical, "HttpServerConnection", "Failed to read body");
|
||||||
|
Dictionary::Ptr result = new Dictionary;
|
||||||
|
result->Set("error", 404);
|
||||||
|
result->Set("status", "Bad Request: Malformed body.");
|
||||||
|
HttpUtility::SendJsonBody(response, result);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
HttpHandler::ProcessRequest(user, request, response);
|
HttpHandler::ProcessRequest(user, request, response);
|
||||||
|
@ -252,7 +262,6 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request)
|
||||||
|
|
||||||
if (request.Headers->Get("accept") == "application/json") {
|
if (request.Headers->Get("accept") == "application/json") {
|
||||||
Dictionary::Ptr result = new Dictionary();
|
Dictionary::Ptr result = new Dictionary();
|
||||||
|
|
||||||
result->Set("error", 503);
|
result->Set("error", 503);
|
||||||
result->Set("status", errorInfo);
|
result->Set("status", errorInfo);
|
||||||
|
|
||||||
|
@ -263,6 +272,7 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
response.Finish();
|
response.Finish();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue