From 40eed598b87fa63158fb7471f52955a0e258dfca Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marco=20Trevisan=20=28Trevi=C3=B1o=29?= Date: Sun, 5 May 2024 18:23:44 +0200 Subject: [PATCH] locations: Ask again for password on encryption failures This sadly requires parsing the error strings since there are not good APIs yet, but that's how upstream handles this too, so let's accept it for now. See: https://gitlab.gnome.org/GNOME/gnome-shell/-/merge_requests/3300 --- locations.js | 39 +++++++++++++++++++++++++++++++++++++++ 1 file changed, 39 insertions(+) diff --git a/locations.js b/locations.js index bf20de800..85d71e252 100644 --- a/locations.js +++ b/locations.js @@ -656,6 +656,12 @@ class MountableVolumeAppInfo extends LocationAppInfo { if (e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED)) this._notifyActionError(action, e.message); + if (action === 'mount' && this._isEncryptedMountError(e)) { + delete this._currentAction; + operation.close(); + return this.launchAction(action); + } + if (!e.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.CANCELLED)) { logError(e, 'Impossible to %s removable %s'.format(action, removable.get_name())); @@ -669,6 +675,39 @@ class MountableVolumeAppInfo extends LocationAppInfo { operation.close(); } } + + _isEncryptedMountError(error) { + // FIXME: we will always get G_IO_ERROR_FAILED from the gvfs udisks + // backend, see https://bugs.freedesktop.org/show_bug.cgi?id=51271 + + if (!error.matches(Gio.IOErrorEnum, Gio.IOErrorEnum.FAILED)) + return false; + + // cryptsetup + if (error.message.includes('No key available with this passphrase')) + return true; + + // udisks (no password) + if (error.message.includes('No key available to unlock device')) + return true; + + // libblockdev wrong password opening LUKS device + if (error.message.includes('Failed to activate device: Incorrect passphrase')) + return true; + + // cryptsetup returns EINVAL in many cases, including wrong TCRYPT password/parameters + if (error.message.includes('Failed to load device\'s parameters: Invalid argument') || + error.message.includes(`Failed to load device's parameters: ${GLib.strerror(22 /* EINVAL */)}`)) + return true; + + // cryptsetup returns EPERM when the TCRYPT header can't be decrypted + // with the provided password/parameters. + if (error.message.includes('Failed to load device\'s parameters: Operation not permitted') || + error.message.includes(`Failed to load device's parameters: ${GLib.strerror(1 /* EPERM */)}`)) + return true; + + return false; + } }); const TrashAppInfo = GObject.registerClass({