mirror of https://github.com/cutefishos/calamares
Merge branch 'issue-1523' into calamares
commit
2bd3f1d8c1
@ -0,0 +1,194 @@
|
|||||||
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
||||||
|
* SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Calamares is Free Software: see the License-Identifier above.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "MiscJobs.h"
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
|
||||||
|
#include "GlobalStorage.h"
|
||||||
|
#include "JobQueue.h"
|
||||||
|
#include "utils/CalamaresUtilsSystem.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/Permissions.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileInfo>
|
||||||
|
|
||||||
|
SetupSudoJob::SetupSudoJob( const QString& group )
|
||||||
|
: m_sudoGroup( group )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
SetupSudoJob::prettyName() const
|
||||||
|
{
|
||||||
|
return tr( "Configure <pre>sudo</pre> users." );
|
||||||
|
}
|
||||||
|
|
||||||
|
Calamares::JobResult
|
||||||
|
SetupSudoJob::exec()
|
||||||
|
{
|
||||||
|
if ( m_sudoGroup.isEmpty() )
|
||||||
|
{
|
||||||
|
return Calamares::JobResult::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
QString sudoersLine = QString( "%%1 ALL=(ALL) ALL\n" ).arg( m_sudoGroup );
|
||||||
|
auto fileResult
|
||||||
|
= CalamaresUtils::System::instance()->createTargetFile( QStringLiteral( "/etc/sudoers.d/10-installer" ),
|
||||||
|
sudoersLine.toUtf8().constData(),
|
||||||
|
CalamaresUtils::System::WriteMode::Overwrite );
|
||||||
|
|
||||||
|
if ( fileResult )
|
||||||
|
{
|
||||||
|
if ( !CalamaresUtils::Permissions::apply( fileResult.path(), 0440 ) )
|
||||||
|
{
|
||||||
|
return Calamares::JobResult::error( tr( "Cannot chmod sudoers file." ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return Calamares::JobResult::error( tr( "Cannot create sudoers file for writing." ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Calamares::JobResult::ok();
|
||||||
|
}
|
||||||
|
|
||||||
|
STATICTEST QStringList
|
||||||
|
groupsInTargetSystem()
|
||||||
|
{
|
||||||
|
Calamares::GlobalStorage* gs = Calamares::JobQueue::instance()->globalStorage();
|
||||||
|
if ( !gs )
|
||||||
|
{
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
QDir targetRoot( gs->value( "rootMountPoint" ).toString() );
|
||||||
|
|
||||||
|
QFileInfo groupsFi( targetRoot.absoluteFilePath( "etc/group" ) );
|
||||||
|
QFile groupsFile( groupsFi.absoluteFilePath() );
|
||||||
|
if ( !groupsFile.open( QIODevice::ReadOnly | QIODevice::Text ) )
|
||||||
|
{
|
||||||
|
return QStringList();
|
||||||
|
}
|
||||||
|
QString groupsData = QString::fromLocal8Bit( groupsFile.readAll() );
|
||||||
|
QStringList groupsLines = groupsData.split( '\n' );
|
||||||
|
QStringList::iterator it = groupsLines.begin();
|
||||||
|
while ( it != groupsLines.end() )
|
||||||
|
{
|
||||||
|
if ( it->startsWith( '#' ) )
|
||||||
|
{
|
||||||
|
it = groupsLines.erase( it );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
int indexOfFirstToDrop = it->indexOf( ':' );
|
||||||
|
if ( indexOfFirstToDrop < 1 )
|
||||||
|
{
|
||||||
|
it = groupsLines.erase( it );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
it->truncate( indexOfFirstToDrop );
|
||||||
|
++it;
|
||||||
|
}
|
||||||
|
return groupsLines;
|
||||||
|
}
|
||||||
|
|
||||||
|
/** @brief Create groups in target system as needed
|
||||||
|
*
|
||||||
|
* Given a list of groups that already exist, @p availableGroups,
|
||||||
|
* go through the @p wantedGroups and create each of them. Groups that
|
||||||
|
* fail, or which should have already been there, are added to
|
||||||
|
* @p missingGroups by name.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
ensureGroupsExistInTarget( const QList< GroupDescription >& wantedGroups,
|
||||||
|
const QStringList& availableGroups,
|
||||||
|
QStringList& missingGroups )
|
||||||
|
{
|
||||||
|
int failureCount = 0;
|
||||||
|
|
||||||
|
for ( const auto& group : wantedGroups )
|
||||||
|
{
|
||||||
|
if ( group.isValid() && !availableGroups.contains( group.name() ) )
|
||||||
|
{
|
||||||
|
if ( group.mustAlreadyExist() )
|
||||||
|
{
|
||||||
|
// Should have been there already: don't create it
|
||||||
|
missingGroups.append( group.name() );
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
QStringList cmd;
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
if ( group.isSystemGroup() )
|
||||||
|
{
|
||||||
|
cWarning() << "Ignoring must-be-a-system group for" << group.name() << "on FreeBSD";
|
||||||
|
}
|
||||||
|
cmd = QStringList { "pw", "groupadd", "-n", group.name() };
|
||||||
|
#else
|
||||||
|
cmd << QStringLiteral( "groupadd" );
|
||||||
|
if ( group.isSystemGroup() )
|
||||||
|
{
|
||||||
|
cmd << "--system";
|
||||||
|
}
|
||||||
|
cmd << group.name();
|
||||||
|
#endif
|
||||||
|
if ( CalamaresUtils::System::instance()->targetEnvCall( cmd ) )
|
||||||
|
{
|
||||||
|
failureCount++;
|
||||||
|
missingGroups.append( group.name() + QChar( '*' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if ( !missingGroups.isEmpty() )
|
||||||
|
{
|
||||||
|
cWarning() << "Missing groups in target system (* for groupadd failure):" << Logger::DebugList( missingGroups );
|
||||||
|
}
|
||||||
|
return failureCount == 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
SetupGroupsJob::SetupGroupsJob( const Config* config )
|
||||||
|
: m_config( config )
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
QString
|
||||||
|
SetupGroupsJob::prettyName() const
|
||||||
|
{
|
||||||
|
return tr( "Preparing groups." );
|
||||||
|
}
|
||||||
|
|
||||||
|
Calamares::JobResult
|
||||||
|
SetupGroupsJob::exec()
|
||||||
|
{
|
||||||
|
const auto& defaultGroups = m_config->defaultGroups();
|
||||||
|
QStringList availableGroups = groupsInTargetSystem();
|
||||||
|
QStringList missingGroups;
|
||||||
|
|
||||||
|
if ( !ensureGroupsExistInTarget( defaultGroups, availableGroups, missingGroups ) )
|
||||||
|
{
|
||||||
|
return Calamares::JobResult::error( tr( "Could not create groups in target system" ) );
|
||||||
|
}
|
||||||
|
if ( !missingGroups.isEmpty() )
|
||||||
|
{
|
||||||
|
return Calamares::JobResult::error(
|
||||||
|
tr( "Could not create groups in target system" ),
|
||||||
|
tr( "These groups are missing in the target system: %1" ).arg( missingGroups.join( ',' ) ) );
|
||||||
|
}
|
||||||
|
|
||||||
|
if ( m_config->doAutoLogin() && !m_config->autologinGroup().isEmpty() )
|
||||||
|
{
|
||||||
|
const QString autologinGroup = m_config->autologinGroup();
|
||||||
|
(void)ensureGroupsExistInTarget(
|
||||||
|
QList< GroupDescription >() << GroupDescription( autologinGroup ), availableGroups, missingGroups );
|
||||||
|
}
|
||||||
|
|
||||||
|
return Calamares::JobResult::ok();
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2014-2015 Teo Mrnjavac <teo@kde.org>
|
||||||
|
* SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Calamares is Free Software: see the License-Identifier above.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**@file Various small jobs
|
||||||
|
*
|
||||||
|
* This file collects miscellaneous jobs that need to be run to prepare
|
||||||
|
* the system for the user-creation job.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef USERS_MISCJOBS_H
|
||||||
|
#define USERS_MISCJOBS_H
|
||||||
|
|
||||||
|
#include "Job.h"
|
||||||
|
|
||||||
|
class Config;
|
||||||
|
|
||||||
|
class SetupSudoJob : public Calamares::Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
SetupSudoJob( const QString& group );
|
||||||
|
QString prettyName() const override;
|
||||||
|
Calamares::JobResult exec() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
QString m_sudoGroup;
|
||||||
|
};
|
||||||
|
|
||||||
|
class SetupGroupsJob : public Calamares::Job
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
|
||||||
|
public:
|
||||||
|
SetupGroupsJob( const Config* config );
|
||||||
|
QString prettyName() const override;
|
||||||
|
Calamares::JobResult exec() override;
|
||||||
|
|
||||||
|
public:
|
||||||
|
const Config* m_config;
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
@ -1,72 +0,0 @@
|
|||||||
/* === This file is part of Calamares - <https://calamares.io> ===
|
|
||||||
*
|
|
||||||
* SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
|
||||||
* SPDX-License-Identifier: GPL-3.0-or-later
|
|
||||||
*
|
|
||||||
* Calamares is Free Software: see the License-Identifier above.
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include "CreateUserJob.h"
|
|
||||||
|
|
||||||
#include "utils/Logger.h"
|
|
||||||
|
|
||||||
#include <QDir>
|
|
||||||
#include <QtTest/QtTest>
|
|
||||||
|
|
||||||
// Implementation details
|
|
||||||
extern QStringList groupsInTargetSystem( const QDir& targetRoot ); // CreateUserJob
|
|
||||||
|
|
||||||
class CreateUserTests : public QObject
|
|
||||||
{
|
|
||||||
Q_OBJECT
|
|
||||||
public:
|
|
||||||
CreateUserTests();
|
|
||||||
~CreateUserTests() override {}
|
|
||||||
|
|
||||||
private Q_SLOTS:
|
|
||||||
void initTestCase();
|
|
||||||
|
|
||||||
void testReadGroup();
|
|
||||||
};
|
|
||||||
|
|
||||||
CreateUserTests::CreateUserTests() {}
|
|
||||||
|
|
||||||
void
|
|
||||||
CreateUserTests::initTestCase()
|
|
||||||
{
|
|
||||||
Logger::setupLogLevel( Logger::LOGDEBUG );
|
|
||||||
cDebug() << "Users test started.";
|
|
||||||
}
|
|
||||||
|
|
||||||
void
|
|
||||||
CreateUserTests::testReadGroup()
|
|
||||||
{
|
|
||||||
QDir root( "/" );
|
|
||||||
QVERIFY( root.exists() );
|
|
||||||
|
|
||||||
// Get the groups in the host system
|
|
||||||
QStringList groups = groupsInTargetSystem( root );
|
|
||||||
QVERIFY( groups.count() > 2 );
|
|
||||||
#ifdef __FreeBSD__
|
|
||||||
QVERIFY( groups.contains( QStringLiteral( "wheel" ) ) );
|
|
||||||
#else
|
|
||||||
QVERIFY( groups.contains( QStringLiteral( "root" ) ) );
|
|
||||||
#endif
|
|
||||||
// openSUSE doesn't have "sys"
|
|
||||||
// QVERIFY( groups.contains( QStringLiteral( "sys" ) ) );
|
|
||||||
QVERIFY( groups.contains( QStringLiteral( "nogroup" ) ) );
|
|
||||||
QVERIFY( groups.contains( QStringLiteral( "tty" ) ) );
|
|
||||||
|
|
||||||
for ( const QString& s : groups )
|
|
||||||
{
|
|
||||||
QVERIFY( !s.isEmpty() );
|
|
||||||
QVERIFY( !s.contains( '#' ) );
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
QTEST_GUILESS_MAIN( CreateUserTests )
|
|
||||||
|
|
||||||
#include "utils/moc-warnings.h"
|
|
||||||
|
|
||||||
#include "TestCreateUserJob.moc"
|
|
@ -0,0 +1,106 @@
|
|||||||
|
/* === This file is part of Calamares - <https://calamares.io> ===
|
||||||
|
*
|
||||||
|
* SPDX-FileCopyrightText: 2020 Adriaan de Groot <groot@kde.org>
|
||||||
|
* SPDX-License-Identifier: GPL-3.0-or-later
|
||||||
|
*
|
||||||
|
* Calamares is Free Software: see the License-Identifier above.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "Config.h"
|
||||||
|
#include "CreateUserJob.h"
|
||||||
|
#include "MiscJobs.h"
|
||||||
|
|
||||||
|
#include "GlobalStorage.h"
|
||||||
|
#include "JobQueue.h"
|
||||||
|
#include "utils/Logger.h"
|
||||||
|
#include "utils/Yaml.h"
|
||||||
|
|
||||||
|
#include <QDir>
|
||||||
|
#include <QtTest/QtTest>
|
||||||
|
|
||||||
|
// Implementation details
|
||||||
|
extern QStringList groupsInTargetSystem(); // CreateUserJob
|
||||||
|
|
||||||
|
class GroupTests : public QObject
|
||||||
|
{
|
||||||
|
Q_OBJECT
|
||||||
|
public:
|
||||||
|
GroupTests();
|
||||||
|
~GroupTests() override {}
|
||||||
|
|
||||||
|
private Q_SLOTS:
|
||||||
|
void initTestCase();
|
||||||
|
|
||||||
|
void testReadGroup();
|
||||||
|
void testCreateGroup();
|
||||||
|
};
|
||||||
|
|
||||||
|
GroupTests::GroupTests() {}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupTests::initTestCase()
|
||||||
|
{
|
||||||
|
Logger::setupLogLevel( Logger::LOGDEBUG );
|
||||||
|
cDebug() << "Users test started.";
|
||||||
|
if ( !Calamares::JobQueue::instance() )
|
||||||
|
{
|
||||||
|
(void)new Calamares::JobQueue();
|
||||||
|
}
|
||||||
|
Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" );
|
||||||
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
GroupTests::testReadGroup()
|
||||||
|
{
|
||||||
|
// Get the groups in the host system
|
||||||
|
QStringList groups = groupsInTargetSystem();
|
||||||
|
QVERIFY( groups.count() > 2 );
|
||||||
|
#ifdef __FreeBSD__
|
||||||
|
QVERIFY( groups.contains( QStringLiteral( "wheel" ) ) );
|
||||||
|
#else
|
||||||
|
QVERIFY( groups.contains( QStringLiteral( "root" ) ) );
|
||||||
|
#endif
|
||||||
|
// openSUSE doesn't have "sys"
|
||||||
|
// QVERIFY( groups.contains( QStringLiteral( "sys" ) ) );
|
||||||
|
QVERIFY( groups.contains( QStringLiteral( "nogroup" ) ) );
|
||||||
|
QVERIFY( groups.contains( QStringLiteral( "tty" ) ) );
|
||||||
|
|
||||||
|
for ( const QString& s : groups )
|
||||||
|
{
|
||||||
|
QVERIFY( !s.isEmpty() );
|
||||||
|
QVERIFY( !s.contains( '#' ) );
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void GroupTests::testCreateGroup()
|
||||||
|
{
|
||||||
|
// BUILD_AS_TEST is the source-directory path
|
||||||
|
QFile fi( QString( "%1/tests/5-issue-1523.conf" ).arg( BUILD_AS_TEST ) );
|
||||||
|
QVERIFY( fi.exists() );
|
||||||
|
|
||||||
|
bool ok = false;
|
||||||
|
const auto map = CalamaresUtils::loadYaml( fi, &ok );
|
||||||
|
QVERIFY( ok );
|
||||||
|
QVERIFY( map.count() > 0 ); // Just that it loaded, one key *defaultGroups*
|
||||||
|
|
||||||
|
Config c;
|
||||||
|
c.setConfigurationMap( map );
|
||||||
|
|
||||||
|
QCOMPARE( c.defaultGroups().count(), 4 );
|
||||||
|
QVERIFY( c.defaultGroups().contains( QStringLiteral( "adm" ) ) );
|
||||||
|
QVERIFY( c.defaultGroups().contains( QStringLiteral( "bar" ) ) );
|
||||||
|
|
||||||
|
Calamares::JobQueue::instance()->globalStorage()->insert( "rootMountPoint", "/" );
|
||||||
|
|
||||||
|
SetupGroupsJob j(&c);
|
||||||
|
QVERIFY( !j.exec() ); // running as regular user this should fail
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
QTEST_GUILESS_MAIN( GroupTests )
|
||||||
|
|
||||||
|
#include "utils/moc-warnings.h"
|
||||||
|
|
||||||
|
#include "TestGroupInformation.moc"
|
@ -0,0 +1,14 @@
|
|||||||
|
# SPDX-FileCopyrightText: no
|
||||||
|
# SPDX-License-Identifier: CC0-1.0
|
||||||
|
#
|
||||||
|
---
|
||||||
|
defaultGroups:
|
||||||
|
- adm
|
||||||
|
- name: foo
|
||||||
|
must_exist: false
|
||||||
|
system: true
|
||||||
|
- name: bar
|
||||||
|
must_exist: true
|
||||||
|
- name: foobar
|
||||||
|
must_exist: false
|
||||||
|
system: false
|
Loading…
Reference in New Issue