pull/1/head
reionwong 5 years ago
parent 3225234e61
commit 0e36014d15

@ -0,0 +1,66 @@
cmake_minimum_required(VERSION 3.16)
project(screenlocker)
set(CMAKE_C_STANDARD 99)
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_INCLUDE_CURRENT_DIR ON)
# set(CMAKE_AUTOUIC ON)
# set(CMAKE_AUTOMOC ON)
# set(CMAKE_AUTORCC ON)
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake)
include(CheckIncludeFile)
include(CheckIncludeFiles)
include(CheckSymbolExists)
include(FeatureSummary)
find_package(Qt5 COMPONENTS Core DBus Widgets X11Extras Quick REQUIRED)
find_package(X11)
# ----------- Check --------------------
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 ()
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")
# --------------------------------------
option(PAM_REQUIRED "Require building with PAM" ON)
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)
set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90")
configure_file(config-screenlocker.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-screenlocker.h)
include_directories(${CMAKE_CURRENT_BINARY_DIR})
add_subdirectory(screenlocker)
add_subdirectory(checkpass)
feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES)

@ -0,0 +1,41 @@
set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH} )
include(UnixAuth)
set_package_properties(PAM PROPERTIES DESCRIPTION "PAM Libraries"
URL "https://www.kernel.org/pub/linux/libs/pam/"
TYPE OPTIONAL
PURPOSE "Required for screen unlocking and optionally used by the KDM log in manager"
)
if(PAM_REQUIRED)
set_package_properties(PAM PROPERTIES TYPE REQUIRED)
endif()
include(CheckTypeSize)
include(FindPkgConfig)
if (PAM_FOUND)
set(KDE4_COMMON_PAM_SERVICE "kde" CACHE STRING "The PAM service to use unless overridden for a particular app.")
macro(define_pam_service APP)
string(TOUPPER ${APP}_PAM_SERVICE var)
set(cvar KDE4_${var})
set(${cvar} "${KDE4_COMMON_PAM_SERVICE}" CACHE STRING "The PAM service for ${APP}.")
mark_as_advanced(${cvar})
set(${var} "\"${${cvar}}\"")
endmacro(define_pam_service)
define_pam_service(kscreensaver)
endif (PAM_FOUND)
check_function_exists(getpassphrase HAVE_GETPASSPHRASE)
check_function_exists(vsyslog HAVE_VSYSLOG)
check_function_exists(statvfs HAVE_STATVFS)
check_include_files(limits.h HAVE_LIMITS_H)
check_include_files(sys/time.h HAVE_SYS_TIME_H) # ksmserver, ksplashml, sftp
check_include_files(sys/param.h HAVE_SYS_PARAM_H)
check_include_files(unistd.h HAVE_UNISTD_H)
check_include_files(malloc.h HAVE_MALLOC_H)
check_function_exists(statfs HAVE_STATFS)
set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
check_function_exists(setpriority HAVE_SETPRIORITY) # kscreenlocker

@ -1 +1,32 @@
# screenlocker
# Screen locker
## Third Party Code
kcheckpass
## Dependencies
### Debian/Ubuntu
```
sudo apt install libpam0g-dev libx11-dev -y
```
## Build
```shell
mkdir build
cd build
cmake ..
make
```
## Install
```shell
sudo make install
```
## License
This project has been licensed by GPLv3.

@ -0,0 +1,33 @@
include_directories( ${UNIXAUTH_INCLUDE_DIRS} )
check_include_files(paths.h HAVE_PATHS_H)
configure_file (config-ccheckpass.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ccheckpass.h )
set(ccheckpass_SRCS
checkpass.h
checkpass.c
checkpass_pam.c
checkpass_shadow.c
)
# find_package(ECM REQUIRED NO_MODULE)
# set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} )
# include(ECMMarkNonGuiExecutable)
add_executable(ccheckpass ${ccheckpass_SRCS})
# ecm_mark_nongui_executable(ccheckpass)
set_property(TARGET ccheckpass APPEND_STRING PROPERTY COMPILE_FLAGS " -U_REENTRANT")
target_link_libraries(ccheckpass ${UNIXAUTH_LIBRARIES} ${SOCKET_LIBRARIES})
if (PAM_FOUND)
set(checkpass_suid "")
else()
set(checkpass_suid "SETUID")
message(STATUS "PAM not found, will install a SUID-kcheckpass")
endif()
install(TARGETS ccheckpass
DESTINATION /usr/bin
PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ${checkpass_suid}
)
#EXTRA_DIST = README

@ -0,0 +1,75 @@
/*****************************************************************
*
*· kcheckpass
*
*· Simple password checker. Just invoke and send it
*· the password on stdin.
*
*· If the password was accepted, the program exits with 0;
*· if it was rejected, it exits with 1. Any other exit
*· code signals an error.
*
*
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*· Copyright (C) 1998, Caldera, Inc.
*· Released under the GNU General Public License
*
*· Olaf Kirch <okir@caldera.de> General Framework and PAM support
*· Christian Esken <esken@kde.org> Shadow and /etc/passwd support
*· Oswald Buddenhagen <ossi@kde.org> Binary server mode
*
* Other parts were taken from kscreensaver's passwd.cpp
*****************************************************************/
#ifndef KCHECKPASS_ENUMS_H
#define KCHECKPASS_ENUMS_H
#ifdef __cplusplus
extern "C" {
#endif
/* these must match kcheckpass' exit codes */
typedef enum {
AuthOk = 0,
AuthBad = 1,
AuthError = 2,
AuthAbort = 3,
} AuthReturn;
typedef enum {
ConvGetBinary,
ConvGetNormal,
ConvGetHidden,
ConvPutInfo,
ConvPutError,
ConvPutAuthSucceeded,
ConvPutAuthFailed,
ConvPutAuthError,
ConvPutAuthAbort,
ConvPutReadyForAuthentication,
} ConvRequest;
/* these must match the defs in kgreeterplugin.h */
typedef enum {
IsUser = 1, /* unused in kcheckpass */
IsPassword = 2,
} DataTag;
#ifdef __cplusplus
}
#endif
#endif /* KCHECKPASS_ENUMS_H */

