35#include "adminauthorization_p.h"
39#include <QCoreApplication>
40#include <QInputDialog>
44#include <sys/resource.h>
49#include <linux/limits.h>
59#include <QStandardPaths>
64#define SU_COMMAND "/usr/bin/sudo"
68bool execAdminFallback(
const QString &program,
const QStringList &arguments);
69const QList<QPair<QString, QStringList>> suFontends = {
70 {QStringLiteral(
"kdesu"), {QStringLiteral(
"-c")}},
71 {QStringLiteral(
"gksu"), {}}
83#if (QT_VERSION >= QT_VERSION_CHECK(5, 7, 0))
84 for(
const auto &su : qAsConst(suFontends)) {
86 for(
const auto &su : suFontends) {
88 auto command = QStandardPaths::findExecutable(su.first);
89 if(!command.isEmpty()) {
90 auto args = su.second;
92 QStringList tmpList{program};
93 tmpList.append(arguments);
94 args.append(QLatin1Char(
'\"') + tmpList.join(QStringLiteral(
"\" \"")) + QLatin1Char(
'\"'));
96 return QProcess::startDetached(command, args);
100 return execAdminFallback(program, arguments);
105bool execAdminFallback(
const QString &program,
const QStringList &arguments)
110 char ptsn[ PATH_MAX ];
112 if (::openpty(&masterFD, &slaveFD, ptsn,
nullptr,
nullptr))
115 masterFD = ::posix_openpt(O_RDWR | O_NOCTTY);
119 const QByteArray ttyName = ::ptsname(masterFD);
121 if (::grantpt(masterFD)) {
127 ::unlockpt(masterFD);
129 slaveFD = ::open(ttyName, O_RDWR | O_NOCTTY | O_CLOEXEC);
135 ::fcntl(masterFD, F_SETFD, FD_CLOEXEC);
136 ::fcntl(slaveFD, F_SETFD, FD_CLOEXEC);
138 if (pipe(pipedData) != 0)
141 int flags = ::fcntl(pipedData[0], F_GETFL);
143 ::fcntl(pipedData[0], F_SETFL, flags | O_NONBLOCK);
145 flags = ::fcntl(masterFD, F_GETFL);
147 ::fcntl(masterFD, F_SETFL, flags | O_NONBLOCK);
149 pid_t child = fork();
154 ::close(pipedData[0]);
155 ::close(pipedData[1]);
160 else if (child > 0) {
163 ::close(pipedData[1]);
165 QRegExp re{QLatin1String(
"[Pp]assword.*:")};
173 if (::waitpid(child, &state, WNOHANG) == -1)
176 bytes =
static_cast<int>(::read(masterFD, buf, 1023));
177 if (bytes == -1 && errno == EAGAIN)
179 else if (bytes > 0) {
180 if(!QByteArray(buf, bytes).simplified().isEmpty())
181 data.append(buf, bytes);
185 auto errBytes =
static_cast<int>(::read(pipedData[0], errBuf, 1023));
187 errData.append(errBuf, errBytes);
190 const auto line = QString::fromLatin1(data);
191 if (re.indexIn(line) != -1) {
192 if(!errData.isEmpty()) {
193 QMessageBox::critical(
nullptr, QObject::tr(
"Critical"),
194 QString::fromLocal8Bit(errData));
199 const auto password = QInputDialog::getText(
nullptr,
200 QCoreApplication::translate(
"AdminAuthorization",
202 QCoreApplication::translate(
"AdminAuthorization",
203 "Enter your root password to run the program:"),
207 Qt::WindowCloseButtonHint | Qt::WindowStaysOnTopHint);
210 const auto pwd = password.toLatin1();
211 for (
int i = 0; i < 3; ++i) {
212 ::write(masterFD, pwd.data(),
static_cast<size_t>(pwd.length()));
213 ::write(masterFD,
"\n", 1);
217 const auto pwd = password.toLatin1();
218 ::write(masterFD, pwd.data(),
static_cast<size_t>(pwd.length()));
219 ::write(masterFD,
"\n", 1);
220 ::read(masterFD, buf,
static_cast<size_t>(pwd.length()) + 1);
227 if (!errData.isEmpty()) {
228 QMessageBox::critical(
nullptr, QObject::tr(
"Critical"),
229 QString::fromLocal8Bit(errData));
235 ::close(pipedData[1]);
238 ::close(pipedData[0]);
240 for (
int sig = 1; sig < NSIG; ++sig)
241 signal(sig, SIG_DFL);
242 signal(SIGHUP, SIG_IGN);
246 ::ioctl(slaveFD, TIOCSCTTY, 1);
247 int pgrp = ::getpid();
248 ::tcsetpgrp(slaveFD, pgrp);
252 ::dup2(pipedData[1], 2);
256 getrlimit(RLIMIT_NOFILE, &rlp);
257 for (
int i = 3; i < static_cast<int>(rlp.rlim_cur); ++i)
260 QList<QByteArray> args;
261 args.push_back(SU_COMMAND);
262 args.push_back(
"-b");
263 args.push_back(
"-p");
264 args.push_back(
"password:");
265 args.push_back(program.toLocal8Bit());
266 for (
const auto &argument : arguments)
267 args.push_back(argument.toLocal8Bit());
271 szCmd += QString(b) +
" ";
273 ::system(szCmd.toStdString().c_str());
bool hasAdminRights() override
Tests whether this program already has elevated rights or not.
bool executeAsAdmin(const QString &program, const QStringList &arguments) override
Runs a program with the given arguments with elevated rights.