Author: lslezak Date: Fri Jul 11 12:45:59 2008 New Revision: 48985 URL: http://svn.opensuse.org/viewcvs/yast?rev=48985&view=rev Log: - added PolicyKit support to SCR Dbus service - reverted ScriptingAgent back to the trunk version Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusConn.cc branches/tmp/lslezak/workshop/core/scr/src/DBusConn.h branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc branches/tmp/lslezak/workshop/core/scr/src/DBusServer.h branches/tmp/lslezak/workshop/core/scr/src/Makefile.am branches/tmp/lslezak/workshop/core/scr/src/PolKit.cc branches/tmp/lslezak/workshop/core/scr/src/PolKit.h branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.cc branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.h Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusConn.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusConn.cc (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusConn.cc Fri Jul 11 12:45:59 2008 @@ -104,3 +104,8 @@ { dbus_connection_flush(connection); } + +DBusConnection *DBusConn::getConnection() const +{ + return connection; +} Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusConn.h URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusConn.h (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusConn.h Fri Jul 11 12:45:59 2008 @@ -32,6 +32,7 @@ bool send(const DBusMsg &msg); void flush(); DBusMsg receive(); + DBusConnection *getConnection() const; }; #endif Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusServer.cc Fri Jul 11 12:45:59 2008 @@ -7,6 +7,7 @@ #include "DBusServer.h" #include "DBusMsg.h" +#include "PolKit.h" #include <ycp/y2log.h> @@ -78,41 +79,64 @@ { // DBus doesn't support YCPPath type, string is used as a workaround std::string path_str(arg0->asString()->value()); - YCPPath pth(path_str); - y2milestone("Reading path %s", path_str.c_str()); - YCPValue arg = request.getYCPValue(1); - YCPValue opt = request.getYCPValue(2); - - std::string method(request.method()); - - // result from SCR:: - YCPValue ret; - bool known_method = true; - - if (method == "Read") - ret = sa->Read(pth, arg, opt); - else if (method == "Write") - ret = sa->Write(pth, arg, opt); - else if (method == "Execute") - ret = sa->Execute(pth, arg, opt); - else if (method == "Dir") - ret = sa->Dir(pth); - else + if (path_str.empty()) { - y2warning("Unknown requested method %s", method.c_str()); - reply.createError(request, ("Unknown method: " + method).c_str(), DBUS_ERROR_UNKNOWN_METHOD); - // don't create a standard reply - known_method = false; + reply.createError(request, "Argument 'path' is empty", DBUS_ERROR_INVALID_ARGS); } - - if (known_method) + else { - reply.createReply(request); + std::string method(request.method()); - if (!ret.isNull()) + if (method == "Read" || method == "Write" || method == "Execute" || method == "Dir") { - reply.addYCPValue(ret); + YCPValue arg = request.getYCPValue(1); + YCPValue opt = request.getYCPValue(2); + std::string caller(request.sender()), arg_str, opt_str; + + if (!arg.isNull()) + { + arg_str = arg->toString(); + } + + if (!opt.isNull()) + { + opt_str = opt->toString(); + } + + // PolicyKit check + if (!isActionAllowed(caller, path_str, method, arg_str, opt_str)) + { + // access denied + reply.createError(request, "Argument 'path' is empty", DBUS_ERROR_ACCESS_DENIED); + } + else + { + YCPPath pth(path_str); + YCPValue ret; + + if (method == "Read") + ret = sa->Read(pth, arg, opt); + else if (method == "Write") + ret = sa->Write(pth, arg, opt); + else if (method == "Execute") + ret = sa->Execute(pth, arg, opt); + else if (method == "Dir") + ret = sa->Dir(pth); + + reply.createReply(request); + + if (!ret.isNull()) + { + reply.addYCPValue(ret); + } + } + } + else + { + y2warning("Unknown requested method %s", method.c_str()); + reply.createError(request, ("Unknown method: " + method).c_str(), DBUS_ERROR_UNKNOWN_METHOD); + // don't create a standard reply } } } @@ -132,7 +156,7 @@ "<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\"> <node> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg name="xml_data" type="s" direction="out"/> </method> </interface> <node name="SCR"/></node>" : // introcpection data for SCR node -"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\"> <node> <interface name="org.opensuse.yast.SCR"> <method name="Read"><arg name="path" type="s" direction="in"/><arg name="arg" type="v" direction="in"/><arg name="opt" type="v" direction="in"/><arg name="ret" type="v" direction="out"/> </method><method name="Write"><arg name="path" type="s" direction="in"/><arg name="arg" type="v" direction="in"/><arg name="opt" type="v" direction="in"/><arg name="ret" type="v" direction="out"/> </method><method name="Execute"><arg name="path" type="s" direction="in"/><arg name="arg" type="v" direction="in"/><arg name="opt" type="v" direction="in"/><arg name="ret" type="v" direction="out"/></method><method name="Dir"><arg name="path" type="s" direction="in"/><arg name="ret" type="av" direction="out"/> </method> </interface> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg name="xml_data" type="s" direction="out"/> </method> </interface> </node> "; +"<!DOCTYPE node PUBLIC \"-//freedesktop//DTD D-BUS Object Introspection 1.0//EN\" \"http://www.freedesktop.org/standards/dbus/1.0/introspect.dtd\"> <node> <interface name="org.opensuse.yast.SCR"> <method name="Read"><arg name="path" type="s" direction="in"/><arg name="arg" type="v" direction="in"/><arg name="opt" type="v" direction="in"/><arg name="ret" type="v" direction="out"/> </method><method name="Write"><arg name="path" type="s" direction="in"/><arg name="arg" type="v" direction="in"/><arg name="opt" type="v" direction="in"/><arg name="ret" type="v" direction="out"/> </method><method name="Execute"><arg name="path" type="s" direction="in"/><arg name="arg" type="v" direction="in"/><arg name="opt" type="v" direction="in"/><arg name="ret" type="v" direction="out"/></method><method name="Dir"><arg name="path" type="s" direction="in"/><arg name="ret" type="av" direction="out"/> </method> </interface> <interface name="org.freedesktop.DBus.Introspectable"> <method name="Introspect"> <arg name="xml_data" type="s" direction="out"/> </method> </interface> </node>"; // create a reply to the request reply.createReply(request); @@ -167,3 +191,26 @@ } } +bool DBusServer::isActionAllowed(const std::string &caller, const std::string &path, const std::string &method, + const std::string &arg, const std::string &opt) +{ + // create actionId + static const char *polkit_prefix = "org.opensuse.yast.scr"; + std::string action_id(PolKit::createActionId(polkit_prefix, path, method, arg, opt)); + + bool ret = false; + + // check the policy here + if (policykit.isDBusUserAuthorized(action_id, caller, connection.getConnection())) + { + y2security("User is authorized to do action %s", action_id.c_str()); + ret = true; + } + else + { + y2security("User is NOT authorized to do action %s", action_id.c_str()); + } + + return ret; +} + Modified: branches/tmp/lslezak/workshop/core/scr/src/DBusServer.h URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/DBusServer.h (original) +++ branches/tmp/lslezak/workshop/core/scr/src/DBusServer.h Fri Jul 11 12:45:59 2008 @@ -9,8 +9,8 @@ #include <dbus/dbus.h> #include "DBusConn.h" - #include "ScriptingAgent.h" +#include "PolKit.h" class DBusServer { @@ -24,15 +24,16 @@ private: - const char *_service_name; - const char *_interface_name; - DBusConn connection; -// DBusError dbus_error; + + bool isActionAllowed(const std::string &caller, const std::string &path, + const std::string &method, const std::string &arg, const std::string &opt); // SCR access ScriptingAgent *sa; + PolKit policykit; + // disable copying DBusServer(const DBusServer&); DBusServer& operator=(const DBusServer&); Modified: branches/tmp/lslezak/workshop/core/scr/src/Makefile.am URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/Makefile.am (original) +++ branches/tmp/lslezak/workshop/core/scr/src/Makefile.am Fri Jul 11 12:45:59 2008 @@ -45,9 +45,9 @@ ybin_PROGRAMS = SCR_dbus_server SCR_dbus_server_SOURCES = SCR_dbus_server.cc DBusServer.cc DBusServer.h \ - DBusMsg.cc DBusMsg.h DBusConn.cc DBusConn.h + DBusMsg.cc DBusMsg.h DBusConn.cc DBusConn.h PolKit.cc PolKit.h -SCR_dbus_server_CPPFLAGS = $(AM_CPPFLAGS) $(DBUS_CFLAGS) +SCR_dbus_server_CPPFLAGS = $(AM_CPPFLAGS) $(DBUS_CFLAGS) $(POLKIT_CFLAGS) -SCR_dbus_server_LDADD = $(DBUS_LIBS) ${AGENT_LIBADD} libpy2scr.la +SCR_dbus_server_LDADD = ${AGENT_LIBADD} libpy2scr.la $(DBUS_LIBS) $(POLKIT_LIBS) Modified: branches/tmp/lslezak/workshop/core/scr/src/PolKit.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/PolKit.cc (original) +++ branches/tmp/lslezak/workshop/core/scr/src/PolKit.cc Fri Jul 11 12:45:59 2008 @@ -5,245 +5,71 @@ #include "PolKit.h" -#include <stdlib.h> - -#include <dbus/dbus.h> -#include <polkit-dbus/polkit-dbus.h> - #include <ycp/y2log.h> -PolKit::PolKit() +PolKit::PolKit() : polkit_error(NULL) { + dbus_error_init (&dbus_error); + context = polkit_context_new(); + polkit_context_init(context, &polkit_error); } PolKit::~PolKit() { + dbus_error_free(&dbus_error); } -bool PolKit::isUserAuthorized(const std::string &action_id) + +bool PolKit::isDBusUserAuthorized(const std::string &action_id, const std::string &dbus_caller, DBusConnection *con) { - y2milestone("Checking action %s", action_id.c_str()); - // root is always authorized - if (getuid() == 0) - { - y2debug("User root is always authorized"); - return true; - } + y2debug("Checking action %s from %s", action_id.c_str(), dbus_caller.c_str()); - bool ret = false; - DBusError dbus_error; - DBusConnection *bus = NULL; - PolKitCaller *caller = NULL; - PolKitAction *action = NULL; - PolKitContext *context = NULL; + PolKitCaller *pk_caller = polkit_caller_new_from_dbus_name(con, dbus_caller.c_str(), &dbus_error); PolKitError *polkit_error = NULL; - PolKitSession *session = NULL; - PolKitResult polkit_result; - - dbus_error_init(&dbus_error); - - if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error))) { - goto finish; - } - - if (!(caller = polkit_caller_new_from_pid(bus, getpid(), &dbus_error))) { - goto finish; - } - - if (!(polkit_caller_set_uid(caller, getuid()))) { - goto finish; - } - - if (!(polkit_caller_get_ck_session(caller, &session))) { - goto finish; - } - - if (session != NULL && !(polkit_session_set_uid(session, getuid()))) { - goto finish; - } - if (!(action = polkit_action_new())) { - goto finish; - } - - if (!polkit_action_set_action_id(action, action_id.c_str())) { - goto finish; - } - - if (!(context = polkit_context_new())) { - goto finish; - } - - if (!polkit_context_init(context, &polkit_error)) { - goto finish; - } - - for (;;) { - - polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error); - - if (polkit_error_is_set(polkit_error)) { - goto finish; - } - - y2milestone("Action: %s Result: %s", action_id.c_str(), polkit_result_to_string_representation(polkit_result)); - - if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH || - polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION || - polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS || - polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT - ) { - y2milestone("Obtaining the authentication..."); - - int obtained = polkit_auth_obtain(action_id.c_str(), 0, getpid(), &dbus_error); - - y2milestone("Obtained: %d", obtained); - - if (obtained) { - polkit_result = POLKIT_RESULT_YES; - break; - } - - if (dbus_error_is_set(&dbus_error)) { - y2error("DBUS error"); - goto finish; - } - } - - break; + if (pk_caller == NULL) + { + y2error("PolKitCaller is NULL!"); + return false; } - ret = polkit_result == POLKIT_RESULT_YES; + PolKitAction *pk_action = polkit_action_new(); + polkit_action_set_action_id (pk_action, action_id.c_str()); -finish: + PolKitResult pk_result = polkit_context_is_caller_authorized( + context, pk_action, pk_caller, TRUE, &polkit_error); - if (caller) - polkit_caller_unref(caller); - - if (action) - polkit_action_unref(action); - - if (context) - polkit_context_unref(context); - - if (bus) - dbus_connection_unref(bus); - - dbus_error_free(&dbus_error); + polkit_caller_unref (pk_caller); + polkit_action_unref (pk_action); if (polkit_error) polkit_error_free(polkit_error); - return ret; + return pk_result == POLKIT_RESULT_YES; } -bool PolKit::isDBusUserAuthorized(const std::string &action_id, const std::string &dbus_caller) +std::string toLower(const std::string &s) { - bool ret = false; - DBusError dbus_error; - DBusConnection *bus = NULL; - PolKitCaller *caller = NULL; - PolKitAction *action = NULL; - PolKitContext *context = NULL; - PolKitError *polkit_error = NULL; - PolKitSession *session = NULL; - PolKitResult polkit_result; + if (s.empty()) + return s; - dbus_error_init(&dbus_error); - - if (!(bus = dbus_bus_get(DBUS_BUS_SYSTEM, &dbus_error))) { - dbus_error_free (&dbus_error); - return false; - } - - caller = polkit_caller_new_from_dbus_name ( - bus, - dbus_caller.c_str(), - &dbus_error); - - if (caller == NULL) { - dbus_error_free (&dbus_error); - return false; - } - - if (!(polkit_caller_get_ck_session(caller, &session))) { - goto finish; - } - - action = polkit_action_new (); - polkit_action_set_action_id (action, action_id.c_str()); - - if (!(context = polkit_context_new())) { - goto finish; - } - - if (!polkit_context_init(context, &polkit_error)) { - goto finish; - } - - for (;;) { - - polkit_result = polkit_context_is_caller_authorized(context, action, caller, TRUE, &polkit_error); - - if (polkit_error_is_set(polkit_error)) { - goto finish; - } - - y2milestone("Action: %s Result: %s", action_id.c_str(), polkit_result_to_string_representation(polkit_result)); - - if (polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH || - polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_SESSION || - polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_KEEP_ALWAYS || - polkit_result == POLKIT_RESULT_ONLY_VIA_ADMIN_AUTH_ONE_SHOT || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_SESSION || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_KEEP_ALWAYS || - polkit_result == POLKIT_RESULT_ONLY_VIA_SELF_AUTH_ONE_SHOT - ) { - y2milestone("Obtaining the authentication..."); - - int obtained = polkit_auth_obtain(action_id.c_str(), 0, getpid(), &dbus_error); - - y2milestone("Obtained: %d", obtained); - - if (obtained) { - polkit_result = POLKIT_RESULT_YES; - break; - } - - if (dbus_error_is_set(&dbus_error)) { - y2error("DBUS error"); - goto finish; - } - } - - break; + std::string ret(s); + for (std::string::size_type i = 0; i < ret.length(); ++i) + { + if (isupper(ret[i])) + ret[i] = static_cast<char>(tolower(ret[i])); } - ret = polkit_result == POLKIT_RESULT_YES; - -finish: - - if (caller) - polkit_caller_unref(caller); - - if (action) - polkit_action_unref(action); - - if (context) - polkit_context_unref(context); - - if (bus) - dbus_connection_unref(bus); + return ret; +} - dbus_error_free(&dbus_error); +std::string PolKit::createActionId(const std::string &prefix, const std::string &path, const std::string &method, + const std::string &arg, const std::string &opt) +{ + std::string action_id(prefix + path + "." + method); - if (polkit_error) - polkit_error_free(polkit_error); + // actionID must contain only [a-z],[0-9] and _. characters + action_id = toLower(action_id); - return ret; + return action_id; } Modified: branches/tmp/lslezak/workshop/core/scr/src/PolKit.h URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/PolKit.h (original) +++ branches/tmp/lslezak/workshop/core/scr/src/PolKit.h Fri Jul 11 12:45:59 2008 @@ -9,6 +9,9 @@ #include <string> +#include <dbus/dbus.h> +#include <polkit-dbus/polkit-dbus.h> + class PolKit { public: @@ -16,11 +19,17 @@ PolKit(); ~PolKit(); - static bool isUserAuthorized(const std::string &action_id); - static bool isDBusUserAuthorized(const std::string &action_id, const std::string &dbus_caller); + bool isDBusUserAuthorized(const std::string &action_id, const std::string &dbus_caller, DBusConnection *con); + + static std::string createActionId(const std::string &prefix, const std::string &path, + const std::string &method, const std::string &arg = std::string(), + const std::string &opt = std::string()); private: + DBusError dbus_error; + PolKitError *polkit_error; + PolKitContext *context; }; #endif Modified: branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.cc URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.cc (original) +++ branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.cc Fri Jul 11 12:45:59 2008 @@ -24,12 +24,6 @@ #include <y2/Y2ComponentBroker.h> #include "ScriptingAgent.h" -#include "config.h" - -#ifdef HAVE_POLKIT -#include "PolKit.h" -const char *polkit_prefix = "org.opensuse.yast"; -#endif ScriptingAgent::ScriptingAgent () : done_sweep (false) @@ -570,48 +564,12 @@ return findSubagent (path); } -std::string toLower( const std::string & s ) -{ - if ( s.empty() ) - return s; - - std::string ret( s ); - for ( std::string::size_type i = 0; i < ret.length(); ++i ) - { - if ( isupper( ret[i] ) ) - ret[i] = static_cast<char>(tolower( ret[i] )); - } - return ret; -} - YCPValue ScriptingAgent::executeSubagentCommand (const char *command, const YCPPath &path, const YCPValue &arg, const YCPValue &optpar) { -#ifdef HAVE_POLKIT - std::string pathstr(path->toString().c_str()); - y2internal("Path: %s", pathstr.c_str()); - -// std::string action_id(polkit_prefix + pathstr + "." + toLower(command)); - std::string action_id(polkit_prefix + toLower (pathstr) + "." + toLower(command)); - - y2security ("action id: %s", action_id.c_str()); - - // check the policy here - if (PolKit::isDBusUserAuthorized(action_id, dbus_caller)) - { - y2internal("User is authorized to do acion %s", action_id.c_str()); - } - else - { - return YCPError(("User is NOT authorized to do " + action_id).c_str(), YCPNull()); - } -#else - y2milestone("PolicyKit is disabled"); -#endif - y2debug( "ScriptingAgent::executeSubagentCommand: %s", command ); y2debug( "path: %s", path->toString ().c_str ()); y2debug( "arg: %s", arg.isNull() ? "null" : arg->toString().c_str ()); @@ -662,4 +620,3 @@ return agents.end (); } - Modified: branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.h URL: http://svn.opensuse.org/viewcvs/yast/branches/tmp/lslezak/workshop/core/scr/... ============================================================================== --- branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.h (original) +++ branches/tmp/lslezak/workshop/core/scr/src/ScriptingAgent.h Fri Jul 11 12:45:59 2008 @@ -43,18 +43,6 @@ */ ~ScriptingAgent (); -/* - YCPValue Get(const YCPPath& path, const YCPValue& arg = YCPNull(), const YCPValue& opt = YCPNull()); - - virtual YCPBoolean Set(const YCPPath& path, const YCPValue& value, const YCPValue& arg = YCPNull()); - - virtual YCPList List(const YCPPath& path); -*/ -// virtual YCPValue Run(const YCPPath& path, const YCPValue& /*value*/ = YCPNull(), -// const YCPValue& /*arg*/ = YCPNull()); - -private: - /** * Reads data. * @param path Specifies what part of the subtree should -- To unsubscribe, e-mail: yast-commit+unsubscribe@opensuse.org For additional commands, e-mail: yast-commit+help@opensuse.org