Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
43 changes: 42 additions & 1 deletion src/app/main.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2017 - 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2017 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-only

Expand All @@ -11,14 +11,29 @@
#include <util/utils.h>
#include <QDebug>
#include <DLog>
#include <DApplication>

Check warning on line 14 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DApplication> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 14 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <DApplication> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <DWidgetUtil>

Check warning on line 15 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DWidgetUtil> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 15 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <DWidgetUtil> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <DGuiApplicationHelper>

Check warning on line 16 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <DGuiApplicationHelper> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 16 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <DGuiApplicationHelper> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <QDBusConnection>

Check warning on line 17 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <QDBusConnection> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 17 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <QDBusConnection> not found. Please note: Cppcheck does not need standard library headers to get proper results.

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#include <DApplicationSettings>
#endif

#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0)
#if defined (Q_OS_LINUX)
#include <polkit-qt5-1/PolkitQt1/Authority>
#include <polkit-qt5-1/PolkitQt1/Subject>
#endif
#else
#if defined (Q_OS_LINUX)
#include <polkit-qt6-1/PolkitQt1/Authority>

Check warning on line 30 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <polkit-qt6-1/PolkitQt1/Authority> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 30 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <polkit-qt6-1/PolkitQt1/Authority> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#include <polkit-qt6-1/PolkitQt1/Subject>

Check warning on line 31 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Include file: <polkit-qt6-1/PolkitQt1/Subject> not found. Please note: Cppcheck does not need standard library headers to get proper results.

Check warning on line 31 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Include file: <polkit-qt6-1/PolkitQt1/Subject> not found. Please note: Cppcheck does not need standard library headers to get proper results.
#endif
#endif

const QString s_PolkitActionCreate = "com.deepin.bootmaker.create";


DCORE_USE_NAMESPACE
DWIDGET_USE_NAMESPACE
Expand Down Expand Up @@ -53,6 +68,27 @@

#endif

// 在前端中预先进行身份验证, 便于流程控制
bool checkAuthorization()
{
#if defined (Q_OS_LINUX)
QString busName = QDBusConnection::systemBus().baseService();
auto authority = PolkitQt1::Authority::instance();
if (!authority) {
qWarning() << "Failed to get Polkit authority instance";
return false;
}
PolkitQt1::Authority::Result ret = authority->checkAuthorizationSync(
s_PolkitActionCreate,
PolkitQt1::SystemBusNameSubject(busName),
PolkitQt1::Authority::AllowUserInteraction);

return PolkitQt1::Authority::Yes == ret;
#else
return true;
#endif
}

