From e61097b8881bc7e72a5499816cb1199ea274a3ca Mon Sep 17 00:00:00 2001 From: Sebastien Braun Date: Thu, 7 Oct 2010 22:54:10 +0200 Subject: Rework template meta-magic - No more implicit dependency on Boost.MPL - Better documentation for template magic - Move input handler policies to handler definitions where they belong - Separate out event descriptions from handlers --- src/gui/frame.cpp | 18 +- src/input/CMakeLists.txt | 5 +- src/input/allowLocalOrPrivileged.cpp | 21 ++ src/input/detail/Makefile.autogen | 8 + src/input/detail/gen/gen_policyChain.cpp | 68 +++++ src/input/detail/gen/gen_typeList.cpp | 115 ++++++++ src/input/detail/policyChain.h | 78 ++++++ src/input/detail/policyChain_autogen.h | 8 + src/input/detail/systemTraits.h | 94 +++++++ src/input/detail/typeList.h | 76 ++++++ src/input/detail/typeList_autogen.h | 60 ++++ src/input/inputEvent.cpp | 32 +++ src/input/inputEvent.h | 49 ++-- src/input/inputEventHandler.cpp | 21 +- src/input/inputEventHandler.h | 407 ++++++++++++++-------------- src/input/inputHandlerChain.h | 49 ---- src/input/inputHandlerChains.h | 25 ++ src/input/killX11Handler.cpp | 2 +- src/input/killX11Handler.h | 14 +- src/input/magicSysRqHandler.cpp | 2 +- src/input/magicSysRqHandler.h | 52 +--- src/input/privilegedHandlerForwarder.cpp | 4 +- src/input/privilegedHandlerForwarder.h | 6 +- src/input/privilegedInputHandlerChain.cpp | 30 ++ src/input/pvsPrivInputHandler.cpp | 3 +- src/input/pvsPrivInputHandler.h | 4 +- src/input/rebootSystemHandler.cpp | 2 +- src/input/rebootSystemHandler.h | 10 +- src/input/sayHelloHandler.cpp | 2 +- src/input/sayHelloHandler.h | 11 +- src/input/unprivilegedInputHandlerChain.cpp | 30 ++ src/input/x11FakeKeyboardHandler.cpp | 4 +- src/input/x11FakeKeyboardHandler.h | 8 +- src/input/x11FakeMouseHandler.cpp | 4 +- src/input/x11FakeMouseHandler.h | 14 +- src/pvs.cpp | 7 +- src/pvs.h | 4 +- 37 files changed, 968 insertions(+), 379 deletions(-) create mode 100644 src/input/allowLocalOrPrivileged.cpp create mode 100644 src/input/detail/Makefile.autogen create mode 100644 src/input/detail/gen/gen_policyChain.cpp create mode 100644 src/input/detail/gen/gen_typeList.cpp create mode 100644 src/input/detail/policyChain.h create mode 100644 src/input/detail/policyChain_autogen.h create mode 100644 src/input/detail/systemTraits.h create mode 100644 src/input/detail/typeList.h create mode 100644 src/input/detail/typeList_autogen.h delete mode 100644 src/input/inputHandlerChain.h create mode 100644 src/input/inputHandlerChains.h create mode 100644 src/input/privilegedInputHandlerChain.cpp create mode 100644 src/input/unprivilegedInputHandlerChain.cpp (limited to 'src') diff --git a/src/gui/frame.cpp b/src/gui/frame.cpp index 1b80c3d..12ce6b5 100644 --- a/src/gui/frame.cpp +++ b/src/gui/frame.cpp @@ -19,7 +19,6 @@ */ #include -#include #include "frame.h" #include #include @@ -434,19 +433,18 @@ void Frame::sendInputEvent(InputEvent const& evt) { QString str; eventToString(evt, str); - std::string evtStr = evt.toString(); PVSMsg msg(PVSCOMMAND, "INPUTEVENT", str); if(_remoteControlEnabled) { if(_remoteControlToAll) { - ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evtStr.c_str())); + ConsoleLog writeLine(QString("sendInputEvent(%1) to one").arg(evt.toString())); PVSConnectionManager::getManager()->getServer()->sendToAll(msg); } else { - ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evtStr.c_str())); + ConsoleLog writeLine(QString("sendInputEvent(%1) to all").arg(evt.toString())); _cFrame->getConnection()->sendMessage(msg); } } @@ -592,14 +590,14 @@ void Frame::showSpecialEventMenu() { qDebug("Trying to show menu..."); QMenu* menu = new QMenu(this); - QList specialEvents = privileged_handler_chain::describe(); - QList::iterator iter; + QList specialEvents = SpecialInputEventDescription::describeSpecialEvents(); + QListIterator iter(specialEvents); int i; - for(i = 0, iter = specialEvents.begin(); - iter != specialEvents.end(); - iter++, i++) + for(i = 0; + iter.hasNext(); + i++) { - QAction* act = menu->addAction((*iter).descriptionString); + QAction* act = menu->addAction(iter.next().description); act->setData(i); } QAction* selected = menu->exec(QCursor::pos()); diff --git a/src/input/CMakeLists.txt b/src/input/CMakeLists.txt index 20fd531..689fd39 100644 --- a/src/input/CMakeLists.txt +++ b/src/input/CMakeLists.txt @@ -2,6 +2,8 @@ include(${QT_USE_FILE}) set(pvsinput_SRCS inputEvent.cpp + unprivilegedInputHandlerChain.cpp + inputEventHandler.cpp ) if(UNIX) @@ -23,7 +25,8 @@ if(UNIX) killX11Handler.cpp magicSysRqHandler.cpp sayHelloHandler.cpp - inputEventHandler.cpp + privilegedInputHandlerChain.cpp + allowLocalOrPrivileged.cpp ) set(pvsprivinputd_MOC_HDRS diff --git a/src/input/allowLocalOrPrivileged.cpp b/src/input/allowLocalOrPrivileged.cpp new file mode 100644 index 0000000..ba456dc --- /dev/null +++ b/src/input/allowLocalOrPrivileged.cpp @@ -0,0 +1,21 @@ +/* + * inputHandlerSecurityPolicies.cpp + * + * Created on: Oct 7, 2010 + * Author: brs + */ + +#include "inputEventHandler.h" +#include "pvsCheckPrivileges.h" + +bool input_policy::AllowLocalOrPrivileged::allow(InputEventContext const* ctx) +{ + if(ctx) + { + if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, ctx)) + return true; + if(PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::USER_PRIVILEGED, ctx)) + return true; + } + return false; +} diff --git a/src/input/detail/Makefile.autogen b/src/input/detail/Makefile.autogen new file mode 100644 index 0000000..6d0bfb3 --- /dev/null +++ b/src/input/detail/Makefile.autogen @@ -0,0 +1,8 @@ +all : policyChain_autogen.h typeList_autogen.h +.PHONY : all + +policyChain_autogen.h : gen/gen_policyChain + gen/gen_policyChain > policyChain_autogen.h + +typeList_autogen.h : gen/gen_typeList + gen/gen_typeList > typeList_autogen.h diff --git a/src/input/detail/gen/gen_policyChain.cpp b/src/input/detail/gen/gen_policyChain.cpp new file mode 100644 index 0000000..3e375ec --- /dev/null +++ b/src/input/detail/gen/gen_policyChain.cpp @@ -0,0 +1,68 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/gen/gen_policyChain.cpp: + # - generate the input_policy::detail::PolicyChain class + # -------------------------------------------------------------------------- + */ + +#include + +using namespace std; + +#define NUM_POLICIES 8 + +int main(int, char**) +{ + int i; + + cout << "template\nstruct PolicyChain :\npublic P0::template apply_ >\n"; + cout << "{};\n"; + + // Base case: + cout << "template\n"; + cout << "struct PolicyChain : public BaseCase {};\n"; + + // We need the following in macros: + cout << "#define _autogen_POLICY_TEMPLATE_PARAMS "; + for(i = 0; i < NUM_POLICIES; i++) + { + if(i) + cout << ", "; + cout << "typename P" << i; + } + + cout << "\n#define _autogen_POLICY_TEMPLATE_ARGS "; + for(i = 0; i < NUM_POLICIES; i++) + { + if(i) + cout << ", "; + cout << "P" << i; + } + cout << "\n"; + + return 0; +} diff --git a/src/input/detail/gen/gen_typeList.cpp b/src/input/detail/gen/gen_typeList.cpp new file mode 100644 index 0000000..e092b80 --- /dev/null +++ b/src/input/detail/gen/gen_typeList.cpp @@ -0,0 +1,115 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/gen/gen_policyChain.cpp: + # - generate the input_policy::detail::TypeList class + # -------------------------------------------------------------------------- + */ + +#include + +using namespace std; + +#define NUM_MAX_ENTRIES 16 + +int main(int, char**) +{ + int i; + + cout << "template<"; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename T" << i << " = void"; + } + cout << ">\nstruct TypeList {\n"; + cout << "typedef T0 head;\n"; + cout << "typedef TypeList<"; + for(i = 1; i < NUM_MAX_ENTRIES; i++) + { + if(i > 1) + cout << ", "; + cout << "T" << i; + } + cout << ", void > tail;\n"; + cout << "};\n"; + + // Contains: + cout << "template\n" + "struct Contains { static const int index = -1; static const bool value = false; };\n"; + + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + int j; + + cout << "template\nstruct Contains >\n{ static const int index = " << i << "; static const bool value = true; };\n"; + } + + // Empty List: + cout << "typedef TypeList<"; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "void"; + } + cout << " > EmptyList;\n"; + + // Macros: + cout << "#define IMPLICIT_TYPE_LIST_PARAMS(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename prefix##" << i << " = void"; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "typename prefix##" << i; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST_ARGS(prefix) "; + for(i = 0; i < NUM_MAX_ENTRIES; i++) + { + if(i) + cout << ", "; + cout << "prefix##" << i; + } + cout << "\n"; + + cout << "#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList\n"; + + return 0; +} diff --git a/src/input/detail/policyChain.h b/src/input/detail/policyChain.h new file mode 100644 index 0000000..ae01ff2 --- /dev/null +++ b/src/input/detail/policyChain.h @@ -0,0 +1,78 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/policyChain.h: + # - Tie together the different bits of policy information a handler may + # give us + # -------------------------------------------------------------------------- + */ + +#ifndef POLICYCHAIN_H_ +#define POLICYCHAIN_H_ + +#include "typeList.h" + +namespace input_policy +{ +namespace detail +{ + +template +struct PolicyChain : public PolicyList::head::template apply_ > +{ +}; + +template +struct PolicyChain : public BaseCase +{ +private: + struct This_Should_Not_Work; +public: + static const int test_value = sizeof(This_Should_Not_Work); +}; + +} +} + +///////////////////////////////////////////////////////////////////////// +// Macros that enable specification of policies: +// A policy is declared like this: +// template< PARAM1, PARAM2, ... > +// BEGIN_POLICY_CLASS(MyPolicy) { +// static const int field1 = 2; +// ... +// } END_POLICY_CLASS(MyPolicy); +///////////////////////////////////////////////////////////////////////// +#define BEGIN_POLICY_CLASS(policyName) \ + struct policyName { \ + template \ + struct apply_ : public NextPolicy +#define END_POLICY_CLASS \ + ; }; + +///////////////////////////////////////////////////////////////////////// +// A macro that enables us to use a template parameter list +// in a class using a policy, like this: +// +// template +// struct MyPolicyBasedClass +// { +// typedef USE_POLICY(baseCase) policy_type; +// }; +// +// now, the following type is valid: +// MyPolicyBasedClass +///////////////////////////////////////////////////////////////////////// +#define POLICY_PARAMS IMPLICIT_TYPE_LIST_PARAMS(Policy) +#define POLICY_PARAMS_LIST IMPLICIT_TYPE_LIST(Policy) +#define USE_POLICY(baseCase) ::input_policy::detail::PolicyChain + +#endif /* POLICYCHAIN_H_ */ diff --git a/src/input/detail/policyChain_autogen.h b/src/input/detail/policyChain_autogen.h new file mode 100644 index 0000000..d9503b8 --- /dev/null +++ b/src/input/detail/policyChain_autogen.h @@ -0,0 +1,8 @@ +template +struct PolicyChain : +public P0::template apply_ > +{}; +template +struct PolicyChain : public BaseCase {}; +#define _autogen_POLICY_TEMPLATE_PARAMS typename P0, typename P1, typename P2, typename P3, typename P4, typename P5, typename P6, typename P7 +#define _autogen_POLICY_TEMPLATE_ARGS P0, P1, P2, P3, P4, P5, P6, P7 diff --git a/src/input/detail/systemTraits.h b/src/input/detail/systemTraits.h new file mode 100644 index 0000000..7f5582f --- /dev/null +++ b/src/input/detail/systemTraits.h @@ -0,0 +1,94 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/systemTraits.h: + # - Define system traits and provide a way to match against them + # -------------------------------------------------------------------------- + */ + +#ifndef SYSTEMTRAITS_H_ +#define SYSTEMTRAITS_H_ + +#include "typeList.h" + +#define DEFINE_SYSTEM_TRAIT(name) struct name; +#define BEGIN_SYSTEM_TRAITS typedef TypeList< +#define END_SYSTEM_TRAITS > SystemTraits; + +namespace input_policy +{ + +// Trait names are externally visible. +DEFINE_SYSTEM_TRAIT(UnixLike) +DEFINE_SYSTEM_TRAIT(LinuxSystem) +DEFINE_SYSTEM_TRAIT(X11GUI) +DEFINE_SYSTEM_TRAIT(ConsoleKitSupported) + +namespace detail +{ +BEGIN_SYSTEM_TRAITS +#ifdef __linux +UnixLike, +LinuxSystem, +X11GUI, +ConsoleKitSupported +#endif +END_SYSTEM_TRAITS +} + +///////////////////////////////////////////////////////////////////////// +// Boolean logic as applied to system traits +///////////////////////////////////////////////////////////////////////// +template +struct AllOf; + +template +struct AnyOf; + +namespace detail +{ +///////////////////////////////////////////////////////////////////////// +// Does the list of system traits match what we have given? +///////////////////////////////////////////////////////////////////////// +template +struct Matches +{ + // if Needles is neither AnyOf<...> nor AllOf<...> + // then we need to know if the Haystack contains it: + static const bool value = Contains::value; +}; + +template +struct MatchesPredicate +{ + template + struct apply + { + static const bool value = Matches::value; + }; +}; + +template +struct Matches, Haystack> +{ + static const bool value = ForAnyInTypeList, IMPLICIT_TYPE_LIST(T)>::value; +}; + +template +struct Matches, Haystack> +{ + static const bool value = ForAllInTypeList, IMPLICIT_TYPE_LIST(T)>::value; +}; +} + +} + +#endif /* SYSTEMTRAITS_H_ */ diff --git a/src/input/detail/typeList.h b/src/input/detail/typeList.h new file mode 100644 index 0000000..5b915a9 --- /dev/null +++ b/src/input/detail/typeList.h @@ -0,0 +1,76 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # detail/typeList.h: + # - Compile-time metaprogramming facilities: Type Lists and Member Check + # -------------------------------------------------------------------------- + */ + +#ifndef TYPELIST_H_ +#define TYPELIST_H_ + +namespace input_policy +{ +namespace detail +{ + +///////////////////////////////////////////////////////////////////////// +// TypeList, Contains, EmptyList: +// This class is autogenerated by gen/gen_typeList.cpp +///////////////////////////////////////////////////////////////////////// +#include "typeList_autogen.h" + +///////////////////////////////////////////////////////////////////////// +// Type-level functions that do not need to be autogenerated as they +// do not depend on the maximum number of entries: +// +// ForAnyInTypeList::value == true +// if there is any entry E in List for which +// Predicate::apply::value == true +///////////////////////////////////////////////////////////////////////// +template +struct ForAnyInTypeList +{ + static const bool value = + Predicate::template apply::value || + ForAnyInTypeList::value; +}; + +template +struct ForAnyInTypeList +{ + static const bool value = false; +}; + +///////////////////////////////////////////////////////////////////////// +// ForAllInTypeList::value == true +// if there is not any entry E in List for which +// Predicate::apply::value == false +///////////////////////////////////////////////////////////////////////// +template +struct ForAllInTypeList +{ + static const bool value = + Predicate::template apply::value && + ForAllInTypeList::value; +}; + +template +struct ForAllInTypeList +{ + static const bool value = true; +}; + +} + +} + +#endif /* TYPELIST_H_ */ diff --git a/src/input/detail/typeList_autogen.h b/src/input/detail/typeList_autogen.h new file mode 100644 index 0000000..0f8fdd4 --- /dev/null +++ b/src/input/detail/typeList_autogen.h @@ -0,0 +1,60 @@ +template +struct TypeList { +typedef T0 head; +typedef TypeList tail; +}; +template +struct Contains { static const int index = -1; static const bool value = false; }; +template +struct Contains > +{ static const int index = 0; static const bool value = true; }; +template +struct Contains > +{ static const int index = 1; static const bool value = true; }; +template +struct Contains > +{ static const int index = 2; static const bool value = true; }; +template +struct Contains > +{ static const int index = 3; static const bool value = true; }; +template +struct Contains > +{ static const int index = 4; static const bool value = true; }; +template +struct Contains > +{ static const int index = 5; static const bool value = true; }; +template +struct Contains > +{ static const int index = 6; static const bool value = true; }; +template +struct Contains > +{ static const int index = 7; static const bool value = true; }; +template +struct Contains > +{ static const int index = 8; static const bool value = true; }; +template +struct Contains > +{ static const int index = 9; static const bool value = true; }; +template +struct Contains > +{ static const int index = 10; static const bool value = true; }; +template +struct Contains > +{ static const int index = 11; static const bool value = true; }; +template +struct Contains > +{ static const int index = 12; static const bool value = true; }; +template +struct Contains > +{ static const int index = 13; static const bool value = true; }; +template +struct Contains > +{ static const int index = 14; static const bool value = true; }; +template +struct Contains > +{ static const int index = 15; static const bool value = true; }; +typedef TypeList EmptyList; +#define IMPLICIT_TYPE_LIST_PARAMS(prefix) typename prefix##0 = void, typename prefix##1 = void, typename prefix##2 = void, typename prefix##3 = void, typename prefix##4 = void, typename prefix##5 = void, typename prefix##6 = void, typename prefix##7 = void, typename prefix##8 = void, typename prefix##9 = void, typename prefix##10 = void, typename prefix##11 = void, typename prefix##12 = void, typename prefix##13 = void, typename prefix##14 = void, typename prefix##15 = void +#define IMPLICIT_TYPE_LIST_PARAMS_NODEFAULT(prefix) typename prefix##0, typename prefix##1, typename prefix##2, typename prefix##3, typename prefix##4, typename prefix##5, typename prefix##6, typename prefix##7, typename prefix##8, typename prefix##9, typename prefix##10, typename prefix##11, typename prefix##12, typename prefix##13, typename prefix##14, typename prefix##15 +#define IMPLICIT_TYPE_LIST_ARGS(prefix) prefix##0, prefix##1, prefix##2, prefix##3, prefix##4, prefix##5, prefix##6, prefix##7, prefix##8, prefix##9, prefix##10, prefix##11, prefix##12, prefix##13, prefix##14, prefix##15 +#define IMPLICIT_TYPE_LIST(prefix) ::input_policy::detail::TypeList diff --git a/src/input/inputEvent.cpp b/src/input/inputEvent.cpp index 9b69a3a..f5abf43 100644 --- a/src/input/inputEvent.cpp +++ b/src/input/inputEvent.cpp @@ -7,6 +7,7 @@ #include #include +#include #include #include #include @@ -97,3 +98,34 @@ InputEvent InputEvent::keyboardRelease(int key, int mods) return InputEvent(ET_KEY, EC_RELEASE, value); } +#define describe(list, description, type, code, value) \ + list.append(SpecialInputEventDescription(InputEvent::type, InputEvent::code, value, QCoreApplication::translate("InputEvent", description))) + +QList SpecialInputEventDescription::describeSpecialEvents() +{ + QList list; + describe(list, "Say Hello", ET_SPECIAL, EC_SAY_HELLO, 0); + describe(list, "Reboot", ET_SPECIAL, EC_REBOOT, 0); + describe(list, "Kill X Server", ET_SPECIAL, EC_KILL_X, 0); + describe(list, "Reboot immediately", ET_SPECIAL, EC_SYSRQ, 'b'); + describe(list, "Power off immediately", ET_SPECIAL, EC_SYSRQ, 'o'); + describe(list, "Crash System", ET_SPECIAL, EC_SYSRQ, 'c'); + describe(list, "Turn off raw keyboard mode", ET_SPECIAL, EC_SYSRQ, 'r'); + describe(list, "Send SIGTERM to all", ET_SPECIAL, EC_SYSRQ, 'e'); + describe(list, "Send SIGKILL to all", ET_SPECIAL, EC_SYSRQ, 'i'); + describe(list, "Kill all on this terminal", ET_SPECIAL, EC_SYSRQ, 'k'); + describe(list, "Activate OOM killer", ET_SPECIAL, EC_SYSRQ, 'f'); + describe(list, "Make real-time tasks niceable", ET_SPECIAL, EC_SYSRQ, 'n'); + describe(list, "Force-thaw filesystems", ET_SPECIAL, EC_SYSRQ, 'j'); + describe(list, "Sync all mounted filesystems", ET_SPECIAL, EC_SYSRQ, 's'); + describe(list, "Remount all readonly", ET_SPECIAL, EC_SYSRQ, 'u'); + describe(list, "Show all held locks", ET_SPECIAL, EC_SYSRQ, 'd'); + describe(list, "Show stack traces", ET_SPECIAL, EC_SYSRQ, 'l'); + describe(list, "Dump memory info", ET_SPECIAL, EC_SYSRQ, 'm'); + describe(list, "Dump registers and flags", ET_SPECIAL, EC_SYSRQ, 'p'); + describe(list, "Dump timers and clockevents", ET_SPECIAL, EC_SYSRQ, 'q'); + describe(list, "Dump task list", ET_SPECIAL, EC_SYSRQ, 't'); + describe(list, "Dump uninterruptible tasks", ET_SPECIAL, EC_SYSRQ, 'w'); + describe(list, "Dump ftrace buffer", ET_SPECIAL, EC_SYSRQ, 'z'); + return list; +} diff --git a/src/input/inputEvent.h b/src/input/inputEvent.h index 7a64bfc..2f557ce 100644 --- a/src/input/inputEvent.h +++ b/src/input/inputEvent.h @@ -18,9 +18,7 @@ #define INPUTEVENT_H_ #include -#include -#include -#include +#include #ifndef __linux # error "This will only run on a Linux system. Porting is required for other systems." @@ -46,8 +44,13 @@ private: // InputEvents are immutable. Prohibit assignment: InputEvent& operator=(InputEvent const&); // There intentionally is no implementation. + public: - InputEvent(uint16_t type, uint16_t code, uint32_t value) : type_(type), code_(code), value_(value) + InputEvent(uint16_t type, uint16_t code, uint32_t value = 0) : type_(type), code_(code), value_(value) + { + } + + InputEvent(InputEvent const& other) : type_(other.type_), code_(other.code_), value_(other.value_) { } @@ -158,7 +161,7 @@ public: return (value_ & 0xffff); } - static std::string typeToString(uint16_t type) + static QString typeToString(uint16_t type) { switch(type) { @@ -171,13 +174,11 @@ public: case ET_SPECIAL: return "SPECIAL"; default: - std::ostringstream s; - s << std::hex << type; - return s.str(); + return QString::number(type, 16); } } - static std::string codeToString(uint16_t code) + static QString codeToString(uint16_t code) { switch(code) { @@ -192,17 +193,13 @@ public: case EC_KILL_X: return "KILL_X"; default: - std::ostringstream s; - s << std::hex << code; - return s.str(); + return QString::number(code, 16); } } - std::string toString() const + QString toString() const { - std::ostringstream s; - s << typeToString(type_) << ':' << codeToString(code_) << ':' << std::hex << value_; - return s.str(); + return QString("%1:%2:%3").arg(typeToString(type_)).arg(codeToString(code_)).arg(value_, 16); } uint32_t qt_keysym() const @@ -216,4 +213,24 @@ public: } }; +struct SpecialInputEventDescription +{ + SpecialInputEventDescription(uint16_t type, uint16_t code, uint32_t value, QString const& description_) + : type(type), code(code), value(value), description(description_) + { + } + + uint16_t type; + uint16_t code; + uint32_t value; + QString description; + + InputEvent toEvent() const + { + return InputEvent(type, code, value); + } + + static QList describeSpecialEvents(); +}; + #endif /* INPUTEVENT_H_ */ diff --git a/src/input/inputEventHandler.cpp b/src/input/inputEventHandler.cpp index c16c358..5298aed 100644 --- a/src/input/inputEventHandler.cpp +++ b/src/input/inputEventHandler.cpp @@ -17,20 +17,17 @@ #include "inputEventHandler.h" #include "pvsCheckPrivileges.h" -bool policy::allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx) +InputEventHandlerBase::HandlerStatus InputEventHandlerBase::handle(InputEvent const& evt, InputEventContext const* ctx) { - if(ctx) - return PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_UNKNOWN, PVSCheckPrivileges::USER_PRIVILEGED, - ctx); - else - return false; + if(!isApplicable(evt, ctx)) + return HANDLER_NOT_APPLICABLE; + if(!allow(evt, ctx)) + return HANDLER_NOT_ALLOWED; + doHandle(evt, ctx); + return HANDLER_MATCHED; } -bool policy::allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx) +bool input_policy::AllowEverybody::allow(InputEventContext const*) { - if(ctx) - return PVSCheckPrivileges::instance()->require(PVSCheckPrivileges::SESSION_LOCAL, PVSCheckPrivileges::USER_UNKNOWN, - ctx); - else - return false; + return true; } diff --git a/src/input/inputEventHandler.h b/src/input/inputEventHandler.h index 52e3338..5b03a90 100644 --- a/src/input/inputEventHandler.h +++ b/src/input/inputEventHandler.h @@ -22,274 +22,283 @@ #include #include #include -#include -#include -#include #include +#include "detail/policyChain.h" +#include "detail/systemTraits.h" -#define HANDLER_TYPE_DONT_CARE 0xffff -#define HANDLER_CODE_DONT_CARE 0xffff -#define HANDLER_VALUE_DONT_CARE 0xffffffff - -class InputEventContext -{ -public: - virtual pid_t getSenderPid() const = 0; - virtual uid_t getSenderUid() const = 0; - virtual gid_t getSenderGid() const = 0; -}; - -struct SpecialInputEventDescription +struct InputEventContext { - SpecialInputEventDescription(QString const& d, quint16 t, quint16 c, quint32 v = 0) - : descriptionString(d), evtType(t), evtCode(c), evtValue(v) + InputEventContext() { + hasBeenDenied = false; } - QString descriptionString; - quint16 evtType; - quint16 evtCode; - quint32 evtValue; + virtual pid_t getSenderPid() const = 0; + virtual uid_t getSenderUid() const = 0; + virtual gid_t getSenderGid() const = 0; - InputEvent toEvent() const - { - return InputEvent(evtType, evtCode, evtValue); - } + mutable bool hasBeenDenied; }; -template -class DefaultInputEventHandler { -protected: - static QString tr(char const* string) - { - return QCoreApplication::translate("InputEventHandler", string); - } - -public: - virtual bool matches(InputEvent const& evt, InputEventContext const*) { - if(Type != HANDLER_TYPE_DONT_CARE) { - if(evt.type() != Type) - return false; - } - if(Code != HANDLER_CODE_DONT_CARE) { - if(evt.code() != Code) - return false; - } - if(Value != HANDLER_VALUE_DONT_CARE) { - if(evt.value() != Value) - return false; - } - return true; - } +namespace input_policy +{ - virtual void initialize() +///////////////////////////////////////////////////////////////////////// +// Policy: +// Modifies the behaviour of an input handler class. +// +// There are several kinds of policy: +// - Security Policy (When to allow a certain action) +// - System Requirements (When to enable a certain handler) +// - Applicability (When to consider a certain handler) +// +// Policies are tied together using the detail::PolicyChain class. +///////////////////////////////////////////////////////////////////////// + +///////////////////////////////////////////////////////////////////////// +// Security Policy: +// At the moment there are two security policies: +// 1. If the user is on a local seat, allow. If the user is privileged, +// allow. Else deny. +// 2. Allow everybody. +// Additional security policies can be added by following the example +// set by AllowLocalOrPrivileged +///////////////////////////////////////////////////////////////////////// +template +BEGIN_POLICY_CLASS(Security) +{ + bool allow(InputEventContext const* context) { + return PolicyImpl::allow(context); } +} +END_POLICY_CLASS - virtual void handle(InputEvent const& evt, InputEventContext const*) = 0; - - static void describeInto(QList& description) - { - } +struct AllowLocalOrPrivileged +{ + static bool allow(InputEventContext const*); }; -namespace policy { - -enum SecurityFlags { - SEC_FREE_FOR_ALL, - SEC_PHYSICAL_OR_PRIVILEGED +struct AllowEverybody +{ + static bool allow(InputEventContext const*); }; -bool allowPhysicalSeat(InputEvent const& evt, InputEventContext const* ctx); -bool allowPrivilegedUser(InputEvent const& evt, InputEventContext const* ctx); +typedef Security Unprivileged; -struct SecurityAllowAny +///////////////////////////////////////////////////////////////////////// +// System Requirements: +// At the moment, this is trivial, as PVS only runs on Linux. But, +// as porting efforts are already underway, we include the necessary +// machinery anyway. +///////////////////////////////////////////////////////////////////////// +template +BEGIN_POLICY_CLASS(Require) { - bool allow(InputEvent const& evt, InputEventContext const* ctx) - { - return true; - } + static const bool areSystemRequirementsFulfilled = + NextPolicy::areSystemRequirementsFulfilled && + detail::Matches::value; +} +END_POLICY_CLASS + +///////////////////////////////////////////////////////////////////////// +// System Requirements: +// At the moment, this is trivial, as PVS only runs on Linux. But, +// as porting efforts are already underway, we include the necessary +// machinery anyway. +///////////////////////////////////////////////////////////////////////// +enum { + HANDLER_CODE_DONT_CARE = 0xffff, + HANDLER_VALUE_DONT_CARE = 0xffffffff }; -struct SecurityAllowPhysicalOrPrivileged +struct T; + +template +BEGIN_POLICY_CLASS(Match) { - bool allow(InputEvent const& evt, InputEventContext const* ctx) + bool isApplicable(InputEvent const& evt) { - if(allowPhysicalSeat(evt, ctx)) - return true; - else if(allowPrivilegedUser(evt, ctx)) - return true; - return false; + if(evt.type() != EventType) + return NextPolicy::isApplicable(evt); + if(EventCode != HANDLER_CODE_DONT_CARE && evt.code() != EventCode) + return NextPolicy::isApplicable(evt); + if(EventValue != HANDLER_VALUE_DONT_CARE && evt.value() != EventValue) + return NextPolicy::isApplicable(evt); + return true; } }; +END_POLICY_CLASS -struct UnixLike; -struct Linux; -struct Windows; - -#if defined(__linux) -typedef boost::mpl::vector2::type Systems; -#elif defined(_WIN32) || defined(__WIN32__) || defined(__TOS_WIN__) || defined(__WINDOWS__) -typedef boost::mpl::vector1::type Systems; -#else -# error "Porting is needed!" -#endif - -struct SystemEnabled; -struct SystemDisabled; - -template -struct RequireSystem -{ - typedef typename boost::mpl::contains::type enabled_type; - static const bool enabled = enabled_type::value; -}; - -struct RequireNoSystem +namespace detail { - typedef boost::mpl::bool_::type enabled_type; - static const bool enabled = enabled_type::value; -}; -} - -template -class HandlerHelper +///////////////////////////////////////////////////////////////////////// +// Base case: If no policies are given: +///////////////////////////////////////////////////////////////////////// +struct InputEventHandlerPolicyBase { -public: - bool handle(InputEvent const& evt, InputEventContext const* context = 0) { - if(!securityPolicy.allow(evt, context)) - { - std::string evtStr = evt.toString(); - qWarning("Input Event %s has been denied by security policy", evtStr.c_str()); - return true; - } - if(delegate.matches(evt, context)) { - delegate.handle(evt, context); - return true; - } else { - return false; - } - } + // The default security policy applies + typedef AllowLocalOrPrivileged DefaultSecurityPolicyImpl; - void initialize() + bool allow(InputEventContext const* context) { - delegate.initialize(); + return DefaultSecurityPolicyImpl::allow(context); } - static void describeInto(QList& list) - { - Delegate::describeInto(list); - } + // A handler that does not specify requirements works + // everywhere + static const bool areSystemRequirementsFulfilled = true; -private: - Delegate delegate; - SecurityPolicy securityPolicy; -}; - -template -class HandlerHelper -{ -public: - bool handle(InputEvent const& evt, InputEventContext const* context = 0) { + // Generate an error when no match policy is given. + bool isApplicable(InputEvent const&) + { return false; } + // If any policy implementation needs an initialization hook: + // Don't forget to call NextPolicy::initialize() in your + // implementation! void initialize() { } - - static void describeInto(QList&) - { - } }; -template -struct Handler : public HandlerHelper -{ -}; +} +} -template -struct ApplyDefaultSecurityPolicy +///////////////////////////////////////////////////////////////////////// +// We want a nice non-generic base so we can make a list of polymorphic +// handlers. +// +// The actual handler class need to provide doHandle and can override +// allow and isApplicable. +///////////////////////////////////////////////////////////////////////// +/* interface */ class InputEventHandlerBase { - typedef HandlerType type; -}; +public: + enum HandlerStatus + { + HANDLER_MATCHED, + HANDLER_NOT_ALLOWED, + HANDLER_NOT_APPLICABLE + }; -template -struct ApplyDefaultSecurityPolicy > -{ - typedef Handler type; + virtual void initialize() = 0; + HandlerStatus handle(InputEvent const& evt, InputEventContext const* context = 0); + +protected: + virtual bool allow(InputEvent const& event, InputEventContext const* context = 0) = 0; + virtual bool isApplicable(InputEvent const& event, InputEventContext const* context = 0) = 0; + virtual void doHandle(InputEvent const& event, InputEventContext const* context = 0) = 0; }; -template -struct InputEventHandlerChainHelper +///////////////////////////////////////////////////////////////////////// +// Now that the machinery is in place, we can finally define what it +// is like to be an input event handler: +///////////////////////////////////////////////////////////////////////// +template +class InputEventHandler : public InputEventHandlerBase { -private: - typedef typename boost::mpl::next::type next_iterator_type; - typedef InputEventHandlerChainHelper next_in_chain; - - typedef typename boost::mpl::deref::type handler_entry_type; - typedef typename ApplyDefaultSecurityPolicy::type handler_type; - - handler_type _handler; - next_in_chain _next; +protected: + typedef USE_POLICY(input_policy::detail::InputEventHandlerPolicyBase) policy_type; + policy_type policy; public: - void handle(InputEvent const& evt, InputEventContext const* context = 0) { - if(!_handler.handle(evt, context)) { - _next.handle(evt, context); - } + void initialize() + { + policy.initialize(); } - void initialize() { - _handler.initialize(); - _next.initialize(); - } + // Export this so the handler chain can decide whether to include this handler + static const bool areSystemRequirementsFulfilled = policy_type::areSystemRequirementsFulfilled; + +protected: + + typedef InputEventHandler super; - static void describeInto(QList& list) + // allow and isApplicable are actually provided by Policy. If the + // handler class wishes to override any of them, the policy implementation + // can be called by means of super. + bool allow(InputEvent const&, InputEventContext const* context = 0) { - handler_type::describeInto(list); - next_in_chain::describeInto(list); + return policy.allow(context); } - static QList describe() + bool isApplicable(InputEvent const& event, InputEventContext const* = 0) { - QList list; - describeInto(list); - return list; + return policy.isApplicable(event); } }; -template -struct InputEventHandlerChainHelper +///////////////////////////////////////////////////////////////////////// +// And we can chain input handlers together: +///////////////////////////////////////////////////////////////////////// +class InputEventHandlerChain { - void handle(InputEvent const&, InputEventContext const* context = 0) { - // do nothing - } +private: + QList handlers; + + ///////////////////////////////////////////////////////////////////////// + // We need to statically dispatch on a static member of HandlerType. + // Unfortunately, we cannot specialize member functions of a template. + // So, we need to make this a class with a static non-template member. + ///////////////////////////////////////////////////////////////////////// + template + struct ConditionallyAppend + { + static void doIt(InputEventHandlerChain* chain) + { + chain->handlers.append(new HandlerType); + } + }; - void initialize() { - // do nothing - } + template + struct ConditionallyAppend + { + static void doIt(InputEventHandlerChain*) + { + } + }; - static void describeInto(QList&) +public: + // Add an event handler to the chain. The argument is only for + // compilers which cannot handle template member functions + // correctly. + template + InputEventHandlerChain& add(HandlerType const* = 0) { - // do nothing + ConditionallyAppend::doIt(this); + return *this; } - static QList describe() + void initialize() { - return QList(); + QListIterator i(handlers); + while(i.hasNext()) + { + i.next()->initialize(); + } } -}; -template -struct InputEventHandlerChain : - public InputEventHandlerChainHelper::type, - typename boost::mpl::end::type> -{ + void handle(InputEvent const& event, InputEventContext const* context = 0) + { + QListIterator i(handlers); + while(i.hasNext()) + { + switch(i.next()->handle(event, context)) + { + case InputEventHandlerBase::HANDLER_MATCHED: + break; + case InputEventHandlerBase::HANDLER_NOT_ALLOWED: + context->hasBeenDenied = true; + case InputEventHandlerBase::HANDLER_NOT_APPLICABLE: + continue; + } + } + } }; #endif /* INPUTEVENTHANDLER_H_ */ diff --git a/src/input/inputHandlerChain.h b/src/input/inputHandlerChain.h deleted file mode 100644 index 3c9446c..0000000 --- a/src/input/inputHandlerChain.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg - # - # This program is free software distributed under the GPL version 2. - # See http://openslx.org/COPYING - # - # If you have any feedback please consult http://openslx.org/feedback and - # send your suggestions, praise, or complaints to feedback@openslx.org - # - # General information about OpenSLX can be found at http://openslx.org/ - # -------------------------------------------------------------------------- - # inputHandlerChain.h: - # - Definition of the input handler chain - # -------------------------------------------------------------------------- - */ - -#ifndef INPUTHANDLERCHAIN_H_ -#define INPUTHANDLERCHAIN_H_ - -#include -#include "inputEventHandler.h" - -#include "x11FakeKeyboardHandler.h" -#include "x11FakeMouseHandler.h" -#include "privilegedHandlerForwarder.h" -#include "rebootSystemHandler.h" -#include "sayHelloHandler.h" -#include "killX11Handler.h" -#include "magicSysRqHandler.h" - -typedef boost::mpl::list< - Handler >, - Handler >, - Handler >, - Handler ->::type unprivileged_handler_list; - -typedef InputEventHandlerChain unprivileged_handler_chain; - -typedef boost::mpl::list< - Handler, - Handler >, - Handler >, - Handler > ->::type privileged_handler_list; - -typedef InputEventHandlerChain privileged_handler_chain; - -#endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/inputHandlerChains.h b/src/input/inputHandlerChains.h new file mode 100644 index 0000000..a91e605 --- /dev/null +++ b/src/input/inputHandlerChains.h @@ -0,0 +1,25 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # inputHandlerChains.h: + # - Definition of the input handler chains - interface + # -------------------------------------------------------------------------- + */ + +#ifndef INPUTHANDLERCHAIN_H_ +#define INPUTHANDLERCHAIN_H_ + +#include "inputEventHandler.h" + +InputEventHandlerChain makeUnprivilegedInputEventHandlerChain(); +InputEventHandlerChain makePrivilegedInputEventHandlerChain(); + +#endif /* INPUTHANDLERCHAIN_H_ */ diff --git a/src/input/killX11Handler.cpp b/src/input/killX11Handler.cpp index 7ac75a1..572656e 100644 --- a/src/input/killX11Handler.cpp +++ b/src/input/killX11Handler.cpp @@ -25,7 +25,7 @@ using namespace std; -void KillX11Handler::handle(InputEvent const&, InputEventContext const* ctx) +void KillX11Handler::doHandle(InputEvent const&, InputEventContext const* ctx) { // Find out which display device is used: QString displayDevice = PVSCheckPrivileges::instance()->getX11DisplayDevice(ctx); diff --git a/src/input/killX11Handler.h b/src/input/killX11Handler.h index 2f3ef44..8c0d655 100644 --- a/src/input/killX11Handler.h +++ b/src/input/killX11Handler.h @@ -20,15 +20,15 @@ #include #include "inputEventHandler.h" -class KillX11Handler : public DefaultInputEventHandler +class KillX11Handler : public InputEventHandler< + input_policy::Match, + input_policy::Require > > { public: - void handle(InputEvent const&, InputEventContext const*); - - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Kill X Server")), InputEvent::ET_SPECIAL, InputEvent::EC_KILL_X); - } + void doHandle(InputEvent const&, InputEventContext const*); }; #endif /* KILLX11HANDLER_H_ */ diff --git a/src/input/magicSysRqHandler.cpp b/src/input/magicSysRqHandler.cpp index 108bfca..7c38216 100644 --- a/src/input/magicSysRqHandler.cpp +++ b/src/input/magicSysRqHandler.cpp @@ -17,7 +17,7 @@ #include #include "magicSysRqHandler.h" -void MagicSysRqHandler::handle(InputEvent const& evt, InputEventContext const*) +void MagicSysRqHandler::doHandle(InputEvent const& evt, InputEventContext const*) { QFile trigger("/proc/sysrq-trigger"); trigger.open(QIODevice::WriteOnly); diff --git a/src/input/magicSysRqHandler.h b/src/input/magicSysRqHandler.h index 563d091..ba02997 100644 --- a/src/input/magicSysRqHandler.h +++ b/src/input/magicSysRqHandler.h @@ -19,54 +19,16 @@ #include "inputEventHandler.h" -class MagicSysRqHandler : public DefaultInputEventHandler +class MagicSysRqHandler : public InputEventHandler< + input_policy::Match, + input_policy::Require > { public: - void handle(InputEvent const& evt, InputEventContext const* ctx); + void doHandle(InputEvent const& evt, InputEventContext const* ctx); - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Reboot immediately"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'b'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Crash system"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'c'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Show all held logs"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'd'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Send SIGTERM to all"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'e'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Activate OOM killer"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'f'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Send SIGKILL to all"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'i'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Force thaw filesystems"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'j'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Kill all on terminal"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'k'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Show stack traces"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'l'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump memory info"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'm'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Make real-time tasks niceable"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'n'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Power off immediately"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'o'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump registers and flags"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'p'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump timers and clockevents"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'q'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Turn off raw keyboard mode"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'r'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Sync all mounted filesystems"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 's'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump task list"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 't'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Remount all read-only"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'u'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump uninterruptible tasks"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'w'); - list << SpecialInputEventDescription(QCoreApplication::translate("InputEventHandler", "Dump ftrace buffer"), - InputEvent::ET_SPECIAL, InputEvent::EC_SYSRQ, 'z'); - } +// static void describeInto(QList& list) +// { +// } }; #endif /* MAGICSYSRQHANDLER_H_ */ diff --git a/src/input/privilegedHandlerForwarder.cpp b/src/input/privilegedHandlerForwarder.cpp index 3c0b3bd..17c4ab1 100644 --- a/src/input/privilegedHandlerForwarder.cpp +++ b/src/input/privilegedHandlerForwarder.cpp @@ -45,9 +45,9 @@ void PrivilegedHandlerForwarder::initialize() } } -void PrivilegedHandlerForwarder::handle(InputEvent const& evt, InputEventContext const*) +void PrivilegedHandlerForwarder::doHandle(InputEvent const& evt, InputEventContext const*) { - qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().c_str()); + qDebug("Trying to handle %s in PrivilegedHandlerForwarder", evt.toString().toLocal8Bit().constData()); if(_socket < 0) { initialize(); diff --git a/src/input/privilegedHandlerForwarder.h b/src/input/privilegedHandlerForwarder.h index 37e8f24..f5a6cc3 100644 --- a/src/input/privilegedHandlerForwarder.h +++ b/src/input/privilegedHandlerForwarder.h @@ -19,10 +19,12 @@ #include "inputEventHandler.h" -class PrivilegedHandlerForwarder : public DefaultInputEventHandler +class PrivilegedHandlerForwarder : public InputEventHandler< + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const& evt, InputEventContext const* = 0); + void doHandle(InputEvent const& evt, InputEventContext const* = 0); void initialize(); private: diff --git a/src/input/privilegedInputHandlerChain.cpp b/src/input/privilegedInputHandlerChain.cpp new file mode 100644 index 0000000..5764728 --- /dev/null +++ b/src/input/privilegedInputHandlerChain.cpp @@ -0,0 +1,30 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # privilegedInputHandlerChain.cpp + # - Definition of the input handler chains - implementation for privileged + # chain + # -------------------------------------------------------------------------- + */ + +#include "rebootSystemHandler.h" +#include "sayHelloHandler.h" +#include "killX11Handler.h" +#include "magicSysRqHandler.h" +#include "inputHandlerChains.h" + +InputEventHandlerChain makePrivilegedInputEventHandlerChain() +{ + return InputEventHandlerChain().add() + .add() + .add() + .add(); +} diff --git a/src/input/pvsPrivInputHandler.cpp b/src/input/pvsPrivInputHandler.cpp index 70ed1bc..bfa60ce 100644 --- a/src/input/pvsPrivInputHandler.cpp +++ b/src/input/pvsPrivInputHandler.cpp @@ -21,7 +21,7 @@ #include #include #include "inputEvent.h" -#include "inputEventHandler.h" +#include "inputHandlerChains.h" #include "pvsPrivInputSocket.h" #include "pvsPrivInputHandler.h" @@ -63,6 +63,7 @@ PVSPrivInputHandler::PVSPrivInputHandler(int fd, QObject* parent) : _notifier = new QSocketNotifier(fd, QSocketNotifier::Read, this); _notifier->setEnabled(true); connect(_notifier, SIGNAL(activated(int)), this, SLOT(canRead())); + _handlerChain = makePrivilegedInputEventHandlerChain(); } PVSPrivInputHandler::~PVSPrivInputHandler() diff --git a/src/input/pvsPrivInputHandler.h b/src/input/pvsPrivInputHandler.h index 9980cdf..e82787b 100644 --- a/src/input/pvsPrivInputHandler.h +++ b/src/input/pvsPrivInputHandler.h @@ -20,7 +20,7 @@ #include #include #include -#include "inputHandlerChain.h" +#include "inputEventHandler.h" class QSocketNotifier; @@ -39,7 +39,7 @@ private: QByteArray _messageAssembly; int _bytes; int _fd; - privileged_handler_chain _handlerChain; + InputEventHandlerChain _handlerChain; }; #endif /* PVSPRIVINPUTHANDLER_H_ */ diff --git a/src/input/rebootSystemHandler.cpp b/src/input/rebootSystemHandler.cpp index b5b8f8a..6c5c63a 100644 --- a/src/input/rebootSystemHandler.cpp +++ b/src/input/rebootSystemHandler.cpp @@ -22,7 +22,7 @@ using namespace std; -void RebootLinuxSystemHandler::handle(InputEvent const& evt, InputEventContext const* ctx) +void RebootLinuxSystemHandler::doHandle(InputEvent const& evt, InputEventContext const* ctx) { // Rebooting a linux system is particulary easy: if(kill(1, SIGINT) < 0) diff --git a/src/input/rebootSystemHandler.h b/src/input/rebootSystemHandler.h index 34fa8ae..4920452 100644 --- a/src/input/rebootSystemHandler.h +++ b/src/input/rebootSystemHandler.h @@ -20,15 +20,11 @@ #include #include "inputEventHandler.h" -class RebootLinuxSystemHandler : public DefaultInputEventHandler +class RebootLinuxSystemHandler : public InputEventHandler< + input_policy::Require > { public: - void handle(InputEvent const&, InputEventContext const*); - - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Reboot")), InputEvent::ET_SPECIAL, InputEvent::EC_REBOOT); - } + void doHandle(InputEvent const&, InputEventContext const*); }; #endif /* REBOOTSYSTEMHANDLER_H_ */ diff --git a/src/input/sayHelloHandler.cpp b/src/input/sayHelloHandler.cpp index fc6f668..712963d 100644 --- a/src/input/sayHelloHandler.cpp +++ b/src/input/sayHelloHandler.cpp @@ -19,7 +19,7 @@ using namespace std; -void SayHelloHandler::handle(InputEvent const&, InputEventContext const* ctx) +void SayHelloHandler::doHandle(InputEvent const&, InputEventContext const* ctx) { cerr << "I'm right here! You sent this message from pid " << ctx->getSenderPid() << " as user " << ctx->getSenderUid() << " with gid " << ctx->getSenderGid() << endl; } diff --git a/src/input/sayHelloHandler.h b/src/input/sayHelloHandler.h index b0d4c7e..00463ca 100644 --- a/src/input/sayHelloHandler.h +++ b/src/input/sayHelloHandler.h @@ -20,15 +20,12 @@ #include #include "inputEventHandler.h" -class SayHelloHandler : public DefaultInputEventHandler +class SayHelloHandler : public InputEventHandler< + input_policy::Match, + input_policy::Security > { public: - void handle(InputEvent const&, InputEventContext const*); - - static void describeInto(QList& list) - { - list << SpecialInputEventDescription(tr(QT_TRANSLATE_NOOP("InputEventHandler", "Say Hello")), InputEvent::ET_SPECIAL, InputEvent::EC_SAY_HELLO); - } + void doHandle(InputEvent const&, InputEventContext const*); }; #endif /* SAYHELLOHANDLER_CPP_ */ diff --git a/src/input/unprivilegedInputHandlerChain.cpp b/src/input/unprivilegedInputHandlerChain.cpp new file mode 100644 index 0000000..fbbc770 --- /dev/null +++ b/src/input/unprivilegedInputHandlerChain.cpp @@ -0,0 +1,30 @@ +/* + # Copyright (c) 2009 - OpenSLX Project, Computer Center University of Freiburg + # + # This program is free software distributed under the GPL version 2. + # See http://openslx.org/COPYING + # + # If you have any feedback please consult http://openslx.org/feedback and + # send your suggestions, praise, or complaints to feedback@openslx.org + # + # General information about OpenSLX can be found at http://openslx.org/ + # -------------------------------------------------------------------------- + # privilegedInputHandlerChain.cpp + # - Definition of the input handler chains - implementation for + # unprivileged chain + # -------------------------------------------------------------------------- + */ + +#include "x11FakeKeyboardHandler.h" +#include "x11FakeMouseHandler.h" +#include "privilegedHandlerForwarder.h" +#include "inputHandlerChains.h" + +InputEventHandlerChain makeUnprivilegedInputEventHandlerChain() +{ + return InputEventHandlerChain().add() + .add() + .add() + .add(); +} + diff --git a/src/input/x11FakeKeyboardHandler.cpp b/src/input/x11FakeKeyboardHandler.cpp index 0c32b66..eab4498 100644 --- a/src/input/x11FakeKeyboardHandler.cpp +++ b/src/input/x11FakeKeyboardHandler.cpp @@ -807,7 +807,7 @@ void X11FakeKeyboardHandler::initialize() current_modifiers = 0; } -void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext const*) +void X11FakeKeyboardHandler::doHandle(InputEvent const& evt, InputEventContext const*) { Display* dpy = X11InputUtils::display(); @@ -818,7 +818,7 @@ void X11FakeKeyboardHandler::handle(InputEvent const& evt, InputEventContext con switch(evt.qt_keysym()) { case Qt::Key_Backtab: - handle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); + doHandle(InputEvent(evt.type(), evt.code(), evt.qt_modifiers() | Qt::ShiftModifier | Qt::Key_Tab)); break; default: ConsoleLog writeLine(QString("Unknown keysym received: %1").arg(evt.qt_keysym(), 8, 16)); diff --git a/src/input/x11FakeKeyboardHandler.h b/src/input/x11FakeKeyboardHandler.h index 3dde7cc..6c18dce 100644 --- a/src/input/x11FakeKeyboardHandler.h +++ b/src/input/x11FakeKeyboardHandler.h @@ -19,10 +19,14 @@ #include "inputEventHandler.h" -class X11FakeKeyboardHandler : public DefaultInputEventHandler +class X11FakeKeyboardHandler : public InputEventHandler< + input_policy::Match, + input_policy::Match, + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const&, InputEventContext const* = 0); + void doHandle(InputEvent const&, InputEventContext const* = 0); void initialize(); }; diff --git a/src/input/x11FakeMouseHandler.cpp b/src/input/x11FakeMouseHandler.cpp index 58415d5..605fe2c 100644 --- a/src/input/x11FakeMouseHandler.cpp +++ b/src/input/x11FakeMouseHandler.cpp @@ -19,7 +19,7 @@ #include #include "x11InputUtils.h" -void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext const*) +void X11FakeMouseButtonHandler::doHandle(InputEvent const& evt, InputEventContext const*) { quint16 pressedButton = evt.pressedButton(); @@ -42,7 +42,7 @@ void X11FakeMouseButtonHandler::handle(InputEvent const& evt, InputEventContext XFlush(dpy); } -void X11FakeMouseMovementHandler::handle(InputEvent const& evt, InputEventContext const*) +void X11FakeMouseMovementHandler::doHandle(InputEvent const& evt, InputEventContext const*) { ConsoleLog writeLine(QString("Received mouse motion event (%1,%2)").arg(evt.xCoord()).arg(evt.yCoord())); Display* dpy = X11InputUtils::display(); diff --git a/src/input/x11FakeMouseHandler.h b/src/input/x11FakeMouseHandler.h index 0e32256..8ff8df4 100644 --- a/src/input/x11FakeMouseHandler.h +++ b/src/input/x11FakeMouseHandler.h @@ -19,16 +19,22 @@ #include "inputEventHandler.h" -class X11FakeMouseButtonHandler : public DefaultInputEventHandler +class X11FakeMouseButtonHandler : public InputEventHandler< + input_policy::Match, + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const&, InputEventContext const* = 0); + void doHandle(InputEvent const&, InputEventContext const* = 0); }; -class X11FakeMouseMovementHandler : public DefaultInputEventHandler +class X11FakeMouseMovementHandler : public InputEventHandler< + input_policy::Match, + input_policy::Require, + input_policy::Unprivileged> { public: - void handle(InputEvent const&, InputEventContext const* = 0); + void doHandle(InputEvent const&, InputEventContext const* = 0); }; #endif /* X11FAKEMOUSEHANDLER_H_ */ diff --git a/src/pvs.cpp b/src/pvs.cpp index eda63f5..96a92ea 100755 --- a/src/pvs.cpp +++ b/src/pvs.cpp @@ -20,7 +20,7 @@ #include "src/net/pvsServiceDiscovery.h" #include "src/net/pvsDiscoveredServer.h" #include "src/input/inputEvent.h" -#include "src/input/inputHandlerChain.h" +#include "src/input/inputHandlerChains.h" #include "src/input/x11InputUtils.h" #include "src/net/mcast/McastConfiguration.h" #include "src/net/pvsOutgoingMulticastTransfer.h" @@ -751,14 +751,15 @@ bool PVS::createMulticastTransfer(QString const& objectPath, quint64& transferID void PVS::handleInputEvent(InputEvent const& evt) { - std::string s = evt.toString(); - ConsoleLog writeLine(QString("Received input event: %1").arg(s.c_str())); + QString s = evt.toString(); + ConsoleLog writeLine(QString("Received input event: %1").arg(s.toLocal8Bit().constData())); _inputEventHandlers.handle(evt); } void PVS::initializeInputEventHandling() { X11InputUtils::setDisplay(X11Info::display()); + _inputEventHandlers = makeUnprivilegedInputEventHandlerChain(); _inputEventHandlers.initialize(); } diff --git a/src/pvs.h b/src/pvs.h index c18e9a3..902fbe7 100755 --- a/src/pvs.h +++ b/src/pvs.h @@ -26,7 +26,7 @@ #include "src/version.h" #include "src/util/consoleLogger.h" #include "src/util/clientGUIUtils.h" -#include "src/input/inputHandlerChain.h" +#include "src/input/inputEventHandler.h" class PVSServiceDiscovery; class PVSDiscoveredServer; @@ -168,7 +168,7 @@ private: int _timerLockDelay; // input event handling: - unprivileged_handler_chain _inputEventHandlers; + InputEventHandlerChain _inputEventHandlers; void handleInputEvent(InputEvent const& evt); void initializeInputEventHandling(); -- cgit v1.2.3-55-g7522