Made the BackendManager.GetOperations' decryption methods static and public so the restores VolumeDecryptor can use the same code.
This commit is contained in:
@@ -64,11 +64,6 @@ partial class BackendManager
|
||||
{
|
||||
TempFile? tmpfile = null;
|
||||
Context.Statwriter.SendEvent(BackendActionType.Get, BackendEventType.Started, RemoteFilename, Size);
|
||||
using var encryption = Context.Options.NoEncryption
|
||||
? null
|
||||
: (DynamicLoader.EncryptionLoader.GetModule(Context.Options.EncryptionModule, Context.Options.Passphrase, Context.Options.RawOptions)
|
||||
?? throw new Exception(Strings.BackendMananger.EncryptionModuleNotFound(Context.Options.EncryptionModule))
|
||||
);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -94,7 +89,7 @@ partial class BackendManager
|
||||
}
|
||||
|
||||
// Perform decryption after hash validation, if needed
|
||||
tmpfile = DecryptFile(tmpfile, DetectEncryptionModule(encryption));
|
||||
tmpfile = DecryptFile(tmpfile, RemoteFilename, Context.Options);
|
||||
|
||||
return (tmpfile, fileHash, dataSizeDownloaded);
|
||||
}
|
||||
@@ -161,40 +156,40 @@ partial class BackendManager
|
||||
/// </summary>
|
||||
/// <param name="encryption">The default encryption module</param>
|
||||
/// <returns>The encryption module to use</returns>
|
||||
private IEncryption? DetectEncryptionModule(IEncryption? encryption)
|
||||
private static IEncryption? DetectEncryptionModule(string filename, Options options, IEncryption? encryption)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Auto-guess the encryption module
|
||||
var ext = (System.IO.Path.GetExtension(RemoteFilename) ?? "").TrimStart('.');
|
||||
var ext = (System.IO.Path.GetExtension(filename) ?? "").TrimStart('.');
|
||||
if (!ext.Equals(encryption?.FilenameExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Check if the file is not encrypted
|
||||
if (DynamicLoader.CompressionLoader.Keys.Contains(ext, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (encryption != null)
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", guessing that it is not encrypted", ext, Context.Options.EncryptionModule);
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", guessing that it is not encrypted", ext, options.EncryptionModule);
|
||||
return null;
|
||||
}
|
||||
// Check if the file is encrypted with something else
|
||||
else if (DynamicLoader.EncryptionLoader.Keys.Contains(ext, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use matching encryption module", ext, Context.Options.EncryptionModule);
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use matching encryption module", ext, options.EncryptionModule);
|
||||
|
||||
try
|
||||
{
|
||||
return DynamicLoader.EncryptionLoader.GetModule(ext, Context.Options.Passphrase, Context.Options.RawOptions)
|
||||
return DynamicLoader.EncryptionLoader.GetModule(ext, options.Passphrase, options.RawOptions)
|
||||
?? encryption;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log.WriteWarningMessage(LOGTAG, "AutomaticDecryptionDetection", ex, "Failed to load encryption module \"{0}\", using specified encryption module \"{1}\"", ext, Context.Options.EncryptionModule);
|
||||
Logging.Log.WriteWarningMessage(LOGTAG, "AutomaticDecryptionDetection", ex, "Failed to load encryption module \"{0}\", using specified encryption module \"{1}\"", ext, options.EncryptionModule);
|
||||
}
|
||||
}
|
||||
// Fallback, lets see what happens...
|
||||
else
|
||||
{
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use specified encryption module as no others match", ext, Context.Options.EncryptionModule);
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use specified encryption module as no others match", ext, options.EncryptionModule);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -213,7 +208,7 @@ partial class BackendManager
|
||||
/// <param name="tempFile">The encrypted file</param>
|
||||
/// <param name="decrypter">Then encryption module to use, or <c>null</c> for no encryption</param>
|
||||
/// <returns>The decrypted file</returns>
|
||||
private TempFile DecryptFile(TempFile tempFile, IEncryption? decrypter)
|
||||
private static TempFile DecryptFile(TempFile tempFile, IEncryption? decrypter)
|
||||
{
|
||||
// Support no encryption
|
||||
if (decrypter == null)
|
||||
@@ -244,5 +239,22 @@ partial class BackendManager
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a file using the specified options
|
||||
/// </summary>
|
||||
/// <param name="tmpfile">The file to decrypt</param>
|
||||
/// <param name="filename">The name of the file. Used for detecting encryption algorithm if not specified in options or if it differs from the options</param>
|
||||
/// <param name="options">The Duplicati options</param>
|
||||
/// <returns>The decrypted file</returns>
|
||||
public static TempFile DecryptFile(TempFile tmpfile, string filename, Options options)
|
||||
{
|
||||
using var encryption = options.NoEncryption
|
||||
? null
|
||||
: (DynamicLoader.EncryptionLoader.GetModule(options.EncryptionModule, options.Passphrase, options.RawOptions)
|
||||
?? throw new Exception(Strings.BackendMananger.EncryptionModuleNotFound(options.EncryptionModule))
|
||||
);
|
||||
return DecryptFile(tmpfile, DetectEncryptionModule(filename, options, encryption));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -139,6 +139,18 @@ internal partial class BackendManager : IBackendManager
|
||||
return Convert.ToBase64String(hasher.ComputeHash(fs));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts a file using the specified options
|
||||
/// </summary>
|
||||
/// <param name="tmpfile">The file to decrypt</param>
|
||||
/// <param name="filename">The name of the file. Used for detecting encryption algorithm if not specified in options or if it differs from the options</param>
|
||||
/// <param name="options">The Duplicati options</param>
|
||||
/// <returns>The decrypted file</returns>
|
||||
public TempFile DecryptFile(TempFile volume, string volume_name, Options options)
|
||||
{
|
||||
return GetOperation.DecryptFile(volume, volume_name, options);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a remote file
|
||||
/// </summary>
|
||||
|
||||
@@ -54,6 +54,15 @@ internal interface IBackendManager : IDisposable
|
||||
/// <returns>An enumerable of file entries</returns>
|
||||
Task<IEnumerable<IFileEntry>> ListAsync(CancellationToken cancelToken);
|
||||
|
||||
/// <summary>
|
||||
/// Decrypts the given file and returns the decrypted file
|
||||
/// </summary>
|
||||
/// <param name="volume">The file to decrypt</param>
|
||||
/// <param name="volume_name">The name of the file. Used for detecting encryption algorithm if not specified in options or if it differs from the options</param>
|
||||
/// <param name="options">The Duplicati options</param>
|
||||
/// <returns>The decrypted file</returns>
|
||||
TempFile DecryptFile(TempFile volume, string volume_name, Options options);
|
||||
|
||||
/// <summary>
|
||||
/// Deletes a file on the backend
|
||||
/// </summary>
|
||||
|
||||
@@ -43,7 +43,7 @@ namespace Duplicati.Library.Main.Operation.Restore
|
||||
/// Runs the volume decryptor process.
|
||||
/// </summary>
|
||||
/// <param name="options">The restore options.</param>
|
||||
public static Task Run(Channels channels, Options options)
|
||||
public static Task Run(Channels channels, IBackendManager backend, Options options)
|
||||
{
|
||||
return AutomationExtensions.RunTask(
|
||||
new
|
||||
@@ -58,13 +58,6 @@ namespace Duplicati.Library.Main.Operation.Restore
|
||||
Stopwatch sw_decrypt = options.InternalProfiling ? new() : null;
|
||||
try
|
||||
{
|
||||
// Taken from BackendManager.GetOperation
|
||||
using var encryption = options.NoEncryption
|
||||
? null
|
||||
: (DynamicLoader.EncryptionLoader.GetModule(options.EncryptionModule, options.Passphrase, options.RawOptions)
|
||||
?? throw new Exception(Strings.BackendMananger.EncryptionModuleNotFound(options.EncryptionModule))
|
||||
);
|
||||
|
||||
while (true)
|
||||
{
|
||||
// Get the block request and volume from the `VolumeDownloader` process.
|
||||
@@ -73,7 +66,7 @@ namespace Duplicati.Library.Main.Operation.Restore
|
||||
sw_read?.Stop();
|
||||
|
||||
sw_decrypt?.Start();
|
||||
var tmpfile = DecryptFile(volume, DetectEncryptionModule(volume_name, options, encryption));
|
||||
var tmpfile = backend.DecryptFile(volume, volume_name, options);
|
||||
var bvr = new BlockVolumeReader(options.CompressionModule, tmpfile, options);
|
||||
sw_decrypt?.Stop();
|
||||
|
||||
@@ -99,83 +92,6 @@ namespace Duplicati.Library.Main.Operation.Restore
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
// Taken from BackendManager.GetOperation
|
||||
public static Library.Utility.TempFile DecryptFile(Library.Utility.TempFile tempFile, Interface.IEncryption? decrypter)
|
||||
{
|
||||
// Support no encryption
|
||||
if (decrypter == null)
|
||||
return tempFile;
|
||||
|
||||
Library.Utility.TempFile? decryptTarget = null;
|
||||
|
||||
// Always dispose the source file
|
||||
using (tempFile)
|
||||
using (new Logging.Timer(LOGTAG, "DecryptFile", "Decrypting " + tempFile))
|
||||
{
|
||||
try
|
||||
{
|
||||
decryptTarget = new Library.Utility.TempFile();
|
||||
try { decrypter.Decrypt(tempFile, decryptTarget); }
|
||||
// If we fail here, make sure that we throw a crypto exception
|
||||
catch (System.Security.Cryptography.CryptographicException) { throw; }
|
||||
catch (Exception ex) { throw new System.Security.Cryptography.CryptographicException(ex.Message, ex); }
|
||||
|
||||
var result = decryptTarget;
|
||||
decryptTarget = null;
|
||||
return result;
|
||||
}
|
||||
finally
|
||||
{
|
||||
// Remove temp files on failure
|
||||
decryptTarget?.Dispose();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private static Interface.IEncryption? DetectEncryptionModule(string remotefilename, Options options, Interface.IEncryption? encryption)
|
||||
{
|
||||
try
|
||||
{
|
||||
// Auto-guess the encryption module
|
||||
var ext = (System.IO.Path.GetExtension(remotefilename) ?? "").TrimStart('.');
|
||||
if (!ext.Equals(encryption?.FilenameExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// Check if the file is not encrypted
|
||||
if (DynamicLoader.CompressionLoader.Keys.Contains(ext, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
if (encryption != null)
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", guessing that it is not encrypted", ext, options.EncryptionModule);
|
||||
return null;
|
||||
}
|
||||
// Check if the file is encrypted with something else
|
||||
else if (DynamicLoader.EncryptionLoader.Keys.Contains(ext, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use matching encryption module", ext, options.EncryptionModule);
|
||||
|
||||
try
|
||||
{
|
||||
return DynamicLoader.EncryptionLoader.GetModule(ext, options.Passphrase, options.RawOptions)
|
||||
?? encryption;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logging.Log.WriteWarningMessage(LOGTAG, "AutomaticDecryptionDetection", ex, "Failed to load encryption module \"{0}\", using specified encryption module \"{1}\"", ext, options.EncryptionModule);
|
||||
}
|
||||
}
|
||||
// Fallback, lets see what happens...
|
||||
else
|
||||
{
|
||||
Logging.Log.WriteVerboseMessage(LOGTAG, "AutomaticDecryptionDetection", "Filename extension \"{0}\" does not match encryption module \"{1}\", attempting to use specified encryption module as no others match", ext, options.EncryptionModule);
|
||||
}
|
||||
}
|
||||
|
||||
return encryption;
|
||||
}
|
||||
// If we fail here, make sure that we throw a crypto exception
|
||||
catch (System.Security.Cryptography.CryptographicException) { throw; }
|
||||
catch (Exception ex) { throw new System.Security.Cryptography.CryptographicException(ex.Message, ex); }
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user