int main(int argc, char **argv)
{
qInfo() << "Starting Boot Maker application";
Expand All @@ -78,6 +114,11 @@
// app.setApplicationVersion(DApplication::buildVersion(VERSION));
// app.setTheme("light");

if (!checkAuthorization()) {

Check warning on line 117 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / cppcheck

Condition '!checkAuthorization()' is always false

Check warning on line 117 in src/app/main.cpp

View workflow job for this annotation

GitHub Actions / static-check / static-check

Condition '!checkAuthorization()' is always false
qInfo() << "Authorization failed, exiting";
return 1;
}

#ifdef Q_OS_MAC
qDebug() << "Checking root privileges on macOS";
if (switchToRoot(app)) {
Expand Down
126 changes: 25 additions & 101 deletions src/service/bootmakerservice.cpp
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2016 - 2022 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2016 - 2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-only

Expand Down Expand Up @@ -43,17 +43,21 @@ const QString s_PolkitActionReboot = "com.deepin.bootmaker.reboot";
/**
@brief Polkit action authorization check.
Use com.deepin.bootmaker.policy config file.
Default action id: "com.deepin.bootmaker"
@note Available on linux/unix/macos platform.
@return check passed.
*/
bool checkAuthorization(qint64 pid, const QString &action)
bool checkAuthorization(const QString &busName, const QString &action)
{
#if defined (Q_OS_LINUX) || defined (Q_OS_UNIX) || defined (Q_OS_MAC)
qDebug() << "Checking authorization for action:" << action << "PID:" << pid;
PolkitQt1::Authority::Result ret = PolkitQt1::Authority::instance()->checkAuthorizationSync(
qDebug() << "Checking authorization for action:" << action << "BusName:" << busName;
auto authority = PolkitQt1::Authority::instance();
if (!authority) {
qWarning() << "Failed to get Polkit authority instance";
return false;
}
PolkitQt1::Authority::Result ret = authority->checkAuthorizationSync(
action,
PolkitQt1::UnixProcessSubject(pid),
PolkitQt1::SystemBusNameSubject(busName),
PolkitQt1::Authority::AllowUserInteraction);

if (PolkitQt1::Authority::Yes == ret) {
Expand All @@ -69,53 +73,6 @@ bool checkAuthorization(qint64 pid, const QString &action)
#endif
}

#if 0 // Not use now
int getProcIdByExeName(std::string execName)
{
int pid = -1;

// Open the /proc directory
DIR *dp = opendir("/proc");
if (dp != NULL) {
// Enumerate all entries in directory until process found
struct dirent *dirp;
while (pid < 0 && (dirp = readdir(dp))) {
// Skip non-numeric entries
int id = atoi(dirp->d_name);
if (id > 0) {
// Read contents of virtual /proc/{pid}/cmdline file
auto exeSymlinkPath = std::string("/proc/") + dirp->d_name + "/exe";
char *actualpath = realpath(exeSymlinkPath.c_str(), NULL);
if (actualpath) {
// Compare against requested process name
if (execName == actualpath) {
pid = id;
}
}
}
}
}

closedir(dp);

return pid;
}
#endif

static QString getProcIdExe(qint64 id)
{
qDebug() << "Getting executable path for process ID:" << id;
QString execName;
if (id > 0) {
// Read contents of virtual /proc/{pid}/cmdline file
QString exeSymlinkPath = QString("/proc/%1/exe").arg(id);
char *actualpath = realpath(exeSymlinkPath.toStdString().c_str(), NULL);
execName = QString(actualpath);
qDebug() << "Process executable path:" << execName;
}
return execName;
}

BootMakerService::BootMakerService(QObject *parent) :
QObject(parent), d_ptr(new BootMakerServicePrivate(this))
{
Expand Down Expand Up @@ -161,7 +118,7 @@ void BootMakerService::Reboot()
{
Q_D(BootMakerService);
qInfo() << "Reboot requested";
if (checkAuthorization(d->dbusCallerPid(), s_PolkitActionReboot)) {
if (d->checkAuthorization(s_PolkitActionReboot)) {
qDebug() << "Reboot authorized, proceeding";
d->bm->reboot();
} else {
Expand All @@ -173,8 +130,8 @@ void BootMakerService::Start()
{
Q_D(BootMakerService);
qInfo() << "Start requested";
if (!d->checkCaller()) {
qWarning() << "Start request denied - Invalid caller";
if (!d->checkAuthorization(s_PolkitActionCreate)) {
qWarning() << "Start request denied - Authorization failed";
return;
}

Expand All @@ -186,8 +143,8 @@ void BootMakerService::Stop()
{
Q_D(BootMakerService);
qInfo() << "Stop requested";
if (!d->checkCaller()) {
qWarning() << "Stop request denied - Invalid caller";
if (!d->checkAuthorization(s_PolkitActionCreate)) {
qWarning() << "Stop request denied - Authorization failed";
return;
}

Expand All @@ -203,8 +160,8 @@ QString BootMakerService::DeviceList()
{
Q_D(BootMakerService);
qDebug() << "Device list requested";
if (!d->checkCaller()) {
qWarning() << "Device list request denied - Invalid caller";
if (!d->checkAuthorization(s_PolkitActionCreate)) {
qWarning() << "Device list request denied - Authorization failed";
return "";
}
return deviceListToJson(d->bm->deviceList());
Expand All @@ -215,12 +172,7 @@ bool BootMakerService::Install(const QString &image, const QString &device, cons
Q_D(BootMakerService);
qInfo() << "Install requested - Image:" << image << "Device:" << device << "Partition:" << partition;

if (!d->checkCaller()) {
qWarning() << "Install request denied - Invalid caller";
return false;
}

if (!d->disableCheck && !checkAuthorization(d->dbusCallerPid(), s_PolkitActionCreate)) {
if (!d->checkAuthorization(s_PolkitActionCreate)) {
qWarning() << "Install request denied - Authorization failed";
return false;
}
Expand All @@ -237,50 +189,22 @@ bool BootMakerService::CheckFile(const QString &filepath)
return d->bm->checkfile(filepath);
}

bool BootMakerServicePrivate::checkCaller()
bool BootMakerServicePrivate::checkAuthorization(const QString &action)
{
if (disableCheck) {
qDebug() << "Caller check disabled";
qDebug() << "Authorization check disabled";
return true;
}

Q_Q(BootMakerService);
if (!q->calledFromDBus()) {
qWarning() << "Caller check failed - Not called from DBus";
return false;
}

qint64 callerPid = dbusCallerPid();
QString callerExe = getProcIdExe(callerPid);
QString dbmExe = QStandardPaths::findExecutable("deepin-boot-maker", {"/usr/bin"});

qDebug() << "Caller check - PID:" << callerPid << "Executable:" << callerExe;

if (callerExe != dbmExe) {
qWarning() << "Caller not authorized - Invalid executable";
qWarning() << "Authorization check failed - Not called from DBus";
return false;
}
qDebug() << "Caller authorized";
return true;
}

/**
@return DBus interface caller pid
If the call is not from dbus (from UT), return 0
*/
qint64 BootMakerServicePrivate::dbusCallerPid()
{
Q_Q(BootMakerService);
if (!q->calledFromDBus()) {
qDebug() << "Not called from DBus, returning 0";
return 0;
}

auto interface = q->connection().interface();
if (interface) {
return static_cast<qint64>(interface->servicePid(q->message().service()).value());
}
QString busName = q->message().service();
bool ret = ::checkAuthorization(busName, action);
qDebug() << "Authorization check result: " << ret;

qDebug() << "Failed to get DBus caller PID";
return 0;
return ret;
}
5 changes: 2 additions & 3 deletions src/service/bootmakerservice_p.h
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
// SPDX-FileCopyrightText: 2023 UnionTech Software Technology Co., Ltd.
// SPDX-FileCopyrightText: 2023-2026 UnionTech Software Technology Co., Ltd.
//
// SPDX-License-Identifier: GPL-3.0-only

Expand All @@ -17,8 +17,7 @@ class BootMakerServicePrivate
{
}
~BootMakerServicePrivate() {}
bool checkCaller();
qint64 dbusCallerPid();
bool checkAuthorization(const QString &action);

bool disableCheck = false;
BootMaker *bm = nullptr;
Expand Down
Loading