author | Andrea Scarpino
<andrea@archlinux.org> 2015-01-17 08:11:47 UTC |
committer | Andrea Scarpino
<andrea@archlinux.org> 2015-01-17 08:11:47 UTC |
parent | 4f8cfc86a53a2acfb337b62a45543f46ecee9982 |
PKGBUILD | +6 | -4 |
screenlocker-input.patch | +705 | -0 |
screenlocker-network.patch | +171 | -0 |
diff --git a/PKGBUILD b/PKGBUILD index 34efdae..fad957d 100644 --- a/PKGBUILD +++ b/PKGBUILD @@ -4,7 +4,7 @@ pkgname=plasma-workspace pkgver=5.1.2 -pkgrel=2 +pkgrel=3 pkgdesc='KDE Plasma Workspace' arch=('i686' 'x86_64') url='https://projects.kde.org/projects/kde/workspace/plasma-workspace' @@ -15,15 +15,17 @@ depends=('knewstuff' 'baloo-frameworks' 'kjsembed' 'knotifyconfig' 'libxcursor' 'xorg-xrdb' 'xorg-xsetroot' 'xorg-xmessage') makedepends=('extra-cmake-modules' 'kdoctools' 'kwin' 'gpsd') optdepends=('plasma-workspace-wallpapers: additional wallpapers' - 'kwin: KDE Window Manager' 'gpsd: GPS support for geolocation') conflicts=('kdebase-workspace') groups=('plasma-next') options=('!buildflags') source=("http://download.kde.org/stable/plasma/${pkgver}/$pkgname-$pkgver.tar.xz" - 'kde.pam') + 'kde.pam' + 'screenlocker-input.patch' 'screenlocker-network.patch') md5sums=('8a01835179b25e3a7ff644fd7e52ec96' - '929b182dec8a096206ad493477c09d2c') + '929b182dec8a096206ad493477c09d2c' + '7e426d07806d8887879d932791bba869' + 'd67e504422a7e80a91b7adf3f41563f5') prepare() { mkdir -p build diff --git a/screenlocker-input.patch b/screenlocker-input.patch new file mode 100644 index 0000000..d4417f2 --- /dev/null +++ b/screenlocker-input.patch @@ -0,0 +1,705 @@ +commit 0ac34dca5d6a6ea8fc5c06e1dae96fb1ad4ce7c9 +Author: Martin Gräßlin <mgraesslin@kde.org> +Date: Wed Dec 10 13:22:49 2014 +0100 + + Use out-of-band communication between ksld and greeter + + The screenlocker_greet needs to tell the parent ksld process which + windows it created. Ksld sends input events to these windows. So + far this was based on an X property on the window. Unfortunately + ksld didn't validate whether the windows tagged with this property + belong to the screenlocker_greet process it started. + + With this change the communication for announcing windows is moved + away from the X11 protocol and instead a custom Wayland protocol is + used. + + Ksld starts a KWaylandServer when the greet process gets started. It + creates anonymous unix sockets for the connection and passes one + filedescriptor to the started greeter process. + + The check for the X property is removed in ksld and instead only + windows ids passed through the Wayland socket connection are + accepted. + + REVIEW: 121429 + +diff --git a/CMakeLists.txt b/CMakeLists.txt +index c6d89c1..227eace 100644 +--- a/CMakeLists.txt ++++ b/CMakeLists.txt +@@ -74,6 +74,16 @@ if(X11_FOUND AND XCB_XCB_FOUND) + set(HAVE_X11 1) + endif() + ++find_package(KF5Wayland CONFIG) ++set_package_properties(KF5Wayland PROPERTIES ++ TYPE REQUIRED ++ PURPOSE "Required for building screenlocker") ++find_package(WaylandScanner) ++find_package(Wayland 1.3 COMPONENTS Client Server) ++set_package_properties(Wayland PROPERTIES ++ TYPE REQUIRED ++ PURPOSE "Required for building screenlocker") ++ + include(ConfigureChecks.cmake) + + include_directories("${CMAKE_CURRENT_BINARY_DIR}") +diff --git a/ksmserver/screenlocker/CMakeLists.txt b/ksmserver/screenlocker/CMakeLists.txt +index 5378a10..83a5b39 100644 +--- a/ksmserver/screenlocker/CMakeLists.txt ++++ b/ksmserver/screenlocker/CMakeLists.txt +@@ -1,6 +1,9 @@ + remove_definitions(-DTRANSLATION_DOMAIN=\"ksmserver\") + add_definitions(-DTRANSLATION_DOMAIN=\"kscreenlocker\") + ++# adjusting CMAKE_C_FLAGS to get wayland protocols to compile ++set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") ++ + add_definitions(-DKDE_DEFAULT_DEBUG_AREA=1223) + add_subdirectory(kcheckpass) + add_subdirectory(greeter) +@@ -17,6 +20,7 @@ set(ksld_SRCS + interface.cpp + lockwindow.cpp + logind.cpp ++ waylandserver.cpp + ) + qt5_add_dbus_adaptor(ksld_SRCS ${screensaver_dbusXML} interface.h ScreenLocker::Interface) + qt5_add_dbus_adaptor(ksld_SRCS ${kscreensaver_dbusXML} interface.h ScreenLocker::Interface kscreensaveradaptor KScreenSaverAdaptor) +@@ -24,6 +28,11 @@ kconfig_add_kcfg_files(ksld_SRCS kcfg/kscreensaversettings.kcfgc) + qt5_add_dbus_interface(ksld_SRCS ${ksmserver_xml} ksmserver_interface) + qt5_add_dbus_interface(ksld_SRCS ${powerdevilpolicyagent_xml} powerdevilpolicyagent) + ++ecm_add_wayland_server_protocol(ksld_SRCS ++ PROTOCOL protocols/ksld.xml ++ BASENAME ksld ++) ++ + add_library(screenlocker_static STATIC ${ksld_SRCS}) + + target_link_libraries(screenlocker_static +@@ -39,6 +48,8 @@ target_link_libraries(screenlocker_static + ${X11_LIBRARIES} + ${X11_Xcursor_LIB} + XCB::XCB ++ KF5::WaylandServer ++ Wayland::Server + ) + + # Needed to compile on Arm target. +diff --git a/ksmserver/screenlocker/greeter/CMakeLists.txt b/ksmserver/screenlocker/greeter/CMakeLists.txt +index 10c4734..14a34f0 100644 +--- a/ksmserver/screenlocker/greeter/CMakeLists.txt ++++ b/ksmserver/screenlocker/greeter/CMakeLists.txt +@@ -18,6 +18,11 @@ set(kscreenlocker_greet_SRCS + qt5_add_resources(kscreenlocker_greet_SRCS fallbacktheme.qrc) + kconfig_add_kcfg_files(kscreenlocker_greet_SRCS ${CMAKE_CURRENT_SOURCE_DIR}/../kcfg/kscreensaversettings.kcfgc) + ++ecm_add_wayland_client_protocol(kscreenlocker_greet_SRCS ++ PROTOCOL ../protocols/ksld.xml ++ BASENAME ksld ++) ++ + add_executable(kscreenlocker_greet ${kscreenlocker_greet_SRCS}) + + target_link_libraries(kscreenlocker_greet +@@ -36,6 +41,8 @@ target_link_libraries(kscreenlocker_greet + Qt5::X11Extras + ${X11_LIBRARIES} + KF5::KDELibs4Support ++ KF5::WaylandClient ++ Wayland::Client + ) + + install(TARGETS kscreenlocker_greet DESTINATION ${LIBEXEC_INSTALL_DIR}) +diff --git a/ksmserver/screenlocker/greeter/greeterapp.cpp b/ksmserver/screenlocker/greeter/greeterapp.cpp +index f2e7ab9..824ba60 100644 +--- a/ksmserver/screenlocker/greeter/greeterapp.cpp ++++ b/ksmserver/screenlocker/greeter/greeterapp.cpp +@@ -33,10 +33,15 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. + #include <Plasma/Package> + #include <Plasma/PackageStructure> + #include <Plasma/PluginLoader> ++// KWayland ++#include <KWayland/Client/connection_thread.h> ++#include <KWayland/Client/event_queue.h> ++#include <KWayland/Client/registry.h> + // Qt + #include <QtCore/QTimer> + #include <QtGui/QKeyEvent> + #include <qscreen.h> ++#include <QThread> + + #include <QQuickView> + #include <QQuickItem> +@@ -45,6 +50,9 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. + #include <QQmlProperty> + + #include <QX11Info> ++// Wayland ++#include <wayland-client.h> ++#include <wayland-ksld-client-protocol.h> + // X11 + #include <X11/Xatom.h> + #include <X11/Xlib.h> +@@ -77,6 +85,18 @@ UnlockApp::UnlockApp(int &argc, char **argv) + UnlockApp::~UnlockApp() + { + qDeleteAll(m_views); ++ ++ if (m_ksldInterface) { ++ org_kde_ksld_destroy(m_ksldInterface); ++ } ++ if (m_ksldRegistry) { ++ delete m_ksldRegistry; ++ } ++ if (m_ksldConnection) { ++ m_ksldConnection->deleteLater(); ++ m_ksldConnectionThread->quit(); ++ m_ksldConnectionThread->wait(); ++ } + } + + void UnlockApp::initialize() +@@ -146,6 +166,12 @@ void UnlockApp::desktopResized() + view->setFlags(Qt::X11BypassWindowManagerHint); + } + ++ if (m_ksldInterface) { ++ view->create(); ++ org_kde_ksld_x11window(m_ksldInterface, view->winId()); ++ wl_display_flush(m_ksldConnection->display()); ++ } ++ + // engine stuff + QQmlContext* context = view->engine()->rootContext(); + const KUser user; +@@ -390,5 +416,43 @@ void UnlockApp::setNoLock(bool noLock) + m_noLock = noLock; + } + ++void UnlockApp::setKsldSocket(int socket) ++{ ++ using namespace KWayland::Client; ++ m_ksldConnection = new ConnectionThread; ++ m_ksldConnection->setSocketFd(socket); ++ ++ m_ksldRegistry = new Registry(); ++ EventQueue *queue = new EventQueue(m_ksldRegistry); ++ ++ connect(m_ksldRegistry, &Registry::interfaceAnnounced, this, ++ [this, queue] (QByteArray interface, quint32 name, quint32 version) { ++ if (interface != QByteArrayLiteral("org_kde_ksld")) { ++ return; ++ } ++ m_ksldInterface = reinterpret_cast<org_kde_ksld*>(wl_registry_bind(*m_ksldRegistry, name, &org_kde_ksld_interface, version)); ++ queue->addProxy(m_ksldInterface); ++ for (auto v : m_views) { ++ org_kde_ksld_x11window(m_ksldInterface, v->winId()); ++ wl_display_flush(m_ksldConnection->display()); ++ } ++ } ++ ); ++ ++ connect(m_ksldConnection, &ConnectionThread::connected, this, ++ [this, queue] { ++ m_ksldRegistry->create(m_ksldConnection); ++ queue->setup(m_ksldConnection); ++ m_ksldRegistry->setEventQueue(queue); ++ m_ksldRegistry->setup(); ++ wl_display_flush(m_ksldConnection->display()); ++ }, Qt::QueuedConnection); ++ ++ m_ksldConnectionThread = new QThread(this); ++ m_ksldConnection->moveToThread(m_ksldConnectionThread); ++ m_ksldConnectionThread->start(); ++ m_ksldConnection->initConnection(); ++} ++ + } // namespace + +diff --git a/ksmserver/screenlocker/greeter/greeterapp.h b/ksmserver/screenlocker/greeter/greeterapp.h +index b92b13b..4a90faf 100644 +--- a/ksmserver/screenlocker/greeter/greeterapp.h ++++ b/ksmserver/screenlocker/greeter/greeterapp.h +@@ -29,8 +29,17 @@ namespace Plasma { + class Package; + }; + ++namespace KWayland { ++namespace Client { ++ class ConnectionThread; ++ class Registry; ++} ++} ++ + class Authenticator; + ++struct org_kde_ksld; ++ + namespace ScreenLocker + { + class Unlocker; +@@ -47,6 +56,7 @@ public: + void lockImmediately(); + void setGraceTime(int milliseconds); + void setNoLock(bool noLock); ++ void setKsldSocket(int socket); + + public Q_SLOTS: + void desktopResized(); +@@ -78,6 +88,11 @@ private: + Authenticator *m_authenticator; + int m_graceTime; + bool m_noLock; ++ ++ KWayland::Client::ConnectionThread *m_ksldConnection = nullptr; ++ KWayland::Client::Registry *m_ksldRegistry = nullptr; ++ QThread *m_ksldConnectionThread = nullptr; ++ org_kde_ksld *m_ksldInterface = nullptr; + }; + } // namespace + +diff --git a/ksmserver/screenlocker/greeter/main.cpp b/ksmserver/screenlocker/greeter/main.cpp +index 12e5701..4477363 100644 +--- a/ksmserver/screenlocker/greeter/main.cpp ++++ b/ksmserver/screenlocker/greeter/main.cpp +@@ -80,11 +80,15 @@ int main(int argc, char* argv[]) + QStringLiteral("0")); + QCommandLineOption nolockOption(QStringLiteral("nolock"), + i18n("Don't show any lock user interface.")); ++ QCommandLineOption waylandFdOption(QStringLiteral("ksldfd"), ++ i18n("File descriptor for connecting to ksld."), ++ QStringLiteral("fd")); + + parser.addOption(testingOption); + parser.addOption(immediateLockOption); + parser.addOption(graceTimeOption); + parser.addOption(nolockOption); ++ parser.addOption(waylandFdOption); + parser.process(app); + + if (parser.isSet(testingOption)) { +@@ -94,11 +98,20 @@ int main(int argc, char* argv[]) + app.setImmediateLock(parser.isSet(immediateLockOption)); + } + app.setNoLock(parser.isSet(nolockOption)); ++ + bool ok = false; + int graceTime = parser.value(graceTimeOption).toInt(&ok); + if (ok) { + app.setGraceTime(graceTime); + } ++ ++ if (parser.isSet(waylandFdOption)) { ++ ok = false; ++ const int fd = parser.value(waylandFdOption).toInt(&ok); ++ if (ok) { ++ app.setKsldSocket(fd); ++ } ++ } + app.desktopResized(); + + // This allow ksmserver to know when the applicaion has actually finished setting itself up. +diff --git a/ksmserver/screenlocker/ksldapp.cpp b/ksmserver/screenlocker/ksldapp.cpp +index 94eccd4..addf49e 100644 +--- a/ksmserver/screenlocker/ksldapp.cpp ++++ b/ksmserver/screenlocker/ksldapp.cpp +@@ -26,6 +26,7 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. + #include "logind.h" + #include "kscreensaversettings.h" + #include <config-ksmserver.h> ++#include "waylandserver.h" + // workspace + #include <kdisplaymanager.h> + // KDE +@@ -68,6 +69,7 @@ KSldApp::KSldApp(QObject * parent) + , m_lockState(Unlocked) + , m_lockProcess(NULL) + , m_lockWindow(NULL) ++ , m_waylandServer(new WaylandServer(this)) + , m_lockedTimer(QElapsedTimer()) + , m_idleId(0) + , m_lockGrace(0) +@@ -330,6 +332,7 @@ void KSldApp::doUnlock() + m_lockedTimer.invalidate(); + endGraceTime(); + KDisplayManager().setLock(false); ++ m_waylandServer->stop(); + emit unlocked(); + // KNotification::event( QLatin1String("unlocked")); + } +@@ -347,12 +350,25 @@ bool KSldApp::startLockProcess(EstablishLock establishLock) + if (m_lockGrace == -1) { + args << "--nolock"; + } ++ ++ // start the Wayland server ++ int fd = m_waylandServer->start(); ++ if (fd == -1) { ++ return false; ++ } ++ ++ args << "--ksldfd"; ++ args << QString::number(fd); ++ + m_lockProcess->start(QStringLiteral(KSCREENLOCKER_GREET_BIN), args); + // we wait one minute + if (!m_lockProcess->waitForStarted(60000)) { + m_lockProcess->kill(); ++ m_waylandServer->stop(); ++ close(fd); + return false; + } ++ close(fd); + + return true; + } +@@ -369,6 +385,7 @@ void KSldApp::showLockWindow() + }, + Qt::QueuedConnection + ); ++ connect(m_waylandServer, &WaylandServer::x11WindowAdded, m_lockWindow, &LockWindow::addAllowedWindow); + } + m_lockWindow->showLockWindow(); + XSync(QX11Info::display(), False); +diff --git a/ksmserver/screenlocker/ksldapp.h b/ksmserver/screenlocker/ksldapp.h +index 095424c..a606aa8 100644 +--- a/ksmserver/screenlocker/ksldapp.h ++++ b/ksmserver/screenlocker/ksldapp.h +@@ -40,6 +40,7 @@ enum class EstablishLock { + }; + + class LockWindow; ++class WaylandServer; + + class KSldApp : public QObject + { +@@ -104,6 +105,7 @@ private: + LockState m_lockState; + QProcess *m_lockProcess; + LockWindow *m_lockWindow; ++ WaylandServer *m_waylandServer; + /** + * Timer to measure how long the screen is locked. + * This information is required by DBus Interface. +diff --git a/ksmserver/screenlocker/lockwindow.cpp b/ksmserver/screenlocker/lockwindow.cpp +index 3aa963a..99245e7 100644 +--- a/ksmserver/screenlocker/lockwindow.cpp ++++ b/ksmserver/screenlocker/lockwindow.cpp +@@ -158,6 +158,7 @@ void LockWindow::hideLockWindow() + gVRoot = 0; + } + XSync(QX11Info::display(), False); ++ m_allowedWindows.clear(); + } + + //--------------------------------------------------------------------------- +@@ -370,7 +371,7 @@ bool LockWindow::nativeEventFilter(const QByteArray &eventType, void *message, l + m_windowInfo[ index ].viewable = true; + else + qDebug() << "Unknown toplevel for MapNotify"; +- if (isLockWindow(xm->window)) { ++ if (m_allowedWindows.contains(xm->window)) { + if (m_lockWindows.contains(xm->window)) { + qDebug() << "uhoh! duplicate!"; + } else { +@@ -497,28 +498,6 @@ void LockWindow::stayOnTop() + XRestackWindows( QX11Info::display(), stack.data(), count ); + } + +-bool LockWindow::isLockWindow(Window id) +-{ +- Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREEN_LOCKER", False); +- Atom actualType; +- int actualFormat; +- unsigned long nitems, remaining; +- unsigned char *data = 0; +- Display *display = QX11Info::display(); +- +- int result = XGetWindowProperty(display, id, tag, 0, 1, False, tag, &actualType, +- &actualFormat, &nitems, &remaining, &data); +- +- bool lockWindow = false; +- if (result == Success && actualType == tag) { +- lockWindow = true; +- } +- if (data) { +- XFree(data); +- } +- return lockWindow; +-} +- + void LockWindow::updateGeo() + { + QDesktopWidget *desktop = QApplication::desktop(); +@@ -530,6 +509,29 @@ void LockWindow::paintEvent(QPaintEvent* ) + QPainter p(this); + p.setBrush(QBrush(Qt::black)); + p.drawRect(geometry()); ++ stayOnTop(); ++} ++ ++void LockWindow::addAllowedWindow(quint32 window) ++{ ++ m_allowedWindows << window; ++ // test whether it's to show ++ const int index = findWindowInfo( window ); ++ if (index == -1 || !m_windowInfo[ index ].viewable) { ++ return; ++ } ++ if (m_lockWindows.contains(window)) { ++ qDebug() << "uhoh! duplicate!"; ++ } else { ++ if (!isVisible()) { ++ // not yet shown and we have a lock window, so we show our own window ++ show(); ++ setCursor(Qt::ArrowCursor); ++ } ++ m_lockWindows.prepend(window); ++ fakeFocusIn(window); ++ stayOnTop(); ++ } + } + + } +diff --git a/ksmserver/screenlocker/lockwindow.h b/ksmserver/screenlocker/lockwindow.h +index 9938d20..cad62ed 100644 +--- a/ksmserver/screenlocker/lockwindow.h ++++ b/ksmserver/screenlocker/lockwindow.h +@@ -41,6 +41,8 @@ public: + void showLockWindow(); + void hideLockWindow(); + ++ void addAllowedWindow(quint32 window); ++ + virtual bool nativeEventFilter(const QByteArray &eventType, void *message, long *result) override; + + Q_SIGNALS: +@@ -59,7 +61,6 @@ private: + void removeVRoot(Window win); + int findWindowInfo(Window w); + void stayOnTop(); +- bool isLockWindow(Window w); + struct WindowInfo + { + Window window; +@@ -67,6 +68,7 @@ private: + }; + QList<WindowInfo> m_windowInfo; + QList<WId> m_lockWindows; ++ QList<quint32> m_allowedWindows; + }; + } + +diff --git a/ksmserver/screenlocker/protocols/ksld.xml b/ksmserver/screenlocker/protocols/ksld.xml +new file mode 100644 +index 0000000..bfb3219 +--- /dev/null ++++ b/ksmserver/screenlocker/protocols/ksld.xml +@@ -0,0 +1,9 @@ ++<?xml version="1.0" encoding="UTF-8"?> ++<protocol name="ksld"> ++ <interface name="org_kde_ksld" version="1"> ++ <request name="x11window"> ++ <arg name="id" type="uint"/> ++ </request> ++ </interface> ++</protocol> ++ +diff --git a/ksmserver/screenlocker/waylandserver.cpp b/ksmserver/screenlocker/waylandserver.cpp +new file mode 100644 +index 0000000..746032e +--- /dev/null ++++ b/ksmserver/screenlocker/waylandserver.cpp +@@ -0,0 +1,119 @@ ++/******************************************************************** ++ KSld - the KDE Screenlocker Daemon ++ This file is part of the KDE project. ++ ++ Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org> ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see <http://www.gnu.org/licenses/>. ++*********************************************************************/ ++#include "waylandserver.h" ++// ksld ++#include <config-ksmserver.h> ++#include <wayland-ksld-server-protocol.h> ++// KWayland ++#include <KWayland/Server/display.h> ++// Wayland ++#include <wayland-server.h> ++// system ++#include <unistd.h> ++#include <fcntl.h> ++#include <sys/types.h> ++#include <sys/socket.h> ++ ++namespace ScreenLocker ++{ ++ ++WaylandServer::WaylandServer(QObject *parent) ++ : QObject(parent) ++{ ++} ++ ++WaylandServer::~WaylandServer() ++{ ++ stop(); ++} ++ ++int WaylandServer::start() ++{ ++ stop(); ++ m_display.reset(new KWayland::Server::Display); ++ m_display->start(KWayland::Server::Display::StartMode::ConnectClientsOnly); ++ if (!m_display->isRunning()) { ++ // failed to start the Wayland server ++ return -1; ++ } ++ int socketPair[2]; ++ if (socketpair(AF_UNIX, SOCK_STREAM, 0, socketPair) == -1) { ++ // failed creating socket ++ return -1; ++ } ++ fcntl(socketPair[0], F_SETFD, FD_CLOEXEC); ++ m_allowedClient = m_display->createClient(socketPair[0]); ++ if (!m_allowedClient) { ++ // failed creating the Wayland client ++ stop(); ++ close(socketPair[0]); ++ close(socketPair[1]); ++ return -1; ++ } ++ m_interface = wl_global_create(*m_display.data(), &org_kde_ksld_interface, 1, this, bind); ++ return socketPair[1]; ++} ++ ++void WaylandServer::stop() ++{ ++ if (m_interface) { ++ wl_global_destroy(m_interface); ++ m_interface = nullptr; ++ } ++ m_display.reset(); ++ m_allowedClient = nullptr; ++} ++ ++void WaylandServer::bind(wl_client *client, void *data, uint32_t version, uint32_t id) ++{ ++ auto s = reinterpret_cast<WaylandServer*>(data); ++ if (client != s->m_allowedClient->client()) { ++ // a proper error would be better ++ wl_client_post_no_memory(client); ++ return; ++ } ++ wl_resource *r = s->m_allowedClient->createResource(&org_kde_ksld_interface, qMin(version, 1u), id); ++ if (!r) { ++ wl_client_post_no_memory(client); ++ return; ++ } ++ ++ static const struct org_kde_ksld_interface s_interface = { ++ x11WindowCallback ++ }; ++ wl_resource_set_implementation(r, &s_interface, s, unbind); ++ s->m_allowedClient->flush(); ++} ++ ++void WaylandServer::unbind(wl_resource *resource) ++{ ++ Q_UNUSED(resource) ++} ++ ++void WaylandServer::x11WindowCallback(wl_client *client, wl_resource *resource, uint32_t id) ++{ ++ auto s = reinterpret_cast<WaylandServer*>(wl_resource_get_user_data(resource)); ++ if (s->m_allowedClient->client() != client) { ++ return; ++ } ++ emit s->x11WindowAdded(id); ++} ++ ++} +diff --git a/ksmserver/screenlocker/waylandserver.h b/ksmserver/screenlocker/waylandserver.h +new file mode 100644 +index 0000000..5a8ed22 +--- /dev/null ++++ b/ksmserver/screenlocker/waylandserver.h +@@ -0,0 +1,64 @@ ++/******************************************************************** ++ KSld - the KDE Screenlocker Daemon ++ This file is part of the KDE project. ++ ++ Copyright (C) 2014 Martin Gräßlin <mgraesslin@kde.org> ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see <http://www.gnu.org/licenses/>. ++*********************************************************************/ ++#ifndef SCREENLOCKER_WAYLANDSERVER_H ++#define SCREENLOCKER_WAYLANDSERVER_H ++ ++#include <QObject> ++ ++struct wl_client; ++struct wl_global; ++struct wl_resource; ++ ++namespace KWayland ++{ ++namespace Server ++{ ++class ClientConnection; ++class Display; ++} ++} ++ ++namespace ScreenLocker ++{ ++ ++class WaylandServer : public QObject ++{ ++ Q_OBJECT ++public: ++ explicit WaylandServer(QObject *parent = nullptr); ++ virtual ~WaylandServer(); ++ int start(); ++ void stop(); ++ ++Q_SIGNALS: ++ void x11WindowAdded(quint32 window); ++ ++private: ++ static void bind(wl_client *client, void *data, uint32_t version, uint32_t id); ++ static void unbind(wl_resource *resource); ++ static void x11WindowCallback(wl_client *client, wl_resource *resource, uint32_t id); ++ QScopedPointer<KWayland::Server::Display> m_display; ++ KWayland::Server::ClientConnection *m_allowedClient = nullptr; ++ wl_global *m_interface = nullptr; ++}; ++ ++} ++ ++#endif diff --git a/screenlocker-network.patch b/screenlocker-network.patch new file mode 100644 index 0000000..1b83dc5 --- /dev/null +++ b/screenlocker-network.patch @@ -0,0 +1,171 @@ +commit 0a9cea625dfcb068fb03a4deab7430b1c4ad8aa4 +Author: Martin Gräßlin <mgraesslin@kde.org> +Date: Fri Jan 2 15:50:15 2015 +0100 + + [ksld] Provide custom QQmlNetworkAccessManagerFactory in greeter + + The greeter installs a custom QQmlNetworkAccessManagerFactory which + creates QNetworkAccessManagers which do not have access to the + network. + + Unfortunately this is not a 100 % secure way to disable network, any + plugin could change the factory again and thus enable network. This + is done for example by KDeclarative, so the greeter now first creates + KDeclarative and then sets the custom factory. + + It is a sufficient solution to block all network access for pure + QtQuick without a binary package as we would find in a look'n'feel + package. + + Network access needs to be blocked in the greeter as otherwise a + look'n'feel package were able to send the entered password (and other + information to the creator of the look'n'feel package. + + REVIEW: 121847 + +diff --git a/ksmserver/screenlocker/greeter/CMakeLists.txt b/ksmserver/screenlocker/greeter/CMakeLists.txt +index 14a34f0..5ec0104 100644 +--- a/ksmserver/screenlocker/greeter/CMakeLists.txt ++++ b/ksmserver/screenlocker/greeter/CMakeLists.txt +@@ -13,6 +13,7 @@ set(kscreenlocker_greet_SRCS + sessions.cpp + greeterapp.cpp + main.cpp ++ noaccessnetworkaccessmanagerfactory.cpp + ) + + qt5_add_resources(kscreenlocker_greet_SRCS fallbacktheme.qrc) +@@ -34,6 +35,7 @@ target_link_libraries(kscreenlocker_greet + KF5::Crash + KF5::I18n + KF5::ConfigGui ++ KF5::Declarative + KF5::WindowSystem + KF5::Solid + Qt5::Quick +diff --git a/ksmserver/screenlocker/greeter/greeterapp.cpp b/ksmserver/screenlocker/greeter/greeterapp.cpp +index 824ba60..a23b562 100644 +--- a/ksmserver/screenlocker/greeter/greeterapp.cpp ++++ b/ksmserver/screenlocker/greeter/greeterapp.cpp +@@ -22,10 +22,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>. + #include "kscreensaversettings.h" + #include "sessions.h" + #include "authenticator.h" ++#include "noaccessnetworkaccessmanagerfactory.h" + + // KDE + #include <KAuthorized> + #include <KCrash> ++#include <kdeclarative/kdeclarative.h> + #include <KUser> + #include <KWindowSystem> + #include <Solid/PowerManagement> +@@ -162,6 +164,16 @@ void UnlockApp::desktopResized() + QQuickView *view = new QQuickView(); + connect(view, &QQuickView::statusChanged, this, &UnlockApp::viewStatusChanged); + ++ // first create KDecoration, to be sure that it created a KIO Network Factory ++ KDeclarative::KDeclarative declarative; ++ declarative.setDeclarativeEngine(view->engine()); ++ declarative.setupBindings(); ++ // overwrite the factory set by kdeclarative ++ auto oldFactory = view->engine()->networkAccessManagerFactory(); ++ view->engine()->setNetworkAccessManagerFactory(nullptr); ++ delete oldFactory; ++ view->engine()->setNetworkAccessManagerFactory(new NoAccessNetworkAccessManagerFactory); ++ + if (!m_testing) { + view->setFlags(Qt::X11BypassWindowManagerHint); + } +@@ -202,6 +214,9 @@ void UnlockApp::desktopResized() + connect(view->rootObject(), SIGNAL(suspendToDisk()), SLOT(suspendToDisk())); + } + ++ // verify that the engine's controller didn't change ++ Q_ASSERT(dynamic_cast<NoAccessNetworkAccessManagerFactory*>(view->engine()->networkAccessManagerFactory())); ++ + m_views << view; + } + +diff --git a/ksmserver/screenlocker/greeter/noaccessnetworkaccessmanagerfactory.cpp b/ksmserver/screenlocker/greeter/noaccessnetworkaccessmanagerfactory.cpp +new file mode 100644 +index 0000000..eaa58c1 +--- /dev/null ++++ b/ksmserver/screenlocker/greeter/noaccessnetworkaccessmanagerfactory.cpp +@@ -0,0 +1,34 @@ ++/******************************************************************** ++ KSld - the KDE Screenlocker Daemon ++ This file is part of the KDE project. ++ ++Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org> ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see <http://www.gnu.org/licenses/>. ++*********************************************************************/ ++#include "noaccessnetworkaccessmanagerfactory.h" ++ ++#include <QNetworkAccessManager> ++ ++namespace ScreenLocker ++{ ++ ++QNetworkAccessManager *NoAccessNetworkAccessManagerFactory::create(QObject *parent) ++{ ++ QNetworkAccessManager *manager = new QNetworkAccessManager(parent); ++ manager->setNetworkAccessible(QNetworkAccessManager::NotAccessible); ++ return manager; ++} ++ ++} +diff --git a/ksmserver/screenlocker/greeter/noaccessnetworkaccessmanagerfactory.h b/ksmserver/screenlocker/greeter/noaccessnetworkaccessmanagerfactory.h +new file mode 100644 +index 0000000..6b2f739 +--- /dev/null ++++ b/ksmserver/screenlocker/greeter/noaccessnetworkaccessmanagerfactory.h +@@ -0,0 +1,36 @@ ++/******************************************************************** ++ KSld - the KDE Screenlocker Daemon ++ This file is part of the KDE project. ++ ++Copyright (C) 2015 Martin Gräßlin <mgraesslin@kde.org> ++ ++This program is free software; you can redistribute it and/or modify ++it under the terms of the GNU General Public License as published by ++the Free Software Foundation; either version 2 of the License, or ++(at your option) any later version. ++ ++This program is distributed in the hope that it will be useful, ++but WITHOUT ANY WARRANTY; without even the implied warranty of ++MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the ++GNU General Public License for more details. ++ ++You should have received a copy of the GNU General Public License ++along with this program. If not, see <http://www.gnu.org/licenses/>. ++*********************************************************************/ ++#ifndef NOACCESSNETWORKACCESSMANAGERFACTORY_H ++#define NOACCESSNETWORKACCESSMANAGERFACTORY_H ++ ++#include <QQmlNetworkAccessManagerFactory> ++ ++namespace ScreenLocker ++{ ++ ++class NoAccessNetworkAccessManagerFactory : public QQmlNetworkAccessManagerFactory ++{ ++public: ++ QNetworkAccessManager *create(QObject *parent) override; ++}; ++ ++} ++ ++#endif