@ -0,0 +1,508 @@
/*****************************************************************
*
* kcheckpass - Simple password checker
*
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
* kcheckpass is a simple password checker. Just invoke and
* send it the password on stdin.
*
* If the password was accepted, the program exits with 0;
* if it was rejected, it exits with 1. Any other exit
* code signals an error.
*
* It's hopefully simple enough to allow it to be setuid
* root.
*
* Compile with -DHAVE_VSYSLOG if you have vsyslog().
* Compile with -DHAVE_PAM if you have a PAM system,
* and link with -lpam -ldl.
* Compile with -DHAVE_SHADOW if you have a shadow
* password system.
*
* Copyright (C) 1998, Caldera, Inc.
* Released under the GNU General Public License
*
* Olaf Kirch <okir@caldera.de> General Framework and PAM support
* Christian Esken <esken@kde.org> Shadow and /etc/passwd support
* Roberto Teixeira <maragato@kde.org> other user (-U) support
* Oswald Buddenhagen <ossi@kde.org> Binary server mode
*
* Other parts were taken from kscreensaver's passwd.cpp.
*
*****************************************************************/
#include "checkpass.h"
#include <errno.h>
#include <fcntl.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#include <time.h>
#include <unistd.h>
#include <config-screenlocker.h>
#if HAVE_SYS_PRCTL_H
#include <sys/prctl.h>
#endif
#if HAVE_SYS_PROCCTL_H
#include <sys/procctl.h>
#include <unistd.h>
#endif
#if HAVE_SIGNALFD_H
#include <sys/signalfd.h>
#endif
#if HAVE_EVENT_H
#include <sys/event.h>
#include <sys/time.h>
#include <sys/types.h>
#endif
#define THROTTLE 3
static int havetty, sfd = -1, nullpass;
static int Reader(void *buf, int count)
{
int ret, rlen;
for (rlen = 0; rlen < count;) {
dord:
ret = read(sfd, (void *)((char *)buf + rlen), count - rlen);
if (ret < 0) {
if (errno == EINTR) {
goto dord;
}
if (errno == EAGAIN) {
break;
}
return -1;
}
if (!ret) {
break;
}
rlen += ret;
}
return rlen;
}
static void GRead(void *buf, int count)
{
if (Reader(buf, count) != count) {
message("Communication breakdown on read\n");
exit(15);
}
}
static void GWrite(const void *buf, int count)
{
if (write(sfd, buf, count) != count) {
message("Communication breakdown on write\n");
exit(15);
}
}
static void GSendInt(int val)
{
GWrite(&val, sizeof(val));
}
static void GSendStr(const char *buf)
{
unsigned len = buf ? strlen(buf) + 1 : 0;
GWrite(&len, sizeof(len));
GWrite(buf, len);
}
static void GSendArr(int len, const char *buf)
{
GWrite(&len, sizeof(len));
GWrite(buf, len);
}
static int GRecvInt(void)
{
int val;
GRead(&val, sizeof(val));
return val;
}
static char *GRecvStr(void)
{
unsigned len;
char *buf;
if (!(len = GRecvInt())) {
return (char *)0;
}
if (len > 0x1000 || !(buf = malloc(len))) {
message("No memory for read buffer\n");
exit(15);
}
GRead(buf, len);
buf[len - 1] = 0; /* we're setuid ... don't trust "them" */
return buf;
}
static char *GRecvArr(void)
{
unsigned len;
char *arr;
unsigned const char *up;
if (!(len = (unsigned)GRecvInt())) {
return (char *)0;
}
if (len < 4) {
message("Too short binary authentication data block\n");
exit(15);
}
if (len > 0x10000 || !(arr = malloc(len))) {
message("No memory for read buffer\n");
exit(15);
}
GRead(arr, len);
up = (unsigned const char *)arr;
if (len != (unsigned)(up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24))) {
message("Mismatched binary authentication data block size\n");
exit(15);
}
return arr;
}
static char *conv_server(ConvRequest what, const char *prompt)
{
GSendInt(what);
switch (what) {
case ConvGetBinary: {
unsigned const char *up = (unsigned const char *)prompt;
int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24);
GSendArr(len, prompt);
return GRecvArr();
}
case ConvGetNormal:
case ConvGetHidden: {
char *msg;
GSendStr(prompt);
msg = GRecvStr();
if (msg && (GRecvInt() & IsPassword) && !*msg) {
nullpass = 1;
}
return msg;
}
case ConvPutAuthSucceeded:
case ConvPutAuthFailed:
case ConvPutAuthError:
case ConvPutAuthAbort:
case ConvPutReadyForAuthentication:
return 0;
case ConvPutInfo:
case ConvPutError:
default:
GSendStr(prompt);
return 0;
}
}
void message(const char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
}
#ifndef O_NOFOLLOW
#define O_NOFOLLOW 0
#endif
static void ATTR_NORETURN usage(int exitval)
{
message(
"usage: kcheckpass {-h|[-c caller] [-m method] -S handle}\n"
" options:\n"
" -h this help message\n"
" -S handle operate in binary server mode on file descriptor handle\n"
" -m method use the specified authentication method (default: \"classic\")\n"
" exit codes:\n"
" 0 success\n"
" 1 invalid password\n"
" 2 cannot read password database\n"
" Anything else tells you something's badly hosed.\n");
exit(exitval);
}
int main(int argc, char **argv)
{
const char *method = "classic";
const char *username = 0;
char *p;
struct passwd *pw;
int c, nfd;
uid_t uid;
AuthReturn ret;
sigset_t signalMask;
#if HAVE_SIGNALFD_H
int signalFd;
struct signalfd_siginfo fdsi;
ssize_t sigReadSize;
#endif
#if HAVE_EVENT_H
/* Event Queue */
int keventQueue;
/* Listen for two events: SIGUSR1 and SIGUSR2 */
struct kevent keventEvent[2];
int keventData;
#endif
pid_t parentPid;
parentPid = getppid();
// disable ptrace on kcheckpass
#if HAVE_PR_SET_DUMPABLE
prctl(PR_SET_DUMPABLE, 0);
#endif
#if HAVE_PROC_TRACE_CTL
int mode = PROC_TRACE_CTL_DISABLE;
procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode);
#endif
// prevent becoming an orphan while waiting for SIGUSR2
#if HAVE_PR_SET_DUMPABLE
prctl(PR_SET_PDEATHSIG, SIGUSR2);
#endif
/* Make sure stdout/stderr are open */
for (c = 1; c <= 2; c++) {
if (fcntl(c, F_GETFL) == -1) {
if ((nfd = open("/dev/null", O_WRONLY)) < 0) {
message("cannot open /dev/null: %s\n", strerror(errno));
exit(10);
}
if (c != nfd) {
dup2(nfd, c);
close(nfd);
}
}
}
havetty = isatty(0);
while ((c = getopt(argc, argv, "hm:S:")) != -1) {
switch (c) {
case 'h':
usage(0);
break;
case 'm':
method = optarg;
break;
case 'S':
sfd = atoi(optarg);
break;
default:
message("Command line option parsing error\n");
usage(10);
}
}
if (sfd == -1) {
message("Only binary protocol supported\n");
return AuthError;
}
uid = getuid();
if (!(p = getenv("LOGNAME")) || !(pw = getpwnam(p)) || pw->pw_uid != uid) {
if (!(p = getenv("USER")) || !(pw = getpwnam(p)) || pw->pw_uid != uid) {
if (!(pw = getpwuid(uid))) {
message("Cannot determinate current user\n");
return AuthError;
}
}
}
if (!(username = strdup(pw->pw_name))) {
message("Out of memory\n");
return AuthError;
}
// setup signals
sigemptyset(&signalMask);
sigaddset(&signalMask, SIGUSR1);
sigaddset(&signalMask, SIGUSR2);
// block them
if (sigprocmask(SIG_BLOCK, &signalMask, NULL) == -1) {
message("Block signal failed\n");
conv_server(ConvPutAuthError, 0);
return 1;
}
#if HAVE_SIGNALFD_H
signalFd = signalfd(-1, &signalMask, SFD_CLOEXEC);
if (signalFd == -1) {
message("Signal fd failed\n");
conv_server(ConvPutAuthError, 0);
return 1;
}
#endif
#if HAVE_EVENT_H
/* Setup the kequeu */
keventQueue = kqueue();
if (keventQueue == -1) {
message("Failed to create kqueue for SIGUSR1\n");
conv_server(ConvPutAuthError, 0);
return 1;
}
/* Setup the events */
EV_SET(&keventEvent[0], SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
EV_SET(&keventEvent[1], SIGUSR2, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL);
int setupResult = kevent(keventQueue, keventEvent, 2, NULL, 0, NULL);
if (setupResult == -1) {
message("Failed to attach event to the kqueue\n");
conv_server(ConvPutAuthError, 0);
return 1;
}
if (keventEvent[0].flags & EV_ERROR) {
message("Error in kevent for SIGUSR1: %s\n", strerror(keventEvent[0].data));
conv_server(ConvPutAuthError, 0);
return 1;
}
if (keventEvent[1].flags & EV_ERROR) {
message("Error in kevent for SIGUSR2: %s\n", strerror(keventEvent[1].data));
conv_server(ConvPutAuthError, 0);
return 1;
}
/* signal_info for sigwaitinfo() */
siginfo_t signalInfo;
#endif
// now lets block on the fd
for (;;) {
conv_server(ConvPutReadyForAuthentication, 0);
#if HAVE_SIGNALFD_H
sigReadSize = read(signalFd, &fdsi, sizeof(struct signalfd_siginfo));
if (sigReadSize != sizeof(struct signalfd_siginfo)) {
message("Read wrong size\n");
return 1;
}
if (fdsi.ssi_signo == SIGUSR1) {
if (fdsi.ssi_pid != parentPid) {
message("signal from wrong process\n");
continue;
}
#endif
#if HAVE_EVENT_H
keventData = kevent(keventQueue, NULL, 0, keventEvent, 1, NULL);
if (keventData == -1) {
/* Let's figure this out in the future, shall we */
message("kevent() failed with %d\n", errno);
return 1;
} else if (keventData == 0) {
/* Do we need to handle timeouts? */
message("kevent timeout\n");
continue;
}
// We know we got a SIGUSR1 or SIGUSR2, so fetch it via sigwaitinfo()
// (otherwise, we could have used sigtimedwait() )
int signalReturn = sigwaitinfo(&signalMask, &signalInfo);
if (signalReturn < 0) {
if (errno == EINTR) {
message("sigawaitinfo() interrupted by unblocked caught signal");
continue;
} else if (errno == EAGAIN) {
/* This should not happen, as kevent notified us about such a signal */
message("no signal of type USR1 or USR2 pending.");
continue;
} else {
message("Unhandled error in sigwaitinfo()");
conv_server(ConvPutAuthError, 0);
return 1;
}
}
if (signalReturn == SIGUSR1) {
if (signalInfo.si_pid != parentPid) {
message("signal from wrong process\n");
continue;
}
#endif
/* Now do the fandango */
ret = Authenticate(method, username, conv_server);
if (ret == AuthBad) {
message("Authentication failure\n");
if (!nullpass) {
openlog("kcheckpass", LOG_PID, LOG_AUTH);
syslog(LOG_NOTICE, "Authentication failure for %s (invoked by uid %d)", username, uid);
}
}
switch (ret) {
case AuthOk:
conv_server(ConvPutAuthSucceeded, 0);
break;
case AuthBad:
conv_server(ConvPutAuthFailed, 0);
break;
case AuthError:
conv_server(ConvPutAuthError, 0);
break;
case AuthAbort:
conv_server(ConvPutAuthAbort, 0);
default:
break;
}
if (uid != geteuid()) {
// we don't support multiple auth for setuid kcheckpass
break;
}
#if HAVE_SIGNALFD_H
} else if (fdsi.ssi_signo == SIGUSR2) {
if (fdsi.ssi_pid != parentPid) {
message("signal from wrong process\n");
continue;
}
break;
#endif
#if HAVE_EVENT_H
} else if (signalReturn == SIGUSR2) {
if (signalInfo.si_pid != parentPid) {
message("signal from wrong process\n");
continue;
}
break;
#endif
} else {
message("unexpected signal\n");
}
}
return 0;
}
void dispose(char *str)
{
memset(str, 0, strlen(str));
free(str);
}
/*****************************************************************
The real authentication methods are in separate source files.
Look in checkpass_*.c
*****************************************************************/

@ -0,0 +1,105 @@
/*****************************************************************
*
* kcheckpass
*
* Simple password checker. Just invoke and send it
* the password on stdin.
*
* If the password was accepted, the program exits with 0;
* if it was rejected, it exits with 1. Any other exit
* code signals an error.
*
*
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* Copyright (C) 1998, Caldera, Inc.
* Released under the GNU General Public License
*
* Olaf Kirch <okir@caldera.de> General Framework and PAM support
* Christian Esken <esken@kde.org> Shadow and /etc/passwd support
* Oswald Buddenhagen <ossi@kde.org> Binary server mode
*
* Other parts were taken from kscreensaver's passwd.cpp
*****************************************************************/
#ifndef KCHECKPASS_H_
#define KCHECKPASS_H_
#include <config-ccheckpass.h>
#include <config-unix.h>
#include <config-workspace.h>
#ifdef HAVE_CRYPT_H
#include <crypt.h>
#endif
#ifdef HAVE_PATHS_H
#include <paths.h>
#endif
#include <pwd.h>
#include <sys/types.h>
#ifndef _PATH_TMP
#define _PATH_TMP "/tmp/"
#endif
#ifdef ultrix
#include <auth.h>
#endif
#include <unistd.h>
/* Make sure there is only one! */
#if defined(HAVE_PAM)
#else
#define HAVE_SHADOW
#endif
#if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4)
#define ATTR_UNUSED __attribute__((unused))
#define ATTR_NORETURN __attribute__((noreturn))
#define ATTR_PRINTFLIKE(fmt, var) __attribute__((format(printf, fmt, var)))
#else
#define ATTR_UNUSED
#define ATTR_NORETURN
#define ATTR_PRINTFLIKE(fmt, var)
#endif
#include "checkpass-enums.h"
#ifdef __cplusplus
extern "C" {
#endif
/*****************************************************************
* Authenticates user
*****************************************************************/
AuthReturn Authenticate(const char *method, const char *user, char *(*conv)(ConvRequest, const char *));
/*****************************************************************
* Output a message to stderr
*****************************************************************/
void message(const char *, ...) ATTR_PRINTFLIKE(1, 2);
/*****************************************************************
* Overwrite and free the passed string
*****************************************************************/
void dispose(char *);
#ifdef __cplusplus
}
#endif
#endif

@ -0,0 +1,204 @@
/*
* Copyright (C) 1998 Caldera, Inc.
* Copyright (C) 2003 Oswald Buddenhagen <ossi@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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "checkpass.h"
#ifdef HAVE_PAM
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <syslog.h>
#ifdef HAVE_PAM_PAM_APPL_H
#include <pam/pam_appl.h>
#else
#include <security/pam_appl.h>
#endif
struct pam_data {
char *(*conv)(ConvRequest, const char *);
int abort : 1;
int classic : 1;
};
#ifdef PAM_MESSAGE_CONST
typedef const struct pam_message pam_message_type;
typedef const void *pam_gi_type;
#else
typedef struct pam_message pam_message_type;
typedef void *pam_gi_type;
#endif
static int PAM_conv(int num_msg, pam_message_type **msg, struct pam_response **resp, void *appdata_ptr)
{
int count;
struct pam_response *repl;
struct pam_data *pd = (struct pam_data *)appdata_ptr;
if (!(repl = calloc(num_msg, sizeof(struct pam_response)))) {
return PAM_CONV_ERR;
}
for (count = 0; count < num_msg; count++) {
switch (msg[count]->msg_style) {
case PAM_TEXT_INFO:
pd->conv(ConvPutInfo, msg[count]->msg);
break;
case PAM_ERROR_MSG:
pd->conv(ConvPutError, msg[count]->msg);
break;
default:
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_ON:
repl[count].resp = pd->conv(ConvGetNormal, msg[count]->msg);
break;
case PAM_PROMPT_ECHO_OFF:
repl[count].resp = pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg);
break;
#ifdef PAM_BINARY_PROMPT
case PAM_BINARY_PROMPT:
repl[count].resp = pd->conv(ConvGetBinary, msg[count]->msg);
break;
#endif
default:
/* Must be an error of some sort... */
goto conv_err;
}
if (!repl[count].resp) {
pd->abort = 1;
goto conv_err;
}
repl[count].resp_retcode = PAM_SUCCESS;
break;
}
}
*resp = repl;
return PAM_SUCCESS;
conv_err:
for (; count >= 0; count--) {
if (repl[count].resp) {
switch (msg[count]->msg_style) {
case PAM_PROMPT_ECHO_OFF:
dispose(repl[count].resp);
break;
#ifdef PAM_BINARY_PROMPT
case PAM_BINARY_PROMPT: /* handle differently? */
#endif
case PAM_PROMPT_ECHO_ON:
free(repl[count].resp);
break;
}
}
}
free(repl);
return PAM_CONV_ERR;
}
static struct pam_data PAM_data;
static struct pam_conv PAM_conversation = {
&PAM_conv,
&PAM_data,
};
#ifdef PAM_FAIL_DELAY
static void fail_delay(int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED, void *appdata_ptr ATTR_UNUSED)
{
}
#endif
AuthReturn Authenticate(const char *method, const char *user, char *(*conv)(ConvRequest, const char *))
{
const char *tty;
pam_handle_t *pamh;
pam_gi_type pam_item;
const char *pam_service;
char pservb[64];
int pam_error;
openlog("kcheckpass", LOG_PID, LOG_AUTH);
PAM_data.conv = conv;
if (strcmp(method, "classic")) {
sprintf(pservb, "%.31s-%.31s", KSCREENSAVER_PAM_SERVICE, method);
pam_service = pservb;
} else {
/* PAM_data.classic = 1; */
pam_service = KSCREENSAVER_PAM_SERVICE;
}
pam_error = pam_start(pam_service, user, &PAM_conversation, &pamh);
if (pam_error != PAM_SUCCESS) {
return AuthError;
}
tty = ttyname(0);
if (!tty) {
tty = getenv("DISPLAY");
}
pam_error = pam_set_item(pamh, PAM_TTY, tty);
if (pam_error != PAM_SUCCESS) {
pam_end(pamh, pam_error);
return AuthError;
}
#ifdef PAM_FAIL_DELAY
pam_set_item(pamh, PAM_FAIL_DELAY, (void *)fail_delay);
#endif
pam_error = pam_authenticate(pamh, 0);
if (pam_error != PAM_SUCCESS) {
if (PAM_data.abort) {
PAM_data.abort = 0;
pam_end(pamh, pam_error);
return AuthAbort;
}
pam_end(pamh, pam_error);
switch (pam_error) {
case PAM_USER_UNKNOWN:
case PAM_AUTH_ERR:
case PAM_MAXTRIES: /* should handle this better ... */
case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */
return AuthBad;
default:
return AuthError;
}
}
/* just in case some module is stupid enough to ignore a preset PAM_USER */
pam_error = pam_get_item(pamh, PAM_USER, &pam_item);
if (pam_error != PAM_SUCCESS) {
pam_end(pamh, pam_error);
return AuthError;
}
if (strcmp((const char *)pam_item, user)) {
pam_end(pamh, PAM_SUCCESS); /* maybe use PAM_AUTH_ERR? */
return AuthBad;
}
pam_error = pam_setcred(pamh, PAM_REFRESH_CRED);
/* ignore errors on refresh credentials. If this did not work we use the old ones. */
pam_end(pamh, PAM_SUCCESS);
return AuthOk;
}
#endif

