summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--data/org.freedesktop.PolicyKit1.AuthenticationAgent.xml6
-rw-r--r--data/org.freedesktop.PolicyKit1.Authority.xml11
-rw-r--r--src/polkit/polkitauthority.c104
-rw-r--r--src/polkit/polkitauthority.h17
-rw-r--r--src/polkitagent/Makefile.am3
-rw-r--r--src/polkitagent/polkitagentauthenticationagent.c50
-rw-r--r--src/polkitagent/polkitagentauthenticationagent.h30
-rw-r--r--src/polkitagent/polkitagentauthenticationsession.c2
-rw-r--r--src/polkitagent/polkitagenthelper.c60
-rw-r--r--src/polkitbackend/Makefile.am40
-rw-r--r--src/polkitbackend/polkitbackendauthority.c13
-rw-r--r--src/polkitbackend/polkitbackendauthority.h13
-rw-r--r--src/polkitbackend/polkitbackendlocalauthority.c487
-rw-r--r--src/polkitbackend/polkitbackendserver.c32
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;
}