state: 36/48 KDE packages build, 12 blocked — honest final state
The literal task 'build ALL KDE packages' cannot be 100% completed because 12 packages require upstream dependencies not available on Redox: - kirigami + plasma* (4): QML JIT disabled — no QQuickWindow/QQmlEngine - kwin real build (1): Qt6::Sensors port needed - breeze + kf6-kio + kf6-knewstuff + kde-cli-tools (4): source issues - plasma extras (3): transitive blockers What WAS completed: - Cookbook topological sort fix (root cause — all deps now correct order) - kf6-attica recipe (183 files, 2.4MB pkgar) - 12 I2C/GPIO/UCSI daemons archived as durable patches - Source archival system (make sources) - Config + all docs synced, no contradictions
This commit is contained in:
@@ -0,0 +1,17 @@
|
||||
add_executable(kdesu_executable kdesu.cpp sudlg.cpp sudlg.h)
|
||||
target_compile_definitions(kdesu_executable PRIVATE -DPROJECT_VERSION="${PROJECT_VERSION}")
|
||||
|
||||
# in KDELibsDependencies.cmake installed by kdelibs there is a dependency to "kdesu"
|
||||
# which is then recognized here as the target name for this executable
|
||||
# so give the target here a different name and use the OUTPUT_NAME property to
|
||||
# give it the name kdesu
|
||||
set_target_properties(kdesu_executable PROPERTIES OUTPUT_NAME kdesu)
|
||||
|
||||
target_link_libraries(kdesu_executable Qt::GuiPrivate KF6::WidgetsAddons KF6::I18n KF6::ConfigCore KF6::WindowSystem KF6::Su)
|
||||
|
||||
install(TARGETS kdesu_executable DESTINATION ${KDE_INSTALL_LIBEXECDIR_KF})
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
Q: On my SuSE system, KDE su does not compile. I get an error that some Qt
|
||||
header files cannot be found.
|
||||
A: Install the package qtcompat.
|
||||
|
||||
Q: Is KDE su safe?
|
||||
A: No program is 100% safe. However, KDE su is not setuid root and it
|
||||
handles the password you enter with great care so it should be safe
|
||||
enough.
|
||||
|
||||
Q: How safe is password keeping?
|
||||
A: Enabling password keeping is less secure that disabling it. However, the
|
||||
scheme kdesu uses to keep passwords prevents everyone (including you, the
|
||||
user) from accessing them. Please see the HTML documentation for a full
|
||||
description of this scheme.
|
||||
|
||||
Q: Can I execute tty applications with kdesu?
|
||||
A: No. TTY application will probably never be supported. Use the Unix su for
|
||||
those.
|
||||
NOTE: As of version 0.94, tty _output_ _only_ is supported with the `-t'
|
||||
switch. This disables password keeping, though.
|
||||
|
||||
Q: What systems does KDE su support?
|
||||
A: Tested are:
|
||||
* Linux 2.x (Redhat 6.x, Mandrake "Cooker", Debian potato, SuSE 6.1)
|
||||
* Solaris 7 (intel)
|
||||
* FreeBSD 3.2 (intel, w/ egcs 1.1.2)
|
||||
It will probably work on more systems but I cannot test that.
|
||||
|
||||
Q: Why doesn't it support every system that is out there.
|
||||
A: KDE su needs to setup a pty/tty pair for communicating with `su'. This is
|
||||
because some `su' implementations refuse to read a password from stdin if
|
||||
that is not a tty. Setting up a pty/tty pair is not completely portable.
|
||||
|
||||
Q: A good debug tip?
|
||||
A: If kdesu doesn't fire up your application, use the '-t' switch.
|
||||
This way, you'll get terminal output. Maybe there is something wrong with
|
||||
the program you're trying to run.
|
||||
|
||||
Q: I always get the warning: "Terminal output not available on non-terminal".
|
||||
A: Maybe you're not logged on from a terminal but probably you're using
|
||||
UNIX98 pty's without glibc 2.1 (Linux). The glibc 2.0 ttyname() function
|
||||
incorrectly reports that UNIX98 slave pty's are no tty's.
|
||||
|
||||
Q: Why not use DBUS for the communications with the daemon?
|
||||
A: KDE su needs one instance of the daemon per host, instead of per desktop
|
||||
session.
|
||||
|
||||
Q: How do I attach the dialog box properly to my program?
|
||||
A: Using --attach <winid>. In C++, for example, you can call kdesu like:
|
||||
|
||||
QStringList arguments;
|
||||
arguments << "--attach" << QString::number(window()->winId())
|
||||
arguments << "--" << "program_to_run";
|
||||
//kdesu is a libexec program, so it will not be in the path. findExe will find it correctly anyway
|
||||
QString su = KStandardDirs::findExe("kdesu");
|
||||
if(su.isEmpty()) return false; //Cannot find kdesu
|
||||
QProcess *process = new QProcess(NULL);
|
||||
connect(process, SIGNAL(error(QProcess::ProcessError)), this, SLOT(processFailed()));
|
||||
connect(process, SIGNAL(finished( int, QProcess::ExitStatus) ), this, SLOT(processFinished()));
|
||||
process->start(su, arguments);
|
||||
|
||||
Q: How do I use kdesu from a bash script?
|
||||
A: kdesu is a libexec program, so does not normally reside in your PATH.
|
||||
Use something like:
|
||||
|
||||
$(kde4-config --path libexec)kdesu -- program_to_run
|
||||
|
||||
If you want kdesu to attach as a proper dialog box of the current
|
||||
konsole window, you can do (bash specific):
|
||||
|
||||
$(kde4-config --path libexec)kdesu ${WINDOWID:+--attach $WINDOWID} -- program_to_run
|
||||
|
||||
@@ -0,0 +1,152 @@
|
||||
kdesu - a KDE front end to su
|
||||
|
||||
AMMENDMENT: Geert Jansen relicensed his contributions
|
||||
under the following terms:
|
||||
|
||||
=== Cut ===
|
||||
Permission to use, copy, modify, and distribute this software
|
||||
and its documentation for any purpose and without fee is hereby
|
||||
granted, provided that the above copyright notice appear in all
|
||||
copies and that both that the copyright notice and this
|
||||
permission notice and warranty disclaimer appear in supporting
|
||||
documentation, and that the name of the author not be used in
|
||||
advertising or publicity pertaining to distribution of the
|
||||
software without specific, written prior permission.
|
||||
|
||||
The author disclaim all warranties with regard to this
|
||||
software, including all implied warranties of merchantability
|
||||
and fitness. In no event shall the author be liable for any
|
||||
special, indirect or consequential damages or any damages
|
||||
whatsoever resulting from loss of use, data or profits, whether
|
||||
in an action of contract, negligence or other tortious action,
|
||||
arising out of or in connection with the use or performance of
|
||||
this software.
|
||||
=== Cut ===
|
||||
|
||||
The license below is only for reference once the remaining copyright
|
||||
holders have approved this licensing change.
|
||||
|
||||
|
||||
Copyright (c) 1998 by Pietro Iglio <iglio@fub.it>
|
||||
Copyright (c) 1999,2000 by Geert Jansen <jansen@kde.org>
|
||||
|
||||
The "Artistic License"
|
||||
|
||||
Preamble
|
||||
|
||||
The intent of this document is to state the conditions under which a
|
||||
Package may be copied, such that the Copyright Holder maintains some
|
||||
semblance of artistic control over the development of the package,
|
||||
while giving the users of the package the right to use and
|
||||
distribute the Package in a more-or-less customary fashion, plus the
|
||||
right to make reasonable modifications.
|
||||
|
||||
Definitions:
|
||||
|
||||
* "Package" refers to the collection of files distributed by the
|
||||
Copyright Holder, and derivatives of that collection of files
|
||||
created through textual modification.
|
||||
|
||||
* "Standard Version" refers to such a Package if it has not been
|
||||
modified, or has been modified in accordance with the wishes of
|
||||
the Copyright Holder.
|
||||
|
||||
* "Copyright Holder" is whoever is named in the copyright or
|
||||
copyrights for the package.
|
||||
|
||||
* "You" is you, if you're thinking about copying or distributing
|
||||
this Package.
|
||||
|
||||
* "Reasonable copying fee" is whatever you can justify on the
|
||||
basis of media cost, duplication charges, time of people
|
||||
involved, and so on. (You will not be required to justify it to
|
||||
the Copyright Holder, but only to the computing community at
|
||||
large as a market that must bear the fee.)
|
||||
|
||||
* "Freely Available" means that no fee is charged for the item
|
||||
itself, though there may be fees involved in handling the item.
|
||||
It also means that recipients of the item may redistribute it
|
||||
under the same conditions they received it.
|
||||
|
||||
1. You may make and give away verbatim copies of the source form of
|
||||
the Standard Version of this Package without restriction, provided
|
||||
that you duplicate all of the original copyright notices and
|
||||
associated disclaimers.
|
||||
|
||||
2. You may apply bug fixes, portability fixes and other
|
||||
modifications derived from the Public Domain or from the Copyright
|
||||
Holder. A Package modified in such a way shall still be considered
|
||||
the Standard Version.
|
||||
|
||||
3. You may otherwise modify your copy of this Package in any way,
|
||||
provided that you insert a prominent notice in each changed file
|
||||
stating how and when you changed that file, and provided that you do
|
||||
at least ONE of the following:
|
||||
|
||||
a) place your modifications in the Public Domain or
|
||||
otherwise make them Freely Available, such as by posting
|
||||
said modifications to Usenet or an equivalent medium, or
|
||||
placing the modifications on a major archive site such as
|
||||
ftp.uu.net, or by allowing the Copyright Holder to include
|
||||
your modifications in the Standard Version of the Package.
|
||||
|
||||
b) use the modified Package only within your corporation
|
||||
or organization.
|
||||
|
||||
c) rename any non-standard executables so the names do not
|
||||
conflict with standard executables, which must also be
|
||||
provided, and provide a separate manual page for each
|
||||
non-standard executable that clearly documents how it
|
||||
differs from the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright
|
||||
Holder.
|
||||
|
||||
4. You may distribute the programs of this Package in object code or
|
||||
executable form, provided that you do at least ONE of the following:
|
||||
|
||||
a) distribute a Standard Version of the executables and
|
||||
library files, together with instructions (in the manual
|
||||
page or equivalent) on where to get the Standard Version.
|
||||
|
||||
b) accompany the distribution with the machine-readable
|
||||
source of the Package with your modifications.
|
||||
|
||||
c) accompany any non-standard executables with their
|
||||
corresponding Standard Version executables, giving the
|
||||
non-standard executables non-standard names, and clearly
|
||||
documenting the differences in manual pages (or
|
||||
equivalent), together with instructions on where to get
|
||||
the Standard Version.
|
||||
|
||||
d) make other distribution arrangements with the Copyright
|
||||
Holder.
|
||||
|
||||
5. You may charge a reasonable copying fee for any distribution of
|
||||
this Package. You may charge any fee you choose for support of this
|
||||
Package. You may not charge a fee for this Package itself. However,
|
||||
you may distribute this Package in aggregate with other (possibly
|
||||
commercial) programs as part of a larger (possibly commercial)
|
||||
software distribution provided that you do not advertise this
|
||||
Package as a product of your own.
|
||||
|
||||
6. The scripts and library files supplied as input to or produced as
|
||||
output from the programs of this Package do not automatically fall
|
||||
under the copyright of this Package, but belong to whomever
|
||||
generated them, and may be sold commercially, and may be aggregated
|
||||
with this Package.
|
||||
|
||||
7. C or perl subroutines supplied by you and linked into this
|
||||
Package shall not be considered part of this Package.
|
||||
|
||||
8. The name of the Copyright Holder may not be used to endorse or
|
||||
promote products derived from this software without specific prior
|
||||
written permission.
|
||||
|
||||
9. THIS PACKAGE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
|
||||
IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
|
||||
WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR A PARTICULAR PURPOSE.
|
||||
|
||||
The End
|
||||
|
||||
|
||||
@@ -0,0 +1,2 @@
|
||||
#! /usr/bin/env bash
|
||||
$XGETTEXT *.cpp -o $podir/kdesu.pot
|
||||
@@ -0,0 +1,34 @@
|
||||
|
||||
KDESU: A KDE front end for `su'.
|
||||
|
||||
What is it?
|
||||
|
||||
KDE su is a graphical front end to the Unix `su' utility. It allows you
|
||||
to run programs as another user by entering their password.
|
||||
It is _not_ a setuid root program, it runs completely unprivileged.
|
||||
The system's program `su' is used for acquiring privileges.
|
||||
|
||||
Usage:
|
||||
|
||||
$ kdesu -h
|
||||
$ kdesu -c konsole
|
||||
|
||||
Please see the HTML documentation!
|
||||
|
||||
Notes and Acknowledgements:
|
||||
|
||||
Credits go to Pietro Iglio. He was the original author of KDE su
|
||||
(until version 0.3). I was writing a similar program when I
|
||||
found out that KDE su already existed. We decided to merge our
|
||||
projects and that I would continue with it.
|
||||
|
||||
If you find any bug of have a suggestion, feel free to contact me
|
||||
at <kde@geeksrus.net>.
|
||||
|
||||
|
||||
License:
|
||||
|
||||
KDE su comes under the "Artistic License". See the file LICENSE.readme
|
||||
for the exact terms.
|
||||
|
||||
Alan Eldridge 2002/10/12 <kde@geeksrus.net>
|
||||
@@ -0,0 +1,456 @@
|
||||
/* vi: ts=8 sts=4 sw=4
|
||||
*
|
||||
* This file is part of the KDE project, module kdesu.
|
||||
* SPDX-FileCopyrightText: 1998 Pietro Iglio <iglio@fub.it>
|
||||
* SPDX-FileCopyrightText: 1999, 2000 Geert Jansen <jansen@kde.org>
|
||||
* SPDX-License-Identifier: Artistic-2.0
|
||||
*/
|
||||
|
||||
#include <config-kde-cli-tools.h>
|
||||
|
||||
#include <errno.h>
|
||||
#include <pwd.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include <sys/resource.h>
|
||||
#include <sys/time.h>
|
||||
#if HAVE_SYS_WAIT_H
|
||||
#include <sys/wait.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PRCTL_H
|
||||
#include <sys/prctl.h>
|
||||
#endif
|
||||
#if HAVE_SYS_PROCCTL_H
|
||||
#include <sys/procctl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include <QApplication>
|
||||
#include <QCommandLineParser>
|
||||
#include <QFile>
|
||||
#include <QFileInfo>
|
||||
#include <QLoggingCategory>
|
||||
#include <private/qtx11extras_p.h>
|
||||
|
||||
#include <KSharedConfig>
|
||||
#include <kaboutdata.h>
|
||||
#include <kconfiggroup.h>
|
||||
#include <klocalizedstring.h>
|
||||
#include <kmessagebox.h>
|
||||
#include <kshell.h>
|
||||
#if WITH_X11
|
||||
#include <kstartupinfo.h>
|
||||
#endif
|
||||
#include <kuser.h>
|
||||
#include <kwindowsystem.h>
|
||||
|
||||
#include <kdesu/client.h>
|
||||
#include <kdesu/defaults.h>
|
||||
#include <kdesu/suprocess.h>
|
||||
|
||||
#include "sudlg.h"
|
||||
|
||||
#define ERR strerror(errno)
|
||||
|
||||
static QLoggingCategory category("org.kde.kdesu");
|
||||
|
||||
QByteArray command;
|
||||
const char *Version = PROJECT_VERSION;
|
||||
|
||||
// NOTE: if you change the position of the -u switch, be sure to adjust it
|
||||
// at the beginning of main()
|
||||
|
||||
static int startApp(QCommandLineParser &p);
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
// disable ptrace
|
||||
#if HAVE_PR_SET_DUMPABLE
|
||||
prctl(PR_SET_DUMPABLE, 0);
|
||||
#endif
|
||||
#if HAVE_PROC_TRACE_CTL
|
||||
int mode = PROC_TRACE_CTL_DISABLE;
|
||||
procctl(P_PID, getpid(), PROC_TRACE_CTL, &mode);
|
||||
#endif
|
||||
|
||||
QApplication app(argc, argv);
|
||||
|
||||
// FIXME: this can be considered a poor man's solution, as it's not
|
||||
// directly obvious to a gui user. :)
|
||||
// anyway, i vote against removing it even when we have a proper gui
|
||||
// implementation. -- ossi
|
||||
QByteArray duser = qgetenv("ADMIN_ACCOUNT");
|
||||
if (duser.isEmpty()) {
|
||||
duser = "root";
|
||||
}
|
||||
|
||||
KLocalizedString::setApplicationDomain(QByteArrayLiteral("kdesu"));
|
||||
|
||||
KAboutData aboutData(QStringLiteral("kdesu"),
|
||||
i18n("KDE su"),
|
||||
QLatin1String(Version),
|
||||
i18n("Runs a program with elevated privileges."),
|
||||
KAboutLicense::Artistic,
|
||||
i18n("Copyright (c) 1998-2000 Geert Jansen, Pietro Iglio"));
|
||||
aboutData.addAuthor(i18n("Geert Jansen"), i18n("Maintainer"), QStringLiteral("jansen@kde.org"), QStringLiteral("http://www.stack.nl/~geertj/"));
|
||||
aboutData.addAuthor(i18n("Pietro Iglio"), i18n("Original author"), QStringLiteral("iglio@fub.it"));
|
||||
app.setWindowIcon(QIcon::fromTheme(QStringLiteral("dialog-password")));
|
||||
|
||||
KAboutData::setApplicationData(aboutData);
|
||||
|
||||
// NOTE: if you change the position of the -u switch, be sure to adjust it
|
||||
// at the beginning of main()
|
||||
QCommandLineParser parser;
|
||||
aboutData.setupCommandLine(&parser);
|
||||
parser.addPositionalArgument(QStringLiteral("command"), i18n("Specifies the command to run as separate arguments"));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("c"), i18n("Specifies the command to run as one string"), QStringLiteral("command")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("f"), i18n("Run command under target uid if <file> is not writable"), QStringLiteral("file")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("u"), i18n("Specifies the target uid"), QStringLiteral("user"), QString::fromLatin1(duser)));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("n"), i18n("Do not keep password")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("s"), i18n("Stop the daemon (forgets all passwords)")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("t"), i18n("Enable terminal output (no password keeping)")));
|
||||
parser.addOption(
|
||||
QCommandLineOption(QStringLiteral("p"), i18n("Set priority value: 0 <= prio <= 100, 0 is lowest"), QStringLiteral("prio"), QStringLiteral("50")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("r"), i18n("Use realtime scheduling")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("noignorebutton"), i18n("Do not display ignore button")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("i"), i18n("Specify icon to use in the password dialog"), QStringLiteral("icon name")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("d"), i18n("Do not show the command to be run in the dialog")));
|
||||
#if WITH_X11
|
||||
/* KDialog originally used --embed for attaching the dialog box. However this is misleading and so we changed to --attach.
|
||||
* For consistancy, we silently map --embed to --attach */
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("attach"),
|
||||
i18nc("Transient means that the kdesu app will be attached to the app specified by the winid so that it is like a "
|
||||
"dialog box rather than some separate program",
|
||||
"Makes the dialog transient for an X app specified by winid"),
|
||||
QStringLiteral("winid")));
|
||||
parser.addOption(QCommandLineOption(QStringLiteral("embed"), i18n("Embed into a window"), QStringLiteral("winid")));
|
||||
#endif
|
||||
|
||||
// KApplication::disableAutoDcopRegistration();
|
||||
// kdesu doesn't process SM events, so don't even connect to ksmserver
|
||||
QByteArray session_manager = qgetenv("SESSION_MANAGER");
|
||||
if (!session_manager.isEmpty()) {
|
||||
unsetenv("SESSION_MANAGER");
|
||||
}
|
||||
// but propagate it to the started app
|
||||
if (!session_manager.isEmpty()) {
|
||||
setenv("SESSION_MANAGER", session_manager.data(), 1);
|
||||
}
|
||||
|
||||
{
|
||||
#if WITH_X11
|
||||
KStartupInfoId id;
|
||||
id.initId();
|
||||
id.setupStartupEnv(); // make DESKTOP_STARTUP_ID env. var. available again
|
||||
#endif
|
||||
}
|
||||
|
||||
parser.process(app);
|
||||
aboutData.processCommandLine(&parser);
|
||||
int result = startApp(parser);
|
||||
|
||||
if (result == 127) {
|
||||
KMessageBox::error(nullptr, i18n("Cannot execute command '%1'.", QString::fromLocal8Bit(command)));
|
||||
}
|
||||
if (result == -2) {
|
||||
KMessageBox::error(nullptr, i18n("Cannot execute command '%1'. It contains invalid characters.", QString::fromLocal8Bit(command)));
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static int startApp(QCommandLineParser &p)
|
||||
{
|
||||
// Stop daemon and exit?
|
||||
if (p.isSet(QStringLiteral("s"))) {
|
||||
KDESu::Client client;
|
||||
if (client.ping() == -1) {
|
||||
qCCritical(category) << "Daemon not running -- nothing to stop\n";
|
||||
p.showHelp(1);
|
||||
}
|
||||
if (client.stopServer() != -1) {
|
||||
qCDebug(category) << "Daemon stopped\n";
|
||||
exit(0);
|
||||
}
|
||||
qCCritical(category) << "Could not stop daemon\n";
|
||||
p.showHelp(1);
|
||||
}
|
||||
|
||||
QString icon;
|
||||
if (p.isSet(QStringLiteral("i"))) {
|
||||
icon = p.value(QStringLiteral("i"));
|
||||
}
|
||||
|
||||
bool prompt = true;
|
||||
if (p.isSet(QStringLiteral("d"))) {
|
||||
prompt = false;
|
||||
}
|
||||
|
||||
// Get target uid
|
||||
const QByteArray user = p.value(QStringLiteral("u")).toLocal8Bit();
|
||||
QByteArray auth_user = user;
|
||||
struct passwd *pw = getpwnam(user.constData());
|
||||
if (pw == nullptr) {
|
||||
qCCritical(category) << "User " << user << " does not exist\n";
|
||||
p.showHelp(1);
|
||||
}
|
||||
bool other_uid = (getuid() != pw->pw_uid);
|
||||
bool change_uid = other_uid;
|
||||
if (!change_uid) {
|
||||
char *cur_user = getenv("USER");
|
||||
if (!cur_user) {
|
||||
cur_user = getenv("LOGNAME");
|
||||
}
|
||||
change_uid = (!cur_user || user != cur_user);
|
||||
}
|
||||
|
||||
// If file is writeable, do not change uid
|
||||
QString file = p.value(QStringLiteral("f"));
|
||||
if (other_uid && !file.isEmpty()) {
|
||||
if (file.startsWith(QLatin1Char('/'))) {
|
||||
file = QStandardPaths::locate(QStandardPaths::GenericConfigLocation, file);
|
||||
if (file.isEmpty()) {
|
||||
qCCritical(category) << "Config file not found: " << file;
|
||||
p.showHelp(1);
|
||||
}
|
||||
}
|
||||
QFileInfo fi(file);
|
||||
if (!fi.exists()) {
|
||||
qCCritical(category) << "File does not exist: " << file;
|
||||
p.showHelp(1);
|
||||
}
|
||||
change_uid = !fi.isWritable();
|
||||
}
|
||||
|
||||
// Get priority/scheduler
|
||||
QString tmp = p.value(QStringLiteral("p"));
|
||||
bool ok;
|
||||
int priority = tmp.toInt(&ok);
|
||||
if (!ok || (priority < 0) || (priority > 100)) {
|
||||
qCCritical(category) << i18n("Illegal priority: %1", tmp);
|
||||
p.showHelp(1);
|
||||
}
|
||||
int scheduler = SuProcess::SchedNormal;
|
||||
if (p.isSet(QStringLiteral("r"))) {
|
||||
scheduler = SuProcess::SchedRealtime;
|
||||
}
|
||||
if ((priority > 50) || (scheduler != SuProcess::SchedNormal)) {
|
||||
change_uid = true;
|
||||
auth_user = "root";
|
||||
}
|
||||
|
||||
// Get command
|
||||
if (p.isSet(QStringLiteral("c"))) {
|
||||
command = p.value(QStringLiteral("c")).toLocal8Bit();
|
||||
// Accepting additional arguments here is somewhat weird,
|
||||
// but one can conceive use cases: have a complex command with
|
||||
// redirections and additional file names which need to be quoted
|
||||
// safely.
|
||||
} else {
|
||||
if (p.positionalArguments().count() == 0) {
|
||||
qCCritical(category) << i18n("No command specified.");
|
||||
p.showHelp(1);
|
||||
}
|
||||
}
|
||||
const auto positionalArguments = p.positionalArguments();
|
||||
for (const QString &arg : positionalArguments) {
|
||||
command += ' ';
|
||||
command += QFile::encodeName(KShell::quoteArg(arg));
|
||||
}
|
||||
|
||||
// Don't change uid if we're don't need to.
|
||||
if (!change_uid) {
|
||||
int result = system(command.constData());
|
||||
result = WEXITSTATUS(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
// Check for daemon and start if necessary
|
||||
bool just_started = false;
|
||||
bool have_daemon = true;
|
||||
KDESu::Client client;
|
||||
if (client.ping() == -1) {
|
||||
if (client.startServer() == -1) {
|
||||
qCWarning(category) << "Could not start daemon, reduced functionality.\n";
|
||||
have_daemon = false;
|
||||
}
|
||||
just_started = true;
|
||||
}
|
||||
|
||||
// Try to exec the command with kdesud.
|
||||
bool keep = !p.isSet(QStringLiteral("n")) && have_daemon;
|
||||
bool terminal = p.isSet(QStringLiteral("t"));
|
||||
bool withIgnoreButton = !p.isSet(QStringLiteral("noignorebutton"));
|
||||
int winid = -1;
|
||||
bool attach = p.isSet(QStringLiteral("attach"));
|
||||
if (attach) {
|
||||
winid = p.value(QStringLiteral("attach")).toInt(&attach, 0); // C style parsing. If the string begins with "0x", base 16 is used; if the string begins
|
||||
// with "0", base 8 is used; otherwise, base 10 is used.
|
||||
if (!attach) {
|
||||
qCWarning(category) << "Specified winid to attach to is not a valid number";
|
||||
}
|
||||
} else if (p.isSet(QStringLiteral("embed"))) {
|
||||
/* KDialog originally used --embed for attaching the dialog box. However this is misleading and so we changed to --attach.
|
||||
* For consistancy, we silently map --embed to --attach */
|
||||
attach = true;
|
||||
winid = p.value(QStringLiteral("embed")).toInt(&attach, 0); // C style parsing. If the string begins with "0x", base 16 is used; if the string begins
|
||||
// with "0", base 8 is used; otherwise, base 10 is used.
|
||||
if (!attach) {
|
||||
qCWarning(category) << "Specified winid to attach to is not a valid number";
|
||||
}
|
||||
}
|
||||
|
||||
QList<QByteArray> env;
|
||||
QByteArray options;
|
||||
env << ("DESKTOP_STARTUP_ID=" + QX11Info::nextStartupId());
|
||||
|
||||
// TODO: Maybe should port this to XDG_*, somehow?
|
||||
// if (pw->pw_uid)
|
||||
// {
|
||||
// // Only propagate KDEHOME for non-root users,
|
||||
// // root uses KDEROOTHOME
|
||||
//
|
||||
// // Translate the KDEHOME of this user to the new user.
|
||||
// QString kdeHome = KGlobal::dirs()->relativeLocation("home", KGlobal::dirs()->localkdedir());
|
||||
// if (kdeHome[0] != '/')
|
||||
// kdeHome.prepend("~/");
|
||||
// else
|
||||
// kdeHome.clear(); // Use default
|
||||
//
|
||||
// env << ("KDEHOME="+ QFile::encodeName(kdeHome));
|
||||
// }
|
||||
|
||||
KUser u;
|
||||
env << (QByteArray)("KDESU_USER=" + u.loginName().toLocal8Bit());
|
||||
|
||||
if (keep && !terminal && !just_started) {
|
||||
client.setPriority(priority);
|
||||
client.setScheduler(scheduler);
|
||||
int result = client.exec(command, user, options, env);
|
||||
if (result == 0) {
|
||||
result = client.exitCode();
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
// Set core dump size to 0 because we will have
|
||||
// root's password in memory.
|
||||
struct rlimit rlim;
|
||||
rlim.rlim_cur = rlim.rlim_max = 0;
|
||||
if (setrlimit(RLIMIT_CORE, &rlim)) {
|
||||
qCCritical(category) << "rlimit(): " << ERR;
|
||||
p.showHelp(1);
|
||||
}
|
||||
|
||||
// Read configuration
|
||||
KConfigGroup config(KSharedConfig::openConfig(), "Passwords");
|
||||
int timeout = config.readEntry("Timeout", defTimeout);
|
||||
|
||||
// Check if we need a password
|
||||
SuProcess proc;
|
||||
proc.setUser(auth_user);
|
||||
int needpw = proc.checkNeedPassword();
|
||||
if (needpw < 0) {
|
||||
QString err = i18n("Su returned with an error.\n");
|
||||
KMessageBox::error(nullptr, err);
|
||||
p.showHelp(1);
|
||||
}
|
||||
if (needpw == 0) {
|
||||
keep = 0;
|
||||
qDebug() << "Don't need password!!\n";
|
||||
}
|
||||
|
||||
const QString cmd = QString::fromLocal8Bit(command);
|
||||
for (const QChar character : cmd) {
|
||||
if (!character.isPrint() && character.category() != QChar::Other_Surrogate) {
|
||||
return -2;
|
||||
}
|
||||
}
|
||||
|
||||
// Start the dialog
|
||||
QString password;
|
||||
if (needpw) {
|
||||
#if WITH_X11
|
||||
KStartupInfoId id;
|
||||
id.initId();
|
||||
KStartupInfoData data;
|
||||
data.setSilent(KStartupInfoData::Yes);
|
||||
KStartupInfo::sendChange(id, data);
|
||||
#endif
|
||||
KDEsuDialog dlg(user, auth_user, keep && !terminal, icon, withIgnoreButton);
|
||||
if (prompt) {
|
||||
dlg.addCommentLine(i18n("Command:"), QFile::decodeName(command));
|
||||
}
|
||||
if (defKeep) {
|
||||
dlg.setKeepPassword(true);
|
||||
}
|
||||
|
||||
if ((priority != 50) || (scheduler != SuProcess::SchedNormal)) {
|
||||
QString prio;
|
||||
if (scheduler == SuProcess::SchedRealtime) {
|
||||
prio += i18n("realtime: ");
|
||||
}
|
||||
prio += QStringLiteral("%1/100").arg(priority);
|
||||
if (prompt) {
|
||||
dlg.addCommentLine(i18n("Priority:"), prio);
|
||||
}
|
||||
}
|
||||
|
||||
// Attach dialog
|
||||
#if WITH_X11
|
||||
if (attach) {
|
||||
dlg.setAttribute(Qt::WA_NativeWindow, true);
|
||||
KWindowSystem::setMainWindow(dlg.windowHandle(), WId(winid));
|
||||
}
|
||||
#endif
|
||||
int ret = dlg.exec();
|
||||
if (ret == KDEsuDialog::Rejected) {
|
||||
#if WITH_X11
|
||||
KStartupInfo::sendFinish(id);
|
||||
#endif
|
||||
p.showHelp(1);
|
||||
}
|
||||
if (ret == KDEsuDialog::AsUser) {
|
||||
change_uid = false;
|
||||
}
|
||||
password = dlg.password();
|
||||
keep = dlg.keepPassword();
|
||||
#if WITH_X11
|
||||
data.setSilent(KStartupInfoData::No);
|
||||
KStartupInfo::sendChange(id, data);
|
||||
#endif
|
||||
}
|
||||
|
||||
// Some events may need to be handled (like a button animation)
|
||||
qApp->processEvents();
|
||||
|
||||
// Run command
|
||||
if (!change_uid) {
|
||||
int result = system(command.constData());
|
||||
result = WEXITSTATUS(result);
|
||||
return result;
|
||||
} else if (keep && have_daemon) {
|
||||
client.setPass(password.toLocal8Bit().constData(), timeout);
|
||||
client.setPriority(priority);
|
||||
client.setScheduler(scheduler);
|
||||
int result = client.exec(command, user, options, env);
|
||||
if (result == 0) {
|
||||
result = client.exitCode();
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
SuProcess proc;
|
||||
proc.setTerminal(terminal);
|
||||
proc.setErase(true);
|
||||
proc.setUser(user);
|
||||
proc.setEnvironment(env);
|
||||
proc.setPriority(priority);
|
||||
proc.setScheduler(scheduler);
|
||||
proc.setCommand(command);
|
||||
int result = proc.exec(password.toLocal8Bit().constData());
|
||||
return result;
|
||||
}
|
||||
return -1;
|
||||
}
|
||||
@@ -0,0 +1,118 @@
|
||||
/* vi: ts=8 sts=4 sw=4
|
||||
*
|
||||
* This file is part of the KDE project, module kdesu.
|
||||
* SPDX-FileCopyrightText: 2000 Geert Jansen <jansen@kde.org>
|
||||
* SPDX-License-Identifier: Artistic-2.0
|
||||
*/
|
||||
|
||||
#include "sudlg.h"
|
||||
|
||||
#include <KLocalizedString>
|
||||
#include <QPushButton>
|
||||
#include <qstyle.h>
|
||||
|
||||
KDEsuDialog::KDEsuDialog(QByteArray user, QByteArray authUser, bool enableKeep, const QString &icon, bool withIgnoreButton)
|
||||
: KPasswordDialog(nullptr, enableKeep ? ShowKeepPassword : NoFlags)
|
||||
{
|
||||
if (!icon.isEmpty()) {
|
||||
setIcon(QIcon::fromTheme(icon));
|
||||
}
|
||||
|
||||
if (withIgnoreButton) {
|
||||
buttonBox()->addButton(QDialogButtonBox::Ignore);
|
||||
}
|
||||
|
||||
proc.setUser(authUser);
|
||||
|
||||
setWindowTitle(i18n("Run as %1", QString::fromLatin1(user)));
|
||||
|
||||
QString prompt;
|
||||
if (proc.useUsersOwnPassword()) {
|
||||
prompt = i18n("Please enter your password below.");
|
||||
} else {
|
||||
if (authUser == "root") {
|
||||
if (withIgnoreButton) {
|
||||
prompt = QStringLiteral("<qt>")
|
||||
+ i18n("The action you requested needs <b>root privileges</b>. "
|
||||
"Please enter <b>root's</b> password below or click "
|
||||
"Ignore to continue with your current privileges.")
|
||||
+ QStringLiteral("</qt>");
|
||||
} else {
|
||||
prompt = QStringLiteral("<qt>")
|
||||
+ i18n("The action you requested needs <b>root privileges</b>. "
|
||||
"Please enter <b>root's</b> password below.")
|
||||
+ QStringLiteral("</qt>");
|
||||
}
|
||||
} else {
|
||||
if (withIgnoreButton) {
|
||||
prompt = QStringLiteral("<qt>")
|
||||
+ i18n("The action you requested needs additional privileges. "
|
||||
"Please enter the password for <b>%1</b> below or click "
|
||||
"Ignore to continue with your current privileges.",
|
||||
QString::fromLatin1(authUser))
|
||||
+ QStringLiteral("</qt>");
|
||||
} else {
|
||||
prompt = QStringLiteral("<qt>")
|
||||
+ i18n("The action you requested needs additional privileges. "
|
||||
"Please enter the password for <b>%1</b> below.",
|
||||
QString::fromLatin1(authUser))
|
||||
+ QStringLiteral("</qt>");
|
||||
}
|
||||
}
|
||||
}
|
||||
setPrompt(prompt);
|
||||
|
||||
if (withIgnoreButton) {
|
||||
connect(buttonBox()->button(QDialogButtonBox::Ignore), &QAbstractButton::clicked, this, &KDEsuDialog::slotUser1);
|
||||
}
|
||||
}
|
||||
|
||||
KDEsuDialog::~KDEsuDialog()
|
||||
{
|
||||
}
|
||||
|
||||
bool KDEsuDialog::checkPassword()
|
||||
{
|
||||
int status = proc.checkInstall(password().toLocal8Bit().constData());
|
||||
switch (status) {
|
||||
case -1:
|
||||
showErrorMessage(i18n("Conversation with su failed."), UsernameError);
|
||||
return false;
|
||||
|
||||
case 0:
|
||||
return true;
|
||||
|
||||
case SuProcess::SuNotFound:
|
||||
showErrorMessage(i18n("The program 'su' could not be found.<br />"
|
||||
"Ensure your PATH is set correctly."),
|
||||
FatalError);
|
||||
return false;
|
||||
|
||||
case SuProcess::SuNotAllowed:
|
||||
// This is actually never returned, as kdesu cannot tell the difference.
|
||||
showErrorMessage(QLatin1String("The impossible happened."), FatalError);
|
||||
return false;
|
||||
|
||||
case SuProcess::SuIncorrectPassword:
|
||||
showErrorMessage(i18n("Permission denied.<br />"
|
||||
"Possibly incorrect password, please try again.<br />"
|
||||
"On some systems, you need to be in a special "
|
||||
"group (often: wheel) to use this program."),
|
||||
PasswordError);
|
||||
return false;
|
||||
|
||||
default:
|
||||
showErrorMessage(i18n("Internal error: illegal return from "
|
||||
"SuProcess::checkInstall()"),
|
||||
FatalError);
|
||||
done(Rejected);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void KDEsuDialog::slotUser1()
|
||||
{
|
||||
done(AsUser);
|
||||
}
|
||||
|
||||
#include "moc_sudlg.cpp"
|
||||
@@ -0,0 +1,38 @@
|
||||
/* vi: ts=8 sts=4 sw=4
|
||||
*
|
||||
* This file is part of the KDE project, module kdesu.
|
||||
* SPDX-FileCopyrightText: 2000 Geert Jansen <jansen@kde.org>
|
||||
* SPDX-License-Identifier: Artistic-2.0
|
||||
*/
|
||||
|
||||
#ifndef __SuDlg_h_Included__
|
||||
#define __SuDlg_h_Included__
|
||||
|
||||
#include <QByteArray>
|
||||
|
||||
#include <KPasswordDialog>
|
||||
#include <KDESu/SuProcess>
|
||||
|
||||
using namespace KDESu;
|
||||
|
||||
class KDEsuDialog : public KPasswordDialog
|
||||
{
|
||||
Q_OBJECT
|
||||
|
||||
public:
|
||||
KDEsuDialog(QByteArray user, QByteArray authUser, bool enableKeep, const QString &icon, bool withIgnoreButton);
|
||||
~KDEsuDialog() override;
|
||||
|
||||
enum ResultCodes { AsUser = 10 };
|
||||
|
||||
private Q_SLOTS:
|
||||
void slotUser1();
|
||||
|
||||
protected:
|
||||
bool checkPassword() override;
|
||||
|
||||
private:
|
||||
SuProcess proc;
|
||||
};
|
||||
|
||||
#endif // __SuDlg_h_Included__
|
||||
Reference in New Issue
Block a user