mirror of
https://bitbucket.org/smil3y/kde-workspace.git
synced 2025-02-23 18:32:50 +00:00
generic: replace kdesu with kdesudo
Signed-off-by: Ivailo Monev <xakepa10@gmail.com>
This commit is contained in:
parent
4b9f0ef959
commit
f87760f410
35 changed files with 41 additions and 2801 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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 */
|
||||
|
||||
|
|
|
@ -55,8 +55,6 @@
|
|||
#include <QtDBus/QDBusInterface>
|
||||
#endif
|
||||
|
||||
using namespace KDESu;
|
||||
|
||||
namespace KFI
|
||||
{
|
||||
|
||||
|
|
|
@ -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)
|
||||
|
||||
|
|
|
@ -1,2 +0,0 @@
|
|||
Pietro Iglio <iglio@fub.it>
|
||||
Geert Jansen <g.t.jansen@stud.tue.nl>
|
|
@ -1,3 +0,0 @@
|
|||
add_subdirectory( kdesu )
|
||||
add_subdirectory( kdesud )
|
||||
|
72
kdesu/FAQ
72
kdesu/FAQ
|
@ -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
|
||||
|
|
@ -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
|
||||
|
||||
|
34
kdesu/README
34
kdesu/README
|
@ -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>
|
|
@ -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})
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/bash
|
||||
$XGETTEXT *.cpp -o $podir/kdesu.pot
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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"
|
|
@ -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__
|
|
@ -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}'\")
|
||||
")
|
||||
|
|
@ -1,2 +0,0 @@
|
|||
#!/bin/bash
|
||||
$XGETTEXT *.cpp -o $podir/kdesud.pot
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
|
@ -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";
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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
|
|
@ -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
|
|
@ -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
|
|
@ -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" ) {
|
||||
|
|
|
@ -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})
|
||||
|
|
|
@ -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&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&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 &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>
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -35,9 +35,6 @@ class ShellConfig : public QWidget
|
|||
|
||||
Ui::shellOptions m_ui;
|
||||
|
||||
protected slots:
|
||||
void slotUpdateUser(bool);
|
||||
|
||||
private:
|
||||
KConfigGroup m_config;
|
||||
};
|
||||
|
|
|
@ -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"
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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.
|
||||
|
|
Loading…
Add table
Reference in a new issue