Skip to content

Commit 8a39db5

Browse files
authored
Merge pull request #10351 from nextcloud/bugfix/notifyWss
fix: do not allow scheme change for push notifications
2 parents 84b05f4 + f60e451 commit 8a39db5

4 files changed

Lines changed: 50 additions & 5 deletions

File tree

src/libsync/account.cpp

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -60,6 +60,17 @@ constexpr int pushNotificationsReconnectInterval = 1000 * 60 * 2;
6060
constexpr int usernamePrefillServerVersionMinSupportedMajor = 24;
6161
constexpr int checksumRecalculateRequestServerVersionMinSupportedMajor = 24;
6262
constexpr auto isSkipE2eeMetadataChecksumValidationAllowedInClientVersion = MIRALL_VERSION_MAJOR == 3 && MIRALL_VERSION_MINOR == 8;
63+
64+
bool isPushNotificationsWebSocketUrlAllowed(const QUrl &accountUrl, const QUrl &webSocketUrl)
65+
{
66+
const auto webSocketScheme = webSocketUrl.scheme();
67+
if (webSocketScheme.compare(QLatin1String("wss"), Qt::CaseInsensitive) == 0) {
68+
return true;
69+
}
70+
71+
return webSocketScheme.compare(QLatin1String("ws"), Qt::CaseInsensitive) == 0
72+
&& accountUrl.scheme().compare(QLatin1String("http"), Qt::CaseInsensitive) == 0;
73+
}
6374
}
6475

6576
namespace OCC {
@@ -344,6 +355,17 @@ void Account::trySetupPushNotifications()
344355
_pushNotificationsReconnectTimer.stop();
345356

346357
if (_capabilities.availablePushNotifications() != PushNotificationType::None) {
358+
const auto webSocketUrl = _capabilities.pushNotificationsWebSocketUrl();
359+
if (!isPushNotificationsWebSocketUrlAllowed(url(), webSocketUrl)) {
360+
qCWarning(lcAccount) << "Reject insecure push notifications websocket endpoint" << webSocketUrl << "for account" << url();
361+
if (_pushNotifications) {
362+
delete _pushNotifications;
363+
_pushNotifications = nullptr;
364+
}
365+
emit pushNotificationsDisabled(sharedFromThis());
366+
return;
367+
}
368+
347369
qCInfo(lcAccount) << "Try to setup push notifications";
348370

349371
if (!_pushNotifications) {

test/pushnotificationstestutils.cpp

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -144,19 +144,21 @@ void FakeWebSocketServer::clearTextMessages()
144144
_processTextMessageSpy->clear();
145145
}
146146

147-
OCC::AccountPtr FakeWebSocketServer::createAccount(const QString &username, const QString &password)
147+
OCC::AccountPtr FakeWebSocketServer::createAccount(const QString &username,
148+
const QString &password,
149+
const QUrl &accountUrl,
150+
const QUrl &webSocketUrl)
148151
{
149152
auto account = OCC::Account::create();
153+
account->setUrl(accountUrl);
150154

151155
QStringList typeList;
152156
typeList.append("files");
153157
typeList.append("activities");
154158
typeList.append("notifications");
155159

156-
QString websocketUrl("ws://localhost:12345");
157-
158160
QVariantMap endpointsMap;
159-
endpointsMap["websocket"] = websocketUrl;
161+
endpointsMap["websocket"] = webSocketUrl;
160162

161163
QVariantMap notifyPushMap;
162164
notifyPushMap["type"] = typeList;

test/pushnotificationstestutils.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,10 @@ class FakeWebSocketServer : public QObject
3737

3838
void clearTextMessages();
3939

40-
static OCC::AccountPtr createAccount(const QString &username = "user", const QString &password = "password");
40+
static OCC::AccountPtr createAccount(const QString &username = "user",
41+
const QString &password = "password",
42+
const QUrl &accountUrl = QUrl(QStringLiteral("http://localhost")),
43+
const QUrl &webSocketUrl = QUrl(QStringLiteral("ws://localhost:12345")));
4144

4245
signals:
4346
void closed();

test/testpushnotifications.cpp

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -106,6 +106,24 @@ private slots:
106106
}));
107107
}
108108

109+
void testSetup_httpsAccountWithPlaintextWebSocket_doesNotSendCredentials()
110+
{
111+
FakeWebSocketServer fakeServer;
112+
const auto account = FakeWebSocketServer::createAccount(
113+
QStringLiteral("user"),
114+
QStringLiteral("app-password"),
115+
QUrl(QStringLiteral("https://cloud.example.test")),
116+
QUrl(QStringLiteral("ws://localhost:12345")));
117+
118+
QVERIFY(!account->pushNotifications());
119+
QCOMPARE(fakeServer.textMessagesCount(), 0);
120+
121+
account->trySetupPushNotifications();
122+
123+
QVERIFY(!account->pushNotifications());
124+
QCOMPARE(fakeServer.textMessagesCount(), 0);
125+
}
126+
109127
void testOnWebSocketTextMessageReceived_notifyFileMessage_emitFilesChanged()
110128
{
111129
FakeWebSocketServer fakeServer;

0 commit comments

Comments
 (0)