generic: replace kdesu with kdesudo

Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
Ivailo Monev 2016-05-15 02:42:57 +00:00
parent 4b9f0ef959
commit f87760f410
35 changed files with 41 additions and 2801 deletions

View file

@ -11,13 +11,6 @@ include(KDE4Defaults)
option(WITH_XINERAMA "Xinerama support for multi-headed X displays" ON)
find_package(Strigi)
set_package_properties(Strigi PROPERTIES
DESCRIPTION "Desktop indexing and search support"
URL "http://strigi.sourceforge.net"
TYPE REQUIRED
)
find_package(ZLIB)
set_package_properties(ZLIB PROPERTIES
DESCRIPTION "Support for gzip compressed files and data streams"
@ -257,7 +250,6 @@ macro_optional_add_subdirectory(statusnotifierwatcher)
macro_optional_add_subdirectory(kstyles)
# imported from kde-runtime and other sub-projects
macro_optional_add_subdirectory(kdesu)
macro_optional_add_subdirectory(menu)
macro_optional_add_subdirectory(kwalletd)
macro_optional_add_subdirectory(kwalletmanager)

View file

@ -92,7 +92,6 @@ macro_bool_to_01(X11_XSync_FOUND HAVE_XSYNC) # kwin
set(CMAKE_EXTRA_INCLUDE_FILES sys/socket.h)
check_type_size("struct ucred" STRUCT_UCRED) # kio_fonts
check_function_exists(getpeereid HAVE_GETPEEREID) # kdesu
check_function_exists(setpriority HAVE_SETPRIORITY) # kscreenlocker
set(CMAKE_REQUIRED_INCLUDES ${X11_Xrandr_INCLUDE_PATH}/Xrandr.h)

View file

@ -21,9 +21,6 @@
/* Define if you have the gethostname prototype */
#cmakedefine HAVE_GETHOSTNAME_PROTO 1
/* Define to 1 if you have the `getpeereid' function. */
#cmakedefine HAVE_GETPEEREID 1
/* Defines if you have Solaris' libkstat */
/* #undef HAVE_KSTAT */

View file

@ -55,8 +55,6 @@
#include <QtDBus/QDBusInterface>
#endif
using namespace KDESu;
namespace KFI
{

View file

@ -4,9 +4,9 @@ include_directories( ${CMAKE_SOURCE_DIR}/kcontrol/kfontinst/lib/
add_library(font MODULE FontThroughAnalyzer.cpp FontEngine.cpp )
target_link_libraries(font ${STRIGI_STREAMANALYZER_LIBRARY} ${FREETYPE_LIBRARIES} ${FONTCONFIG_LIBRARIES} ${KDE4_KIO_LIBS} kfontinst )
target_link_libraries(font ${KDE4_KSTREAM_LIBS} ${FREETYPE_LIBRARIES} ${FONTCONFIG_LIBRARIES} ${KDE4_KIO_LIBS} kfontinst )
set_target_properties(font PROPERTIES PREFIX strigita_)
install(TARGETS font LIBRARY DESTINATION ${LIB_INSTALL_DIR}/strigi)
install(TARGETS font LIBRARY DESTINATION ${LIB_INSTALL_DIR}/kstream)

View file

@ -1,2 +0,0 @@
Pietro Iglio <iglio@fub.it>
Geert Jansen <g.t.jansen@stud.tue.nl>

View file

@ -1,3 +0,0 @@
add_subdirectory( kdesu )
add_subdirectory( kdesud )

View file

@ -1,72 +0,0 @@
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

View file

@ -1,152 +0,0 @@
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

View file

@ -1,34 +0,0 @@
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>

View file

@ -1,24 +0,0 @@
########### next target ###############
set(kdesu_SRCS kdesu.cpp sudlg.cpp )
add_executable(kdesu_executable ${kdesu_SRCS})
# 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 ${KDE4_KDEUI_LIBS} ${KDE4_KDESU_LIBS} )
install(TARGETS kdesu_executable DESTINATION ${LIBEXEC_INSTALL_DIR})

View file

@ -1,2 +0,0 @@
#!/bin/bash
$XGETTEXT *.cpp -o $podir/kdesu.pot

View file

@ -1,455 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1998 Pietro Iglio <iglio@fub.it>
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*/
#include <config-runtime.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <pwd.h>
#include <stdlib.h>
#include <sys/time.h>
#include <sys/resource.h>
#if defined(HAVE_SYS_WAIT_H)
#include <sys/wait.h>
#endif
#include <QFileInfo>
#include <QFile>
#include <QtDBus/QtDBus>
#include <kdebug.h>
#include <kglobal.h>
#include <kapplication.h>
#include <kstandarddirs.h>
#include <kconfig.h>
#include <klocale.h>
#include <kaboutdata.h>
#include <kcmdlineargs.h>
#include <kmessagebox.h>
#include <kuser.h>
#include <kshell.h>
#include <kstartupinfo.h>
#include <kdefakes.h>
#include <kwindowsystem.h>
#include <kdesu/defaults.h>
#include <kdesu/su.h>
#include <kdesu/client.h>
#include "sudlg.h"
#define ERR strerror(errno)
QByteArray command;
const char *Version = "1.0";
// NOTE: if you change the position of the -u switch, be sure to adjust it
// at the beginning of main()
#if 0
// D-BUS has no equivalent
QByteArray dcopNetworkId()
{
QByteArray result;
result.resize(1025);
QFile file(DCOPClient::dcopServerFile());
if (!file.open(QIODevice::ReadOnly))
return "";
int i = file.readLine(result.data(), 1024);
if (i <= 0)
return "";
result.data()[i-1] = '\0'; // strip newline
return result;
}
#endif
static int startApp();
int main(int argc, char *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";
KAboutData aboutData("kdesu", 0, ki18n("KDE su"),
Version, ki18n("Runs a program with elevated privileges."),
KAboutData::License_Artistic,
ki18n("Copyright (c) 1998-2000 Geert Jansen, Pietro Iglio"));
aboutData.addAuthor(ki18n("Geert Jansen"), ki18n("Maintainer"),
"jansen@kde.org", "http://www.stack.nl/~geertj/");
aboutData.addAuthor(ki18n("Pietro Iglio"), ki18n("Original author"),
"iglio@fub.it");
aboutData.setProgramIconName("dialog-password");
KCmdLineArgs::init(argc, argv, &aboutData);
// NOTE: if you change the position of the -u switch, be sure to adjust it
// at the beginning of main()
KCmdLineOptions options;
options.add("!+command", ki18n("Specifies the command to run as separate arguments"));
options.add("c <command>", ki18n("Specifies the command to run as one string"));
options.add("f <file>", ki18n("Run command under target uid if <file> is not writable"));
options.add("u <user>", ki18n("Specifies the target uid"), duser);
options.add("n", ki18n("Do not keep password"));
options.add("s", ki18n("Stop the daemon (forgets all passwords)"));
options.add("t", ki18n("Enable terminal output (no password keeping)"));
options.add("p <prio>", ki18n("Set priority value: 0 <= prio <= 100, 0 is lowest"), "50");
options.add("r", ki18n("Use realtime scheduling"));
options.add("noignorebutton", ki18n("Do not display ignore button"));
options.add("i <icon name>", ki18n("Specify icon to use in the password dialog"));
options.add("d", ki18n("Do not show the command to be run in the dialog"));
#ifdef Q_WS_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 */
options.add("attach <winid>", ki18nc("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"));
options.add("embed <winid>");
#endif
KCmdLineArgs::addCmdLineOptions(options);
//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" );
KApplication app;
// but propagate it to the started app
if (!session_manager.isEmpty())
setenv( "SESSION_MANAGER", session_manager.data(), 1 );
{
#ifdef Q_WS_X11
KStartupInfoId id;
id.initId( kapp->startupId());
id.setupStartupEnv(); // make DESKTOP_STARTUP_ID env. var. available again
#endif
}
int result = startApp();
if (result == 127)
{
KMessageBox::sorry(0, i18n("Cannot execute command '%1'.", QString::fromLocal8Bit(command)));
}
return result;
}
static int startApp()
{
KCmdLineArgs *args = KCmdLineArgs::parsedArgs();
// Stop daemon and exit?
if (args->isSet("s"))
{
KDEsuClient client;
if (client.ping() == -1)
{
kError(1206) << "Daemon not running -- nothing to stop\n";
exit(1);
}
if (client.stopServer() != -1)
{
kDebug(1206) << "Daemon stopped\n";
exit(0);
}
kError(1206) << "Could not stop daemon\n";
exit(1);
}
QString icon;
if ( args->isSet("i"))
icon = args->getOption("i");
bool prompt = true;
if ( args->isSet("d"))
prompt = false;
// Get target uid
QByteArray user = args->getOption("u").toLocal8Bit();
QByteArray auth_user = user;
struct passwd *pw = getpwnam(user);
if (pw == 0L)
{
kError(1206) << "User " << user << " does not exist\n";
exit(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 = args->getOption("f");
if (other_uid && !file.isEmpty())
{
if (file.at(0) != '/')
{
KStandardDirs dirs;
file = dirs.findResource("config", file);
if (file.isEmpty())
{
kError(1206) << "Config file not found: " << file << "\n";
exit(1);
}
}
QFileInfo fi(file);
if (!fi.exists())
{
kError(1206) << "File does not exist: " << file << "\n";
exit(1);
}
change_uid = !fi.isWritable();
}
// Get priority/scheduler
QString tmp = args->getOption("p");
bool ok;
int priority = tmp.toInt(&ok);
if (!ok || (priority < 0) || (priority > 100))
{
KCmdLineArgs::usageError(i18n("Illegal priority: %1", tmp));
exit(1);
}
int scheduler = SuProcess::SchedNormal;
if (args->isSet("r"))
scheduler = SuProcess::SchedRealtime;
if ((priority > 50) || (scheduler != SuProcess::SchedNormal))
{
change_uid = true;
auth_user = "root";
}
// Get command
if (args->isSet("c"))
{
command = args->getOption("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( args->count() == 0 )
{
KCmdLineArgs::usageError(i18n("No command specified."));
exit(1);
}
}
for (int i = 0; i < args->count(); i++)
{
command += ' ';
command += QFile::encodeName(KShell::quoteArg(args->arg(i)));
}
// Don't change uid if we're don't need to.
if (!change_uid)
{
int result = system(command);
result = WEXITSTATUS(result);
return result;
}
// Check for daemon and start if necessary
bool just_started = false;
bool have_daemon = true;
KDEsuClient client;
if (!client.isServerSGID())
{
kWarning(1206) << "Daemon not safe (not sgid), not using it.\n";
have_daemon = false;
}
else if (client.ping() == -1)
{
if (client.startServer() == -1)
{
kWarning(1206) << "Could not start daemon, reduced functionality.\n";
have_daemon = false;
}
just_started = true;
}
// Try to exec the command with kdesud.
bool keep = !args->isSet("n") && have_daemon;
bool terminal = args->isSet("t");
bool withIgnoreButton = args->isSet("ignorebutton");
int winid = -1;
bool attach = args->isSet("attach");
if(attach) {
winid = args->getOption("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)
kWarning(1206) << "Specified winid to attach to is not a valid number";
} else if(args->isSet("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 = args->getOption("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)
kWarning(1206) << "Specified winid to attach to is not a valid number";
}
QList<QByteArray> env;
QByteArray options;
env << ( "DESKTOP_STARTUP_ID=" + kapp->startupId());
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))
{
kError(1206) << "rlimit(): " << ERR << "\n";
exit(1);
}
// Read configuration
KConfigGroup config(KGlobal::config(), "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)
{
KMessageBox::error(0L, i18n("Su returned with an error.\n"));
exit(1);
}
if (needpw == 0)
{
keep = 0;
kDebug() << "Don't need password!!\n";
}
// Start the dialog
QString password;
if (needpw)
{
#ifdef Q_WS_X11
KStartupInfoId id;
id.initId( kapp->startupId());
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 += QString("%1/100").arg(priority);
if (prompt)
dlg.addCommentLine(i18n("Priority:"), prio);
}
//Attach dialog
#ifdef Q_WS_X11
if(attach)
KWindowSystem::setMainWindow(&dlg, (WId)winid);
#endif
int ret = dlg.exec();
if (ret == KDEsuDialog::Rejected)
{
#ifdef Q_WS_X11
KStartupInfo::sendFinish( id );
#endif
exit(1);
}
if (ret == KDEsuDialog::AsUser)
change_uid = false;
password = dlg.password();
keep = dlg.keepPassword();
#ifdef Q_WS_X11
data.setSilent( KStartupInfoData::No );
KStartupInfo::sendChange( id, data );
#endif
}
// Some events may need to be handled (like a button animation)
kapp->processEvents();
// Run command
if (!change_uid)
{
int result = system(command);
result = WEXITSTATUS(result);
return result;
}
else if (keep && have_daemon)
{
client.setPass(password.toLocal8Bit(), 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());
return result;
}
return -1;
}

View file

@ -1,113 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 2000 Geert Jansen <jansen@kde.org>
*/
#include "sudlg.h"
#include <QByteArray>
#include <KDebug>
#include <KLocale>
KDEsuDialog::KDEsuDialog(QByteArray user, QByteArray authUser, bool enableKeep, const QString& icon, bool withIgnoreButton)
: KPasswordDialog(0, enableKeep ? ShowKeepPassword : NoFlags,
withIgnoreButton ? User1 : NoDefault)
{
if ( !icon.isEmpty() ) {
setPixmap(DesktopIcon(icon));
}
if ( withIgnoreButton ) {
setButtonText( User1, i18n("Ignore") );
}
QString superUserCommand = proc.superUserCommand();
proc.setUser(authUser);
setCaption(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 = "<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.") + "</qt>";
else
prompt = "<qt>" + i18n("The action you requested needs <b>root privileges</b>. "
"Please enter <b>root's</b> password below.") + "</qt>";
} else {
if(withIgnoreButton)
prompt = "<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)) +
"</qt>";
else
prompt = "<qt>" + i18n("The action you requested needs additional privileges. "
"Please enter the password for <b>%1</b> below.", QString::fromLatin1(authUser)) +
"</qt>";
}
}
setPrompt(prompt);
if( withIgnoreButton )
setButtonText(User1, i18n("&Ignore"));
connect(this,SIGNAL(user1Clicked()),this,SLOT(slotUser1()));
setMinimumSize(minimumSizeHint());
}
KDEsuDialog::~KDEsuDialog()
{
}
bool KDEsuDialog::checkPassword()
{
int status = proc.checkInstall(password().toLocal8Bit());
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"

View file

@ -1,38 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 2000 Geert Jansen <jansen@kde.org>
*/
#ifndef __SuDlg_h_Included__
#define __SuDlg_h_Included__
#include <QByteArray>
#include <KPasswordDialog>
#include <kdesu/su.h>
using namespace KDESu;
class KDEsuDialog
: public KPasswordDialog
{
Q_OBJECT
public:
KDEsuDialog(QByteArray user, QByteArray authUser, bool enableKeep, const QString& icon , bool withIgnoreButton);
~KDEsuDialog();
enum ResultCodes { AsUser = 10 };
private slots:
void slotUser1();
protected:
bool checkPassword();
private:
SuProcess proc;
};
#endif // __SuDlg_h_Included__

View file

@ -1,30 +0,0 @@
check_function_exists(getpeereid HAVE_GETPEEREID) # openbsd style
check_function_exists(getpeereucred HAVE_GETPEERUCRED) # solaris style
configure_file (config-kdesud.h.cmake ${CMAKE_CURRENT_BINARY_DIR}/config-kdesud.h )
set(kdesud_SRCS
kdesud.cpp
repo.cpp
lexer.cpp
handler.cpp
secure.cpp )
add_executable(kdesud ${kdesud_SRCS})
target_link_libraries(kdesud ${KDE4_KDESU_LIBS} ${KDE4_KDECORE_LIBS} ${X11_LIBRARIES})
if(KDE4_ENABLE_FPIE)
macro_add_compile_flags(kdesud ${KDE4_CXX_FPIE_FLAGS})
macro_add_link_flags(kdesud ${KDE4_PIE_LDFLAGS})
endif(KDE4_ENABLE_FPIE)
########### install files ###############
install(TARGETS kdesud DESTINATION ${LIBEXEC_INSTALL_DIR})
install(CODE "
set(KDESUD_PATH \"\$ENV{DESTDIR}${LIBEXEC_INSTALL_DIR}/kdesud\")
EXECUTE_PROCESS(COMMAND sh -c \"chgrp nogroup '\${KDESUD_PATH}' && chmod g+s '\${KDESUD_PATH}'\")
")

View file

@ -1,2 +0,0 @@
#!/bin/bash
$XGETTEXT *.cpp -o $podir/kdesud.pot

View file

@ -1,7 +0,0 @@
/* config-kdesud.h. Generated by cmake from config-kdesud.h.cmake */
/* Define to 1 if you have the `getpeereid' function. */
#cmakedefine HAVE_GETPEEREID 1
/* Define to 1 if you have the `getpeerucred' function. */
#cmakedefine HAVE_GETPEERUCRED 1

View file

@ -1,508 +0,0 @@
/*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*
* handler.cpp: A connection handler for kdesud.
*/
#include "handler.h"
#include <stdlib.h>
#include <string.h>
#include <assert.h>
#include <unistd.h>
#include <signal.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <kdebug.h>
#include <kdesu/su.h>
#include <kdesu/ssh.h>
#include "repo.h"
#include "lexer.h"
#include "secure.h"
using namespace KDESu;
#define BUF_SIZE 1024
// Global repository
extern Repository *repo;
void kdesud_cleanup();
ConnectionHandler::ConnectionHandler(int fd)
: SocketSecurity(fd), m_exitCode(0), m_hasExitCode(false), m_needExitCode(false), m_pid(0)
{
m_Fd = fd;
m_Priority = 50;
m_Scheduler = SuProcess::SchedNormal;
}
ConnectionHandler::~ConnectionHandler()
{
m_Buf.fill('x');
m_Pass.fill('x');
close(m_Fd);
}
/*
* Handle a connection: make sure we don't block
*/
int ConnectionHandler::handle()
{
int ret, nbytes;
m_Buf.reserve(BUF_SIZE);
nbytes = recv(m_Fd, m_Buf.data() + m_Buf.size(), BUF_SIZE - 1 - m_Buf.size(), 0);
if (nbytes < 0)
{
if (errno == EINTR)
return 0;
// read error
return -1;
} else if (nbytes == 0)
{
// eof
return -1;
}
m_Buf.resize(m_Buf.size()+nbytes);
if (m_Buf.size() == BUF_SIZE - 1)
{
kWarning(1205) << "line too long";
return -1;
}
// Do we have a complete command yet?
int n;
while ((n = m_Buf.indexOf('\n')) != -1)
{
n++;
QByteArray newbuf = QByteArray(m_Buf.data(), n); // ensure new detached buffer for simplicity
int nsize = m_Buf.size() - n;
::memmove(m_Buf.data(), m_Buf.data() + n, nsize);
::memset(m_Buf.data() + nsize, 'x', n);
m_Buf.resize(nsize);
ret = doCommand(newbuf);
if (newbuf.isDetached()) // otherwise somebody else will clear it
newbuf.fill('x');
if (ret < 0)
return ret;
}
return 0;
}
QByteArray ConnectionHandler::makeKey(int _namespace, const QByteArray &s1,
const QByteArray &s2, const QByteArray &s3) const
{
QByteArray res;
res.setNum(_namespace);
res += '*';
res += s1 + '*' + s2 + '*' + s3;
return res;
}
void ConnectionHandler::sendExitCode()
{
if (!m_needExitCode)
return;
QByteArray buf;
buf.setNum(m_exitCode);
buf.prepend("OK ");
buf.append("\n");
send(m_Fd, buf.data(), buf.length(), 0);
}
void ConnectionHandler::respond(int ok, const QByteArray &s)
{
QByteArray buf;
switch (ok) {
case Res_OK:
buf = "OK";
break;
case Res_NO:
default:
buf = "NO";
break;
}
if (!s.isEmpty())
{
buf += ' ';
buf += s;
}
buf += '\n';
send(m_Fd, buf.data(), buf.length(), 0);
}
/*
* Parse and do one command. On a parse error, return -1. This will
* close the socket in the main accept loop.
*/
int ConnectionHandler::doCommand(QByteArray buf)
{
if ((uid_t) peerUid() != getuid())
{
kWarning(1205) << "Peer uid not equal to me\n";
kWarning(1205) << "Peer: " << peerUid() << " Me: " << getuid() ;
return -1;
}
QByteArray key, command, pass, name, user, value, env_check;
Data_entry data;
Lexer *l = new Lexer(buf);
int tok = l->lex();
switch (tok)
{
case Lexer::Tok_pass: // "PASS password:string timeout:int\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
m_Pass.fill('x');
m_Pass = l->lval();
tok = l->lex();
if (tok != Lexer::Tok_num)
goto parse_error;
m_Timeout = l->lval().toInt();
if (l->lex() != '\n')
goto parse_error;
if (m_Pass.isNull())
m_Pass = "";
kDebug(1205) << "Password set!\n";
respond(Res_OK);
break;
case Lexer::Tok_host: // "HOST host:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
m_Host = l->lval();
if (l->lex() != '\n')
goto parse_error;
kDebug(1205) << "Host set to " << m_Host;
respond(Res_OK);
break;
case Lexer::Tok_prio: // "PRIO priority:int\n"
tok = l->lex();
if (tok != Lexer::Tok_num)
goto parse_error;
m_Priority = l->lval().toInt();
if (l->lex() != '\n')
goto parse_error;
kDebug(1205) << "priority set to " << m_Priority;
respond(Res_OK);
break;
case Lexer::Tok_sched: // "SCHD scheduler:int\n"
tok = l->lex();
if (tok != Lexer::Tok_num)
goto parse_error;
m_Scheduler = l->lval().toInt();
if (l->lex() != '\n')
goto parse_error;
kDebug(1205) << "Scheduler set to " << m_Scheduler;
respond(Res_OK);
break;
case Lexer::Tok_exec: // "EXEC command:string user:string [options:string (env:string)*]\n"
{
QByteArray options;
QList<QByteArray> env;
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
command = l->lval();
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
user = l->lval();
tok = l->lex();
if (tok != '\n')
{
if (tok != Lexer::Tok_str)
goto parse_error;
options = l->lval();
tok = l->lex();
while (tok != '\n')
{
if (tok != Lexer::Tok_str)
goto parse_error;
QByteArray env_str = l->lval();
env.append(env_str);
if (strncmp(env_str, "DESKTOP_STARTUP_ID=", strlen("DESKTOP_STARTUP_ID=")) != 0)
env_check += '*'+env_str;
tok = l->lex();
}
}
QByteArray auth_user;
if ((m_Scheduler != SuProcess::SchedNormal) || (m_Priority > 50))
auth_user = "root";
else
auth_user = user;
key = makeKey(2, m_Host, auth_user, command);
// We only use the command if the environment is the same.
if (repo->find(key) == env_check)
{
key = makeKey(0, m_Host, auth_user, command);
pass = repo->find(key);
}
if (pass.isNull()) // isNull() means no password, isEmpty() can mean empty password
{
if (m_Pass.isNull())
{
respond(Res_NO);
break;
}
data.value = env_check;
data.timeout = m_Timeout;
key = makeKey(2, m_Host, auth_user, command);
repo->add(key, data);
data.value = m_Pass;
data.timeout = m_Timeout;
key = makeKey(0, m_Host, auth_user, command);
repo->add(key, data);
pass = m_Pass;
}
// Execute the command asynchronously
kDebug(1205) << "Executing command: " << command;
pid_t pid = fork();
if (pid < 0)
{
kDebug(1205) << "fork(): " << strerror(errno);
respond(Res_NO);
break;
} else if (pid > 0)
{
m_pid = pid;
respond(Res_OK);
break;
}
// Ignore SIGCHLD because "class SuProcess" needs waitpid()
signal(SIGCHLD, SIG_DFL);
int ret;
if (m_Host.isEmpty())
{
SuProcess proc;
proc.setCommand(command);
proc.setUser(user);
if (options.contains('x'))
proc.setXOnly(true);
proc.setPriority(m_Priority);
proc.setScheduler(m_Scheduler);
proc.setEnvironment(env);
ret = proc.exec(pass.data());
} else
{
SshProcess proc;
proc.setCommand(command);
proc.setUser(user);
proc.setHost(m_Host);
ret = proc.exec(pass.data());
}
kDebug(1205) << "Command completed: " << command;
_exit(ret);
}
case Lexer::Tok_delCmd: // "DEL command:string user:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
command = l->lval();
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
user = l->lval();
if (l->lex() != '\n')
goto parse_error;
key = makeKey(0, m_Host, user, command);
if (repo->remove(key) < 0) {
kDebug(1205) << "Unknown command: " << command;
respond(Res_NO);
}
else {
kDebug(1205) << "Deleted command: " << command << ", user = "
<< user << endl;
respond(Res_OK);
}
break;
case Lexer::Tok_delVar: // "DELV name:string \n"
{
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
tok = l->lex();
if (tok != '\n')
goto parse_error;
key = makeKey(1, name);
if (repo->remove(key) < 0)
{
kDebug(1205) << "Unknown name: " << name;
respond(Res_NO);
}
else {
kDebug(1205) << "Deleted name: " << name;
respond(Res_OK);
}
break;
}
case Lexer::Tok_delGroup: // "DELG group:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
if (repo->removeGroup(name) < 0)
{
kDebug(1205) << "No keys found under group: " << name;
respond(Res_NO);
}
else
{
kDebug(1205) << "Removed all keys under group: " << name;
respond(Res_OK);
}
break;
case Lexer::Tok_delSpecialKey: // "DELS special_key:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
if (repo->removeSpecialKey(name) < 0)
respond(Res_NO);
else
respond(Res_OK);
break;
case Lexer::Tok_set: // "SET name:string value:string group:string timeout:int\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
data.value = l->lval();
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
data.group = l->lval();
tok = l->lex();
if (tok != Lexer::Tok_num)
goto parse_error;
data.timeout = l->lval().toInt();
if (l->lex() != '\n')
goto parse_error;
key = makeKey(1, name);
repo->add(key, data);
kDebug(1205) << "Stored key: " << key;
respond(Res_OK);
break;
case Lexer::Tok_get: // "GET name:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
if (l->lex() != '\n')
goto parse_error;
key = makeKey(1, name);
kDebug(1205) << "Request for key: " << key;
value = repo->find(key);
if (!value.isEmpty())
respond(Res_OK, value);
else
respond(Res_NO);
break;
case Lexer::Tok_getKeys: // "GETK groupname:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
if (l->lex() != '\n')
goto parse_error;
kDebug(1205) << "Request for group key: " << name;
value = repo->findKeys(name);
if (!value.isEmpty())
respond(Res_OK, value);
else
respond(Res_NO);
break;
case Lexer::Tok_chkGroup: // "CHKG groupname:string\n"
tok = l->lex();
if (tok != Lexer::Tok_str)
goto parse_error;
name = l->lval();
if (l->lex() != '\n')
goto parse_error;
kDebug(1205) << "Checking for group key: " << name;
if ( repo->hasGroup( name ) < 0 )
respond(Res_NO);
else
respond(Res_OK);
break;
case Lexer::Tok_ping: // "PING\n"
tok = l->lex();
if (tok != '\n')
goto parse_error;
respond(Res_OK);
break;
case Lexer::Tok_exit: // "EXIT\n"
tok = l->lex();
if (tok != '\n')
goto parse_error;
m_needExitCode = true;
if (m_hasExitCode)
sendExitCode();
break;
case Lexer::Tok_stop: // "STOP\n"
tok = l->lex();
if (tok != '\n')
goto parse_error;
kDebug(1205) << "Stopping by command";
respond(Res_OK);
kdesud_cleanup();
exit(0);
default:
kWarning(1205) << "Unknown command: " << l->lval() ;
respond(Res_NO);
goto parse_error;
}
delete l;
return 0;
parse_error:
kWarning(1205) << "Parse error" ;
delete l;
return -1;
}

View file

@ -1,53 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*/
#ifndef __Handler_h_included__
#define __Handler_h_included__
#include <sys/types.h>
#include <QByteArray>
#include "secure.h"
/**
* A ConnectionHandler handles a client. It is called from the main program
* loop whenever there is data to read from a corresponding socket.
* It keeps reading data until a newline is read. Then, a command is parsed
* and executed.
*/
class ConnectionHandler: public SocketSecurity
{
public:
ConnectionHandler(int fd);
~ConnectionHandler();
/** Handle incoming data. */
int handle();
/* Send back exit code. */
void sendExitCode();
private:
enum Results { Res_OK, Res_NO };
int doCommand(QByteArray buf);
void respond(int ok, const QByteArray &s = QByteArray());
QByteArray makeKey(int namspace, const QByteArray &s1,
const QByteArray &s2 = QByteArray(), const QByteArray &s3 = QByteArray()) const;
int m_Fd, m_Timeout;
int m_Priority, m_Scheduler;
QByteArray m_Buf, m_Pass, m_Host;
public:
int m_exitCode;
bool m_hasExitCode;
bool m_needExitCode;
pid_t m_pid;
};
#endif

View file

@ -1,435 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*
*
* kdesud.cpp: KDE su daemon. Offers "keep password" functionality to kde su.
*
* The socket $KDEHOME/socket-$(HOSTNAME)/kdesud_$(display) is used for communication with
* client programs.
*
* The protocol: Client initiates the connection. All commands and responses
* are terminated by a newline.
*
* Client Server Description
* ------ ------ -----------
*
* PASS <pass> <timeout> OK Set password for commands in
* this session. Password is
* valid for <timeout> seconds.
*
* USER <user> OK Set the target user [required]
*
* EXEC <command> OK Execute command <command>. If
* NO <command> has been executed
* before (< timeout) no PASS
* command is needed.
*
* DEL <command> OK Delete password for command
* NO <command>.
*
* PING OK Ping the server (diagnostics).
*/
#include <config-runtime.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h>
#include <unistd.h>
#include <ctype.h>
#include <string.h>
#include <stdarg.h>
#include <signal.h>
#include <pwd.h>
#include <errno.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <sys/resource.h>
#include <sys/wait.h>
#ifdef HAVE_SYS_SELECT_H
#include <sys/select.h> // Needed on some systems.
#endif
#include <QVector>
#include <QFile>
#include <QRegExp>
#include <QByteArray>
#include <qplatformdefs.h>
#include <kcomponentdata.h>
#include <kdebug.h>
#include <klocale.h>
#include <kcmdlineargs.h>
#include <kstandarddirs.h>
#include <kaboutdata.h>
#include <kdesu/client.h>
#include <kdesu/defaults.h>
#include "repo.h"
#include "handler.h"
#ifdef Q_WS_X11
#include <X11/X.h>
#include <X11/Xlib.h>
#endif
#ifndef SUN_LEN
#define SUN_LEN(ptr) ((QT_SOCKLEN_T) \
(offsetof(struct sockaddr_un, sun_path) + strlen ((ptr)->sun_path)))
#endif
#define ERR strerror(errno)
using namespace KDESu;
// Globals
Repository *repo;
const char *Version = "1.01";
QByteArray sock;
#ifdef Q_WS_X11
Display *x11Display;
#endif
int pipeOfDeath[2];
void kdesud_cleanup()
{
unlink(sock);
}
// Borrowed from kdebase/kaudio/kaudioserver.cpp
#ifdef Q_WS_X11
extern "C" int xio_errhandler(Display *);
int xio_errhandler(Display *)
{
kError(1205) << "Fatal IO error, exiting...\n";
kdesud_cleanup();
exit(1);
return 1; //silence compilers
}
int initXconnection()
{
x11Display = XOpenDisplay(NULL);
if (x11Display != 0L)
{
XSetIOErrorHandler(xio_errhandler);
XCreateSimpleWindow(x11Display, DefaultRootWindow(x11Display),
0, 0, 1, 1, 0,
BlackPixelOfScreen(DefaultScreenOfDisplay(x11Display)),
BlackPixelOfScreen(DefaultScreenOfDisplay(x11Display)));
return XConnectionNumber(x11Display);
} else
{
kWarning(1205) << "Can't connect to the X Server.\n";
kWarning(1205) << "Might not terminate at end of session.\n";
return -1;
}
}
#endif
extern "C" {
void signal_exit(int);
void sigchld_handler(int);
}
void signal_exit(int sig)
{
kDebug(1205) << "Exiting on signal " << sig << "\n";
kdesud_cleanup();
exit(1);
}
void sigchld_handler(int)
{
char c = ' ';
write(pipeOfDeath[1], &c, 1);
}
/**
* Creates an AF_UNIX socket in socket resource, mode 0600.
*/
int create_socket()
{
int sockfd;
QT_SOCKLEN_T addrlen;
QT_STATBUF s;
QString display = QString::fromAscii(getenv("DISPLAY"));
if (display.isEmpty())
{
kWarning(1205) << "$DISPLAY is not set\n";
return -1;
}
// strip the screen number from the display
display.replace(QRegExp("\\.[0-9]+$"), "");
sock = QFile::encodeName(KStandardDirs::locateLocal("socket", QString("kdesud_%1").arg(display)));
int stat_err= QT_LSTAT(sock, &s);
if(!stat_err && S_ISLNK(s.st_mode)) {
kWarning(1205) << "Someone is running a symlink attack on you\n";
if(unlink(sock)) {
kWarning(1205) << "Could not delete symlink\n";
return -1;
}
}
if (!access(sock, R_OK|W_OK))
{
KDEsuClient client;
if (client.ping() == -1)
{
kWarning(1205) << "stale socket exists\n";
if (unlink(sock))
{
kWarning(1205) << "Could not delete stale socket\n";
return -1;
}
} else
{
kWarning(1205) << "kdesud is already running\n";
return -1;
}
}
sockfd = socket(PF_UNIX, SOCK_STREAM, 0);
if (sockfd < 0)
{
kError(1205) << "socket(): " << ERR << "\n";
return -1;
}
struct sockaddr_un addr;
addr.sun_family = AF_UNIX;
strncpy(addr.sun_path, sock, sizeof(addr.sun_path)-1);
addr.sun_path[sizeof(addr.sun_path)-1] = '\000';
addrlen = SUN_LEN(&addr);
if (bind(sockfd, (struct sockaddr *)&addr, addrlen) < 0)
{
kError(1205) << "bind(): " << ERR << "\n";
return -1;
}
struct linger lin;
lin.l_onoff = lin.l_linger = 0;
if (setsockopt(sockfd, SOL_SOCKET, SO_LINGER, (char *) &lin,
sizeof(linger)) < 0)
{
kError(1205) << "setsockopt(SO_LINGER): " << ERR << "\n";
return -1;
}
int opt = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (char *) &opt,
sizeof(opt)) < 0)
{
kError(1205) << "setsockopt(SO_REUSEADDR): " << ERR << "\n";
return -1;
}
opt = 1;
if (setsockopt(sockfd, SOL_SOCKET, SO_KEEPALIVE, (char *) &opt,
sizeof(opt)) < 0)
{
kError(1205) << "setsockopt(SO_KEEPALIVE): " << ERR << "\n";
return -1;
}
chmod(sock, 0600);
return sockfd;
}
/**
* Main program
*/
int main(int argc, char *argv[])
{
KAboutData aboutData("kdesud", 0, ki18n("KDE su daemon"),
Version, ki18n("Daemon used by kdesu"),
KAboutData::License_Artistic,
ki18n("Copyright (c) 1999,2000 Geert Jansen"));
aboutData.addAuthor(ki18n("Geert Jansen"), ki18n("Author"),
"jansen@kde.org", "http://www.stack.nl/~geertj/");
KCmdLineArgs::init(argc, argv, &aboutData);
KComponentData componentData(&aboutData);
// Set core dump size to 0
struct rlimit rlim;
rlim.rlim_cur = rlim.rlim_max = 0;
if (setrlimit(RLIMIT_CORE, &rlim) < 0)
{
kError(1205) << "setrlimit(): " << ERR << "\n";
exit(1);
}
// Create the Unix socket.
int sockfd = create_socket();
if (sockfd < 0)
exit(1);
if (listen(sockfd, 10) < 0)
{
kError(1205) << "listen(): " << ERR << "\n";
kdesud_cleanup();
exit(1);
}
int maxfd = sockfd;
// Ok, we're accepting connections. Fork to the background.
pid_t pid = fork();
if (pid == -1)
{
kError(1205) << "fork():" << ERR << "\n";
kdesud_cleanup();
exit(1);
}
if (pid)
_exit(0);
#ifdef Q_WS_X11
// Make sure we exit when the display gets closed.
int x11Fd = initXconnection();
maxfd = qMax(maxfd, x11Fd);
#endif
repo = new Repository;
QVector<ConnectionHandler *> handler;
pipe(pipeOfDeath);
maxfd = qMax(maxfd, pipeOfDeath[0]);
// Signal handlers
struct sigaction sa;
sa.sa_handler = signal_exit;
sigemptyset(&sa.sa_mask);
sa.sa_flags = 0;
sigaction(SIGHUP, &sa, 0L);
sigaction(SIGINT, &sa, 0L);
sigaction(SIGTERM, &sa, 0L);
sigaction(SIGQUIT, &sa, 0L);
sa.sa_handler = sigchld_handler;
sa.sa_flags = SA_NOCLDSTOP;
sigaction(SIGCHLD, &sa, 0L);
sa.sa_handler = SIG_IGN;
sigaction(SIGPIPE, &sa, 0L);
// Main execution loop
QT_SOCKLEN_T addrlen;
struct sockaddr_un clientname;
fd_set tmp_fds, active_fds;
FD_ZERO(&active_fds);
FD_SET(sockfd, &active_fds);
FD_SET(pipeOfDeath[0], &active_fds);
#ifdef Q_WS_X11
if (x11Fd != -1)
FD_SET(x11Fd, &active_fds);
#endif
while (1)
{
tmp_fds = active_fds;
#ifdef Q_WS_X11
if(x11Display)
XFlush(x11Display);
#endif
if (select(maxfd+1, &tmp_fds, 0L, 0L, 0L) < 0)
{
if (errno == EINTR) continue;
kError(1205) << "select(): " << ERR << "\n";
exit(1);
}
repo->expire();
for (int i=0; i<=maxfd; i++)
{
if (!FD_ISSET(i, &tmp_fds))
continue;
if (i == pipeOfDeath[0])
{
char buf[101];
read(pipeOfDeath[0], buf, 100);
pid_t result;
do
{
int status;
result = waitpid((pid_t)-1, &status, WNOHANG);
if (result > 0)
{
for(int j=handler.size(); j--;)
{
if (handler[j] && (handler[j]->m_pid == result))
{
handler[j]->m_exitCode = WEXITSTATUS(status);
handler[j]->m_hasExitCode = true;
handler[j]->sendExitCode();
handler[j]->m_pid = 0;
break;
}
}
}
}
while(result > 0);
}
#ifdef Q_WS_X11
if (i == x11Fd)
{
// Discard X events
XEvent event_return;
if (x11Display)
while(XPending(x11Display))
XNextEvent(x11Display, &event_return);
continue;
}
#endif
if (i == sockfd)
{
// Accept new connection
int fd;
addrlen = 64;
fd = accept(sockfd, (struct sockaddr *) &clientname, &addrlen);
if (fd < 0)
{
kError(1205) << "accept():" << ERR << "\n";
continue;
}
while (fd+1 > (int) handler.size())
handler.append(0);
delete handler[fd];
handler[fd] = new ConnectionHandler(fd);
maxfd = qMax(maxfd, fd);
FD_SET(fd, &active_fds);
fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) | O_NONBLOCK);
continue;
}
// handle already established connection
if (handler[i] && handler[i]->handle() < 0)
{
delete handler[i];
handler[i] = 0;
FD_CLR(i, &active_fds);
}
}
}
kWarning(1205) << "???\n";
}

View file

@ -1,146 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*
* lexer.cpp: A lexer for the kdesud protocol. See kdesud.cpp for a
* description of the protocol.
*/
#include "lexer.h"
#include <ctype.h>
Lexer::Lexer(const QByteArray &input)
{
m_Input = input;
in = 0;
}
Lexer::~Lexer()
{
// Erase buffers
m_Input.fill('x');
m_Output.fill('x');
}
QByteArray &Lexer::lval()
{
return m_Output;
}
/*
* lex() is the lexer. There is no end-of-input check here so that has to be
* done by the caller.
*/
int Lexer::lex()
{
char c;
c = m_Input[in++];
m_Output.fill('x');
m_Output.resize(0);
while (1)
{
// newline?
if (c == '\n')
return '\n';
// No control characters
if (iscntrl(c))
return Tok_none;
if (isspace(c))
while (isspace(c = m_Input[in++]))
;
// number?
if (isdigit(c))
{
m_Output += c;
while (isdigit(c = m_Input[in++]))
m_Output += c;
in--;
return Tok_num;
}
// quoted string?
if (c == '"')
{
c = m_Input[in++];
while ((c != '"') && !iscntrl(c)) {
// handle escaped characters
if (c == '\\') {
c = m_Input[in++];
if (iscntrl(c))
return Tok_none;
if (c == '^') {
c = m_Input[in++];
if ((c == '"') || iscntrl(c))
return Tok_none;
m_Output += c - '@';
} else {
m_Output += c;
}
} else {
m_Output += c;
}
c = m_Input[in++];
}
if (c == '"')
return Tok_str;
return Tok_none;
}
// normal string
while (!isspace(c) && !iscntrl(c))
{
m_Output += c;
c = m_Input[in++];
}
in--;
// command?
if (m_Output.length() <= 4)
{
if (m_Output == "EXEC")
return Tok_exec;
if (m_Output == "PASS")
return Tok_pass;
if (m_Output == "DEL")
return Tok_delCmd;
if (m_Output == "PING")
return Tok_ping;
if (m_Output == "EXIT")
return Tok_exit;
if (m_Output == "STOP")
return Tok_stop;
if (m_Output == "SET")
return Tok_set;
if (m_Output == "GET")
return Tok_get;
if (m_Output == "HOST")
return Tok_host;
if (m_Output == "SCHD")
return Tok_sched;
if (m_Output == "PRIO")
return Tok_prio;
if (m_Output == "DELV")
return Tok_delVar;
if (m_Output == "DELG")
return Tok_delGroup;
if (m_Output == "DELS")
return Tok_delSpecialKey;
if (m_Output == "GETK")
return Tok_getKeys;
if (m_Output == "CHKG")
return Tok_chkGroup;
}
return Tok_str;
}
}

View file

@ -1,42 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*/
#ifndef __Lexer_h_included__
#define __Lexer_h_included__
#include <QByteArray>
/**
* This is a lexer for the kdesud protocol.
*/
class Lexer {
public:
Lexer(const QByteArray &input);
~Lexer();
/** Read next token. */
int lex();
/** Return the token's value. */
QByteArray &lval();
enum Tokens {
Tok_none, Tok_exec=256, Tok_pass, Tok_delCmd,
Tok_ping, Tok_str, Tok_num , Tok_stop,
Tok_set, Tok_get, Tok_delVar, Tok_delGroup,
Tok_host, Tok_prio, Tok_sched, Tok_getKeys,
Tok_chkGroup, Tok_delSpecialKey, Tok_exit
};
private:
QByteArray m_Input;
QByteArray m_Output;
int in;
};
#endif

View file

@ -1,186 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <g.t.jansen@stud.tue.nl>
*/
#include "repo.h"
#include <time.h>
#include <assert.h>
#include <QStack>
#include <KDebug>
Repository::Repository()
{
head_time = (unsigned) -1;
}
Repository::~Repository()
{}
void Repository::add(const QByteArray &key, Data_entry &data)
{
RepoIterator it = repo.find(key);
if (it != repo.end())
remove(key);
if (data.timeout == 0)
data.timeout = (unsigned) -1;
else
data.timeout += time(0L);
head_time = qMin(head_time, data.timeout);
repo.insert(key, data);
}
int Repository::remove(const QByteArray &key)
{
if( key.isEmpty() )
return -1;
RepoIterator it = repo.find(key);
if (it == repo.end())
return -1;
it.value().value.fill('x');
it.value().group.fill('x');
repo.erase(it);
return 0;
}
int Repository::removeSpecialKey(const QByteArray &key)
{
int found = -1;
if ( !key.isEmpty() )
{
QStack<QByteArray> rm_keys;
for (RepoCIterator it=repo.constBegin(); it!=repo.constEnd(); ++it)
{
if ( key.indexOf( it.value().group ) == 0 &&
it.key().indexOf( key ) >= 0 )
{
rm_keys.push(it.key());
found = 0;
}
}
while (!rm_keys.isEmpty())
{
kDebug(1205) << "Removed key: " << rm_keys.top();
remove(rm_keys.pop());
}
}
return found;
}
int Repository::removeGroup(const QByteArray &group)
{
int found = -1;
if ( !group.isEmpty() )
{
QStack<QByteArray> rm_keys;
for (RepoCIterator it=repo.constBegin(); it!=repo.constEnd(); ++it)
{
if (it.value().group == group)
{
rm_keys.push(it.key());
found = 0;
}
}
while (!rm_keys.isEmpty())
{
kDebug(1205) << "Removed key: " << rm_keys.top();
remove(rm_keys.pop());
}
}
return found;
}
int Repository::hasGroup(const QByteArray &group) const
{
if ( !group.isEmpty() )
{
RepoCIterator it;
for (it=repo.begin(); it!=repo.end(); ++it)
{
if (it.value().group == group)
return 0;
}
}
return -1;
}
QByteArray Repository::findKeys(const QByteArray &group, const char *sep ) const
{
QByteArray list="";
if( !group.isEmpty() )
{
kDebug(1205) << "Looking for matching key with group key: " << group;
int pos;
QByteArray key;
RepoCIterator it;
for (it=repo.begin(); it!=repo.end(); ++it)
{
if (it.value().group == group)
{
key = it.key();
kDebug(1205) << "Matching key found: " << key;
pos = key.lastIndexOf(sep);
key.truncate( pos );
key.remove(0, 2);
if (!list.isEmpty())
{
// Add the same keys only once please :)
if( !list.contains(key) )
{
kDebug(1205) << "Key added to list: " << key;
list += '\007'; // I do not know
list.append(key);
}
}
else
list = key;
}
}
}
return list;
}
QByteArray Repository::find(const QByteArray &key) const
{
if( key.isEmpty() )
return 0;
RepoCIterator it = repo.find(key);
if (it == repo.end())
return 0;
return it.value().value;
}
int Repository::expire()
{
unsigned current = time(0L);
if (current < head_time)
return 0;
unsigned t;
QStack<QByteArray> keys;
head_time = (unsigned) -1;
RepoIterator it;
for (it=repo.begin(); it!=repo.end(); ++it)
{
t = it.value().timeout;
if (t <= current)
keys.push(it.key());
else
head_time = qMin(head_time, t);
}
int n = keys.count();
while (!keys.isEmpty())
remove(keys.pop());
return n;
}

View file

@ -1,68 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*/
#ifndef __Repo_h_included__
#define __Repo_h_included__
#include <QMap>
#include <QByteArray>
/**
* Used internally.
*/
struct Data_entry
{
QByteArray value;
QByteArray group;
unsigned int timeout;
};
/**
* String repository.
*
* This class implements a string repository with expiration.
*/
class Repository {
public:
Repository();
~Repository();
/** Remove data elements which are expired. */
int expire();
/** Add a data element */
void add(const QByteArray& key, Data_entry& data);
/** Delete a data element. */
int remove(const QByteArray& key);
/** Delete all data entries having the given group. */
int removeGroup(const QByteArray& group);
/** Delete all data entries based on key. */
int removeSpecialKey(const QByteArray& key );
/** Checks for the existence of the specified group. */
int hasGroup(const QByteArray &group) const;
/** Return a data value. */
QByteArray find(const QByteArray& key) const;
/** Returns the key values for the given group. */
QByteArray findKeys(const QByteArray& group, const char *sep= "-") const;
private:
QMap<QByteArray,Data_entry> repo;
typedef QMap<QByteArray,Data_entry>::Iterator RepoIterator;
typedef QMap<QByteArray,Data_entry>::ConstIterator RepoCIterator;
unsigned head_time;
};
#endif

View file

@ -1,97 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <g.t.jansen@stud.tue.nl>
*
* secure.cpp: Peer credentials for a UNIX socket.
*/
#include "secure.h"
#include <config-runtime.h>
#include <config-kdesud.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <kdebug.h>
#include <qplatformdefs.h>
/**
* Under Linux, Socket_security is supported.
*/
#if defined(HAVE_GETPEEREID)
SocketSecurity::SocketSecurity(int sockfd) : pid(-1), gid(-1), uid(-1)
{
uid_t euid;
gid_t egid;
if (getpeereid(sockfd, &euid, &egid) == 0) {
uid = euid;
gid = egid;
pid = -1;
}
}
# elif defined(HAVE_GETPEERUCRED)
#include <ucred.h>
SocketSecurity::SocketSecurity(int sockfd) : pid(-1), gid(-1), uid(-1)
{
ucred_t *ucred = 0;
if (getpeerucred(sockfd, &ucred) == 0) {
uid = ucred_geteuid(ucred);
gid = ucred_getrgid(ucred);
pid = -1;
ucred_free(ucred);
}
}
#elif defined(SO_PEERCRED)
SocketSecurity::SocketSecurity(int sockfd) : pid(-1), gid(-1), uid(-1)
{
ucred cred;
QT_SOCKLEN_T len = sizeof(struct ucred);
if (getsockopt(sockfd, SOL_SOCKET, SO_PEERCRED, &cred, &len) < 0) {
kError() << "getsockopt(SO_PEERCRED) " << perror << endl;
return;
}
pid = cred.pid;
gid = cred.gid;
uid = cred.uid;
}
# else
#ifdef __GNUC__
#warning SocketSecurity support for your platform not implemented/available!
#endif
/**
* The default version does nothing.
*/
SocketSecurity::SocketSecurity(int sockfd) : pid(-1), gid(-1), uid(-1)
{
static bool warned_him = false;
if (!warned_him) {
kWarning() << "Using void socket security. Please add support for your" ;
kWarning() << "platform to kdesu/kdesud/secure.cpp" ;
warned_him = true;
}
// This passes the test made in handler.cpp
uid = getuid();
}
#endif

View file

@ -1,38 +0,0 @@
/* vi: ts=8 sts=4 sw=4
*
* This file is part of the KDE project, module kdesu.
* Copyright (C) 1999,2000 Geert Jansen <jansen@kde.org>
*/
#ifndef __Secure_h_included__
#define __Secure_h_included__
#include <sys/types.h>
#include <sys/socket.h>
/**
* The Socket_security class autheticates the peer for you. It provides
* the process-id, user-id and group-id plus the MD5 sum of the connected
* binary.
*/
class SocketSecurity {
public:
explicit SocketSecurity(int fd);
/** Returns the peer's process-id. */
int peerPid() const { return pid; }
/** Returns the peer's user-id */
int peerUid() const { return uid; }
/** Returns the peer's group-id */
int peerGid() const { return gid; }
private:
int pid;
int gid;
int uid;
};
#endif

View file

@ -117,7 +117,7 @@ QProcess* KSMServer::startApplication( const QStringList& cmd, const QString& cl
command.prepend( "--" );
command.prepend( userId );
command.prepend( "-u" );
command.prepend( KStandardDirs::findExe("kdesu") );
command.prepend( KStandardDirs::findExe("kdesudo") );
}
}
if ( !clientMachine.isEmpty() && clientMachine != "localhost" ) {

View file

@ -1,11 +1,10 @@
set(krunner_shell_SRCS
shellrunner.cpp
shell_config.cpp
shellOptions.ui
)
kde4_add_plugin(krunner_shell ${krunner_shell_SRCS})
target_link_libraries(krunner_shell ${KDE4_KIO_LIBS} ${KDE4_PLASMA_LIBS} ${KDE4_KDESU_LIBS})
target_link_libraries(krunner_shell ${KDE4_KIO_LIBS} ${KDE4_PLASMA_LIBS})
install(TARGETS krunner_shell DESTINATION ${PLUGIN_INSTALL_DIR})
install(FILES plasma-runner-shell.desktop DESTINATION ${SERVICES_INSTALL_DIR})

View file

@ -7,7 +7,7 @@
<x>0</x>
<y>0</y>
<width>325</width>
<height>112</height>
<height>35</height>
</rect>
</property>
<property name="sizePolicy">
@ -17,7 +17,16 @@
</sizepolicy>
</property>
<layout class="QGridLayout">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
@ -28,7 +37,16 @@
<property name="spacing">
<number>3</number>
</property>
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<item>
@ -40,76 +58,22 @@
<enum>QFrame::Raised</enum>
</property>
<layout class="QGridLayout">
<property name="margin">
<property name="leftMargin">
<number>0</number>
</property>
<property name="topMargin">
<number>0</number>
</property>
<property name="rightMargin">
<number>0</number>
</property>
<property name="bottomMargin">
<number>0</number>
</property>
<property name="spacing">
<number>3</number>
</property>
<item row="3" column="1">
<widget class="QLabel" name="lbUsername">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>Enter the user you want to run the application as here.</string>
</property>
<property name="text">
<string>User&amp;name:</string>
</property>
<property name="buddy">
<cstring>leUsername</cstring>
</property>
</widget>
</item>
<item row="4" column="2" colspan="2">
<widget class="KLineEdit" name="lePassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>5</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>Enter the password here for the user you specified above.</string>
</property>
<property name="echoMode">
<enum>QLineEdit::Password</enum>
</property>
</widget>
</item>
<item row="4" column="1">
<widget class="QLabel" name="lbPassword">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Minimum" vsizetype="Preferred">
<horstretch>0</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>Enter the password here for the user you specified above.</string>
</property>
<property name="text">
<string>Pass&amp;word:</string>
</property>
<property name="buddy">
<cstring>lePassword</cstring>
</property>
</widget>
</item>
<item row="1" column="0" colspan="4">
<item row="1" column="0" colspan="3">
<widget class="QCheckBox" name="cbRunInTerminal">
<property name="whatsThis">
<string>Check this option if the application you want to run is a text mode application. The application will then be run in a terminal emulator window.</string>
@ -119,49 +83,7 @@
</property>
</widget>
</item>
<item row="3" column="2" colspan="2">
<widget class="KLineEdit" name="leUsername">
<property name="enabled">
<bool>false</bool>
</property>
<property name="sizePolicy">
<sizepolicy hsizetype="Preferred" vsizetype="Fixed">
<horstretch>5</horstretch>
<verstretch>0</verstretch>
</sizepolicy>
</property>
<property name="whatsThis">
<string>Enter the user you want to run the application as here.</string>
</property>
</widget>
</item>
<item row="2" column="0" colspan="4">
<widget class="QCheckBox" name="cbRunAsOther">
<property name="whatsThis">
<string>Check this option if you want to run the application with a different user id. Every process has a user id associated with it. This id code determines file access and other permissions. The password of the user is required to do this.</string>
</property>
<property name="text">
<string>Run as a different &amp;user</string>
</property>
</widget>
</item>
<item row="3" column="0" rowspan="2">
<spacer>
<property name="orientation">
<enum>Qt::Horizontal</enum>
</property>
<property name="sizeType">
<enum>QSizePolicy::Fixed</enum>
</property>
<property name="sizeHint" stdset="0">
<size>
<width>20</width>
<height>40</height>
</size>
</property>
</spacer>
</item>
<item row="5" column="1">
<item row="2" column="1">
<spacer name="verticalSpacer">
<property name="orientation">
<enum>Qt::Vertical</enum>
@ -181,84 +103,9 @@
</item>
</layout>
</widget>
<customwidgets>
<customwidget>
<class>KLineEdit</class>
<extends>QLineEdit</extends>
<header>klineedit.h</header>
</customwidget>
</customwidgets>
<tabstops>
<tabstop>cbRunInTerminal</tabstop>
<tabstop>cbRunAsOther</tabstop>
<tabstop>leUsername</tabstop>
<tabstop>lePassword</tabstop>
</tabstops>
<resources/>
<connections>
<connection>
<sender>cbRunAsOther</sender>
<signal>toggled(bool)</signal>
<receiver>lbUsername</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>153</x>
<y>59</y>
</hint>
<hint type="destinationlabel">
<x>96</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>cbRunAsOther</sender>
<signal>toggled(bool)</signal>
<receiver>leUsername</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>127</x>
<y>59</y>
</hint>
<hint type="destinationlabel">
<x>188</x>
<y>62</y>
</hint>
</hints>
</connection>
<connection>
<sender>cbRunAsOther</sender>
<signal>toggled(bool)</signal>
<receiver>lbPassword</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>81</x>
<y>45</y>
</hint>
<hint type="destinationlabel">
<x>146</x>
<y>101</y>
</hint>
</hints>
</connection>
<connection>
<sender>cbRunAsOther</sender>
<signal>toggled(bool)</signal>
<receiver>lePassword</receiver>
<slot>setEnabled(bool)</slot>
<hints>
<hint type="sourcelabel">
<x>114</x>
<y>41</y>
</hint>
<hint type="destinationlabel">
<x>323</x>
<y>101</y>
</hint>
</hints>
</connection>
</connections>
<connections/>
</ui>

View file

@ -35,27 +35,10 @@ ShellConfig::ShellConfig(const KConfigGroup &config, QWidget* parent)
QHBoxLayout *hboxLayout = new QHBoxLayout(parent);
hboxLayout->addWidget(this);
m_ui.setupUi(this);
#ifdef Q_OS_UNIX
connect(m_ui.cbRunAsOther, SIGNAL(clicked(bool)), this, SLOT(slotUpdateUser(bool)));
#else
m_ui.cbRunAsOther->hide();
m_ui.lbUsername->hide();
m_ui.leUsername->hide();
m_ui.lbPassword->hide();
m_ui.lePassword->hide();
#endif
}
ShellConfig::~ShellConfig()
{
}
void ShellConfig::slotUpdateUser(bool b)
{
if (b) {
m_ui.leUsername->setFocus();
}
}
#include "moc_shell_config.cpp"

View file

@ -35,9 +35,6 @@ class ShellConfig : public QWidget
Ui::shellOptions m_ui;
protected slots:
void slotUpdateUser(bool);
private:
KConfigGroup m_config;
};

