diff options
author | maksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-23 21:18:42 +0000 |
---|---|---|
committer | maksymb@chromium.org <maksymb@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2013-07-23 21:18:42 +0000 |
commit | e13d870701987ec2bd3d2d584a06a524be16f46a (patch) | |
tree | 08d195db75a32f624ac0c86a0e9aebbbd87e81bd /cloud_print | |
parent | 144c8e950add26b44467784568d0ca5387a1047d (diff) | |
download | chromium_src-e13d870701987ec2bd3d2d584a06a524be16f46a.zip chromium_src-e13d870701987ec2bd3d2d584a06a524be16f46a.tar.gz chromium_src-e13d870701987ec2bd3d2d584a06a524be16f46a.tar.bz2 |
Added HTTP-method (POST, GET) checking for Privet requests. Added IsRegistered() checking.
BUG=
Review URL: https://chromiumcodereview.appspot.com/19147003
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@213221 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'cloud_print')
-rw-r--r-- | cloud_print/gcp20/prototype/printer.cc | 9 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/printer.h | 2 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/privet_http_server.cc | 65 | ||||
-rw-r--r-- | cloud_print/gcp20/prototype/privet_http_server.h | 17 |
4 files changed, 78 insertions, 15 deletions
diff --git a/cloud_print/gcp20/prototype/printer.cc b/cloud_print/gcp20/prototype/printer.cc index aa6bcd5..04d3066 100644 --- a/cloud_print/gcp20/prototype/printer.cc +++ b/cloud_print/gcp20/prototype/printer.cc @@ -174,6 +174,10 @@ bool Printer::CheckXPrivetTokenHeader(const std::string& token) const { return xtoken_.CheckValidXToken(token); } +bool Printer::IsRegistered() const { + return reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED; +} + PrivetHttpServer::RegistrationErrorStatus Printer::RegistrationGetClaimToken( const std::string& user, std::string* token, @@ -290,8 +294,7 @@ void Printer::OnRegistrationError(const std::string& description) { PrivetHttpServer::RegistrationErrorStatus Printer::CheckCommonRegErrors( const std::string& user) const { - if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED) - return PrivetHttpServer::REG_ERROR_REGISTERED; + DCHECK(!IsRegistered()); if (reg_info_.state != RegistrationInfo::DEV_REG_UNREGISTERED && user != reg_info_.user) { @@ -324,7 +327,7 @@ std::vector<std::string> Printer::CreateTxt() const { void Printer::SaveToFile(const base::FilePath& file_path) const { base::DictionaryValue json; // TODO(maksymb): Get rid of in-place constants. - if (reg_info_.state == RegistrationInfo::DEV_REG_REGISTERED) { + if (IsRegistered()) { json.SetBoolean("registered", true); json.SetString("user", reg_info_.user); json.SetString("device_id", reg_info_.device_id); diff --git a/cloud_print/gcp20/prototype/printer.h b/cloud_print/gcp20/prototype/printer.h index b03c729..246e3df 100644 --- a/cloud_print/gcp20/prototype/printer.h +++ b/cloud_print/gcp20/prototype/printer.h @@ -79,7 +79,7 @@ class Printer : public PrivetHttpServer::Delegate, const std::string& user) OVERRIDE; virtual void GetRegistrationServerError(std::string* description) OVERRIDE; virtual void CreateInfo(PrivetHttpServer::DeviceInfo* info) OVERRIDE; - + virtual bool IsRegistered() const OVERRIDE; virtual bool CheckXPrivetTokenHeader(const std::string& token) const OVERRIDE; // CloudRequester::Delegate methods: diff --git a/cloud_print/gcp20/prototype/privet_http_server.cc b/cloud_print/gcp20/prototype/privet_http_server.cc index 55fcefb..33fd2ab 100644 --- a/cloud_print/gcp20/prototype/privet_http_server.cc +++ b/cloud_print/gcp20/prototype/privet_http_server.cc @@ -40,6 +40,21 @@ scoped_ptr<base::DictionaryValue> CreateErrorWithTimeout( return error.Pass(); } +// Returns |true| if |request| should be GET method. +bool IsGetMethod(const std::string& request) { + return request == "/privet/info"/* || + request == "/privet/accesstoken" || + request == "/privet/capabilities" || + request == "/privet/printer/jobstate"*/; +} + +// Returns |true| if |request| should be POST method. +bool IsPostMethod(const std::string& request) { + return request == "/privet/register"/* || + request == "/privet/printer/createjob" || + request == "/privet/printer/submitdoc"*/; +} + } // namespace PrivetHttpServer::DeviceInfo::DeviceInfo() : uptime(0) { @@ -86,12 +101,17 @@ void PrivetHttpServer::OnHttpRequest(int connection_id, VLOG(1) << "Processing HTTP request: " << info.path; GURL url("http://host" + info.path); + if (!ValidateRequestMethod(connection_id, url.path(), info.method)) + return; + if (!CommandLine::ForCurrentProcess()->HasSwitch("disable-x-token")) { net::HttpServerRequestInfo::HeadersMap::const_iterator iter = info.headers.find("X-Privet-Token"); if (iter == info.headers.end()) { server_->Send(connection_id, net::HTTP_BAD_REQUEST, - "Missing X-Privet-Token header.", "text/plain"); + "Missing X-Privet-Token header.\n" + "TODO: Message should be in header, not in the body!", + "text/plain"); return; } @@ -105,7 +125,8 @@ void PrivetHttpServer::OnHttpRequest(int connection_id, } std::string response; - net::HttpStatusCode status_code = ProcessHttpRequest(url, &response); + net::HttpStatusCode status_code = + ProcessHttpRequest(url, info.data, &response); // TODO(maksymb): Add checking for right |info.method| in query. server_->Send(connection_id, status_code, response, "application/json"); @@ -122,8 +143,36 @@ void PrivetHttpServer::OnWebSocketMessage(int connection_id, void PrivetHttpServer::OnClose(int connection_id) { } +void PrivetHttpServer::ReportInvalidMethod(int connection_id) { + server_->Send(connection_id, net::HTTP_BAD_REQUEST, "Invalid method", + "text/plain"); +} + +bool PrivetHttpServer::ValidateRequestMethod(int connection_id, + const std::string& request, + const std::string& method) { + DCHECK(!IsGetMethod(request) || !IsPostMethod(request)); + + if (!IsGetMethod(request) && !IsPostMethod(request)) { + server_->Send404(connection_id); + return false; + } + + if (CommandLine::ForCurrentProcess()->HasSwitch("disable-method-check")) + return true; + + if ((IsGetMethod(request) && method != "GET") || + (IsPostMethod(request) && method != "POST")) { + ReportInvalidMethod(connection_id); + return false; + } + + return true; +} + net::HttpStatusCode PrivetHttpServer::ProcessHttpRequest( const GURL& url, + const std::string& data, std::string* response) { net::HttpStatusCode status_code = net::HTTP_OK; scoped_ptr<base::DictionaryValue> json_response; @@ -133,8 +182,7 @@ net::HttpStatusCode PrivetHttpServer::ProcessHttpRequest( } else if (url.path() == "/privet/register") { json_response = ProcessRegister(url, &status_code); } else { - response->clear(); - return net::HTTP_NOT_FOUND; + NOTREACHED(); } if (!json_response) { @@ -188,7 +236,10 @@ scoped_ptr<base::DictionaryValue> PrivetHttpServer::ProcessInfo( scoped_ptr<base::DictionaryValue> PrivetHttpServer::ProcessRegister( const GURL& url, net::HttpStatusCode* status_code) { - // TODO(maksymb): Add saving state to drive. + if (delegate_->IsRegistered()) { + *status_code = net::HTTP_NOT_FOUND; + return scoped_ptr<base::DictionaryValue>(); + } std::string action; if (!net::GetValueForKeyInQuery(url, "action", &action)) { @@ -248,10 +299,6 @@ void PrivetHttpServer::ProcessRegistrationStatus( *status_code = net::HTTP_BAD_REQUEST; current_response->reset(); break; - case REG_ERROR_REGISTERED: - *status_code = net::HTTP_NOT_FOUND; - current_response->reset(); - break; case REG_ERROR_DEVICE_BUSY: *status_code = net::HTTP_OK; diff --git a/cloud_print/gcp20/prototype/privet_http_server.h b/cloud_print/gcp20/prototype/privet_http_server.h index 580774c..c4071f0 100644 --- a/cloud_print/gcp20/prototype/privet_http_server.h +++ b/cloud_print/gcp20/prototype/privet_http_server.h @@ -22,7 +22,6 @@ class PrivetHttpServer: public net::HttpServer::Delegate { enum RegistrationErrorStatus { REG_ERROR_OK, REG_ERROR_NO_RESULT, // default value, never set. - REG_ERROR_REGISTERED, REG_ERROR_DEVICE_BUSY, REG_ERROR_PENDING_USER_ACTION, @@ -83,9 +82,13 @@ class PrivetHttpServer: public net::HttpServer::Delegate { // Invoked for receiving server error details. virtual void GetRegistrationServerError(std::string* description) = 0; - // Invoked if /privet/info is called. + // Invoked when /privet/info is called. virtual void CreateInfo(DeviceInfo* info) = 0; + // Invoked for checking should /privet/register be exposed. + virtual bool IsRegistered() const = 0; + + // Invoked when XPrivetToken has to be checked. virtual bool CheckXPrivetTokenHeader(const std::string& token) const = 0; }; @@ -113,9 +116,19 @@ class PrivetHttpServer: public net::HttpServer::Delegate { const std::string& data) OVERRIDE; virtual void OnClose(int connection_id) OVERRIDE; + // Sends error as response. Invoked when request method is invalid. + void ReportInvalidMethod(int connection_id); + + // Returns |true| if |request| should be done with correct |method|. + // Otherwise sends |Invalid method| error. + // Also checks support of |request| by this server. + bool ValidateRequestMethod(int connection_id, const std::string& request, + const std::string& method); + // Processes http request after all preparations (XPrivetHeader check, // data handling etc.) net::HttpStatusCode ProcessHttpRequest(const GURL& url, + const std::string& data, std::string* response); // Pivet API methods. Return reference to NULL if output should be empty. |