@ -0,0 +1,85 @@
/*
* Copyright (C) 1998 Christian Esken <esken@kde.org>
* Copyright (C) 2003 Oswald Buddenhagen <ossi@kde.org>
*
* This is a modified version of checkpass_shadow.cpp
*
* Modifications made by Thorsten Kukuk <kukuk@suse.de>
* Mathias Kettner <kettner@suse.de>
*
* ------------------------------------------------------------
*
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
#include "checkpass.h"
/*******************************************************************
* This is the authentication code for Shadow-Passwords
*******************************************************************/
#ifdef HAVE_SHADOW
#include <pwd.h>
#include <stdlib.h>
#include <string.h>
#ifndef __hpux
#include <shadow.h>
#endif
AuthReturn Authenticate(const char *method, const char *login, char *(*conv)(ConvRequest, const char *))
{
char *typed_in_password;
char *crpt_passwd;
char *password;
struct passwd *pw;
struct spwd *spw;
if (strcmp(method, "classic"))
return AuthError;
if (!(pw = getpwnam(login)))
return AuthAbort;
spw = getspnam(login);
password = spw ? spw->sp_pwdp : pw->pw_passwd;
if (!*password)
return AuthOk;
if (!(typed_in_password = conv(ConvGetHidden, 0)))
return AuthAbort;
#if defined(__linux__) && defined(HAVE_PW_ENCRYPT)
crpt_passwd = pw_encrypt(typed_in_password, password); /* (1) */
#else
crpt_passwd = crypt(typed_in_password, password);
#endif
if (crpt_passwd && !strcmp(password, crpt_passwd)) {
dispose(typed_in_password);
return AuthOk; /* Success */
}
dispose(typed_in_password);
return AuthBad; /* Password wrong or account locked */
}
/*
(1) Deprecated - long passwords have known weaknesses. Also,
pw_encrypt is non-standard (requires libshadow.a) while
everything else you need to support shadow passwords is in
the standard (ELF) libc.
*/
#endif

