diff options
-rw-r--r-- | data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml | 6 | ||||
-rw-r--r-- | data/org.freedesktop.PolicyKit1.Authority.xml | 11 | ||||
-rw-r--r-- | src/polkit/polkitauthority.c | 104 | ||||
-rw-r--r-- | src/polkit/polkitauthority.h | 17 | ||||
-rw-r--r-- | src/polkitagent/Makefile.am | 3 | ||||
-rw-r--r-- | src/polkitagent/polkitagentauthenticationagent.c | 50 | ||||
-rw-r--r-- | src/polkitagent/polkitagentauthenticationagent.h | 30 | ||||
-rw-r--r-- | src/polkitagent/polkitagentauthenticationsession.c | 2 | ||||
-rw-r--r-- | src/polkitagent/polkitagenthelper.c | 60 | ||||
-rw-r--r-- | src/polkitbackend/Makefile.am | 40 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendauthority.c | 13 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendauthority.h | 13 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendlocalauthority.c | 487 | ||||
-rw-r--r-- | src/polkitbackend/polkitbackendserver.c | 32 |
14 files changed, 799 insertions, 69 deletions
diff --git a/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml b/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml index 1a2063c..cf0040b 100644 --- a/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml +++ b/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml @@ -6,7 +6,6 @@ <interface name="org.freedesktop.PolicyKit1.AuthenticationAgent"> <method name="BeginAuthentication"> - <!-- The action id for the action that the user is authentication for --> <arg name="action_id" direction="in" type="s"/> @@ -15,13 +14,10 @@ <!-- A list of identities of that the user can use for authentication --> <arg name="identities" direction="in" type="a(sa{sv})"/> - </method> - <method name="EndAuthentication"> - + <method name="CancelAuthentication"> <arg name="cookie" direction="in" type="s"/> - </method> </interface> diff --git a/data/org.freedesktop.PolicyKit1.Authority.xml b/data/org.freedesktop.PolicyKit1.Authority.xml index c21fa84..4a15f74 100644 --- a/data/org.freedesktop.PolicyKit1.Authority.xml +++ b/data/org.freedesktop.PolicyKit1.Authority.xml @@ -238,5 +238,16 @@ </arg> </method> + <method name="AuthenticationAgentResponse"> + <arg name="cookie" direction="in" type="s"> + <annotation name="org.gtk.EggDBus.DocString" value="The cookie identifying the authentication request that was passed to the authentication agent"/> + </arg> + + <arg name="identity" direction="in" type="(sa{sv})"> + <annotation name="org.gtk.EggDBus.StructType" value="Identity"/> + <annotation name="org.gtk.EggDBus.DocString" value="The identity that was authenticated"/> + </arg> + </method> + </interface> </node> diff --git a/src/polkit/polkitauthority.c b/src/polkit/polkitauthority.c index 3d36c14..70324fe 100644 --- a/src/polkit/polkitauthority.c +++ b/src/polkit/polkitauthority.c @@ -1046,3 +1046,107 @@ polkit_authority_unregister_authentication_agent_sync (PolkitAuthority *auth } /* ---------------------------------------------------------------------------------------------------- */ + +static guint +polkit_authority_authentication_agent_response_async (PolkitAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + guint call_id; + GSimpleAsyncResult *simple; + _PolkitIdentity *real_identity; + + simple = g_simple_async_result_new (G_OBJECT (authority), + callback, + user_data, + polkit_authority_authentication_agent_response_async); + + real_identity = polkit_identity_get_real (identity); + + call_id = _polkit_authority_authentication_agent_response (authority->real, + EGG_DBUS_CALL_FLAGS_NONE, + cookie, + real_identity, + cancellable, + generic_async_cb, + simple); + + g_object_unref (real_identity); + + return call_id; +} + +void +polkit_authority_authentication_agent_response (PolkitAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data) +{ + polkit_authority_authentication_agent_response_async (authority, + cookie, + identity, + cancellable, + callback, + user_data); +} + +gboolean +polkit_authority_authentication_agent_response_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_authentication_agent_response_async); + + ret = _polkit_authority_authentication_agent_response_finish (authority->real, + real_res, + error); + + if (!ret) + goto out; + + out: + g_object_unref (real_res); + return ret; +} + + +gboolean +polkit_authority_authentication_agent_response_sync (PolkitAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + GCancellable *cancellable, + GError **error) +{ + guint call_id; + GAsyncResult *res; + gboolean ret; + + call_id = polkit_authority_authentication_agent_response_async (authority, + cookie, + identity, + cancellable, + generic_cb, + &res); + + egg_dbus_connection_pending_call_block (authority->system_bus, call_id); + + ret = polkit_authority_authentication_agent_response_finish (authority, res, error); + + g_object_unref (res); + + return ret; +} + +/* ---------------------------------------------------------------------------------------------------- */ diff --git a/src/polkit/polkitauthority.h b/src/polkit/polkitauthority.h index e6ece8e..db1bb46 100644 --- a/src/polkit/polkitauthority.h +++ b/src/polkit/polkitauthority.h @@ -93,6 +93,12 @@ gboolean polkit_authority_unregister_authentication_agent_sync GCancellable *cancellable, GError **error); +gboolean polkit_authority_authentication_agent_response_sync (PolkitAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + GCancellable *cancellable, + GError **error); + /* ---------------------------------------------------------------------------------------------------- */ void polkit_authority_enumerate_actions (PolkitAuthority *authority, @@ -188,6 +194,17 @@ gboolean polkit_authority_unregister_authentication_agent_fini GAsyncResult *res, GError **error); +void polkit_authority_authentication_agent_response (PolkitAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + GCancellable *cancellable, + GAsyncReadyCallback callback, + gpointer user_data); + +gboolean polkit_authority_authentication_agent_response_finish (PolkitAuthority *authority, + GAsyncResult *res, + GError **error); + /* ---------------------------------------------------------------------------------------------------- */ G_END_DECLS diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am index d227661..b792f93 100644 --- a/src/polkitagent/Makefile.am +++ b/src/polkitagent/Makefile.am @@ -65,7 +65,8 @@ libpolkit_agent_1_la_LIBADD = \ libexec_PROGRAMS = polkit-agent-helper-1 polkit_agent_helper_1_SOURCES = polkitagenthelper.c -polkit_agent_helper_1_LDADD = $(AUTH_LIBS) +polkit_agent_helper_1_CFLAGS = $(GLIB_CFLAGS) +polkit_agent_helper_1_LDADD = $(AUTH_LIBS) $(top_builddir)/src/polkit/libpolkit-gobject-1.la # polkit-agent-helper-1 need to be setuid root because it's used to # authenticate not only the invoking user, but possibly also root diff --git a/src/polkitagent/polkitagentauthenticationagent.c b/src/polkitagent/polkitagentauthenticationagent.c index 844a32e..5014b37 100644 --- a/src/polkitagent/polkitagentauthenticationagent.c +++ b/src/polkitagent/polkitagentauthenticationagent.c @@ -35,7 +35,7 @@ struct _PolkitAgentAuthenticationAgent PolkitAuthority *authority; PolkitAgentAuthenticationAgentBeginFunc begin_func; - PolkitAgentAuthenticationAgentEndFunc end_func; + PolkitAgentAuthenticationAgentCancelFunc cancel_func; gpointer user_data; }; @@ -100,7 +100,7 @@ polkit_agent_authentication_agent_class_init (PolkitAgentAuthenticationAgentClas PolkitAgentAuthenticationAgent * polkit_agent_authentication_agent_new (PolkitAgentAuthenticationAgentBeginFunc begin_func, - PolkitAgentAuthenticationAgentEndFunc end_func, + PolkitAgentAuthenticationAgentCancelFunc cancel_func, gpointer user_data, GError **error) { @@ -109,7 +109,7 @@ polkit_agent_authentication_agent_new (PolkitAgentAuthenticationAgentBeginFunc b agent = POLKIT_AGENT_AUTHENTICATION_AGENT (g_object_new (POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT, NULL)); agent->begin_func = begin_func; - agent->end_func = end_func; + agent->cancel_func = cancel_func; agent->user_data = user_data; if (!polkit_authority_register_authentication_agent_sync (agent->authority, @@ -147,41 +147,51 @@ handle_begin_authentication (_PolkitAgentAuthenticationAgent *instance, list = g_list_reverse (list); error = NULL; - if (!agent->begin_func (agent, - action_id, - cookie, - list, - &error, - agent->user_data)) + + agent->begin_func (agent, + action_id, + cookie, + list, + (gpointer) method_invocation); + + g_list_free (list); +} + +void +polkit_agent_authentication_agent_finish (PolkitAgentAuthenticationAgent *agent, + gpointer pending_call, + GError *error) +{ + EggDBusMethodInvocation *method_invocation = EGG_DBUS_METHOD_INVOCATION (pending_call); + + if (error != NULL) { egg_dbus_method_invocation_return_gerror (method_invocation, error); - g_error_free (error); } else { _polkit_agent_authentication_agent_handle_begin_authentication_finish (method_invocation); } - - g_list_free (list); } + static void -handle_end_authentication (_PolkitAgentAuthenticationAgent *instance, - const gchar *cookie, - EggDBusMethodInvocation *method_invocation) +handle_cancel_authentication (_PolkitAgentAuthenticationAgent *instance, + const gchar *cookie, + EggDBusMethodInvocation *method_invocation) { PolkitAgentAuthenticationAgent *agent = POLKIT_AGENT_AUTHENTICATION_AGENT (instance); - agent->end_func (agent, - cookie, - agent->user_data); + agent->cancel_func (agent, + cookie, + agent->user_data); - _polkit_agent_authentication_agent_handle_end_authentication_finish (method_invocation); + _polkit_agent_authentication_agent_handle_cancel_authentication_finish (method_invocation); } static void authentication_agent_iface_init (_PolkitAgentAuthenticationAgentIface *agent_iface) { agent_iface->handle_begin_authentication = handle_begin_authentication; - agent_iface->handle_end_authentication = handle_end_authentication; + agent_iface->handle_cancel_authentication = handle_cancel_authentication; } diff --git a/src/polkitagent/polkitagentauthenticationagent.h b/src/polkitagent/polkitagentauthenticationagent.h index 9d315ff..96d009b 100644 --- a/src/polkitagent/polkitagentauthenticationagent.h +++ b/src/polkitagent/polkitagentauthenticationagent.h @@ -19,8 +19,8 @@ * Author: David Zeuthen <davidz@redhat.com> */ -#ifndef __POLKIT_AGENT_AUTHENTICATION_SESSION_H -#define __POLKIT_AGENT_AUTHENTICATION_SESSION_H +#ifndef __POLKIT_AGENT_AUTHENTICATION_AGENT_H +#define __POLKIT_AGENT_AUTHENTICATION_AGENT_H #include <polkit/polkit.h> #include <polkitagent/polkitagenttypes.h> @@ -41,25 +41,29 @@ typedef struct _PolkitAgentAuthenticationAgentClass PolkitAgentAuthentication /* TODO: we probably want to express this interface in another way but this is good enough for now */ -typedef gboolean (*PolkitAgentAuthenticationAgentBeginFunc) (PolkitAgentAuthenticationAgent *agent, - const gchar *action_id, - const gchar *cookie, - GList *identities, - GError **error, - gpointer user_data); - -typedef void (*PolkitAgentAuthenticationAgentEndFunc) (PolkitAgentAuthenticationAgent *agent, +typedef void (*PolkitAgentAuthenticationAgentBeginFunc) (PolkitAgentAuthenticationAgent *agent, + const gchar *action_id, const gchar *cookie, - gpointer user_data); + GList *identities, + gpointer pending_call); + +typedef void (*PolkitAgentAuthenticationAgentCancelFunc) (PolkitAgentAuthenticationAgent *agent, + const gchar *cookie, + gpointer user_data); GType polkit_agent_authentication_agent_get_type (void) G_GNUC_CONST; + PolkitAgentAuthenticationAgent *polkit_agent_authentication_agent_new (PolkitAgentAuthenticationAgentBeginFunc begin_func, - PolkitAgentAuthenticationAgentEndFunc end_func, + PolkitAgentAuthenticationAgentCancelFunc cancel_func, gpointer user_data, GError **error); +void polkit_agent_authentication_agent_finish (PolkitAgentAuthenticationAgent *agent, + gpointer pending_call, + GError *error); + /* --- */ G_END_DECLS -#endif /* __POLKIT_AGENT_AUTHENTICATION_SESSION_H */ +#endif /* __POLKIT_AGENT_AUTHENTICATION_AGENT_H */ diff --git a/src/polkitagent/polkitagentauthenticationsession.c b/src/polkitagent/polkitagentauthenticationsession.c index 2c6bc65..993313c 100644 --- a/src/polkitagent/polkitagentauthenticationsession.c +++ b/src/polkitagent/polkitagentauthenticationsession.c @@ -286,7 +286,7 @@ polkit_agent_authentication_session_initiate_auth (PolkitAgentAuthenticationSess goto error; } - helper_argv[0] = PACKAGE_LIBEXEC_DIR "/polkit-session-helper-1"; + helper_argv[0] = PACKAGE_LIBEXEC_DIR "/polkit-agent-helper-1"; helper_argv[1] = passwd->pw_name; helper_argv[2] = session->cookie; helper_argv[3] = NULL; diff --git a/src/polkitagent/polkitagenthelper.c b/src/polkitagent/polkitagenthelper.c index df59f18..d5844e5 100644 --- a/src/polkitagent/polkitagenthelper.c +++ b/src/polkitagent/polkitagenthelper.c @@ -29,6 +29,8 @@ #include <syslog.h> #include <security/pam_appl.h> +#include <polkit/polkit.h> + #ifdef HAVE_SOLARIS # define LOG_AUTHPRIV (10<<3) #endif @@ -38,7 +40,9 @@ * sensitive information. */ #undef PAH_DEBUG -#define PAH_DEBUG +//#define PAH_DEBUG + +static gboolean send_dbus_message (const char *cookie, const char *user); static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data); @@ -154,9 +158,11 @@ main (int argc, char *argv[]) fprintf (stderr, "polkit-agent-helper-1: successfully authenticated user '%s'.\n", user_to_auth); #endif /* PAH_DEBUG */ - /* TODO: now send a D-Bus message to the PolicyKit daemon that - * includes a) the cookie; and b) the user we authenticated + /* now send a D-Bus message to the PolicyKit daemon that + * includes a) the cookie; and b) the user we authenticated */ + if (!send_dbus_message (cookie, user_to_auth)) + goto error; fprintf (stdout, "SUCCESS\n"); fflush (stdout); @@ -253,3 +259,51 @@ error: *resp = NULL; return PAM_CONV_ERR; } + +static gboolean +send_dbus_message (const char *cookie, const char *user) +{ + PolkitAuthority *authority; + PolkitIdentity *identity; + GError *error; + gboolean ret; + + ret = FALSE; + + error = NULL; + + g_type_init (); + + authority = polkit_authority_get (); + + identity = polkit_unix_user_new_for_name (user, &error); + if (identity == NULL) + { + g_printerr ("Error constructing identity: %s\n", error->message); + g_error_free (error); + goto out; + } + + if (!polkit_authority_authentication_agent_response_sync (authority, + cookie, + identity, + NULL, + &error)) + { + g_printerr ("Error sending response to PolicyKit daemon: %s\n", error->message); + g_error_free (error); + goto out; + } + + ret = TRUE; + + out: + + if (identity != NULL) + g_object_unref (identity); + + if (authority != NULL) + g_object_unref (authority); + + return ret; +} diff --git a/src/polkitbackend/Makefile.am b/src/polkitbackend/Makefile.am index 5b6d7ea..da6f2a3 100644 --- a/src/polkitbackend/Makefile.am +++ b/src/polkitbackend/Makefile.am @@ -15,23 +15,33 @@ INCLUDES = \ -DEGG_DBUS_I_KNOW_API_IS_SUBJECT_TO_CHANGE \ $(NULL) -BUILT_SOURCES = \ - ckmanager.c ckmanager.h \ - cksession.c cksession.h \ - ckseat.c ckseat.h \ - ckdevice.c ckdevice.h \ - ckbindings.c ckbindings.h \ - ckbindingsmarshal.list \ - ckbindingsmarshal.c ckbindingsmarshal.h \ - ckbindingstypes.h \ - ckerror.c ckerror.h \ +BUILT_SOURCES = \ + ckmanager.c ckmanager.h \ + cksession.c cksession.h \ + ckseat.c ckseat.h \ + ckdevice.c ckdevice.h \ + ckbindings.c ckbindings.h \ + ckbindingsmarshal.list \ + ckbindingsmarshal.c ckbindingsmarshal.h \ + ckbindingstypes.h \ + ckerror.c ckerror.h \ + _polkitagentauthenticationagent.c _polkitagentauthenticationagent.h \ + _polkitagentbindings.c _polkitagentbindings.h \ + _polkitagentbindingsmarshal.list \ + _polkitagentbindingsmarshal.c _polkitagentbindingsmarshal.h \ + _polkitagentbindingstypes.h \ $(NULL) -$(BUILT_SOURCES) : Makefile.am $(top_srcdir)/src/polkitbackend/org.freedesktop.ConsoleKit.xml - eggdbus-binding-tool \ - --namespace "Ck" \ - --dbus-namespace "org.freedesktop.ConsoleKit" \ - --introspection-xml $(top_srcdir)/src/polkitbackend/org.freedesktop.ConsoleKit.xml \ +$(BUILT_SOURCES) : Makefile.am $(top_srcdir)/src/polkitbackend/org.freedesktop.ConsoleKit.xml $(top_srcdir)/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml + eggdbus-binding-tool \ + --namespace "Ck" \ + --dbus-namespace "org.freedesktop.ConsoleKit" \ + --introspection-xml $(top_srcdir)/src/polkitbackend/org.freedesktop.ConsoleKit.xml \ + $(NULL) + eggdbus-binding-tool \ + --namespace "_PolkitAgent" \ + --dbus-namespace "org.freedesktop.PolicyKit1" \ + --introspection-xml $(top_srcdir)/data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml \ $(NULL) lib_LTLIBRARIES=libpolkit-backend-1.la diff --git a/src/polkitbackend/polkitbackendauthority.c b/src/polkitbackend/polkitbackendauthority.c index 399b4c7..5f06e10 100644 --- a/src/polkitbackend/polkitbackendauthority.c +++ b/src/polkitbackend/polkitbackendauthority.c @@ -161,3 +161,16 @@ polkit_backend_authority_unregister_authentication_agent (PolkitBackendAuthority klass->unregister_authentication_agent (authority, object_path, pending_call); } +void +polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + PolkitBackendPendingCall *pending_call) +{ + PolkitBackendAuthorityClass *klass; + + klass = POLKIT_BACKEND_AUTHORITY_GET_CLASS (authority); + + klass->authentication_agent_response (authority, cookie, identity, pending_call); +} + diff --git a/src/polkitbackend/polkitbackendauthority.h b/src/polkitbackend/polkitbackendauthority.h index a35ad7e..06f54fa 100644 --- a/src/polkitbackend/polkitbackendauthority.h +++ b/src/polkitbackend/polkitbackendauthority.h @@ -95,6 +95,11 @@ struct _PolkitBackendAuthorityClass const gchar *object_path, PolkitBackendPendingCall *pending_call); + void (*authentication_agent_response) (PolkitBackendAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + PolkitBackendPendingCall *pending_call); + /*< private >*/ /* Padding for future expansion */ void (*_polkit_reserved1) (void); @@ -154,6 +159,11 @@ void polkit_backend_authority_unregister_authentication_agent (PolkitBackend const gchar *object_path, PolkitBackendPendingCall *pending_call); +void polkit_backend_authority_authentication_agent_response (PolkitBackendAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + PolkitBackendPendingCall *pending_call); + /* --- */ void polkit_backend_authority_enumerate_actions_finish (PolkitBackendPendingCall *pending_call, @@ -176,8 +186,11 @@ void polkit_backend_authority_add_authorization_finish (PolkitBackend void polkit_backend_authority_remove_authorization_finish (PolkitBackendPendingCall *pending_call); void polkit_backend_authority_register_authentication_agent_finish (PolkitBackendPendingCall *pending_call); + void polkit_backend_authority_unregister_authentication_agent_finish (PolkitBackendPendingCall *pending_call); +void polkit_backend_authority_authentication_agent_response_finish (PolkitBackendPendingCall *pending_call); + G_END_DECLS diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c index d97da1d..3cb6c46 100644 --- a/src/polkitbackend/polkitbackendlocalauthority.c +++ b/src/polkitbackend/polkitbackendlocalauthority.c @@ -32,6 +32,10 @@ #include "polkitbackendpendingcall.h" #include "polkitbackendsessionmonitor.h" +#include "_polkitagentbindings.h" +#include <polkit/polkitprivate.h> + + typedef struct { PolkitBackendActionPool *action_pool; @@ -59,8 +63,13 @@ static AuthorizationStore *get_authorization_store_for_identity (PolkitBackendLo struct AuthenticationAgent; typedef struct AuthenticationAgent AuthenticationAgent; +struct AuthenticationSession; +typedef struct AuthenticationSession AuthenticationSession; + typedef void (*AuthenticationAgentCallback) (AuthenticationAgent *agent, PolkitSubject *subject, + PolkitIdentity *user_of_subject, + PolkitBackendLocalAuthority *authority, const gchar *action_id, PolkitImplicitAuthorization implicit_authorization, gboolean authentication_success, @@ -70,7 +79,10 @@ static void authentication_agent_free (AuthenticationAgent *agent static void authentication_agent_initiate_challenge (AuthenticationAgent *agent, PolkitSubject *subject, + PolkitIdentity *user_of_subject, + PolkitBackendLocalAuthority *authority, const gchar *action_id, + PolkitSubject *caller, PolkitImplicitAuthorization implicit_authorization, AuthenticationAgentCallback callback, gpointer user_data); @@ -78,6 +90,14 @@ static void authentication_agent_initiate_challenge (Authenticati static AuthenticationAgent *get_authentication_agent_for_subject (PolkitBackendLocalAuthority *authority, PolkitSubject *subject); +static AuthenticationSession *get_authentication_session_for_cookie (PolkitBackendLocalAuthority *authority, + const gchar *cookie); + +static GList *get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendLocalAuthority *authority, + const gchar *system_bus_unique_name); + +static void authentication_session_cancel (AuthenticationSession *session); + /* ---------------------------------------------------------------------------------------------------- */ static gboolean check_authorization_for_identity (PolkitBackendLocalAuthority *authority, @@ -157,6 +177,11 @@ static void polkit_backend_local_authority_unregister_authentication_agent (Polk const gchar *object_path, PolkitBackendPendingCall *pending_call); +static void polkit_backend_local_authority_authentication_agent_response (PolkitBackendAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + PolkitBackendPendingCall *pending_call); + /* ---------------------------------------------------------------------------------------------------- */ G_DEFINE_TYPE (PolkitBackendLocalAuthority, polkit_backend_local_authority, POLKIT_BACKEND_TYPE_AUTHORITY); @@ -231,6 +256,8 @@ polkit_backend_local_authority_class_init (PolkitBackendLocalAuthorityClass *kla authority_class->remove_authorization = polkit_backend_local_authority_remove_authorization; authority_class->register_authentication_agent = polkit_backend_local_authority_register_authentication_agent; authority_class->unregister_authentication_agent = polkit_backend_local_authority_unregister_authentication_agent; + authority_class->authentication_agent_response = polkit_backend_local_authority_authentication_agent_response; + g_type_class_add_private (klass, sizeof (PolkitBackendLocalAuthorityPrivate)); } @@ -359,6 +386,8 @@ polkit_backend_local_authority_enumerate_groups (PolkitBackendAuthority *autho static void check_authorization_challenge_cb (AuthenticationAgent *agent, PolkitSubject *subject, + PolkitIdentity *user_of_subject, + PolkitBackendLocalAuthority *authority, const gchar *action_id, PolkitImplicitAuthorization implicit_authorization, gboolean authentication_success, @@ -382,7 +411,30 @@ check_authorization_challenge_cb (AuthenticationAgent *agent, { result = POLKIT_AUTHORIZATION_RESULT_AUTHORIZED; - /* TODO: store temporary authorization depending on value of implicit_authorization */ + /* store temporary authorization depending on value of implicit_authorization */ + if (implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_AUTHENTICATION_REQUIRED_RETAINED || + implicit_authorization == POLKIT_IMPLICIT_AUTHORIZATION_ADMINISTRATOR_AUTHENTICATION_REQUIRED_RETAINED) + { + GError *error; + PolkitAuthorization *authorization; + + authorization = polkit_authorization_new (action_id, + subject, + FALSE); + + if (!add_authorization_for_identity (authority, + user_of_subject, + authorization, + &error)) + { + g_warning ("Error adding temporary authorization gained from authentication: %s", + error->message); + + g_error_free (error); + } + + g_object_unref (authorization); + } } else { @@ -529,7 +581,10 @@ polkit_backend_local_authority_check_authorization (PolkitBackendAuthority authentication_agent_initiate_challenge (agent, subject, + user_of_subject, + local_authority, action_id, + inquirer, implicit_authorization, check_authorization_challenge_cb, pending_call); @@ -891,11 +946,120 @@ struct AuthenticationAgent gchar *object_path; gchar *unique_system_bus_name; + + EggDBusObjectProxy *object_proxy; + + GList *active_sessions; +}; + +struct AuthenticationSession +{ + AuthenticationAgent *agent; + + gchar *cookie; + + PolkitSubject *subject; + + PolkitIdentity *user_of_subject; + + PolkitBackendLocalAuthority *authority; + + GList *identities; + + gchar *action_id; + + gchar *initiated_by_system_bus_unique_name; + + PolkitImplicitAuthorization implicit_authorization; + + AuthenticationAgentCallback callback; + + gpointer user_data; + + guint call_id; + + gboolean is_authenticated; }; +static AuthenticationSession * +authentication_session_new (AuthenticationAgent *agent, + const gchar *cookie, + PolkitSubject *subject, + PolkitIdentity *user_of_subject, + PolkitBackendLocalAuthority *authority, + GList *identities, + const gchar *action_id, + const gchar *initiated_by_system_bus_unique_name, + PolkitImplicitAuthorization implicit_authorization, + AuthenticationAgentCallback callback, + gpointer user_data) +{ + AuthenticationSession *session; + + session = g_new0 (AuthenticationSession, 1); + session->agent = agent; + session->cookie = g_strdup (cookie); + session->subject = g_object_ref (subject); + session->user_of_subject = g_object_ref (user_of_subject); + session->authority = g_object_ref (authority); + session->identities = g_list_copy (identities); + g_list_foreach (session->identities, (GFunc) g_object_ref, NULL); + session->action_id = g_strdup (action_id); + session->initiated_by_system_bus_unique_name = g_strdup (initiated_by_system_bus_unique_name); + session->implicit_authorization = implicit_authorization; + session->callback = callback; + session->user_data = user_data; + + return session; +} + +static void +authentication_session_free (AuthenticationSession *session) +{ + g_free (session->cookie); + g_list_foreach (session->identities, (GFunc) g_object_unref, NULL); + g_list_free (session->identities); + g_object_unref (session->subject); + g_object_unref (session->user_of_subject); + g_object_unref (session->authority); + g_free (session->action_id); + g_free (session->initiated_by_system_bus_unique_name); + g_free (session); +} + +static gchar * +authentication_agent_new_cookie (AuthenticationAgent *agent) +{ + static gint counter = 0; + + /* TODO: use a more random-looking cookie */ + + return g_strdup_printf ("cookie%d", counter++); +} + static void authentication_agent_free (AuthenticationAgent *agent) { + /* cancel all active authentication sessions; use a copy of the list since + * callbacks will modify the list + */ + if (agent->active_sessions != NULL) + { + GList *l; + GList *active_sessions; + + active_sessions = g_list_copy (agent->active_sessions); + for (l = active_sessions; l != NULL; l = l->next) + { + AuthenticationSession *session = l->data; + + authentication_session_cancel (session); + } + g_list_free (active_sessions); + } + + g_object_unref (agent->object_proxy); + g_object_unref (agent->session); g_free (agent->object_path); g_free (agent->unique_system_bus_name); @@ -908,6 +1072,7 @@ authentication_agent_new (PolkitSubject *session, const gchar *object_path) { AuthenticationAgent *agent; + EggDBusConnection *system_bus; agent = g_new0 (AuthenticationAgent, 1); @@ -915,6 +1080,14 @@ authentication_agent_new (PolkitSubject *session, agent->object_path = g_strdup (object_path); agent->unique_system_bus_name = g_strdup (unique_system_bus_name); + system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + agent->object_proxy = egg_dbus_connection_get_object_proxy (system_bus, + agent->unique_system_bus_name, + agent->object_path); + + g_object_unref (system_bus); + return agent; } @@ -946,6 +1119,77 @@ get_authentication_agent_for_subject (PolkitBackendLocalAuthority *authority, return agent; } +static AuthenticationSession * +get_authentication_session_for_cookie (PolkitBackendLocalAuthority *authority, + const gchar *cookie) +{ + PolkitBackendLocalAuthorityPrivate *priv; + GHashTableIter hash_iter; + AuthenticationAgent *agent; + AuthenticationSession *result; + + result = NULL; + + /* TODO: perhaps use a hash on the cookie to speed this up */ + + priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority); + + g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent); + while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent)) + { + GList *l; + + for (l = agent->active_sessions; l != NULL; l = l->next) + { + AuthenticationSession *session = l->data; + + if (strcmp (session->cookie, cookie) == 0) + { + result = session; + goto out; + } + } + } + + out: + return result; +} + +static GList * +get_authentication_sessions_initiated_by_system_bus_unique_name (PolkitBackendLocalAuthority *authority, + const gchar *system_bus_unique_name) +{ + PolkitBackendLocalAuthorityPrivate *priv; + GHashTableIter hash_iter; + AuthenticationAgent *agent; + GList *result; + + result = NULL; + + /* TODO: perhaps use a hash on the cookie to speed this up */ + + priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (authority); + + g_hash_table_iter_init (&hash_iter, priv->hash_session_to_authentication_agent); + while (g_hash_table_iter_next (&hash_iter, NULL, (gpointer) &agent)) + { + GList *l; + + for (l = agent->active_sessions; l != NULL; l = l->next) + { + AuthenticationSession *session = l->data; + + if (strcmp (session->initiated_by_system_bus_unique_name, system_bus_unique_name) == 0) + { + result = g_list_prepend (result, session); + } + } + } + + return result; +} + + static AuthenticationAgent * get_authentication_agent_by_unique_system_bus_name (PolkitBackendLocalAuthority *authority, const gchar *unique_system_bus_name) @@ -970,21 +1214,139 @@ get_authentication_agent_by_unique_system_bus_name (PolkitBackendLocalAuthority } static void +authentication_agent_begin_callback (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + _PolkitAgentAuthenticationAgent *agent_dbus = _POLKIT_AGENT_AUTHENTICATION_AGENT (source_object); + AuthenticationSession *session = user_data; + GError *error; + gboolean gained_authorization; + + error = NULL; + if (!_polkit_agent_authentication_agent_begin_authentication_finish (agent_dbus, + res, + &error)) + { + g_warning ("Error performing authentication: %s", error->message); + g_error_free (error); + + gained_authorization = FALSE; + } + else + { + gained_authorization = session->is_authenticated; + + g_debug ("Authentication complete, is_authenticated = %d", session->is_authenticated); + } + + session->agent->active_sessions = g_list_remove (session->agent->active_sessions, session); + + session->callback (session->agent, + session->subject, + session->user_of_subject, + session->authority, + session->action_id, + session->implicit_authorization, + gained_authorization, + session->user_data); + + authentication_session_free (session); +} + +static void authentication_agent_initiate_challenge (AuthenticationAgent *agent, PolkitSubject *subject, + PolkitIdentity *user_of_subject, + PolkitBackendLocalAuthority *authority, const gchar *action_id, + PolkitSubject *caller, PolkitImplicitAuthorization implicit_authorization, AuthenticationAgentCallback callback, gpointer user_data) { - /* TODO */ - - callback (agent, - subject, - action_id, - implicit_authorization, - FALSE, - user_data); + AuthenticationSession *session; + _PolkitAgentAuthenticationAgent *agent_dbus; + gchar *cookie; + GList *l; + GList *identities; + EggDBusArraySeq *real_identities; + + cookie = authentication_agent_new_cookie (agent); + + /* TODO: add uid 0 OR users in wheel group depending on value of @implicit_authorization */ + identities = g_list_prepend (NULL, g_object_ref (user_of_subject)); + + session = authentication_session_new (agent, + cookie, + subject, + user_of_subject, + authority, + identities, + action_id, + polkit_system_bus_name_get_name (POLKIT_SYSTEM_BUS_NAME (caller)), + implicit_authorization, + callback, + user_data); + + agent->active_sessions = g_list_prepend (agent->active_sessions, session); + + agent_dbus = _POLKIT_AGENT_QUERY_INTERFACE_AUTHENTICATION_AGENT (agent->object_proxy); + + real_identities = egg_dbus_array_seq_new (EGG_DBUS_TYPE_STRUCTURE, g_object_unref, NULL, NULL); + for (l = identities; l != NULL; l = l->next) + { + PolkitIdentity *identity = POLKIT_IDENTITY (l->data); + egg_dbus_array_seq_add (real_identities, polkit_identity_get_real (identity)); + } + + session->call_id = _polkit_agent_authentication_agent_begin_authentication (agent_dbus, + EGG_DBUS_CALL_FLAGS_NONE, + action_id, + session->cookie, + real_identities, + NULL, + authentication_agent_begin_callback, + session); + + g_list_foreach (identities, (GFunc) g_object_unref, NULL); + g_list_free (identities); + g_object_unref (real_identities); + g_free (cookie); +} + +static void +authentication_agent_cancel_callback (GObject *source_object, + GAsyncResult *res, + gpointer user_data) +{ + _PolkitAgentAuthenticationAgent *agent_dbus = _POLKIT_AGENT_AUTHENTICATION_AGENT (source_object); + + _polkit_agent_authentication_agent_cancel_authentication_finish (agent_dbus, + res, + NULL); +} + +static void +authentication_session_cancel (AuthenticationSession *session) +{ + EggDBusConnection *system_bus; + _PolkitAgentAuthenticationAgent *agent_dbus; + + system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM); + + agent_dbus = _POLKIT_AGENT_QUERY_INTERFACE_AUTHENTICATION_AGENT (session->agent->object_proxy); + + _polkit_agent_authentication_agent_cancel_authentication (agent_dbus, + EGG_DBUS_CALL_FLAGS_NONE, + session->cookie, + NULL, + authentication_agent_cancel_callback, + NULL); + + egg_dbus_connection_pending_call_cancel (system_bus, session->call_id); + + g_object_unref (system_bus); } /* ---------------------------------------------------------------------------------------------------- */ @@ -1127,6 +1489,97 @@ polkit_backend_local_authority_unregister_authentication_agent (PolkitBackendAut /* ---------------------------------------------------------------------------------------------------- */ static void +polkit_backend_local_authority_authentication_agent_response (PolkitBackendAuthority *authority, + const gchar *cookie, + PolkitIdentity *identity, + PolkitBackendPendingCall *pending_call) +{ + PolkitBackendLocalAuthority *local_authority; + PolkitBackendLocalAuthorityPrivate *priv; + PolkitSubject *caller; + PolkitIdentity *user_of_caller; + gchar *identity_str; + GError *error; + AuthenticationSession *session; + GList *l; + + local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority); + priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority); + + error = NULL; + user_of_caller = NULL; + + identity_str = polkit_identity_to_string (identity); + + g_debug ("In authentication_agent_response for cookie '%s' and identity %s", + cookie, + identity_str); + + caller = polkit_backend_pending_call_get_caller (pending_call); + + user_of_caller = polkit_backend_session_monitor_get_user_for_subject (priv->session_monitor, + caller, + &error); + if (error != NULL) + { + polkit_backend_pending_call_return_gerror (pending_call, error); + g_error_free (error); + goto out; + } + + /* only uid 0 is allowed to invoke this method */ + if (!POLKIT_IS_UNIX_USER (user_of_caller) || polkit_unix_user_get_uid (POLKIT_UNIX_USER (user_of_caller)) != 0) + { + polkit_backend_pending_call_return_error (pending_call, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "Only uid 0 may invoke this method. This incident has been logged."); + goto out; + } + + /* find the authentication session */ + session = get_authentication_session_for_cookie (local_authority, cookie); + if (session == NULL) + { + polkit_backend_pending_call_return_error (pending_call, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "No session for cookie"); + goto out; + } + + /* check that the authentication identity was one of the possibilities we allowed */ + for (l = session->identities; l != NULL; l = l->next) + { + PolkitIdentity *i = POLKIT_IDENTITY (l->data); + + if (polkit_identity_equal (i, identity)) + break; + } + if (l == NULL) + { + polkit_backend_pending_call_return_error (pending_call, + POLKIT_ERROR, + POLKIT_ERROR_FAILED, + "The authenticated identity is wrong"); + goto out; + } + + /* checks out, mark the session as authenticated */ + session->is_authenticated = TRUE; + + polkit_backend_authority_authentication_agent_response_finish (pending_call); + + out: + g_free (identity_str); + + if (user_of_caller != NULL) + g_object_unref (user_of_caller); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void polkit_backend_local_authority_system_bus_name_owner_changed (PolkitBackendAuthority *authority, const gchar *name, const gchar *old_owner, @@ -1134,15 +1587,18 @@ polkit_backend_local_authority_system_bus_name_owner_changed (PolkitBackendAutho { PolkitBackendLocalAuthority *local_authority; PolkitBackendLocalAuthorityPrivate *priv; - AuthenticationAgent *agent; local_authority = POLKIT_BACKEND_LOCAL_AUTHORITY (authority); priv = POLKIT_BACKEND_LOCAL_AUTHORITY_GET_PRIVATE (local_authority); - //g_debug ("name-owner-changed: '%s' '%s' '%s'", name, old_owner, new_owner); + g_debug ("name-owner-changed: '%s' '%s' '%s'", name, old_owner, new_owner); if (name[0] == ':' && strlen (new_owner) == 0) { + AuthenticationAgent *agent; + GList *sessions; + GList *l; + agent = get_authentication_agent_by_unique_system_bus_name (local_authority, name); if (agent != NULL) { @@ -1154,6 +1610,15 @@ polkit_backend_local_authority_system_bus_name_owner_changed (PolkitBackendAutho /* this works because we have exactly one agent per session */ g_hash_table_remove (priv->hash_session_to_authentication_agent, agent->session); } + + sessions = get_authentication_sessions_initiated_by_system_bus_unique_name (local_authority, name); + for (l = sessions; l != NULL; l = l->next) + { + AuthenticationSession *session = l->data; + + authentication_session_cancel (session); + } + g_list_free (sessions); } } diff --git a/src/polkitbackend/polkitbackendserver.c b/src/polkitbackend/polkitbackendserver.c index 2414bde..d89cb37 100644 --- a/src/polkitbackend/polkitbackendserver.c +++ b/src/polkitbackend/polkitbackendserver.c @@ -473,6 +473,37 @@ polkit_backend_authority_unregister_authentication_agent_finish (PolkitBackendPe /* ---------------------------------------------------------------------------------------------------- */ static void +authority_handle_authentication_agent_response (_PolkitAuthority *instance, + const gchar *cookie, + _PolkitIdentity *real_identity, + EggDBusMethodInvocation *method_invocation) +{ + PolkitBackendServer *server = POLKIT_BACKEND_SERVER (instance); + PolkitBackendPendingCall *pending_call; + PolkitIdentity *identity; + + pending_call = _polkit_backend_pending_call_new (method_invocation, server); + + identity = polkit_identity_new_for_real (real_identity); + + g_object_set_data_full (G_OBJECT (pending_call), "identity", identity, (GDestroyNotify) g_object_unref); + + polkit_backend_authority_authentication_agent_response (server->authority, + cookie, + identity, + pending_call); +} + +void +polkit_backend_authority_authentication_agent_response_finish (PolkitBackendPendingCall *pending_call) +{ + _polkit_authority_handle_authentication_agent_response_finish (_polkit_backend_pending_call_get_method_invocation (pending_call)); + g_object_unref (pending_call); +} + +/* ---------------------------------------------------------------------------------------------------- */ + +static void authority_iface_init (_PolkitAuthorityIface *authority_iface) { authority_iface->handle_enumerate_actions = authority_handle_enumerate_actions; @@ -484,4 +515,5 @@ authority_iface_init (_PolkitAuthorityIface *authority_iface) authority_iface->handle_remove_authorization = authority_handle_remove_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; } |