[gparted] Keep password dialog open until successful unlock or cancellation (#795617)



commit 307472489dc61261f2fc9360760301657dc81113
Author: Mike Fleetwood <mike fleetwood googlemail com>
Date:   Sun Feb 11 21:07:00 2018 +0000

    Keep password dialog open until successful unlock or cancellation (#795617)
    
    To keep password dialog open, just keep running it in a loop performing
    LUKS mapping unlock attempts with the entered passphrase until it
    succeeds or the dialog is cancelled or closed.  This is the same model
    that is already used for the File Support System dialog and how the
    [Rescan For Supported Actions] button is implemented.
    
    Also any error from attempting to open the LUKS mapping is no longer
    displayed in a separate error dialog or at all.  Will add some sort of
    error reporting into the password entry dialog in a following commit.
    
    Creates new method Win_GParted::open_encrypted_partition() which handles
    the non UI parts of attempting to open an encrypted partition.  Running
    "cryptsetup luksOpen" and updating the stored passphrase as needed.
    
    Bug 795617 - Implement opening and closing of LUKS mappings

 include/Win_GParted.h |    1 +
 src/Win_GParted.cc    |  110 ++++++++++++++++++++++++++++++++++++++----------
 2 files changed, 88 insertions(+), 23 deletions(-)
---
diff --git a/include/Win_GParted.h b/include/Win_GParted.h
index a8d3c93..0b7fb90 100644
--- a/include/Win_GParted.h
+++ b/include/Win_GParted.h
@@ -180,6 +180,7 @@ private:
        void activate_delete();
        void activate_info();
        void activate_format( FSType new_fs );
+       bool open_encrypted_partition( const Partition & partition, const char * password, Glib::ustring & 
message );
        void toggle_crypt_busy_state();
        bool check_toggle_busy_allowed( const Glib::ustring & disallowed_msg );
        void show_toggle_failure_dialog( const Glib::ustring & failure_summary,
diff --git a/src/Win_GParted.cc b/src/Win_GParted.cc
index e54a9f3..3e32a7c 100644
--- a/src/Win_GParted.cc
+++ b/src/Win_GParted.cc
@@ -2421,6 +2421,77 @@ void Win_GParted::activate_format( FSType new_fs )
        temp_ptn = NULL;
 }
 
+bool Win_GParted::open_encrypted_partition( const Partition & partition,
+                                            const char * entered_password,
+                                            Glib::ustring & message )
+{
+       const char * pw = NULL;
+       if ( entered_password == NULL )
+       {
+               pw = PasswordRAMStore::lookup( partition.uuid );
+               if ( pw == NULL )
+               {
+                       // Internal documentation message never shown to user.
+                       message = "No stored password available";
+                       return false;
+               }
+       }
+       else
+       {
+               pw = entered_password;
+               if ( strlen( pw ) == 0 )
+               {
+                       // Internal documentation message never shown to user.
+                       message = "Invalid zero length password";
+                       return false;
+               }
+       }
+
+       // Create LUKS mapping name from partition name:
+       // "/dev/sdb1" -> "sdb1_crypt"
+       Glib::ustring mapping_name = selected_partition_ptr->get_path();
+       Glib::ustring::size_type last_slash = mapping_name.rfind( "/" );
+       if ( last_slash != Glib::ustring::npos )
+               mapping_name = mapping_name.substr( last_slash + 1 );
+       mapping_name += "_crypt";
+
+       Glib::ustring cmd = "cryptsetup luksOpen " +
+                           Glib::shell_quote( partition.get_path() ) + " " +
+                           Glib::shell_quote( mapping_name );
+
+       show_pulsebar( String::ucompose( _("Opening encryption on %1"), partition.get_path() ) );
+       Glib::ustring output;
+       Glib::ustring error;
+       bool success = ! Utils::execute_command( cmd, pw, output, error );
+       hide_pulsebar();
+       if ( success && pw != NULL )
+       {
+               // Replace the password just successfully used to open the LUKS mapping if
+               // it is different to the one already saved, or there is no saved
+               // password.
+               const char * stored_pw = PasswordRAMStore::lookup( partition.uuid );
+               if ( stored_pw != NULL            &&
+                    strcmp( pw, stored_pw ) == 0    )
+               {
+                       PasswordRAMStore::erase( partition.uuid );
+                       stored_pw = NULL;
+               }
+               if ( stored_pw == NULL )
+               {
+                       PasswordRAMStore::insert( partition.uuid, pw );
+               }
+       }
+       else if ( ! success )
+       {
+               // Erase the password used during for the failure to open the LUKS
+               // mapping.
+               PasswordRAMStore::erase( partition.uuid );
+       }
+
+       message = "<i># " + cmd + "\n" + error + "\n" + output + "</i>";
+       return success;
+}
+
 void Win_GParted::toggle_crypt_busy_state()
 {
        g_assert( selected_partition_ptr != NULL );  // Bug: Partition callback without a selected partition
@@ -2447,8 +2518,6 @@ void Win_GParted::toggle_crypt_busy_state()
        {
                action = LUKSOPEN;
                disallowed_msg = _("The open encryption action cannot be performed when there are operations 
pending for the partition.");
-               pulse_msg = String::ucompose( _("Opening encryption on %1"), 
selected_partition_ptr->get_path() );
-               failure_msg = _("Could not open encryption");
        }
 
        if ( ! check_toggle_busy_allowed( disallowed_msg ) )
@@ -2478,30 +2547,25 @@ void Win_GParted::toggle_crypt_busy_state()
                        break;
                case LUKSOPEN:
                {
+                       // Attempt to unlock LUKS using stored passphrase first.
+                       success = open_encrypted_partition( *selected_partition_ptr, NULL, error_msg );
+                       if ( success )
+                               break;
 
+                       // Open password dialog and attempt to unlock LUKS mapping.
                        DialogPasswordEntry dialog( *selected_partition_ptr );
                        dialog.set_transient_for( *this );
-                       if ( dialog.run() != Gtk::RESPONSE_OK )
-                               // Password dialog cancelled or closed
-                               return;
-
-                       // Create LUKS mapping name from partition name:
-                       // "/dev/sdb1" -> "sdb1_crypt"
-                       Glib::ustring mapping_name = selected_partition_ptr->get_path();
-                       Glib::ustring::size_type last_slash = mapping_name.rfind( "/" );
-                       if ( last_slash != Glib::ustring::npos )
-                               mapping_name = mapping_name.substr( last_slash + 1 );
-                       mapping_name += "_crypt";
-
-                       cmd = "cryptsetup luksOpen " +
-                             Glib::shell_quote( selected_partition_ptr->get_path() ) + " " +
-                             Glib::shell_quote( mapping_name );
-                       show_pulsebar( pulse_msg );
-                       success = ! Utils::execute_command( cmd, dialog.get_password().c_str(),
-                                                           output, error );
-                       hide_pulsebar();
-                       error_msg = "<i># " + cmd + "\n" + error + "</i>";
-                       break;
+                       do
+                       {
+                               if ( dialog.run() != Gtk::RESPONSE_OK )
+                                       // Password dialog cancelled or closed without the
+                                       // LUKS mapping having been opened.  Skip refresh.
+                                       return;
+
+                               success = open_encrypted_partition( *selected_partition_ptr,
+                                                                   dialog.get_password().c_str(),
+                                                                   error_msg );
+                       } while ( ! success );
                }
                default:
                        // Impossible


[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]