From aa6b29fe7e60759afe2f5fec5350ee9add2b2fb9 Mon Sep 17 00:00:00 2001 From: Chocobo1 Date: Mon, 15 Aug 2022 11:56:59 +0800 Subject: [PATCH] Set HTTP method restriction on WebAPI actions PR #17548. --- src/webui/webapplication.cpp | 16 ++++++++++++++++ src/webui/webapplication.h | 15 +++++++++++++++ 2 files changed, 31 insertions(+) diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index bc161e17e..9308859fd 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -251,9 +251,11 @@ void WebApplication::doProcessRequest() const QString action = match.captured(u"action"_qs); const QString scope = match.captured(u"scope"_qs); + // Check public/private scope if (!session() && !isPublicAPI(scope, action)) throw ForbiddenHTTPError(); + // Find matching API APIController *controller = nullptr; if (session()) controller = session()->getAPIController(scope); @@ -265,6 +267,20 @@ void WebApplication::doProcessRequest() throw NotFoundHTTPError(); } + // Filter HTTP methods + const auto allowedMethodIter = m_allowedMethod.find({scope, action}); + if (allowedMethodIter == m_allowedMethod.end()) + { + // by default allow both GET, POST methods + if ((m_request.method != Http::METHOD_GET) && (m_request.method != Http::METHOD_POST)) + throw MethodNotAllowedHTTPError(); + } + else + { + if (*allowedMethodIter != m_request.method) + throw MethodNotAllowedHTTPError(); + } + DataMap data; for (const Http::UploadedFile &torrent : request().files) data[torrent.filename] = torrent.data; diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index db494cd9f..2eb8f12f6 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -29,6 +29,7 @@ #pragma once #include +#include #include #include @@ -137,6 +138,20 @@ private: const QRegularExpression m_apiPathPattern {u"^/api/v2/(?[A-Za-z_][A-Za-z_0-9]*)/(?[A-Za-z_][A-Za-z_0-9]*)$"_qs}; QSet m_publicAPIs; + const QHash, QString> m_allowedMethod = + { + // <, HTTP method> + // TODO: this list is incomplete + {{u"app"_qs, u"setPreferences"_qs}, Http::METHOD_POST}, + {{u"app"_qs, u"shutdown"_qs}, Http::METHOD_POST}, + {{u"auth"_qs, u"login"_qs}, Http::METHOD_POST}, + {{u"auth"_qs, u"logout"_qs}, Http::METHOD_POST}, + {{u"rss"_qs, u"addFeed"_qs}, Http::METHOD_POST}, + {{u"search"_qs, u"installPlugin"_qs}, Http::METHOD_POST}, + {{u"torrents"_qs, u"add"_qs}, Http::METHOD_POST}, + {{u"torrents"_qs, u"addPeers"_qs}, Http::METHOD_POST}, + {{u"torrents"_qs, u"addTrackers"_qs}, Http::METHOD_POST} + }; bool m_isAltUIUsed = false; Path m_rootFolder;