@ -0,0 +1,3 @@
/* Define to 1 if you have the <paths.h> header file. */
#cmakedefine HAVE_PATHS_H 1

@ -0,0 +1,36 @@
#=============================================================================
# Copyright 2017 Tobias C. Berner <tcberner@FreeBSD.org>
#
# 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(cklistsessions_EXECUTABLE NAMES ck-list-sessions)
find_program(qdbus_EXECUTABLE NAMES qdbus)
find_package_handle_standard_args(ConsoleKit
FOUND_VAR
ConsoleKit_FOUND
REQUIRED_VARS
cklistsessions_EXECUTABLE
qdbus_EXECUTABLE
)
mark_as_advanced(ConsoleKit_FOUND cklistsessions_EXECUTABLE qdbus_EXECUTABLE)

@ -0,0 +1,74 @@
# - Try to find the PAM libraries
# Once done this will define
#
# PAM_FOUND - system has pam
# PAM_INCLUDE_DIR - the pam include directory
# PAM_LIBRARIES - libpam library
if (PAM_INCLUDE_DIR AND PAM_LIBRARY)
# Already in cache, be silent
set(PAM_FIND_QUIETLY TRUE)
endif (PAM_INCLUDE_DIR AND PAM_LIBRARY)
find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h)
find_library(PAM_LIBRARY pam)
find_library(DL_LIBRARY dl)
if (PAM_INCLUDE_DIR AND PAM_LIBRARY)
set(PAM_FOUND TRUE)
if (DL_LIBRARY)
set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY})
else (DL_LIBRARY)
set(PAM_LIBRARIES ${PAM_LIBRARY})
endif (DL_LIBRARY)
if (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h)
# darwin claims to be something special
set(HAVE_PAM_PAM_APPL_H 1)
endif (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h)
if (NOT DEFINED PAM_MESSAGE_CONST)
include(CheckCXXSourceCompiles)
# XXX does this work with plain c?
check_cxx_source_compiles("
#if ${HAVE_PAM_PAM_APPL_H}+0
# include <pam/pam_appl.h>
#else
# include <security/pam_appl.h>
#endif
static int PAM_conv(
int num_msg,
const struct pam_message **msg, /* this is the culprit */
struct pam_response **resp,
void *ctx)
{
return 0;
}
int main(void)
{
struct pam_conv PAM_conversation = {
&PAM_conv, /* this bombs out if the above does not match */
0
};
return 0;
}
" PAM_MESSAGE_CONST)
endif (NOT DEFINED PAM_MESSAGE_CONST)
set(PAM_MESSAGE_CONST ${PAM_MESSAGE_CONST} CACHE BOOL "PAM expects a conversation function with const pam_message")
endif (PAM_INCLUDE_DIR AND PAM_LIBRARY)
if (PAM_FOUND)
if (NOT PAM_FIND_QUIETLY)
message(STATUS "Found PAM: ${PAM_LIBRARIES}")
endif (NOT PAM_FIND_QUIETLY)
else (PAM_FOUND)
if (PAM_FIND_REQUIRED)
message(FATAL_ERROR "PAM was not found")
endif(PAM_FIND_REQUIRED)
endif (PAM_FOUND)
mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY DL_LIBRARY PAM_MESSAGE_CONST)

@ -0,0 +1,34 @@
#=============================================================================
# Copyright 2016 Martin Gräßlin <mgraesslin@kde.org>
#
# 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_FOUND loginctl_EXECUTABLE)

@ -0,0 +1,56 @@
find_package(PAM)
include(CheckFunctionExists)
include(CheckLibraryExists)
include(CheckIncludeFiles)
include(CMakePushCheckState)
set(UNIXAUTH_LIBRARIES)
set(UNIXAUTH_INCLUDE_DIRS)
set(SHADOW_LIBRARIES)
check_function_exists(getspnam found_getspnam)
if (found_getspnam)
set(HAVE_GETSPNAM 1)
else (found_getspnam)
cmake_push_check_state()
set(CMAKE_REQUIRED_LIBRARIES -lshadow)
check_function_exists(getspnam found_getspnam_shadow)
if (found_getspnam_shadow)
set(HAVE_GETSPNAM 1)
set(SHADOW_LIBRARIES shadow)
check_function_exists(pw_encrypt HAVE_PW_ENCRYPT) # ancient Linux shadow
else (found_getspnam_shadow)
set(CMAKE_REQUIRED_LIBRARIES -lgen) # UnixWare
check_function_exists(getspnam found_getspnam_gen)
if (found_getspnam_gen)
set(HAVE_GETSPNAM 1)
set(SHADOW_LIBRARIES gen)
endif (found_getspnam_gen)
endif (found_getspnam_shadow)
cmake_pop_check_state()
endif (found_getspnam)
set(CRYPT_LIBRARIES)
check_library_exists(crypt crypt "" HAVE_CRYPT)
if (HAVE_CRYPT)
set(CRYPT_LIBRARIES crypt)
check_include_files(crypt.h HAVE_CRYPT_H)
endif (HAVE_CRYPT)
if (PAM_FOUND)
set(HAVE_PAM 1)
set(UNIXAUTH_LIBRARIES ${PAM_LIBRARIES})
set(UNIXAUTH_INCLUDE_DIRS ${PAM_INCLUDE_DIR})
else (PAM_FOUND)
if (HAVE_GETSPNAM)
set(UNIXAUTH_LIBRARIES ${SHADOW_LIBRARIES})
endif (HAVE_GETSPNAM)
if (NOT HAVE_PW_ENCRYPT)
set(UNIXAUTH_LIBRARIES ${UNIXAUTH_LIBRARIES} ${CRYPT_LIBRARIES})
endif (NOT HAVE_PW_ENCRYPT)
endif (PAM_FOUND)

@ -0,0 +1,2 @@
/* Define if you have the XInput extension */
#cmakedefine X11_Xinput_FOUND 1

@ -0,0 +1,16 @@
#ifdef KSCREENLOCKER_TEST_APPS
#define KCHECKPASS_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/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_SIGNALFD_H
#cmakedefine01 HAVE_EVENT_H

@ -0,0 +1,32 @@
/* Defines if you have PAM (Pluggable Authentication Modules) */
#cmakedefine HAVE_PAM 1
/* Define if your PAM headers are in pam/ instead of security/ */
#cmakedefine HAVE_PAM_PAM_APPL_H 1
/* Define if your PAM expects a conversation function with const pam_message (Solaris) */
#cmakedefine PAM_MESSAGE_CONST 1
/* The PAM service to be used by kscreensaver */
#cmakedefine KSCREENSAVER_PAM_SERVICE ${KSCREENSAVER_PAM_SERVICE}
/* Defines if your system has the getspnam function */
#cmakedefine HAVE_GETSPNAM 1
/* Defines if your system has the crypt function */
#cmakedefine HAVE_CRYPT 1
/* Define to 1 if you have the <crypt.h> header file. */
#cmakedefine HAVE_CRYPT_H 1
/* Define to 1 if you have the `pw_encrypt' function. */
#cmakedefine HAVE_PW_ENCRYPT 1
/* Define to 1 if you have the `getpassphrase' function. */
#cmakedefine HAVE_GETPASSPHRASE 1
/* Define to 1 if you have the `vsyslog' function. */
#cmakedefine HAVE_VSYSLOG 1
/* Define to 1 if you have the <limits.h> header file. */
#cmakedefine HAVE_LIMITS_H 1

