I apologize for the somewhat lengthy discussion. Also, this is my first submission to StackOverflow, so please forgive my unfamiliarity.
I usually use C++/Qt Widget or C++/QML with Linux. This time, I need to create or write files with root privileges, and I am using the following URL (PolKit-Qt-1) to create and test my own C++/Qt Widget software.
https://api.kde.org/polkit-qt-1/html/
I am using polkit-qt-gui-1 to create software (C++/Qt) to create and write files with root privileges when a button is pressed.
However, a permission error occurs because the file cannot be created or written as root, but has been created or written as the executing user.
Perhaps there is a mistake in some configuration file, or there is a missing or incorrect part of the source code.
I want to create or write a file with root privileges when a button is pressed. How do I create or write files with root privileges using C++/Qt and PolKit-Qt-1?
Thank you for your cooperation.
My own source code is shown below. The action file for polkit-1 is also shown below.
main.cpp:
#include "mainwindow.h"
#include <QApplication>
int main(int argc, char *argv[])
{
QApplication a(argc, argv);
MainWindow w;
w.show();
return a.exec();
}
mainwindow.cpp:
#include "mainwindow.h"
#include "ui_mainwindow.h"
MainWindow::MainWindow(QWidget *parent) : QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this);
PolkitQt1::Gui::ActionButton *bt = new PolkitQt1::Gui::ActionButton(ui->pushButton, "org.qt.policykit.examples.write", this);
bt->setText("Run with administrative privileges");
bt->setVisible(true, PolkitQt1::Gui::Action::No | PolkitQt1::Gui::Action::Auth | PolkitQt1::Gui::Action::Yes);
bt->setEnabled(true, PolkitQt1::Gui::Action::No | PolkitQt1::Gui::Action::Auth | PolkitQt1::Gui::Action::Yes);
connect(bt, SIGNAL(triggered(bool)), this, SLOT(activateAction()));
connect(bt, SIGNAL(clicked(QAbstractButton*,bool)), bt, SLOT(activate()));
connect(bt, SIGNAL(authorized()), this, SLOT(onBtnClicked()));
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::activateAction()
{
PolkitQt1::Gui::Action *action = qobject_cast<PolkitQt1::Gui::Action *>(sender());
action->activate();
}
void MainWindow::onBtnClicked()
{
PolkitQt1::Gui::Action *action = qobject_cast<PolkitQt1::Gui::Action *>(sender());
qDebug() << "pretending to be the mechanism for action:" << action->actionId();
PolkitQt1::UnixProcessSubject subject(static_cast<uint>(QCoreApplication::applicationPid()));
PolkitQt1::Authority::Result result = PolkitQt1::Authority::instance()->checkAuthorizationSync(action->actionId(), subject, PolkitQt1::Authority::AllowUserInteraction);
if (result == PolkitQt1::Authority::Yes)
{
// Write /opt/sample.txt file with root privilege.
writeTextFile("/opt/sample.txt", "foo bar");
}
else
{
return;
}
return;
}
void MainWindow::writeTextFile(QString FileName, QString strOutputData)
{
QFileInfo FileInfo(FileName);
QFile File(FileName);
if(!File.open(QIODevice::WriteOnly))
{
QString strErrMsg = "File(" + FileInfo.fileName() + ") Open Error: " + File.errorString();
qDebug() << strErrMsg;
return;
}
QTextStream OutStream(&File);
OutStream << strOutputData;
File.close();
return;
}
mainwindow.h:
#define MAINWINDOW_H
#include <QMainWindow>
#include <QtWidgets>
#include <QDBusContext>
#include <QDBusMessage>
#include <QDBusConnection>
#include <polkit-qt5-1/polkitqt1-gui-action.h>
#include <polkit-qt5-1/polkitqt1-gui-actionbutton.h>
#include <polkit-qt5-1/polkitqt1-gui-actionbuttons.h>
#include <polkit-qt5-1/polkitqt1-authority.h>
#include <dbus/dbus.h>
#include <QDebug>
QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE
class MainWindow : public QMainWindow, protected QDBusContext
{
Q_OBJECT
private:
void writeTextFile(QString FileName, QString strOutputData);
public:
MainWindow(QWidget *parent = nullptr);
~MainWindow();
private:
Ui::MainWindow *ui;
private Q_SLOTS:
void activateAction();
void onBtnClicked();
};
#endif // MAINWINDOW_H
/usr/share/polkit-1/actions/org.qt.policykit.examples.policy:
<?xml version='1.0' encoding='utf-8'?>
<!DOCTYPE policyconfig PUBLIC '-//freedesktop//DTD PolicyKit Policy Configuration 1.0//EN' 'http://www.freedesktop.org/standards/PolicyKit/1.0/policyconfig.dtd'>
<policyconfig>
<vendor>KDE</vendor>
<vendor_url>http://www.kde.org</vendor_url>
<action id="org.qt.policykit.examples.write">
<description>Write</description>
<message>Prevents PolKit-Qt-1 example from writing</message>
<defaults>
<allow_inactive>no</allow_inactive>
<allow_active>auth_admin_keep</allow_active>
</defaults>
</action>
</policyconfig>
Sorry for the long wait.
After much trial and error, the following source code allows the program to run with administrative privilege (root) only when a specific button is pressed.
Please forgive the somewhat lengthy post.
Main executable
Main executable is GUI software that sends D-Bus messages by pressing a button.
main.cpp:
mainwindow.cpp:
mainwindow.h:
Helper executable
Helper executable is software that receives messages from D-Bus and creates files with root privileges.
main.cpp:
SampleHelper.cpp:
SampleHelper.h:
Execute the
qdbusxml2cpp
command (using the D-Bus interface file at this time) to generate the adapter source code file and header files for the helper.In this example, SampleAdaptor.cpp and SampleAdaptor.h are generated.
Add this file to the helper executable's project.
If this is done automatically :
Qt .pro file, the following commands were written.
CMake file, the following commands were written.
Create Polkit policy file
/usr/share/polkit-1/actions/org.qt.policykit.examples.policy:
Create D-Bus configuration files
/usr/share/dbus-1/interfaces/org.qt.policykit.examples.xml:
/usr/share/dbus-1/system-services/org.qt.policykit.examples.service:
/etc/dbus-1/system-local.conf:
or
/etc/dbus-1/system.d/org.qt.policykit.examples.conf:
or
/usr/share/dbus-1/system.d/org.qt.policykit.examples.conf: