diff --git a/src/modules/fstab/main.py b/src/modules/fstab/main.py index 1cfb5e660..95f10a643 100755 --- a/src/modules/fstab/main.py +++ b/src/modules/fstab/main.py @@ -162,13 +162,18 @@ class FstabGenerator(object): crypttab_options = self.crypttab_options # Set crypttab password for partition to none and remove crypttab options + # if crypto_keyfile.bin was not generated + if not os.path.exists(os.path.join(self.root_mount_point, "crypto_keyfile.bin")): + password = "none" + crypttab_options = "" # on root partition when /boot is unencrypted - if partition["mountPoint"] == "/": + elif partition["mountPoint"] == "/": if any([p["mountPoint"] == "/boot" and "luksMapperName" not in p for p in self.partitions]): password = "none" crypttab_options = "" + return dict( name=mapper_name, diff --git a/src/modules/partition/Config.cpp b/src/modules/partition/Config.cpp index 550e17460..367c4ee38 100644 --- a/src/modules/partition/Config.cpp +++ b/src/modules/partition/Config.cpp @@ -251,7 +251,9 @@ fillGSConfigurationEFI( Calamares::GlobalStorage* gs, const QVariantMap& configu gs->insert( "efiSystemPartitionSize", sizeString ); gs->insert( "efiSystemPartitionSize_i", part_size.toBytes() ); - if ( part_size.toBytes() != PartUtils::efiFilesystemMinimumSize() ) + // Assign long long int to long unsigned int to prevent compilation warning + size_t unsigned_part_size = part_size.toBytes(); + if ( unsigned_part_size != PartUtils::efiFilesystemMinimumSize() ) { cWarning() << "EFI partition size" << sizeString << "has been adjusted to" << PartUtils::efiFilesystemMinimumSize() << "bytes"; diff --git a/src/modules/partition/core/KPMHelpers.cpp b/src/modules/partition/core/KPMHelpers.cpp index d5086ef21..003d47088 100644 --- a/src/modules/partition/core/KPMHelpers.cpp +++ b/src/modules/partition/core/KPMHelpers.cpp @@ -22,128 +22,210 @@ #include #include #include +#include +#include using CalamaresUtils::Partition::PartitionIterator; namespace KPMHelpers { -Partition* -findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ) -{ - for ( auto device : devices ) - for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) - if ( PartitionInfo::mountPoint( *it ) == mountPoint ) - { - return *it; - } - return nullptr; -} - - -Partition* -createNewPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - PartitionTable::Flags flags ) -{ - FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector, device.logicalSize() ); - fs->setLabel( fsLabel ); - return new Partition( parent, - device, - role, - fs, - fs->firstSector(), - fs->lastSector(), - QString() /* path */, - KPM_PARTITION_FLAG( None ) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - flags /* activeFlags */, - KPM_PARTITION_STATE( New ) ); -} - - -Partition* -createNewEncryptedPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - const QString& passphrase, - PartitionTable::Flags flags ) -{ - PartitionRole::Roles newRoles = role.roles(); - if ( !role.has( PartitionRole::Luks ) ) + Partition* + findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ) { - newRoles |= PartitionRole::Luks; - } - - FS::luks* fs = dynamic_cast< FS::luks* >( - FileSystemFactory::create( FileSystem::Luks, firstSector, lastSector, device.logicalSize() ) ); - if ( !fs ) - { - cError() << "cannot create LUKS filesystem. Giving up."; + for ( auto device : devices ) + for ( auto it = PartitionIterator::begin( device ); it != PartitionIterator::end( device ); ++it ) + if ( PartitionInfo::mountPoint( *it ) == mountPoint ) + { + return *it; + } return nullptr; } - fs->createInnerFileSystem( fsType ); - fs->setPassphrase( passphrase ); - fs->setLabel( fsLabel ); - Partition* p = new Partition( parent, - device, - PartitionRole( newRoles ), - fs, - fs->firstSector(), - fs->lastSector(), - QString() /* path */, - KPM_PARTITION_FLAG( None ) /* availableFlags */, - QString() /* mountPoint */, - false /* mounted */, - flags /* activeFlags */, - KPM_PARTITION_STATE( New ) ); - return p; -} - -Partition* -clonePartition( Device* device, Partition* partition ) -{ - FileSystem* fs = FileSystemFactory::create( - partition->fileSystem().type(), partition->firstSector(), partition->lastSector(), device->logicalSize() ); - return new Partition( partition->parent(), - *device, - partition->roles(), - fs, - fs->firstSector(), - fs->lastSector(), - partition->partitionPath(), - partition->activeFlags() ); -} - -Calamares::JobResult -execute( Operation& operation, const QString& failureMessage ) -{ - operation.setStatus( Operation::StatusRunning ); - - Report report( nullptr ); - if ( operation.execute( report ) ) + Partition* + createNewPartition( PartitionNode* parent, + const Device& device, + const PartitionRole& role, + FileSystem::Type fsType, + const QString& fsLabel, + qint64 firstSector, + qint64 lastSector, + PartitionTable::Flags flags ) { - return Calamares::JobResult::ok(); + FileSystem* fs = FileSystemFactory::create( fsType, firstSector, lastSector, device.logicalSize() ); + fs->setLabel( fsLabel ); + return new Partition( parent, + device, + role, + fs, + fs->firstSector(), + fs->lastSector(), + QString() /* path */, + KPM_PARTITION_FLAG( None ) /* availableFlags */, + QString() /* mountPoint */, + false /* mounted */, + flags /* activeFlags */, + KPM_PARTITION_STATE( New ) ); } - // Remove the === lines from the report by trimming them to empty - QStringList l = report.toText().split( '\n' ); - std::for_each( l.begin(), l.end(), []( QString& s ) { CalamaresUtils::removeLeading( s, '=' ); } ); - return Calamares::JobResult::error( failureMessage, l.join( '\n' ) ); -} + Partition* + createNewEncryptedPartition( PartitionNode* parent, + const Device& device, + const PartitionRole& role, + FileSystem::Type fsType, + const QString& fsLabel, + qint64 firstSector, + qint64 lastSector, + const QString& passphrase, + PartitionTable::Flags flags ) + { + PartitionRole::Roles newRoles = role.roles(); + if ( !role.has( PartitionRole::Luks ) ) + { + newRoles |= PartitionRole::Luks; + } + + FS::luks* fs = dynamic_cast< FS::luks* >( + FileSystemFactory::create( FileSystem::Luks, firstSector, lastSector, device.logicalSize() ) ); + if ( !fs ) + { + cError() << "cannot create LUKS filesystem. Giving up."; + return nullptr; + } + + fs->createInnerFileSystem( fsType ); + fs->setPassphrase( passphrase ); + fs->setLabel( fsLabel ); + Partition* p = new Partition( parent, + device, + PartitionRole( newRoles ), + fs, + fs->firstSector(), + fs->lastSector(), + QString() /* path */, + KPM_PARTITION_FLAG( None ) /* availableFlags */, + QString() /* mountPoint */, + false /* mounted */, + flags /* activeFlags */, + KPM_PARTITION_STATE( New ) ); + return p; + } + + + Partition* + clonePartition( Device* device, Partition* partition ) + { + FileSystem* fs = FileSystemFactory::create( + partition->fileSystem().type(), partition->firstSector(), partition->lastSector(), device->logicalSize() ); + return new Partition( partition->parent(), + *device, + partition->roles(), + fs, + fs->firstSector(), + fs->lastSector(), + partition->partitionPath(), + partition->activeFlags() ); + } + + // Adapted from luks cryptOpen which always opens a dialog to ask for a passphrase + int + updateLuksDevice( Partition* partition, const QString& passphrase ) + { + const QString deviceNode = partition->partitionPath(); + + cDebug() << "Update Luks device: " << deviceNode; + + if ( passphrase.isEmpty() ) + { + cWarning() << Logger::SubEntry << "#1: Passphrase is empty"; + return 1; + } + + if ( partition->fileSystem().type() != FileSystem::Luks ) + { + cWarning() << Logger::SubEntry << "#2: Not a luks encrypted device"; + return 2; + } + + // Cast partition fs to luks fs + FS::luks* luksFs = dynamic_cast< FS::luks* >( &partition->fileSystem() ); + + // Test the given passphrase + if ( !luksFs->testPassphrase( deviceNode, passphrase ) ) + { + cWarning() << Logger::SubEntry << "#3: Passphrase incorrect"; + return 3; + } + + if ( luksFs->isCryptOpen() ) + { + if ( !luksFs->mapperName().isEmpty()) + { + cWarning() << Logger::SubEntry << "#4: Device already decrypted"; + return 4; + } + else + { + cDebug() << Logger::SubEntry << "No mapper node found"; + luksFs->setCryptOpen( false ); + } + } + + ExternalCommand openCmd( QStringLiteral( "cryptsetup" ), + { 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"; + return openCmd.exitCode(); + } + + // Save the existing passphrase + luksFs->setPassphrase( passphrase ); + + luksFs->scan( deviceNode ); + + if ( luksFs->mapperName().isEmpty() ) + { + cWarning() << Logger::SubEntry << "#5: No mapper node found"; + return 5; + } + + luksFs->loadInnerFileSystem( luksFs->mapperName() ); + luksFs->setCryptOpen( luksFs->innerFS() != nullptr ); + + if ( !luksFs->isCryptOpen() ) + { + cWarning() << Logger::SubEntry << "#6: Device could not be decrypted"; + return 6; + } + + return 0; + } + + Calamares::JobResult + execute( Operation& operation, const QString& failureMessage ) + { + operation.setStatus( Operation::StatusRunning ); + + Report report( nullptr ); + if ( operation.execute( report ) ) + { + return Calamares::JobResult::ok(); + } + + // Remove the === lines from the report by trimming them to empty + QStringList l = report.toText().split( '\n' ); + std::for_each( l.begin(), l.end(), []( QString& s ) { CalamaresUtils::removeLeading( s, '=' ); } ); + + return Calamares::JobResult::error( failureMessage, l.join( '\n' ) ); + } } // namespace KPMHelpers diff --git a/src/modules/partition/core/KPMHelpers.h b/src/modules/partition/core/KPMHelpers.h index 2f867bc25..b958b3866 100644 --- a/src/modules/partition/core/KPMHelpers.h +++ b/src/modules/partition/core/KPMHelpers.h @@ -43,54 +43,56 @@ class PartitionRole; namespace KPMHelpers { -/** - * Iterates on all devices and return the first partition which is associated - * with mountPoint. This uses PartitionInfo::mountPoint(), not Partition::mountPoint() - */ -Partition* findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ); + /** + * Iterates on all devices and return the first partition which is associated + * with mountPoint. This uses PartitionInfo::mountPoint(), not Partition::mountPoint() + */ + Partition* findPartitionByMountPoint( const QList< Device* >& devices, const QString& mountPoint ); -/** - * Helper function to create a new Partition object (does not create anything - * on the disk) associated with a FileSystem. - */ -Partition* createNewPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - PartitionTable::Flags flags ); + /** + * Helper function to create a new Partition object (does not create anything + * on the disk) associated with a FileSystem. + */ + Partition* createNewPartition( PartitionNode* parent, + const Device& device, + const PartitionRole& role, + FileSystem::Type fsType, + const QString& fsLabel, + qint64 firstSector, + qint64 lastSector, + PartitionTable::Flags flags ); -Partition* createNewEncryptedPartition( PartitionNode* parent, - const Device& device, - const PartitionRole& role, - FileSystem::Type fsType, - const QString& fsLabel, - qint64 firstSector, - qint64 lastSector, - const QString& passphrase, - PartitionTable::Flags flags ); + Partition* createNewEncryptedPartition( PartitionNode* parent, + const Device& device, + const PartitionRole& role, + FileSystem::Type fsType, + const QString& fsLabel, + qint64 firstSector, + qint64 lastSector, + const QString& passphrase, + PartitionTable::Flags flags ); -Partition* clonePartition( Device* device, Partition* partition ); + Partition* clonePartition( Device* device, Partition* partition ); -/** @brief Return a result for an @p operation - * - * Executes the operation, and if successful, returns a success result. - * Otherwise returns an error using @p failureMessage as the primary part - * of the error, and details obtained from the operation. - */ -Calamares::JobResult execute( Operation& operation, const QString& failureMessage ); -/** @brief Return a result for an @p operation - * - * It's acceptable to use an rvalue: the operation-running is the effect - * you're interested in, rather than keeping the temporary around. - */ -static inline Calamares::JobResult -execute( Operation&& operation, const QString& failureMessage ) -{ - return execute( operation, failureMessage ); -} + int updateLuksDevice( Partition* partition, const QString& passphrase ); + + /** @brief Return a result for an @p operation + * + * Executes the operation, and if successful, returns a success result. + * Otherwise returns an error using @p failureMessage as the primary part + * of the error, and details obtained from the operation. + */ + Calamares::JobResult execute( Operation& operation, const QString& failureMessage ); + /** @brief Return a result for an @p operation + * + * It's acceptable to use an rvalue: the operation-running is the effect + * you're interested in, rather than keeping the temporary around. + */ + static inline Calamares::JobResult + execute( Operation&& operation, const QString& failureMessage ) + { + return execute( operation, failureMessage ); + } } // namespace KPMHelpers diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.cpp b/src/modules/partition/gui/EditExistingPartitionDialog.cpp index 0bc35cabe..4883edd76 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.cpp +++ b/src/modules/partition/gui/EditExistingPartitionDialog.cpp @@ -20,6 +20,7 @@ #include "core/PartUtils.h" #include "core/PartitionCoreModule.h" #include "core/PartitionInfo.h" +#include "core/KPMHelpers.h" #include "gui/PartitionDialogHelpers.h" #include "gui/PartitionSizeController.h" @@ -28,14 +29,18 @@ #include "Settings.h" #include "partition/FileSystem.h" #include "utils/Logger.h" +#include "widgets/TranslationFix.h" #include #include #include +#include #include #include #include +#include +#include using CalamaresUtils::Partition::untranslatedFS; using CalamaresUtils::Partition::userVisibleFS; @@ -52,6 +57,7 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, , m_usedMountPoints( usedMountPoints ) { m_ui->setupUi( this ); + m_ui->encryptWidget->hide(); standardMountPoints( *( m_ui->mountPointComboBox ), PartitionInfo::mountPoint( partition ) ); QColor color = ColorUtils::colorForPartition( m_partition ); @@ -132,10 +138,8 @@ EditExistingPartitionDialog::EditExistingPartitionDialog( Device* device, setFlagList( *( m_ui->m_listFlags ), m_partition->availableFlags(), PartitionInfo::flags( m_partition ) ); } - EditExistingPartitionDialog::~EditExistingPartitionDialog() {} - PartitionTable::Flags EditExistingPartitionDialog::newFlags() const { @@ -242,8 +246,31 @@ EditExistingPartitionDialog::applyChanges( PartitionCoreModule* core ) { core->setFilesystemLabel( m_device, m_partition, fsLabel ); } + core->refreshPartition( m_device, m_partition ); } + + // Update the existing luks partition + const QString passphrase = m_ui->encryptWidget->passphrase(); + if ( !passphrase.isEmpty() ) + { + int retCode = KPMHelpers::updateLuksDevice( m_partition, passphrase ); + if ( retCode != 0 ) + { + QString message = tr( "Passphrase for existing partition" ); + QString description = tr( "Partition %1 could not be decrypted " + "with the given passphrase." + "