@ -0,0 +1,141 @@
/* config-workspace.h. Generated by cmake from config-workspace.h.cmake */
/* Define if you have DPMS support */
#cmakedefine HAVE_DPMS 1
/* Define if you have the DPMSCapable prototype in <X11/extensions/dpms.h> */
#cmakedefine HAVE_DPMSCAPABLE_PROTO 1
/* Define if you have the DPMSInfo prototype in <X11/extensions/dpms.h> */
#cmakedefine HAVE_DPMSINFO_PROTO 1
/* Define if you have gethostname */
#cmakedefine HAVE_GETHOSTNAME 1
/* Define if you have the gethostname prototype */
#cmakedefine HAVE_GETHOSTNAME_PROTO 1
/* Define if you have long long as datatype */
#cmakedefine HAVE_LONG_LONG 1
/* Define to 1 if you have the `nice' function. */
#cmakedefine HAVE_NICE 1
/* Define to 1 if you have the <sasl.h> header file. */
#cmakedefine HAVE_SASL_H 1
/* Define to 1 if you have the <sasl/sasl.h> header file. */
#cmakedefine HAVE_SASL_SASL_H 1
/* Define to 1 if you have the `setpriority' function. */
#cmakedefine HAVE_SETPRIORITY 1
/* Define to 1 if you have the `sigaction' function. */
#cmakedefine HAVE_SIGACTION 1
/* Define to 1 if you have the `sigset' function. */
#cmakedefine HAVE_SIGSET 1
/* Define to 1 if you have statvfs */
#cmakedefine HAVE_STATVFS 1
/* Define to 1 if you have the <string.h> header file. */
#cmakedefine HAVE_STRING_H 1
/* Define if you have the struct ucred */
#cmakedefine HAVE_STRUCT_UCRED 1
/* Define to 1 if you have the <sys/loadavg.h> header file. */
#cmakedefine HAVE_SYS_LOADAVG_H 1
/* Define to 1 if you have the <sys/mount.h> header file. */
#cmakedefine HAVE_SYS_MOUNT_H 1
/* Define to 1 if you have the <sys/param.h> header file. */
#cmakedefine HAVE_SYS_PARAM_H 1
/* Define to 1 if you have the <sys/statfs.h> header file. */
#cmakedefine HAVE_SYS_STATFS_H 1
/* Define to 1 if you have the <sys/statvfs.h> header file. */
#cmakedefine HAVE_SYS_STATVFS_H 1
/* Define to 1 if you have statfs(). */
#cmakedefine HAVE_STATFS 1
/* Define to 1 if you have the <sys/select.h> header file. */
#cmakedefine HAVE_SYS_SELECT_H 1
/* Define to 1 if you have the <sys/socket.h> header file. */
#cmakedefine HAVE_SYS_SOCKET_H 1
/* Define to 1 if you have the <sys/time.h> header file. */
#cmakedefine HAVE_SYS_TIME_H 1
/* Define to 1 if you have the <sys/types.h> header file. */
#cmakedefine HAVE_SYS_TYPES_H 1
/* Define to 1 if you have the <sys/vfs.h> header file. */
#cmakedefine HAVE_SYS_VFS_H 1
/* Define to 1 if you have the <sys/wait.h> header file. */
#cmakedefine HAVE_SYS_WAIT_H 1
/* Define to 1 if you have the <unistd.h> header file. */
#cmakedefine HAVE_UNISTD_H 1
/* Define to 1 if you have the <stdint.h> header file. */
#cmakedefine HAVE_STDINT_H 1
/* Define to 1 if you have the <malloc.h> header file. */
#cmakedefine HAVE_MALLOC_H 1
/* Define if you have unsetenv */
#cmakedefine HAVE_UNSETENV 1
/* Define if you have the unsetenv prototype */
#cmakedefine HAVE_UNSETENV_PROTO 1
/* Define if you have usleep */
#cmakedefine HAVE_USLEEP 1
/* Define if you have the usleep prototype */
#cmakedefine HAVE_USLEEP_PROTO 1
/* Define to 1 if you have the `vsnprintf' function. */
#cmakedefine HAVE_VSNPRINTF 1
/* Define to 1 if you have the Wayland libraries. */
#cmakedefine WAYLAND_FOUND 1
/* KDE's default home directory */
#cmakedefine KDE_DEFAULT_HOME "${KDE_DEFAULT_HOME}"
/* KDE's binaries directory */
#define KDE_BINDIR "${BIN_INSTALL_DIR}"
/* KDE's configuration directory */
#define KDE_CONFDIR "${CONFIG_INSTALL_DIR}"
/* KDE's static data directory */
#define KDE_DATADIR "${DATA_INSTALL_DIR}"
/* Define to 1 if you can safely include both <sys/time.h> and <time.h>. */
#cmakedefine TIME_WITH_SYS_TIME 1
/* X binaries directory */
#cmakedefine XBINDIR "${XBINDIR}"
/* X libraries directory */
#cmakedefine XLIBDIR "${XLIBDIR}"
/* Number of bits in a file offset, on hosts where this is settable. */
#define _FILE_OFFSET_BITS 64
/*
* On HP-UX, the declaration of vsnprintf() is needed every time !
*/
/* type to use in place of socklen_t if not defined */
#define kde_socklen_t socklen_t

@ -0,0 +1,28 @@
set(CMAKE_AUTOUIC ON)
set(CMAKE_AUTOMOC ON)
set(CMAKE_AUTORCC ON)
set(PROJECT_SOURCES
main.cpp
application.cpp
authenticator.cpp
wallpaper.cpp
kcheckpass-enums.h
fixx11h.h
qml.qrc
)
add_executable(screenlocker
${PROJECT_SOURCES}
)
target_link_libraries(screenlocker
PRIVATE
Qt5::Core
Qt5::DBus
Qt5::Widgets
Qt5::X11Extras
Qt5::Quick
${X11_LIBRARIES}
)

