Merge pull request #1979 from abalfoort/issue-1963

FIXES #1963 : label encrypted partitions
This commit is contained in:
Adriaan de Groot 2022-06-09 09:17:22 +02:00 committed by GitHub
commit 4d10629acf
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 159 additions and 20 deletions

View File

@ -25,6 +25,8 @@
#include <kpmcore/fs/luks.h> #include <kpmcore/fs/luks.h>
#include <kpmcore/util/externalcommand.h> #include <kpmcore/util/externalcommand.h>
#include <qregularexpression.h>
using CalamaresUtils::Partition::PartitionIterator; using CalamaresUtils::Partition::PartitionIterator;
namespace KPMHelpers namespace KPMHelpers
@ -133,7 +135,6 @@ clonePartition( Device* device, Partition* partition )
partition->activeFlags() ); partition->activeFlags() );
} }
// Adapted from src/fs/luks.cpp cryptOpen which always opens a dialog to ask for a passphrase
SavePassphraseValue SavePassphraseValue
savePassphrase( Partition* partition, const QString& passphrase ) savePassphrase( Partition* partition, const QString& passphrase )
{ {
@ -143,57 +144,161 @@ savePassphrase( Partition* partition, const QString& passphrase )
return SavePassphraseValue::EmptyPassphrase; return SavePassphraseValue::EmptyPassphrase;
} }
if ( partition->fileSystem().type() != FileSystem::Luks ) FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() );
if ( luksFs == nullptr )
{ {
// No luks device
return SavePassphraseValue::NotLuksPartition; return SavePassphraseValue::NotLuksPartition;
} }
FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() );
const QString deviceNode = partition->partitionPath();
// Test the given passphrase // Test the given passphrase
if ( !luksFs->testPassphrase( deviceNode, passphrase ) ) if ( !luksFs->testPassphrase( partition->partitionPath(), passphrase ) )
{
// Save the existing passphrase
luksFs->setPassphrase( passphrase );
}
else
{ {
return SavePassphraseValue::IncorrectPassphrase; return SavePassphraseValue::IncorrectPassphrase;
} }
return SavePassphraseValue::NoError;
}
// Adapted from src/fs/luks.cpp cryptOpen which always opens a dialog to ask for a passphrase
QString
cryptOpen( Partition* partition )
{
FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() );
if ( luksFs == nullptr )
{
// No luks device
return QString();
}
if ( luksFs->isCryptOpen() ) if ( luksFs->isCryptOpen() )
{ {
if ( !luksFs->mapperName().isEmpty() ) if ( !luksFs->mapperName().isEmpty() )
{ {
return SavePassphraseValue::NoError; // Already decrypted
return luksFs->mapperName();
} }
else else
{ {
cDebug() << Logger::SubEntry << "No mapper node found"; cDebug() << Logger::SubEntry << "No mapper node found - reset cryptOpen";
luksFs->setCryptOpen( false ); luksFs->setCryptOpen( false );
} }
} }
ExternalCommand openCmd( QStringLiteral( "cryptsetup" ), if ( luksFs->passphrase().isEmpty() )
{ QStringLiteral( "open" ), deviceNode, luksFs->suggestedMapperName( deviceNode ) } );
if ( !( openCmd.write( passphrase.toLocal8Bit() + '\n' ) && openCmd.start( -1 ) && openCmd.exitCode() == 0 ) )
{ {
cWarning() << Logger::SubEntry << openCmd.exitCode() << ": cryptsetup command failed"; // No passphrase for decryption
return SavePassphraseValue::CryptsetupError; return QString();
} }
// Save the existing passphrase // Decrypt the partition
luksFs->setPassphrase( passphrase ); const QString deviceNode = partition->partitionPath();
ExternalCommand openCmd( QStringLiteral( "cryptsetup" ),
{ QStringLiteral( "open" ), deviceNode, luksFs->suggestedMapperName( deviceNode ) } );
if ( ( openCmd.write( luksFs->passphrase().toLocal8Bit() + '\n' ) && openCmd.start( -1 ) && openCmd.exitCode() == 0 ) )
{
luksFs->scan( deviceNode ); luksFs->scan( deviceNode );
if ( luksFs->mapperName().isEmpty() ) if ( luksFs->mapperName().isEmpty() )
{ {
return SavePassphraseValue::NoMapperNode; return QString();
} }
luksFs->loadInnerFileSystem( luksFs->mapperName() ); luksFs->loadInnerFileSystem( luksFs->mapperName() );
luksFs->setCryptOpen( luksFs->innerFS() != nullptr ); luksFs->setCryptOpen( luksFs->innerFS() != nullptr );
if ( !luksFs->isCryptOpen() ) if ( !luksFs->isCryptOpen() )
{ {
return SavePassphraseValue::DeviceNotDecrypted; return QString();
}
return luksFs->mapperName();
}
return QString();
}
void
cryptClose( Partition* partition )
{
FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() );
if ( luksFs == nullptr )
{
// No luks device
return;
} }
return SavePassphraseValue::NoError; if ( luksFs->mapperName().isEmpty() )
{
// Not opened
return;
}
// Close the partition
luksFs->cryptClose( partition->partitionPath() );
}
bool
cryptLabel( Partition* partition, const QString& label )
{
int version = cryptVersion( partition );
if ( version == 0 || label.isEmpty() )
{
return false;
}
if ( version == 1 )
{
QString mappedDevice = cryptOpen( partition );
if ( !mappedDevice.isEmpty() )
{
// Label mapped device
ExternalCommand openCmd( QStringLiteral( "e2label" ),
{ mappedDevice,
label } );
openCmd.start( -1 );
cryptClose( partition );
return true;
}
}
else
{
ExternalCommand openCmd( QStringLiteral( "cryptsetup" ),
{ QStringLiteral( "config" ),
partition->partitionPath(),
QStringLiteral( "--label" ),
label } );
if ( openCmd.start( -1 ) && openCmd.exitCode() == 0 )
{
return true;
}
}
return false;
}
int
cryptVersion( Partition* partition )
{
if ( partition->fileSystem().type() != FileSystem::Luks )
{
return 0;
}
// Get luks version from header information
int luksVersion = 1;
ExternalCommand openCmd( QStringLiteral( "cryptsetup" ),
{ QStringLiteral( "luksDump" ),
partition->partitionPath() } );
if ( openCmd.start( -1 ) && openCmd.exitCode() == 0 )
{
QRegularExpression re( QStringLiteral( R"(version:\s+(\d))" ),
QRegularExpression::CaseInsensitiveOption );
QRegularExpressionMatch rem = re.match( openCmd.output() );
if ( rem.hasMatch() )
{
luksVersion = rem.captured( 1 ).toInt();
}
}
return luksVersion;
} }
Calamares::JobResult Calamares::JobResult

