diff --git a/data/css/default.css b/data/css/default.css index 2f0415d63..a7384d135 100644 --- a/data/css/default.css +++ b/data/css/default.css @@ -241,6 +241,14 @@ text-shadow: 1px 1px 0 var(--bcol), padding-bottom: 75px; } +.wf-locker .failure { + animation-name: shake; + animation-duration:0.5s; + animation-timing-function: linear; + animation-iteration-count: 1; + animation-fill-mode: forwards; +} + .wf-locker.sized-480 { font-size:6px; } @@ -292,3 +300,25 @@ text-shadow: 1px 1px 0 var(--bcol), padding-right: 0rem; } } + +@keyframes shake { + 0% { + transform: translateX(0px); + } + 20% { + transform: translateX(20px); + } + 40% { + transform: translateX(-20px); + } + 60% { + transform: translateX(20px); + } + 80% { + transform: translateX(-20px); + } + 100% { + transform: translateX(0px); + } +} + diff --git a/data/meson.build b/data/meson.build index e35455ef1..ea20a57aa 100644 --- a/data/meson.build +++ b/data/meson.build @@ -13,6 +13,6 @@ install_data(join_paths('icons', '256x256', 'wayfire.png'), install_dir: join_pa install_data(join_paths('icons', '512x512', 'wayfire.png'), install_dir: join_paths(get_option('prefix'), 'share', 'icons', 'hicolor', '512x512', 'apps')) install_data(join_paths('icons', 'scalable', 'wayfire.svg'), install_dir: join_paths(get_option('prefix'), 'share', 'icons', 'hicolor', 'scalable', 'apps')) -install_data('wf-locker-password', install_dir:'/etc/pam.d/') +install_data('wf-locker', install_dir:'/etc/pam.d/') -subdir('css') \ No newline at end of file +subdir('css') diff --git a/data/wf-locker b/data/wf-locker new file mode 100644 index 000000000..fd46cb30b --- /dev/null +++ b/data/wf-locker @@ -0,0 +1,2 @@ +auth required pam_unix.so nodelay unlock_time=60 +account required pam_unix.so nodelay unlock_time=60 diff --git a/data/wf-locker-password b/data/wf-locker-password deleted file mode 100644 index c1355e38b..000000000 --- a/data/wf-locker-password +++ /dev/null @@ -1 +0,0 @@ -auth include login diff --git a/src/locker/plugin.hpp b/src/locker/plugin.hpp index 1a9687f50..bd158bbee 100644 --- a/src/locker/plugin.hpp +++ b/src/locker/plugin.hpp @@ -26,5 +26,7 @@ class WayfireLockerPlugin virtual void deinit() = 0; /* Called after lockscreen unlocked. */ virtual void lockout_changed(bool lockout) {} /* Called when too many failed logins have occured */ + virtual void failure() + {} virtual ~WayfireLockerPlugin() = default; }; diff --git a/src/locker/plugin/fingerprint.cpp b/src/locker/plugin/fingerprint.cpp index 53876e0ce..41bbf6c34 100644 --- a/src/locker/plugin/fingerprint.cpp +++ b/src/locker/plugin/fingerprint.cpp @@ -151,6 +151,7 @@ void WayfireLockerFingerprintPlugin::start_fingerprint_scanning() { std::cout << "No match" << std::endl; show(); + failure(); update("Invalid fingerprint", "dialog-error-symbolic", "bad"); stop_fingerprint_scanning(); WayfireLockerApp::get().recieved_bad_auth(); @@ -411,6 +412,14 @@ void WayfireLockerFingerprintPlugin::update(std::string label, std::string image } } +void WayfireLockerFingerprintPlugin::failure() +{ + for (auto & it : widgets) + { + it.second->failure(); + } +} + void WayfireLockerFingerprintPlugin::hide() { show_state = false; diff --git a/src/locker/plugin/fingerprint.hpp b/src/locker/plugin/fingerprint.hpp index 58245fa11..344bcb4c3 100644 --- a/src/locker/plugin/fingerprint.hpp +++ b/src/locker/plugin/fingerprint.hpp @@ -49,6 +49,7 @@ class WayfireLockerFingerprintPlugin : public WayfireLockerPlugin void init() override; void deinit() override; void lockout_changed(bool lockout) override; + void failure() override; void hide(); void show(); void color(std::string color); diff --git a/src/locker/plugin/password.cpp b/src/locker/plugin/password.cpp index c7af4d344..856ce85d8 100644 --- a/src/locker/plugin/password.cpp +++ b/src/locker/plugin/password.cpp @@ -25,16 +25,19 @@ WayfireLockerPasswordPluginWidget::~WayfireLockerPasswordPluginWidget() { entry_submitted.disconnect(); } + + for (auto signal : replies_signals) + { + signal.disconnect(); + } } -void WayfireLockerPasswordPlugin::update_labels(std::string text) +void WayfireLockerPasswordPlugin::add_reply(std::string text) { for (auto& it : widgets) { - it.second->label.set_label(text); + it.second->add_reply(text); } - - label_contents = text; } void WayfireLockerPasswordPlugin::blank_passwords() @@ -45,9 +48,23 @@ void WayfireLockerPasswordPlugin::blank_passwords() } } +void WayfireLockerPasswordPluginWidget::lockout_changed(bool lockout) +{ + if (lockout) + { + entry.set_text(""); + entry.set_sensitive(false); + entry.set_placeholder_text("Too many attempts"); + } else + { + entry.set_sensitive(true); + entry.set_placeholder_text("Password"); + } +} + void WayfireLockerPasswordPlugin::add_output(int id, std::shared_ptr grid) { - widgets.emplace(id, new WayfireLockerPasswordPluginWidget(label_contents)); + widgets.emplace(id, new WayfireLockerPasswordPluginWidget()); /* Share string to every other entry */ auto widget = widgets[id]; @@ -84,21 +101,33 @@ void WayfireLockerPasswordPlugin::add_output(int id, std::shared_ptr new_label = std::make_shared(message); + replies.append(*new_label); + + replies_signals.push_back(Glib::signal_timeout().connect_seconds([this, new_label] () + { + replies.remove(*new_label); + return G_SOURCE_REMOVE; + }, 15)); +} + void WayfireLockerPasswordPlugin::remove_output(int id, std::shared_ptr grid) { grid->remove(*widgets[id]); @@ -113,8 +142,6 @@ WayfireLockerPasswordPlugin::WayfireLockerPasswordPlugin() : int pam_conversation(int num_mesg, const struct pam_message **mesg, struct pam_response **resp, void *appdata_ptr) { - std::cout << "PAM convo step ... " << std::endl; - WayfireLockerPasswordPlugin *pass_plugin = (WayfireLockerPasswordPlugin*)appdata_ptr; *resp = (struct pam_response*)calloc(num_mesg, sizeof(struct pam_response)); if (*resp == NULL) @@ -125,7 +152,8 @@ int pam_conversation(int num_mesg, const struct pam_message **mesg, struct pam_r for (int count = 0; count < num_mesg; count++) { - std::cout << "PAM msg : " << mesg[count]->msg << std::endl; + std::string message = mesg[count]->msg; + resp[count]->resp_retcode = 0; /* Echo OFF prompt should be user password. */ if (mesg[count]->msg_style == PAM_PROMPT_ECHO_OFF) @@ -133,10 +161,10 @@ int pam_conversation(int num_mesg, const struct pam_message **mesg, struct pam_r resp[count]->resp = strdup(pass_plugin->submitted_password.c_str()); } else if (mesg[count]->msg_style == PAM_ERROR_MSG) { - pass_plugin->update_labels(mesg[count]->msg); + pass_plugin->add_reply(message); } else if (mesg[count]->msg_style == PAM_TEXT_INFO) { - pass_plugin->update_labels(mesg[count]->msg); + pass_plugin->add_reply(message); } } @@ -158,12 +186,11 @@ void WayfireLockerPasswordPlugin::submit_user_password(std::string password) int retval; /* Start the password-based conversation */ std::cout << "PAM start ... " << std::endl; - retval = pam_start("wf-locker-password", username, &local_conversation, &local_auth_handle); + retval = pam_start("wf-locker", username, &local_conversation, &local_auth_handle); if (retval != PAM_SUCCESS) { /* We don't expect to be here. No graceful way out of this. */ - std::cout << "PAM start returned " << retval << std::endl; - update_labels("pam_start failure"); + add_reply("pam_start failure"); exit(retval); } @@ -175,8 +202,7 @@ void WayfireLockerPasswordPlugin::submit_user_password(std::string password) { if (retval == PAM_AUTH_ERR) { - std::cout << "Authentication failure." << std::endl; - update_labels("Authentication failure."); + failure(); } } else { @@ -191,6 +217,23 @@ void WayfireLockerPasswordPlugin::submit_user_password(std::string password) } } +void WayfireLockerPasswordPlugin::lockout_changed(bool lockout) +{ + for (auto & it : widgets) + { + it.second->lockout_changed(lockout); + } +} + +void WayfireLockerPasswordPlugin::failure() +{ + WayfireLockerApp::get().recieved_bad_auth(); + for (auto & it : widgets) + { + it.second->failure(); + } +} + void WayfireLockerPasswordPlugin::init() {} diff --git a/src/locker/plugin/password.hpp b/src/locker/plugin/password.hpp index 54b6a6984..c26b94434 100644 --- a/src/locker/plugin/password.hpp +++ b/src/locker/plugin/password.hpp @@ -18,10 +18,14 @@ class WayfireLockerPasswordPluginWidget : public WayfireLockerTimedRevealer ~WayfireLockerPasswordPluginWidget(); Gtk::Box box; Gtk::Entry entry; - Gtk::Label label; - WayfireLockerPasswordPluginWidget(std::string label_contents); + Gtk::Box replies; + WayfireLockerPasswordPluginWidget(); sigc::connection entry_updated, entry_submitted; + std::vector replies_signals; + + void add_reply(std::string message); + void lockout_changed(bool lockout); }; class WayfireLockerPasswordPlugin : public WayfireLockerPlugin @@ -35,11 +39,12 @@ class WayfireLockerPasswordPlugin : public WayfireLockerPlugin void submit_user_password(std::string password); void blank_passwords(); void update_passwords(std::string password); + void lockout_changed(bool lockout) override; + void failure() override; sigc::connection timeout; - void update_labels(std::string text); + void add_reply(std::string text); std::unordered_map> widgets; - std::string label_contents = ""; std::string submitted_password = ""; }; diff --git a/src/locker/timedrevealer.cpp b/src/locker/timedrevealer.cpp index 9d9b42e6d..dd4f30b34 100644 --- a/src/locker/timedrevealer.cpp +++ b/src/locker/timedrevealer.cpp @@ -5,6 +5,7 @@ WayfireLockerTimedRevealer::WayfireLockerTimedRevealer(std::string always_option) : always_show(WfOption{always_option}) { + set_overflow(Gtk::Overflow::VISIBLE); if ((hide_timeout > 0) && !always_show) { set_reveal_child(false); @@ -84,6 +85,11 @@ WayfireLockerTimedRevealer::~WayfireLockerTimedRevealer() { signal.disconnect(); } + + if (signal_failure) + { + signal_failure.disconnect(); + } } void WayfireLockerTimedRevealer::activity() @@ -107,3 +113,20 @@ void WayfireLockerTimedRevealer::activity() }, hide_timeout * 1000); } + +void WayfireLockerTimedRevealer::failure() +{ + if (signal_failure) + { + signal_failure.disconnect(); + } + + remove_css_class("failure"); + + Glib::signal_idle().connect( + [this] () + { + add_css_class("failure"); + return G_SOURCE_REMOVE; + }); +} diff --git a/src/locker/timedrevealer.hpp b/src/locker/timedrevealer.hpp index 837dca817..e01497bba 100644 --- a/src/locker/timedrevealer.hpp +++ b/src/locker/timedrevealer.hpp @@ -7,6 +7,7 @@ class WayfireLockerTimedRevealer : public Gtk::Revealer { private: sigc::connection signal; + sigc::connection signal_failure; public: WayfireLockerTimedRevealer(std::string always_option); @@ -17,4 +18,5 @@ class WayfireLockerTimedRevealer : public Gtk::Revealer WfOption hide_animation_duration{"locker/hide_anim_dur"}; virtual void activity(); /* Allow plugins to have their own logic if more intricate */ + void failure(); };