@ -0,0 +1,299 @@
#include "application.h"
#include "wallpaper.h"
// Qt Core
#include <QAbstractNativeEventFilter>
#include <QScreen>
#include <QX11Info>
#include <QEvent>
// Qt Quick
#include <QQuickItem>
#include <QQmlContext>
#include <QQmlEngine>
#include <QQmlProperty>
// X11
#include <X11/Xatom.h>
#include <X11/Xlib.h>
#include "fixx11h.h"
// Xcb
#include <xcb/xcb.h>
// this is usable to fake a "screensaver" installation for testing
// *must* be "0" for every public commit!
#define TEST_SCREENSAVER 0
class FocusOutEventFilter : public QAbstractNativeEventFilter
{
public:
bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override {
Q_UNUSED(result)
if (qstrcmp(eventType, "xcb_generic_event_t") != 0) {
return false;
}
xcb_generic_event_t *event = reinterpret_cast<xcb_generic_event_t *>(message);
if ((event->response_type & ~0x80) == XCB_FOCUS_OUT) {
return true;
}
return false;
}
};
Application::Application(int &argc, char **argv)
: QGuiApplication(argc, argv)
, m_authenticator(new Authenticator(AuthenticationMode::Direct, this))
{
// It's a queued connection to give the QML part time to eventually execute code connected to Authenticator::succeeded if any
connect(m_authenticator, &Authenticator::succeeded, this, &QCoreApplication::quit, Qt::QueuedConnection);
installEventFilter(this);
// Screens
connect(this, &Application::screenAdded, this, &Application::onScreenAdded);
connect(this, &Application::screenRemoved, this, &Application::desktopResized);
if (QX11Info::isPlatformX11()) {
installNativeEventFilter(new FocusOutEventFilter);
}
}
Application::~Application()
{
// workaround QTBUG-55460
// will be fixed when themes port to QQC2
for (auto view : qAsConst(m_views)) {
if (QQuickItem *focusItem = view->activeFocusItem()) {
focusItem->setFocus(false);
}
}
qDeleteAll(m_views);
}
void Application::initialViewSetup()
{
for (QScreen *screen : screens()) {
connect(screen, &QScreen::geometryChanged, this, [this, screen](const QRect &geo) {
screenGeometryChanged(screen, geo);
});
}
desktopResized();
}
void Application::desktopResized()
{
const int nScreens = screens().count();
// remove useless views and savers
while (m_views.count() > nScreens) {
m_views.takeLast()->deleteLater();
}
// extend views and savers to current demand
for (int i = m_views.count(); i < nScreens; ++i) {
// create the view
auto *view = new QQuickView;
view->create();
// engine stuff
QQmlContext *context = view->engine()->rootContext();
context->setContextProperty(QStringLiteral("authenticator"), m_authenticator);
context->setContextProperty(QStringLiteral("wallpaper"), new Wallpaper);
view->setSource(QUrl("qrc:/qml/LockScreen.qml"));
view->setResizeMode(QQuickView::SizeRootObjectToView);
view->setColor(Qt::black);
auto screen = QGuiApplication::screens()[i];
view->setGeometry(screen->geometry());
if (!m_testing) {
if (QX11Info::isPlatformX11()) {
view->setFlags(Qt::X11BypassWindowManagerHint);
} else {
view->setFlags(Qt::FramelessWindowHint);
}
}
// overwrite the factory set by kdeclarative
// auto oldFactory = view->engine()->networkAccessManagerFactory();
// view->engine()->setNetworkAccessManagerFactory(nullptr);
// delete oldFactory;
// view->engine()->setNetworkAccessManagerFactory(new NoAccessNetworkAccessManagerFactory);
view->setGeometry(screen->geometry());
connect(view, &QQuickView::frameSwapped, this, [=] { markViewsAsVisible(view); }, Qt::QueuedConnection);
m_views << view;
}
// update geometry of all views and savers
for (int i = 0; i < nScreens; ++i) {
auto *view = m_views.at(i);
auto screen = QGuiApplication::screens()[i];
view->setScreen(screen);
// on Wayland we may not use fullscreen as that puts all windows on one screen
if (m_testing || QX11Info::isPlatformX11()) {
view->show();
} else {
view->showFullScreen();
}
view->raise();
}
}
void Application::onScreenAdded(QScreen *screen)
{
// Lambda connections can not have uniqueness constraints, ensure
// geometry change signals are only connected once
connect(screen, &QScreen::geometryChanged, this, [this, screen](const QRect &geo) {
screenGeometryChanged(screen, geo);
});
desktopResized();
}
void Application::getFocus()
{
QWindow *activeScreen = getActiveScreen();
if (!activeScreen) {
return;
}
// this loop is required to make the qml/graphicsscene properly handle the shared keyboard input
// ie. "type something into the box of every greeter"
for (QQuickView *view : qAsConst(m_views)) {
if (!m_testing) {
view->setKeyboardGrabEnabled(true); // TODO - check whether this still works in master!
}
}
// activate window and grab input to be sure it really ends up there.
// focus setting is still required for proper internal QWidget state (and eg. visual reflection)
if (!m_testing) {
activeScreen->setKeyboardGrabEnabled(true); // TODO - check whether this still works in master!
}
activeScreen->requestActivate();
}
void Application::markViewsAsVisible(QQuickView *view)
{
disconnect(view, &QQuickWindow::frameSwapped, this, nullptr);
QQmlProperty showProperty(view->rootObject(), QStringLiteral("viewVisible"));
showProperty.write(true);
// random state update, actually rather required on init only
QMetaObject::invokeMethod(this, "getFocus", Qt::QueuedConnection);
}
bool Application::eventFilter(QObject *obj, QEvent *event)
{
if (obj != this && event->type() == QEvent::Show) {
QQuickView *view = nullptr;
for (QQuickView *v : qAsConst(m_views)) {
if (v == obj) {
view = v;
break;
}
}
if (view && view->winId() && QX11Info::isPlatformX11()) {
// showing greeter view window, set property
static Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREEN_LOCKER", False);
XChangeProperty(QX11Info::display(), view->winId(), tag, tag, 32, PropModeReplace, nullptr, 0);
}
// no further processing
return false;
}
if (event->type() == QEvent::MouseButtonPress && QX11Info::isPlatformX11()) {
if (getActiveScreen()) {
getActiveScreen()->requestActivate();
}
return false;
}
if (event->type() == QEvent::KeyPress) { // react if saver is visible
shareEvent(event, qobject_cast<QQuickView *>(obj));
return false; // we don't care
} else if (event->type() == QEvent::KeyRelease) { // conditionally reshow the saver
QKeyEvent *ke = static_cast<QKeyEvent *>(event);
if (ke->key() != Qt::Key_Escape) {
shareEvent(event, qobject_cast<QQuickView *>(obj));
return false; // irrelevant
}
return true; // don't pass
}
return false;
}
QWindow *Application::getActiveScreen()
{
QWindow *activeScreen = nullptr;
if (m_views.isEmpty()) {
return activeScreen;
}
for (QQuickView *view : qAsConst(m_views)) {
if (view->geometry().contains(QCursor::pos())) {
activeScreen = view;
break;
}
}
if (!activeScreen) {
activeScreen = m_views.first();
}
return activeScreen;
}
void Application::shareEvent(QEvent *e, QQuickView *from)
{
// from can be NULL any time (because the parameter is passed as qobject_cast)
// m_views.contains(from) is atm. supposed to be true but required if any further
// QQuickView are added (which are not part of m_views)
// this makes "from" an optimization (nullptr check aversion)
if (from && m_views.contains(from)) {
// NOTICE any recursion in the event sharing will prevent authentication on multiscreen setups!
// Any change in regarded event processing shall be tested thoroughly!
removeEventFilter(this); // prevent recursion!
const bool accepted = e->isAccepted(); // store state
for (QQuickView *view : qAsConst(m_views)) {
if (view != from) {
QCoreApplication::sendEvent(view, e);
e->setAccepted(accepted);
}
}
installEventFilter(this);
}
}
void Application::screenGeometryChanged(QScreen *screen, const QRect &geo)
{
// We map screens() to m_views by index and Qt is free to
// reorder screens, so pointer to pointer connections
// may not remain matched by index, perform index
// mapping in the change event itself
const int screenIndex = QGuiApplication::screens().indexOf(screen);
if (screenIndex < 0) {
qWarning() << "Screen not found, not updating geometry" << screen;
return;
}
if (screenIndex >= m_views.size()) {
qWarning() << "Screen index out of range, not updating geometry" << screenIndex;
return;
}
QQuickView *view = m_views[screenIndex];
view->setGeometry(geo);
}

@ -0,0 +1,44 @@
#ifndef APPLICATION_H
#define APPLICATION_H
#include <QGuiApplication>
#include <QQuickView>
#include "authenticator.h"
struct org_kde_ksld;
class Application : public QGuiApplication
{
Q_OBJECT
public:
explicit Application(int &argc, char **argv);
~Application();
void initialViewSetup();
public slots:
void desktopResized();
void onScreenAdded(QScreen *screen);
private slots:
void getFocus();
void markViewsAsVisible(QQuickView *view);
protected:
bool eventFilter(QObject *obj, QEvent *event) override;
private:
QWindow *getActiveScreen();
void shareEvent(QEvent *e, QQuickView *from);
void screenGeometryChanged(QScreen *screen, const QRect &geo);
private:
Authenticator *m_authenticator;
QList<QQuickView *> m_views;
org_kde_ksld *m_ksldInterface = nullptr;
bool m_testing = true;
};
#endif // APPLICATION_H

