From 7e5f5544fc06fea0ef36e7c83a95a63ed368b48c Mon Sep 17 00:00:00 2001 From: Michael Friedrich Date: Thu, 5 Nov 2015 15:18:53 +0100 Subject: [PATCH] Require 'Accept' header for API requests (except for GET) fixes #10548 --- lib/remote/apiclient.cpp | 4 ++++ lib/remote/configfileshandler.cpp | 5 +++++ lib/remote/httpserverconnection.cpp | 9 ++++++++- 3 files changed, 17 insertions(+), 1 deletion(-) diff --git a/lib/remote/apiclient.cpp b/lib/remote/apiclient.cpp index 11dd39e97..af035b36f 100644 --- a/lib/remote/apiclient.cpp +++ b/lib/remote/apiclient.cpp @@ -51,6 +51,7 @@ void ApiClient::GetTypes(const TypesCompletionCallback& callback) const req->RequestMethod = "GET"; req->RequestUrl = url; req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password)); + req->AddHeader("Accept", "application/json"); m_Connection->SubmitRequest(req, boost::bind(TypesHttpCompletionCallback, _1, _2, callback)); } catch (const std::exception& ex) { callback(boost::current_exception(), std::vector()); @@ -134,6 +135,7 @@ void ApiClient::GetObjects(const String& pluralType, const ObjectsCompletionCall req->RequestMethod = "GET"; req->RequestUrl = url; req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password)); + req->AddHeader("Accept", "application/json"); m_Connection->SubmitRequest(req, boost::bind(ObjectsHttpCompletionCallback, _1, _2, callback)); } catch (const std::exception& ex) { callback(boost::current_exception(), std::vector()); @@ -231,6 +233,7 @@ void ApiClient::ExecuteScript(const String& session, const String& command, bool req->RequestMethod = "POST"; req->RequestUrl = url; req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password)); + req->AddHeader("Accept", "application/json"); m_Connection->SubmitRequest(req, boost::bind(ExecuteScriptHttpCompletionCallback, _1, _2, callback)); } catch (const std::exception& ex) { callback(boost::current_exception(), Empty); @@ -315,6 +318,7 @@ void ApiClient::AutocompleteScript(const String& session, const String& command, req->RequestMethod = "POST"; req->RequestUrl = url; req->AddHeader("Authorization", "Basic " + Base64::Encode(m_User + ":" + m_Password)); + req->AddHeader("Accept", "application/json"); m_Connection->SubmitRequest(req, boost::bind(AutocompleteScriptHttpCompletionCallback, _1, _2, callback)); } catch (const std::exception& ex) { callback(boost::current_exception(), Array::Ptr()); diff --git a/lib/remote/configfileshandler.cpp b/lib/remote/configfileshandler.cpp index 5e586a940..b346c1e99 100644 --- a/lib/remote/configfileshandler.cpp +++ b/lib/remote/configfileshandler.cpp @@ -49,6 +49,11 @@ bool ConfigFilesHandler::HandleRequest(const ApiUser::Ptr& user, HttpRequest& re params->Set("path", boost::algorithm::join(tmpPath, "/")); } + if (request.Headers->Get("accept") == "application/json") { + HttpUtility::SendJsonError(response, 400, "Invalid Accept header. Either remove the Accept header or set it to 'application/octet-stream'."); + return true; + } + FilterUtility::CheckPermission(user, "config/query"); String packageName = HttpUtility::GetLastParameter(params, "package"); diff --git a/lib/remote/httpserverconnection.cpp b/lib/remote/httpserverconnection.cpp index 044983b71..3e821cb17 100644 --- a/lib/remote/httpserverconnection.cpp +++ b/lib/remote/httpserverconnection.cpp @@ -161,7 +161,14 @@ void HttpServerConnection::ProcessMessageAsync(HttpRequest& request) HttpResponse response(m_Stream, request); - if (!user) { + String accept_header = request.Headers->Get("accept"); + + if (request.RequestMethod != "GET" && accept_header != "application/json") { + response.SetStatus(400, "Wrong Accept header"); + response.AddHeader("Content-Type", "text/html"); + String msg = "

Accept header is missing or not set to 'application/json'.

"; + response.WriteBody(msg.CStr(), msg.GetLength()); + } else if (!user) { Log(LogWarning, "HttpServerConnection") << "Unauthorized request: " << request.RequestMethod << " " << requestUrl; response.SetStatus(401, "Unauthorized");