diff --git a/src/base/preferences.cpp b/src/base/preferences.cpp index 1623e7f3d..e2aade35d 100644 --- a/src/base/preferences.cpp +++ b/src/base/preferences.cpp @@ -653,6 +653,16 @@ void Preferences::setWebUISessionTimeout(const int timeout) setValue(u"Preferences/WebUI/SessionTimeout"_qs, timeout); } +QString Preferences::getWebAPISessionCookieName() const +{ + return value(u"WebAPI/SessionCookieName"_qs); +} + +void Preferences::setWebAPISessionCookieName(const QString &cookieName) +{ + setValue(u"WebAPI/SessionCookieName"_qs, cookieName); +} + bool Preferences::isWebUiClickjackingProtectionEnabled() const { return value(u"Preferences/WebUI/ClickjackingProtection"_qs, true); diff --git a/src/base/preferences.h b/src/base/preferences.h index fa10fca50..86e81cae7 100644 --- a/src/base/preferences.h +++ b/src/base/preferences.h @@ -197,6 +197,8 @@ public: void setWebUIBanDuration(std::chrono::seconds duration); int getWebUISessionTimeout() const; void setWebUISessionTimeout(int timeout); + QString getWebAPISessionCookieName() const; + void setWebAPISessionCookieName(const QString &cookieName); // WebUI security bool isWebUiClickjackingProtectionEnabled() const; diff --git a/src/webui/webapplication.cpp b/src/webui/webapplication.cpp index f16e6e812..c3f2de6fb 100644 --- a/src/webui/webapplication.cpp +++ b/src/webui/webapplication.cpp @@ -47,7 +47,6 @@ #include "base/logger.h" #include "base/preferences.h" #include "base/types.h" -#include "base/utils/bytearray.h" #include "base/utils/fs.h" #include "base/utils/misc.h" #include "base/utils/random.h" @@ -63,7 +62,7 @@ #include "api/transfercontroller.h" const int MAX_ALLOWED_FILESIZE = 10 * 1024 * 1024; -const auto C_SID = QByteArrayLiteral("SID"); // name of session id cookie +const QString DEFAULT_SESSION_COOKIE_NAME = u"SID"_qs; const QString WWW_FOLDER = u":/www"_qs; const QString PUBLIC_FOLDER = u"/public"_qs; @@ -129,6 +128,18 @@ namespace return languages.join(u'\n'); } + + bool isValidCookieName(const QString &cookieName) + { + if (cookieName.isEmpty() || (cookieName.size() > 128)) + return false; + + const QRegularExpression invalidNameRegex {u"[^a-zA-Z0-9_\\-]"_qs}; + if (invalidNameRegex.match(cookieName).hasMatch()) + return false; + + return true; + } } WebApplication::WebApplication(IApplication *app, QObject *parent) @@ -141,6 +152,14 @@ WebApplication::WebApplication(IApplication *app, QObject *parent) configure(); connect(Preferences::instance(), &Preferences::changed, this, &WebApplication::configure); + + m_sessionCookieName = Preferences::instance()->getWebAPISessionCookieName(); + if (!isValidCookieName(m_sessionCookieName)) + { + LogMsg(tr("Unacceptable session cookie name is specified: '%1'. Default one is used.") + .arg(m_sessionCookieName), Log::WARNING); + m_sessionCookieName = DEFAULT_SESSION_COOKIE_NAME; + } } WebApplication::~WebApplication() @@ -563,7 +582,7 @@ void WebApplication::sessionInitialize() { Q_ASSERT(!m_currentSession); - const QString sessionId {parseCookie(m_request.headers.value(u"cookie"_qs)).value(QString::fromLatin1(C_SID))}; + const QString sessionId {parseCookie(m_request.headers.value(u"cookie"_qs)).value(m_sessionCookieName)}; // TODO: Additional session check @@ -649,7 +668,7 @@ void WebApplication::sessionStart() m_currentSession->registerAPIController(u"transfer"_qs); m_sessions[m_currentSession->id()] = m_currentSession; - QNetworkCookie cookie(C_SID, m_currentSession->id().toUtf8()); + QNetworkCookie cookie {m_sessionCookieName.toLatin1(), m_currentSession->id().toUtf8()}; cookie.setHttpOnly(true); cookie.setSecure(m_isSecureCookieEnabled && m_isHttpsEnabled); cookie.setPath(u"/"_qs); @@ -663,7 +682,7 @@ void WebApplication::sessionEnd() { Q_ASSERT(m_currentSession); - QNetworkCookie cookie(C_SID); + QNetworkCookie cookie {m_sessionCookieName.toLatin1()}; cookie.setPath(u"/"_qs); cookie.setExpirationDate(QDateTime::currentDateTime().addDays(-1)); diff --git a/src/webui/webapplication.h b/src/webui/webapplication.h index bc55919b0..bba270496 100644 --- a/src/webui/webapplication.h +++ b/src/webui/webapplication.h @@ -225,6 +225,7 @@ private: bool m_isAuthSubnetWhitelistEnabled; QVector m_authSubnetWhitelist; int m_sessionTimeout; + QString m_sessionCookieName; // security related QStringList m_domainList;