View file

@ -38,8 +38,7 @@
ShellRunner::ShellRunner(QObject *parent, const QVariantList &args)
: Plasma::AbstractRunner(parent, args),
m_inTerminal(false),
m_asOtherUser(false)
m_inTerminal(false)
{
setObjectName( QLatin1String("Command" ));
setPriority(AbstractRunner::HighestPriority);
@ -77,44 +76,7 @@ void ShellRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryM
// filter match's id to remove runner's name
// as this is the command we want to run
//kDebug() << m_asOtherUser << m_username << m_password;
if (m_asOtherUser && !m_username.isEmpty()) {
//TODO: provide some user feedback on failure
QString exec;
QString args;
if (m_inTerminal) {
// we have to reimplement this from KToolInvocation because we need to use KDESu
KConfigGroup confGroup( KGlobal::config(), "General" );
exec = confGroup.readPathEntry("TerminalApplication", "konsole");
if (!exec.isEmpty()) {
if (exec == "konsole") {
args += " --noclose";
} else if (exec == "xterm") {
args += " -hold";
}
args += " -e " + context.query();
}
} else {
const QStringList commandLine = KShell::splitArgs(context.query(), KShell::TildeExpand);
if (!commandLine.isEmpty()) {
exec = commandLine.at(0);
}
args = context.query().right(context.query().size() - commandLine.at(0).length());
}
if (!exec.isEmpty()) {
exec = KStandardDirs::findExe(exec);
exec.append(args);
if (!exec.isEmpty()) {
KDESu::SuProcess client(m_username.toLocal8Bit(), exec.toLocal8Bit());
const QByteArray password = m_password.toLocal8Bit();
//TODO handle errors like wrong password via KNotifications in 4.7
client.exec(password.constData());
}
}
} else if (m_inTerminal) {
if (m_inTerminal) {
KToolInvocation::invokeTerminal(context.query());
} else {
KRun::runCommand(context.query(), NULL);
@ -122,9 +84,6 @@ void ShellRunner::run(const Plasma::RunnerContext &context, const Plasma::QueryM
// reset for the next run!
m_inTerminal = false;
m_asOtherUser = false;
m_username.clear();
m_password.clear();
}
void ShellRunner::createRunOptions(QWidget *parent)
@ -139,15 +98,7 @@ void ShellRunner::createRunOptions(QWidget *parent)
pal.setColor(QPalette::Normal, QPalette::WindowText, theme->color(Plasma::Theme::TextColor));
configWidget->setPalette(pal);
connect(configWidget->m_ui.cbRunAsOther, SIGNAL(clicked(bool)), this, SLOT(setRunAsOtherUser(bool)));
connect(configWidget->m_ui.cbRunInTerminal, SIGNAL(clicked(bool)), this, SLOT(setRunInTerminal(bool)));
connect(configWidget->m_ui.leUsername, SIGNAL(textChanged(QString)), this, SLOT(setUsername(QString)));
connect(configWidget->m_ui.lePassword, SIGNAL(textChanged(QString)), this, SLOT(setPassword(QString)));
}
void ShellRunner::setRunAsOtherUser(bool asOtherUser)
{
m_asOtherUser = asOtherUser;
}
void ShellRunner::setRunInTerminal(bool runInTerminal)
@ -155,14 +106,4 @@ void ShellRunner::setRunInTerminal(bool runInTerminal)
m_inTerminal = runInTerminal;
}
void ShellRunner::setUsername(const QString &username)
{
m_username = username;
}
void ShellRunner::setPassword(const QString &password)
{
m_password = password;
}
#include "moc_shellrunner.cpp"

View file

@ -41,16 +41,10 @@ class ShellRunner : public Plasma::AbstractRunner
void createRunOptions(QWidget *parent);
private Q_SLOTS:
void setRunAsOtherUser(bool asOtherUser);
void setRunInTerminal(bool runInTerminal);
void setUsername(const QString &username);
void setPassword(const QString &password);
private:
QString m_username;
QString m_password;
bool m_inTerminal;
bool m_asOtherUser;
};
K_EXPORT_PLASMA_RUNNER(shell, ShellRunner)

View file

@ -232,7 +232,7 @@ fi
# Mark that full KDE session is running (e.g. Konqueror preloading works only
# with full KDE running). The KDE_FULL_SESSION property can be detected by
# any X client connected to the same X session, even if not launched
# directly from the KDE session but e.g. using "ssh -X", kdesu. $KDE_FULL_SESSION
# directly from the KDE session but e.g. using "ssh -X", kdesudo. $KDE_FULL_SESSION
# however guarantees that the application is launched in the same environment
# like the KDE session and that e.g. KDE utilities/libraries are available.
# KDE_FULL_SESSION property is also only available since KDE 3.5.5.