├── debian ├── compat ├── source │ └── format ├── copyright ├── rules ├── changelog └── control ├── config-X11.h.cmake ├── checkpass ├── config-ccheckpass.h.cmake ├── CMakeLists.txt ├── checkpass-enums.h ├── checkpass_shadow.c ├── checkpass.h ├── checkpass_pam.c └── checkpass.c ├── screenlocker ├── images │ ├── dark │ │ ├── media-playback-pause-symbolic.svg │ │ ├── media-playback-start-symbolic.svg │ │ ├── media-skip-backward-symbolic.svg │ │ └── media-skip-forward-symbolic.svg │ ├── light │ │ ├── media-playback-pause-symbolic.svg │ │ ├── media-playback-start-symbolic.svg │ │ ├── media-skip-backward-symbolic.svg │ │ └── media-skip-forward-symbolic.svg │ ├── login.svg │ ├── system-lock-screen-symbolic.svg │ ├── screensaver-unlock-symbolic.svg │ └── media-cover.svg ├── CMakeLists.txt ├── qml.qrc ├── main.cpp ├── application.h ├── qml │ ├── LoginButton.qml │ ├── IconButton.qml │ ├── MprisItem.qml │ └── LockScreen.qml ├── kcheckpass-enums.h ├── authenticator.h ├── fixx11h.h ├── authenticator.cpp └── application.cpp ├── README.md ├── config-screenlocker.h.cmake ├── .gitignore ├── translations ├── zh_CN.ts ├── zh_TW.ts ├── he_IL.ts ├── ja_JP.ts ├── bn_BD.ts ├── fa_IR.ts ├── lv_LV.ts ├── sr_RS.ts ├── bs_BA.ts ├── cs_CZ.ts ├── hr_HR.ts ├── it_IT.ts ├── lt_LT.ts ├── pl_PL.ts ├── sk_SK.ts ├── en_US.ts ├── hu_HU.ts ├── nb_NO.ts ├── so.ts ├── tr_TR.ts ├── uk_UA.ts ├── ar_AA.ts ├── az_AZ.ts ├── fi_FI.ts ├── id_ID.ts ├── pt_BR.ts ├── sv_SE.ts ├── uz_UZ.ts ├── vi_VN.ts ├── be_BY.ts ├── da_DK.ts ├── eo_XX.ts ├── es_ES.ts ├── got.ts ├── hi_IN.ts ├── ie.ts ├── ne_NP.ts ├── nl_NL.ts ├── ro_RO.ts ├── ru_RU.ts ├── si_LK.ts ├── ta_IN.ts ├── tt_RU.ts ├── tzm.ts ├── bg_BG.ts ├── de_DE.ts ├── es_MX.ts ├── be_Latn.ts ├── fr_FR.ts ├── pt_PT.ts ├── mg.ts ├── ml_IN.ts ├── sw.ts └── zh_Hant_HK.ts ├── config-unix.h.cmake ├── .github └── workflows │ └── build.yml ├── ConfigureChecks.cmake ├── cmake ├── UnixAuth.cmake ├── Findloginctl.cmake ├── FindConsoleKit.cmake └── FindPAM.cmake ├── CMakeLists.txt └── config-workspace.h.cmake /debian/compat: -------------------------------------------------------------------------------- 1 | 9 2 | -------------------------------------------------------------------------------- /debian/source/format: -------------------------------------------------------------------------------- 1 | 3.0 (quilt) 2 | -------------------------------------------------------------------------------- /config-X11.h.cmake: -------------------------------------------------------------------------------- 1 | /* Define if you have the XInput extension */ 2 | #cmakedefine X11_Xinput_FOUND 1 3 | -------------------------------------------------------------------------------- /checkpass/config-ccheckpass.h.cmake: -------------------------------------------------------------------------------- 1 | /* Define to 1 if you have the header file. */ 2 | #cmakedefine HAVE_PATHS_H 1 3 | 4 | -------------------------------------------------------------------------------- /debian/copyright: -------------------------------------------------------------------------------- 1 | Format: http://www.debian.org/doc/packaging-manuals/copyright-format/1.0/ 2 | Upstream-Name: cutefish-screenlocker 3 | Source: cutefishos.com 4 | -------------------------------------------------------------------------------- /debian/rules: -------------------------------------------------------------------------------- 1 | #!/usr/bin/make -f 2 | 3 | export QT_SELECT=5 4 | 5 | %: 6 | dh $@ --parallel 7 | 8 | override_dh_auto_configure: 9 | dh_auto_configure -- -DEMBED_TRANSLATIONS=ON -DBUILD_TESTING=ON 10 | -------------------------------------------------------------------------------- /debian/changelog: -------------------------------------------------------------------------------- 1 | cutefish-screenlocker (0.6-1) UNRELEASED; urgency=high 2 | 3 | * Initial release (CutefishOS) 4 | 5 | -- CutefishOS Packaging Team Sun, 21 Nov 2021 13:52:29 +0800 -------------------------------------------------------------------------------- /screenlocker/images/dark/media-playback-pause-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /screenlocker/images/light/media-playback-pause-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Screen locker 2 | 3 | ## Third Party Code 4 | 5 | kcheckpass 6 | 7 | ## Dependencies 8 | 9 | ### Debian/Ubuntu 10 | 11 | ``` 12 | sudo apt install libpam0g-dev libx11-dev -y 13 | ``` 14 | 15 | ## Build 16 | 17 | ```shell 18 | mkdir build 19 | cd build 20 | cmake -DCMAKE_INSTALL_PREFIX:PATH=/usr .. 21 | make 22 | ``` 23 | 24 | ## Install 25 | 26 | ```shell 27 | sudo make install 28 | ``` 29 | 30 | ## License 31 | 32 | This project has been licensed by GPLv3. 33 | -------------------------------------------------------------------------------- /screenlocker/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set(CMAKE_AUTOUIC ON) 2 | set(CMAKE_AUTOMOC ON) 3 | set(CMAKE_AUTORCC ON) 4 | 5 | set(PROJECT_SOURCES 6 | main.cpp 7 | application.cpp 8 | authenticator.cpp 9 | kcheckpass-enums.h 10 | fixx11h.h 11 | qml.qrc 12 | ) 13 | 14 | add_executable(cutefish-screenlocker 15 | ${PROJECT_SOURCES} 16 | ) 17 | 18 | target_link_libraries(cutefish-screenlocker 19 | PRIVATE 20 | Qt5::Core 21 | Qt5::DBus 22 | Qt5::Widgets 23 | Qt5::X11Extras 24 | Qt5::Quick 25 | 26 | ${X11_LIBRARIES} 27 | ) 28 | 29 | install(TARGETS cutefish-screenlocker RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR}) 30 | -------------------------------------------------------------------------------- /config-screenlocker.h.cmake: -------------------------------------------------------------------------------- 1 | #ifdef KSCREENLOCKER_TEST_APPS 2 | #define KCHECKPASS_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/kcheckpass" 3 | #elif defined(KSCREENLOCKER_UNIT_TEST) 4 | #define KCHECKPASS_BIN "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/fakekcheckpass" 5 | #else 6 | #define KCHECKPASS_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/kcheckpass" 7 | #endif 8 | 9 | #define KSCREENLOCKER_GREET_BIN "${CMAKE_INSTALL_FULL_LIBEXECDIR}/kscreenlocker_greet" 10 | 11 | #cmakedefine01 HAVE_SYS_PRCTL_H 12 | #cmakedefine01 HAVE_PR_SET_DUMPABLE 13 | #cmakedefine01 HAVE_SYS_PROCCTL_H 14 | #cmakedefine01 HAVE_PROC_TRACE_CTL 15 | #cmakedefine01 HAVE_SIGNALFD_H 16 | #cmakedefine01 HAVE_EVENT_H -------------------------------------------------------------------------------- /screenlocker/images/dark/media-playback-start-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /screenlocker/images/light/media-playback-start-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | -------------------------------------------------------------------------------- /screenlocker/images/login.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | -------------------------------------------------------------------------------- /screenlocker/images/dark/media-skip-backward-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /screenlocker/images/light/media-skip-backward-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /screenlocker/images/dark/media-skip-forward-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /screenlocker/images/light/media-skip-forward-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # C++ objects and libs 2 | *.slo 3 | *.lo 4 | *.o 5 | *.a 6 | *.la 7 | *.lai 8 | *.so 9 | *.so.* 10 | *.dll 11 | *.dylib 12 | 13 | # Qt-es 14 | object_script.*.Release 15 | object_script.*.Debug 16 | *_plugin_import.cpp 17 | /.qmake.cache 18 | /.qmake.stash 19 | *.pro.user 20 | *.pro.user.* 21 | *.qbs.user 22 | *.qbs.user.* 23 | *.moc 24 | moc_*.cpp 25 | moc_*.h 26 | qrc_*.cpp 27 | ui_*.h 28 | *.qmlc 29 | *.jsc 30 | Makefile* 31 | *build-* 32 | *.qm 33 | *.prl 34 | 35 | # Qt unit tests 36 | target_wrapper.* 37 | 38 | # QtCreator 39 | *.autosave 40 | 41 | # QtCreator Qml 42 | *.qmlproject.user 43 | *.qmlproject.user.* 44 | 45 | # QtCreator CMake 46 | CMakeLists.txt.user* 47 | 48 | # QtCreator 4.8< compilation database 49 | compile_commands.json 50 | 51 | # QtCreator local machine specific files for imported projects 52 | *creator.user* 53 | 54 | /build/* 55 | -------------------------------------------------------------------------------- /screenlocker/images/system-lock-screen-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /screenlocker/images/screensaver-unlock-symbolic.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | image/svg+xml 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | -------------------------------------------------------------------------------- /translations/zh_CN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 密码 10 | 11 | 12 | 13 | Unlock 14 | 解锁 15 | 16 | 17 | 18 | Please enter your password 19 | 请输入您的密码 20 | 21 | 22 | 23 | Unlocking failed 24 | 解锁失败 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/zh_TW.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 密碼 10 | 11 | 12 | 13 | Unlock 14 | 開鎖 15 | 16 | 17 | 18 | Please enter your password 19 | 請輸入您的密碼 20 | 21 | 22 | 23 | Unlocking failed 24 | 解鎖失敗 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/he_IL.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | סיסמא 10 | 11 | 12 | 13 | Unlock 14 | בטל נעילה 15 | 16 | 17 | 18 | Please enter your password 19 | הקש סיסמה 20 | 21 | 22 | 23 | Unlocking failed 24 | ההתחברות נכשלה 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ja_JP.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | パスワード 10 | 11 | 12 | 13 | Unlock 14 | ロックを解除 15 | 16 | 17 | 18 | Please enter your password 19 | パスワードを入力してください 20 | 21 | 22 | 23 | Unlocking failed 24 | ロックの解除に失敗しました 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /screenlocker/qml.qrc: -------------------------------------------------------------------------------- 1 | 2 | 3 | qml/LockScreen.qml 4 | images/login.svg 5 | qml/LoginButton.qml 6 | images/screensaver-unlock-symbolic.svg 7 | images/system-lock-screen-symbolic.svg 8 | qml/MprisItem.qml 9 | images/media-cover.svg 10 | images/light/media-playback-pause-symbolic.svg 11 | images/light/media-playback-start-symbolic.svg 12 | images/light/media-skip-backward-symbolic.svg 13 | images/light/media-skip-forward-symbolic.svg 14 | images/dark/media-playback-pause-symbolic.svg 15 | images/dark/media-playback-start-symbolic.svg 16 | images/dark/media-skip-backward-symbolic.svg 17 | images/dark/media-skip-forward-symbolic.svg 18 | qml/IconButton.qml 19 | 20 | 21 | -------------------------------------------------------------------------------- /translations/bn_BD.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | পাসওয়ার্ড 10 | 11 | 12 | 13 | Unlock 14 | আনলক করুন 15 | 16 | 17 | 18 | Please enter your password 19 | আপনার পাসওয়ার্ড দিন 20 | 21 | 22 | 23 | Unlocking failed 24 | আনলক করা যায়নি 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/fa_IR.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | رمز عبور 10 | 11 | 12 | 13 | Unlock 14 | ورود 15 | 16 | 17 | 18 | Please enter your password 19 | لطفا رمز خود را وارد کنید 20 | 21 | 22 | 23 | Unlocking failed 24 | خطا در ورود 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/lv_LV.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Parole 10 | 11 | 12 | 13 | Unlock 14 | Atbloķēt 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/sr_RS.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Šifra 10 | 11 | 12 | 13 | Unlock 14 | Otključaj 15 | 16 | 17 | 18 | Please enter your password 19 | Unesite šifru 20 | 21 | 22 | 23 | Unlocking failed 24 | Otključavanje nije uspelo 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/bs_BA.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Lozinka 10 | 11 | 12 | 13 | Unlock 14 | Otključavanje 15 | 16 | 17 | 18 | Please enter your password 19 | Unesi lozinku 20 | 21 | 22 | 23 | Unlocking failed 24 | Otključavanje neuspješno 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/cs_CZ.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Heslo 10 | 11 | 12 | 13 | Unlock 14 | Odemknout 15 | 16 | 17 | 18 | Please enter your password 19 | Zadejte své heslo 20 | 21 | 22 | 23 | Unlocking failed 24 | Odemykání se nezdařilo 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/hr_HR.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Lozinka 10 | 11 | 12 | 13 | Unlock 14 | Otključavanje 15 | 16 | 17 | 18 | Please enter your password 19 | Upiši lozinku 20 | 21 | 22 | 23 | Unlocking failed 24 | Otključavanje neuspješno 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/it_IT.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Password 10 | 11 | 12 | 13 | Unlock 14 | Sblocca 15 | 16 | 17 | 18 | Please enter your password 19 | Inserisci la tua password 20 | 21 | 22 | 23 | Unlocking failed 24 | Sblocco fallito 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/lt_LT.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Slaptažodis 10 | 11 | 12 | 13 | Unlock 14 | Atrakinti 15 | 16 | 17 | 18 | Please enter your password 19 | Įveskite slaptažodį 20 | 21 | 22 | 23 | Unlocking failed 24 | Nepavyko atrakinti 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/pl_PL.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Hasło 10 | 11 | 12 | 13 | Unlock 14 | Odblokuj 15 | 16 | 17 | 18 | Please enter your password 19 | Proszę wprowadzić hasło 20 | 21 | 22 | 23 | Unlocking failed 24 | Odblokowanie nieudane 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/sk_SK.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Heslo 10 | 11 | 12 | 13 | Unlock 14 | Odomknúť 15 | 16 | 17 | 18 | Please enter your password 19 | Prosím, zadajte Vaše heslo 20 | 21 | 22 | 23 | Unlocking failed 24 | Odomknutie zlyhalo 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/en_US.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Password 10 | 11 | 12 | 13 | Unlock 14 | Unlock 15 | 16 | 17 | 18 | Please enter your password 19 | Please enter your password 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/hu_HU.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Jelszó 10 | 11 | 12 | 13 | Unlock 14 | Feloldás 15 | 16 | 17 | 18 | Please enter your password 19 | Kérjük adja meg a jelszavát 20 | 21 | 22 | 23 | Unlocking failed 24 | A feloldás sikertelen 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/nb_NO.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Passord 10 | 11 | 12 | 13 | Unlock 14 | Lås opp 15 | 16 | 17 | 18 | Please enter your password 19 | Skriv inn passordet ditt 20 | 21 | 22 | 23 | Unlocking failed 24 | Opplåsing mislyktes 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/so.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Ereykugal 10 | 11 | 12 | 13 | Unlock 14 | Fur 15 | 16 | 17 | 18 | Please enter your password 19 | Fadlan gali ereykugalkaaga 20 | 21 | 22 | 23 | Unlocking failed 24 | Furiddu way fashilantay 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/tr_TR.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Şifre 10 | 11 | 12 | 13 | Unlock 14 | Kilidi kaldır 15 | 16 | 17 | 18 | Please enter your password 19 | Lütfen şifrenizi girin 20 | 21 | 22 | 23 | Unlocking failed 24 | Giriş başarısız oldu 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/uk_UA.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Пароль 10 | 11 | 12 | 13 | Unlock 14 | Розблокувати 15 | 16 | 17 | 18 | Please enter your password 19 | Уведіть свій пароль 20 | 21 | 22 | 23 | Unlocking failed 24 | Не вдалося розблокувати 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ar_AA.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | كلمة المرور 10 | 11 | 12 | 13 | Unlock 14 | إلغاء القُفْل 15 | 16 | 17 | 18 | Please enter your password 19 | يُرجى إدخال كلمة المرور 20 | 21 | 22 | 23 | Unlocking failed 24 | فَشِل إلغاء القُفْل 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/az_AZ.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Şifrə 10 | 11 | 12 | 13 | Unlock 14 | Kiliddən çıxar 15 | 16 | 17 | 18 | Please enter your password 19 | Lütfən şifrəni daxil et 20 | 21 | 22 | 23 | Unlocking failed 24 | Kiliddən çıxarıla bilmədi 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/fi_FI.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Salasana 10 | 11 | 12 | 13 | Unlock 14 | Avaa lukitus 15 | 16 | 17 | 18 | Please enter your password 19 | Syötä salasana 20 | 21 | 22 | 23 | Unlocking failed 24 | Lukituksen avaaminen epäonnistui 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/id_ID.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Kata Sandi 10 | 11 | 12 | 13 | Unlock 14 | Buka Kunci 15 | 16 | 17 | 18 | Please enter your password 19 | Mohon Masukan Password Anda 20 | 21 | 22 | 23 | Unlocking failed 24 | Gagal Membuka Kunci 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/pt_BR.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Senha 10 | 11 | 12 | 13 | Unlock 14 | Desbloquear 15 | 16 | 17 | 18 | Please enter your password 19 | Por favor, insira sua senha 20 | 21 | 22 | 23 | Unlocking failed 24 | O desbloqueio falhou 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/sv_SE.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Lösenord 10 | 11 | 12 | 13 | Unlock 14 | Lås upp 15 | 16 | 17 | 18 | Please enter your password 19 | Vänligen ange ditt lösenord 20 | 21 | 22 | 23 | Unlocking failed 24 | Upplåsning misslyckades 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/uz_UZ.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Parol 10 | 11 | 12 | 13 | Unlock 14 | Ruxsat berish 15 | 16 | 17 | 18 | Please enter your password 19 | Iltimos, parolni kiriting 20 | 21 | 22 | 23 | Unlocking failed 24 | Qulifni ochishda xatolik 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/vi_VN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Mật khẩu 10 | 11 | 12 | 13 | Unlock 14 | Mở khóa 15 | 16 | 17 | 18 | Please enter your password 19 | Hãy nhập mật khẩu của bạn 20 | 21 | 22 | 23 | Unlocking failed 24 | Việc mở khóa đã thất bại 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/be_BY.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Пароль 10 | 11 | 12 | 13 | Unlock 14 | Разблакіраваць 15 | 16 | 17 | 18 | Please enter your password 19 | Калі ласка, увядзіце пароль 20 | 21 | 22 | 23 | Unlocking failed 24 | Не ўдалося разблакаваць 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/da_DK.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Adgangskode 10 | 11 | 12 | 13 | Unlock 14 | Lås op 15 | 16 | 17 | 18 | Please enter your password 19 | Indtast venligst din adgangskode 20 | 21 | 22 | 23 | Unlocking failed 24 | Oplåsning mislykkedes 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/eo_XX.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/es_ES.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Contraseña 10 | 11 | 12 | 13 | Unlock 14 | Desbloquear 15 | 16 | 17 | 18 | Please enter your password 19 | Porfavor, escriba su contraseña 20 | 21 | 22 | 23 | Unlocking failed 24 | Desbloqueo fallido 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/got.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/hi_IN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ie.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Contrasigne 10 | 11 | 12 | 13 | Unlock 14 | Desserrar 15 | 16 | 17 | 18 | Please enter your password 19 | Ples provider vor contrasigne 20 | 21 | 22 | 23 | Unlocking failed 24 | Ne successat desserrar 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ne_NP.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/nl_NL.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Wachtwoord 10 | 11 | 12 | 13 | Unlock 14 | Ontgrendel 15 | 16 | 17 | 18 | Please enter your password 19 | Voer je wachtwoord in 20 | 21 | 22 | 23 | Unlocking failed 24 | Het ontgrendelen is mislukt 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ro_RO.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Parolă 10 | 11 | 12 | 13 | Unlock 14 | Deblochează 15 | 16 | 17 | 18 | Please enter your password 19 | Introduceți parola dumneavoastră 20 | 21 | 22 | 23 | Unlocking failed 24 | Deblocarea nu a reușit 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ru_RU.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Пароль 10 | 11 | 12 | 13 | Unlock 14 | Разблокировать 15 | 16 | 17 | 18 | Please enter your password 19 | Пожалуйста, введите пароль 20 | 21 | 22 | 23 | Unlocking failed 24 | Не удалось разблокировать 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/si_LK.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | මුර පදය 10 | 11 | 12 | 13 | Unlock 14 | අගුල අරින්න 15 | 16 | 17 | 18 | Please enter your password 19 | කරුණාකර ඔබගේ මුරපදය අතුලත් කරන්න 20 | 21 | 22 | 23 | Unlocking failed 24 | අගුල ඇරීම අසාර්ථක විය 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ta_IN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | கடவுச்சொல் 10 | 11 | 12 | 13 | Unlock 14 | திறக்க 15 | 16 | 17 | 18 | Please enter your password 19 | உங்கள் கடவுச்சொல்லை உள்ளிடவும் 20 | 21 | 22 | 23 | Unlocking failed 24 | திறத்தல் தோல்வியடைந்தது 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/tt_RU.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/tzm.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Taguri n uzerray 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/bg_BG.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Парола 10 | 11 | 12 | 13 | Unlock 14 | Отключване 15 | 16 | 17 | 18 | Please enter your password 19 | Моля, въведете вашата парола 20 | 21 | 22 | 23 | Unlocking failed 24 | Възникна грешка при откючване 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/de_DE.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Passwort 10 | 11 | 12 | 13 | Unlock 14 | Entsperren 15 | 16 | 17 | 18 | Please enter your password 19 | Bitte geben Sie Ihr Passwort ein 20 | 21 | 22 | 23 | Unlocking failed 24 | Entsperren fehlgeschlagen 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/es_MX.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Contraseña 10 | 11 | 12 | 13 | Unlock 14 | Desbloquear 15 | 16 | 17 | 18 | Please enter your password 19 | Por favor, introduzca su contraseña 20 | 21 | 22 | 23 | Unlocking failed 24 | Desbloqueo fallido 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/be_Latn.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/fr_FR.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Mot de passe 10 | 11 | 12 | 13 | Unlock 14 | Déverrouiller 15 | 16 | 17 | 18 | Please enter your password 19 | Veuillez entrer votre mot de passe 20 | 21 | 22 | 23 | Unlocking failed 24 | Échec du déverrouillage 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/pt_PT.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Palavra-passe 10 | 11 | 12 | 13 | Unlock 14 | Desbloquear 15 | 16 | 17 | 18 | Please enter your password 19 | Por favor introduza a sua palavra-passe 20 | 21 | 22 | 23 | Unlocking failed 24 | Falha a desbloquear 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/mg.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Teny miafina 10 | 11 | 12 | 13 | Unlock 14 | Sokafana 15 | 16 | 17 | 18 | Please enter your password 19 | Ampidiro ny teny miafinao azafady 20 | 21 | 22 | 23 | Unlocking failed 24 | Misy tsy fihetezana ny fanokafana 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/ml_IN.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | പാസ്സ്‌വേർഡ് 10 | 11 | 12 | 13 | Unlock 14 | അൺലോക്ക് 15 | 16 | 17 | 18 | Please enter your password 19 | നിങ്ങളുടെ പാസ്സ്‌വേർഡ് ടൈപ്പ് ചെയ്യുക 20 | 21 | 22 | 23 | Unlocking failed 24 | അൺലോക്ക് ചെയ്യാൻ കഴിഞ്ഞില്ല 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/sw.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | Neno la siri 10 | 11 | 12 | 13 | Unlock 14 | Fungua 15 | 16 | 17 | 18 | Please enter your password 19 | Tafadhali ingiza neno la siri 20 | 21 | 22 | 23 | Unlocking failed 24 | Kufunguliwa limeshindwa 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /translations/zh_Hant_HK.ts: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | LockScreen 6 | 7 | 8 | Password 9 | 10 | 11 | 12 | 13 | Unlock 14 | 15 | 16 | 17 | 18 | Please enter your password 19 | 20 | 21 | 22 | 23 | Unlocking failed 24 | 25 | 26 | 27 | 28 | -------------------------------------------------------------------------------- /debian/control: -------------------------------------------------------------------------------- 1 | Source: cutefish-screenlocker 2 | Section: devel 3 | Priority: optional 4 | Maintainer: CutefishOS 5 | Build-Depends: cmake, 6 | debhelper (>= 9), 7 | extra-cmake-modules, 8 | qtbase5-dev, 9 | qtdeclarative5-dev, 10 | qtquickcontrols2-5-dev, 11 | qttools5-dev, 12 | qttools5-dev-tools, 13 | libqt5x11extras5-dev, 14 | libpam0g-dev, 15 | libx11-dev 16 | Standards-Version: 4.5.0 17 | Homepage: https://cutefishos.com 18 | 19 | Package: cutefish-screenlocker 20 | Architecture: any 21 | Depends: qml-module-qtquick-controls2, 22 | qml-module-qtquick2, 23 | qml-module-qtquick-layouts, 24 | qml-module-qt-labs-platform, 25 | qml-module-qt-labs-settings, 26 | qml-module-qtqml, 27 | qml-module-qtquick-window2, 28 | qml-module-qtquick-shapes, 29 | qml-module-qtquick-dialogs, 30 | ${misc:Depends}, 31 | ${shlibs:Depends} 32 | Description: CutefishOS Screen Locker 33 | -------------------------------------------------------------------------------- /checkpass/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories( ${UNIXAUTH_INCLUDE_DIRS} ) 2 | check_include_files(paths.h HAVE_PATHS_H) 3 | configure_file (config-ccheckpass.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-ccheckpass.h ) 4 | 5 | set(ccheckpass_SRCS 6 | checkpass.h 7 | checkpass.c 8 | checkpass_pam.c 9 | checkpass_shadow.c 10 | ) 11 | 12 | # find_package(ECM REQUIRED NO_MODULE) 13 | # set(CMAKE_MODULE_PATH ${ECM_MODULE_PATH} ) 14 | # include(ECMMarkNonGuiExecutable) 15 | 16 | add_executable(ccheckpass ${ccheckpass_SRCS}) 17 | # ecm_mark_nongui_executable(ccheckpass) 18 | 19 | set_property(TARGET ccheckpass APPEND_STRING PROPERTY COMPILE_FLAGS " -U_REENTRANT") 20 | target_link_libraries(ccheckpass ${UNIXAUTH_LIBRARIES} ${SOCKET_LIBRARIES}) 21 | 22 | if (PAM_FOUND) 23 | set(checkpass_suid "") 24 | else() 25 | set(checkpass_suid "SETUID") 26 | message(STATUS "PAM not found, will install a SUID-kcheckpass") 27 | endif() 28 | install(TARGETS ccheckpass 29 | DESTINATION ${CMAKE_INSTALL_BINDIR} 30 | PERMISSIONS OWNER_READ OWNER_WRITE OWNER_EXECUTE GROUP_READ GROUP_EXECUTE WORLD_READ WORLD_EXECUTE ${checkpass_suid} 31 | ) 32 | 33 | #EXTRA_DIST = README 34 | -------------------------------------------------------------------------------- /config-unix.h.cmake: -------------------------------------------------------------------------------- 1 | /* Defines if you have PAM (Pluggable Authentication Modules) */ 2 | #cmakedefine HAVE_PAM 1 3 | 4 | /* Define if your PAM headers are in pam/ instead of security/ */ 5 | #cmakedefine HAVE_PAM_PAM_APPL_H 1 6 | 7 | /* Define if your PAM expects a conversation function with const pam_message (Solaris) */ 8 | #cmakedefine PAM_MESSAGE_CONST 1 9 | 10 | /* The PAM service to be used by kscreensaver */ 11 | #cmakedefine KSCREENSAVER_PAM_SERVICE ${KSCREENSAVER_PAM_SERVICE} 12 | 13 | /* Defines if your system has the getspnam function */ 14 | #cmakedefine HAVE_GETSPNAM 1 15 | 16 | /* Defines if your system has the crypt function */ 17 | #cmakedefine HAVE_CRYPT 1 18 | 19 | /* Define to 1 if you have the header file. */ 20 | #cmakedefine HAVE_CRYPT_H 1 21 | 22 | /* Define to 1 if you have the `pw_encrypt' function. */ 23 | #cmakedefine HAVE_PW_ENCRYPT 1 24 | 25 | /* Define to 1 if you have the `getpassphrase' function. */ 26 | #cmakedefine HAVE_GETPASSPHRASE 1 27 | 28 | /* Define to 1 if you have the `vsyslog' function. */ 29 | #cmakedefine HAVE_VSYSLOG 1 30 | 31 | /* Define to 1 if you have the header file. */ 32 | #cmakedefine HAVE_LIMITS_H 1 33 | -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Build 2 | 3 | on: 4 | push: 5 | branches: [ main ] 6 | pull_request: 7 | branches: [ main ] 8 | 9 | jobs: 10 | debian: 11 | name: Debian 12 | runs-on: ubuntu-latest 13 | container: docker.io/library/debian:sid 14 | steps: 15 | - name: Checkout Source 16 | uses: actions/checkout@v2 17 | - name: Update repository 18 | run: apt-get update -y 19 | - name: Install the basic dev packages 20 | run: apt-get install -y equivs curl git devscripts lintian build-essential automake autotools-dev cmake g++ 21 | - name: Install build dependencies 22 | run: mk-build-deps -i -t "apt-get --yes" -r 23 | - name: Build Package 24 | run: dpkg-buildpackage -b -uc -us -j$(nproc) 25 | 26 | ubuntu: 27 | name: Ubuntu 28 | runs-on: ubuntu-latest 29 | steps: 30 | - name: Checkout Source 31 | uses: actions/checkout@v2 32 | - name: Update repository 33 | run: sudo apt-get update -y 34 | - name: Install the basic dev packages 35 | run: sudo apt-get install -y equivs curl git devscripts lintian build-essential automake autotools-dev cmake g++ 36 | - name: Install build dependencies 37 | run: sudo mk-build-deps -i -t "apt-get --yes" -r 38 | - name: Build Package 39 | run: dpkg-buildpackage -b -uc -us -j$(nproc) 40 | -------------------------------------------------------------------------------- /ConfigureChecks.cmake: -------------------------------------------------------------------------------- 1 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake ${CMAKE_MODULE_PATH} ) 2 | include(UnixAuth) 3 | set_package_properties(PAM PROPERTIES DESCRIPTION "PAM Libraries" 4 | URL "https://www.kernel.org/pub/linux/libs/pam/" 5 | TYPE OPTIONAL 6 | PURPOSE "Required for screen unlocking and optionally used by the KDM log in manager" 7 | ) 8 | if(PAM_REQUIRED) 9 | set_package_properties(PAM PROPERTIES TYPE REQUIRED) 10 | endif() 11 | include(CheckTypeSize) 12 | include(FindPkgConfig) 13 | 14 | if (PAM_FOUND) 15 | set(KDE4_COMMON_PAM_SERVICE "kde" CACHE STRING "The PAM service to use unless overridden for a particular app.") 16 | 17 | macro(define_pam_service APP) 18 | string(TOUPPER ${APP}_PAM_SERVICE var) 19 | set(cvar KDE4_${var}) 20 | set(${cvar} "${KDE4_COMMON_PAM_SERVICE}" CACHE STRING "The PAM service for ${APP}.") 21 | mark_as_advanced(${cvar}) 22 | set(${var} "\"${${cvar}}\"") 23 | endmacro(define_pam_service) 24 | 25 | define_pam_service(kscreensaver) 26 | endif (PAM_FOUND) 27 | 28 | check_function_exists(getpassphrase HAVE_GETPASSPHRASE) 29 | check_function_exists(vsyslog HAVE_VSYSLOG) 30 | check_function_exists(statvfs HAVE_STATVFS) 31 | 32 | check_include_files(limits.h HAVE_LIMITS_H) 33 | check_include_files(sys/time.h HAVE_SYS_TIME_H) # ksmserver, ksplashml, sftp 34 | check_include_files(sys/param.h HAVE_SYS_PARAM_H) 35 | check_include_files(unistd.h HAVE_UNISTD_H) 36 | check_include_files(malloc.h HAVE_MALLOC_H) 37 | check_function_exists(statfs HAVE_STATFS) 38 | 39 | set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h) 40 | 41 | check_function_exists(setpriority HAVE_SETPRIORITY) # kscreenlocker -------------------------------------------------------------------------------- /cmake/UnixAuth.cmake: -------------------------------------------------------------------------------- 1 | find_package(PAM) 2 | 3 | include(CheckFunctionExists) 4 | include(CheckLibraryExists) 5 | include(CheckIncludeFiles) 6 | include(CMakePushCheckState) 7 | 8 | set(UNIXAUTH_LIBRARIES) 9 | set(UNIXAUTH_INCLUDE_DIRS) 10 | 11 | set(SHADOW_LIBRARIES) 12 | check_function_exists(getspnam found_getspnam) 13 | if (found_getspnam) 14 | set(HAVE_GETSPNAM 1) 15 | else (found_getspnam) 16 | cmake_push_check_state() 17 | set(CMAKE_REQUIRED_LIBRARIES -lshadow) 18 | check_function_exists(getspnam found_getspnam_shadow) 19 | if (found_getspnam_shadow) 20 | set(HAVE_GETSPNAM 1) 21 | set(SHADOW_LIBRARIES shadow) 22 | check_function_exists(pw_encrypt HAVE_PW_ENCRYPT) # ancient Linux shadow 23 | else (found_getspnam_shadow) 24 | set(CMAKE_REQUIRED_LIBRARIES -lgen) # UnixWare 25 | check_function_exists(getspnam found_getspnam_gen) 26 | if (found_getspnam_gen) 27 | set(HAVE_GETSPNAM 1) 28 | set(SHADOW_LIBRARIES gen) 29 | endif (found_getspnam_gen) 30 | endif (found_getspnam_shadow) 31 | cmake_pop_check_state() 32 | endif (found_getspnam) 33 | 34 | set(CRYPT_LIBRARIES) 35 | check_library_exists(crypt crypt "" HAVE_CRYPT) 36 | if (HAVE_CRYPT) 37 | set(CRYPT_LIBRARIES crypt) 38 | check_include_files(crypt.h HAVE_CRYPT_H) 39 | endif (HAVE_CRYPT) 40 | 41 | if (PAM_FOUND) 42 | 43 | set(HAVE_PAM 1) 44 | set(UNIXAUTH_LIBRARIES ${PAM_LIBRARIES}) 45 | set(UNIXAUTH_INCLUDE_DIRS ${PAM_INCLUDE_DIR}) 46 | 47 | else (PAM_FOUND) 48 | 49 | if (HAVE_GETSPNAM) 50 | set(UNIXAUTH_LIBRARIES ${SHADOW_LIBRARIES}) 51 | endif (HAVE_GETSPNAM) 52 | if (NOT HAVE_PW_ENCRYPT) 53 | set(UNIXAUTH_LIBRARIES ${UNIXAUTH_LIBRARIES} ${CRYPT_LIBRARIES}) 54 | endif (NOT HAVE_PW_ENCRYPT) 55 | 56 | endif (PAM_FOUND) 57 | -------------------------------------------------------------------------------- /screenlocker/main.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Reion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "application.h" 21 | #include 22 | #include 23 | #include 24 | 25 | int main(int argc, char *argv[]) 26 | { 27 | Application app(argc, argv); 28 | 29 | if (!QDBusConnection::sessionBus().registerService("com.cutefish.ScreenLocker")) { 30 | return -1; 31 | } 32 | 33 | if (!QDBusConnection::sessionBus().registerObject("/ScreenLocker", &app)) { 34 | return -1; 35 | } 36 | 37 | // Translations 38 | QLocale locale; 39 | QString qmFilePath = QString("%1/%2.qm").arg("/usr/share/cutefish-screenlocker/translations/").arg(locale.name()); 40 | if (QFile::exists(qmFilePath)) { 41 | QTranslator *translator = new QTranslator(app.instance()); 42 | if (translator->load(qmFilePath)) { 43 | app.installTranslator(translator); 44 | } else { 45 | translator->deleteLater(); 46 | } 47 | } 48 | 49 | app.setQuitOnLastWindowClosed(false); 50 | app.initialViewSetup(); 51 | return app.exec(); 52 | } 53 | -------------------------------------------------------------------------------- /screenlocker/application.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Reion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #ifndef APPLICATION_H 21 | #define APPLICATION_H 22 | 23 | #include 24 | #include 25 | 26 | #include 27 | #include "authenticator.h" 28 | 29 | class Application : public QGuiApplication 30 | { 31 | Q_OBJECT 32 | 33 | public: 34 | explicit Application(int &argc, char **argv); 35 | ~Application(); 36 | 37 | void initialViewSetup(); 38 | 39 | public slots: 40 | void desktopResized(); 41 | void onScreenAdded(QScreen *screen); 42 | 43 | private slots: 44 | void onSucceeded(); 45 | void getFocus(); 46 | void markViewsAsVisible(QQuickView *view); 47 | 48 | protected: 49 | bool eventFilter(QObject *obj, QEvent *event) override; 50 | 51 | private: 52 | QWindow *getActiveScreen(); 53 | void shareEvent(QEvent *e, QQuickView *from); 54 | void screenGeometryChanged(QScreen *screen, const QRect &geo); 55 | 56 | private: 57 | Authenticator *m_authenticator; 58 | QList m_views; 59 | 60 | bool m_testing = false; 61 | }; 62 | 63 | #endif // APPLICATION_H 64 | -------------------------------------------------------------------------------- /cmake/Findloginctl.cmake: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Copyright 2016 Martin Gräßlin 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # 8 | # 1. Redistributions of source code must retain the copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 3. The name of the author may not be used to endorse or promote products 14 | # derived from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | #============================================================================= 27 | find_program(loginctl_EXECUTABLE NAMES loginctl) 28 | find_package_handle_standard_args(loginctl 29 | FOUND_VAR 30 | loginctl_FOUND 31 | REQUIRED_VARS 32 | loginctl_EXECUTABLE 33 | ) 34 | mark_as_advanced(loginctl_FOUND loginctl_EXECUTABLE) 35 | -------------------------------------------------------------------------------- /cmake/FindConsoleKit.cmake: -------------------------------------------------------------------------------- 1 | #============================================================================= 2 | # Copyright 2017 Tobias C. Berner 3 | # 4 | # Redistribution and use in source and binary forms, with or without 5 | # modification, are permitted provided that the following conditions 6 | # are met: 7 | # 8 | # 1. Redistributions of source code must retain the copyright 9 | # notice, this list of conditions and the following disclaimer. 10 | # 2. Redistributions in binary form must reproduce the copyright 11 | # notice, this list of conditions and the following disclaimer in the 12 | # documentation and/or other materials provided with the distribution. 13 | # 3. The name of the author may not be used to endorse or promote products 14 | # derived from this software without specific prior written permission. 15 | # 16 | # THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR 17 | # IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES 18 | # OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. 19 | # IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, 20 | # INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT 21 | # NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, 22 | # DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY 23 | # THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT 24 | # (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF 25 | # THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 | #============================================================================= 27 | find_program(cklistsessions_EXECUTABLE NAMES ck-list-sessions) 28 | find_program(qdbus_EXECUTABLE NAMES qdbus) 29 | find_package_handle_standard_args(ConsoleKit 30 | FOUND_VAR 31 | ConsoleKit_FOUND 32 | REQUIRED_VARS 33 | cklistsessions_EXECUTABLE 34 | qdbus_EXECUTABLE 35 | ) 36 | mark_as_advanced(ConsoleKit_FOUND cklistsessions_EXECUTABLE qdbus_EXECUTABLE) 37 | -------------------------------------------------------------------------------- /cmake/FindPAM.cmake: -------------------------------------------------------------------------------- 1 | # - Try to find the PAM libraries 2 | # Once done this will define 3 | # 4 | # PAM_FOUND - system has pam 5 | # PAM_INCLUDE_DIR - the pam include directory 6 | # PAM_LIBRARIES - libpam library 7 | 8 | if (PAM_INCLUDE_DIR AND PAM_LIBRARY) 9 | # Already in cache, be silent 10 | set(PAM_FIND_QUIETLY TRUE) 11 | endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) 12 | 13 | find_path(PAM_INCLUDE_DIR NAMES security/pam_appl.h pam/pam_appl.h) 14 | find_library(PAM_LIBRARY pam) 15 | find_library(DL_LIBRARY dl) 16 | 17 | if (PAM_INCLUDE_DIR AND PAM_LIBRARY) 18 | set(PAM_FOUND TRUE) 19 | if (DL_LIBRARY) 20 | set(PAM_LIBRARIES ${PAM_LIBRARY} ${DL_LIBRARY}) 21 | else (DL_LIBRARY) 22 | set(PAM_LIBRARIES ${PAM_LIBRARY}) 23 | endif (DL_LIBRARY) 24 | 25 | if (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) 26 | # darwin claims to be something special 27 | set(HAVE_PAM_PAM_APPL_H 1) 28 | endif (EXISTS ${PAM_INCLUDE_DIR}/pam/pam_appl.h) 29 | 30 | if (NOT DEFINED PAM_MESSAGE_CONST) 31 | include(CheckCXXSourceCompiles) 32 | # XXX does this work with plain c? 33 | check_cxx_source_compiles(" 34 | #if ${HAVE_PAM_PAM_APPL_H}+0 35 | # include 36 | #else 37 | # include 38 | #endif 39 | 40 | static int PAM_conv( 41 | int num_msg, 42 | const struct pam_message **msg, /* this is the culprit */ 43 | struct pam_response **resp, 44 | void *ctx) 45 | { 46 | return 0; 47 | } 48 | 49 | int main(void) 50 | { 51 | struct pam_conv PAM_conversation = { 52 | &PAM_conv, /* this bombs out if the above does not match */ 53 | 0 54 | }; 55 | 56 | return 0; 57 | } 58 | " PAM_MESSAGE_CONST) 59 | endif (NOT DEFINED PAM_MESSAGE_CONST) 60 | set(PAM_MESSAGE_CONST ${PAM_MESSAGE_CONST} CACHE BOOL "PAM expects a conversation function with const pam_message") 61 | 62 | endif (PAM_INCLUDE_DIR AND PAM_LIBRARY) 63 | 64 | if (PAM_FOUND) 65 | if (NOT PAM_FIND_QUIETLY) 66 | message(STATUS "Found PAM: ${PAM_LIBRARIES}") 67 | endif (NOT PAM_FIND_QUIETLY) 68 | else (PAM_FOUND) 69 | if (PAM_FIND_REQUIRED) 70 | message(FATAL_ERROR "PAM was not found") 71 | endif(PAM_FIND_REQUIRED) 72 | endif (PAM_FOUND) 73 | 74 | mark_as_advanced(PAM_INCLUDE_DIR PAM_LIBRARY DL_LIBRARY PAM_MESSAGE_CONST) 75 | -------------------------------------------------------------------------------- /screenlocker/qml/LoginButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Reion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Window 2.3 22 | import QtQuick.Controls 2.4 23 | import FishUI 1.0 as FishUI 24 | 25 | Item { 26 | id: control 27 | 28 | property var size: 32 29 | property var iconMargins: 0 30 | height: size 31 | width: size 32 | 33 | property alias background: _background 34 | property color backgroundColor: FishUI.Theme.highlightColor 35 | property color hoveredColor: Qt.lighter(backgroundColor, 1.1) 36 | property color pressedColor: Qt.darker(backgroundColor, 1.2) 37 | property alias source: _image.source 38 | property alias image: _image 39 | signal clicked() 40 | 41 | Rectangle { 42 | id: _background 43 | anchors.fill: parent 44 | // radius: FishUI.Theme.bigRadius //control.height / 2 45 | color: mouseArea.pressed ? pressedColor : mouseArea.containsMouse ? control.hoveredColor : control.backgroundColor 46 | 47 | gradient: Gradient { 48 | GradientStop { position: 0.0; color: Qt.lighter(_background.color, 1.3) } 49 | GradientStop { position: 1.0; color: _background.color } 50 | } 51 | } 52 | 53 | MouseArea { 54 | id: mouseArea 55 | anchors.fill: parent 56 | hoverEnabled: true 57 | onClicked: control.clicked() 58 | } 59 | 60 | Image { 61 | id: _image 62 | objectName: "image" 63 | anchors.fill: parent 64 | anchors.margins: control.iconMargins 65 | fillMode: Image.PreserveAspectFit 66 | sourceSize: Qt.size(width, height) 67 | cache: true 68 | asynchronous: false 69 | } 70 | } 71 | -------------------------------------------------------------------------------- /checkpass/checkpass-enums.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * 3 | *· kcheckpass 4 | * 5 | *· Simple password checker. Just invoke and send it 6 | *· the password on stdin. 7 | * 8 | *· If the password was accepted, the program exits with 0; 9 | *· if it was rejected, it exits with 1. Any other exit 10 | *· code signals an error. 11 | * 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2 of the License, or (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public 24 | * License along with this program; if not, write to the Free 25 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | * 27 | *· Copyright (C) 1998, Caldera, Inc. 28 | *· Released under the GNU General Public License 29 | * 30 | *· Olaf Kirch General Framework and PAM support 31 | *· Christian Esken Shadow and /etc/passwd support 32 | *· Oswald Buddenhagen Binary server mode 33 | * 34 | * Other parts were taken from kscreensaver's passwd.cpp 35 | *****************************************************************/ 36 | 37 | #ifndef KCHECKPASS_ENUMS_H 38 | #define KCHECKPASS_ENUMS_H 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | /* these must match kcheckpass' exit codes */ 45 | typedef enum { 46 | AuthOk = 0, 47 | AuthBad = 1, 48 | AuthError = 2, 49 | AuthAbort = 3, 50 | } AuthReturn; 51 | 52 | typedef enum { 53 | ConvGetBinary, 54 | ConvGetNormal, 55 | ConvGetHidden, 56 | ConvPutInfo, 57 | ConvPutError, 58 | ConvPutAuthSucceeded, 59 | ConvPutAuthFailed, 60 | ConvPutAuthError, 61 | ConvPutAuthAbort, 62 | ConvPutReadyForAuthentication, 63 | } ConvRequest; 64 | 65 | /* these must match the defs in kgreeterplugin.h */ 66 | typedef enum { 67 | IsUser = 1, /* unused in kcheckpass */ 68 | IsPassword = 2, 69 | } DataTag; 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /* KCHECKPASS_ENUMS_H */ 76 | -------------------------------------------------------------------------------- /screenlocker/kcheckpass-enums.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * 3 | *· kcheckpass 4 | * 5 | *· Simple password checker. Just invoke and send it 6 | *· the password on stdin. 7 | * 8 | *· If the password was accepted, the program exits with 0; 9 | *· if it was rejected, it exits with 1. Any other exit 10 | *· code signals an error. 11 | * 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2 of the License, or (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public 24 | * License along with this program; if not, write to the Free 25 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | * 27 | *· Copyright (C) 1998, Caldera, Inc. 28 | *· Released under the GNU General Public License 29 | * 30 | *· Olaf Kirch General Framework and PAM support 31 | *· Christian Esken Shadow and /etc/passwd support 32 | *· Oswald Buddenhagen Binary server mode 33 | * 34 | * Other parts were taken from kscreensaver's passwd.cpp 35 | *****************************************************************/ 36 | 37 | #ifndef KCHECKPASS_ENUMS_H 38 | #define KCHECKPASS_ENUMS_H 39 | 40 | #ifdef __cplusplus 41 | extern "C" { 42 | #endif 43 | 44 | /* these must match kcheckpass' exit codes */ 45 | typedef enum { 46 | AuthOk = 0, 47 | AuthBad = 1, 48 | AuthError = 2, 49 | AuthAbort = 3, 50 | } AuthReturn; 51 | 52 | typedef enum { 53 | ConvGetBinary, 54 | ConvGetNormal, 55 | ConvGetHidden, 56 | ConvPutInfo, 57 | ConvPutError, 58 | ConvPutAuthSucceeded, 59 | ConvPutAuthFailed, 60 | ConvPutAuthError, 61 | ConvPutAuthAbort, 62 | ConvPutReadyForAuthentication, 63 | } ConvRequest; 64 | 65 | /* these must match the defs in kgreeterplugin.h */ 66 | typedef enum { 67 | IsUser = 1, /* unused in kcheckpass */ 68 | IsPassword = 2, 69 | } DataTag; 70 | 71 | #ifdef __cplusplus 72 | } 73 | #endif 74 | 75 | #endif /* KCHECKPASS_ENUMS_H */ 76 | -------------------------------------------------------------------------------- /screenlocker/qml/IconButton.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Reion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Controls 2.12 22 | import QtQuick.Layouts 1.12 23 | import FishUI 1.0 as FishUI 24 | 25 | Item { 26 | id: control 27 | 28 | property url source 29 | property real size: 24 30 | property string popupText 31 | 32 | signal leftButtonClicked 33 | signal rightButtonClicked 34 | 35 | MouseArea { 36 | id: mouseArea 37 | anchors.fill: parent 38 | acceptedButtons: Qt.LeftButton | Qt.RightButton 39 | hoverEnabled: control.visible ? true : false 40 | 41 | onClicked: { 42 | if (mouse.button === Qt.LeftButton) 43 | control.leftButtonClicked() 44 | else if (mouse.button === Qt.RightButton) 45 | control.rightButtonClicked() 46 | } 47 | } 48 | 49 | Rectangle { 50 | anchors.fill: parent 51 | anchors.margins: 1 52 | // radius: parent.height * 0.2 53 | radius: parent.height / 2 54 | 55 | color: { 56 | if (mouseArea.containsMouse) { 57 | if (mouseArea.containsPress) 58 | return (FishUI.Theme.darkMode) ? Qt.rgba(255, 255, 255, 0.3) : Qt.rgba(0, 0, 0, 0.2) 59 | else 60 | return (FishUI.Theme.darkMode) ? Qt.rgba(255, 255, 255, 0.2) : Qt.rgba(0, 0, 0, 0.1) 61 | } 62 | 63 | return "transparent" 64 | } 65 | } 66 | 67 | Image { 68 | id: iconImage 69 | anchors.centerIn: parent 70 | width: parent.height * 0.8 71 | height: width 72 | sourceSize.width: width 73 | sourceSize.height: height 74 | source: control.source 75 | asynchronous: true 76 | antialiasing: true 77 | smooth: false 78 | } 79 | } 80 | -------------------------------------------------------------------------------- /checkpass/checkpass_shadow.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1998 Christian Esken 3 | * Copyright (C) 2003 Oswald Buddenhagen 4 | * 5 | * This is a modified version of checkpass_shadow.cpp 6 | * 7 | * Modifications made by Thorsten Kukuk 8 | * Mathias Kettner 9 | * 10 | * ------------------------------------------------------------ 11 | * 12 | * This program is free software; you can redistribute it and/or 13 | * modify it under the terms of the GNU General Public 14 | * License as published by the Free Software Foundation; either 15 | * version 2 of the License, or (at your option) any later version. 16 | * 17 | * This program is distributed in the hope that it will be useful, 18 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 19 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 20 | * General Public License for more details. 21 | * 22 | * You should have received a copy of the GNU General Public 23 | * License along with this program; if not, write to the Free 24 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 25 | */ 26 | 27 | #include "checkpass.h" 28 | 29 | /******************************************************************* 30 | * This is the authentication code for Shadow-Passwords 31 | *******************************************************************/ 32 | 33 | #ifdef HAVE_SHADOW 34 | #include 35 | #include 36 | #include 37 | 38 | #ifndef __hpux 39 | #include 40 | #endif 41 | 42 | AuthReturn Authenticate(const char *method, const char *login, char *(*conv)(ConvRequest, const char *)) 43 | { 44 | char *typed_in_password; 45 | char *crpt_passwd; 46 | char *password; 47 | struct passwd *pw; 48 | struct spwd *spw; 49 | 50 | if (strcmp(method, "classic")) 51 | return AuthError; 52 | 53 | if (!(pw = getpwnam(login))) 54 | return AuthAbort; 55 | 56 | spw = getspnam(login); 57 | password = spw ? spw->sp_pwdp : pw->pw_passwd; 58 | 59 | if (!*password) 60 | return AuthOk; 61 | 62 | if (!(typed_in_password = conv(ConvGetHidden, 0))) 63 | return AuthAbort; 64 | 65 | #if defined(__linux__) && defined(HAVE_PW_ENCRYPT) 66 | crpt_passwd = pw_encrypt(typed_in_password, password); /* (1) */ 67 | #else 68 | crpt_passwd = crypt(typed_in_password, password); 69 | #endif 70 | 71 | if (crpt_passwd && !strcmp(password, crpt_passwd)) { 72 | dispose(typed_in_password); 73 | return AuthOk; /* Success */ 74 | } 75 | dispose(typed_in_password); 76 | return AuthBad; /* Password wrong or account locked */ 77 | } 78 | 79 | /* 80 | (1) Deprecated - long passwords have known weaknesses. Also, 81 | pw_encrypt is non-standard (requires libshadow.a) while 82 | everything else you need to support shadow passwords is in 83 | the standard (ELF) libc. 84 | */ 85 | #endif 86 | -------------------------------------------------------------------------------- /screenlocker/images/media-cover.svg: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(screenlocker) 4 | set(CMAKE_C_STANDARD 99) 5 | set(CMAKE_CXX_STANDARD 17) 6 | set(CMAKE_CXX_STANDARD_REQUIRED ON) 7 | 8 | set(CMAKE_INCLUDE_CURRENT_DIR ON) 9 | 10 | # set(CMAKE_AUTOUIC ON) 11 | # set(CMAKE_AUTOMOC ON) 12 | # set(CMAKE_AUTORCC ON) 13 | 14 | set(CMAKE_MODULE_PATH ${CMAKE_CURRENT_SOURCE_DIR}/cmake) 15 | 16 | include(CheckIncludeFile) 17 | include(CheckIncludeFiles) 18 | include(CheckSymbolExists) 19 | include(FeatureSummary) 20 | 21 | find_package(Qt5 COMPONENTS Core DBus Widgets X11Extras Quick LinguistTools REQUIRED) 22 | find_package(X11) 23 | 24 | # ----------- Check -------------------- 25 | 26 | check_include_file("sys/prctl.h" HAVE_SYS_PRCTL_H) 27 | check_symbol_exists(PR_SET_DUMPABLE "sys/prctl.h" HAVE_PR_SET_DUMPABLE) 28 | check_include_file("sys/procctl.h" HAVE_SYS_PROCCTL_H) 29 | check_symbol_exists(PROC_TRACE_CTL "sys/procctl.h" HAVE_PROC_TRACE_CTL) 30 | if (HAVE_PR_SET_DUMPABLE OR HAVE_PROC_TRACE_CTL) 31 | set(CAN_DISABLE_PTRACE TRUE) 32 | endif () 33 | add_feature_info("prctl/procctl tracing control" 34 | CAN_DISABLE_PTRACE 35 | "Required for disallowing ptrace on greeter and kcheckpass process") 36 | 37 | check_include_file("sys/signalfd.h" HAVE_SIGNALFD_H) 38 | if (NOT HAVE_SIGNALFD_H) 39 | check_include_files("sys/types.h;sys/event.h" HAVE_EVENT_H) 40 | endif () 41 | add_feature_info("sys/signalfd.h" 42 | HAVE_SIGNALFD_H 43 | "Use the signalfd() api for signalhandling") 44 | add_feature_info("sys/event.h" 45 | HAVE_EVENT_H 46 | "Use the kevent() and sigwaitinfo() api for signalhandling") 47 | 48 | # -------------------------------------- 49 | 50 | option(PAM_REQUIRED "Require building with PAM" ON) 51 | 52 | include(ConfigureChecks.cmake) 53 | 54 | configure_file(config-workspace.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-workspace.h) 55 | configure_file(config-unix.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-unix.h ) 56 | configure_file(config-X11.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-X11.h) 57 | 58 | set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -std=gnu90") 59 | 60 | configure_file(config-screenlocker.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-screenlocker.h) 61 | include_directories(${CMAKE_CURRENT_BINARY_DIR}) 62 | 63 | add_subdirectory(screenlocker) 64 | add_subdirectory(checkpass) 65 | 66 | feature_summary(WHAT ALL INCLUDE_QUIET_PACKAGES FATAL_ON_MISSING_REQUIRED_PACKAGES) 67 | 68 | 69 | # Get the installation directory from qmake 70 | get_target_property(QT_QMAKE_EXECUTABLE ${Qt5Core_QMAKE_EXECUTABLE} IMPORTED_LOCATION) 71 | if(NOT QT_QMAKE_EXECUTABLE) 72 | message(FATAL_ERROR "qmake is not found.") 73 | endif() 74 | 75 | execute_process(COMMAND ${QT_QMAKE_EXECUTABLE} -query QT_INSTALL_QML 76 | OUTPUT_VARIABLE INSTALL_QMLDIR 77 | OUTPUT_STRIP_TRAILING_WHITESPACE 78 | ) 79 | if(INSTALL_QMLDIR) 80 | message(STATUS "qml directory:" "${INSTALL_QMLDIR}") 81 | else() 82 | message(FATAL_ERROR "qml directory cannot be detected.") 83 | endif() 84 | 85 | # Install translations 86 | file(GLOB TS_FILES translations/*.ts) 87 | qt5_create_translation(QM_FILES ${TS_FILES}) 88 | add_custom_target(translations DEPENDS ${QM_FILES} SOURCES ${TS_FILES}) 89 | add_dependencies(cutefish-screenlocker translations) 90 | install(FILES ${QM_FILES} DESTINATION /usr/share/cutefish-screenlocker/translations) 91 | 92 | -------------------------------------------------------------------------------- /screenlocker/authenticator.h: -------------------------------------------------------------------------------- 1 | /******************************************************************** 2 | KSld - the KDE Screenlocker Daemon 3 | This file is part of the KDE project. 4 | 5 | Copyright (C) 2014 Martin Gräßlin 6 | 7 | This program is free software; you can redistribute it and/or modify 8 | it under the terms of the GNU General Public License as published by 9 | the Free Software Foundation; either version 2 of the License, or 10 | (at your option) any later version. 11 | 12 | This program is distributed in the hope that it will be useful, 13 | but WITHOUT ANY WARRANTY; without even the implied warranty of 14 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 | GNU General Public License for more details. 16 | 17 | You should have received a copy of the GNU General Public License 18 | along with this program. If not, see . 19 | *********************************************************************/ 20 | #ifndef AUTHENTICATOR_H 21 | #define AUTHENTICATOR_H 22 | 23 | #include 24 | 25 | class QSocketNotifier; 26 | class QTimer; 27 | class KCheckPass; 28 | 29 | enum class AuthenticationMode { 30 | Delayed, 31 | Direct, 32 | }; 33 | 34 | class Authenticator : public QObject 35 | { 36 | Q_OBJECT 37 | Q_PROPERTY(bool graceLocked READ isGraceLocked NOTIFY graceLockedChanged) 38 | public: 39 | explicit Authenticator(AuthenticationMode mode = AuthenticationMode::Direct, QObject *parent = nullptr); 40 | ~Authenticator() override; 41 | 42 | bool isGraceLocked() const; 43 | 44 | public Q_SLOTS: 45 | void tryUnlock(const QString &password); 46 | 47 | Q_SIGNALS: 48 | void failed(); 49 | void succeeded(); 50 | void graceLockedChanged(); 51 | void message(const QString &msg); // don't remove the "msg" param, used in QML!!! 52 | void error(const QString &err); // don't remove the "err" param, used in QML!!! 53 | 54 | private: 55 | void setupCheckPass(); 56 | QTimer *m_graceLockTimer; 57 | KCheckPass *m_checkPass; 58 | }; 59 | 60 | class KCheckPass : public QObject 61 | { 62 | Q_OBJECT 63 | public: 64 | explicit KCheckPass(AuthenticationMode mode, QObject *parent = nullptr); 65 | ~KCheckPass() override; 66 | 67 | void start(); 68 | 69 | bool isReady() const 70 | { 71 | return m_ready; 72 | } 73 | 74 | void setPassword(const QString &password) 75 | { 76 | m_password = password; 77 | } 78 | 79 | void startAuth(); 80 | 81 | Q_SIGNALS: 82 | void failed(); 83 | void succeeded(); 84 | void message(const QString &); 85 | void error(const QString &); 86 | 87 | private Q_SLOTS: 88 | void handleVerify(); 89 | 90 | private: 91 | void cantCheck(); 92 | void reapVerify(); 93 | // kcheckpass interface 94 | int Reader(void *buf, int count); 95 | bool GRead(void *buf, int count); 96 | bool GWrite(const void *buf, int count); 97 | bool GSendInt(int val); 98 | bool GSendStr(const char *buf); 99 | bool GSendArr(int len, const char *buf); 100 | bool GRecvInt(int *val); 101 | bool GRecvArr(char **buf); 102 | 103 | QString m_password; 104 | QSocketNotifier *m_notifier; 105 | int m_pid; 106 | int m_fd; 107 | bool m_ready = false; 108 | AuthenticationMode m_mode; 109 | }; 110 | 111 | #endif 112 | -------------------------------------------------------------------------------- /checkpass/checkpass.h: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * 3 | * kcheckpass 4 | * 5 | * Simple password checker. Just invoke and send it 6 | * the password on stdin. 7 | * 8 | * If the password was accepted, the program exits with 0; 9 | * if it was rejected, it exits with 1. Any other exit 10 | * code signals an error. 11 | * 12 | * 13 | * This program is free software; you can redistribute it and/or 14 | * modify it under the terms of the GNU General Public 15 | * License as published by the Free Software Foundation; either 16 | * version 2 of the License, or (at your option) any later version. 17 | * 18 | * This program is distributed in the hope that it will be useful, 19 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 20 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 | * General Public License for more details. 22 | * 23 | * You should have received a copy of the GNU General Public 24 | * License along with this program; if not, write to the Free 25 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 26 | * 27 | * Copyright (C) 1998, Caldera, Inc. 28 | * Released under the GNU General Public License 29 | * 30 | * Olaf Kirch General Framework and PAM support 31 | * Christian Esken Shadow and /etc/passwd support 32 | * Oswald Buddenhagen Binary server mode 33 | * 34 | * Other parts were taken from kscreensaver's passwd.cpp 35 | *****************************************************************/ 36 | 37 | #ifndef KCHECKPASS_H_ 38 | #define KCHECKPASS_H_ 39 | 40 | #include 41 | #include 42 | #include 43 | 44 | #ifdef HAVE_CRYPT_H 45 | #include 46 | #endif 47 | 48 | #ifdef HAVE_PATHS_H 49 | #include 50 | #endif 51 | 52 | #include 53 | #include 54 | 55 | #ifndef _PATH_TMP 56 | #define _PATH_TMP "/tmp/" 57 | #endif 58 | 59 | #ifdef ultrix 60 | #include 61 | #endif 62 | 63 | #include 64 | 65 | /* Make sure there is only one! */ 66 | #if defined(HAVE_PAM) 67 | #else 68 | #define HAVE_SHADOW 69 | #endif 70 | 71 | #if __GNUC__ > 2 || (__GNUC__ == 2 && __GNUC_MINOR__ > 4) 72 | #define ATTR_UNUSED __attribute__((unused)) 73 | #define ATTR_NORETURN __attribute__((noreturn)) 74 | #define ATTR_PRINTFLIKE(fmt, var) __attribute__((format(printf, fmt, var))) 75 | #else 76 | #define ATTR_UNUSED 77 | #define ATTR_NORETURN 78 | #define ATTR_PRINTFLIKE(fmt, var) 79 | #endif 80 | 81 | #include "checkpass-enums.h" 82 | 83 | #ifdef __cplusplus 84 | extern "C" { 85 | #endif 86 | 87 | /***************************************************************** 88 | * Authenticates user 89 | *****************************************************************/ 90 | AuthReturn Authenticate(const char *method, const char *user, char *(*conv)(ConvRequest, const char *)); 91 | 92 | /***************************************************************** 93 | * Output a message to stderr 94 | *****************************************************************/ 95 | void message(const char *, ...) ATTR_PRINTFLIKE(1, 2); 96 | 97 | /***************************************************************** 98 | * Overwrite and free the passed string 99 | *****************************************************************/ 100 | void dispose(char *); 101 | 102 | #ifdef __cplusplus 103 | } 104 | #endif 105 | #endif 106 | -------------------------------------------------------------------------------- /config-workspace.h.cmake: -------------------------------------------------------------------------------- 1 | /* config-workspace.h. Generated by cmake from config-workspace.h.cmake */ 2 | 3 | /* Define if you have DPMS support */ 4 | #cmakedefine HAVE_DPMS 1 5 | 6 | /* Define if you have the DPMSCapable prototype in */ 7 | #cmakedefine HAVE_DPMSCAPABLE_PROTO 1 8 | 9 | /* Define if you have the DPMSInfo prototype in */ 10 | #cmakedefine HAVE_DPMSINFO_PROTO 1 11 | 12 | /* Define if you have gethostname */ 13 | #cmakedefine HAVE_GETHOSTNAME 1 14 | 15 | /* Define if you have the gethostname prototype */ 16 | #cmakedefine HAVE_GETHOSTNAME_PROTO 1 17 | 18 | /* Define if you have long long as datatype */ 19 | #cmakedefine HAVE_LONG_LONG 1 20 | 21 | /* Define to 1 if you have the `nice' function. */ 22 | #cmakedefine HAVE_NICE 1 23 | 24 | /* Define to 1 if you have the header file. */ 25 | #cmakedefine HAVE_SASL_H 1 26 | 27 | /* Define to 1 if you have the header file. */ 28 | #cmakedefine HAVE_SASL_SASL_H 1 29 | 30 | /* Define to 1 if you have the `setpriority' function. */ 31 | #cmakedefine HAVE_SETPRIORITY 1 32 | 33 | /* Define to 1 if you have the `sigaction' function. */ 34 | #cmakedefine HAVE_SIGACTION 1 35 | 36 | /* Define to 1 if you have the `sigset' function. */ 37 | #cmakedefine HAVE_SIGSET 1 38 | 39 | /* Define to 1 if you have statvfs */ 40 | #cmakedefine HAVE_STATVFS 1 41 | 42 | /* Define to 1 if you have the header file. */ 43 | #cmakedefine HAVE_STRING_H 1 44 | 45 | /* Define if you have the struct ucred */ 46 | #cmakedefine HAVE_STRUCT_UCRED 1 47 | 48 | /* Define to 1 if you have the header file. */ 49 | #cmakedefine HAVE_SYS_LOADAVG_H 1 50 | 51 | /* Define to 1 if you have the header file. */ 52 | #cmakedefine HAVE_SYS_MOUNT_H 1 53 | 54 | /* Define to 1 if you have the header file. */ 55 | #cmakedefine HAVE_SYS_PARAM_H 1 56 | 57 | /* Define to 1 if you have the header file. */ 58 | #cmakedefine HAVE_SYS_STATFS_H 1 59 | 60 | /* Define to 1 if you have the header file. */ 61 | #cmakedefine HAVE_SYS_STATVFS_H 1 62 | 63 | /* Define to 1 if you have statfs(). */ 64 | #cmakedefine HAVE_STATFS 1 65 | 66 | /* Define to 1 if you have the header file. */ 67 | #cmakedefine HAVE_SYS_SELECT_H 1 68 | 69 | /* Define to 1 if you have the header file. */ 70 | #cmakedefine HAVE_SYS_SOCKET_H 1 71 | 72 | /* Define to 1 if you have the header file. */ 73 | #cmakedefine HAVE_SYS_TIME_H 1 74 | 75 | /* Define to 1 if you have the header file. */ 76 | #cmakedefine HAVE_SYS_TYPES_H 1 77 | 78 | /* Define to 1 if you have the header file. */ 79 | #cmakedefine HAVE_SYS_VFS_H 1 80 | 81 | /* Define to 1 if you have the header file. */ 82 | #cmakedefine HAVE_SYS_WAIT_H 1 83 | 84 | /* Define to 1 if you have the header file. */ 85 | #cmakedefine HAVE_UNISTD_H 1 86 | 87 | /* Define to 1 if you have the header file. */ 88 | #cmakedefine HAVE_STDINT_H 1 89 | 90 | /* Define to 1 if you have the header file. */ 91 | #cmakedefine HAVE_MALLOC_H 1 92 | 93 | /* Define if you have unsetenv */ 94 | #cmakedefine HAVE_UNSETENV 1 95 | 96 | /* Define if you have the unsetenv prototype */ 97 | #cmakedefine HAVE_UNSETENV_PROTO 1 98 | 99 | /* Define if you have usleep */ 100 | #cmakedefine HAVE_USLEEP 1 101 | 102 | /* Define if you have the usleep prototype */ 103 | #cmakedefine HAVE_USLEEP_PROTO 1 104 | 105 | /* Define to 1 if you have the `vsnprintf' function. */ 106 | #cmakedefine HAVE_VSNPRINTF 1 107 | 108 | /* Define to 1 if you have the Wayland libraries. */ 109 | #cmakedefine WAYLAND_FOUND 1 110 | 111 | /* KDE's default home directory */ 112 | #cmakedefine KDE_DEFAULT_HOME "${KDE_DEFAULT_HOME}" 113 | 114 | /* KDE's binaries directory */ 115 | #define KDE_BINDIR "${BIN_INSTALL_DIR}" 116 | 117 | /* KDE's configuration directory */ 118 | #define KDE_CONFDIR "${CONFIG_INSTALL_DIR}" 119 | 120 | /* KDE's static data directory */ 121 | #define KDE_DATADIR "${DATA_INSTALL_DIR}" 122 | 123 | /* Define to 1 if you can safely include both and . */ 124 | #cmakedefine TIME_WITH_SYS_TIME 1 125 | 126 | /* X binaries directory */ 127 | #cmakedefine XBINDIR "${XBINDIR}" 128 | 129 | /* X libraries directory */ 130 | #cmakedefine XLIBDIR "${XLIBDIR}" 131 | 132 | /* Number of bits in a file offset, on hosts where this is settable. */ 133 | #define _FILE_OFFSET_BITS 64 134 | 135 | /* 136 | * On HP-UX, the declaration of vsnprintf() is needed every time ! 137 | */ 138 | 139 | /* type to use in place of socklen_t if not defined */ 140 | #define kde_socklen_t socklen_t 141 | 142 | -------------------------------------------------------------------------------- /checkpass/checkpass_pam.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 1998 Caldera, Inc. 3 | * Copyright (C) 2003 Oswald Buddenhagen 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this program; if not, write to the Free 17 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | */ 19 | 20 | #include "checkpass.h" 21 | 22 | #ifdef HAVE_PAM 23 | 24 | #include 25 | #include 26 | #include 27 | #include 28 | 29 | #ifdef HAVE_PAM_PAM_APPL_H 30 | #include 31 | #else 32 | #include 33 | #endif 34 | 35 | struct pam_data { 36 | char *(*conv)(ConvRequest, const char *); 37 | int abort : 1; 38 | int classic : 1; 39 | }; 40 | 41 | #ifdef PAM_MESSAGE_CONST 42 | typedef const struct pam_message pam_message_type; 43 | typedef const void *pam_gi_type; 44 | #else 45 | typedef struct pam_message pam_message_type; 46 | typedef void *pam_gi_type; 47 | #endif 48 | 49 | static int PAM_conv(int num_msg, pam_message_type **msg, struct pam_response **resp, void *appdata_ptr) 50 | { 51 | int count; 52 | struct pam_response *repl; 53 | struct pam_data *pd = (struct pam_data *)appdata_ptr; 54 | 55 | if (!(repl = calloc(num_msg, sizeof(struct pam_response)))) { 56 | return PAM_CONV_ERR; 57 | } 58 | 59 | for (count = 0; count < num_msg; count++) { 60 | switch (msg[count]->msg_style) { 61 | case PAM_TEXT_INFO: 62 | pd->conv(ConvPutInfo, msg[count]->msg); 63 | break; 64 | case PAM_ERROR_MSG: 65 | pd->conv(ConvPutError, msg[count]->msg); 66 | break; 67 | default: 68 | switch (msg[count]->msg_style) { 69 | case PAM_PROMPT_ECHO_ON: 70 | repl[count].resp = pd->conv(ConvGetNormal, msg[count]->msg); 71 | break; 72 | case PAM_PROMPT_ECHO_OFF: 73 | repl[count].resp = pd->conv(ConvGetHidden, pd->classic ? 0 : msg[count]->msg); 74 | break; 75 | #ifdef PAM_BINARY_PROMPT 76 | case PAM_BINARY_PROMPT: 77 | repl[count].resp = pd->conv(ConvGetBinary, msg[count]->msg); 78 | break; 79 | #endif 80 | default: 81 | /* Must be an error of some sort... */ 82 | goto conv_err; 83 | } 84 | if (!repl[count].resp) { 85 | pd->abort = 1; 86 | goto conv_err; 87 | } 88 | repl[count].resp_retcode = PAM_SUCCESS; 89 | break; 90 | } 91 | } 92 | *resp = repl; 93 | return PAM_SUCCESS; 94 | 95 | conv_err: 96 | for (; count >= 0; count--) { 97 | if (repl[count].resp) { 98 | switch (msg[count]->msg_style) { 99 | case PAM_PROMPT_ECHO_OFF: 100 | dispose(repl[count].resp); 101 | break; 102 | #ifdef PAM_BINARY_PROMPT 103 | case PAM_BINARY_PROMPT: /* handle differently? */ 104 | #endif 105 | case PAM_PROMPT_ECHO_ON: 106 | free(repl[count].resp); 107 | break; 108 | } 109 | } 110 | } 111 | free(repl); 112 | return PAM_CONV_ERR; 113 | } 114 | 115 | static struct pam_data PAM_data; 116 | 117 | static struct pam_conv PAM_conversation = { 118 | &PAM_conv, 119 | &PAM_data, 120 | }; 121 | 122 | #ifdef PAM_FAIL_DELAY 123 | static void fail_delay(int retval ATTR_UNUSED, unsigned usec_delay ATTR_UNUSED, void *appdata_ptr ATTR_UNUSED) 124 | { 125 | } 126 | #endif 127 | 128 | AuthReturn Authenticate(const char *method, const char *user, char *(*conv)(ConvRequest, const char *)) 129 | { 130 | const char *tty; 131 | pam_handle_t *pamh; 132 | pam_gi_type pam_item; 133 | const char *pam_service; 134 | char pservb[64]; 135 | int pam_error; 136 | 137 | openlog("kcheckpass", LOG_PID, LOG_AUTH); 138 | 139 | PAM_data.conv = conv; 140 | if (strcmp(method, "classic")) { 141 | sprintf(pservb, "%.31s-%.31s", KSCREENSAVER_PAM_SERVICE, method); 142 | pam_service = pservb; 143 | } else { 144 | /* PAM_data.classic = 1; */ 145 | pam_service = KSCREENSAVER_PAM_SERVICE; 146 | } 147 | pam_error = pam_start(pam_service, user, &PAM_conversation, &pamh); 148 | if (pam_error != PAM_SUCCESS) { 149 | return AuthError; 150 | } 151 | 152 | tty = ttyname(0); 153 | if (!tty) { 154 | tty = getenv("DISPLAY"); 155 | } 156 | 157 | pam_error = pam_set_item(pamh, PAM_TTY, tty); 158 | if (pam_error != PAM_SUCCESS) { 159 | pam_end(pamh, pam_error); 160 | return AuthError; 161 | } 162 | 163 | #ifdef PAM_FAIL_DELAY 164 | pam_set_item(pamh, PAM_FAIL_DELAY, (void *)fail_delay); 165 | #endif 166 | 167 | pam_error = pam_authenticate(pamh, 0); 168 | if (pam_error != PAM_SUCCESS) { 169 | if (PAM_data.abort) { 170 | PAM_data.abort = 0; 171 | pam_end(pamh, pam_error); 172 | return AuthAbort; 173 | } 174 | pam_end(pamh, pam_error); 175 | switch (pam_error) { 176 | case PAM_USER_UNKNOWN: 177 | case PAM_AUTH_ERR: 178 | case PAM_MAXTRIES: /* should handle this better ... */ 179 | case PAM_AUTHINFO_UNAVAIL: /* returned for unknown users ... bogus */ 180 | return AuthBad; 181 | default: 182 | return AuthError; 183 | } 184 | } 185 | 186 | /* just in case some module is stupid enough to ignore a preset PAM_USER */ 187 | pam_error = pam_get_item(pamh, PAM_USER, &pam_item); 188 | if (pam_error != PAM_SUCCESS) { 189 | pam_end(pamh, pam_error); 190 | return AuthError; 191 | } 192 | if (strcmp((const char *)pam_item, user)) { 193 | pam_end(pamh, PAM_SUCCESS); /* maybe use PAM_AUTH_ERR? */ 194 | return AuthBad; 195 | } 196 | 197 | pam_error = pam_setcred(pamh, PAM_REFRESH_CRED); 198 | /* ignore errors on refresh credentials. If this did not work we use the old ones. */ 199 | 200 | pam_end(pamh, PAM_SUCCESS); 201 | return AuthOk; 202 | } 203 | 204 | #endif 205 | -------------------------------------------------------------------------------- /screenlocker/fixx11h.h: -------------------------------------------------------------------------------- 1 | /* 2 | SPDX-FileCopyrightText: 2003 Lubos Lunak 3 | 4 | SPDX-License-Identifier: MIT 5 | */ 6 | 7 | //#ifdef don't do this, this file is supposed to be included 8 | //#define multiple times 9 | 10 | #include 11 | 12 | /* Usage: 13 | 14 | If you get compile errors caused by X11 includes (the line 15 | where first error appears contains word like None, Unsorted, 16 | Below, etc.), put #include in the .cpp file 17 | (not .h file!) between the place where X11 headers are 18 | included and the place where the file with compile 19 | error is included (or the place where the compile error 20 | in the .cpp file occurs). 21 | 22 | This file remaps X11 #defines to const variables or 23 | inline functions. The side effect may be that these 24 | symbols may now refer to different variables 25 | (e.g. if X11 #defined NoButton, after this file 26 | is included NoButton would no longer be X11's 27 | NoButton, but Qt::NoButton instead). At this time, 28 | there's no conflict known that could cause problems. 29 | 30 | The original X11 symbols are still accessible 31 | (e.g. for None) as X::None, XNone, and also still 32 | None, unless name lookup finds different None 33 | first (in the current class, etc.) 34 | 35 | Use 'Unsorted', 'Bool' and 'index' as templates. 36 | 37 | */ 38 | 39 | namespace X 40 | { 41 | // template ---> 42 | // Affects: Should be without side effects. 43 | #ifdef Unsorted 44 | #ifndef FIXX11H_Unsorted 45 | #define FIXX11H_Unsorted 46 | const int XUnsorted = Unsorted; 47 | #undef Unsorted 48 | const int Unsorted = XUnsorted; 49 | #endif 50 | #undef Unsorted 51 | #endif 52 | // template <--- 53 | 54 | // Affects: Should be without side effects. 55 | #ifdef None 56 | #ifndef FIXX11H_None 57 | #define FIXX11H_None 58 | const XID XNone = None; 59 | #undef None 60 | const XID None = XNone; 61 | #endif 62 | #undef None 63 | #endif 64 | 65 | // template ---> 66 | // Affects: Should be without side effects. 67 | #ifdef Bool 68 | #ifndef FIXX11H_Bool 69 | #define FIXX11H_Bool 70 | #ifdef _XTYPEDEF_BOOL /* Xdefs.h has typedef'ed Bool already */ 71 | #undef Bool 72 | #else 73 | typedef Bool XBool; 74 | #undef Bool 75 | typedef XBool Bool; 76 | #endif 77 | #endif 78 | #undef Bool 79 | #define _XTYPEDEF_BOOL 80 | #endif 81 | // template <--- 82 | 83 | // Affects: Should be without side effects. 84 | #ifdef KeyPress 85 | #ifndef FIXX11H_KeyPress 86 | #define FIXX11H_KeyPress 87 | const int XKeyPress = KeyPress; 88 | #undef KeyPress 89 | const int KeyPress = XKeyPress; 90 | #endif 91 | #undef KeyPress 92 | #endif 93 | 94 | // Affects: Should be without side effects. 95 | #ifdef KeyRelease 96 | #ifndef FIXX11H_KeyRelease 97 | #define FIXX11H_KeyRelease 98 | const int XKeyRelease = KeyRelease; 99 | #undef KeyRelease 100 | const int KeyRelease = XKeyRelease; 101 | #endif 102 | #undef KeyRelease 103 | #endif 104 | 105 | // Affects: Should be without side effects. 106 | #ifdef Above 107 | #ifndef FIXX11H_Above 108 | #define FIXX11H_Above 109 | const int XAbove = Above; 110 | #undef Above 111 | const int Above = XAbove; 112 | #endif 113 | #undef Above 114 | #endif 115 | 116 | // Affects: Should be without side effects. 117 | #ifdef Below 118 | #ifndef FIXX11H_Below 119 | #define FIXX11H_Below 120 | const int XBelow = Below; 121 | #undef Below 122 | const int Below = XBelow; 123 | #endif 124 | #undef Below 125 | #endif 126 | 127 | // Affects: Should be without side effects. 128 | #ifdef FocusIn 129 | #ifndef FIXX11H_FocusIn 130 | #define FIXX11H_FocusIn 131 | const int XFocusIn = FocusIn; 132 | #undef FocusIn 133 | const int FocusIn = XFocusIn; 134 | #endif 135 | #undef FocusIn 136 | #endif 137 | 138 | // Affects: Should be without side effects. 139 | #ifdef FocusOut 140 | #ifndef FIXX11H_FocusOut 141 | #define FIXX11H_FocusOut 142 | const int XFocusOut = FocusOut; 143 | #undef FocusOut 144 | const int FocusOut = XFocusOut; 145 | #endif 146 | #undef FocusOut 147 | #endif 148 | 149 | // Affects: Should be without side effects. 150 | #ifdef Always 151 | #ifndef FIXX11H_Always 152 | #define FIXX11H_Always 153 | const int XAlways = Always; 154 | #undef Always 155 | const int Always = XAlways; 156 | #endif 157 | #undef Always 158 | #endif 159 | 160 | // Affects: Should be without side effects. 161 | #ifdef Expose 162 | #ifndef FIXX11H_Expose 163 | #define FIXX11H_Expose 164 | const int XExpose = Expose; 165 | #undef Expose 166 | const int Expose = XExpose; 167 | #endif 168 | #undef Expose 169 | #endif 170 | 171 | // Affects: Should be without side effects. 172 | #ifdef Success 173 | #ifndef FIXX11H_Success 174 | #define FIXX11H_Success 175 | const int XSuccess = Success; 176 | #undef Success 177 | const int Success = XSuccess; 178 | #endif 179 | #undef Success 180 | #endif 181 | 182 | // Affects: Should be without side effects. 183 | #ifdef GrayScale 184 | #ifndef FIXX11H_GrayScale 185 | #define FIXX11H_GrayScale 186 | const int XGrayScale = GrayScale; 187 | #undef GrayScale 188 | const int GrayScale = XGrayScale; 189 | #endif 190 | #undef GrayScale 191 | #endif 192 | 193 | // Affects: Should be without side effects. 194 | #ifdef Status 195 | #ifndef FIXX11H_Status 196 | #define FIXX11H_Status 197 | typedef Status XStatus; 198 | #undef Status 199 | typedef XStatus Status; 200 | #endif 201 | #undef Status 202 | #endif 203 | 204 | // template ---> 205 | // Affects: Should be without side effects. 206 | #ifdef CursorShape 207 | #ifndef FIXX11H_CursorShape 208 | #define FIXX11H_CursorShape 209 | const int XCursorShape = CursorShape; 210 | #undef CursorShape 211 | const int CursorShape = XCursorShape; 212 | #endif 213 | #undef CursorShape 214 | #endif 215 | // template <--- 216 | 217 | // template ---> 218 | // Affects: Should be without side effects. 219 | #ifdef FontChange 220 | #ifndef FIXX11H_FontChange 221 | #define FIXX11H_FontChange 222 | const int XFontChange = FontChange; 223 | #undef FontChange 224 | const int FontChange = XFontChange; 225 | #endif 226 | #undef FontChange 227 | #endif 228 | // template <--- 229 | 230 | // Affects: Should be without side effects. 231 | #ifdef NormalState 232 | #ifndef FIXX11H_NormalState 233 | #define FIXX11H_NormalState 234 | const int XNormalState = NormalState; 235 | #undef NormalState 236 | const int NormalState = XNormalState; 237 | #endif 238 | #undef NormalState 239 | #endif 240 | 241 | // template ---> 242 | // Affects: Should be without side effects. 243 | #ifdef index 244 | #ifndef FIXX11H_index 245 | #define FIXX11H_index 246 | inline const char *Xindex(const char *s, int c) 247 | { 248 | return index(s, c); 249 | } 250 | #undef index 251 | inline const char *index(const char *s, int c) 252 | { 253 | return Xindex(s, c); 254 | } 255 | #endif 256 | #undef index 257 | #endif 258 | // template <--- 259 | 260 | #ifdef rindex 261 | // Affects: Should be without side effects. 262 | #ifndef FIXX11H_rindex 263 | #define FIXX11H_rindex 264 | inline const char *Xrindex(const char *s, int c) 265 | { 266 | return rindex(s, c); 267 | } 268 | #undef rindex 269 | inline const char *rindex(const char *s, int c) 270 | { 271 | return Xrindex(s, c); 272 | } 273 | #endif 274 | #undef rindex 275 | #endif 276 | } 277 | 278 | using namespace X; 279 | -------------------------------------------------------------------------------- /screenlocker/qml/MprisItem.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Reion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Layouts 1.12 22 | import QtQuick.Controls 2.12 23 | import QtGraphicalEffects 1.0 24 | import FishUI 1.0 as FishUI 25 | import Cutefish.Mpris 1.0 26 | 27 | Item { 28 | id: control 29 | 30 | property bool available: mprisManager.availableServices.length > 0 31 | property bool isPlaying: currentService && mprisManager.playbackStatus === Mpris.Playing 32 | property alias currentService: mprisManager.currentService 33 | property var artUrlTag: Mpris.metadataToString(Mpris.ArtUrl) 34 | property var titleTag: Mpris.metadataToString(Mpris.Title) 35 | property var artistTag: Mpris.metadataToString(Mpris.Artist) 36 | 37 | MprisManager { 38 | id: mprisManager 39 | 40 | onCurrentServiceChanged: { 41 | control.updateInfo() 42 | } 43 | 44 | onMetadataChanged: { 45 | control.updateInfo() 46 | } 47 | } 48 | 49 | Component.onCompleted: { control.updateInfo() } 50 | 51 | function updateInfo() { 52 | var titleAvailable = (titleTag in mprisManager.metadata) ? mprisManager.metadata[titleTag].toString() !== "" : false 53 | var artistAvailable = (artistTag in mprisManager.metadata) ? mprisManager.metadata[artistTag].toString() !== "" : false 54 | 55 | control.visible = titleAvailable || artistAvailable 56 | _songLabel.text = titleAvailable ? mprisManager.metadata[titleTag].toString() : "" 57 | _artistLabel.text = artistAvailable ? mprisManager.metadata[artistTag].toString() : "" 58 | artImage.source = (artUrlTag in mprisManager.metadata) ? mprisManager.metadata[artUrlTag].toString() : "" 59 | } 60 | 61 | Rectangle { 62 | anchors.fill: parent 63 | radius: FishUI.Theme.bigRadius + 2 64 | color: FishUI.Theme.darkMode ? "#424242" : "white" 65 | opacity: 0.5 66 | } 67 | 68 | RowLayout { 69 | id: _mainLayout 70 | anchors.fill: parent 71 | anchors.margins: FishUI.Units.largeSpacing 72 | spacing: FishUI.Units.largeSpacing 73 | 74 | Image { 75 | id: defaultImage 76 | width: _mainLayout.height 77 | height: width 78 | source: "qrc:/images/media-cover.svg" 79 | sourceSize: Qt.size(width, height) 80 | visible: !artImage.visible 81 | 82 | layer.enabled: true 83 | layer.effect: OpacityMask { 84 | maskSource: Item { 85 | width: defaultImage.width 86 | height: defaultImage.height 87 | 88 | Rectangle { 89 | anchors.fill: parent 90 | radius: FishUI.Theme.smallRadius 91 | } 92 | } 93 | } 94 | } 95 | 96 | Image { 97 | id: artImage 98 | Layout.preferredHeight: _mainLayout.height 99 | Layout.preferredWidth: _mainLayout.height 100 | visible: status === Image.Ready 101 | // sourceSize: Qt.size(width, height) 102 | fillMode: Image.PreserveAspectFit 103 | 104 | layer.enabled: true 105 | layer.effect: OpacityMask { 106 | maskSource: Item { 107 | width: artImage.width 108 | height: artImage.height 109 | 110 | Rectangle { 111 | anchors.fill: parent 112 | radius: FishUI.Theme.smallRadius 113 | } 114 | } 115 | } 116 | } 117 | 118 | Item { 119 | Layout.fillHeight: true 120 | Layout.fillWidth: true 121 | 122 | ColumnLayout { 123 | anchors.fill: parent 124 | 125 | Item { 126 | Layout.fillHeight: true 127 | } 128 | 129 | Label { 130 | id: _songLabel 131 | Layout.fillWidth: true 132 | visible: _songLabel.text !== "" 133 | elide: Text.ElideRight 134 | } 135 | 136 | Label { 137 | id: _artistLabel 138 | Layout.fillWidth: true 139 | visible: _artistLabel.text !== "" 140 | elide: Text.ElideRight 141 | } 142 | 143 | Item { 144 | Layout.fillHeight: true 145 | } 146 | } 147 | } 148 | 149 | Item { 150 | id: _buttons 151 | Layout.fillHeight: true 152 | Layout.preferredWidth: _buttonsLayout.implicitWidth 153 | 154 | RowLayout { 155 | id: _buttonsLayout 156 | anchors.fill: parent 157 | spacing: FishUI.Units.smallSpacing 158 | 159 | IconButton { 160 | width: 30 161 | height: 30 162 | source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-skip-backward-symbolic.svg" 163 | onLeftButtonClicked: if (mprisManager.canGoPrevious) mprisManager.previous() 164 | visible: mprisManager.canGoPrevious 165 | Layout.alignment: Qt.AlignRight 166 | } 167 | 168 | IconButton { 169 | width: 30 170 | height: 30 171 | source: control.isPlaying ? "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-playback-pause-symbolic.svg" 172 | : "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-playback-start-symbolic.svg" 173 | Layout.alignment: Qt.AlignRight 174 | visible: mprisManager.canPause || mprisManager.canPlay 175 | onLeftButtonClicked: 176 | if ((control.isPlaying && mprisManager.canPause) || (!control.isPlaying && mprisManager.canPlay)) { 177 | mprisManager.playPause() 178 | } 179 | } 180 | 181 | IconButton { 182 | width: 30 183 | height: 30 184 | source: "qrc:/images/" + (FishUI.Theme.darkMode ? "dark" : "light") + "/media-skip-forward-symbolic.svg" 185 | Layout.alignment: Qt.AlignRight 186 | visible: mprisManager.canGoNext 187 | onLeftButtonClicked: if (mprisManager.canGoNext) mprisManager.next() 188 | } 189 | } 190 | } 191 | } 192 | } 193 | -------------------------------------------------------------------------------- /screenlocker/authenticator.cpp: -------------------------------------------------------------------------------- 1 | /******************************************************************** 2 | KSld - the KDE Screenlocker Daemon 3 | This file is part of the KDE project. 4 | 5 | Copyright (C) 1999 Martin R. Jones 6 | Copyright (C) 2002 Luboš Luňák 7 | Copyright (C) 2003 Oswald Buddenhagen 8 | Copyright (C) 2014 Martin Gräßlin 9 | 10 | This program is free software; you can redistribute it and/or modify 11 | it under the terms of the GNU General Public License as published by 12 | the Free Software Foundation; either version 2 of the License, or 13 | (at your option) any later version. 14 | 15 | This program is distributed in the hope that it will be useful, 16 | but WITHOUT ANY WARRANTY; without even the implied warranty of 17 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 18 | GNU General Public License for more details. 19 | 20 | You should have received a copy of the GNU General Public License 21 | along with this program. If not, see . 22 | *********************************************************************/ 23 | #include "authenticator.h" 24 | 25 | #include "kcheckpass-enums.h" 26 | 27 | // Qt 28 | #include 29 | #include 30 | #include 31 | #include 32 | 33 | // system 34 | #include 35 | #include 36 | #include 37 | #include 38 | #include 39 | #include 40 | 41 | Authenticator::Authenticator(AuthenticationMode mode, QObject *parent) 42 | : QObject(parent) 43 | , m_graceLockTimer(new QTimer(this)) 44 | , m_checkPass(nullptr) 45 | { 46 | m_graceLockTimer->setSingleShot(true); 47 | m_graceLockTimer->setInterval(1500); 48 | connect(m_graceLockTimer, &QTimer::timeout, this, &Authenticator::graceLockedChanged); 49 | 50 | if (mode == AuthenticationMode::Delayed) { 51 | m_checkPass = new KCheckPass(AuthenticationMode::Delayed, this); 52 | setupCheckPass(); 53 | } 54 | } 55 | 56 | Authenticator::~Authenticator() = default; 57 | 58 | void Authenticator::tryUnlock(const QString &password) 59 | { 60 | if (isGraceLocked()) { 61 | Q_EMIT failed(); 62 | return; 63 | } 64 | m_graceLockTimer->start(); 65 | Q_EMIT graceLockedChanged(); 66 | 67 | if (!m_checkPass) { 68 | m_checkPass = new KCheckPass(AuthenticationMode::Direct, this); 69 | m_checkPass->setPassword(password); 70 | setupCheckPass(); 71 | } else { 72 | if (!m_checkPass->isReady()) { 73 | Q_EMIT failed(); 74 | return; 75 | } 76 | m_checkPass->setPassword(password); 77 | m_checkPass->startAuth(); 78 | } 79 | } 80 | 81 | void Authenticator::setupCheckPass() 82 | { 83 | connect(m_checkPass, &KCheckPass::succeeded, this, &Authenticator::succeeded); 84 | connect(m_checkPass, &KCheckPass::failed, this, &Authenticator::failed); 85 | connect(m_checkPass, &KCheckPass::message, this, &Authenticator::message); 86 | connect(m_checkPass, &KCheckPass::error, this, &Authenticator::error); 87 | connect(m_checkPass, &KCheckPass::destroyed, this, [this] { 88 | m_checkPass = nullptr; 89 | }); 90 | m_checkPass->start(); 91 | } 92 | 93 | bool Authenticator::isGraceLocked() const 94 | { 95 | return m_graceLockTimer->isActive(); 96 | } 97 | 98 | KCheckPass::KCheckPass(AuthenticationMode mode, QObject *parent) 99 | : QObject(parent) 100 | , m_notifier(nullptr) 101 | , m_pid(0) 102 | , m_fd(0) 103 | , m_mode(mode) 104 | { 105 | if (mode == AuthenticationMode::Direct) { 106 | connect(this, &KCheckPass::succeeded, this, &QObject::deleteLater); 107 | connect(this, &KCheckPass::failed, this, &QObject::deleteLater); 108 | } 109 | } 110 | 111 | KCheckPass::~KCheckPass() 112 | { 113 | reapVerify(); 114 | } 115 | 116 | void KCheckPass::start() 117 | { 118 | int sfd[2]; 119 | char fdbuf[16]; 120 | 121 | if (m_notifier) { 122 | return; 123 | } 124 | if (::socketpair(AF_LOCAL, SOCK_STREAM, 0, sfd)) { 125 | cantCheck(); 126 | return; 127 | } 128 | if ((m_pid = ::fork()) < 0) { 129 | ::close(sfd[0]); 130 | ::close(sfd[1]); 131 | cantCheck(); 132 | return; 133 | } 134 | if (!m_pid) { 135 | ::close(sfd[0]); 136 | sprintf(fdbuf, "%d", sfd[1]); 137 | execlp(QFile::encodeName(QStringLiteral("ccheckpass")).data(), "kcheckpass", "-m", "classic", "-S", fdbuf, (char *)nullptr); 138 | _exit(20); 139 | } 140 | ::close(sfd[1]); 141 | m_fd = sfd[0]; 142 | m_notifier = new QSocketNotifier(m_fd, QSocketNotifier::Read, this); 143 | connect(m_notifier, &QSocketNotifier::activated, this, &KCheckPass::handleVerify); 144 | } 145 | 146 | ////// kckeckpass interface code 147 | 148 | int KCheckPass::Reader(void *buf, int count) 149 | { 150 | int ret, rlen; 151 | 152 | for (rlen = 0; rlen < count;) { 153 | dord: 154 | ret = ::read(m_fd, (void *)((char *)buf + rlen), count - rlen); 155 | if (ret < 0) { 156 | if (errno == EINTR) { 157 | goto dord; 158 | } 159 | if (errno == EAGAIN) { 160 | break; 161 | } 162 | return -1; 163 | } 164 | if (!ret) { 165 | break; 166 | } 167 | rlen += ret; 168 | } 169 | return rlen; 170 | } 171 | 172 | bool KCheckPass::GRead(void *buf, int count) 173 | { 174 | return Reader(buf, count) == count; 175 | } 176 | 177 | bool KCheckPass::GWrite(const void *buf, int count) 178 | { 179 | return ::write(m_fd, buf, count) == count; 180 | } 181 | 182 | bool KCheckPass::GSendInt(int val) 183 | { 184 | return GWrite(&val, sizeof(val)); 185 | } 186 | 187 | bool KCheckPass::GSendStr(const char *buf) 188 | { 189 | int len = buf ? ::strlen(buf) + 1 : 0; 190 | return GWrite(&len, sizeof(len)) && GWrite(buf, len); 191 | } 192 | 193 | bool KCheckPass::GSendArr(int len, const char *buf) 194 | { 195 | return GWrite(&len, sizeof(len)) && GWrite(buf, len); 196 | } 197 | 198 | bool KCheckPass::GRecvInt(int *val) 199 | { 200 | return GRead(val, sizeof(*val)); 201 | } 202 | 203 | bool KCheckPass::GRecvArr(char **ret) 204 | { 205 | int len; 206 | char *buf; 207 | 208 | if (!GRecvInt(&len)) { 209 | return false; 210 | } 211 | if (!len) { 212 | *ret = nullptr; 213 | return true; 214 | } 215 | if (!(buf = (char *)::malloc(len))) { 216 | return false; 217 | } 218 | *ret = buf; 219 | if (GRead(buf, len)) { 220 | return true; 221 | } else { 222 | ::free(buf); 223 | *ret = nullptr; 224 | return false; 225 | } 226 | } 227 | 228 | void KCheckPass::handleVerify() 229 | { 230 | m_ready = false; 231 | int ret; 232 | char *arr; 233 | 234 | if (GRecvInt(&ret)) { 235 | switch (ret) { 236 | case ConvGetBinary: 237 | if (!GRecvArr(&arr)) { 238 | break; 239 | } 240 | // FIXME: not supported 241 | cantCheck(); 242 | if (arr) { 243 | ::free(arr); 244 | } 245 | return; 246 | case ConvGetNormal: 247 | case ConvGetHidden: { 248 | if (!GRecvArr(&arr)) { 249 | break; 250 | } 251 | 252 | if (m_password.isNull()) { 253 | GSendStr(nullptr); 254 | } else { 255 | QByteArray utf8pass = m_password.toUtf8(); 256 | GSendStr(utf8pass.constData()); 257 | GSendInt(IsPassword); 258 | } 259 | 260 | m_password.clear(); 261 | 262 | if (arr) { 263 | ::free(arr); 264 | } 265 | return; 266 | } 267 | case ConvPutInfo: 268 | if (!GRecvArr(&arr)) { 269 | break; 270 | } 271 | Q_EMIT message(QString::fromLocal8Bit(arr)); 272 | ::free(arr); 273 | return; 274 | case ConvPutError: 275 | if (!GRecvArr(&arr)) { 276 | break; 277 | } 278 | Q_EMIT error(QString::fromLocal8Bit(arr)); 279 | ::free(arr); 280 | return; 281 | case ConvPutAuthSucceeded: 282 | Q_EMIT succeeded(); 283 | return; 284 | case ConvPutAuthFailed: 285 | Q_EMIT failed(); 286 | return; 287 | case ConvPutAuthError: 288 | case ConvPutAuthAbort: 289 | cantCheck(); 290 | return; 291 | case ConvPutReadyForAuthentication: 292 | m_ready = true; 293 | if (m_mode == AuthenticationMode::Direct) { 294 | ::kill(m_pid, SIGUSR1); 295 | } 296 | return; 297 | } 298 | } 299 | if (m_mode == AuthenticationMode::Direct) { 300 | reapVerify(); 301 | } else { 302 | // we broke, let's restart the greeter 303 | // error code 1 will result in a restart through the system 304 | qApp->exit(1); 305 | } 306 | } 307 | 308 | void KCheckPass::reapVerify() 309 | { 310 | m_notifier->setEnabled(false); 311 | m_notifier->deleteLater(); 312 | m_notifier = nullptr; 313 | ::close(m_fd); 314 | int status; 315 | ::kill(m_pid, SIGUSR2); 316 | while (::waitpid(m_pid, &status, 0) < 0) { 317 | if (errno != EINTR) { // This should not happen ... 318 | cantCheck(); 319 | return; 320 | } 321 | } 322 | } 323 | 324 | void KCheckPass::cantCheck() 325 | { 326 | // TODO: better signal? 327 | Q_EMIT failed(); 328 | } 329 | 330 | void KCheckPass::startAuth() 331 | { 332 | ::kill(m_pid, SIGUSR1); 333 | } 334 | -------------------------------------------------------------------------------- /screenlocker/qml/LockScreen.qml: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Rion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | import QtQuick 2.12 21 | import QtQuick.Window 2.12 22 | import QtQuick.Controls 2.12 23 | import QtQuick.Layouts 1.12 24 | import QtGraphicalEffects 1.0 25 | 26 | import Cutefish.Accounts 1.0 as Accounts 27 | import Cutefish.System 1.0 as System 28 | import FishUI 1.0 as FishUI 29 | 30 | Item { 31 | id: root 32 | 33 | property string notification 34 | 35 | LayoutMirroring.enabled: Qt.locale().textDirection === Qt.RightToLeft 36 | LayoutMirroring.childrenInherit: true 37 | 38 | System.Wallpaper { 39 | id: wallpaper 40 | } 41 | 42 | Image { 43 | id: wallpaperImage 44 | anchors.fill: parent 45 | source: "file://" + wallpaper.path 46 | sourceSize: Qt.size(width * Screen.devicePixelRatio, 47 | height * Screen.devicePixelRatio) 48 | fillMode: Image.PreserveAspectCrop 49 | asynchronous: false 50 | clip: true 51 | cache: false 52 | smooth: true 53 | } 54 | 55 | FastBlur { 56 | id: wallpaperBlur 57 | anchors.fill: parent 58 | radius: 0 59 | source: wallpaperImage 60 | cached: true 61 | visible: true 62 | } 63 | 64 | NumberAnimation { 65 | id: blurAni 66 | target: wallpaperBlur 67 | property: "radius" 68 | duration: 300 69 | from: 10 70 | to: 64 71 | } 72 | 73 | Accounts.UserAccount { 74 | id: currentUser 75 | } 76 | 77 | Timer { 78 | repeat: true 79 | running: true 80 | interval: 1000 81 | 82 | onTriggered: { 83 | timeLabel.updateInfo() 84 | dateLabel.updateInfo() 85 | } 86 | } 87 | 88 | Component.onCompleted: { 89 | timeLabel.updateInfo() 90 | dateLabel.updateInfo() 91 | 92 | blurAni.start() 93 | } 94 | 95 | Item { 96 | id: _topItem 97 | anchors.left: parent.left 98 | anchors.right: parent.right 99 | anchors.top: parent.top 100 | anchors.bottom: _mainItem.top 101 | anchors.bottomMargin: root.height * 0.1 102 | 103 | // Image { 104 | // id: icon 105 | // anchors.horizontalCenter: parent.horizontalCenter 106 | // anchors.verticalCenter: parent.verticalCenter 107 | // Layout.alignment: Qt.AlignHCenter 108 | // width: 32 109 | // height: 32 110 | // sourceSize: Qt.size(width, height) 111 | // source: "qrc:/images/system-lock-screen-symbolic.svg" 112 | // } 113 | 114 | Label { 115 | id: timeLabel 116 | // anchors.top: icon.bottom 117 | // anchors.topMargin: FishUI.Units.largeSpacing 118 | anchors.horizontalCenter: parent.horizontalCenter 119 | anchors.verticalCenter: parent.verticalCenter 120 | Layout.alignment: Qt.AlignHCenter 121 | font.pointSize: 35 122 | color: "white" 123 | 124 | function updateInfo() { 125 | timeLabel.text = new Date().toLocaleString(Qt.locale(), "hh:mm") 126 | } 127 | } 128 | 129 | Label { 130 | id: dateLabel 131 | anchors.top: timeLabel.bottom 132 | anchors.topMargin: FishUI.Units.largeSpacing 133 | anchors.horizontalCenter: parent.horizontalCenter 134 | font.pointSize: 19 135 | color: "white" 136 | 137 | function updateInfo() { 138 | dateLabel.text = new Date().toLocaleDateString(Qt.locale(), Locale.LongFormat) 139 | } 140 | } 141 | 142 | DropShadow { 143 | anchors.fill: timeLabel 144 | source: timeLabel 145 | z: -1 146 | horizontalOffset: 1 147 | verticalOffset: 1 148 | radius: 10 149 | samples: radius * 4 150 | spread: 0.35 151 | color: Qt.rgba(0, 0, 0, 0.8) 152 | opacity: 0.1 153 | visible: true 154 | } 155 | 156 | DropShadow { 157 | anchors.fill: dateLabel 158 | source: dateLabel 159 | z: -1 160 | horizontalOffset: 1 161 | verticalOffset: 1 162 | radius: 10 163 | samples: radius * 4 164 | spread: 0.35 165 | color: Qt.rgba(0, 0, 0, 0.8) 166 | opacity: 0.1 167 | visible: true 168 | } 169 | } 170 | 171 | Item { 172 | id: _mainItem 173 | anchors.centerIn: parent 174 | width: 280 + FishUI.Units.largeSpacing * 3 175 | height: _mainLayout.implicitHeight + FishUI.Units.largeSpacing * 4 176 | 177 | Layout.alignment: Qt.AlignHCenter 178 | 179 | Rectangle { 180 | anchors.fill: parent 181 | radius: FishUI.Theme.bigRadius + 2 182 | color: FishUI.Theme.darkMode ? "#424242" : "white" 183 | opacity: 0.5 184 | } 185 | 186 | ColumnLayout { 187 | id: _mainLayout 188 | anchors.fill: parent 189 | anchors.margins: FishUI.Units.largeSpacing * 1.5 190 | spacing: FishUI.Units.smallSpacing * 1.5 191 | 192 | Image { 193 | id: userIcon 194 | 195 | property int iconSize: 60 196 | 197 | Layout.preferredHeight: iconSize 198 | Layout.preferredWidth: iconSize 199 | sourceSize: String(source) === "image://icontheme/default-user" ? Qt.size(iconSize, iconSize) : undefined 200 | source: currentUser.iconFileName ? "file:///" + currentUser.iconFileName : "image://icontheme/default-user" 201 | Layout.alignment: Qt.AlignHCenter 202 | 203 | layer.enabled: true 204 | layer.effect: OpacityMask { 205 | maskSource: Item { 206 | width: userIcon.width 207 | height: userIcon.height 208 | 209 | Rectangle { 210 | anchors.fill: parent 211 | radius: parent.height / 2 212 | } 213 | } 214 | } 215 | } 216 | 217 | Label { 218 | Layout.alignment: Qt.AlignHCenter 219 | text: currentUser.userName 220 | } 221 | 222 | Item { 223 | height: 1 224 | } 225 | 226 | TextField { 227 | id: password 228 | Layout.alignment: Qt.AlignHCenter 229 | Layout.preferredHeight: 36 230 | Layout.fillWidth: true 231 | placeholderText: qsTr("Password") 232 | leftPadding: FishUI.Units.largeSpacing 233 | rightPadding: 36 + FishUI.Units.largeSpacing //FishUI.Units.largeSpacing 234 | enabled: !authenticator.graceLocked 235 | focus: true 236 | 237 | echoMode: TextInput.Password 238 | 239 | background: Rectangle { 240 | color: FishUI.Theme.darkMode ? "#B6B6B6" : "white" 241 | // radius: FishUI.Theme.bigRadius 242 | opacity: 0.5 243 | } 244 | 245 | Keys.onEnterPressed: root.tryUnlock() 246 | Keys.onReturnPressed: root.tryUnlock() 247 | Keys.onEscapePressed: password.text = "" 248 | 249 | LoginButton { 250 | anchors.right: password.right 251 | anchors.top: password.top 252 | anchors.bottom: password.bottom 253 | source: "qrc:/images/screensaver-unlock-symbolic.svg" 254 | iconMargins: 10 255 | Layout.alignment: Qt.AlignHCenter 256 | enabled: !authenticator.graceLocked 257 | onClicked: root.tryUnlock() 258 | size: 36 259 | Layout.preferredHeight: 36 260 | Layout.preferredWidth: 36 261 | } 262 | 263 | layer.enabled: true 264 | layer.effect: OpacityMask { 265 | maskSource: Item { 266 | width: password.width 267 | height: password.height 268 | 269 | Rectangle { 270 | anchors.fill: parent 271 | radius: FishUI.Theme.mediumRadius 272 | } 273 | } 274 | } 275 | } 276 | 277 | Item { 278 | height: 1 279 | } 280 | } 281 | } 282 | 283 | Label { 284 | id: message 285 | anchors.top: _mainItem.bottom 286 | anchors.topMargin: FishUI.Units.largeSpacing 287 | anchors.horizontalCenter: parent.horizontalCenter 288 | font.bold: true 289 | color: "white" 290 | text: root.notification 291 | 292 | Behavior on opacity { 293 | NumberAnimation { 294 | duration: 250 295 | } 296 | } 297 | 298 | opacity: text == "" ? 0 : 1 299 | } 300 | 301 | DropShadow { 302 | anchors.fill: message 303 | source: message 304 | z: -1 305 | horizontalOffset: 1 306 | verticalOffset: 1 307 | radius: 10 308 | samples: radius * 4 309 | spread: 0.35 310 | color: Qt.rgba(0, 0, 0, 0.8) 311 | opacity: 0.3 312 | visible: true 313 | } 314 | 315 | Item { 316 | // anchors.top: message.bottom 317 | // anchors.topMargin: FishUI.Units.largeSpacing 318 | anchors.bottom: parent.bottom 319 | anchors.bottomMargin: root.height * 0.05 //FishUI.Units.largeSpacing 320 | anchors.horizontalCenter: parent.horizontalCenter 321 | 322 | width: 280 + FishUI.Units.largeSpacing * 3 323 | height: 70 324 | 325 | MprisItem { 326 | anchors.fill: parent 327 | } 328 | } 329 | 330 | function tryUnlock() { 331 | if (!password.text) { 332 | notificationResetTimer.start() 333 | root.notification = qsTr("Please enter your password") 334 | return 335 | } 336 | 337 | authenticator.tryUnlock(password.text) 338 | } 339 | 340 | Timer { 341 | id: notificationResetTimer 342 | interval: 3000 343 | onTriggered: root.notification = "" 344 | } 345 | 346 | Connections { 347 | target: authenticator 348 | 349 | function onFailed() { 350 | notificationResetTimer.start() 351 | root.notification = qsTr("Unlocking failed") 352 | } 353 | 354 | function onGraceLockedChanged() { 355 | if (!authenticator.graceLocked) { 356 | root.notification = "" 357 | password.selectAll() 358 | password.focus = true 359 | } 360 | } 361 | 362 | function onMessage(text) { 363 | notificationResetTimer.start() 364 | root.notification = text 365 | } 366 | 367 | function onError(text) { 368 | notificationResetTimer.start() 369 | root.notification = text 370 | } 371 | } 372 | } 373 | -------------------------------------------------------------------------------- /screenlocker/application.cpp: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (C) 2021 CutefishOS Team. 3 | * 4 | * Author: Reion Wong 5 | * 6 | * This program is free software: you can redistribute it and/or modify 7 | * it under the terms of the GNU General Public License as published by 8 | * the Free Software Foundation, either version 3 of the License, or 9 | * any later version. 10 | * 11 | * This program is distributed in the hope that it will be useful, 12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 14 | * GNU General Public License for more details. 15 | * 16 | * You should have received a copy of the GNU General Public License 17 | * along with this program. If not, see . 18 | */ 19 | 20 | #include "application.h" 21 | 22 | // Qt Core 23 | #include 24 | #include 25 | #include 26 | #include 27 | 28 | // Qt Quick 29 | #include 30 | #include 31 | #include 32 | #include 33 | 34 | // X11 35 | #include 36 | #include 37 | #include "fixx11h.h" 38 | 39 | // Xcb 40 | #include 41 | 42 | // this is usable to fake a "screensaver" installation for testing 43 | // *must* be "0" for every public commit! 44 | #define TEST_SCREENSAVER 0 45 | 46 | class FocusOutEventFilter : public QAbstractNativeEventFilter 47 | { 48 | public: 49 | bool nativeEventFilter(const QByteArray &eventType, void *message, long int *result) override { 50 | Q_UNUSED(result) 51 | if (qstrcmp(eventType, "xcb_generic_event_t") != 0) { 52 | return false; 53 | } 54 | 55 | xcb_generic_event_t *event = reinterpret_cast(message); 56 | if ((event->response_type & ~0x80) == XCB_FOCUS_OUT) { 57 | return true; 58 | } 59 | 60 | return false; 61 | } 62 | }; 63 | 64 | Application::Application(int &argc, char **argv) 65 | : QGuiApplication(argc, argv) 66 | , m_authenticator(new Authenticator(AuthenticationMode::Direct, this)) 67 | { 68 | // It's a queued connection to give the QML part time to eventually execute code connected to Authenticator::succeeded if any 69 | connect(m_authenticator, &Authenticator::succeeded, this, &Application::onSucceeded, Qt::QueuedConnection); 70 | 71 | installEventFilter(this); 72 | 73 | // Screens 74 | connect(this, &Application::screenAdded, this, &Application::onScreenAdded); 75 | connect(this, &Application::screenRemoved, this, &Application::desktopResized); 76 | 77 | if (QX11Info::isPlatformX11()) { 78 | installNativeEventFilter(new FocusOutEventFilter); 79 | } 80 | } 81 | 82 | Application::~Application() 83 | { 84 | // workaround QTBUG-55460 85 | // will be fixed when themes port to QQC2 86 | for (auto view : qAsConst(m_views)) { 87 | if (QQuickItem *focusItem = view->activeFocusItem()) { 88 | focusItem->setFocus(false); 89 | } 90 | } 91 | qDeleteAll(m_views); 92 | } 93 | 94 | void Application::initialViewSetup() 95 | { 96 | for (QScreen *screen : screens()) { 97 | connect(screen, &QScreen::geometryChanged, this, [this, screen](const QRect &geo) { 98 | screenGeometryChanged(screen, geo); 99 | }); 100 | } 101 | 102 | desktopResized(); 103 | } 104 | 105 | void Application::desktopResized() 106 | { 107 | const int nScreens = screens().count(); 108 | // remove useless views and savers 109 | while (m_views.count() > nScreens) { 110 | m_views.takeLast()->deleteLater(); 111 | } 112 | 113 | // extend views and savers to current demand 114 | for (int i = m_views.count(); i < nScreens; ++i) { 115 | // create the view 116 | auto *view = new QQuickView; 117 | view->create(); 118 | 119 | // engine stuff 120 | QQmlContext *context = view->engine()->rootContext(); 121 | context->setContextProperty(QStringLiteral("authenticator"), m_authenticator); 122 | 123 | view->setSource(QUrl("qrc:/qml/LockScreen.qml")); 124 | view->setResizeMode(QQuickView::SizeRootObjectToView); 125 | 126 | view->setColor(Qt::black); 127 | auto screen = QGuiApplication::screens()[i]; 128 | view->setGeometry(screen->geometry()); 129 | 130 | if (!m_testing) { 131 | if (QX11Info::isPlatformX11()) { 132 | view->setFlags(Qt::X11BypassWindowManagerHint); 133 | } else { 134 | view->setFlags(Qt::FramelessWindowHint); 135 | } 136 | } 137 | 138 | // overwrite the factory set by kdeclarative 139 | // auto oldFactory = view->engine()->networkAccessManagerFactory(); 140 | // view->engine()->setNetworkAccessManagerFactory(nullptr); 141 | // delete oldFactory; 142 | // view->engine()->setNetworkAccessManagerFactory(new NoAccessNetworkAccessManagerFactory); 143 | 144 | view->setGeometry(screen->geometry()); 145 | 146 | connect(view, &QQuickView::frameSwapped, this, [=] { markViewsAsVisible(view); }, Qt::QueuedConnection); 147 | 148 | m_views << view; 149 | } 150 | 151 | // update geometry of all views and savers 152 | for (int i = 0; i < nScreens; ++i) { 153 | auto *view = m_views.at(i); 154 | auto screen = QGuiApplication::screens()[i]; 155 | view->setScreen(screen); 156 | 157 | // on Wayland we may not use fullscreen as that puts all windows on one screen 158 | if (m_testing || QX11Info::isPlatformX11()) { 159 | view->show(); 160 | } else { 161 | view->showFullScreen(); 162 | } 163 | 164 | view->raise(); 165 | } 166 | } 167 | 168 | void Application::onScreenAdded(QScreen *screen) 169 | { 170 | // Lambda connections can not have uniqueness constraints, ensure 171 | // geometry change signals are only connected once 172 | connect(screen, &QScreen::geometryChanged, this, [this, screen](const QRect &geo) { 173 | screenGeometryChanged(screen, geo); 174 | }); 175 | 176 | desktopResized(); 177 | } 178 | 179 | void Application::onSucceeded() 180 | { 181 | QQuickView *mainView = nullptr; 182 | 183 | // 寻找主屏幕的 view 184 | for (int i = 0; i < m_views.size(); ++i) { 185 | if (m_views.at(i)->screen() == QGuiApplication::primaryScreen()) { 186 | mainView = m_views.at(i); 187 | break; 188 | } 189 | } 190 | 191 | if (mainView) { 192 | QVariantAnimation *ani = new QVariantAnimation; 193 | 194 | connect(ani, &QVariantAnimation::valueChanged, [mainView] (const QVariant &value) { 195 | mainView->setY(value.toInt()); 196 | }); 197 | 198 | connect(ani, &QVariantAnimation::finished, this, [=] { 199 | QCoreApplication::exit(); 200 | }); 201 | 202 | ani->setDuration(500); 203 | ani->setEasingCurve(QEasingCurve::OutSine); 204 | ani->setStartValue(mainView->geometry().y()); 205 | ani->setEndValue(mainView->geometry().y() + -mainView->geometry().height()); 206 | ani->start(); 207 | } else { 208 | QCoreApplication::exit(); 209 | } 210 | } 211 | 212 | void Application::getFocus() 213 | { 214 | QWindow *activeScreen = getActiveScreen(); 215 | 216 | if (!activeScreen) { 217 | return; 218 | } 219 | 220 | // this loop is required to make the qml/graphicsscene properly handle the shared keyboard input 221 | // ie. "type something into the box of every greeter" 222 | for (QQuickView *view : qAsConst(m_views)) { 223 | if (!m_testing) { 224 | view->setKeyboardGrabEnabled(true); // TODO - check whether this still works in master! 225 | } 226 | } 227 | 228 | // activate window and grab input to be sure it really ends up there. 229 | // focus setting is still required for proper internal QWidget state (and eg. visual reflection) 230 | if (!m_testing) { 231 | activeScreen->setKeyboardGrabEnabled(true); // TODO - check whether this still works in master! 232 | } 233 | 234 | activeScreen->requestActivate(); 235 | } 236 | 237 | void Application::markViewsAsVisible(QQuickView *view) 238 | { 239 | disconnect(view, &QQuickWindow::frameSwapped, this, nullptr); 240 | QQmlProperty showProperty(view->rootObject(), QStringLiteral("viewVisible")); 241 | showProperty.write(true); 242 | 243 | // random state update, actually rather required on init only 244 | QMetaObject::invokeMethod(this, "getFocus", Qt::QueuedConnection); 245 | } 246 | 247 | bool Application::eventFilter(QObject *obj, QEvent *event) 248 | { 249 | if (obj != this && event->type() == QEvent::Show) { 250 | QQuickView *view = nullptr; 251 | for (QQuickView *v : qAsConst(m_views)) { 252 | if (v == obj) { 253 | view = v; 254 | break; 255 | } 256 | } 257 | if (view && view->winId() && QX11Info::isPlatformX11()) { 258 | // showing greeter view window, set property 259 | static Atom tag = XInternAtom(QX11Info::display(), "_KDE_SCREEN_LOCKER", False); 260 | XChangeProperty(QX11Info::display(), view->winId(), tag, tag, 32, PropModeReplace, nullptr, 0); 261 | } 262 | // no further processing 263 | return false; 264 | } 265 | 266 | if (event->type() == QEvent::MouseButtonPress && QX11Info::isPlatformX11()) { 267 | if (getActiveScreen()) { 268 | getActiveScreen()->requestActivate(); 269 | } 270 | return false; 271 | } 272 | 273 | if (event->type() == QEvent::KeyPress) { // react if saver is visible 274 | shareEvent(event, qobject_cast(obj)); 275 | return false; // we don't care 276 | } else if (event->type() == QEvent::KeyRelease) { // conditionally reshow the saver 277 | QKeyEvent *ke = static_cast(event); 278 | if (ke->key() != Qt::Key_Escape) { 279 | shareEvent(event, qobject_cast(obj)); 280 | return false; // irrelevant 281 | } 282 | return true; // don't pass 283 | } 284 | 285 | return false; 286 | } 287 | 288 | QWindow *Application::getActiveScreen() 289 | { 290 | QWindow *activeScreen = nullptr; 291 | 292 | if (m_views.isEmpty()) { 293 | return activeScreen; 294 | } 295 | 296 | for (QQuickView *view : qAsConst(m_views)) { 297 | if (view->geometry().contains(QCursor::pos())) { 298 | activeScreen = view; 299 | break; 300 | } 301 | } 302 | if (!activeScreen) { 303 | activeScreen = m_views.first(); 304 | } 305 | 306 | return activeScreen; 307 | } 308 | 309 | void Application::shareEvent(QEvent *e, QQuickView *from) 310 | { 311 | // from can be NULL any time (because the parameter is passed as qobject_cast) 312 | // m_views.contains(from) is atm. supposed to be true but required if any further 313 | // QQuickView are added (which are not part of m_views) 314 | // this makes "from" an optimization (nullptr check aversion) 315 | if (from && m_views.contains(from)) { 316 | // NOTICE any recursion in the event sharing will prevent authentication on multiscreen setups! 317 | // Any change in regarded event processing shall be tested thoroughly! 318 | removeEventFilter(this); // prevent recursion! 319 | const bool accepted = e->isAccepted(); // store state 320 | for (QQuickView *view : qAsConst(m_views)) { 321 | if (view != from) { 322 | QCoreApplication::sendEvent(view, e); 323 | e->setAccepted(accepted); 324 | } 325 | } 326 | installEventFilter(this); 327 | } 328 | } 329 | 330 | void Application::screenGeometryChanged(QScreen *screen, const QRect &geo) 331 | { 332 | // We map screens() to m_views by index and Qt is free to 333 | // reorder screens, so pointer to pointer connections 334 | // may not remain matched by index, perform index 335 | // mapping in the change event itself 336 | const int screenIndex = QGuiApplication::screens().indexOf(screen); 337 | if (screenIndex < 0) { 338 | qWarning() << "Screen not found, not updating geometry" << screen; 339 | return; 340 | } 341 | 342 | if (screenIndex >= m_views.size()) { 343 | qWarning() << "Screen index out of range, not updating geometry" << screenIndex; 344 | return; 345 | } 346 | 347 | QQuickView *view = m_views[screenIndex]; 348 | view->setGeometry(geo); 349 | } 350 | -------------------------------------------------------------------------------- /checkpass/checkpass.c: -------------------------------------------------------------------------------- 1 | /***************************************************************** 2 | * 3 | * kcheckpass - Simple password checker 4 | * 5 | * This program is free software; you can redistribute it and/or 6 | * modify it under the terms of the GNU General Public 7 | * License as published by the Free Software Foundation; either 8 | * version 2 of the License, or (at your option) any later version. 9 | * 10 | * This program is distributed in the hope that it will be useful, 11 | * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 | * General Public License for more details. 14 | * 15 | * You should have received a copy of the GNU General Public 16 | * License along with this program; if not, write to the Free 17 | * Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 18 | * 19 | * 20 | * kcheckpass is a simple password checker. Just invoke and 21 | * send it the password on stdin. 22 | * 23 | * If the password was accepted, the program exits with 0; 24 | * if it was rejected, it exits with 1. Any other exit 25 | * code signals an error. 26 | * 27 | * It's hopefully simple enough to allow it to be setuid 28 | * root. 29 | * 30 | * Compile with -DHAVE_VSYSLOG if you have vsyslog(). 31 | * Compile with -DHAVE_PAM if you have a PAM system, 32 | * and link with -lpam -ldl. 33 | * Compile with -DHAVE_SHADOW if you have a shadow 34 | * password system. 35 | * 36 | * Copyright (C) 1998, Caldera, Inc. 37 | * Released under the GNU General Public License 38 | * 39 | * Olaf Kirch General Framework and PAM support 40 | * Christian Esken Shadow and /etc/passwd support 41 | * Roberto Teixeira other user (-U) support 42 | * Oswald Buddenhagen Binary server mode 43 | * 44 | * Other parts were taken from kscreensaver's passwd.cpp. 45 | * 46 | *****************************************************************/ 47 | 48 | #include "checkpass.h" 49 | 50 | #include 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #include 58 | #include 59 | #include 60 | 61 | #include 62 | 63 | #if HAVE_SYS_PRCTL_H 64 | #include 65 | #endif 66 | #if HAVE_SYS_PROCCTL_H 67 | #include 68 | #include 69 | #endif 70 | #if HAVE_SIGNALFD_H 71 | #include 72 | #endif 73 | #if HAVE_EVENT_H 74 | #include 75 | #include 76 | #include 77 | #endif 78 | 79 | #define THROTTLE 3 80 | 81 | static int havetty, sfd = -1, nullpass; 82 | 83 | static int Reader(void *buf, int count) 84 | { 85 | int ret, rlen; 86 | 87 | for (rlen = 0; rlen < count;) { 88 | dord: 89 | ret = read(sfd, (void *)((char *)buf + rlen), count - rlen); 90 | if (ret < 0) { 91 | if (errno == EINTR) { 92 | goto dord; 93 | } 94 | if (errno == EAGAIN) { 95 | break; 96 | } 97 | return -1; 98 | } 99 | if (!ret) { 100 | break; 101 | } 102 | rlen += ret; 103 | } 104 | return rlen; 105 | } 106 | 107 | static void GRead(void *buf, int count) 108 | { 109 | if (Reader(buf, count) != count) { 110 | message("Communication breakdown on read\n"); 111 | exit(15); 112 | } 113 | } 114 | 115 | static void GWrite(const void *buf, int count) 116 | { 117 | if (write(sfd, buf, count) != count) { 118 | message("Communication breakdown on write\n"); 119 | exit(15); 120 | } 121 | } 122 | 123 | static void GSendInt(int val) 124 | { 125 | GWrite(&val, sizeof(val)); 126 | } 127 | 128 | static void GSendStr(const char *buf) 129 | { 130 | unsigned len = buf ? strlen(buf) + 1 : 0; 131 | GWrite(&len, sizeof(len)); 132 | GWrite(buf, len); 133 | } 134 | 135 | static void GSendArr(int len, const char *buf) 136 | { 137 | GWrite(&len, sizeof(len)); 138 | GWrite(buf, len); 139 | } 140 | 141 | static int GRecvInt(void) 142 | { 143 | int val; 144 | 145 | GRead(&val, sizeof(val)); 146 | return val; 147 | } 148 | 149 | static char *GRecvStr(void) 150 | { 151 | unsigned len; 152 | char *buf; 153 | 154 | if (!(len = GRecvInt())) { 155 | return (char *)0; 156 | } 157 | if (len > 0x1000 || !(buf = malloc(len))) { 158 | message("No memory for read buffer\n"); 159 | exit(15); 160 | } 161 | GRead(buf, len); 162 | buf[len - 1] = 0; /* we're setuid ... don't trust "them" */ 163 | return buf; 164 | } 165 | 166 | static char *GRecvArr(void) 167 | { 168 | unsigned len; 169 | char *arr; 170 | unsigned const char *up; 171 | 172 | if (!(len = (unsigned)GRecvInt())) { 173 | return (char *)0; 174 | } 175 | if (len < 4) { 176 | message("Too short binary authentication data block\n"); 177 | exit(15); 178 | } 179 | if (len > 0x10000 || !(arr = malloc(len))) { 180 | message("No memory for read buffer\n"); 181 | exit(15); 182 | } 183 | GRead(arr, len); 184 | up = (unsigned const char *)arr; 185 | if (len != (unsigned)(up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24))) { 186 | message("Mismatched binary authentication data block size\n"); 187 | exit(15); 188 | } 189 | return arr; 190 | } 191 | 192 | static char *conv_server(ConvRequest what, const char *prompt) 193 | { 194 | GSendInt(what); 195 | switch (what) { 196 | case ConvGetBinary: { 197 | unsigned const char *up = (unsigned const char *)prompt; 198 | int len = up[3] | (up[2] << 8) | (up[1] << 16) | (up[0] << 24); 199 | GSendArr(len, prompt); 200 | return GRecvArr(); 201 | } 202 | case ConvGetNormal: 203 | case ConvGetHidden: { 204 | char *msg; 205 | GSendStr(prompt); 206 | msg = GRecvStr(); 207 | if (msg && (GRecvInt() & IsPassword) && !*msg) { 208 | nullpass = 1; 209 | } 210 | return msg; 211 | } 212 | case ConvPutAuthSucceeded: 213 | case ConvPutAuthFailed: 214 | case ConvPutAuthError: 215 | case ConvPutAuthAbort: 216 | case ConvPutReadyForAuthentication: 217 | return 0; 218 | case ConvPutInfo: 219 | case ConvPutError: 220 | default: 221 | GSendStr(prompt); 222 | return 0; 223 | } 224 | } 225 | 226 | void message(const char *fmt, ...) 227 | { 228 | va_list ap; 229 | 230 | va_start(ap, fmt); 231 | vfprintf(stderr, fmt, ap); 232 | va_end(ap); 233 | } 234 | 235 | #ifndef O_NOFOLLOW 236 | #define O_NOFOLLOW 0 237 | #endif 238 | 239 | static void ATTR_NORETURN usage(int exitval) 240 | { 241 | message( 242 | "usage: kcheckpass {-h|[-c caller] [-m method] -S handle}\n" 243 | " options:\n" 244 | " -h this help message\n" 245 | " -S handle operate in binary server mode on file descriptor handle\n" 246 | " -m method use the specified authentication method (default: \"classic\")\n" 247 | " exit codes:\n" 248 | " 0 success\n" 249 | " 1 invalid password\n" 250 | " 2 cannot read password database\n" 251 | " Anything else tells you something's badly hosed.\n"); 252 | exit(exitval); 253 | } 254 | 255 | int main(int argc, char **argv) 256 | { 257 | const char *method = "classic"; 258 | const char *username = 0; 259 | char *p; 260 | struct passwd *pw; 261 | int c, nfd; 262 | uid_t uid; 263 | AuthReturn ret; 264 | sigset_t signalMask; 265 | #if HAVE_SIGNALFD_H 266 | int signalFd; 267 | struct signalfd_siginfo fdsi; 268 | ssize_t sigReadSize; 269 | #endif 270 | #if HAVE_EVENT_H 271 | /* Event Queue */ 272 | int keventQueue; 273 | /* Listen for two events: SIGUSR1 and SIGUSR2 */ 274 | struct kevent keventEvent[2]; 275 | int keventData; 276 | #endif 277 | pid_t parentPid; 278 | 279 | parentPid = getppid(); 280 | 281 | // disable ptrace on kcheckpass 282 | #if HAVE_PR_SET_DUMPABLE 283 | prctl(PR_SET_DUMPABLE, 0); 284 | #endif 285 | #if HAVE_PROC_TRACE_CTL 286 | int mode = PROC_TRACE_CTL_DISABLE; 287 | procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode); 288 | #endif 289 | 290 | // prevent becoming an orphan while waiting for SIGUSR2 291 | #if HAVE_PR_SET_DUMPABLE 292 | prctl(PR_SET_PDEATHSIG, SIGUSR2); 293 | #endif 294 | 295 | /* Make sure stdout/stderr are open */ 296 | for (c = 1; c <= 2; c++) { 297 | if (fcntl(c, F_GETFL) == -1) { 298 | if ((nfd = open("/dev/null", O_WRONLY)) < 0) { 299 | message("cannot open /dev/null: %s\n", strerror(errno)); 300 | exit(10); 301 | } 302 | if (c != nfd) { 303 | dup2(nfd, c); 304 | close(nfd); 305 | } 306 | } 307 | } 308 | 309 | havetty = isatty(0); 310 | 311 | while ((c = getopt(argc, argv, "hm:S:")) != -1) { 312 | switch (c) { 313 | case 'h': 314 | usage(0); 315 | break; 316 | case 'm': 317 | method = optarg; 318 | break; 319 | case 'S': 320 | sfd = atoi(optarg); 321 | break; 322 | default: 323 | message("Command line option parsing error\n"); 324 | usage(10); 325 | } 326 | } 327 | 328 | if (sfd == -1) { 329 | message("Only binary protocol supported\n"); 330 | return AuthError; 331 | } 332 | 333 | uid = getuid(); 334 | if (!(p = getenv("LOGNAME")) || !(pw = getpwnam(p)) || pw->pw_uid != uid) { 335 | if (!(p = getenv("USER")) || !(pw = getpwnam(p)) || pw->pw_uid != uid) { 336 | if (!(pw = getpwuid(uid))) { 337 | message("Cannot determinate current user\n"); 338 | return AuthError; 339 | } 340 | } 341 | } 342 | if (!(username = strdup(pw->pw_name))) { 343 | message("Out of memory\n"); 344 | return AuthError; 345 | } 346 | 347 | // setup signals 348 | sigemptyset(&signalMask); 349 | sigaddset(&signalMask, SIGUSR1); 350 | sigaddset(&signalMask, SIGUSR2); 351 | // block them 352 | if (sigprocmask(SIG_BLOCK, &signalMask, NULL) == -1) { 353 | message("Block signal failed\n"); 354 | conv_server(ConvPutAuthError, 0); 355 | return 1; 356 | } 357 | #if HAVE_SIGNALFD_H 358 | signalFd = signalfd(-1, &signalMask, SFD_CLOEXEC); 359 | if (signalFd == -1) { 360 | message("Signal fd failed\n"); 361 | conv_server(ConvPutAuthError, 0); 362 | return 1; 363 | } 364 | #endif 365 | #if HAVE_EVENT_H 366 | /* Setup the kequeu */ 367 | keventQueue = kqueue(); 368 | if (keventQueue == -1) { 369 | message("Failed to create kqueue for SIGUSR1\n"); 370 | conv_server(ConvPutAuthError, 0); 371 | return 1; 372 | } 373 | /* Setup the events */ 374 | EV_SET(&keventEvent[0], SIGUSR1, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); 375 | EV_SET(&keventEvent[1], SIGUSR2, EVFILT_SIGNAL, EV_ADD, 0, 0, NULL); 376 | int setupResult = kevent(keventQueue, keventEvent, 2, NULL, 0, NULL); 377 | if (setupResult == -1) { 378 | message("Failed to attach event to the kqueue\n"); 379 | conv_server(ConvPutAuthError, 0); 380 | return 1; 381 | } 382 | if (keventEvent[0].flags & EV_ERROR) { 383 | message("Error in kevent for SIGUSR1: %s\n", strerror(keventEvent[0].data)); 384 | conv_server(ConvPutAuthError, 0); 385 | return 1; 386 | } 387 | if (keventEvent[1].flags & EV_ERROR) { 388 | message("Error in kevent for SIGUSR2: %s\n", strerror(keventEvent[1].data)); 389 | conv_server(ConvPutAuthError, 0); 390 | return 1; 391 | } 392 | 393 | /* signal_info for sigwaitinfo() */ 394 | siginfo_t signalInfo; 395 | 396 | #endif 397 | // now lets block on the fd 398 | for (;;) { 399 | conv_server(ConvPutReadyForAuthentication, 0); 400 | #if HAVE_SIGNALFD_H 401 | sigReadSize = read(signalFd, &fdsi, sizeof(struct signalfd_siginfo)); 402 | if (sigReadSize != sizeof(struct signalfd_siginfo)) { 403 | message("Read wrong size\n"); 404 | return 1; 405 | } 406 | if (fdsi.ssi_signo == SIGUSR1) { 407 | if (fdsi.ssi_pid != parentPid) { 408 | message("signal from wrong process\n"); 409 | continue; 410 | } 411 | #endif 412 | #if HAVE_EVENT_H 413 | keventData = kevent(keventQueue, NULL, 0, keventEvent, 1, NULL); 414 | if (keventData == -1) { 415 | /* Let's figure this out in the future, shall we */ 416 | message("kevent() failed with %d\n", errno); 417 | return 1; 418 | } else if (keventData == 0) { 419 | /* Do we need to handle timeouts? */ 420 | message("kevent timeout\n"); 421 | continue; 422 | } 423 | // We know we got a SIGUSR1 or SIGUSR2, so fetch it via sigwaitinfo() 424 | // (otherwise, we could have used sigtimedwait() ) 425 | int signalReturn = sigwaitinfo(&signalMask, &signalInfo); 426 | if (signalReturn < 0) { 427 | if (errno == EINTR) { 428 | message("sigawaitinfo() interrupted by unblocked caught signal"); 429 | continue; 430 | } else if (errno == EAGAIN) { 431 | /* This should not happen, as kevent notified us about such a signal */ 432 | message("no signal of type USR1 or USR2 pending."); 433 | continue; 434 | } else { 435 | message("Unhandled error in sigwaitinfo()"); 436 | conv_server(ConvPutAuthError, 0); 437 | return 1; 438 | } 439 | } 440 | if (signalReturn == SIGUSR1) { 441 | if (signalInfo.si_pid != parentPid) { 442 | message("signal from wrong process\n"); 443 | continue; 444 | } 445 | #endif 446 | /* Now do the fandango */ 447 | ret = Authenticate(method, username, conv_server); 448 | 449 | if (ret == AuthBad) { 450 | message("Authentication failure\n"); 451 | if (!nullpass) { 452 | openlog("kcheckpass", LOG_PID, LOG_AUTH); 453 | syslog(LOG_NOTICE, "Authentication failure for %s (invoked by uid %d)", username, uid); 454 | } 455 | } 456 | switch (ret) { 457 | case AuthOk: 458 | conv_server(ConvPutAuthSucceeded, 0); 459 | break; 460 | case AuthBad: 461 | conv_server(ConvPutAuthFailed, 0); 462 | break; 463 | case AuthError: 464 | conv_server(ConvPutAuthError, 0); 465 | break; 466 | case AuthAbort: 467 | conv_server(ConvPutAuthAbort, 0); 468 | default: 469 | break; 470 | } 471 | if (uid != geteuid()) { 472 | // we don't support multiple auth for setuid kcheckpass 473 | break; 474 | } 475 | #if HAVE_SIGNALFD_H 476 | } else if (fdsi.ssi_signo == SIGUSR2) { 477 | if (fdsi.ssi_pid != parentPid) { 478 | message("signal from wrong process\n"); 479 | continue; 480 | } 481 | break; 482 | #endif 483 | #if HAVE_EVENT_H 484 | } else if (signalReturn == SIGUSR2) { 485 | if (signalInfo.si_pid != parentPid) { 486 | message("signal from wrong process\n"); 487 | continue; 488 | } 489 | break; 490 | #endif 491 | } else { 492 | message("unexpected signal\n"); 493 | } 494 | } 495 | 496 | return 0; 497 | } 498 | 499 | void dispose(char *str) 500 | { 501 | memset(str, 0, strlen(str)); 502 | free(str); 503 | } 504 | 505 | /***************************************************************** 506 | The real authentication methods are in separate source files. 507 | Look in checkpass_*.c 508 | *****************************************************************/ 509 | --------------------------------------------------------------------------------