View File

@ -98,6 +98,27 @@ Partition* clonePartition( Device* device, Partition* partition );
*/ */
SavePassphraseValue savePassphrase( Partition* partition, const QString& passphrase ); SavePassphraseValue savePassphrase( Partition* partition, const QString& passphrase );
/** @brief Decrypt an encrypted partition.
*
* Uses @p partition to decrypt the partition.
* The passphrase saved in @p partition is used.
* Returns the mapped device path or an empty string if it fails.
*/
QString cryptOpen( Partition* partition );
void cryptClose( Partition* partition );
/** @brief Set label of luks encrypted partition.
*
* Returns true on success or false if it fails.
*/
bool cryptLabel( Partition* partition, const QString& label );
/** @brief Returns the luks version used to encrypt the partition.
*
* Used by cryptLabel
*/
int cryptVersion( Partition* partition );
/** @brief Return a result for an @p operation /** @brief Return a result for an @p operation
* *
* Executes the operation, and if successful, returns a success result. * Executes the operation, and if successful, returns a success result.

View File

@ -9,6 +9,8 @@
#include "ChangeFilesystemLabelJob.h" #include "ChangeFilesystemLabelJob.h"
#include "core/KPMHelpers.h"
#include "utils/Logger.h" #include "utils/Logger.h"
#include <kpmcore/backend/corebackend.h> #include <kpmcore/backend/corebackend.h>
@ -58,6 +60,17 @@ ChangeFilesystemLabelJob::exec()
return Calamares::JobResult::ok(); return Calamares::JobResult::ok();
} }
// Check for luks device
if ( partition()->fileSystem().type() == FileSystem::Luks )
{
if ( KPMHelpers::cryptLabel( partition(), m_label ) )
{
return Calamares::JobResult::ok();
}
return Calamares::JobResult::error(
tr( "The installer failed to update partition table on disk '%1'." ).arg( m_device->name() ) );
}
Report report( nullptr ); Report report( nullptr );
SetFileSystemLabelOperation op( *partition(), m_label ); SetFileSystemLabelOperation op( *partition(), m_label );
op.setStatus( Operation::StatusRunning ); op.setStatus( Operation::StatusRunning );