@ -0,0 +1,333 @@
/********************************************************************
KSld - the KDE Screenlocker Daemon
This file is part of the KDE project.
Copyright (C) 1999 Martin R. Jones <mjones@kde.org>
Copyright (C) 2002 Luboš Luňák <l.lunak@kde.org>
Copyright (C) 2003 Oswald Buddenhagen <ossi@kde.org>
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 "authenticator.h"
#include "kcheckpass-enums.h"
// Qt
#include <QCoreApplication>
#include <QFile>
#include <QSocketNotifier>
#include <QTimer>
// system
#include <errno.h>
#include <signal.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <sys/wait.h>
#include <unistd.h>
Authenticator::Authenticator(AuthenticationMode mode, QObject *parent)
: QObject(parent)
, m_graceLockTimer(new QTimer(this))
, m_checkPass(nullptr)
{
m_graceLockTimer->setSingleShot(true);
m_graceLockTimer->setInterval(3000);
connect(m_graceLockTimer, &QTimer::timeout, this, &Authenticator::graceLockedChanged);
if (mode == AuthenticationMode::Delayed) {
m_checkPass = new KCheckPass(AuthenticationMode::Delayed, this);
setupCheckPass();
}
}
Authenticator::~Authenticator() = default;
void Authenticator::tryUnlock(const QString &password)
{
if (isGraceLocked()) {
Q_EMIT failed();
return;
}
m_graceLockTimer->start();
Q_EMIT graceLockedChanged();
if (!m_checkPass) {
m_checkPass = new KCheckPass(AuthenticationMode::Direct, this);
m_checkPass->setPassword(password);
setupCheckPass();
} else {
if (!m_checkPass->isReady()) {
Q_EMIT failed();
return;
}
m_checkPass->setPassword(password);
m_checkPass->startAuth();
}
}
void Authenticator::setupCheckPass()
{
connect(m_checkPass, &KCheckPass::succeeded, this, &Authenticator::succeeded);
connect(m_checkPass, &KCheckPass::failed, this, &Authenticator::failed);
connect(m_checkPass, &KCheckPass::message, this, &Authenticator::message);
connect(m_checkPass, &KCheckPass::error, this, &Authenticator::error);
connect(m_checkPass, &KCheckPass::destroyed, this, [this] {
m_checkPass = nullptr;
});
m_checkPass->start();
}
bool Authenticator::isGraceLocked() const
{
return m_graceLockTimer->isActive();
}
KCheckPass::KCheckPass(AuthenticationMode mode, QObject *parent)
: QObject(parent)
, m_notifier(nullptr)
, m_pid(0)
, m_fd(0)
, m_mode(mode)
{
if (mode == AuthenticationMode::Direct) {
connect(this, &KCheckPass::succeeded, this, &QObject::deleteLater);
connect(this, &KCheckPass::failed, this, &QObject::deleteLater);
}
}
KCheckPass::~KCheckPass()
{
reapVerify();
}
void KCheckPass::start()
{
int sfd[2];
char fdbuf[16];
if (m_notifier) {
return;
}
if (::socketpair(AF_LOCAL, SOCK_STREAM, 0, sfd)) {
cantCheck();
return;
}
if ((m_pid = ::fork()) < 0) {
::close(sfd[0]);
::close(sfd[1]);
cantCheck();
return;
}
if (!m_pid) {
::close(sfd[0]);
sprintf(fdbuf, "%d", sfd[1]);
execlp(QFile::encodeName(QStringLiteral("ccheckpass")).data(), "kcheckpass", "-m", "classic", "-S", fdbuf, (char *)nullptr);
_exit(20);
}
::close(sfd[1]);
m_fd = sfd[0];
m_notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this);
connect(m_notifier, &QSocketNotifier::activated, this, &KCheckPass::handleVerify);
}
////// kckeckpass interface code
int KCheckPass::Reader(void *buf, int count)
{
int ret, rlen;
for (rlen = 0; rlen < count;) {
dord:
ret = ::read(m_fd, (void *)((char *)buf + rlen), count - rlen);
if (ret < 0) {
if (errno == EINTR) {
goto dord;
}
if (errno == EAGAIN) {
break;
}
return -1;
}
if (!ret) {
break;
}
rlen += ret;
}
return rlen;
}
bool KCheckPass::GRead(void *buf, int count)
{
return Reader(buf, count) == count;
}
bool KCheckPass::GWrite(const void *buf, int count)
{
return ::write(m_fd, buf, count) == count;
}
bool KCheckPass::GSendInt(int val)
{
return GWrite(&val, sizeof(val));
}
bool KCheckPass::GSendStr(const char *buf)
{
int len = buf ? ::strlen(buf) + 1 : 0;
return GWrite(&len, sizeof(len)) && GWrite(buf, len);
}
bool KCheckPass::GSendArr(int len, const char *buf)
{
return GWrite(&len, sizeof(len)) && GWrite(buf, len);
}
bool KCheckPass::GRecvInt(int *val)
{
return GRead(val, sizeof(*val));
}
bool KCheckPass::GRecvArr(char **ret)
{
int len;
char *buf;
if (!GRecvInt(&len)) {
return false;
}
if (!len) {
*ret = nullptr;
return true;
}
if (!(buf = (char *)::malloc(len))) {
return false;
}
*ret = buf;
if (GRead(buf, len)) {
return true;
} else {
::free(buf);
*ret = nullptr;
return false;
}
}
void KCheckPass::handleVerify()
{
m_ready = false;
int ret;
char *arr;
if (GRecvInt(&ret)) {
switch (ret) {
case ConvGetBinary:
if (!GRecvArr(&arr)) {
break;
}
// FIXME: not supported
cantCheck();
if (arr) {
::free(arr);
}
return;
case ConvGetNormal:
case ConvGetHidden: {
if (!GRecvArr(&arr)) {
break;
}
if (m_password.isNull()) {
GSendStr(nullptr);
} else {
QByteArray utf8pass = m_password.toUtf8();
GSendStr(utf8pass.constData());
GSendInt(IsPassword);
}
m_password.clear();
if (arr) {
::free(arr);
}
return;
}
case ConvPutInfo:
if (!GRecvArr(&arr)) {
break;
}
Q_EMIT message(QString::fromLocal8Bit(arr));
::free(arr);
return;
case ConvPutError:
if (!GRecvArr(&arr)) {
break;
}
Q_EMIT error(QString::fromLocal8Bit(arr));
::free(arr);
return;
case ConvPutAuthSucceeded:
Q_EMIT succeeded();
return;
case ConvPutAuthFailed:
Q_EMIT failed();
return;
case ConvPutAuthError:
case ConvPutAuthAbort:
cantCheck();
return;
case ConvPutReadyForAuthentication:
m_ready = true;
if (m_mode == AuthenticationMode::Direct) {
::kill(m_pid, SIGUSR1);
}
return;
}
}
if (m_mode == AuthenticationMode::Direct) {
reapVerify();
} else {
// we broke, let's restart the greeter
// error code 1 will result in a restart through the system
qApp->exit(1);
}
}
void KCheckPass::reapVerify()
{
m_notifier->setEnabled(false);
m_notifier->deleteLater();
m_notifier = nullptr;
::close(m_fd);
int status;
::kill(m_pid, SIGUSR2);
while (::waitpid(m_pid, &status, 0) < 0) {
if (errno != EINTR) { // This should not happen ...
cantCheck();
return;
}
}
}
void KCheckPass::cantCheck()
{
// TODO: better signal?
Q_EMIT failed();
}
void KCheckPass::startAuth()
{
::kill(m_pid, SIGUSR1);
}

@ -0,0 +1,111 @@
/********************************************************************
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 AUTHENTICATOR_H
#define AUTHENTICATOR_H
#include <QObject>
class QSocketNotifier;
class QTimer;
class KCheckPass;
enum class AuthenticationMode {
Delayed,
Direct,
};
class Authenticator : public QObject
{
Q_OBJECT
Q_PROPERTY(bool graceLocked READ isGraceLocked NOTIFY graceLockedChanged)
public:
explicit Authenticator(AuthenticationMode mode = AuthenticationMode::Direct, QObject *parent = nullptr);
~Authenticator() override;
bool isGraceLocked() const;
public Q_SLOTS:
void tryUnlock(const QString &password);
Q_SIGNALS:
void failed();
void succeeded();
void graceLockedChanged();
void message(const QString &msg); // don't remove the "msg" param, used in QML!!!
void error(const QString &err); // don't remove the "err" param, used in QML!!!
private:
void setupCheckPass();
QTimer *m_graceLockTimer;
KCheckPass *m_checkPass;
};
class KCheckPass : public QObject
{
Q_OBJECT
public:
explicit KCheckPass(AuthenticationMode mode, QObject *parent = nullptr);
~KCheckPass() override;
void start();
bool isReady() const
{
return m_ready;
}
void setPassword(const QString &password)
{
m_password = password;
}
void startAuth();
Q_SIGNALS:
void failed();
void succeeded();
void message(const QString &);
void error(const QString &);
private Q_SLOTS:
void handleVerify();
private:
void cantCheck();
void reapVerify();
// kcheckpass interface
int Reader(void *buf, int count);
bool GRead(void *buf, int count);
bool GWrite(const void *buf, int count);
bool GSendInt(int val);
bool GSendStr(const char *buf);
bool GSendArr(int len, const char *buf);
bool GRecvInt(int *val);
bool GRecvArr(char **buf);
QString m_password;
QSocketNotifier *m_notifier;
int m_pid;
int m_fd;
bool m_ready = false;
AuthenticationMode m_mode;
};
#endif

@ -0,0 +1,278 @@
/*
SPDX-FileCopyrightText: 2003 Lubos Lunak <l.lunak@kde.org>
SPDX-License-Identifier: MIT
*/
//#ifdef don't do this, this file is supposed to be included
//#define multiple times
#include <QtGlobal>
/* Usage:
If you get compile errors caused by X11 includes (the line
where first error appears contains word like None, Unsorted,
Below, etc.), put #include <fixx11h.h> in the .cpp file
(not .h file!) between the place where X11 headers are
included and the place where the file with compile
error is included (or the place where the compile error
in the .cpp file occurs).
This file remaps X11 #defines to const variables or
inline functions. The side effect may be that these
symbols may now refer to different variables
(e.g. if X11 #defined NoButton, after this file
is included NoButton would no longer be X11's
NoButton, but Qt::NoButton instead). At this time,
there's no conflict known that could cause problems.
The original X11 symbols are still accessible
(e.g. for None) as X::None, XNone, and also still
None, unless name lookup finds different None
first (in the current class, etc.)
Use 'Unsorted', 'Bool' and 'index' as templates.
*/
namespace X
{
// template --->
// Affects: Should be without side effects.
#ifdef Unsorted
#ifndef FIXX11H_Unsorted
#define FIXX11H_Unsorted
const int XUnsorted = Unsorted;
#undef Unsorted
const int Unsorted = XUnsorted;
#endif
#undef Unsorted
#endif
// template <---
// Affects: Should be without side effects.
#ifdef None
#ifndef FIXX11H_None
#define FIXX11H_None
const XID XNone = None;
#undef None
const XID None = XNone;
#endif
#undef None
#endif
// template --->
// Affects: Should be without side effects.
#ifdef Bool
#ifndef FIXX11H_Bool
#define FIXX11H_Bool
#ifdef _XTYPEDEF_BOOL /* Xdefs.h has typedef'ed Bool already */
#undef Bool
#else
typedef Bool XBool;
#undef Bool
typedef XBool Bool;
#endif
#endif
#undef Bool
#define _XTYPEDEF_BOOL
#endif
// template <---
// Affects: Should be without side effects.
#ifdef KeyPress
#ifndef FIXX11H_KeyPress
#define FIXX11H_KeyPress
const int XKeyPress = KeyPress;
#undef KeyPress
const int KeyPress = XKeyPress;
#endif
#undef KeyPress
#endif
// Affects: Should be without side effects.
#ifdef KeyRelease
#ifndef FIXX11H_KeyRelease
#define FIXX11H_KeyRelease
const int XKeyRelease = KeyRelease;
#undef KeyRelease
const int KeyRelease = XKeyRelease;
#endif
#undef KeyRelease
#endif
// Affects: Should be without side effects.
#ifdef Above
#ifndef FIXX11H_Above
#define FIXX11H_Above
const int XAbove = Above;
#undef Above
const int Above = XAbove;
#endif
#undef Above
#endif
// Affects: Should be without side effects.
#ifdef Below
#ifndef FIXX11H_Below
#define FIXX11H_Below
const int XBelow = Below;
#undef Below
const int Below = XBelow;
#endif
#undef Below
#endif
// Affects: Should be without side effects.
#ifdef FocusIn
#ifndef FIXX11H_FocusIn
#define FIXX11H_FocusIn
const int XFocusIn = FocusIn;
#undef FocusIn
const int FocusIn = XFocusIn;
#endif
#undef FocusIn
#endif
// Affects: Should be without side effects.
#ifdef FocusOut
#ifndef FIXX11H_FocusOut
#define FIXX11H_FocusOut
const int XFocusOut = FocusOut;
#undef FocusOut
const int FocusOut = XFocusOut;
#endif
#undef FocusOut
#endif
// Affects: Should be without side effects.
#ifdef Always
#ifndef FIXX11H_Always
#define FIXX11H_Always
const int XAlways = Always;
#undef Always
const int Always = XAlways;
#endif
#undef Always
#endif
// Affects: Should be without side effects.
#ifdef Expose
#ifndef FIXX11H_Expose
#define FIXX11H_Expose
const int XExpose = Expose;
#undef Expose
const int Expose = XExpose;
#endif
#undef Expose
#endif
// Affects: Should be without side effects.
#ifdef Success
#ifndef FIXX11H_Success
#define FIXX11H_Success
const int XSuccess = Success;
#undef Success
const int Success = XSuccess;
#endif
#undef Success
#endif
// Affects: Should be without side effects.
#ifdef GrayScale
#ifndef FIXX11H_GrayScale
#define FIXX11H_GrayScale
const int XGrayScale = GrayScale;
#undef GrayScale
const int GrayScale = XGrayScale;
#endif
#undef GrayScale
#endif
// Affects: Should be without side effects.
#ifdef Status
#ifndef FIXX11H_Status
#define FIXX11H_Status
typedef Status XStatus;
#undef Status
typedef XStatus Status;
#endif
#undef Status
#endif
// template --->
// Affects: Should be without side effects.
#ifdef CursorShape
#ifndef FIXX11H_CursorShape
#define FIXX11H_CursorShape
const int XCursorShape = CursorShape;
#undef CursorShape
const int CursorShape = XCursorShape;
#endif
#undef CursorShape
#endif
// template <---
// template --->
// Affects: Should be without side effects.
#ifdef FontChange
#ifndef FIXX11H_FontChange
#define FIXX11H_FontChange
const int XFontChange = FontChange;
#undef FontChange
const int FontChange = XFontChange;
#endif
#undef FontChange
#endif
// template <---
// Affects: Should be without side effects.
#ifdef NormalState
#ifndef FIXX11H_NormalState
#define FIXX11H_NormalState
const int XNormalState = NormalState;
#undef NormalState
const int NormalState = XNormalState;
#endif
#undef NormalState
#endif
// template --->
// Affects: Should be without side effects.
#ifdef index
#ifndef FIXX11H_index
#define FIXX11H_index
inline const char *Xindex(const char *s, int c)
{
return index(s, c);
}
#undef index
inline const char *index(const char *s, int c)
{
return Xindex(s, c);
}
#endif
#undef index
#endif
// template <---
#ifdef rindex
// Affects: Should be without side effects.
#ifndef FIXX11H_rindex
#define FIXX11H_rindex
inline const char *Xrindex(const char *s, int c)
{
return rindex(s, c);
}
#undef rindex
inline const char *rindex(const char *s, int c)
{
return Xrindex(s, c);
}
#endif
#undef rindex
#endif
}
using namespace X;

