16#include "stubprocess_p.h"
20#include <QStandardPaths>
21#include <qplatformdefs.h>
24#include <KConfigGroup>
25#include <KSharedConfig>
28#if defined(KDESU_USE_SUDO_DEFAULT)
29#define DEFAULT_SUPER_USER_COMMAND QStringLiteral("sudo")
30#elif defined(KDESU_USE_DOAS_DEFAULT)
31#define DEFAULT_SUPER_USER_COMMAND QStringLiteral("doas")
33#define DEFAULT_SUPER_USER_COMMAND QStringLiteral("su")
38using namespace KDESuPrivate;
40class SuProcessPrivate :
public StubProcessPrivate
43 bool isPrivilegeEscalation()
const;
47bool SuProcessPrivate::isPrivilegeEscalation()
const
53 : StubProcess(*new SuProcessPrivate)
61 KConfigGroup group(config, QStringLiteral(
"super-user-command"));
62 d->superUserCommand = group.readEntry(
"super-user-command", DEFAULT_SUPER_USER_COMMAND);
64 if (!d->isPrivilegeEscalation() && d->superUserCommand !=
QLatin1String(
"su")) {
65 qCWarning(KSU_LOG) <<
"unknown super user command.";
66 d->superUserCommand = DEFAULT_SUPER_USER_COMMAND;
70SuProcess::~SuProcess() =
default;
76 return d->superUserCommand;
79bool SuProcess::useUsersOwnPassword()
83 if (d->isPrivilegeEscalation() && m_user ==
"root") {
91int SuProcess::checkInstall(
const char *password)
93 return exec(password, Install);
96int SuProcess::checkNeedPassword()
98 return exec(
nullptr, NeedPassword);
104int SuProcess::exec(
const char *password,
int check)
115 d->superUserCommand = QStringLiteral(
"su");
119 if (d->isPrivilegeEscalation()) {
123 if (m_scheduler != SchedNormal || m_priority > 50) {
134 KConfigGroup group(config, QStringLiteral(
"super-user-command"));
135 const QString defaultPath = QStringLiteral(KDE_INSTALL_FULL_LIBEXECDIR_KF) + QStringLiteral(
"/kdesu_stub");
136 const QString kdesuStubPath = group.readEntry(
"kdesu_stub_path", defaultPath);
143 return check ? SuNotFound : -1;
148 enableLocalEcho(
false);
150 if (StubProcess::exec(command, args) < 0) {
151 return check ? SuNotFound : -1;
154 SuErrors ret = (SuErrors)converseSU(password);
158 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
159 <<
"Conversation with" << d->superUserCommand <<
"failed.";
163 if (check == NeedPassword) {
165 if (d->isPrivilegeEscalation()) {
169 if (kill(m_pid, SIGKILL) < 0) {
175 int iret = waitForChild();
184 if (m_erase && password) {
185 memset(
const_cast<char *
>(password), 0, qstrlen(password));
189 kill(m_pid, SIGKILL);
190 if (d->isPrivilegeEscalation()) {
193 return SuIncorrectPassword;
196 int iret = converseStub(check);
199 qCCritical(KSU_LOG) <<
"[" << __FILE__ <<
":" << __LINE__ <<
"] "
200 <<
"Conversation with kdesu_stub failed.";
203 }
else if (iret == 1) {
204 kill(m_pid, SIGKILL);
206 return SuIncorrectPassword;
209 if (check == Install) {
214 iret = waitForChild();
222int SuProcess::converseSU(
const char *password)
228 } state = WaitForPrompt;
237 if ((line.
contains(
':') && state != WaitForPrompt) || line.
isNull()) {
238 return (state == HandleStub ? notauthorized : error);
241 if (line ==
"kdesu_stub") {
247 case WaitForPrompt: {
248 if (waitMS(fd(), 100) > 0) {
256 const uint len = line.
length();
258 for (i = 0, j = 0, colon = 0; i < len; ++i) {
259 if (line[i] ==
':') {
264 if (!isspace(line[i])) {
268 if (colon == 1 && line[j] ==
':') {
269 if (password ==
nullptr) {
275 write(fd(), password, strlen(password));
276 write(fd(),
"\n", 1);
288 const bool starCond = std::any_of(s.
cbegin(), s.
cend(), [](
const char c) {
306void SuProcess::virtual_hook(
int id,
void *data)
308 StubProcess::virtual_hook(
id, data);
Executes a command under elevated privileges, using su.
static KSharedConfig::Ptr openConfig(const QString &fileName=QString(), OpenFlags mode=FullConfig, QStandardPaths::StandardLocation type=QStandardPaths::GenericConfigLocation)
QString loginName() const
void error(QWidget *parent, const QString &text, const QString &title, const KGuiItem &buttonOk, Options options=Notify)
const_iterator cbegin() const const
const_iterator cend() const const
bool contains(QByteArrayView bv) const const
bool isEmpty() const const
bool isNull() const const
qsizetype length() const const
QByteArray trimmed() const const
QString findExecutable(const QString &executableName, const QStringList &paths)
QString fromUtf8(QByteArrayView str)
QByteArray toLocal8Bit() const const