1 /* === This file is part of Calamares - <https://calamares.io> ===
2 *
3 * SPDX-FileCopyrightText: 2014 Kevin Kofler <kevin.kofler@chello.at>
4 * SPDX-FileCopyrightText: 2016 Philip Müller <philm@manjaro.org>
5 * SPDX-FileCopyrightText: 2017 Alf Gaida <agaida@siduction.org>
6 * SPDX-FileCopyrightText: 2019-2020 Adriaan de Groot <groot@kde.org>
7 * SPDX-License-Identifier: GPL-3.0-or-later
8 *
9 * Calamares is Free Software: see the License-Identifier above.
10 *
11 */
12
13 #include "Workers.h"
14
15 #include "utils/CalamaresUtilsSystem.h"
16 #include "utils/Entropy.h"
17 #include "utils/Logger.h"
18
19 #include <QFile>
20
21 /// @brief Returns a recommended size for the entropy pool (in bytes)
22 STATICTEST int
getUrandomPoolSize()23 getUrandomPoolSize()
24 {
25 QFile f( "/proc/sys/kernel/random/poolsize" );
26 constexpr const int minimumPoolSize = 512;
27 int poolSize = minimumPoolSize;
28
29 if ( f.exists() && f.open( QIODevice::ReadOnly | QIODevice::Text ) )
30 {
31 QByteArray v = f.read( 16 );
32 if ( v.length() > 2 )
33 {
34 if ( v.endsWith( '\n' ) )
35 {
36 v.chop( 1 );
37 }
38 bool ok = false;
39 poolSize = v.toInt( &ok );
40 if ( !ok )
41 {
42 poolSize = minimumPoolSize;
43 }
44 }
45 }
46 return ( poolSize >= minimumPoolSize ) ? poolSize : minimumPoolSize;
47 }
48
49 namespace MachineId
50 {
51
52 static inline bool
isAbsolutePath(const QString & fileName)53 isAbsolutePath( const QString& fileName )
54 {
55 return fileName.startsWith( '/' );
56 }
57
58 Calamares::JobResult
copyFile(const QString & rootMountPoint,const QString & fileName)59 copyFile( const QString& rootMountPoint, const QString& fileName )
60 {
61 if ( !isAbsolutePath( fileName ) )
62 {
63 return Calamares::JobResult::internalError(
64 QObject::tr( "File not found" ),
65 QObject::tr( "Path <pre>%1</pre> must be an absolute path." ).arg( fileName ),
66 0 );
67 }
68
69 QFile f( fileName );
70 if ( !f.exists() )
71 {
72 return Calamares::JobResult::error( QObject::tr( "File not found" ), fileName );
73 }
74 if ( !f.copy( rootMountPoint + fileName ) )
75 {
76 return Calamares::JobResult::error( QObject::tr( "File not found" ), rootMountPoint + fileName );
77 }
78 return Calamares::JobResult::ok();
79 }
80
81 Calamares::JobResult
createNewEntropy(int poolSize,const QString & rootMountPoint,const QString & fileName)82 createNewEntropy( int poolSize, const QString& rootMountPoint, const QString& fileName )
83 {
84 QFile entropyFile( rootMountPoint + fileName );
85 if ( entropyFile.exists() )
86 {
87 cWarning() << "Entropy file" << ( rootMountPoint + fileName ) << "already exists.";
88 return Calamares::JobResult::ok(); // .. anyway
89 }
90 if ( !entropyFile.open( QIODevice::WriteOnly ) )
91 {
92 return Calamares::JobResult::error(
93 QObject::tr( "File not found" ),
94 QObject::tr( "Could not create new random file <pre>%1</pre>." ).arg( fileName ) );
95 }
96
97 QByteArray data;
98 CalamaresUtils::EntropySource source = CalamaresUtils::getEntropy( poolSize, data );
99 entropyFile.write( data );
100 entropyFile.close();
101 if ( entropyFile.size() < data.length() )
102 {
103 cWarning() << "Entropy file is" << entropyFile.size() << "bytes, random data was" << data.length();
104 }
105 if ( data.length() < poolSize )
106 {
107 cWarning() << "Entropy data is" << data.length() << "bytes, rather than poolSize" << poolSize;
108 }
109 if ( source != CalamaresUtils::EntropySource::URandom )
110 {
111 cWarning() << "Entropy data for pool is low-quality.";
112 }
113 return Calamares::JobResult::ok();
114 }
115
116
117 Calamares::JobResult
createEntropy(const EntropyGeneration kind,const QString & rootMountPoint,const QString & fileName)118 createEntropy( const EntropyGeneration kind, const QString& rootMountPoint, const QString& fileName )
119 {
120 if ( kind == EntropyGeneration::CopyFromHost )
121 {
122 if ( QFile::exists( fileName ) )
123 {
124 auto r = copyFile( rootMountPoint, fileName );
125 if ( r )
126 {
127 return r;
128 }
129 else
130 {
131 cWarning() << "Could not copy" << fileName << "for entropy, generating new.";
132 }
133 }
134 else
135 {
136 cWarning() << "Host system entropy does not exist at" << fileName;
137 }
138 }
139
140 int poolSize = getUrandomPoolSize();
141 return createNewEntropy( poolSize, rootMountPoint, fileName );
142 }
143
144 static Calamares::JobResult
runCmd(const QStringList & cmd)145 runCmd( const QStringList& cmd )
146 {
147 auto r = CalamaresUtils::System::instance()->targetEnvCommand( cmd );
148 if ( r.getExitCode() )
149 {
150 return r.explainProcess( cmd, std::chrono::seconds( 0 ) );
151 }
152
153 return Calamares::JobResult::ok();
154 }
155
156 Calamares::JobResult
createSystemdMachineId(const QString & rootMountPoint,const QString & fileName)157 createSystemdMachineId( const QString& rootMountPoint, const QString& fileName )
158 {
159 Q_UNUSED( rootMountPoint )
160 Q_UNUSED( fileName )
161 return runCmd( QStringList { QStringLiteral( "systemd-machine-id-setup" ) } );
162 }
163
164 Calamares::JobResult
createDBusMachineId(const QString & rootMountPoint,const QString & fileName)165 createDBusMachineId( const QString& rootMountPoint, const QString& fileName )
166 {
167 Q_UNUSED( rootMountPoint )
168 Q_UNUSED( fileName )
169 return runCmd( QStringList { QStringLiteral( "dbus-uuidgen" ), QStringLiteral( "--ensure" ) } );
170 }
171
172 Calamares::JobResult
createDBusLink(const QString & rootMountPoint,const QString & fileName,const QString & systemdFileName)173 createDBusLink( const QString& rootMountPoint, const QString& fileName, const QString& systemdFileName )
174 {
175 Q_UNUSED( rootMountPoint )
176 return runCmd( QStringList { QStringLiteral( "ln" ), QStringLiteral( "-sf" ), systemdFileName, fileName } );
177 }
178
179 } // namespace MachineId
180