/* * Remmina - The GTK+ Remote Desktop Client * Copyright (C) 2016-2021 Antenore Gatta, Giovanni Panozzo * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 51 Franklin Street, Fifth Floor, * Boston, MA 02110-1301, USA. * * In addition, as a special exception, the copyright holders give * permission to link the code of portions of this program with the * OpenSSL library under certain conditions as described in each * individual source file, and distribute linked combinations * including the two. * You must obey the GNU General Public License in all respects * for all of the code used other than OpenSSL. * If you modify * file(s) with this exception, you may extend this exception to your * version of the file(s), but you are not obligated to do so. * If you * do not wish to do so, delete this exception statement from your * version. * If you delete this exception statement from all source * files in the program, then also delete it here. * */ #include #include #include #include #include #include "config.h" #include "remmina_sodium.h" #include "remmina_pref.h" #include "remmina_unlock.h" #include "remmina_public.h" #include "remmina/remmina_trace_calls.h" #if SODIUM_VERSION_INT >= 90200 static RemminaUnlockDialog *remmina_unlock_dialog; #define GET_OBJ(object_name) gtk_builder_get_object(remmina_unlock_dialog->builder, object_name) GTimer *timer; gboolean isinit; static void remmina_unlock_timer_init() { TRACE_CALL(__func__); timer = g_timer_new(); g_info("Unlock Master Password timer initialized"); } static void remmina_unlock_timer_reset(gpointer user_data) { TRACE_CALL(__func__); g_timer_reset(timer); g_info("Unlock Master Password timer reset"); } void remmina_unlock_timer_destroy() { TRACE_CALL(__func__); g_timer_destroy(timer); } static void remmina_unlock_unlock_clicked(GtkButton *btn, gpointer user_data) { TRACE_CALL(__func__); //g_timer_reset(remmina_unlock_dialog->timer); gchar *unlock_password; const gchar *entry_passwd; gint rc; unlock_password = remmina_pref_get_value("unlock_password"); entry_passwd = gtk_entry_get_text(remmina_unlock_dialog->entry_unlock); rc = remmina_sodium_pwhash_str_verify(unlock_password, entry_passwd); g_info("remmina_sodium_pwhash_str_verify returned %i", rc); if (rc == 0) { g_info("Passphrase veryfied successfully"); remmina_unlock_timer_reset(remmina_unlock_dialog); gtk_widget_destroy(GTK_WIDGET(remmina_unlock_dialog->dialog)); remmina_unlock_dialog->dialog = NULL; } else { g_warning ("Passphrase is wrong, to reset it, you can edit the remmina.pref file by hand"); } } static void remmina_unlock_cancel_clicked(GtkButton *btn, gpointer user_data) { TRACE_CALL(__func__); remmina_unlock_dialog->retval = 0; gtk_widget_destroy(GTK_WIDGET(remmina_unlock_dialog->dialog)); remmina_unlock_dialog->dialog = NULL; } gint remmina_unlock_new(GtkWindow *parent) { TRACE_CALL(__func__); gdouble unlock_timeout; gdouble elapsed = 0.0; gboolean lock = TRUE; unlock_timeout = remmina_pref.unlock_timeout; remmina_unlock_dialog = g_new0(RemminaUnlockDialog, 1); remmina_unlock_dialog->retval = 1; if (timer == NULL) remmina_unlock_timer_init(); if (timer != NULL) elapsed = g_timer_elapsed(timer, NULL); if (((int)unlock_timeout - elapsed) < 0) lock = TRUE; if (((int)unlock_timeout - elapsed) >= 0) lock = FALSE; /* timer & timout = 0 */ if (timer != NULL && (int)unlock_timeout == 0) lock = FALSE; /* first time and timout = 30 */ if (isinit == 0 && (int)unlock_timeout >= 0) { lock = TRUE; isinit = TRUE; } /* first time and timout = 0 */ if (isinit == 0 && (int)unlock_timeout == 0) { lock = TRUE; isinit = TRUE; } g_info("Based on settings and current status, the unlock dialog is set to %d", lock); remmina_unlock_dialog->builder = remmina_public_gtk_builder_new_from_resource("/org/remmina/Remmina/src/../data/ui/remmina_unlock.glade"); remmina_unlock_dialog->dialog = GTK_DIALOG(gtk_builder_get_object(remmina_unlock_dialog->builder, "RemminaUnlockDialog")); if (parent) gtk_window_set_transient_for(GTK_WINDOW(remmina_unlock_dialog->dialog), parent); remmina_unlock_dialog->entry_unlock = GTK_ENTRY(GET_OBJ("entry_unlock")); gtk_entry_set_activates_default(GTK_ENTRY(remmina_unlock_dialog->entry_unlock), TRUE); remmina_unlock_dialog->button_unlock = GTK_BUTTON(GET_OBJ("button_unlock")); gtk_widget_set_can_default(GTK_WIDGET(remmina_unlock_dialog->button_unlock), TRUE); gtk_widget_grab_default(GTK_WIDGET(remmina_unlock_dialog->button_unlock)); remmina_unlock_dialog->button_unlock_cancel = GTK_BUTTON(GET_OBJ("button_unlock_cancel")); g_signal_connect(remmina_unlock_dialog->button_unlock, "clicked", G_CALLBACK(remmina_unlock_unlock_clicked), (gpointer)remmina_unlock_dialog); g_signal_connect(remmina_unlock_dialog->button_unlock_cancel, "clicked", G_CALLBACK(remmina_unlock_cancel_clicked), (gpointer)remmina_unlock_dialog); g_signal_connect (remmina_unlock_dialog->dialog, "close", G_CALLBACK (remmina_unlock_cancel_clicked), (gpointer)remmina_unlock_dialog); /* Connect signals */ gtk_builder_connect_signals(remmina_unlock_dialog->builder, NULL); if (remmina_pref_get_boolean("use_master_password") && (g_strcmp0(remmina_pref_get_value("unlock_password"), "") != 0) && lock != 0) gtk_dialog_run(remmina_unlock_dialog->dialog); return(remmina_unlock_dialog->retval); } #else gint remmina_unlock_new(GtkWindow *parent) { return 1; } #endif