diff options
author | David Zeuthen <davidz@redhat.com> | 2009-07-20 18:49:25 -0400 |
---|---|---|
committer | David Zeuthen <davidz@redhat.com> | 2009-07-20 18:49:25 -0400 |
commit | 36fc7a6d358c1d373c181191da6265a538a71dae (patch) | |
tree | 166630eadb8a659fb9ea988f93d3ff7120d8dd64 | |
parent | ae8ea087928b7a1bc34b2380872da8867563bec1 (diff) | |
download | polkit-36fc7a6d358c1d373c181191da6265a538a71dae.tar.gz |
Add support for querying and revoking temporary authorizations
Also change how authentication agents are registered (take a Subject
instead of the session-id) and add convenience functions to
asynchronously construct a PolkitUnixSession object given a process id
(by querying ConsoleKit).
24 files changed, 1958 insertions, 211 deletions
diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml index ed4e57a..6b29e8e 100644 --- a/data/org.freedesktop.PolicyKit1.Authority.xml +++ b/data/org.freedesktop.PolicyKit1.Authority.xml @@ -30,7 +30,7 @@ <!-- Identity struct --> <annotation name="org.gtk.EggDBus.DeclareStruct" value="Identity"> - <annotation name="org.gtk.EggDBus.DocString.Summary" value="Subjects"/> + <annotation name="org.gtk.EggDBus.DocString.Summary" value="Identities"/> <annotation name="org.gtk.EggDBus.DocString" value="<para>This struct describes identities such as UNIX users and UNIX groups. It is typically used to check if a given process is authorized for an action.</para><para>The following kinds of identities are known:</para> <formalpara><title>Unix User</title><para><literal>identity_kind</literal> should be set to <literal>unix-user</literal> with key <literal>uid</literal> (of type <literal>uint32</literal>).</para></formalpara> <formalpara><title>Unix Group</title><para><literal>identity_kind</literal> should be set to <literal>unix-group</literal> with key <literal>gid</literal> (of type <literal>uint32</literal>).</para></formalpara> @@ -254,8 +254,9 @@ <method name="RegisterAuthenticationAgent"> <annotation name="org.gtk.EggDBus.DocString" value="<para>Register an authentication agent.</para><para>Note that current versions of PolicyKit will only work if @session_id is set to the empty string. In the future it might work for non-empty strings if the caller is sufficiently privileged.</para>"/> - <arg name="session_id" direction="in" type="s"> - <annotation name="org.gtk.EggDBus.DocString" value="The session to register the authentication for or blank for the session the caller of the method is in."/> + <arg name="subject" direction="in" type="(sa{sv})"> + <annotation name="org.gtk.EggDBus.Type" value="Subject"/> + <annotation name="org.gtk.EggDBus.DocString" value="The subject to register the authentication agent for, typically a session subject."/> </arg> <arg name="locale" direction="in" type="s"> @@ -270,12 +271,13 @@ <method name="UnregisterAuthenticationAgent"> <annotation name="org.gtk.EggDBus.DocString" value="Unregister an authentication agent."/> - <arg name="session_id" direction="in" type="s"> - <annotation name="org.gtk.EggDBus.DocString" value="The session identifier passed to org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent()."/> + <arg name="subject" direction="in" type="(sa{sv})"> + <annotation name="org.gtk.EggDBus.Type" value="Subject"/> + <annotation name="org.gtk.EggDBus.DocString" value="The @subject passed to org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent()."/> </arg> <arg name="object_path" direction="in" type="s"> - <annotation name="org.gtk.EggDBus.DocString" value="The object path of authentication agent object on the unique name of the caller."/> + <annotation name="org.gtk.EggDBus.DocString" value="The @object_path passed to org.freedesktop.PolicyKit1.Authority.RegisterAuthenticationAgent()."/> </arg> </method> @@ -292,6 +294,62 @@ </arg> </method> + <!-- ---------------------------------------------------------------------------------------------------- --> + + <!-- TemporaryAuthorization struct --> + <annotation name="org.gtk.EggDBus.DeclareStruct" value="TemporaryAuthorization"> + <annotation name="org.gtk.EggDBus.DocString.Summary" value="Temporary Authorizations"/> + <annotation name="org.gtk.EggDBus.DocString" value="This struct describes a temporary authorization."/> + + <annotation name="org.gtk.EggDBus.Struct.Member" value="String:id"> + <annotation name="org.gtk.EggDBus.DocString" value="An opaque identifier for the temporary authorization."/> + </annotation> + + <annotation name="org.gtk.EggDBus.Struct.Member" value="String:action_id"> + <annotation name="org.gtk.EggDBus.DocString" value="The action the temporary authorization is for."/> + </annotation> + + <annotation name="org.gtk.EggDBus.Struct.Member" value="Subject:subject"> + <annotation name="org.gtk.EggDBus.Type" value="Subject"/> + <annotation name="org.gtk.EggDBus.DocString" value="The subject the temporary authorization is for."/> + </annotation> + + <annotation name="org.gtk.EggDBus.Struct.Member" value="UInt64:time_obtained"> + <annotation name="org.gtk.EggDBus.DocString" value="When the temporary authorization was obtained, in seconds since the Epoch Jan 1, 1970 0:00 UTC."/> + </annotation> + + <annotation name="org.gtk.EggDBus.Struct.Member" value="UInt64:time_expires"> + <annotation name="org.gtk.EggDBus.DocString" value="When the temporary authorization is set to expire, in seconds since the Epoch Jan 1, 1970 0:00 UTC."/> + </annotation> + </annotation> + + <!-- ---------------------------------------------------------------------------------------------------- --> + + <method name="EnumerateTemporaryAuthorizations"> + <annotation name="org.gtk.EggDBus.DocString" value="Retrieves all temporary authorizations that applies to @subject."/> + + <arg name="subject" direction="in" type="(sa{sv})"> + <annotation name="org.gtk.EggDBus.Type" value="Subject"/> + <annotation name="org.gtk.EggDBus.DocString" value="The subject to get temporary authorizations for."/> + </arg> + + <arg name="temporary_authorizations" direction="out" type="a(ss(sa{sv})tt)"> + <annotation name="org.gtk.EggDBus.Type" value="Array<TemporaryAuthorization>"/> + <annotation name="org.gtk.EggDBus.DocString" value="An array of #TemporaryAuthorization structs."/> + </arg> + </method> + + <method name="RevokeTemporaryAuthorizations"> + <annotation name="org.gtk.EggDBus.DocString" value="Revokes all temporary authorizations that applies to @subject."/> + + <arg name="subject" direction="in" type="(sa{sv})"> + <annotation name="org.gtk.EggDBus.Type" value="Subject"/> + <annotation name="org.gtk.EggDBus.DocString" value="The subject to revoke temporary authorizations from."/> + </arg> + </method> + + <!-- ---------------------------------------------------------------------------------------------------- --> + <signal name="Changed"> <annotation name="org.gtk.EggDBus.DocString" value="This signal is emitted when actions and/or authorizations change"/> </signal> diff --git a/docs/polkit/polkit-1-docs.xml b/docs/polkit/polkit-1-docs.xml index aa3aa16..f09954b 100644 --- a/docs/polkit/polkit-1-docs.xml +++ b/docs/polkit/polkit-1-docs.xml @@ -72,6 +72,7 @@ <xi:include href="xml/polkitdetails.xml"/> <xi:include href="xml/polkiterror.xml"/> <xi:include href="xml/polkitactiondescription.xml"/> + <xi:include href="xml/polkittemporaryauthorization.xml"/> <chapter id="subjects"> <title>Subjects</title> <xi:include href="xml/polkitsubject.xml"/> diff --git a/docs/polkit/polkit-1-sections.txt b/docs/polkit/polkit-1-sections.txt index 1e3bd8c..f096d2d 100644 --- a/docs/polkit/polkit-1-sections.txt +++ b/docs/polkit/polkit-1-sections.txt @@ -31,11 +31,17 @@ polkit_authority_unregister_authentication_agent polkit_authority_unregister_authentication_agent_finish polkit_authority_authentication_agent_response polkit_authority_authentication_agent_response_finish +polkit_authority_enumerate_temporary_authorizations +polkit_authority_enumerate_temporary_authorizations_finish +polkit_authority_revoke_temporary_authorizations +polkit_authority_revoke_temporary_authorizations_finish polkit_authority_check_authorization_sync polkit_authority_enumerate_actions_sync polkit_authority_register_authentication_agent_sync polkit_authority_unregister_authentication_agent_sync polkit_authority_authentication_agent_response_sync +polkit_authority_enumerate_temporary_authorizations_sync +polkit_authority_revoke_temporary_authorizations_sync <SUBSECTION Standard> PolkitAuthorityClass POLKIT_AUTHORITY @@ -104,6 +110,9 @@ POLKIT_UNIX_GROUP_GET_CLASS <FILE>polkitunixsession</FILE> PolkitUnixSession polkit_unix_session_new +polkit_unix_session_new_for_process +polkit_unix_session_new_for_process_finish +polkit_unix_session_new_for_process_sync polkit_unix_session_get_session_id polkit_unix_session_set_session_id <SUBSECTION Standard> @@ -158,6 +167,9 @@ PolkitSubject PolkitSubjectIface polkit_subject_hash polkit_subject_equal +polkit_subject_exists +polkit_subject_exists_finish +polkit_subject_exists_sync polkit_subject_to_string polkit_subject_from_string <SUBSECTION Standard> @@ -252,6 +264,8 @@ polkit_backend_authority_unregister_authentication_agent polkit_backend_authority_authentication_agent_response polkit_backend_authority_enumerate_actions polkit_backend_authority_system_bus_name_owner_changed +polkit_backend_authority_enumerate_temporary_authorizations +polkit_backend_authority_revoke_temporary_authorizations polkit_backend_authority_get polkit_backend_register_authority <SUBSECTION Standard> @@ -420,3 +434,23 @@ POLKIT_AGENT_LISTENER_CLASS POLKIT_AGENT_IS_LISTENER_CLASS POLKIT_AGENT_LISTENER_GET_CLASS </SECTION> + +<SECTION> +<FILE>polkittemporaryauthorization</FILE> +<TITLE>PolkitTemporaryAuthorization</TITLE> +PolkitTemporaryAuthorization +PolkitTemporaryAuthorizationClass +polkit_temporary_authorization_get_id +polkit_temporary_authorization_get_action_id +polkit_temporary_authorization_get_subject +polkit_temporary_authorization_get_time_obtained +polkit_temporary_authorization_get_time_expires +<SUBSECTION Standard> +POLKIT_TEMPORARY_AUTHORIZATION +POLKIT_TEMPORARY_IS_AUTHORIZATION +POLKIT_TEMPORARY_TYPE_AUTHORIZATION +polkit_temporary_authorization_get_type +POLKIT_TEMPORARY_AUTHORIZATION_CLASS +POLKIT_TEMPORARY_IS_AUTHORIZATION_CLASS +POLKIT_TEMPORARY_AUTHORIZATION_GET_CLASS +</SECTION> diff --git a/docs/polkit/polkit-1.types b/docs/polkit/polkit-1.types index c212fd2..749b8bc 100644 --- a/docs/polkit/polkit-1.types +++ b/docs/polkit/polkit-1.types @@ -12,6 +12,7 @@ polkit_unix_session_get_type polkit_system_bus_name_get_type polkit_error_get_type polkit_authorization_result_get_type +polkit_temporary_authorization_get_type polkit_backend_authority_get_type polkit_backend_interactive_authority_get_type diff --git a/src/polkit/Makefile.am b/src/polkit/Makefile.am index b035282..88d5f38 100644 --- a/src/polkit/Makefile.am +++ b/src/polkit/Makefile.am @@ -33,7 +33,7 @@ polkit-built-sources.stamp : Makefile.am $(top_srcdir)/data/org.freedesktop.Poli # keep in sync with contents of polkit-built-sources.stamp (Thanks autotools) # -polkit_built_sources = _polkitbindingsmarshal.c _polkitbindingsmarshal.h _polkitbindingsmarshal.list _polkitbindings.c _polkitbindings.h _polkitbindingstypes.h _polkitauthenticationagent.c _polkitauthenticationagent.h docbook-interface-org.freedesktop.PolicyKit1.AuthenticationAgent.xml _polkitauthority.c _polkitauthority.h docbook-interface-org.freedesktop.PolicyKit1.Authority.xml _polkiterror.c _polkiterror.h _polkitimplicitauthorization.c _polkitimplicitauthorization.h _polkitauthorizationresult.c _polkitauthorizationresult.h _polkitcheckauthorizationflags.c _polkitcheckauthorizationflags.h _polkitactiondescription.c _polkitactiondescription.h _polkitidentity.c _polkitidentity.h _polkitsubject.c _polkitsubject.h +polkit_built_sources = _polkitactiondescription.c _polkitactiondescription.h _polkitauthenticationagent.c _polkitauthenticationagent.h _polkitauthority.c _polkitauthority.h _polkitauthorizationresult.c _polkitauthorizationresult.h _polkitbindings.c _polkitbindings.h _polkitbindingsmarshal.c _polkitbindingsmarshal.h _polkitbindingstypes.h _polkitcheckauthorizationflags.c _polkitcheckauthorizationflags.h _polkiterror.c _polkiterror.h _polkitidentity.c _polkitidentity.h _polkitimplicitauthorization.c _polkitimplicitauthorization.h _polkitsubject.c _polkitsubject.h _polkittemporaryauthorization.c _polkittemporaryauthorization.h docbook-interface-org.freedesktop.PolicyKit1.AuthenticationAgent.xml docbook-interface-org.freedesktop.PolicyKit1.Authority.xml lib_LTLIBRARIES=libpolkit-gobject-1.la @@ -57,6 +57,7 @@ libpolkit_gobject_1include_HEADERS = \ polkitauthorizationresult.h \ polkitcheckauthorizationflags.h \ polkitimplicitauthorization.h \ + polkittemporaryauthorization.h \ $(NULL) libpolkit_gobject_1_la_SOURCES = \ @@ -77,6 +78,7 @@ libpolkit_gobject_1_la_SOURCES = \ polkitauthorizationresult.c polkitauthorizationresult.h \ polkitcheckauthorizationflags.c polkitcheckauthorizationflags.h \ polkitimplicitauthorization.c polkitimplicitauthorization.h \ + polkittemporaryauthorization.c polkittemporaryauthorization.h \ $(NULL) libpolkit_gobject_1_la_CFLAGS = \ diff --git a/src/polkit/polkit.h b/src/polkit/polkit.h index ee3b0bd..9c16710 100644 --- a/src/polkit/polkit.h +++ b/src/polkit/polkit.h @@ -38,6 +38,7 @@ #include <polkit/polkitcheckauthorizationflags.h> #include <polkit/polkitauthority.h> #include <polkit/polkitdetails.h> +#include <polkit/polkittemporaryauthorization.h> #undef _POLKIT_INSIDE_POLKIT_H diff --git a/src/polkit/polkitactiondescription.c b/src/polkit/polkitactiondescription.c index f36b68d..cc1a8b5 100644 --- a/src/polkit/polkitactiondescription.c +++ b/src/polkit/polkitactiondescription.c @@ -33,7 +33,7 @@ /** * SECTION:polkitactiondescription * @title: PolkitActionDescription - * @short_description: Actions + * @short_description: Description of Actions * * Object used to encapsulate a registered action. */ diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c index 4bb7ecd..4d34b16 100644 --- a/src/polkit/polkitauthority.c +++ b/src/polkit/polkitauthority.c @@ -572,7 +572,7 @@ polkit_authority_check_authorization_sync (PolkitAuthority *author static guint polkit_authority_register_authentication_agent_async (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GCancellable *cancellable, @@ -581,20 +581,24 @@ polkit_authority_register_authentication_agent_async (PolkitAuthority *auth { guint call_id; GSimpleAsyncResult *simple; + _PolkitSubject *real_subject; simple = g_simple_async_result_new (G_OBJECT (authority), callback, user_data, polkit_authority_register_authentication_agent_async); + real_subject = polkit_subject_get_real (subject); + call_id = _polkit_authority_register_authentication_agent (authority->real, EGG_DBUS_CALL_FLAGS_NONE, - session_id, + real_subject, locale, object_path, cancellable, generic_async_cb, simple); + g_object_unref (real_subject); return call_id; } @@ -602,7 +606,7 @@ polkit_authority_register_authentication_agent_async (PolkitAuthority *auth /** * polkit_authority_register_authentication_agent: * @authority: A #PolkitAuthority. - * @session_id: The identifier of the session to register for or %NULL for the session of the caller. + * @subject: The subject the authentication agent is for, typically a #PolkitUnixSession object. * @locale: The locale of the authentication agent. * @object_path: The object path for the authentication agent. * @cancellable: A #GCancellable or %NULL. @@ -617,7 +621,7 @@ polkit_authority_register_authentication_agent_async (PolkitAuthority *auth **/ void polkit_authority_register_authentication_agent (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GCancellable *cancellable, @@ -625,7 +629,7 @@ polkit_authority_register_authentication_agent (PolkitAuthority *authority, gpointer user_data) { polkit_authority_register_authentication_agent_async (authority, - session_id, + subject, locale, object_path, cancellable, @@ -673,7 +677,7 @@ polkit_authority_register_authentication_agent_finish (PolkitAuthority *authorit /** * polkit_authority_register_authentication_agent_sync: * @authority: A #PolkitAuthority. - * @session_id: The identifier of the session to register for or %NULL for the session of the caller. + * @subject: The subject the authentication agent is for, typically a #PolkitUnixSession object. * @locale: The locale of the authentication agent. * @object_path: The object path for the authentication agent. * @cancellable: A #GCancellable or %NULL. @@ -685,7 +689,7 @@ polkit_authority_register_authentication_agent_finish (PolkitAuthority *authorit **/ gboolean polkit_authority_register_authentication_agent_sync (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GCancellable *cancellable, @@ -696,7 +700,7 @@ polkit_authority_register_authentication_agent_sync (PolkitAuthority *author gboolean ret; call_id = polkit_authority_register_authentication_agent_async (authority, - session_id, + subject, locale, object_path, cancellable, @@ -716,7 +720,7 @@ polkit_authority_register_authentication_agent_sync (PolkitAuthority *author static guint polkit_authority_unregister_authentication_agent_async (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -724,27 +728,32 @@ polkit_authority_unregister_authentication_agent_async (PolkitAuthority *au { guint call_id; GSimpleAsyncResult *simple; + _PolkitSubject *real_subject; simple = g_simple_async_result_new (G_OBJECT (authority), callback, user_data, polkit_authority_unregister_authentication_agent_async); + real_subject = polkit_subject_get_real (subject); + call_id = _polkit_authority_unregister_authentication_agent (authority->real, EGG_DBUS_CALL_FLAGS_NONE, - session_id, + real_subject, object_path, cancellable, generic_async_cb, simple); + g_object_unref (real_subject); + return call_id; } /** * polkit_authority_unregister_authentication_agent: * @authority: A #PolkitAuthority. - * @session_id: The identifier of the session the agent is registered at or %NULL for the session of the caller. + * @subject: The #PolkitSubject passed when registering the agent. * @object_path: The object path that the authentication agent is registered at. * @cancellable: A #GCancellable or %NULL. * @callback: A #GAsyncReadyCallback to call when the request is satisfied. @@ -758,14 +767,14 @@ polkit_authority_unregister_authentication_agent_async (PolkitAuthority *au **/ void polkit_authority_unregister_authentication_agent (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data) { polkit_authority_unregister_authentication_agent_async (authority, - session_id, + subject, object_path, cancellable, callback, @@ -811,7 +820,7 @@ polkit_authority_unregister_authentication_agent_finish (PolkitAuthority *author /** * polkit_authority_unregister_authentication_agent_sync: * @authority: A #PolkitAuthority. - * @session_id: The identifier of the session the agent is registered at or %NULL for the session of the caller. + * @subject: The #PolkitSubject passed when registering the agent. * @object_path: The object path that the authentication agent is registered at. * @cancellable: A #GCancellable or %NULL. * @error: Return location for error or %NULL. @@ -822,7 +831,7 @@ polkit_authority_unregister_authentication_agent_finish (PolkitAuthority *author **/ gboolean polkit_authority_unregister_authentication_agent_sync (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GCancellable *cancellable, GError **error) @@ -832,7 +841,7 @@ polkit_authority_unregister_authentication_agent_sync (PolkitAuthority *auth gboolean ret; call_id = polkit_authority_unregister_authentication_agent_async (authority, - session_id, + subject, object_path, cancellable, generic_cb, @@ -995,3 +1004,197 @@ polkit_authority_authentication_agent_response_sync (PolkitAuthority *author } /* ---------------------------------------------------------------------------------------------------- */ + +static guint +polkit_authority_enumerate_temporary_authorizations_async (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + guint call_id; + GSimpleAsyncResult *simple; + _PolkitSubject *real_subject; + + simple = g_simple_async_result_new (G_OBJECT (authority), + callback, + user_data, + polkit_authority_enumerate_temporary_authorizations_async); + + real_subject = polkit_subject_get_real (subject); + + call_id = _polkit_authority_enumerate_temporary_authorizations (authority->real, + EGG_DBUS_CALL_FLAGS_NONE, + real_subject, + cancellable, + generic_async_cb, + simple); + + g_object_unref (real_subject); + + return call_id; +} + +void +polkit_authority_enumerate_temporary_authorizations (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + polkit_authority_enumerate_temporary_authorizations_async (authority, subject, cancellable, callback, user_data); +} + +GList * +polkit_authority_enumerate_temporary_authorizations_finish (PolkitAuthority *authority, + GAsyncResult *res, + GError **error) +{ + EggDBusArraySeq *array_seq; + GList *result; + guint n; + GSimpleAsyncResult *simple; + GAsyncResult *real_res; + + simple = G_SIMPLE_ASYNC_RESULT (res); + real_res = G_ASYNC_RESULT (g_simple_async_result_get_op_res_gpointer (simple)); + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_authority_enumerate_temporary_authorizations_async); + + result = NULL; + + if (!_polkit_authority_enumerate_temporary_authorizations_finish (authority->real, + &array_seq, + real_res, + error)) + goto out; + + for (n = 0; n < array_seq->size; n++) + { + _PolkitTemporaryAuthorization *real_ta; + + real_ta = array_seq->data.v_ptr[n]; + + result = g_list_prepend (result, polkit_temporary_authorization_new_for_real (real_ta)); + } + + result = g_list_reverse (result); + + g_object_unref (array_seq); + + out: + g_object_unref (real_res); + return result; +} + +GList * +polkit_authority_enumerate_temporary_authorizations_sync (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GError **error) +{ + guint call_id; + GAsyncResult *res; + GList *result; + + call_id = polkit_authority_enumerate_temporary_authorizations_async (authority, subject, cancellable, generic_cb, &res); + + egg_dbus_connection_pending_call_block (authority->system_bus, call_id); + + result = polkit_authority_enumerate_temporary_authorizations_finish (authority, res, error); + + g_object_unref (res); + + return result; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static guint +polkit_authority_revoke_temporary_authorizations_async (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + guint call_id; + GSimpleAsyncResult *simple; + _PolkitSubject *real_subject; + + simple = g_simple_async_result_new (G_OBJECT (authority), + callback, + user_data, + polkit_authority_revoke_temporary_authorizations_async); + + real_subject = polkit_subject_get_real (subject); + + call_id = _polkit_authority_revoke_temporary_authorizations (authority->real, + EGG_DBUS_CALL_FLAGS_NONE, + real_subject, + cancellable, + generic_async_cb, + simple); + + g_object_unref (real_subject); + + return call_id; +} + +void +polkit_authority_revoke_temporary_authorizations (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + polkit_authority_revoke_temporary_authorizations_async (authority, subject, cancellable, callback, user_data); +} + +gboolean +polkit_authority_revoke_temporary_authorizations_finish (PolkitAuthority *authority, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple; + GAsyncResult *real_res; + gboolean ret; + + simple = G_SIMPLE_ASYNC_RESULT (res); + real_res = G_ASYNC_RESULT (g_simple_async_result_get_op_res_gpointer (simple)); + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_authority_revoke_temporary_authorizations_async); + + ret = _polkit_authority_revoke_temporary_authorizations_finish (authority->real, + real_res, + error); + + if (!ret) + goto out; + + out: + g_object_unref (real_res); + return ret; +} + +gboolean +polkit_authority_revoke_temporary_authorizations_sync (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GError **error) +{ + guint call_id; + GAsyncResult *res; + gboolean result; + + call_id = polkit_authority_revoke_temporary_authorizations_async (authority, subject, cancellable, generic_cb, &res); + + egg_dbus_connection_pending_call_block (authority->system_bus, call_id); + + result = polkit_authority_revoke_temporary_authorizations_finish (authority, res, error); + + g_object_unref (res); + + return result; +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/polkit/polkitauthority.h b/src/polkit/polkitauthority.h index e9df6d0..61a6e7c 100644 --- a/src/polkit/polkitauthority.h +++ b/src/polkit/polkitauthority.h @@ -71,14 +71,14 @@ PolkitAuthorizationResult *polkit_authority_check_authorization_sync (PolkitAuth GError **error); gboolean polkit_authority_register_authentication_agent_sync (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GCancellable *cancellable, GError **error); gboolean polkit_authority_unregister_authentication_agent_sync (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GCancellable *cancellable, GError **error); @@ -89,6 +89,16 @@ gboolean polkit_authority_authentication_agent_response_sync ( GCancellable *cancellable, GError **error); +GList *polkit_authority_enumerate_temporary_authorizations_sync (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GError **error); + +gboolean polkit_authority_revoke_temporary_authorizations_sync (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GError **error); + /* ---------------------------------------------------------------------------------------------------- */ void polkit_authority_enumerate_actions (PolkitAuthority *authority, @@ -114,7 +124,7 @@ PolkitAuthorizationResult *polkit_authority_check_authorization_finish (PolkitAu GError **error); void polkit_authority_register_authentication_agent (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GCancellable *cancellable, @@ -126,7 +136,7 @@ gboolean polkit_authority_register_authentication_agent_finish GError **error); void polkit_authority_unregister_authentication_agent (PolkitAuthority *authority, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GCancellable *cancellable, GAsyncReadyCallback callback, @@ -147,6 +157,26 @@ gboolean polkit_authority_authentication_agent_response_finish GAsyncResult *res, GError **error); +void polkit_authority_enumerate_temporary_authorizations (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +GList *polkit_authority_enumerate_temporary_authorizations_finish (PolkitAuthority *authority, + GAsyncResult *res, + GError **error); + +void polkit_authority_revoke_temporary_authorizations (PolkitAuthority *authority, + PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean polkit_authority_revoke_temporary_authorizations_finish (PolkitAuthority *authority, + GAsyncResult *res, + GError **error); + /* ---------------------------------------------------------------------------------------------------- */ G_END_DECLS diff --git a/src/polkit/polkitprivate.h b/src/polkit/polkitprivate.h index 89601fc..3d4ed16 100644 --- a/src/polkit/polkitprivate.h +++ b/src/polkit/polkitprivate.h @@ -26,6 +26,7 @@ #include "polkitactiondescription.h" #include "polkitsubject.h" #include "polkitauthorizationresult.h" +#include "polkittemporaryauthorization.h" #include "_polkitbindings.h" /* notes: @@ -47,6 +48,8 @@ _PolkitIdentity *polkit_identity_get_real (PolkitIdentity *identity); PolkitAuthorizationResult *polkit_authorization_result_new_for_real (_PolkitAuthorizationResult *real); _PolkitAuthorizationResult *polkit_authorization_result_get_real (PolkitAuthorizationResult *authorization_result); +_PolkitTemporaryAuthorization *polkit_temporary_authorization_get_real (PolkitTemporaryAuthorization *authorization); +PolkitTemporaryAuthorization *polkit_temporary_authorization_new_for_real (_PolkitTemporaryAuthorization *real); PolkitDetails *polkit_details_new_for_hash (GHashTable *hash); GHashTable *polkit_details_get_hash (PolkitDetails *details); diff --git a/src/polkit/polkitsubject.c b/src/polkit/polkitsubject.c index 43be6b9..b2f9290 100644 --- a/src/polkit/polkitsubject.c +++ b/src/polkit/polkitsubject.c @@ -126,6 +126,74 @@ polkit_subject_to_string (PolkitSubject *subject) } /** + * polkit_subject_exists: + * @subject: A #PolkitSubject. + * @cancellable: A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback. + * + * Asynchronously checks if @subject exists. + * + * When the operation is finished, @callback will be invoked. You can + * then call polkit_subject_exists_finish() to get the result of the + * operation. + **/ +void +polkit_subject_exists (PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + POLKIT_SUBJECT_GET_IFACE (subject)->exists (subject, + cancellable, + callback, + user_data); +} + +/** + * polkit_subject_exists_finish: + * @subject: A #PolkitSubject. + * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to polkit_subject_exists(). + * @error: Return location for error or %NULL. + * + * Finishes checking whether a subject exists. + * + * Returns: %TRUE if the subject exists, %FALSE if not or @error is set. + */ +gboolean +polkit_subject_exists_finish (PolkitSubject *subject, + GAsyncResult *res, + GError **error) +{ + return POLKIT_SUBJECT_GET_IFACE (subject)->exists_finish (subject, + res, + error); +} + +/** + * polkit_subject_exists_sync: + * @subject: A #PolkitSubject. + * @cancellable: A #GCancellable or %NULL. + * @error: Return location for error or %NULL. + * + * Checks if @subject exists. + * + * This is a synchronous blocking call, see polkit_subject_exists() + * for the asynchronous version. + * + * Returns: %TRUE if the subject exists, %FALSE if not or @error is set. + */ +gboolean +polkit_subject_exists_sync (PolkitSubject *subject, + GCancellable *cancellable, + GError **error) +{ + return POLKIT_SUBJECT_GET_IFACE (subject)->exists_sync (subject, + cancellable, + error); +} + +/** * polkit_subject_from_string: * @str: A string obtained from polkit_subject_to_string(). * @error: Return location for error. diff --git a/src/polkit/polkitsubject.h b/src/polkit/polkitsubject.h index 6eb8fef..616d95e 100644 --- a/src/polkit/polkitsubject.h +++ b/src/polkit/polkitsubject.h @@ -54,6 +54,9 @@ typedef struct _PolkitSubjectIface PolkitSubjectIface; * @equal: Checks if two #PolkitSubject<!-- -->s are equal. * @to_string: Serializes a #PolkitSubject to a string that can be * used in polkit_subject_from_string(). + * @exists: Asynchronously check if a #PolkitSubject exists. + * @exists_finish: Finishes checking if a #PolkitSubject exists. + * @exists_sync: Synchronously check if a #PolkitSubject exists. * * An interface for subjects. */ @@ -61,21 +64,44 @@ struct _PolkitSubjectIface { GTypeInterface parent_iface; - guint (*hash) (PolkitSubject *subject); + guint (*hash) (PolkitSubject *subject); - gboolean (*equal) (PolkitSubject *a, - PolkitSubject *b); + gboolean (*equal) (PolkitSubject *a, + PolkitSubject *b); - gchar * (*to_string) (PolkitSubject *subject); + gchar * (*to_string) (PolkitSubject *subject); + + void (*exists) (PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + + gboolean (*exists_finish) (PolkitSubject *subject, + GAsyncResult *res, + GError **error); + + gboolean (*exists_sync) (PolkitSubject *subject, + GCancellable *cancellable, + GError **error); }; -GType polkit_subject_get_type (void) G_GNUC_CONST; -guint polkit_subject_hash (PolkitSubject *subject); -gboolean polkit_subject_equal (PolkitSubject *a, - PolkitSubject *b); -gchar *polkit_subject_to_string (PolkitSubject *subject); -PolkitSubject *polkit_subject_from_string (const gchar *str, - GError **error); +GType polkit_subject_get_type (void) G_GNUC_CONST; +guint polkit_subject_hash (PolkitSubject *subject); +gboolean polkit_subject_equal (PolkitSubject *a, + PolkitSubject *b); +gchar *polkit_subject_to_string (PolkitSubject *subject); +PolkitSubject *polkit_subject_from_string (const gchar *str, + GError **error); +void polkit_subject_exists (PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +gboolean polkit_subject_exists_finish (PolkitSubject *subject, + GAsyncResult *res, + GError **error); +gboolean polkit_subject_exists_sync (PolkitSubject *subject, + GCancellable *cancellable, + GError **error); G_END_DECLS diff --git a/src/polkit/polkitsystembusname.c b/src/polkit/polkitsystembusname.c index 44b71e5..180b6b6 100644 --- a/src/polkit/polkitsystembusname.c +++ b/src/polkit/polkitsystembusname.c @@ -224,10 +224,158 @@ polkit_system_bus_name_to_string (PolkitSubject *subject) return g_strdup_printf ("system-bus-name:%s", system_bus_name->name); } + +static void +name_exists_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + EggDBusMessage *reply; + GError *error; + + error = NULL; + reply = egg_dbus_connection_send_message_with_reply_finish (EGG_DBUS_CONNECTION (source_object), + res, + &error); + if (reply != NULL) + { + gboolean has_owner; + if (egg_dbus_message_extract_boolean (reply, &has_owner, &error)) + { + g_simple_async_result_set_op_res_gboolean (simple, has_owner); + } + g_object_unref (reply); + } + + if (error != NULL) + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +polkit_system_bus_name_exists (PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + PolkitSystemBusName *name = POLKIT_SYSTEM_BUS_NAME (subject); + EggDBusMessage *message; + EggDBusConnection *connection; + GSimpleAsyncResult *simple; + + message = NULL; + connection = NULL; + + connection = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + message = egg_dbus_connection_new_message_for_method_call (connection, + NULL, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "NameHasOwner"); + egg_dbus_message_append_string (message, name->name, NULL); + + simple = g_simple_async_result_new (G_OBJECT (name), + callback, + user_data, + polkit_system_bus_name_exists); + + egg_dbus_connection_send_message_with_reply (connection, + EGG_DBUS_CALL_FLAGS_NONE, + message, + NULL, + cancellable, + name_exists_cb, + simple); + + g_object_unref (message); + g_object_unref (connection); +} + +static gboolean +polkit_system_bus_name_exists_sync (PolkitSubject *subject, + GCancellable *cancellable, + GError **error) +{ + PolkitSystemBusName *name = POLKIT_SYSTEM_BUS_NAME (subject); + EggDBusMessage *message; + EggDBusMessage *reply; + EggDBusConnection *connection; + gboolean ret; + + message = NULL; + reply = NULL; + connection = NULL; + ret = FALSE; + + connection = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + message = egg_dbus_connection_new_message_for_method_call (connection, + NULL, + "org.freedesktop.DBus", + "/org/freedesktop/DBus", + "org.freedesktop.DBus", + "NameHasOwner"); + egg_dbus_message_append_string (message, name->name, NULL); + + reply = egg_dbus_connection_send_message_with_reply_sync (connection, + EGG_DBUS_CALL_FLAGS_NONE, + message, + NULL, + cancellable, + error); + if (reply == NULL) + goto out; + + if (!egg_dbus_message_extract_boolean (reply, &ret, error)) + goto out; + + out: + if (message != NULL) + g_object_unref (message); + if (reply != NULL) + g_object_unref (reply); + if (connection != NULL) + g_object_unref (connection); + + return ret; +} + +static gboolean +polkit_system_bus_name_exists_finish (PolkitSubject *subject, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + gboolean ret; + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_system_bus_name_exists); + + ret = FALSE; + + if (g_simple_async_result_propagate_error (simple, error)) + goto out; + + ret = g_simple_async_result_get_op_res_gboolean (simple); + + out: + return ret; +} + static void subject_iface_init (PolkitSubjectIface *subject_iface) { - subject_iface->hash = polkit_system_bus_name_hash; - subject_iface->equal = polkit_system_bus_name_equal; - subject_iface->to_string = polkit_system_bus_name_to_string; + subject_iface->hash = polkit_system_bus_name_hash; + subject_iface->equal = polkit_system_bus_name_equal; + subject_iface->to_string = polkit_system_bus_name_to_string; + subject_iface->exists = polkit_system_bus_name_exists; + subject_iface->exists_finish = polkit_system_bus_name_exists_finish; + subject_iface->exists_sync = polkit_system_bus_name_exists_sync; } diff --git a/src/polkit/polkittemporaryauthorization.c b/src/polkit/polkittemporaryauthorization.c new file mode 100644 index 0000000..409a5ec --- /dev/null +++ b/src/polkit/polkittemporaryauthorization.c @@ -0,0 +1,211 @@ +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#ifdef HAVE_CONFIG_H +# include "config.h" +#endif + +#include <string.h> +#include "polkitimplicitauthorization.h" +#include "polkittemporaryauthorization.h" +#include "_polkittemporaryauthorization.h" + +#include "polkitprivate.h" + +/** + * SECTION:polkittemporaryauthorization + * @title: PolkitTemporaryAuthorization + * @short_description: Temporary Authorizations + * + * Object used to describe a temporary authorization. + */ + +/** + * PolkitTemporaryAuthorization: + * + * The #PolkitTemporaryAuthorization struct should not be accessed directly. + */ +struct _PolkitTemporaryAuthorization +{ + GObject parent_instance; + + _PolkitTemporaryAuthorization *real; + + gchar **annotation_keys; +}; + +struct _PolkitTemporaryAuthorizationClass +{ + GObjectClass parent_class; +}; + +G_DEFINE_TYPE (PolkitTemporaryAuthorization, polkit_temporary_authorization, G_TYPE_OBJECT); + +static void +polkit_temporary_authorization_init (PolkitTemporaryAuthorization *authorization) +{ +} + +static void +polkit_temporary_authorization_finalize (GObject *object) +{ + PolkitTemporaryAuthorization *authorization; + + authorization = POLKIT_TEMPORARY_AUTHORIZATION (object); + + g_object_unref (authorization->real); + + if (G_OBJECT_CLASS (polkit_temporary_authorization_parent_class)->finalize != NULL) + G_OBJECT_CLASS (polkit_temporary_authorization_parent_class)->finalize (object); +} + +static void +polkit_temporary_authorization_class_init (PolkitTemporaryAuthorizationClass *klass) +{ + GObjectClass *gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = polkit_temporary_authorization_finalize; +} + +/** + * polkit_temporary_authorization_new: + * @id: Id for temporary authorization + * @action_id: An action id. + * @subject: A #PolkitSubject. + * @time_obtained: Time obtained, since the Epoch Jan 1, 1970 0:00 UTC. + * @time_expires: Time the temporary authorization will expire, since the Epoch Jan 1, 1970 0:00 UTC. + * + * Creates a new temporary authorization. + * + * Returns: A #PolkitTemporaryAuthorization, free with g_object_unref() + **/ +PolkitTemporaryAuthorization * +polkit_temporary_authorization_new (const gchar *id, + const gchar *action_id, + PolkitSubject *subject, + guint64 time_obtained, + guint64 time_expires) +{ + PolkitTemporaryAuthorization *ret; + _PolkitTemporaryAuthorization *real; + _PolkitSubject *real_subject; + + real_subject = polkit_subject_get_real (subject); + real = _polkit_temporary_authorization_new (id, + action_id, + real_subject, + time_obtained, + time_expires); + g_object_unref (real_subject); + + ret = polkit_temporary_authorization_new_for_real (real); + g_object_unref (real); + + return ret; +} + + +PolkitTemporaryAuthorization * +polkit_temporary_authorization_new_for_real (_PolkitTemporaryAuthorization *real) +{ + PolkitTemporaryAuthorization *authorization; + + authorization = POLKIT_TEMPORARY_AUTHORIZATION (g_object_new (POLKIT_TYPE_TEMPORARY_AUTHORIZATION, NULL)); + authorization->real = g_object_ref (real); + + return authorization; +} + +_PolkitTemporaryAuthorization * +polkit_temporary_authorization_get_real (PolkitTemporaryAuthorization *authorization) +{ + return g_object_ref (authorization->real); +} + +/** + * polkit_temporary_authorization_get_id: + * @authorization: A #PolkitTemporaryAuthorization. + * + * Gets the opaque identifier for @authorization. + * + * Returns: A string owned by @authorization. Do not free. + */ +const gchar * +polkit_temporary_authorization_get_id (PolkitTemporaryAuthorization *authorization) +{ + return _polkit_temporary_authorization_get_id (authorization->real); +} + +/** + * polkit_temporary_authorization_get_action_id: + * @authorization: A #PolkitTemporaryAuthorization. + * + * Gets the action that @authorization is for. + * + * Returns: A string owned by @authorization. Do not free. + **/ +const gchar * +polkit_temporary_authorization_get_action_id (PolkitTemporaryAuthorization *authorization) +{ + return _polkit_temporary_authorization_get_action_id (authorization->real); +} + +/** + * polkit_temporary_authorization_get_subject: + * @authorization: A #PolkitTemporaryAuthorization. + * + * Gets the subject that @authorization is for. + * + * Returns: A #PolkitSubject, free with g_object_unref(). + **/ +PolkitSubject * +polkit_temporary_authorization_get_subject (PolkitTemporaryAuthorization *authorization) +{ + return polkit_subject_new_for_real (_polkit_temporary_authorization_get_subject (authorization->real)); +} + +/** + * polkit_temporary_authorization_get_time_obtained: + * @authorization: A #PolkitTemporaryAuthorization. + * + * Gets the time when @authorization was obtained. + * + * Returns: Seconds since the Epoch Jan 1. 1970, 0:00 UTC. + **/ +guint64 +polkit_temporary_authorization_get_time_obtained (PolkitTemporaryAuthorization *authorization) +{ + return _polkit_temporary_authorization_get_time_obtained (authorization->real); +} + +/** + * polkit_temporary_authorization_get_time_expires: + * @authorization: A #PolkitTemporaryAuthorization. + * + * Gets the time when @authorization will expire. + * + * Returns: Seconds since the Epoch Jan 1. 1970, 0:00 UTC. + **/ +guint64 +polkit_temporary_authorization_get_time_expires (PolkitTemporaryAuthorization *authorization) +{ + return _polkit_temporary_authorization_get_time_expires (authorization->real); +} diff --git a/src/polkit/polkittemporaryauthorization.h b/src/polkit/polkittemporaryauthorization.h new file mode 100644 index 0000000..4d0c530 --- /dev/null +++ b/src/polkit/polkittemporaryauthorization.h @@ -0,0 +1,61 @@ +/* + * Copyright (C) 2008 Red Hat, Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General + * Public License along with this library; if not, write to the + * Free Software Foundation, Inc., 59 Temple Place, Suite 330, + * Boston, MA 02111-1307, USA. + * + * Author: David Zeuthen <davidz@redhat.com> + */ + +#if !defined (_POLKIT_COMPILATION) && !defined(_POLKIT_INSIDE_POLKIT_H) +#error "Only <polkit/polkit.h> can be included directly, this file may disappear or change contents." +#endif + +#ifndef __POLKIT_TEMPORARY_AUTHORIZATION_H +#define __POLKIT_TEMPORARY_AUTHORIZATION_H + +#include <glib-object.h> +#include <gio/gio.h> +#include <polkit/polkittypes.h> + +G_BEGIN_DECLS + +#define POLKIT_TYPE_TEMPORARY_AUTHORIZATION (polkit_temporary_authorization_get_type()) +#define POLKIT_TEMPORARY_AUTHORIZATION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_TYPE_TEMPORARY_AUTHORIZATION, PolkitTemporaryAuthorization)) +#define POLKIT_TEMPORARY_AUTHORIZATION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_TYPE_TEMPORARY_AUTHORIZATION, PolkitTemporaryAuthorizationClass)) +#define POLKIT_TEMPORARY_AUTHORIZATION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_TYPE_TEMPORARY_AUTHORIZATION, PolkitTemporaryAuthorizationClass)) +#define POLKIT_IS_TEMPORARY_AUTHORIZATION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_TYPE_TEMPORARY_AUTHORIZATION)) +#define POLKIT_IS_TEMPORARY_AUTHORIZATION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_TYPE_TEMPORARY_AUTHORIZATION)) + +#if 0 +typedef struct _PolkitTemporaryAuthorization PolkitTemporaryAuthorization; +#endif +typedef struct _PolkitTemporaryAuthorizationClass PolkitTemporaryAuthorizationClass; + +GType polkit_temporary_authorization_get_type (void) G_GNUC_CONST; +PolkitTemporaryAuthorization *polkit_temporary_authorization_new (const gchar *id, + const gchar *action_id, + PolkitSubject *subject, + guint64 time_obtained, + guint64 time_expires); +const gchar *polkit_temporary_authorization_get_id (PolkitTemporaryAuthorization *authorization); +const gchar *polkit_temporary_authorization_get_action_id (PolkitTemporaryAuthorization *authorization); +PolkitSubject *polkit_temporary_authorization_get_subject (PolkitTemporaryAuthorization *authorization); +guint64 polkit_temporary_authorization_get_time_obtained (PolkitTemporaryAuthorization *authorization); +guint64 polkit_temporary_authorization_get_time_expires (PolkitTemporaryAuthorization *authorization); + +G_END_DECLS + +#endif /* __POLKIT_TEMPORARY_AUTHORIZATION_H */ diff --git a/src/polkit/polkittypes.h b/src/polkit/polkittypes.h index fcc98fa..0da7faf 100644 --- a/src/polkit/polkittypes.h +++ b/src/polkit/polkittypes.h @@ -55,4 +55,7 @@ typedef struct _PolkitAuthorizationResult PolkitAuthorizationResult; struct _PolkitDetails; typedef struct _PolkitDetails PolkitDetails; +struct _PolkitTemporaryAuthorization; +typedef struct _PolkitTemporaryAuthorization PolkitTemporaryAuthorization; + #endif /* __POLKIT_TYPES_H */ diff --git a/src/polkit/polkitunixprocess.c b/src/polkit/polkitunixprocess.c index 181f221..0a410be 100644 --- a/src/polkit/polkitunixprocess.c +++ b/src/polkit/polkitunixprocess.c @@ -28,6 +28,7 @@ #include "polkitunixprocess.h" #include "polkitsubject.h" #include "polkitprivate.h" +#include "polkiterror.h" /** * SECTION:polkitunixprocess @@ -68,7 +69,8 @@ enum static void subject_iface_init (PolkitSubjectIface *subject_iface); -static guint64 get_start_time_for_pid (pid_t pid); +static guint64 get_start_time_for_pid (pid_t pid, + GError **error); G_DEFINE_TYPE_WITH_CODE (PolkitUnixProcess, polkit_unix_process, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (POLKIT_TYPE_SUBJECT, subject_iface_init) @@ -211,7 +213,7 @@ polkit_unix_process_set_pid (PolkitUnixProcess *process, { process->pid = pid; if (pid != (pid_t) -1) - process->start_time = get_start_time_for_pid (pid); + process->start_time = get_start_time_for_pid (pid, NULL); } /** @@ -286,12 +288,81 @@ polkit_unix_process_to_string (PolkitSubject *subject) return g_strdup_printf ("unix-process:%d:%" G_GUINT64_FORMAT, process->pid, process->start_time); } +static gboolean +polkit_unix_process_exists_sync (PolkitSubject *subject, + GCancellable *cancellable, + GError **error) +{ + PolkitUnixProcess *process = POLKIT_UNIX_PROCESS (subject); + GError *local_error; + guint64 start_time; + gboolean ret; + + ret = TRUE; + + local_error = NULL; + start_time = get_start_time_for_pid (process->pid, &local_error); + if (local_error != NULL) + { + g_propagate_error (error, local_error); + g_error_free (local_error); + ret = FALSE; + } + else + { + if (start_time != process->start_time) + { + ret = FALSE; + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Start times for pid %d do not match", + (gint) process->pid); + } + } + + return ret; +} + +static void +polkit_unix_process_exists (PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + GSimpleAsyncResult *simple; + simple = g_simple_async_result_new (G_OBJECT (subject), + callback, + user_data, + polkit_unix_process_exists); + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static gboolean +polkit_unix_process_exists_finish (PolkitSubject *subject, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_unix_process_exists); + + return polkit_unix_process_exists_sync (subject, + NULL, + error); +} + + static void subject_iface_init (PolkitSubjectIface *subject_iface) { - subject_iface->hash = polkit_unix_process_hash; - subject_iface->equal = polkit_unix_process_equal; - subject_iface->to_string = polkit_unix_process_to_string; + subject_iface->hash = polkit_unix_process_hash; + subject_iface->equal = polkit_unix_process_equal; + subject_iface->to_string = polkit_unix_process_to_string; + subject_iface->exists = polkit_unix_process_exists; + subject_iface->exists_finish = polkit_unix_process_exists_finish; + subject_iface->exists_sync = polkit_unix_process_exists_sync; } #ifdef HAVE_SOLARIS @@ -317,126 +388,78 @@ get_pid_psinfo (pid_t pid, struct psinfo *ps) #endif static guint64 -get_start_time_for_pid (pid_t pid) +get_start_time_for_pid (pid_t pid, + GError **error) { gchar *filename; gchar *contents; size_t length; guint64 start_time; - GError *error; -#ifdef HAVE_SOLARIS - struct psinfo info; -#else gchar **tokens; guint num_tokens; gchar *p; gchar *endp; -#endif start_time = 0; contents = NULL; -#ifdef HAVE_SOLARIS - if (polkit_sysdeps_pid_psinfo (pid, &info)) - { - goto out; - } - start_time = (unsigned long long) (info.pr_start.tv_sec); -#else -#ifdef __FreeBSD__ - filename = g_strdup_printf ("/proc/%d/status", pid); -#else filename = g_strdup_printf ("/proc/%d/stat", pid); -#endif - error = NULL; - if (!g_file_get_contents (filename, &contents, &length, &error)) - { - g_warning ("Cannot get contents of '%s': %s\n", filename, error->message); - goto out; - } - -#ifdef __FreeBSD__ - tokens = kit_strsplit (contents, " ", &num_tokens); - if (tokens == NULL) + if (!g_file_get_contents (filename, &contents, &length, error)) goto out; - if (num_tokens < 8) - { - g_strfreev (tokens); - goto out; - } - - p = g_strdup (tokens[7]); - g_strfreev (tokens); - - tokens = g_strsplit (p, ",", 0); - g_free (p); - - if (tokens == NULL) - goto out; - - num_tokens = g_strv_length (tokens); - - if (num_tokens >= 1) - { - start_time = strtoll (tokens[0], &endp, 10); - if (endp == tokens[0]) - { - g_strfreev (tokens); - goto out; - } - } - else - { - g_strfreev (tokens); - goto out; - } - - g_strfreev (tokens); - -#else - - /* start time is the 19th token after the '(process name)' entry */ + /* start time is the 19th token after the '(process name)' entry */ p = strchr (contents, ')'); if (p == NULL) { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Error parsing file %s", + filename); goto out; } p += 2; /* skip ') ' */ if (p - contents >= (int) length) { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Error parsing file %s", + filename); goto out; } tokens = g_strsplit (p, " ", 0); - if (tokens == NULL) - goto out; - num_tokens = g_strv_length (tokens); if (num_tokens < 20) - goto out; + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Error parsing file %s", + filename); + goto out; + } start_time = strtoll (tokens[19], &endp, 10); if (endp == tokens[19]) - goto out; + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Error parsing file %s", + filename); + goto out; + } g_strfreev (tokens); -#endif -#endif out: -#ifndef HAVE_SOLARIS g_free (filename); g_free (contents); -#endif - - if (start_time == 0) - { - g_warning ("Cannot lookup start-time for pid %d", pid); - } return start_time; } diff --git a/src/polkit/polkitunixsession.c b/src/polkit/polkitunixsession.c index 968be2d..fc6a18b 100644 --- a/src/polkit/polkitunixsession.c +++ b/src/polkit/polkitunixsession.c @@ -26,6 +26,7 @@ #include <string.h> #include "polkitunixsession.h" #include "polkitsubject.h" +#include "polkiterror.h" #include "polkitprivate.h" /** @@ -48,6 +49,8 @@ struct _PolkitUnixSession GObject parent_instance; gchar *session_id; + + pid_t pid; }; struct _PolkitUnixSessionClass @@ -59,16 +62,21 @@ enum { PROP_0, PROP_SESSION_ID, + PROP_PID, }; -static void subject_iface_init (PolkitSubjectIface *subject_iface); +static void subject_iface_init (PolkitSubjectIface *subject_iface); +static void initable_iface_init (GInitableIface *initable_iface); +static void async_initable_iface_init (GAsyncInitableIface *async_initable_iface); G_DEFINE_TYPE_WITH_CODE (PolkitUnixSession, polkit_unix_session, G_TYPE_OBJECT, G_IMPLEMENT_INTERFACE (POLKIT_TYPE_SUBJECT, subject_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_INITABLE, initable_iface_init) + G_IMPLEMENT_INTERFACE (G_TYPE_ASYNC_INITABLE, async_initable_iface_init) ); static void -polkit_unix_session_init (PolkitUnixSession *unix_session) +polkit_unix_session_init (PolkitUnixSession *session) { } @@ -117,6 +125,10 @@ polkit_unix_session_set_property (GObject *object, polkit_unix_session_set_session_id (session, g_value_get_string (value)); break; + case PROP_PID: + session->pid = g_value_get_uint (value); + break; + default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); break; @@ -149,6 +161,26 @@ polkit_unix_session_class_init (PolkitUnixSessionClass *klass) G_PARAM_STATIC_BLURB | G_PARAM_STATIC_NICK)); + + /** + * PolkitUnixSession:pid: + * + * The UNIX process id to look up the session. + */ + g_object_class_install_property (gobject_class, + PROP_PID, + g_param_spec_uint ("pid", + "Process ID", + "Process ID to use for looking up the session", + 0, + G_MAXUINT, + 0, + G_PARAM_CONSTRUCT_ONLY | + G_PARAM_WRITABLE | + G_PARAM_STATIC_NAME | + G_PARAM_STATIC_BLURB | + G_PARAM_STATIC_NICK)); + } /** @@ -197,6 +229,95 @@ polkit_unix_session_new (const gchar *session_id) NULL)); } +/** + * polkit_unix_session_new_for_process: + * @pid: The process id of the process to get the session for. + * @cancellable: A #GCancellable or %NULL. + * @callback: A #GAsyncReadyCallback to call when the request is satisfied + * @user_data: The data to pass to @callback. + * + * Asynchronously creates a new #PolkitUnixSession object for the + * process with process id @pid. + * + * When the operation is finished, @callback will be invoked. You can + * then call polkit_unix_session_new_for_process_finish() to get the + * result of the operation. + * + * This method constructs the object asynchronously, for the synchronous and blocking version + * use polkit_unix_session_new_for_process_sync(). + **/ +void +polkit_unix_session_new_for_process (pid_t pid, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + g_async_initable_new_async (POLKIT_TYPE_UNIX_SESSION, + G_PRIORITY_DEFAULT, + cancellable, + callback, + user_data, + "pid", pid, + NULL); +} + +/** + * polkit_unix_session_new_for_process_finish: + * @res: A #GAsyncResult obtained from the #GAsyncReadyCallback passed to polkit_unix_session_new_for_process(). + * @error: Return location for error. + * + * Finishes constructing a #PolkitSubject for a process id. + * + * Returns: A #PolkitUnixSession for the @pid passed to polkit_unix_session_new_for_process() or %NULL + * if @error is set. Free with g_object_unref(). + **/ +PolkitSubject * +polkit_unix_session_new_for_process_finish (GAsyncResult *res, + GError **error) +{ + GObject *object; + GObject *source_object; + + source_object = g_async_result_get_source_object (res); + g_assert (source_object != NULL); + + object = g_async_initable_new_finish (G_ASYNC_INITABLE (source_object), + res, + error); + g_object_unref (source_object); + + if (object != NULL) + return POLKIT_SUBJECT (object); + else + return NULL; +} + + +/** + * polkit_unix_session_new_for_process_sync: + * @pid: The process id of the process to get the session for. + * @cancellable: A #GCancellable or %NULL. + * @error: Return location for error. + * + * Creates a new #PolkitUnixSession for the process with process id @pid. + * + * This is a synchronous call that does blocking IO, for the asynchronous version, use + * polkit_unix_session_new_for_process(). + * + * Returns: A #PolkitUnixSession for @pid or %NULL if @error is set. Free with g_object_unref(). + **/ +PolkitSubject * +polkit_unix_session_new_for_process_sync (pid_t pid, + GCancellable *cancellable, + GError **error) +{ + return POLKIT_SUBJECT (g_initable_new (POLKIT_TYPE_UNIX_SESSION, + cancellable, + error, + "pid", pid, + NULL)); +} + static guint polkit_unix_session_hash (PolkitSubject *subject) { @@ -227,9 +348,310 @@ polkit_unix_session_to_string (PolkitSubject *subject) } static void +session_exists_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + EggDBusMessage *reply; + GError *error; + + error = NULL; + reply = egg_dbus_connection_send_message_with_reply_finish (EGG_DBUS_CONNECTION (source_object), + res, + &error); + if (error != NULL) + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + if (reply != NULL) + g_object_unref (reply); + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +polkit_unix_session_exists (PolkitSubject *subject, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); + EggDBusMessage *message; + EggDBusConnection *connection; + GSimpleAsyncResult *simple; + + message = NULL; + connection = NULL; + + connection = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + message = egg_dbus_connection_new_message_for_method_call (connection, + NULL, + "org.freedesktop.ConsoleKit", + session->session_id, + "org.freedesktop.ConsoleKit.Session", + "GetUser"); + + simple = g_simple_async_result_new (G_OBJECT (session), + callback, + user_data, + polkit_unix_session_exists); + + egg_dbus_connection_send_message_with_reply (connection, + EGG_DBUS_CALL_FLAGS_NONE, + message, + NULL, + cancellable, + session_exists_cb, + simple); + + g_object_unref (message); + g_object_unref (connection); +} + +static gboolean +polkit_unix_session_exists_sync (PolkitSubject *subject, + GCancellable *cancellable, + GError **error) +{ + PolkitUnixSession *session = POLKIT_UNIX_SESSION (subject); + EggDBusMessage *message; + EggDBusMessage *reply; + EggDBusConnection *connection; + gboolean ret; + + message = NULL; + reply = NULL; + connection = NULL; + ret = FALSE; + + connection = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + message = egg_dbus_connection_new_message_for_method_call (connection, + NULL, + "org.freedesktop.ConsoleKit", + session->session_id, + "org.freedesktop.ConsoleKit.Session", + "GetUser"); + + reply = egg_dbus_connection_send_message_with_reply_sync (connection, + EGG_DBUS_CALL_FLAGS_NONE, + message, + NULL, + cancellable, + error); + if (reply == NULL) + goto out; + + ret = TRUE; + + out: + if (message != NULL) + g_object_unref (message); + if (reply != NULL) + g_object_unref (reply); + if (connection != NULL) + g_object_unref (connection); + + return ret; +} + +static gboolean +polkit_unix_session_exists_finish (PolkitSubject *subject, + GAsyncResult *res, + GError **error) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + gboolean ret; + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_unix_session_exists); + + ret = FALSE; + + if (g_simple_async_result_propagate_error (simple, error)) + goto out; + + ret = TRUE; + + out: + return ret; +} + +static void subject_iface_init (PolkitSubjectIface *subject_iface) { - subject_iface->hash = polkit_unix_session_hash; - subject_iface->equal = polkit_unix_session_equal; - subject_iface->to_string = polkit_unix_session_to_string; + subject_iface->hash = polkit_unix_session_hash; + subject_iface->equal = polkit_unix_session_equal; + subject_iface->to_string = polkit_unix_session_to_string; + subject_iface->exists = polkit_unix_session_exists; + subject_iface->exists_finish = polkit_unix_session_exists_finish; + subject_iface->exists_sync = polkit_unix_session_exists_sync; +} + +static gboolean +polkit_unix_session_initable_init (GInitable *initable, + GCancellable *cancellable, + GError **error) +{ + PolkitUnixSession *session = POLKIT_UNIX_SESSION (initable); + EggDBusMessage *message; + EggDBusMessage *reply; + EggDBusConnection *connection; + gboolean ret; + + message = NULL; + reply = NULL; + connection = NULL; + ret = FALSE; + + connection = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + message = egg_dbus_connection_new_message_for_method_call (connection, + NULL, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + "GetSessionForUnixProcess"); + egg_dbus_message_append_uint (message, session->pid, NULL); + + reply = egg_dbus_connection_send_message_with_reply_sync (connection, + EGG_DBUS_CALL_FLAGS_NONE, + message, + NULL, + cancellable, + error); + if (reply == NULL) + goto out; + + if (!egg_dbus_message_extract_object_path (reply, &session->session_id, error)) + goto out; + + ret = TRUE; + + out: + if (message != NULL) + g_object_unref (message); + if (reply != NULL) + g_object_unref (reply); + if (connection != NULL) + g_object_unref (connection); + + return ret; +} + +static void +initable_iface_init (GInitableIface *initable_iface) +{ + initable_iface->init = polkit_unix_session_initable_init; +} + +static void +async_init_cb (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (user_data); + EggDBusMessage *reply; + GError *error; + + error = NULL; + reply = egg_dbus_connection_send_message_with_reply_finish (EGG_DBUS_CONNECTION (source_object), + res, + &error); + + if (reply != NULL) + { + gchar *session_id; + if (egg_dbus_message_extract_object_path (reply, &session_id, &error)) + { + g_simple_async_result_set_op_res_gpointer (simple, + session_id, + g_free); + } + g_object_unref (reply); + } + + if (error != NULL) + { + g_simple_async_result_set_from_error (simple, error); + g_error_free (error); + } + + g_simple_async_result_complete (simple); + g_object_unref (simple); +} + +static void +polkit_unix_session_async_initable_init_async (GAsyncInitable *async_initable, + gint io_priority, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + PolkitUnixSession *session = POLKIT_UNIX_SESSION (async_initable); + EggDBusMessage *message; + EggDBusConnection *connection; + GSimpleAsyncResult *simple; + + message = NULL; + connection = NULL; + + connection = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + message = egg_dbus_connection_new_message_for_method_call (connection, + NULL, + "org.freedesktop.ConsoleKit", + "/org/freedesktop/ConsoleKit/Manager", + "org.freedesktop.ConsoleKit.Manager", + "GetSessionForUnixProcess"); + egg_dbus_message_append_uint (message, session->pid, NULL); + + simple = g_simple_async_result_new (G_OBJECT (session), + callback, + user_data, + polkit_unix_session_async_initable_init_async); + + egg_dbus_connection_send_message_with_reply (connection, + EGG_DBUS_CALL_FLAGS_NONE, + message, + NULL, + cancellable, + async_init_cb, + simple); + + g_object_unref (message); + g_object_unref (connection); +} + +static gboolean +polkit_unix_session_async_initable_init_finish (GAsyncInitable *async_initable, + GAsyncResult *res, + GError **error) +{ + PolkitUnixSession *session = POLKIT_UNIX_SESSION (async_initable); + GSimpleAsyncResult *simple = G_SIMPLE_ASYNC_RESULT (res); + gboolean ret; + + ret = FALSE; + + g_warn_if_fail (g_simple_async_result_get_source_tag (simple) == polkit_unix_session_async_initable_init_async); + + if (g_simple_async_result_propagate_error (simple, error)) + goto out; + + session->session_id = g_strdup (g_simple_async_result_get_op_res_gpointer (simple)); + ret = TRUE; + + out: + return ret; +} + +static void +async_initable_iface_init (GAsyncInitableIface *async_initable_iface) +{ + async_initable_iface->init_async = polkit_unix_session_async_initable_init_async; + async_initable_iface->init_finish = polkit_unix_session_async_initable_init_finish; } diff --git a/src/polkit/polkitunixsession.h b/src/polkit/polkitunixsession.h index 949811d..e858094 100644 --- a/src/polkit/polkitunixsession.h +++ b/src/polkit/polkitunixsession.h @@ -44,11 +44,20 @@ typedef struct _PolkitUnixSession PolkitUnixSession; #endif typedef struct _PolkitUnixSessionClass PolkitUnixSessionClass; -GType polkit_unix_session_get_type (void) G_GNUC_CONST; -PolkitSubject *polkit_unix_session_new (const gchar *session_id); -const gchar *polkit_unix_session_get_session_id (PolkitUnixSession *session); -void polkit_unix_session_set_session_id (PolkitUnixSession *session, - const gchar *session_id); +GType polkit_unix_session_get_type (void) G_GNUC_CONST; +PolkitSubject *polkit_unix_session_new (const gchar *session_id); +void polkit_unix_session_new_for_process (pid_t pid, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); +PolkitSubject *polkit_unix_session_new_for_process_finish (GAsyncResult *res, + GError **error); +PolkitSubject *polkit_unix_session_new_for_process_sync (pid_t pid, + GCancellable *cancellable, + GError **error); +const gchar *polkit_unix_session_get_session_id (PolkitUnixSession *session); +void polkit_unix_session_set_session_id (PolkitUnixSession *session, + const gchar *session_id); G_END_DECLS diff --git a/src/polkitagent/polkitagentlistener.c b/src/polkitagent/polkitagentlistener.c index 0251ed4..c2ab69a 100644 --- a/src/polkitagent/polkitagentlistener.c +++ b/src/polkitagent/polkitagentlistener.c @@ -70,7 +70,7 @@ struct _Server PolkitAgentListener *listener; - gchar *session_id; + PolkitSubject *subject; gchar *object_path; GHashTable *cookie_to_pending_auth; @@ -103,7 +103,7 @@ server_register (Server *server, local_error = NULL; if (!polkit_authority_register_authentication_agent_sync (server->authority, - server->session_id, + server->subject, g_getenv ("LANG"), server->object_path, NULL, @@ -199,7 +199,7 @@ server_finalize (GObject *object) error = NULL; if (!polkit_authority_unregister_authentication_agent_sync (server->authority, - server->session_id, + server->subject, server->object_path, NULL, &error)) @@ -209,7 +209,7 @@ server_finalize (GObject *object) } } - g_free (server->session_id); + g_object_unref (server->subject); g_free (server->object_path); g_object_unref (server->authority); @@ -244,15 +244,15 @@ listener_died (gpointer user_data, /** * polkit_agent_register_listener: * @listener: An instance of a class that is derived from #PolkitAgentListener. - * @session_id: The session id to become an authentication agent for or %NULL for the current session. + * @subject: The subject to become an authentication agent for, typically a #PolkitUnixSession object. * @object_path: The D-Bus object path to use for the authentication agent or %NULL for the default object path. * @error: Return location for error. * - * Registers @listener with the PolicyKit daemon as an authentication agent for @session_id. This + * Registers @listener with the PolicyKit daemon as an authentication agent for @subject. This * is implemented by registering a D-Bus object at @object_path on the unique name assigned by the * system message bus. * - * Whenever the PolicyKit daemon needs to authenticate the user of @session_id for an action, the methods + * Whenever the PolicyKit daemon needs to authenticate a processes that is related @subject, the methods * polkit_agent_listener_initiate_authentication() and polkit_agent_listener_initiate_authentication_finish() * will be invoked on @listener. * @@ -265,14 +265,14 @@ listener_died (gpointer user_data, **/ gboolean polkit_agent_register_listener (PolkitAgentListener *listener, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GError **error) { Server *server; server = SERVER (g_object_new (TYPE_SERVER, NULL)); - server->session_id = g_strdup (session_id); + server->subject = g_object_ref (subject); server->object_path = object_path != NULL ? g_strdup (object_path) : g_strdup ("/org/freedesktop/PolicyKit1/AuthenticationAgent"); server->listener = listener; diff --git a/src/polkitagent/polkitagentlistener.h b/src/polkitagent/polkitagentlistener.h index 0f0b295..a20feb8 100644 --- a/src/polkitagent/polkitagentlistener.h +++ b/src/polkitagent/polkitagentlistener.h @@ -93,6 +93,7 @@ struct _PolkitAgentListenerClass }; GType polkit_agent_listener_get_type (void) G_GNUC_CONST; + void polkit_agent_listener_initiate_authentication (PolkitAgentListener *listener, const gchar *action_id, const gchar *message, @@ -103,14 +104,15 @@ void polkit_agent_listener_initiate_authentication (PolkitAgentList GCancellable *cancellable, GAsyncReadyCallback callback, gpointer user_data); + gboolean polkit_agent_listener_initiate_authentication_finish (PolkitAgentListener *listener, GAsyncResult *res, GError **error); -gboolean polkit_agent_register_listener (PolkitAgentListener *listener, - const gchar *session_id, - const gchar *object_path, - GError **error); +gboolean polkit_agent_register_listener (PolkitAgentListener *listener, + PolkitSubject *subject, + const gchar *object_path, + GError **error); G_END_DECLS diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c index 93911ca..eec0664 100644 --- a/src/polkitbackend/polkitbackendauthority.c +++ b/src/polkitbackend/polkitbackendauthority.c @@ -224,7 +224,7 @@ polkit_backend_authority_check_authorization_finish (PolkitBackendAuthority *au * polkit_backend_authority_register_authentication_agent: * @authority: A #PolkitBackendAuthority. * @caller: The system bus name that initiated the query. - * @session_id: The identifier of the session to register for or %NULL for the session of the caller. + * @subject: The subject the authentication agent wants to register for. * @locale: The locale of the authentication agent. * @object_path: The object path for the authentication agent. * @error: Return location for error or %NULL. @@ -236,7 +236,7 @@ polkit_backend_authority_check_authorization_finish (PolkitBackendAuthority *au gboolean polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GError **error) @@ -255,7 +255,7 @@ polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority } else { - return klass->register_authentication_agent (authority, caller, session_id, locale, object_path, error); + return klass->register_authentication_agent (authority, caller, subject, locale, object_path, error); } } @@ -263,7 +263,7 @@ polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority * polkit_backend_authority_unregister_authentication_agent: * @authority: A #PolkitBackendAuthority. * @caller: The system bus name that initiated the query. - * @session_id: The identifier of the session the agent is registered at or %NULL for the session of the caller. + * @subject: The subject the agent claims to be registered at. * @object_path: The object path that the authentication agent is registered at. * @error: Return location for error or %NULL. * @@ -274,7 +274,7 @@ polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority gboolean polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GError **error) { @@ -292,7 +292,7 @@ polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority } else { - return klass->unregister_authentication_agent (authority, caller, session_id, object_path, error); + return klass->unregister_authentication_agent (authority, caller, subject, object_path, error); } } @@ -336,6 +336,80 @@ polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority /* ---------------------------------------------------------------------------------------------------- */ +/** + * polkit_backend_authority_enumerate_temporary_authorizations: + * @authority: A #PolkitBackendAuthority. + * @caller: The system bus name that initiated the query. + * @subject: The subject to get temporary authorizations for. + * @error: Return location for error. + * + * Gets temporary authorizations for @subject. + * + * Returns: A list of #PolkitTemporaryAuthorization objects or %NULL if @error is set. The returned list + * should be freed with g_list_free() after each element have been freed with g_object_unref(). + */ +GList * +polkit_backend_authority_enumerate_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error) +{ + PolkitBackendAuthorityClass *klass; + + klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority); + + if (klass->enumerate_temporary_authorizations == NULL) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_NOT_SUPPORTED, + "Operation not supported"); + return NULL; + } + else + { + return klass->enumerate_temporary_authorizations (authority, caller, subject, error); + } +} + +/** + * polkit_backend_authority_revoke_temporary_authorizations: + * @authority: A #PolkitBackendAuthority. + * @caller: The system bus name that initiated the query. + * @subject: The subject to revoke temporary authorizations for. + * @error: Return location for error. + * + * Revokes temporary authorizations for @subject. + * + * Returns: %TRUE if the operatoin succeeded, %FALSE if @error is set. + **/ +gboolean +polkit_backend_authority_revoke_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error) +{ + PolkitBackendAuthorityClass *klass; + + klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority); + + if (klass->revoke_temporary_authorizations == NULL) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_NOT_SUPPORTED, + "Operation not supported"); + return FALSE; + } + else + { + return klass->revoke_temporary_authorizations (authority, caller, subject, error); + } +} + + +/* ---------------------------------------------------------------------------------------------------- */ + #define TYPE_SERVER (server_get_type ()) #define SERVER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), TYPE_SERVER, Server)) #define SERVER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), TYPE_SERVER, ServerClass)) @@ -639,21 +713,24 @@ authority_handle_cancel_check_authorization (_PolkitAuthority *ins static void authority_handle_register_authentication_agent (_PolkitAuthority *instance, - const gchar *session_id, + _PolkitSubject *real_subject, const gchar *locale, const gchar *object_path, EggDBusMethodInvocation *method_invocation) { Server *server = SERVER (instance); PolkitSubject *caller; + PolkitSubject *subject; GError *error; caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation)); + subject = polkit_subject_new_for_real (real_subject); + g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref); error = NULL; if (!polkit_backend_authority_register_authentication_agent (server->authority, caller, - session_id, + subject, locale, object_path, &error)) @@ -673,20 +750,23 @@ authority_handle_register_authentication_agent (_PolkitAuthority * static void authority_handle_unregister_authentication_agent (_PolkitAuthority *instance, - const gchar *session_id, + _PolkitSubject *real_subject, const gchar *object_path, EggDBusMethodInvocation *method_invocation) { Server *server = SERVER (instance); PolkitSubject *caller; + PolkitSubject *subject; GError *error; caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation)); + subject = polkit_subject_new_for_real (real_subject); + g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref); error = NULL; if (!polkit_backend_authority_unregister_authentication_agent (server->authority, caller, - session_id, + subject, object_path, &error)) { @@ -741,14 +821,112 @@ authority_handle_authentication_agent_response (_PolkitAuthority * /* ---------------------------------------------------------------------------------------------------- */ static void +authority_handle_enumerate_temporary_authorizations (_PolkitAuthority *instance, + _PolkitSubject *real_subject, + EggDBusMethodInvocation *method_invocation) +{ + Server *server = SERVER (instance); + PolkitSubject *caller; + EggDBusArraySeq *array; + GError *error; + GList *temporary_authorizations; + GList *l; + PolkitSubject *subject; + + error = NULL; + caller = NULL; + temporary_authorizations = NULL; + + caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation)); + + subject = polkit_subject_new_for_real (real_subject); + g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref); + + temporary_authorizations = polkit_backend_authority_enumerate_temporary_authorizations (server->authority, + caller, + subject, + &error); + if (error != NULL) + { + egg_dbus_method_invocation_return_gerror (method_invocation, error); + g_error_free (error); + goto out; + } + + array = egg_dbus_array_seq_new (G_TYPE_OBJECT, //_POLKIT_TYPE_TEMPORARY_AUTHORIZATION, + (GDestroyNotify) g_object_unref, + NULL, + NULL); + + for (l = temporary_authorizations; l != NULL; l = l->next) + { + PolkitTemporaryAuthorization *ta = POLKIT_TEMPORARY_AUTHORIZATION (l->data); + _PolkitTemporaryAuthorization *real; + + real = polkit_temporary_authorization_get_real (ta); + egg_dbus_array_seq_add (array, real); + } + + _polkit_authority_handle_enumerate_temporary_authorizations_finish (method_invocation, array); + + g_object_unref (array); + + out: + g_list_foreach (temporary_authorizations, (GFunc) g_object_unref, NULL); + g_list_free (temporary_authorizations); + g_object_unref (caller); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void +authority_handle_revoke_temporary_authorizations (_PolkitAuthority *instance, + _PolkitSubject *real_subject, + EggDBusMethodInvocation *method_invocation) +{ + Server *server = SERVER (instance); + PolkitSubject *caller; + GError *error; + PolkitSubject *subject; + + error = NULL; + caller = NULL; + + caller = polkit_system_bus_name_new (egg_dbus_method_invocation_get_caller (method_invocation)); + + subject = polkit_subject_new_for_real (real_subject); + g_object_set_data_full (G_OBJECT (method_invocation), "subject", subject, (GDestroyNotify) g_object_unref); + + polkit_backend_authority_revoke_temporary_authorizations (server->authority, + caller, + subject, + &error); + if (error != NULL) + { + egg_dbus_method_invocation_return_gerror (method_invocation, error); + g_error_free (error); + goto out; + } + + _polkit_authority_handle_revoke_temporary_authorizations_finish (method_invocation); + + out: + g_object_unref (caller); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void authority_iface_init (_PolkitAuthorityIface *authority_iface) { - authority_iface->handle_enumerate_actions = authority_handle_enumerate_actions; - authority_iface->handle_check_authorization = authority_handle_check_authorization; - authority_iface->handle_cancel_check_authorization = authority_handle_cancel_check_authorization; - authority_iface->handle_register_authentication_agent = authority_handle_register_authentication_agent; - authority_iface->handle_unregister_authentication_agent = authority_handle_unregister_authentication_agent; - authority_iface->handle_authentication_agent_response = authority_handle_authentication_agent_response; + authority_iface->handle_enumerate_actions = authority_handle_enumerate_actions; + authority_iface->handle_check_authorization = authority_handle_check_authorization; + authority_iface->handle_cancel_check_authorization = authority_handle_cancel_check_authorization; + authority_iface->handle_register_authentication_agent = authority_handle_register_authentication_agent; + authority_iface->handle_unregister_authentication_agent = authority_handle_unregister_authentication_agent; + authority_iface->handle_authentication_agent_response = authority_handle_authentication_agent_response; + authority_iface->handle_enumerate_temporary_authorizations = authority_handle_enumerate_temporary_authorizations; + authority_iface->handle_revoke_temporary_authorizations = authority_handle_revoke_temporary_authorizations; } static void diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h index 679ae4c..ca784ef 100644 --- a/src/polkitbackend/polkitbackendauthority.h +++ b/src/polkitbackend/polkitbackendauthority.h @@ -86,6 +86,14 @@ struct _PolkitBackendAuthority * doesn't support the operation. See * polkit_backend_authority_authentication_agent_response() for * details. + * @enumerate_temporary_authorizations: Called to enumerate temporary + * authorizations or %NULL if the backend doesn't support the operation. + * See polkit_backend_authority_enumerate_temporary_authorizations() + * for details. + * @revoke_temporary_authorizations: Called to revoke temporary + * authorizations or %NULL if the backend doesn't support the operation. + * See polkit_backend_authority_revoke_temporary_authorizations() + * for details. * @system_bus_name_owner_changed: temporary VFunc, to be removed before 1.0. * * VFuncs that authority backends need to implement. @@ -121,14 +129,14 @@ struct _PolkitBackendAuthorityClass gboolean (*register_authentication_agent) (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GError **error); gboolean (*unregister_authentication_agent) (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GError **error); @@ -138,6 +146,16 @@ struct _PolkitBackendAuthorityClass PolkitIdentity *identity, GError **error); + GList *(*enumerate_temporary_authorizations) (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error); + + gboolean (*revoke_temporary_authorizations) (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error); + /* TODO: need something more efficient such that we don't watch all name changes */ void (*system_bus_name_owner_changed) (PolkitBackendAuthority *authority, const gchar *name, @@ -210,14 +228,14 @@ PolkitAuthorizationResult *polkit_backend_authority_check_authorization_finish ( gboolean polkit_backend_authority_register_authentication_agent (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *session_id, + PolkitSubject *subject, const gchar *locale, const gchar *object_path, GError **error); gboolean polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority *authority, PolkitSubject *caller, - const gchar *session_id, + PolkitSubject *subject, const gchar *object_path, GError **error); @@ -227,6 +245,16 @@ gboolean polkit_backend_authority_authentication_agent_response (PolkitBackendAu PolkitIdentity *identity, GError **error); +GList *polkit_backend_authority_enumerate_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error); + +gboolean polkit_backend_authority_revoke_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error); + /* --- */ PolkitBackendAuthority *polkit_backend_authority_get (void); diff --git a/src/polkitbackend/polkitbackendinteractiveauthority.c b/src/polkitbackend/polkitbackendinteractiveauthority.c index 5cecc85..1677404 100644 --- a/src/polkitbackend/polkitbackendinteractiveauthority.c +++ b/src/polkitbackend/polkitbackendinteractiveauthority.c @@ -50,7 +50,7 @@ typedef struct TemporaryAuthorizationStore TemporaryAuthorizationStore; -static TemporaryAuthorizationStore *temporary_authorization_store_new (void); +static TemporaryAuthorizationStore *temporary_authorization_store_new (PolkitBackendInteractiveAuthority *authority); static void temporary_authorization_store_free (TemporaryAuthorizationStore *store); static gboolean temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *store, @@ -59,6 +59,7 @@ static gboolean temporary_authorization_store_has_authorization (TemporaryAuthor static void temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store, PolkitSubject *subject, + PolkitSubject *session, const gchar *action_id); /* ---------------------------------------------------------------------------------------------------- */ @@ -92,9 +93,12 @@ static void authentication_agent_initiate_challenge (Authenticati AuthenticationAgentCallback callback, gpointer user_data); +static PolkitSubject *authentication_agent_get_session (AuthenticationAgent *agent); + static AuthenticationAgent *get_authentication_agent_for_subject (PolkitBackendInteractiveAuthority *authority, PolkitSubject *subject); + static AuthenticationSession *get_authentication_session_for_cookie (PolkitBackendInteractiveAuthority *authority, const gchar *cookie); @@ -140,17 +144,17 @@ static PolkitAuthorizationResult *check_authorization_sync (PolkitBackendAuthori GError **error); static gboolean polkit_backend_interactive_authority_register_authentication_agent (PolkitBackendAuthority *authority, - PolkitSubject *caller, - const gchar *session_id, - const gchar *locale, - const gchar *object_path, - GError **error); + PolkitSubject *caller, + PolkitSubject *subject, + const gchar *locale, + const gchar *object_path, + GError **error); static gboolean polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBackendAuthority *authority, - PolkitSubject *caller, - const gchar *session_id, - const gchar *object_path, - GError **error); + PolkitSubject *caller, + PolkitSubject *subject, + const gchar *object_path, + GError **error); static gboolean polkit_backend_interactive_authority_authentication_agent_response (PolkitBackendAuthority *authority, PolkitSubject *caller, @@ -158,6 +162,17 @@ static gboolean polkit_backend_interactive_authority_authentication_agent_respon PolkitIdentity *identity, GError **error); +static GList *polkit_backend_interactive_authority_enumerate_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error); + + +static gboolean polkit_backend_interactive_authority_revoke_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error); + /* ---------------------------------------------------------------------------------------------------- */ @@ -208,7 +223,7 @@ polkit_backend_interactive_authority_init (PolkitBackendInteractiveAuthority *au (GCallback) action_pool_changed, authority); - priv->temporary_authorization_store = temporary_authorization_store_new (); + priv->temporary_authorization_store = temporary_authorization_store_new (authority); priv->hash_session_to_authentication_agent = g_hash_table_new_full ((GHashFunc) polkit_subject_hash, (GEqualFunc) polkit_subject_equal, @@ -258,6 +273,9 @@ polkit_backend_interactive_authority_class_init (PolkitBackendInteractiveAuthori authority_class->register_authentication_agent = polkit_backend_interactive_authority_register_authentication_agent; authority_class->unregister_authentication_agent = polkit_backend_interactive_authority_unregister_authentication_agent; authority_class->authentication_agent_response = polkit_backend_interactive_authority_authentication_agent_response; + authority_class->enumerate_temporary_authorizations = polkit_backend_interactive_authority_enumerate_temporary_authorizations; + authority_class->revoke_temporary_authorizations = polkit_backend_interactive_authority_revoke_temporary_authorizations; + g_type_class_add_private (klass, sizeof (PolkitBackendInteractiveAuthorityPrivate)); @@ -323,7 +341,10 @@ check_authorization_challenge_cb (AuthenticationAgent *agent, { temporary_authorization_store_add_authorization (priv->temporary_authorization_store, subject, + authentication_agent_get_session (agent), action_id); + /* we've added a temporary authorization, let the user know */ + g_signal_emit_by_name (authority, "changed"); } } else @@ -948,6 +969,12 @@ authentication_agent_new_cookie (AuthenticationAgent *agent) return g_strdup_printf ("cookie%d", counter++); } +static PolkitSubject * +authentication_agent_get_session (AuthenticationAgent *agent) +{ + return agent->session; +} + static void authentication_agent_free (AuthenticationAgent *agent) { @@ -1489,11 +1516,11 @@ authentication_session_cancel (AuthenticationSession *session) static gboolean polkit_backend_interactive_authority_register_authentication_agent (PolkitBackendAuthority *authority, - PolkitSubject *caller, - const gchar *session_id, - const gchar *locale, - const gchar *object_path, - GError **error) + PolkitSubject *caller, + PolkitSubject *subject, + const gchar *locale, + const gchar *object_path, + GError **error) { PolkitBackendInteractiveAuthority *interactive_authority; PolkitBackendInteractiveAuthorityPrivate *priv; @@ -1507,12 +1534,12 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority); priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority); - if (session_id != NULL && strlen (session_id) > 0) + if (!POLKIT_IS_UNIX_SESSION (subject)) { g_set_error (error, POLKIT_ERROR, POLKIT_ERROR_FAILED, - "The session_id parameter must be blank for now."); + "Can only register PolkitUnixSession objects for now."); goto out; } @@ -1524,7 +1551,16 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken g_set_error (error, POLKIT_ERROR, POLKIT_ERROR_FAILED, - "Cannot determine session"); + "Cannot determine session the caller is in"); + goto out; + } + + if (!polkit_subject_equal (session_for_caller, subject)) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Passed session and the session the caller is in differs. They must be equal for now."); goto out; } @@ -1566,10 +1602,10 @@ polkit_backend_interactive_authority_register_authentication_agent (PolkitBacken static gboolean polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBackendAuthority *authority, - PolkitSubject *caller, - const gchar *session_id, - const gchar *object_path, - GError **error) + PolkitSubject *caller, + PolkitSubject *subject, + const gchar *object_path, + GError **error) { PolkitBackendInteractiveAuthority *interactive_authority; PolkitBackendInteractiveAuthorityPrivate *priv; @@ -1583,12 +1619,12 @@ polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBack ret = FALSE; session_for_caller = NULL; - if (session_id != NULL && strlen (session_id) > 0) + if (!POLKIT_IS_UNIX_SESSION (subject)) { g_set_error (error, POLKIT_ERROR, POLKIT_ERROR_FAILED, - "The session_id parameter must be blank for now."); + "Can only unregister PolkitUnixSession objects for now."); goto out; } @@ -1600,7 +1636,16 @@ polkit_backend_interactive_authority_unregister_authentication_agent (PolkitBack g_set_error (error, POLKIT_ERROR, POLKIT_ERROR_FAILED, - "Cannot determine session"); + "Cannot determine session the caller is in"); + goto out; + } + + if (!polkit_subject_equal (session_for_caller, subject)) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Passed session and the session the caller is in differs. They must be equal for now."); goto out; } @@ -1804,43 +1849,41 @@ typedef struct TemporaryAuthorization TemporaryAuthorization; struct TemporaryAuthorizationStore { GList *authorizations; + PolkitBackendInteractiveAuthority *authority; + guint64 serial; }; struct TemporaryAuthorization { + TemporaryAuthorizationStore *store; PolkitSubject *subject; + PolkitSubject *session; + gchar *id; gchar *action_id; guint64 time_granted; + guint64 time_expires; + guint expiration_timeout_id; }; static void temporary_authorization_free (TemporaryAuthorization *authorization) { + g_free (authorization->id); g_object_unref (authorization->subject); + g_object_unref (authorization->session); g_free (authorization->action_id); + if (authorization->expiration_timeout_id > 0) + g_source_remove (authorization->expiration_timeout_id); g_free (authorization); } -static TemporaryAuthorization * -temporary_authorization_new (PolkitSubject *subject, - const gchar *action_id) -{ - TemporaryAuthorization *authorization; - - authorization = g_new0 (TemporaryAuthorization, 1); - authorization->subject = g_object_ref (subject); - authorization->action_id = g_strdup (action_id); - authorization->time_granted = time (NULL); - - return authorization; -} - static TemporaryAuthorizationStore * -temporary_authorization_store_new (void) +temporary_authorization_store_new (PolkitBackendInteractiveAuthority *authority) { TemporaryAuthorizationStore *store; store = g_new0 (TemporaryAuthorizationStore, 1); + store->authority = authority; store->authorizations = NULL; return store; @@ -1883,16 +1926,208 @@ temporary_authorization_store_has_authorization (TemporaryAuthorizationStore *st return ret; } +static gboolean +on_expiration_timeout (gpointer user_data) +{ + TemporaryAuthorization *authorization = user_data; + + authorization->store->authorizations = g_list_remove (authorization->store->authorizations, + authorization); + authorization->expiration_timeout_id = 0; + g_signal_emit_by_name (authorization->store->authority, "changed"); + temporary_authorization_free (authorization); + + /* remove source */ + return FALSE; +} + static void temporary_authorization_store_add_authorization (TemporaryAuthorizationStore *store, PolkitSubject *subject, + PolkitSubject *session, const gchar *action_id) { + TemporaryAuthorization *authorization; + guint expiration_seconds; + g_return_if_fail (store != NULL); g_return_if_fail (POLKIT_IS_SUBJECT (subject)); g_return_if_fail (action_id != NULL); g_return_if_fail (!temporary_authorization_store_has_authorization (store, subject, action_id)); - store->authorizations = g_list_prepend (store->authorizations, - temporary_authorization_new (subject, action_id)); + /* TODO: right now this is hard-coded - we could make it a propery on the + * PolkitBackendInteractiveAuthority class. Or we could even read + * it per action from an annotation. + */ + expiration_seconds = 5 * 60; + + authorization = g_new0 (TemporaryAuthorization, 1); + authorization->id = g_strdup_printf ("tmpauthz%" G_GUINT64_FORMAT, store->serial++); + authorization->store = store; + authorization->subject = g_object_ref (subject); + authorization->session = g_object_ref (session); + authorization->action_id = g_strdup (action_id); + authorization->time_granted = time (NULL); + authorization->time_expires = authorization->time_granted + expiration_seconds; + authorization->expiration_timeout_id = g_timeout_add (expiration_seconds * 1000, + on_expiration_timeout, + authorization); + + store->authorizations = g_list_prepend (store->authorizations, authorization); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static GList * +polkit_backend_interactive_authority_enumerate_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error) +{ + PolkitBackendInteractiveAuthority *interactive_authority; + PolkitBackendInteractiveAuthorityPrivate *priv; + PolkitSubject *session_for_caller; + GList *ret; + GList *l; + + interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority); + priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority); + + ret = NULL; + session_for_caller = NULL; + + if (!POLKIT_IS_UNIX_SESSION (subject)) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Can only handle PolkitUnixSession objects for now."); + goto out; + } + + session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor, + caller, + NULL); + if (session_for_caller == NULL) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Cannot determine session the caller is in"); + goto out; + } + + if (!polkit_subject_equal (session_for_caller, subject)) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Passed session and the session the caller is in differs. They must be equal for now."); + goto out; + } + + for (l = priv->temporary_authorization_store->authorizations; l != NULL; l = l->next) + { + TemporaryAuthorization *ta = l->data; + PolkitTemporaryAuthorization *tmp_authz; + + if (!polkit_subject_equal (ta->session, subject)) + continue; + + tmp_authz = polkit_temporary_authorization_new (ta->id, + ta->action_id, + ta->subject, + ta->time_granted, + ta->time_expires); + + ret = g_list_prepend (ret, tmp_authz); + } + + out: + if (session_for_caller != NULL) + g_object_unref (session_for_caller); + + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static gboolean +polkit_backend_interactive_authority_revoke_temporary_authorizations (PolkitBackendAuthority *authority, + PolkitSubject *caller, + PolkitSubject *subject, + GError **error) +{ + PolkitBackendInteractiveAuthority *interactive_authority; + PolkitBackendInteractiveAuthorityPrivate *priv; + PolkitSubject *session_for_caller; + gboolean ret; + GList *l; + GList *ll; + guint num_removed; + + interactive_authority = POLKIT_BACKEND_INTERACTIVE_AUTHORITY (authority); + priv = POLKIT_BACKEND_INTERACTIVE_AUTHORITY_GET_PRIVATE (interactive_authority); + + ret = FALSE; + session_for_caller = NULL; + + if (!POLKIT_IS_UNIX_SESSION (subject)) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Can only handle PolkitUnixSession objects for now."); + goto out; + } + + session_for_caller = polkit_backend_session_monitor_get_session_for_subject (priv->session_monitor, + caller, + NULL); + if (session_for_caller == NULL) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Cannot determine session the caller is in"); + goto out; + } + + if (!polkit_subject_equal (session_for_caller, subject)) + { + g_set_error (error, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Passed session and the session the caller is in differs. They must be equal for now."); + goto out; + } + + num_removed = 0; + for (l = priv->temporary_authorization_store->authorizations; l != NULL; l = ll) + { + TemporaryAuthorization *ta = l->data; + + ll = l->next; + + if (!polkit_subject_equal (ta->session, subject)) + continue; + + priv->temporary_authorization_store->authorizations = g_list_remove (priv->temporary_authorization_store->authorizations, ta); + temporary_authorization_free (ta); + + num_removed++; + } + + if (num_removed > 0) + g_signal_emit_by_name (authority, "changed"); + + ret = TRUE; + + out: + if (session_for_caller != NULL) + g_object_unref (session_for_caller); + + return ret; } + +/* ---------------------------------------------------------------------------------------------------- */ |