@ -0,0 +1,75 @@
/*****************************************************************
*
*· kcheckpass
*
*· Simple password checker. Just invoke and send it
*· the password on stdin.
*
*· If the password was accepted, the program exits with 0;
*· if it was rejected, it exits with 1. Any other exit
*· code signals an error.
*
*
* 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, write to the Free
* Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*· Copyright (C) 1998, Caldera, Inc.
*· Released under the GNU General Public License
*
*· Olaf Kirch <okir@caldera.de> General Framework and PAM support
*· Christian Esken <esken@kde.org> Shadow and /etc/passwd support
*· Oswald Buddenhagen <ossi@kde.org> Binary server mode
*
* Other parts were taken from kscreensaver's passwd.cpp
*****************************************************************/
#ifndef KCHECKPASS_ENUMS_H
#define KCHECKPASS_ENUMS_H
#ifdef __cplusplus
extern "C" {
#endif
/* these must match kcheckpass' exit codes */
typedef enum {
AuthOk = 0,
AuthBad = 1,
AuthError = 2,
AuthAbort = 3,
} AuthReturn;
typedef enum {
ConvGetBinary,
ConvGetNormal,
ConvGetHidden,
ConvPutInfo,
ConvPutError,
ConvPutAuthSucceeded,
ConvPutAuthFailed,
ConvPutAuthError,
ConvPutAuthAbort,
ConvPutReadyForAuthentication,
} ConvRequest;
/* these must match the defs in kgreeterplugin.h */
typedef enum {
IsUser = 1, /* unused in kcheckpass */
IsPassword = 2,
} DataTag;
#ifdef __cplusplus
}
#endif
#endif /* KCHECKPASS_ENUMS_H */

@ -0,0 +1,9 @@
#include "application.h"
int main(int argc, char *argv[])
{
Application app(argc, argv);
app.setQuitOnLastWindowClosed(false);
app.initialViewSetup();
return app.exec();
}

@ -0,0 +1,6 @@
<RCC>
<qresource prefix="/">
<file>qml/LockScreen.qml</file>
<file>qml/Greeter.qml</file>
</qresource>
</RCC>

@ -0,0 +1,5 @@
import QtQuick 2.0
Item {
}

@ -0,0 +1,117 @@
import QtQuick 2.0
import QtQuick.Window 2.12
import QtQuick.Controls 2.12
import QtQuick.Layouts 1.12
import QtGraphicalEffects 1.0
import FishUI 1.0 as FishUI
Item {
id: root
property alias notification: message.text
Image {
id: wallpaperImage
anchors.fill: parent
source: "file://" + wallpaper.path
sourceSize: Qt.size(width * Screen.devicePixelRatio,
height * Screen.devicePixelRatio)
fillMode: Image.PreserveAspectCrop
asynchronous: false
clip: true
cache: false
smooth: true
}
FastBlur {
id: wallpaperBlur
anchors.fill: parent
radius: 64
source: wallpaperImage
cached: true
visible: true
}
ColumnLayout {
anchors.fill: parent
spacing: FishUI.Units.largeSpacing * 1.5
Item {
Layout.fillHeight: true
}
Label {
Layout.alignment: Qt.AlignHCenter
text: "cutefish"
color: "white"
}
TextField {
id: password
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: 40
Layout.preferredWidth: 240
placeholderText: qsTr("Password")
focus: true
echoMode: TextInput.Password
background: Rectangle {
color: "white"
opacity: 0.4
radius: FishUI.Theme.bigRadius
}
Keys.onEnterPressed: authenticator.tryUnlock(password.text)
Keys.onReturnPressed: authenticator.tryUnlock(password.text)
Keys.onEscapePressed: password.text = ""
}
Button {
Layout.alignment: Qt.AlignHCenter
Layout.preferredHeight: 40
Layout.preferredWidth: 240
text: qsTr("Unlock")
onClicked: authenticator.tryUnlock(password.text)
}
Label {
id: message
text: ""
Layout.alignment: Qt.AlignHCenter
font.bold: true
color: "white"
Behavior on opacity {
NumberAnimation {
duration: 250
}
}
opacity: text == "" ? 0 : 1
}
Item {
Layout.fillHeight: true
}
}
Connections {
target: authenticator
function onFailed() {
root.notification = qsTr("Unlocking failed")
}
function onGraceLockedChanged() {
if (!authenticator.graceLocked) {
root.notification = ""
password.selectAll()
password.focus = true
}
}
function onMessage(text) {
root.notification = text
}
function onError(text) {
root.notification = text
}
}
}

@ -0,0 +1,24 @@
#include "wallpaper.h"
Wallpaper::Wallpaper(QObject *parent)
: QObject(parent)
, m_interface("org.cutefish.Settings",
"/Theme", "org.cutefish.Theme",
QDBusConnection::sessionBus(), this)
{
if (m_interface.isValid()) {
connect(&m_interface, SIGNAL(wallpaperChanged(QString)), this, SLOT(onPathChanged(QString)));
}
}
QString Wallpaper::path() const
{
return m_interface.property("wallpaper").toString();
}
void Wallpaper::onPathChanged(QString path)
{
Q_UNUSED(path);
emit pathChanged();
}

@ -0,0 +1,28 @@
#ifndef WALLPAPER_H
#define WALLPAPER_H
#include <QObject>
#include <QDBusInterface>
class Wallpaper : public QObject
{
Q_OBJECT
Q_PROPERTY(QString path READ path NOTIFY pathChanged)
public:
explicit Wallpaper(QObject *parent = nullptr);
QString path() const;
signals:
void pathChanged();
private slots:
void onPathChanged(QString path);
private:
QDBusInterface m_interface;
QString m_wallpaper;
};
#endif // WALLPAPER_H
Loading…
Cancel
Save