diff --git a/settings.conf b/settings.conf index 1818fd918..2f2ff68f9 100644 --- a/settings.conf +++ b/settings.conf @@ -80,6 +80,7 @@ sequence: - localecfg # - luksbootkeyfile # - luksopenswaphookcfg +# - dracutlukscfg # - plymouthcfg - initcpiocfg - initcpio diff --git a/src/modules/dracutlukscfg/CMakeLists.txt b/src/modules/dracutlukscfg/CMakeLists.txt new file mode 100644 index 000000000..a239521dd --- /dev/null +++ b/src/modules/dracutlukscfg/CMakeLists.txt @@ -0,0 +1,9 @@ +calamares_add_plugin( dracutlukscfg + TYPE job + EXPORT_MACRO PLUGINDLLEXPORT_PRO + SOURCES + DracutLuksCfgJob.cpp + LINK_LIBRARIES + calamares + SHARED_LIB +) diff --git a/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp b/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp new file mode 100644 index 000000000..273ff98ae --- /dev/null +++ b/src/modules/dracutlukscfg/DracutLuksCfgJob.cpp @@ -0,0 +1,143 @@ +/* === This file is part of Calamares - === + * + * Copyright 2016, Kevin Kofler + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#include "DracutLuksCfgJob.h" + +#include +#include +#include +#include + +#include "CalamaresVersion.h" +#include "JobQueue.h" +#include "GlobalStorage.h" + +#include "utils/Logger.h" + +// static +const QString DracutLuksCfgJob::CONFIG_FILE = QStringLiteral( "/etc/dracut.conf.d/calamares-luks.conf" ); + +// static +const char *DracutLuksCfgJob::CONFIG_FILE_CONTENTS = + "# Configuration file automatically written by the Calamares system installer\n" + "# (This file is written once at install time and should be safe to edit.)\n" + "# Enables support for LUKS full disk encryption with single sign on from GRUB.\n" + "\n" + "# force installing /etc/crypttab even if hostonly=\"no\", install the keyfile\n" + "install_items+=\" /etc/crypttab /crypto_keyfile.bin \"\n"; + +// static +const QString DracutLuksCfgJob::CONFIG_FILE_SWAPLINE = QStringLiteral( "# enable automatic resume from swap\nadd_device+=\" /dev/disk/by-uuid/%1 \"\n" ); + +// static +QString +DracutLuksCfgJob::rootMountPoint() +{ + Calamares::GlobalStorage *globalStorage = Calamares::JobQueue::instance()->globalStorage(); + return globalStorage->value( QStringLiteral( "rootMountPoint" ) ).toString(); +} + +// static +QVariantList +DracutLuksCfgJob::partitions() +{ + Calamares::GlobalStorage *globalStorage = Calamares::JobQueue::instance()->globalStorage(); + return globalStorage->value( QStringLiteral( "partitions" ) ).toList(); +} + +// static +bool +DracutLuksCfgJob::isRootEncrypted() +{ + const QVariantList partitions = DracutLuksCfgJob::partitions(); + for ( const QVariant &partition : partitions ) + { + QVariantMap partitionMap = partition.toMap(); + QString mountPoint = partitionMap.value( QStringLiteral( "mountPoint" ) ).toString(); + if ( mountPoint == QStringLiteral( "/" ) ) + return partitionMap.contains( QStringLiteral( "luksMapperName" ) ); + } + return false; +} + +// static +QString +DracutLuksCfgJob::swapOuterUuid() +{ + const QVariantList partitions = DracutLuksCfgJob::partitions(); + for ( const QVariant &partition : partitions ) + { + QVariantMap partitionMap = partition.toMap(); + QString fsType = partitionMap.value( QStringLiteral( "fs" ) ).toString(); + if ( fsType == QStringLiteral( "linuxswap" ) && partitionMap.contains( QStringLiteral( "luksMapperName" ) ) ) + return partitionMap.value( QStringLiteral( "luksUuid" ) ).toString(); + } + return QString(); +} + +DracutLuksCfgJob::DracutLuksCfgJob( QObject* parent ) + : Calamares::CppJob( parent ) +{ +} + + +DracutLuksCfgJob::~DracutLuksCfgJob() +{ +} + + +QString +DracutLuksCfgJob::prettyName() const +{ + if ( isRootEncrypted() ) + return tr( "Write LUKS configuration for Dracut to %1" ).arg( CONFIG_FILE ); + else + return tr( "Skip writing LUKS configuration for Dracut: \"/\" partition is not encrypted" ); +} + + +Calamares::JobResult +DracutLuksCfgJob::exec() +{ + if ( isRootEncrypted() ) + { + const QString realConfigFilePath = rootMountPoint() + CONFIG_FILE; + cDebug() << "[DRACUTLUKSCFG]: Writing" << realConfigFilePath; + QDir( QStringLiteral( "/" ) ).mkpath( QFileInfo( realConfigFilePath ).absolutePath() ); + QFile configFile( realConfigFilePath ); + if ( ! configFile.open( QIODevice::WriteOnly | QIODevice::Text ) ) + { + cDebug() << "[DRACUTLUKSCFG]: Failed to open" << realConfigFilePath; + return Calamares::JobResult::error( tr( "Failed to open %1" ).arg( realConfigFilePath ) ); + } + QTextStream outStream( &configFile ); + outStream << CONFIG_FILE_CONTENTS; + const QString swapOuterUuid = DracutLuksCfgJob::swapOuterUuid(); + if ( ! swapOuterUuid.isEmpty() ) + { + cDebug() << "[DRACUTLUKSCFG]: Swap outer UUID" << swapOuterUuid; + outStream << CONFIG_FILE_SWAPLINE.arg( swapOuterUuid ).toLatin1(); + } + cDebug() << "[DRACUTLUKSCFG]: Wrote config to" << realConfigFilePath; + } else + cDebug() << "[DRACUTLUKSCFG]: / not encrypted, skipping"; + + return Calamares::JobResult::ok(); +} + +CALAMARES_PLUGIN_FACTORY_DEFINITION( DracutLuksCfgJobFactory, registerPlugin(); ) diff --git a/src/modules/dracutlukscfg/DracutLuksCfgJob.h b/src/modules/dracutlukscfg/DracutLuksCfgJob.h new file mode 100644 index 000000000..bfedb85cf --- /dev/null +++ b/src/modules/dracutlukscfg/DracutLuksCfgJob.h @@ -0,0 +1,56 @@ +/* === This file is part of Calamares - === + * + * Copyright 2016, Kevin Kofler + * + * Calamares is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * Calamares is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with Calamares. If not, see . + */ + +#ifndef DRACUTLUKSCFGJOB_H +#define DRACUTLUKSCFGJOB_H + +#include +#include + +#include + +#include + +#include + +class PLUGINDLLEXPORT DracutLuksCfgJob : public Calamares::CppJob +{ + Q_OBJECT + +public: + explicit DracutLuksCfgJob( QObject* parent = nullptr ); + virtual ~DracutLuksCfgJob(); + + QString prettyName() const override; + + Calamares::JobResult exec() override; + +private: + static const QString CONFIG_FILE; + static const char *CONFIG_FILE_CONTENTS; + static const QString CONFIG_FILE_SWAPLINE; + + static QString rootMountPoint(); + static QVariantList partitions(); + static bool isRootEncrypted(); + static QString swapOuterUuid(); +}; + +CALAMARES_PLUGIN_FACTORY_DECLARATION( DracutLuksCfgJobFactory ) + +#endif // DRACUTLUKSCFGJOB_H diff --git a/src/modules/dracutlukscfg/module.desc b/src/modules/dracutlukscfg/module.desc new file mode 100644 index 000000000..10d9b78a9 --- /dev/null +++ b/src/modules/dracutlukscfg/module.desc @@ -0,0 +1,7 @@ +# Module metadata file for dracutlukscfg job +# Syntax is YAML 1.2 +--- +type: "job" +name: "dracutlukscfg" +interface: "qtplugin" +load: "libcalamares_job_dracutlukscfg.so"