" + "Edit the partition again and give the correct passphrase" + "or delete and create a new encrypted partition." ) + .arg( m_partition->partitionPath() ); + + QMessageBox mb( QMessageBox::Information, message, description, + QMessageBox::Ok, this->parentWidget() ); + Calamares::fixButtonLabels( &mb ); + mb.exec(); + } + } } } @@ -266,7 +293,6 @@ EditExistingPartitionDialog::replacePartResizerWidget() m_partitionSizeController->setPartResizerWidget( widget, m_ui->formatRadioButton->isChecked() ); } - void EditExistingPartitionDialog::updateMountPointPicker() { @@ -293,13 +319,50 @@ EditExistingPartitionDialog::updateMountPointPicker() { setSelectedMountPoint( m_ui->mountPointComboBox, QString() ); } + + toggleEncryptWidget(); + } void EditExistingPartitionDialog::checkMountPointSelection() { - validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ), - m_usedMountPoints, - m_ui->mountPointExplanation, - m_ui->buttonBox->button( QDialogButtonBox::Ok ) ); + if ( validateMountPoint( selectedMountPoint( m_ui->mountPointComboBox ), + m_usedMountPoints, + m_ui->mountPointExplanation, + m_ui->buttonBox->button( QDialogButtonBox::Ok ) ) ) + { + toggleEncryptWidget(); + } +} + +void +EditExistingPartitionDialog::toggleEncryptWidget() +{ + // Show/hide encryptWidget: + // check if partition is a previously luks formatted partition + // and not currently formatted + // and its mount point not a standard mount point except when it's /home + QString mp = selectedMountPoint( m_ui->mountPointComboBox ); + if ( !mp.isEmpty() + && m_partition->fileSystem().type() == FileSystem::Luks + && !m_ui->formatRadioButton->isChecked() + && ( !standardMountPoints().contains(mp) || mp == "/home" ) ) + { + m_ui->encryptWidget->show(); + m_ui->encryptWidget->reset( false ); + } + // TODO: When formatting a partition user must be able to encrypt that partition + // Probably need to delete this partition and create a new one + // else if ( m_ui->formatRadioButton->isChecked() + // && !mp.isEmpty()) + // { + // m_ui->encryptWidget->show(); + // m_ui->encryptWidget->reset(); + // } + else + { + m_ui->encryptWidget->reset(); + m_ui->encryptWidget->hide(); + } } diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.h b/src/modules/partition/gui/EditExistingPartitionDialog.h index 89b5b55e4..a912c577d 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.h +++ b/src/modules/partition/gui/EditExistingPartitionDialog.h @@ -32,6 +32,11 @@ class EditExistingPartitionDialog : public QDialog { Q_OBJECT public: + struct FreeSpace + { + Partition* p; + }; + EditExistingPartitionDialog( Device* device, Partition* partition, const QStringList& usedMountPoints, @@ -53,6 +58,7 @@ private: PartitionTable::Flags newFlags() const; void replacePartResizerWidget(); void updateMountPointPicker(); + void toggleEncryptWidget(); }; #endif /* EDITEXISTINGPARTITIONDIALOG_H */ diff --git a/src/modules/partition/gui/EditExistingPartitionDialog.ui b/src/modules/partition/gui/EditExistingPartitionDialog.ui index 4a9982656..ff9cc33c5 100644 --- a/src/modules/partition/gui/EditExistingPartitionDialog.ui +++ b/src/modules/partition/gui/EditExistingPartitionDialog.ui @@ -10,8 +10,8 @@ SPDX-License-Identifier: GPL-3.0-or-later 0 0 - 450 - 615 + 570 + 689 @@ -97,7 +97,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - + &Mount Point: @@ -107,7 +107,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - + @@ -153,14 +153,14 @@ SPDX-License-Identifier: GPL-3.0-or-later - + Flags: - + true @@ -173,7 +173,7 @@ SPDX-License-Identifier: GPL-3.0-or-later - + Label for the filesystem @@ -183,20 +183,39 @@ SPDX-License-Identifier: GPL-3.0-or-later - + FS Label: - + + + + + + + + Qt::Vertical + + + QSizePolicy::Fixed + + + + 20 + 13 + + + + @@ -218,6 +237,12 @@ SPDX-License-Identifier: GPL-3.0-or-later
kpmcore/gui/partresizerwidget.h
1 + + EncryptWidget + QWidget +
gui/EncryptWidget.h
+ 1 +
sizeSpinBox diff --git a/src/modules/partition/gui/EncryptWidget.cpp b/src/modules/partition/gui/EncryptWidget.cpp index fe7623050..7efe0ea1a 100644 --- a/src/modules/partition/gui/EncryptWidget.cpp +++ b/src/modules/partition/gui/EncryptWidget.cpp @@ -70,14 +70,17 @@ EncryptWidget::EncryptWidget( QWidget* parent ) void -EncryptWidget::reset() +EncryptWidget::reset( bool checkVisible ) { m_ui->m_passphraseLineEdit->clear(); m_ui->m_confirmLineEdit->clear(); m_ui->m_encryptCheckBox->setChecked( false ); -} + m_ui->m_encryptCheckBox->setVisible( checkVisible ); + m_ui->m_passphraseLineEdit->setVisible( !checkVisible ); + m_ui->m_confirmLineEdit->setVisible( !checkVisible ); +} EncryptWidget::Encryption EncryptWidget::state() const @@ -146,7 +149,7 @@ EncryptWidget::updateState() } Encryption newState; - if ( m_ui->m_encryptCheckBox->isChecked() ) + if ( m_ui->m_encryptCheckBox->isChecked() || !m_ui->m_encryptCheckBox->isVisible()) { if ( !m_ui->m_passphraseLineEdit->text().isEmpty() && m_ui->m_passphraseLineEdit->text() == m_ui->m_confirmLineEdit->text() ) diff --git a/src/modules/partition/gui/EncryptWidget.h b/src/modules/partition/gui/EncryptWidget.h index 5c24d68e6..704365817 100644 --- a/src/modules/partition/gui/EncryptWidget.h +++ b/src/modules/partition/gui/EncryptWidget.h @@ -33,7 +33,7 @@ public: explicit EncryptWidget( QWidget* parent = nullptr ); - void reset(); + void reset( bool checkVisible = true ); Encryption state() const; void setText( const QString& text );