diff --git a/src/modules/machineid/MachineIdJob.cpp b/src/modules/machineid/MachineIdJob.cpp index 00149793c..37df5ef34 100644 --- a/src/modules/machineid/MachineIdJob.cpp +++ b/src/modules/machineid/MachineIdJob.cpp @@ -52,12 +52,29 @@ removeFile( const QString& rootMountPoint, const QString& fileName ) QFile::remove( rootMountPoint + fileName ); } +/// @brief Copy @p fileName from host into target system at @p rootMountPoint +static Calamares::JobResult +copyFile( const QString& rootMountPoint, const QString& fileName ) +{ + QFile f( fileName ); + if ( !f.exists() ) + { + return Calamares::JobResult::error( QObject::tr( "File not found" ), fileName ); + } + if ( !f.copy( rootMountPoint + fileName ) ) + { + return Calamares::JobResult::error( QObject::tr( "File not found" ), rootMountPoint + fileName ); + } + return Calamares::JobResult::ok(); +} + /// @brief How to generate entropy (bool-like) enum class EntropyGeneration { New, CopyFromHost }; + /// @brief How to create the DBus machine-id (bool-like) enum class DBusGeneration { @@ -65,10 +82,92 @@ enum class DBusGeneration SymlinkFromSystemD }; +static int +getUrandomPoolSize() +{ + QFile f( "/proc/sys/kernel/random/poolsize" ); + constexpr const int minimumPoolSize = 512; + int poolSize = minimumPoolSize; + + if ( f.exists() && f.open( QIODevice::ReadOnly | QIODevice::Text ) ) + { + QByteArray v = f.read( 16 ); + if ( v.length() > 2 ) + { + bool ok = false; + poolSize = v.toInt( &ok ); + if ( !ok ) + { + poolSize = minimumPoolSize; + } + } + } + return poolSize >= minimumPoolSize ? poolSize : minimumPoolSize; +} + +static Calamares::JobResult +createNewEntropy( int poolSize, const QString& rootMountPoint, const QString& fileName ) +{ + QFile urandom( "/dev/urandom" ); + if ( urandom.exists() && urandom.open( QIODevice::ReadOnly ) ) + { + QByteArray data = urandom.read( poolSize ); + urandom.close(); + + QFile entropyFile( rootMountPoint + fileName ); + if ( entropyFile.exists() ) + { + cWarning() << "Entropy file" << ( rootMountPoint + fileName ) << "already exists."; + return Calamares::JobResult::ok(); // .. anyway + } + if ( !entropyFile.open( QIODevice::WriteOnly ) ) + { + return Calamares::JobResult::error( + QObject::tr( "File not found" ), + QObject::tr( "Could not create new random file
%1." ).arg( fileName ) ); + } + entropyFile.write( data ); + entropyFile.close(); + if ( entropyFile.size() < data.length() ) + { + cWarning() << "Entropy file is" << entropyFile.size() << "bytes, random data was" << data.length(); + } + if ( data.length() < poolSize ) + { + cWarning() << "Entropy data is" << data.length() << "bytes, rather than poolSize" << poolSize; + } + } + return Calamares::JobResult::error( + QObject::tr( "File not found" ), + QObject::tr( "Could not read random file
%1." ).arg( QStringLiteral( "/dev/urandom" ) ) ); +} + + static Calamares::JobResult createEntropy( const EntropyGeneration kind, const QString& rootMountPoint, const QString& fileName ) { - return Calamares::JobResult::internalError( QObject::tr( "Internal Error" ), QObject::tr( "Not implemented" ), 0 ); + if ( kind == EntropyGeneration::CopyFromHost ) + { + if ( QFile::exists( fileName ) ) + { + auto r = copyFile( rootMountPoint, fileName ); + if ( r ) + { + return r; + } + else + { + cWarning() << "Could not copy" << fileName << "for entropy, generating new."; + } + } + else + { + cWarning() << "Host system entropy does not exist at" << fileName; + } + } + + int poolSize = getUrandomPoolSize(); + return createNewEntropy( poolSize, rootMountPoint, fileName ); } static Calamares::JobResult