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;
44 QString superUserCommand;
47bool SuProcessPrivate::isPrivilegeEscalation()
const
49 return (superUserCommand == QLatin1String(
"sudo") || superUserCommand == QLatin1String(
"doas"));
52SuProcess::SuProcess(
const QByteArray &user,
const QByteArray &command)
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;
83 if (d->isPrivilegeEscalation() && m_user ==
"root") {
93 return exec(password, Install);
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) {
void virtual_hook(int id, void *data) override
Standard hack to add virtual methods in a BC way.
Executes a command under elevated privileges, using su.
void virtual_hook(int id, void *data) override
Standard hack to add virtual methods in a BC way.
int checkInstall(const char *password)
Checks if the stub is installed and the password is correct.
bool useUsersOwnPassword()
Checks whether or not the user's password is being asked for or another user's password.
QString superUserCommand()
Checks what the default super user command is, e.g.
int checkNeedPassword()
Checks if a password is needed.
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