diff --git a/CMakeLists.txt b/CMakeLists.txt index 384ffed..2a4a729 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,247 +1,273 @@ cmake_minimum_required(VERSION 3.0) project(kscreenlocker) set(PROJECT_VERSION "5.12.80") set(PROJECT_VERSION_MAJOR 5) set(QT_MIN_VERSION "5.9.0") set(KF5_MIN_VERSION "5.42.0") -find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS Widgets Quick QuickWidgets Test) +find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS DBus Widgets Quick QuickWidgets Test) find_package(ECM ${KF5_MIN_VERSION} REQUIRED NO_MODULE) set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${ECM_MODULE_PATH} ${ECM_KDE_MODULE_DIR}) include(KDEInstallDirs) include(KDECMakeSettings) include(KDECompilerSettings NO_POLICY_SCOPE) include(ECMSetupVersion) include(ECMGenerateHeaders) include(CheckIncludeFiles) include(ECMMarkNonGuiExecutable) include(CMakePackageConfigHelpers) include(FeatureSummary) include(GenerateExportHeader) include(CheckIncludeFile) include(CheckSymbolExists) check_include_file("sys/prctl.h" HAVE_SYS_PRCTL_H) check_symbol_exists(PR_SET_DUMPABLE "sys/prctl.h" HAVE_PR_SET_DUMPABLE) check_include_file("sys/procctl.h" HAVE_SYS_PROCCTL_H) check_symbol_exists(PROC_TRACE_CTL "sys/procctl.h" HAVE_PROC_TRACE_CTL) if (HAVE_PR_SET_DUMPABLE OR HAVE_PROC_TRACE_CTL) set(CAN_DISABLE_PTRACE TRUE) endif () add_feature_info("prctl/procctl tracing control" CAN_DISABLE_PTRACE "Required for disallowing ptrace on greeter and kcheckpass process") check_include_file("sys/signalfd.h" HAVE_SIGNALFD_H) if (NOT HAVE_SIGNALFD_H) check_include_files("sys/types.h;sys/event.h" HAVE_EVENT_H) endif () if (NOT (HAVE_SIGNALFD_H OR HAVE_EVENT_H)) message(FATAL_ERROR "kcheckpass either needs signalfd() or kevent()&sigtimedwait() to work") endif () add_feature_info("sys/signalfd.h" HAVE_SIGNALFD_H "Use the signalfd() api for signalhandling") add_feature_info("sys/event.h" HAVE_EVENT_H "Use the kevent() and sigwaitinfo() api for signalhandling") find_package(KF5 ${KF5_MIN_VERSION} REQUIRED COMPONENTS Crash Declarative GlobalAccel I18n IdleTime KCMUtils Notifications Solid TextWidgets WindowSystem XmlGui ) find_package(X11) set_package_properties(X11 PROPERTIES DESCRIPTION "X11 libraries" URL "http://www.x.org" TYPE REQUIRED PURPOSE "Required for building the X11 based workspace") find_package(XCB MODULE REQUIRED COMPONENTS XCB KEYSYMS XTEST) set_package_properties(XCB PROPERTIES TYPE REQUIRED) add_feature_info("XInput" X11_Xinput_FOUND "Required for grabbing XInput2 devices in the screen locker") find_package(Qt5 ${QT_MIN_VERSION} CONFIG REQUIRED COMPONENTS X11Extras) find_package(KF5Wayland CONFIG REQUIRED) 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") find_package(loginctl) set_package_properties(loginctl PROPERTIES URL "https://www.freedesktop.org/software/systemd/man/loginctl.html" DESCRIPTION "Send control commands to the login manager" TYPE RUNTIME - PURPOSE "Needed for emergency unlock in case that the greeter is broken. In case your distribution does not provide loginctl please contact plasma-devel@kde.org to discuss alternatives." ) +set(HAVE_LOGINCTL ${loginctl_FOUND}) + +if ( NOT HAVE_LOGINCTL ) + find_package(ConsoleKit) + set_package_properties(ConsoleKit PROPERTIES + URL "https://github.com/ConsoleKit2/ConsoleKit2" + DESCRIPTION "Framework for tracking user login sessions" + TYPE RECOMMENDED + ) + set(HAVE_CONSOLEKIT ${ConsoleKit_FOUND}) +endif () + +if (HAVE_LOGINCTL OR HAVE_CONSOLEKIT) + set(HAVE_UNLOCK_CAPABILITY TRUE) +endif () + +add_feature_info("Unlock broken screenlocker" + HAVE_UNLOCK_CAPABILITY + "Needed for emergency unlock in case that the greeter is broken. In case your distribution does not provide loginctl or consolekit please contact plasma-devel@kde.org to discuss alternatives.") option(PAM_REQUIRED "Require building with PAM" ON) find_package(Seccomp) set_package_properties(Seccomp PROPERTIES TYPE OPTIONAL PURPOSE "Used for putting the look'n'feel package in the greeter into a sandbox." ) set(HAVE_SECCOMP ${Seccomp_FOUND}) include(ConfigureChecks.cmake) configure_file(config-workspace.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-workspace.h) configure_file(config-unix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-unix.h ) configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h) +if (HAVE_CONSOLEKIT) + configure_file(ck-unlock-session.cmake ${CMAKE_CURRENT_BINARY_DIR}/ck-unlock-session) +endif () + # adjusting CMAKE_C_FLAGS to get wayland protocols to compile set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") ecm_setup_version(${PROJECT_VERSION} VARIABLE_PREFIX KSCREENLOCKER VERSION_HEADER "${CMAKE_CURRENT_BINARY_DIR}/kscreenlocker_version.h" PACKAGE_VERSION_FILE "${CMAKE_CURRENT_BINARY_DIR}/KScreenLockerConfigVersion.cmake" SOVERSION 5) configure_file(config-kscreenlocker.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kscreenlocker.h) include_directories(${CMAKE_CURRENT_BINARY_DIR}) set(KSLD_INCLUDEDIR "${CMAKE_INSTALL_INCLUDEDIR}/KScreenLocker") add_subdirectory(kcheckpass) add_subdirectory(greeter) add_subdirectory(kcm) add_definitions(-DTRANSLATION_DOMAIN=\"kscreenlocker\") set(screensaver_dbusXML dbus/org.freedesktop.ScreenSaver.xml) set(kscreensaver_dbusXML dbus/org.kde.screensaver.xml) set(powerdevilpolicyagent_xml dbus/kf5_org.kde.Solid.PowerManagement.PolicyAgent.xml) set(ksld_SRCS abstractlocker.cpp ksldapp.cpp interface.cpp globalaccel.cpp x11locker.cpp waylandlocker.cpp logind.cpp waylandserver.cpp powermanagement.cpp powermanagement_inhibition.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) kconfig_add_kcfg_files(ksld_SRCS kcfg/kscreensaversettings.kcfgc) qt5_add_dbus_interface(ksld_SRCS ${powerdevilpolicyagent_xml} powerdevilpolicyagent) ecm_add_wayland_server_protocol(ksld_SRCS PROTOCOL protocols/ksld.xml BASENAME ksld ) add_library(KScreenLocker SHARED ${ksld_SRCS}) target_link_libraries(KScreenLocker PUBLIC Qt5::Core Qt5::X11Extras PRIVATE + Qt5::DBus KF5::I18n KF5::IdleTime KF5::GlobalAccel KF5::Notifications KF5::CoreAddons KF5::ConfigGui KF5::WindowSystem ${X11_LIBRARIES} XCB::XCB XCB::KEYSYMS KF5::WaylandServer Wayland::Server ) if (X11_Xinput_FOUND) target_link_libraries(KScreenLocker PRIVATE ${X11_Xinput_LIB}) endif() target_include_directories(KScreenLocker INTERFACE "$") # Needed to compile on Arm target. set_target_properties(KScreenLocker PROPERTIES COMPILE_FLAGS "-fPIC") add_library(PW::KScreenLocker ALIAS KScreenLocker) generate_export_header(KScreenLocker BASE_NAME KScreenLocker EXPORT_MACRO_NAME KSCREENLOCKER_EXPORT EXPORT_FILE_NAME KScreenLocker/kscreenlocker_export.h ) configure_package_config_file(ScreenSaverDBusInterfaceConfig.cmake.in ${CMAKE_CURRENT_BINARY_DIR}/ScreenSaverDBusInterfaceConfig.cmake PATH_VARS KDE_INSTALL_DBUSINTERFACEDIR INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/ScreenSaverDBusInterface") set_target_properties(KScreenLocker PROPERTIES VERSION ${PROJECT_VERSION} SOVERSION ${PROJECT_VERSION_MAJOR}) install(FILES ${CMAKE_CURRENT_BINARY_DIR}/ScreenSaverDBusInterfaceConfig.cmake DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/ScreenSaverDBusInterface") configure_package_config_file("${CMAKE_CURRENT_SOURCE_DIR}/KScreenLockerConfig.cmake.in" "${CMAKE_CURRENT_BINARY_DIR}/KScreenLockerConfig.cmake" - INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker") + INSTALL_DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker") +if (HAVE_CONSOLEKIT) + install(PROGRAMS ${CMAKE_CURRENT_BINARY_DIR}/ck-unlock-session DESTINATION ${KDE_INSTALL_BINDIR}) +endif () install(TARGETS KScreenLocker EXPORT KScreenLockerTargets ${INSTALL_TARGETS_DEFAULT_ARGS} LIBRARY) install(EXPORT KScreenLockerTargets DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker" FILE KScreenLockerTargets.cmake NAMESPACE PW::) ecm_generate_headers(KScreenLocker_CamelCase_HEADERS HEADER_NAMES KsldApp REQUIRED_HEADERS KScreenLocker_HEADERS) install( FILES ${CMAKE_CURRENT_BINARY_DIR}/KScreenLocker/kscreenlocker_export.h ${KScreenLocker_CamelCase_HEADERS} ${KScreenLocker_HEADERS} DESTINATION ${KSLD_INCLUDEDIR}/KScreenLocker COMPONENT Devel) install(FILES "${CMAKE_CURRENT_BINARY_DIR}/KScreenLockerConfig.cmake" "${CMAKE_CURRENT_BINARY_DIR}/KScreenLockerConfigVersion.cmake" DESTINATION "${CMAKECONFIG_INSTALL_PREFIX}/KScreenLocker" COMPONENT Devel) install(FILES kscreenlocker.notifyrc DESTINATION ${KDE_INSTALL_KNOTIFY5RCDIR} RENAME ksmserver.notifyrc) install(FILES ${screensaver_dbusXML} DESTINATION ${KDE_INSTALL_DBUSINTERFACEDIR} RENAME kf5_org.freedesktop.ScreenSaver.xml) install(FILES updaters/kscreenlocker.upd DESTINATION ${KDE_INSTALL_DATADIR}/kconf_update) install(PROGRAMS updaters/ksreenlocker_5_3_separate_autologin.pl DESTINATION ${KDE_INSTALL_DATADIR}/kconf_update) if(BUILD_TESTING) add_subdirectory(autotests) add_subdirectory(tests) endif() feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) diff --git a/abstractlocker.cpp b/abstractlocker.cpp index 4935003..1f498ef 100644 --- a/abstractlocker.cpp +++ b/abstractlocker.cpp @@ -1,109 +1,125 @@ /******************************************************************** KSld - the KDE Screenlocker Daemon This file is part of the KDE project. Copyright (C) 1999 Martin R. Jones Copyright (C) 2002 Luboš Luňák Copyright (C) 2003 Oswald Buddenhagen Copyright (C) 2008 Chani Armitage Copyright (C) 2011 Martin Gräßlin Copyright (C) 2015 Bhushan Shah 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 . *********************************************************************/ #include "abstractlocker.h" #include #include #include +#include #include namespace ScreenLocker { BackgroundWindow::BackgroundWindow(AbstractLocker *lock) : QRasterWindow() , m_lock(lock) { setFlags(Qt::X11BypassWindowManagerHint | Qt::FramelessWindowHint); setProperty("org_kde_ksld_emergency", true); } BackgroundWindow::~BackgroundWindow() = default; void BackgroundWindow::paintEvent(QPaintEvent* ) { QPainter p(this); p.fillRect(0, 0, width(), height(), Qt::black); if (m_greeterFailure) { - auto text = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" - "In order to unlock switch to a virtual terminal (e.g. Ctrl+Alt+F2),\n" - "log in and execute the command:\n\n" - "loginctl unlock-session %1\n\n" - "Afterwards switch back to the running session (Ctrl+Alt+F%2)."); - text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_SESSION_ID"))); - text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_VTNR"))); + auto text = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" + "In order to unlock it either ConsoleKit or LoginD is needed, none of\n" + "which could be found on your system."); + auto text_ck = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" + "In order to unlock switch to a virtual terminal (e.g. Ctrl+Alt+F2),\n" + "log in as root and execute the command:\n\n" + "# ck-unlock-session \n\n"); + auto text_ld = ki18n("The screen locker is broken and unlocking is not possible anymore.\n" + "In order to unlock switch to a virtual terminal (e.g. Ctrl+Alt+F2),\n" + "log in and execute the command:\n\n" + "loginctl unlock-session %1\n\n" + "Afterwards switch back to the running session (Ctrl+Alt+F%2)."); + + auto haveService = [](QString service){return QDBusConnection::systemBus().interface()->isServiceRegistered(service);}; + if (haveService("org.freedesktop.ConsoleKit")) { + text = text_ck; + } else if (haveService("org.freedesktop.login1")) { + text = text_ld; + text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_SESSION_ID"))); + text = text.subs(QString::fromLocal8Bit(qgetenv("XDG_VTNR"))); + } + p.setPen(Qt::white); QFont f = p.font(); f.setBold(true); f.setPointSize(24); // for testing emergency mode, we need to disable antialias, as otherwise // screen wouldn't be completely black and white. if (qEnvironmentVariableIsSet("KSLD_TESTMODE")) { f.setStyleStrategy(QFont::NoAntialias); } p.setFont(f); const auto screens = QGuiApplication::screens(); for (auto s : screens) { p.drawText(s->geometry(), Qt::AlignVCenter | Qt::AlignHCenter, text.toString()); } } m_lock->stayOnTop(); } void BackgroundWindow::emergencyShow() { m_greeterFailure = true; update(); show(); } AbstractLocker::AbstractLocker(QObject *parent) : QObject(parent) { if (qobject_cast(QCoreApplication::instance())) { m_background.reset(new BackgroundWindow(this)); } } AbstractLocker::~AbstractLocker() { } void AbstractLocker::emergencyShow() { if (m_background.isNull()) { return; } m_background->emergencyShow(); } void AbstractLocker::addAllowedWindow(quint32 windows) { } } diff --git a/ck-unlock-session.cmake b/ck-unlock-session.cmake new file mode 100644 index 0000000..82f17fe --- /dev/null +++ b/ck-unlock-session.cmake @@ -0,0 +1,25 @@ +#!/bin/sh +# This helper script unlocks the Plasma5 screenlocker of the session given by argument, +# should the locker ever crash. +# +# Requirements: ConsoleKit[2] & qdbus +# + +# list running sesions +list_sessions () +{ + ${cklistsessions_EXECUTABLE} | grep -oE '^Session[^:]*' +} + +# unlock_session +unlock_session () +{ + ${qdbus_EXECUTABLE} --system org.freedesktop.ConsoleKit "/org/freedesktop/ConsoleKit/$1" org.freedesktop.ConsoleKit.Session.Unlock +} + +if [ $# -ne 1 ] ; then + list_sessions +else + unlock_session $1 +fi + diff --git a/cmake/Findloginctl.cmake b/cmake/FindConsoleKit.cmake similarity index 80% copy from cmake/Findloginctl.cmake copy to cmake/FindConsoleKit.cmake index 02a9655..4554a32 100644 --- a/cmake/Findloginctl.cmake +++ b/cmake/FindConsoleKit.cmake @@ -1,34 +1,36 @@ #============================================================================= -# Copyright 2016 Martin Gräßlin +# Copyright 2017 Tobias C. Berner # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= -find_program(loginctl_EXECUTABLE NAMES loginctl) -find_package_handle_standard_args(loginctl +find_program(cklistsessions_EXECUTABLE NAMES ck-list-sessions) +find_program(qdbus_EXECUTABLE NAMES qdbus) +find_package_handle_standard_args(ConsoleKit FOUND_VAR - loginctl_FOUND + ConsoleKit_FOUND REQUIRED_VARS - loginctl_EXECUTABLE + cklistsessions_EXECUTABLE + qdbus_EXECUTABLE ) -mark_as_advanced(loginctl_EXECUTABLE) +mark_as_advanced(ConsoleKit_FOUND cklistsessions_EXECUTABLE qdbus_EXECUTABLE) diff --git a/cmake/Findloginctl.cmake b/cmake/Findloginctl.cmake index 02a9655..56061ab 100644 --- a/cmake/Findloginctl.cmake +++ b/cmake/Findloginctl.cmake @@ -1,34 +1,34 @@ #============================================================================= # Copyright 2016 Martin Gräßlin # # Redistribution and use in source and binary forms, with or without # modification, are permitted provided that the following conditions # are met: # # 1. Redistributions of source code must retain the copyright # notice, this list of conditions and the following disclaimer. # 2. Redistributions in binary form must reproduce the copyright # notice, this list of conditions and the following disclaimer in the # documentation and/or other materials provided with the distribution. # 3. The name of the author may not be used to endorse or promote products # derived from this software without specific prior written permission. # # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. #============================================================================= find_program(loginctl_EXECUTABLE NAMES loginctl) find_package_handle_standard_args(loginctl FOUND_VAR loginctl_FOUND REQUIRED_VARS loginctl_EXECUTABLE ) -mark_as_advanced(loginctl_EXECUTABLE) +mark_as_advanced(loginctl_FOUND loginctl_EXECUTABLE) diff --git a/config-kscreenlocker.h.cmake b/config-kscreenlocker.h.cmake index 6c704aa..b32a645 100644 --- a/config-kscreenlocker.h.cmake +++ b/config-kscreenlocker.h.cmake @@ -1,17 +1,18 @@ #ifdef KSCREENLOCKER_TEST_APPS #define KCHECKPASS_BIN "${CMAKE_BINARY_DIR}/kcheckpass/kcheckpass" #elif defined(KSCREENLOCKER_UNIT_TEST) #define KCHECKPASS_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fakekcheckpass" #else #define KCHECKPASS_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/kcheckpass" #endif #define KSCREENLOCKER_GREET_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/kscreenlocker_greet" #cmakedefine01 HAVE_SYS_PRCTL_H #cmakedefine01 HAVE_PR_SET_DUMPABLE #cmakedefine01 HAVE_SYS_PROCCTL_H #cmakedefine01 HAVE_PROC_TRACE_CTL #cmakedefine01 HAVE_SECCOMP #cmakedefine01 HAVE_SIGNALFD_H #cmakedefine01 HAVE_EVENT_H +