]> git.proxmox.com Git - proxmox-backup.git/commitdiff
tape: fix regression in restoring key from medium
authorDominik Csapak <d.csapak@proxmox.com>
Wed, 31 Jan 2024 13:42:33 +0000 (14:42 +0100)
committerThomas Lamprecht <t.lamprecht@proxmox.com>
Thu, 1 Feb 2024 15:31:29 +0000 (16:31 +0100)
Since commit 1343dcaf we automatically try to load the key into the
drive after reading the media-set label, this cannot work for the case
where we actually restore the key from the tape itself.

To address this special case while preserving the automatic key
loading, everything except the setup of the key has been separated
from the 'read_label' method into a new function named
'read_label_without_loading_key'. Consequently, the 'restore-key' API
endpoint can be switched to utilize this new method, thereby avoiding
the issue.

Fixes: 1343dcaf ("tape: move 'set_encryption' calls to the TapeDriver")
Signed-off-by: Dominik Csapak <d.csapak@proxmox.com>
 [ TL: reword and shorten commit message ]
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
(cherry picked from commit a33d7957412214c41489499f449450b3b5e6601a)
Signed-off-by: Thomas Lamprecht <t.lamprecht@proxmox.com>
src/api2/tape/drive.rs
src/tape/drive/mod.rs

index 0dddcefcb1dfa0583990899a7c162ccb8f43b18e..87c42feb3b4f5e95d3d3e3f29335348f06b6413b 100644 (file)
@@ -609,7 +609,7 @@ pub async fn restore_key(drive: String, password: String) -> Result<(), Error> {
     run_drive_blocking_task(drive.clone(), "restore key".to_string(), move |config| {
         let mut drive = open_drive(&config, &drive)?;
 
-        let (_media_id, key_config) = drive.read_label()?;
+        let (_media_id, key_config) = drive.read_label_without_loading_key()?;
 
         if let Some(key_config) = key_config {
             let password_fn = || Ok(password.as_bytes().to_vec());
index 73886f14020e4ee7ab696c049721f635b4960145..2fc88ef876f5569c7bcb272dbaca5fa5d2baa3bc 100644 (file)
@@ -105,11 +105,13 @@ pub trait TapeDriver {
         key_config: Option<&KeyConfig>,
     ) -> Result<(), Error>;
 
-    /// Read the media label
+    /// Read the media label without setting the encryption key
     ///
-    /// This tries to read both media labels (label and
-    /// media_set_label). Also returns the optional encryption key configuration.
-    fn read_label(&mut self) -> Result<(Option<MediaId>, Option<KeyConfig>), Error> {
+    /// This is used internally by 'read_label' and when restoring the encryption
+    /// key from the drive. Should not be used or overwritten otherwise!
+    fn read_label_without_loading_key(
+        &mut self,
+    ) -> Result<(Option<MediaId>, Option<KeyConfig>), Error> {
         self.rewind()?;
 
         let label = {
@@ -182,18 +184,34 @@ pub trait TapeDriver {
             bail!("got unexpected data after media set label");
         }
 
-        drop(reader);
+        media_id.media_set_label = Some(media_set_label);
 
-        let encrypt_fingerprint = media_set_label
-            .encryption_key_fingerprint
-            .clone()
-            .map(|fp| (fp, media_set_label.uuid.clone()));
+        Ok((Some(media_id), key_config))
+    }
 
-        self.set_encryption(encrypt_fingerprint)?;
+    /// Read the media label
+    ///
+    /// This tries to read both media labels (label and
+    /// media_set_label). Also returns the optional encryption key configuration.
+    ///
+    /// Automatically sets the encryption key on the drive
+    fn read_label(&mut self) -> Result<(Option<MediaId>, Option<KeyConfig>), Error> {
+        let (media_id, key_config) = self.read_label_without_loading_key()?;
 
-        media_id.media_set_label = Some(media_set_label);
+        let encrypt_fingerprint = if let Some(media_set_label) =
+            media_id.as_ref().and_then(|id| id.media_set_label.clone())
+        {
+            media_set_label
+                .encryption_key_fingerprint
+                .clone()
+                .map(|fp| (fp, media_set_label.uuid.clone()))
+        } else {
+            None
+        };
 
-        Ok((Some(media_id), key_config))
+        self.set_encryption(encrypt_fingerprint)?;
+
+        Ok((media_id, key_config))
     }
 
     /// Eject media