PolicyKit: Branch 'master'
David Zeuthen
david at kemper.freedesktop.org
Fri Jan 30 17:25:21 PST 2009
src/polkitagent/Makefile.am | 8
src/polkitagent/polkitagent.h | 4
src/polkitagent/polkitagentauthenticationagent.c | 294 -------------
src/polkitagent/polkitagentauthenticationagent.h | 68 ---
src/polkitagent/polkitagentauthenticationsession.c | 362 ----------------
src/polkitagent/polkitagentauthenticationsession.h | 139 ------
src/polkitagent/polkitagenthelper.c | 2
src/polkitagent/polkitagentlistener.c | 439 ++++++++++++++++++++
src/polkitagent/polkitagentlistener.h | 95 ++++
src/polkitagent/polkitagentsession.c | 458 +++++++++++++++++++++
src/polkitagent/polkitagentsession.h | 53 ++
src/polkitagent/polkitagenttypes.h | 9
src/polkitbackend/polkitbackendlocalauthority.c | 8
13 files changed, 1063 insertions(+), 876 deletions(-)
New commits:
commit 914df46f860c28ea29dc93d99e136fe99800a9e7
Author: David Zeuthen <davidz at redhat.com>
Date: Fri Jan 30 20:23:02 2009 -0500
rework API of polkitagent
still a work in progress, supporting multiple identities (wheel style auth) is 99% complete.
diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am
index b792f93..7d0d857 100644
--- a/src/polkitagent/Makefile.am
+++ b/src/polkitagent/Makefile.am
@@ -37,15 +37,15 @@ libpolkit_agent_1includedir=$(includedir)/polkit-1/polkitagent
libpolkit_agent_1include_HEADERS = \
polkitagent.h \
polkitagenttypes.h \
- polkitagentauthenticationsession.h \
- polkitagentauthenticationagent.h \
+ polkitagentsession.h \
+ polkitagentlistener.h \
$(NULL)
libpolkit_agent_1_la_SOURCES = \
polkitagent.h \
polkitagenttypes.h \
- polkitagentauthenticationsession.h polkitagentauthenticationsession.c \
- polkitagentauthenticationagent.h polkitagentauthenticationagent.c \
+ polkitagentsession.h polkitagentsession.c \
+ polkitagentlistener.h polkitagentlistener.c \
$(BUILT_SOURCES) \
$(NULL)
diff --git a/src/polkitagent/polkitagent.h b/src/polkitagent/polkitagent.h
index 0bc8fdc..4b56683 100644
--- a/src/polkitagent/polkitagent.h
+++ b/src/polkitagent/polkitagent.h
@@ -23,8 +23,8 @@
#define __POLKIT_AGENT_H
#define _POLKIT_AGENT_INSIDE_POLKIT_AGENT_H 1
-#include <polkitagent/polkitagentauthenticationagent.h>
-#include <polkitagent/polkitagentauthenticationsession.h>
+#include <polkitagent/polkitagentlistener.h>
+#include <polkitagent/polkitagentsession.h>
#undef _POLKIT_AGENT_INSIDE_POLKIT_AGENT_H
#endif /* __POLKIT_AGENT_H */
diff --git a/src/polkitagent/polkitagentauthenticationagent.c b/src/polkitagent/polkitagentauthenticationagent.c
deleted file mode 100644
index 9917706..0000000
--- a/src/polkitagent/polkitagentauthenticationagent.c
+++ /dev/null
@@ -1,294 +0,0 @@
-/*
- * 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 at redhat.com>
- */
-
-#include "config.h"
-
-#include <polkit/polkitprivate.h>
-#include "_polkitagentbindings.h"
-
-#include "polkitagentauthenticationagent.h"
-
-/**
- * SECTION:polkitagentauthenticationagent
- * @title: PolkitAgentAuthenticationAgent
- * @short_description: Authentication Agent
- *
- * The #PolkitAgentAuthenticationAgent class is used for implementing authentication agents.
- */
-
-struct _PolkitAgentAuthenticationAgent
-{
- GObject parent_instance;
-
- EggDBusConnection *system_bus;
-
- EggDBusObjectProxy *authority_proxy;
-
- PolkitAuthority *authority;
-
- gboolean is_registered;
-
- PolkitAgentAuthenticationAgentBeginFunc begin_func;
- PolkitAgentAuthenticationAgentCancelFunc cancel_func;
- gpointer user_data;
-};
-
-struct _PolkitAgentAuthenticationAgentClass
-{
- GObjectClass parent_class;
-
-};
-
-static void authentication_agent_iface_init (_PolkitAgentAuthenticationAgentIface *agent_iface);
-
-G_DEFINE_TYPE_WITH_CODE (PolkitAgentAuthenticationAgent, polkit_agent_authentication_agent, G_TYPE_OBJECT,
- G_IMPLEMENT_INTERFACE (_POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT,
- authentication_agent_iface_init)
- );
-
-static gboolean
-polkit_agent_authentication_agent_register (PolkitAgentAuthenticationAgent *agent,
- GError **error)
-{
- GError *local_error;
- gboolean ret;
-
- ret = FALSE;
-
- local_error = NULL;
- if (!polkit_authority_register_authentication_agent_sync (agent->authority,
- "/org/freedesktop/PolicyKit1/AuthenticationAgent",
- NULL,
- &local_error))
- {
- g_warning ("Unable to register authentication agent: %s", local_error->message);
- g_propagate_error (error, local_error);
- }
- else
- {
- agent->is_registered = TRUE;
- ret = TRUE;
- }
-
- return ret;
-}
-
-static void
-name_owner_notify (EggDBusObjectProxy *object_proxy,
- GParamSpec *pspec,
- gpointer user_data)
-{
- PolkitAgentAuthenticationAgent *agent = POLKIT_AGENT_AUTHENTICATION_AGENT (user_data);
- gchar *owner;
-
- owner = egg_dbus_object_proxy_get_name_owner (agent->authority_proxy);
-
- if (owner == NULL)
- {
- g_printerr ("PolicyKit daemon disconnected from the bus.\n");
-
- if (agent->is_registered)
- g_printerr ("We are no longer a registered authentication agent.\n");
-
- agent->is_registered = FALSE;
- }
- else
- {
- /* only register if there is a name owner */
- if (!agent->is_registered)
- {
- GError *error;
-
- g_printerr ("PolicyKit daemon reconnected to bus.\n");
- g_printerr ("Attempting to re-register as an authentication agent.\n");
-
- error = NULL;
- if (polkit_agent_authentication_agent_register (agent, &error))
- {
- g_printerr ("We are now a registered authentication agent.\n");
- }
- else
- {
- g_printerr ("Failed to register as an authentication agent: %s\n", error->message);
- g_error_free (error);
- }
- }
- }
-
- g_free (owner);
-}
-
-static void
-polkit_agent_authentication_agent_init (PolkitAgentAuthenticationAgent *agent)
-{
- GError *error;
-
- agent->system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
-
- egg_dbus_connection_register_interface (agent->system_bus,
- "/org/freedesktop/PolicyKit1/AuthenticationAgent",
- _POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT,
- G_OBJECT (agent),
- G_TYPE_INVALID);
-
- agent->authority = polkit_authority_get ();
-
- /* the only use of this proxy is to re-register with the polkit daemon
- * if it jumps off the bus and comes back (which is useful for debugging)
- */
- agent->authority_proxy = egg_dbus_connection_get_object_proxy (agent->system_bus,
- "org.freedesktop.PolicyKit1",
- "/org/freedesktop/PolicyKit1/Authority");
-
- g_signal_connect (agent->authority_proxy,
- "notify::name-owner",
- G_CALLBACK (name_owner_notify),
- agent);
-
- error = NULL;
- if (!polkit_agent_authentication_agent_register (agent, &error))
- {
- g_printerr ("Failed to register as an authentication agent: %s\n", error->message);
- g_error_free (error);
- }
-}
-
-static void
-polkit_agent_authentication_agent_finalize (GObject *object)
-{
- PolkitAgentAuthenticationAgent *agent = POLKIT_AGENT_AUTHENTICATION_AGENT (object);
- GError *error;
-
- error = NULL;
- if (!polkit_authority_unregister_authentication_agent_sync (agent->authority,
- "/org/freedesktop/PolicyKit1/AuthenticationAgent",
- NULL,
- &error))
- {
- g_warning ("Error unregistering authentication agent: %s", error->message);
- g_error_free (error);
- }
-
- g_object_unref (agent->authority);
-
- g_object_unref (agent->authority_proxy);
-
- g_object_unref (agent->system_bus);
-
- if (G_OBJECT_CLASS (polkit_agent_authentication_agent_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (polkit_agent_authentication_agent_parent_class)->finalize (object);
-}
-
-static void
-polkit_agent_authentication_agent_class_init (PolkitAgentAuthenticationAgentClass *klass)
-{
- GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->finalize = polkit_agent_authentication_agent_finalize;
-}
-
-PolkitAgentAuthenticationAgent *
-polkit_agent_authentication_agent_new (PolkitAgentAuthenticationAgentBeginFunc begin_func,
- PolkitAgentAuthenticationAgentCancelFunc cancel_func,
- gpointer user_data)
-{
- PolkitAgentAuthenticationAgent *agent;
-
- agent = POLKIT_AGENT_AUTHENTICATION_AGENT (g_object_new (POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT, NULL));
-
- agent->begin_func = begin_func;
- agent->cancel_func = cancel_func;
- agent->user_data = user_data;
-
- return agent;
-}
-
-static void
-handle_begin_authentication (_PolkitAgentAuthenticationAgent *instance,
- const gchar *action_id,
- const gchar *cookie,
- EggDBusArraySeq *identities,
- EggDBusMethodInvocation *method_invocation)
-{
- PolkitAgentAuthenticationAgent *agent = POLKIT_AGENT_AUTHENTICATION_AGENT (instance);
- GList *list;
- guint n;
- GError *error;
-
- list = NULL;
- for (n = 0; n < identities->size; n++)
- {
- _PolkitIdentity *real_identity = _POLKIT_IDENTITY (identities->data.v_ptr[n]);
-
- list = g_list_prepend (list, polkit_identity_new_for_real (real_identity));
- }
-
- list = g_list_reverse (list);
-
- error = NULL;
-
- 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);
- }
- else
- {
- _polkit_agent_authentication_agent_handle_begin_authentication_finish (method_invocation);
- }
-}
-
-
-static void
-handle_cancel_authentication (_PolkitAgentAuthenticationAgent *instance,
- const gchar *cookie,
- EggDBusMethodInvocation *method_invocation)
-{
- PolkitAgentAuthenticationAgent *agent = POLKIT_AGENT_AUTHENTICATION_AGENT (instance);
-
- agent->cancel_func (agent,
- cookie,
- agent->user_data);
-
- _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_cancel_authentication = handle_cancel_authentication;
-}
diff --git a/src/polkitagent/polkitagentauthenticationagent.h b/src/polkitagent/polkitagentauthenticationagent.h
deleted file mode 100644
index b076f8c..0000000
--- a/src/polkitagent/polkitagentauthenticationagent.h
+++ /dev/null
@@ -1,68 +0,0 @@
-/*
- * 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 at redhat.com>
- */
-
-#ifndef __POLKIT_AGENT_AUTHENTICATION_AGENT_H
-#define __POLKIT_AGENT_AUTHENTICATION_AGENT_H
-
-#include <polkit/polkit.h>
-#include <polkitagent/polkitagenttypes.h>
-
-G_BEGIN_DECLS
-
-#define POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT (polkit_agent_authentication_agent_get_type ())
-#define POLKIT_AGENT_AUTHENTICATION_AGENT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT, PolkitAgentAuthenticationAgent))
-#define POLKIT_AGENT_AUTHENTICATION_AGENT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT, PolkitAgentAuthenticationAgentClass))
-#define POLKIT_AGENT_AUTHENTICATION_AGENT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT,PolkitAgentAuthenticationAgentClass))
-#define POLKIT_AGENT_IS_AUTHENTICATION_AGENT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT))
-#define POLKIT_AGENT_IS_AUTHENTICATION_AGENT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT))
-
-#if 0
-typedef struct _PolkitAgentAuthenticationAgent PolkitAgentAuthenticationAgent;
-#endif
-typedef struct _PolkitAgentAuthenticationAgentClass PolkitAgentAuthenticationAgentClass;
-
-/* TODO: we probably want to express this interface in another way but this is good enough for now */
-
-typedef void (*PolkitAgentAuthenticationAgentBeginFunc) (PolkitAgentAuthenticationAgent *agent,
- const gchar *action_id,
- const gchar *cookie,
- 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,
- PolkitAgentAuthenticationAgentCancelFunc cancel_func,
- gpointer user_data);
-
-void polkit_agent_authentication_agent_finish (PolkitAgentAuthenticationAgent *agent,
- gpointer pending_call,
- GError *error);
-
-/* --- */
-
-G_END_DECLS
-
-#endif /* __POLKIT_AGENT_AUTHENTICATION_AGENT_H */
diff --git a/src/polkitagent/polkitagentauthenticationsession.c b/src/polkitagent/polkitagentauthenticationsession.c
deleted file mode 100644
index 8d1a165..0000000
--- a/src/polkitagent/polkitagentauthenticationsession.c
+++ /dev/null
@@ -1,362 +0,0 @@
-/*
- * 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 at redhat.com>
- */
-
-/* TODO: This whole class needs to be rewritten so it uses the main loop etc. etc.
- *
- * And we REALLY REALLY really really should use signals instead of callbacks...
- */
-
-/**
- * SECTION:polkitagentauthenticationsession
- * @title: PolkitAgentAuthenticationSession
- * @short_description: Authentcation Sessions
- *
- * The #PolkitAgentAuthenticationSession class is used for implementing authentication agents.
- */
-
-
-/* for getline(), see below */
-#define _GNU_SOURCE
-
-#include "config.h"
-#include <string.h>
-#include <stdlib.h>
-#include <stdio.h>
-#include <sys/types.h>
-#include <sys/wait.h>
-#include <pwd.h>
-
-#include "polkitagentauthenticationsession.h"
-
-struct _PolkitAgentAuthenticationSession
-{
- GObject parent_instance;
-
- gchar *cookie;
- PolkitIdentity *identity;
-
- int child_stdin;
- int child_stdout;
- GPid child_pid;
- FILE *child_stdout_f;
-
- int child_watch_id;
- int io_watch_id;
-
- gboolean success;
- gboolean helper_is_running;
-
- PolkitAgentAuthenticationSessionConversationPromptEchoOff func_prompt_echo_off;
- PolkitAgentAuthenticationSessionConversationPromptEchoOn func_prompt_echo_on;
- PolkitAgentAuthenticationSessionConversationErrorMessage func_error_message;
- PolkitAgentAuthenticationSessionConversationTextInfo func_text_info;
- PolkitAgentAuthenticationSessionDone func_done;
- void *user_data;
-};
-
-struct _PolkitAgentAuthenticationSessionClass
-{
- GObjectClass parent_class;
-
-};
-
-G_DEFINE_TYPE (PolkitAgentAuthenticationSession, polkit_agent_authentication_session, G_TYPE_OBJECT);
-
-static void
-polkit_agent_authentication_session_init (PolkitAgentAuthenticationSession *session)
-{
-}
-
-static void
-polkit_agent_authentication_session_finalize (GObject *object)
-{
- PolkitAgentAuthenticationSession *session;
-
- session = POLKIT_AGENT_AUTHENTICATION_SESSION (object);
-
- g_free (session->cookie);
- if (session->identity != NULL)
- g_object_unref (session->identity);
-
- if (G_OBJECT_CLASS (polkit_agent_authentication_session_parent_class)->finalize != NULL)
- G_OBJECT_CLASS (polkit_agent_authentication_session_parent_class)->finalize (object);
-}
-
-static void
-polkit_agent_authentication_session_class_init (PolkitAgentAuthenticationSessionClass *klass)
-{
- GObjectClass *gobject_class;
-
- gobject_class = G_OBJECT_CLASS (klass);
-
- gobject_class->finalize = polkit_agent_authentication_session_finalize;
-
-
-
-}
-
-PolkitAgentAuthenticationSession *
-polkit_agent_authentication_session_new (PolkitIdentity *identity,
- const gchar *cookie)
-{
- PolkitAgentAuthenticationSession *session;
-
- session = POLKIT_AGENT_AUTHENTICATION_SESSION (g_object_new (POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION, NULL));
-
- session->identity = g_object_ref (identity);
- session->cookie = g_strdup (cookie);
-
- return session;
-}
-
-void
-polkit_agent_authentication_session_set_functions (PolkitAgentAuthenticationSession *session,
- PolkitAgentAuthenticationSessionConversationPromptEchoOff func_prompt_echo_off,
- PolkitAgentAuthenticationSessionConversationPromptEchoOn func_prompt_echo_on,
- PolkitAgentAuthenticationSessionConversationErrorMessage func_error_message,
- PolkitAgentAuthenticationSessionConversationTextInfo func_text_info,
- PolkitAgentAuthenticationSessionDone func_done,
- void *user_data)
-{
- session->func_prompt_echo_off = func_prompt_echo_off;
- session->func_prompt_echo_on = func_prompt_echo_on;
- session->func_error_message = func_error_message;
- session->func_text_info = func_text_info;
- session->func_done = func_done;
- session->user_data = user_data;
-}
-
-static void
-child_watch_func (GPid pid, gint status, gpointer user_data)
-{
- PolkitAgentAuthenticationSession *session = POLKIT_AGENT_AUTHENTICATION_SESSION (user_data);
- gint exit_code;
- gboolean input_was_bogus;
-
- g_return_if_fail (session->helper_is_running);
-
- exit_code = WEXITSTATUS (status);
-
- g_debug ("pid %d terminated", pid);
- waitpid (pid, &status, 0);
-
- if (exit_code >= 2)
- input_was_bogus = TRUE;
- else
- input_was_bogus = FALSE;
-
- session->success = (exit_code == 0);
- session->helper_is_running = FALSE;
- session->func_done (session, session->success, input_was_bogus, session->user_data);
-}
-
-static gboolean
-io_watch_have_data (GIOChannel *channel, GIOCondition condition, gpointer user_data)
-{
- PolkitAgentAuthenticationSession *session = POLKIT_AGENT_AUTHENTICATION_SESSION (user_data);
- char *line;
- size_t line_len;
- gchar *id;
- size_t id_len;
- gchar *response;
- gchar *response_prefix;
- int fd;
-
- g_return_val_if_fail (session->helper_is_running, FALSE);
-
- fd = g_io_channel_unix_get_fd (channel);
-
- line = NULL;
- line_len = 0;
-
- /* TODO: getline is GNU only, see kit_getline() in old polkit */
- while (getline (&line, &line_len, session->child_stdout_f) != -1)
- {
- if (strlen (line) > 0 && line[strlen (line) - 1] == '\n')
- line[strlen (line) - 1] = '\0';
-
- response = NULL;
- response_prefix = NULL;
-
- id = "PAM_PROMPT_ECHO_OFF ";
- if (g_str_has_prefix (line, id))
- {
- id_len = strlen (id);
- response_prefix = "";
- response = session->func_prompt_echo_off (session,
- line + id_len,
- session->user_data);
- goto processed;
- }
-
- id = "PAM_PROMPT_ECHO_ON ";
- if (g_str_has_prefix (line, id))
- {
- id_len = strlen (id);
- response_prefix = "";
- response = session->func_prompt_echo_on (session,
- line + id_len,
- session->user_data);
- goto processed;
- }
-
- id = "PAM_ERROR_MSG ";
- if (g_str_has_prefix (line, id))
- {
- id_len = strlen (id);
- session->func_error_message (session,
- line + id_len,
- session->user_data);
- goto processed;
- }
-
- id = "PAM_TEXT_INFO ";
- if (g_str_has_prefix (line, id))
- {
- id_len = strlen (id);
- session->func_text_info (session,
- line + id_len,
- session->user_data);
- goto processed;
- }
-
- processed:
- if (response != NULL && response_prefix != NULL)
- {
- char *buf;
- gboolean add_newline;
-
- /* add a newline if there isn't one already... */
- add_newline = FALSE;
- if (response[strlen (response) - 1] != '\n')
- {
- add_newline = TRUE;
- }
- buf = g_strdup_printf ("%s%s%c",
- response_prefix,
- response,
- add_newline ? '\n' : '\0');
- write (session->child_stdin, buf, strlen (buf));
- g_free (buf);
- g_free (response);
- }
- }
-
- if (line != NULL)
- free (line);
-
- return FALSE;
-}
-
-gboolean
-polkit_agent_authentication_session_initiate_auth (PolkitAgentAuthenticationSession *session)
-{
- uid_t uid;
- GError *error;
- gchar *helper_argv[4];
- GIOChannel *channel;
- gboolean ret;
- struct passwd *passwd;
-
- ret = FALSE;
-
- /* TODO: also support authorization for other kinds of identities */
- if (!POLKIT_IS_UNIX_USER (session->identity))
- {
- g_warning ("Unsupported identity type");
- goto error;
- }
-
- uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (session->identity));
-
- passwd = getpwuid (uid);
- if (passwd == NULL)
- {
- g_warning ("No user with uid %d", uid);
- goto error;
- }
-
- 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;
-
- session->child_stdin = -1;
- session->child_stdout = -1;
-
- error = NULL;
- if (!g_spawn_async_with_pipes (NULL,
- (char **) helper_argv,
- NULL,
- G_SPAWN_DO_NOT_REAP_CHILD |
- 0,//G_SPAWN_STDERR_TO_DEV_NULL,
- NULL,
- NULL,
- &session->child_pid,
- &session->child_stdin,
- &session->child_stdout,
- NULL,
- &error))
- {
- g_warning ("Cannot spawn helper: %s\n", error->message);
- g_error_free (error);
- goto error;
- }
-
- session->child_watch_id = g_child_watch_add (session->child_pid, child_watch_func, session);
-
- channel = g_io_channel_unix_new (session->child_stdout);
- session->io_watch_id = g_io_add_watch (channel, G_IO_IN, io_watch_have_data, session);
- g_io_channel_unref (channel);
-
- /* so we can use getline... */
- session->child_stdout_f = fdopen (session->child_stdout, "r");
-
- session->success = FALSE;
-
- session->helper_is_running = TRUE;
-
- ret = TRUE;
-
-error:
-
- return ret;
-}
-
-
-void
-polkit_agent_authentication_session_cancel (PolkitAgentAuthenticationSession *session)
-{
- GPid pid;
-
- g_return_if_fail (session->helper_is_running);
-
- pid = session->child_pid;
- session->child_pid = 0;
- if (pid > 0)
- {
- int status;
- kill (pid, SIGTERM);
- waitpid (pid, &status, 0);
- session->helper_is_running = FALSE;
- }
- session->func_done (session, FALSE, FALSE, session->user_data);
-}
diff --git a/src/polkitagent/polkitagentauthenticationsession.h b/src/polkitagent/polkitagentauthenticationsession.h
deleted file mode 100644
index b1239fe..0000000
--- a/src/polkitagent/polkitagentauthenticationsession.h
+++ /dev/null
@@ -1,139 +0,0 @@
-/*
- * 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 at redhat.com>
- */
-
-#ifndef __POLKIT_AGENT_AUTHENTICATION_SESSION_H
-#define __POLKIT_AGENT_AUTHENTICATION_SESSION_H
-
-#include <polkit/polkit.h>
-#include <polkitagent/polkitagenttypes.h>
-
-G_BEGIN_DECLS
-
-#define POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION (polkit_agent_authentication_session_get_type())
-#define POLKIT_AGENT_AUTHENTICATION_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION, PolkitAgentAuthenticationSession))
-#define POLKIT_AGENT_AUTHENTICATION_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION, PolkitAgentAuthenticationSessionClass))
-#define POLKIT_AGENT_AUTHENTICATION_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION, PolkitAgentAuthenticationSessionClass))
-#define POLKIT_AGENT_IS_AUTHENTICATION_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION))
-#define POLKIT_AGENT_IS_AUTHENTICATION_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_AGENT_TYPE_AUTHENTICATION_SESSION))
-
-/**
- * PolkitAgentAuthenticationSessionConversationPromptEchoOff:
- * @session: A #PolkitAgentAuthenticationSession.
- * @prompt: prompt passed by the authentication layer; do not free this string
- * @user_data: user data pointer as passed into polkit_agent_authorization_session_set_functions()
- *
- * Type for callback function that is invoked when the authentication
- * layer needs to ask the user a secret and the UI should NOT echo what
- * the user types on the screen.
- *
- * Returns: the answer obtained from the user; must be allocated with
- * malloc(3) and will be freed by the #PolkitAgentAuthenticationSession class.
- **/
-typedef char* (*PolkitAgentAuthenticationSessionConversationPromptEchoOff) (PolkitAgentAuthenticationSession *session,
- const gchar *prompt,
- gpointer user_data);
-
-/**
- * PolkitAgentAuthenticationSessionConversationPromptEchoOn:
- * @session: A #PolkitAgentAuthenticationSession.
- * @prompt: prompt passed by the authentication layer; do not free this string
- * @user_data: user data pointer as passed into polkit_agent_authorization_session_set_functions()
- *
- * Type for callback function that is invoked when the authentication
- * layer needs to ask the user a secret and the UI should echo what
- * the user types on the screen.
- *
- * Returns: the answer obtained from the user; must be allocated with
- * malloc(3) and will be freed by the #PolkitAgentAuthenticationSession class.
- **/
-typedef char* (*PolkitAgentAuthenticationSessionConversationPromptEchoOn) (PolkitAgentAuthenticationSession *session,
- const gchar *prompt,
- gpointer user_data);
-
-/**
- * PolkitAgentAuthenticationSessionConversationErrorMessage:
- * @session: A #PolkitAgentAuthenticationSession.
- * @error_message: error message passed by the authentication layer; do not free this string
- * @user_data: user data pointer as passed into polkit_agent_authorization_session_set_functions()
- *
- * Type for callback function that is invoked when the authentication
- * layer produces an error message that should be displayed in the UI.
- **/
-typedef void (*PolkitAgentAuthenticationSessionConversationErrorMessage) (PolkitAgentAuthenticationSession *session,
- const gchar *error_message,
- gpointer user_data);
-
-/**
- * PolkitAgentAuthenticationSessionConversationTextInfo:
- * @session: A #PolkitAgentAuthenticationSession.
- * @text_info: information passed by the authentication layer; do not free this string
- * @user_data: user data pointer as passed into polkit_agent_authorization_session_set_functions()
- *
- * Type for callback function that is invoked when the authentication
- * layer produces an informational message that should be displayed in
- * the UI.
- **/
-typedef void (*PolkitAgentAuthenticationSessionConversationTextInfo) (PolkitAgentAuthenticationSession *session,
- const gchar *text_info,
- gpointer user_data);
-
-/**
- * PolkitAgentAuthenticationSessionDone:
- * @session: A #PolkitAgentAuthenticationSession.
- * @gained_authorization: whether the authorization was obtained
- * @invalid_data: whether the input data was bogus (not including bad passwords)
- * @user_data: user data pointer as passed into polkit_agent_authorization_session_set_functions()
- *
- * This function is called when the granting process ends; either if
- * successful or if it was canceled using e.g. polkit_agent_authorization_session_cancel_auth().
- **/
-typedef void (*PolkitAgentAuthenticationSessionDone) (PolkitAgentAuthenticationSession *session,
- gboolean gained_authorization,
- gboolean invalid_data,
- gpointer user_data);
-
-
-#if 0
-typedef struct _PolkitAgentAuthenticationSession PolkitAgentAuthenticationSession;
-#endif
-typedef struct _PolkitAgentAuthenticationSessionClass PolkitAgentAuthenticationSessionClass;
-
-GType polkit_agent_authentication_session_get_type (void) G_GNUC_CONST;
-PolkitAgentAuthenticationSession *polkit_agent_authentication_session_new (PolkitIdentity *identity,
- const gchar *cookie);
-
-/* TODO: would be much nicer to use signals here */
-void polkit_agent_authentication_session_set_functions
- (PolkitAgentAuthenticationSession *session,
- PolkitAgentAuthenticationSessionConversationPromptEchoOff func_prompt_echo_off,
- PolkitAgentAuthenticationSessionConversationPromptEchoOn func_prompt_echo_on,
- PolkitAgentAuthenticationSessionConversationErrorMessage func_error_message,
- PolkitAgentAuthenticationSessionConversationTextInfo func_text_info,
- PolkitAgentAuthenticationSessionDone func_done,
- void *user_data);
-
-gboolean polkit_agent_authentication_session_initiate_auth (PolkitAgentAuthenticationSession *session);
-
-void polkit_agent_authentication_session_cancel (PolkitAgentAuthenticationSession *session);
-
-G_END_DECLS
-
-#endif /* __POLKIT_AGENT_AUTHENTICATION_SESSION_H */
diff --git a/src/polkitagent/polkitagenthelper.c b/src/polkitagent/polkitagenthelper.c
index d5844e5..b5181e5 100644
--- a/src/polkitagent/polkitagenthelper.c
+++ b/src/polkitagent/polkitagenthelper.c
@@ -40,7 +40,7 @@
* sensitive information.
*/
#undef PAH_DEBUG
-//#define PAH_DEBUG
+#define PAH_DEBUG
static gboolean send_dbus_message (const char *cookie, const char *user);
diff --git a/src/polkitagent/polkitagentlistener.c b/src/polkitagent/polkitagentlistener.c
new file mode 100644
index 0000000..05042aa
--- /dev/null
+++ b/src/polkitagent/polkitagentlistener.c
@@ -0,0 +1,439 @@
+/*
+ * 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 at redhat.com>
+ */
+
+#include "config.h"
+
+#include <polkit/polkitprivate.h>
+#include "_polkitagentbindings.h"
+
+#include "polkitagentlistener.h"
+
+/**
+ * SECTION:polkitagentlistener
+ * @title: PolkitAgentListener
+ * @short_description: Authentication Agent Listener
+ *
+ * The #PolkitAgentListener is an abstract base class used for implementing authentication agents.
+ */
+
+/* private class for exporting an interface D-Bus */
+
+#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), POLKIT_AGENT_TYPE_LISTENER, ServerClass))
+#define SERVER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), TYPE_SERVER, ServerClass))
+#define IS_SERVER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), TYPE_SERVER))
+#define IS_SERVER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), TYPE_SERVER))
+
+typedef struct _Server Server;
+typedef struct _ServerClass ServerClass;
+
+struct _Server
+{
+ GObject parent_instance;
+
+ EggDBusConnection *system_bus;
+
+ EggDBusObjectProxy *authority_proxy;
+
+ PolkitAuthority *authority;
+
+ gboolean is_registered;
+
+ PolkitAgentListener *listener;
+
+ gchar *session_id;
+ gchar *object_path;
+
+ GHashTable *cookie_to_pending_auth;
+
+};
+
+struct _ServerClass
+{
+ GObjectClass parent_class;
+
+};
+
+static GType server_get_type (void) G_GNUC_CONST;
+
+static void authentication_agent_iface_init (_PolkitAgentAuthenticationAgentIface *agent_iface);
+
+G_DEFINE_TYPE_WITH_CODE (Server, server, G_TYPE_OBJECT,
+ G_IMPLEMENT_INTERFACE (_POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT,
+ authentication_agent_iface_init)
+ );
+
+static gboolean
+server_register (Server *server,
+ GError **error)
+{
+ GError *local_error;
+ gboolean ret;
+
+ ret = FALSE;
+
+ local_error = NULL;
+ /* TODO: also pass server->session_id */
+ if (!polkit_authority_register_authentication_agent_sync (server->authority,
+ server->object_path,
+ NULL,
+ &local_error))
+ {
+ g_warning ("Unable to register authentication agent: %s", local_error->message);
+ g_propagate_error (error, local_error);
+ }
+ else
+ {
+ server->is_registered = TRUE;
+ ret = TRUE;
+ }
+
+ return ret;
+}
+
+static void
+name_owner_notify (EggDBusObjectProxy *object_proxy,
+ GParamSpec *pspec,
+ gpointer user_data)
+{
+ Server *server = SERVER (user_data);
+ gchar *owner;
+
+ owner = egg_dbus_object_proxy_get_name_owner (server->authority_proxy);
+
+ if (owner == NULL)
+ {
+ g_printerr ("PolicyKit daemon disconnected from the bus.\n");
+
+ if (server->is_registered)
+ g_printerr ("We are no longer a registered authentication agent.\n");
+
+ server->is_registered = FALSE;
+ }
+ else
+ {
+ /* only register if there is a name owner */
+ if (!server->is_registered)
+ {
+ GError *error;
+
+ g_printerr ("PolicyKit daemon reconnected to bus.\n");
+ g_printerr ("Attempting to re-register as an authentication agent.\n");
+
+ error = NULL;
+ if (server_register (server, &error))
+ {
+ g_printerr ("We are now a registered authentication agent.\n");
+ }
+ else
+ {
+ g_printerr ("Failed to register as an authentication agent: %s\n", error->message);
+ g_error_free (error);
+ }
+ }
+ }
+
+ g_free (owner);
+}
+
+static void
+server_init (Server *server)
+{
+ server->cookie_to_pending_auth = g_hash_table_new (g_str_hash, g_str_equal);
+
+ server->system_bus = egg_dbus_connection_get_for_bus (EGG_DBUS_BUS_TYPE_SYSTEM);
+
+ server->authority = polkit_authority_get ();
+
+ /* the only use of this proxy is to re-register with the polkit daemon
+ * if it jumps off the bus and comes back (which is useful for debugging)
+ */
+ server->authority_proxy = egg_dbus_connection_get_object_proxy (server->system_bus,
+ "org.freedesktop.PolicyKit1",
+ "/org/freedesktop/PolicyKit1/Authority");
+
+ g_signal_connect (server->authority_proxy,
+ "notify::name-owner",
+ G_CALLBACK (name_owner_notify),
+ server);
+}
+
+static void
+server_finalize (GObject *object)
+{
+ Server *server = SERVER (object);
+
+ if (server->is_registered)
+ {
+ GError *error;
+
+ error = NULL;
+ if (!polkit_authority_unregister_authentication_agent_sync (server->authority,
+ server->object_path,
+ NULL,
+ &error))
+ {
+ g_warning ("Error unregistering authentication agent: %s", error->message);
+ g_error_free (error);
+ }
+ }
+
+ g_free (server->session_id);
+ g_free (server->object_path);
+
+ g_object_unref (server->authority);
+
+ g_object_unref (server->authority_proxy);
+
+ g_object_unref (server->system_bus);
+
+ g_hash_table_unref (server->cookie_to_pending_auth);
+
+ if (G_OBJECT_CLASS (server_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (server_parent_class)->finalize (object);
+}
+
+static void
+server_class_init (ServerClass *klass)
+{
+ GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = server_finalize;
+}
+
+static void
+listener_died (gpointer user_data,
+ GObject *where_the_object_was)
+{
+ Server *server = SERVER (user_data);
+
+ g_object_unref (server);
+}
+
+void
+polkit_agent_export_listener (PolkitAgentListener *listener,
+ const gchar *session_id,
+ const gchar *object_path)
+{
+ Server *server;
+ GError *error;
+
+ server = SERVER (g_object_new (TYPE_SERVER, NULL));
+ server->session_id = g_strdup (session_id);
+ server->object_path = g_strdup (object_path);
+ server->listener = listener;
+
+ /* take a weak ref and kill server when listener dies */
+ g_object_weak_ref (G_OBJECT (server->listener), listener_died, server);
+
+ egg_dbus_connection_register_interface (server->system_bus,
+ server->object_path,
+ _POLKIT_AGENT_TYPE_AUTHENTICATION_AGENT,
+ G_OBJECT (server),
+ G_TYPE_INVALID);
+
+ error = NULL;
+ if (!server_register (server, &error))
+ {
+ g_printerr ("Failed to register as an authentication agent: %s\n", error->message);
+ g_printerr ("Will attempt to register when the PolicyKit daemon is back up\n");
+ g_error_free (error);
+ }
+}
+
+typedef struct
+{
+ Server *server;
+ gchar *cookie;
+ EggDBusMethodInvocation *method_invocation;
+ GCancellable *cancellable;
+} AuthData;
+
+static AuthData *
+auth_data_new (Server *server,
+ const gchar *cookie,
+ EggDBusMethodInvocation *method_invocation,
+ GCancellable *cancellable)
+{
+ AuthData *data;
+
+ data = g_new0 (AuthData, 1);
+ data->server = g_object_ref (server);
+ data->cookie = g_strdup (cookie);
+ data->method_invocation = g_object_ref (method_invocation);
+ data->cancellable = g_object_ref (cancellable);
+
+ return data;
+}
+
+static void
+auth_data_free (AuthData *data)
+{
+ g_object_unref (data->server);
+ g_free (data->cookie);
+ g_object_unref (data->method_invocation);
+ g_object_unref (data->cancellable);
+ g_free (data);
+}
+
+static void
+auth_cb (GObject *source_object,
+ GAsyncResult *res,
+ gpointer user_data)
+{
+ AuthData *data = user_data;
+ GError *error;
+
+ error = NULL;
+ if (!polkit_agent_listener_initiate_authentication_finish (POLKIT_AGENT_LISTENER (source_object),
+ res,
+ &error))
+ {
+ egg_dbus_method_invocation_return_gerror (data->method_invocation, error);
+ g_error_free (error);
+ }
+ else
+ {
+ _polkit_agent_authentication_agent_handle_begin_authentication_finish (data->method_invocation);
+ }
+
+ g_hash_table_remove (data->server->cookie_to_pending_auth, data->cookie);
+
+ auth_data_free (data);
+}
+
+static void
+handle_begin_authentication (_PolkitAgentAuthenticationAgent *instance,
+ const gchar *action_id,
+ const gchar *cookie,
+ EggDBusArraySeq *identities,
+ EggDBusMethodInvocation *method_invocation)
+{
+ Server *server = SERVER (instance);
+ AuthData *data;
+ GList *list;
+ guint n;
+ GCancellable *cancellable;
+
+ list = NULL;
+ for (n = 0; n < identities->size; n++)
+ {
+ _PolkitIdentity *real_identity = _POLKIT_IDENTITY (identities->data.v_ptr[n]);
+
+ list = g_list_prepend (list, polkit_identity_new_for_real (real_identity));
+ }
+
+ list = g_list_reverse (list);
+
+ cancellable = g_cancellable_new ();
+ data = auth_data_new (server,
+ cookie,
+ method_invocation,
+ cancellable);
+ g_object_unref (cancellable);
+
+ g_hash_table_insert (server->cookie_to_pending_auth, (gpointer) cookie, data);
+
+ polkit_agent_listener_initiate_authentication (server->listener,
+ action_id,
+ cookie,
+ list,
+ data->cancellable,
+ auth_cb,
+ data);
+
+ g_list_free (list);
+}
+
+static void
+handle_cancel_authentication (_PolkitAgentAuthenticationAgent *instance,
+ const gchar *cookie,
+ EggDBusMethodInvocation *method_invocation)
+{
+ Server *server = SERVER (instance);
+ AuthData *data;
+
+ data = g_hash_table_lookup (server->cookie_to_pending_auth, cookie);
+ if (data == NULL)
+ {
+ egg_dbus_method_invocation_return_error (method_invocation,
+ POLKIT_ERROR,
+ POLKIT_ERROR_FAILED,
+ "No pending authentication request for cookie '%s'",
+ cookie);
+ }
+ else
+ {
+ g_cancellable_cancel (data->cancellable);
+ _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_cancel_authentication = handle_cancel_authentication;
+}
+
+/* ---------------------------------------------------------------------------------------------------- */
+
+G_DEFINE_ABSTRACT_TYPE (PolkitAgentListener, polkit_agent_listener, G_TYPE_OBJECT);
+
+static void
+polkit_agent_listener_init (PolkitAgentListener *listener)
+{
+}
+
+static void
+polkit_agent_listener_class_init (PolkitAgentListenerClass *klass)
+{
+}
+
+void
+polkit_agent_listener_initiate_authentication (PolkitAgentListener *listener,
+ const gchar *action_id,
+ const gchar *cookie,
+ GList *identities,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data)
+{
+ POLKIT_AGENT_LISTENER_GET_CLASS (listener)->initiate_authentication (listener,
+ action_id,
+ cookie,
+ identities,
+ cancellable,
+ callback,
+ user_data);
+}
+
+gboolean
+polkit_agent_listener_initiate_authentication_finish (PolkitAgentListener *listener,
+ GAsyncResult *res,
+ GError **error)
+{
+ return POLKIT_AGENT_LISTENER_GET_CLASS (listener)->initiate_authentication_finish (listener,
+ res,
+ error);
+}
+
diff --git a/src/polkitagent/polkitagentlistener.h b/src/polkitagent/polkitagentlistener.h
new file mode 100644
index 0000000..d71acf7
--- /dev/null
+++ b/src/polkitagent/polkitagentlistener.h
@@ -0,0 +1,95 @@
+/*
+ * 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 at redhat.com>
+ */
+
+#ifndef __POLKIT_AGENT_LISTENER_H
+#define __POLKIT_AGENT_LISTENER_H
+
+#include <polkit/polkit.h>
+#include <polkitagent/polkitagenttypes.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_AGENT_TYPE_LISTENER (polkit_agent_listener_get_type ())
+#define POLKIT_AGENT_LISTENER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_AGENT_TYPE_LISTENER, PolkitAgentListener))
+#define POLKIT_AGENT_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST ((k), POLKIT_AGENT_TYPE_LISTENER, PolkitAgentListenerClass))
+#define POLKIT_AGENT_LISTENER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_AGENT_TYPE_LISTENER,PolkitAgentListenerClass))
+#define POLKIT_AGENT_IS_LISTENER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_AGENT_TYPE_LISTENER))
+#define POLKIT_AGENT_IS_LISTENER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_AGENT_TYPE_LISTENER))
+
+#if 0
+typedef struct _PolkitAgentListener PolkitAgentListener;
+#endif
+typedef struct _PolkitAgentListenerClass PolkitAgentListenerClass;
+
+struct _PolkitAgentListener
+{
+ GObject parent_instance;
+};
+
+struct _PolkitAgentListenerClass
+{
+ GObjectClass parent_class;
+
+ /*< public >*/
+ /* VFuncs */
+ void (*initiate_authentication) (PolkitAgentListener *listener,
+ const gchar *action_id,
+ const gchar *cookie,
+ GList *identities,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+
+ gboolean (*initiate_authentication_finish) (PolkitAgentListener *listener,
+ GAsyncResult *res,
+ GError **error);
+
+ /*< private >*/
+ /* Padding for future expansion */
+ void (*_polkit_reserved0) (void);
+ void (*_polkit_reserved1) (void);
+ void (*_polkit_reserved2) (void);
+ void (*_polkit_reserved3) (void);
+ void (*_polkit_reserved4) (void);
+ void (*_polkit_reserved5) (void);
+ void (*_polkit_reserved6) (void);
+ void (*_polkit_reserved7) (void);
+};
+
+GType polkit_agent_listener_get_type (void) G_GNUC_CONST;
+void polkit_agent_listener_initiate_authentication (PolkitAgentListener *listener,
+ const gchar *action_id,
+ const gchar *cookie,
+ GList *identities,
+ GCancellable *cancellable,
+ GAsyncReadyCallback callback,
+ gpointer user_data);
+gboolean polkit_agent_listener_initiate_authentication_finish (PolkitAgentListener *listener,
+ GAsyncResult *res,
+ GError **error);
+
+void polkit_agent_export_listener (PolkitAgentListener *listener,
+ const gchar *session_id,
+ const gchar *object_path);
+
+G_END_DECLS
+
+#endif /* __POLKIT_AGENT_LISTENER_H */
diff --git a/src/polkitagent/polkitagentsession.c b/src/polkitagent/polkitagentsession.c
new file mode 100644
index 0000000..0510227
--- /dev/null
+++ b/src/polkitagent/polkitagentsession.c
@@ -0,0 +1,458 @@
+/*
+ * 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 at redhat.com>
+ */
+
+/**
+ * SECTION:polkitagentsession
+ * @title: PolkitAgentSession
+ * @short_description: Authentcation Sessions
+ *
+ * The #PolkitAgentSession class is used for interacting with an authentication system.
+ */
+
+#include "config.h"
+#include <string.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/wait.h>
+#include <pwd.h>
+
+#include "polkitagentsession.h"
+
+struct _PolkitAgentSession
+{
+ GObject parent_instance;
+
+ gchar *cookie;
+ PolkitIdentity *identity;
+
+ int child_stdin;
+ int child_stdout;
+ GPid child_pid;
+
+ int child_watch_id;
+ int child_stdout_watch_id;
+ GIOChannel *child_stdout_channel;
+
+ gboolean success;
+ gboolean helper_is_running;
+};
+
+struct _PolkitAgentSessionClass
+{
+ GObjectClass parent_class;
+
+};
+
+enum
+{
+ REQUEST_ECHO_ON_SIGNAL,
+ REQUEST_ECHO_OFF_SIGNAL,
+ SHOW_INFO_SIGNAL,
+ SHOW_ERROR_SIGNAL,
+ COMPLETED_SIGNAL,
+ LAST_SIGNAL,
+};
+
+static guint signals[LAST_SIGNAL] = {0};
+
+G_DEFINE_TYPE (PolkitAgentSession, polkit_agent_session, G_TYPE_OBJECT);
+
+static void
+polkit_agent_session_init (PolkitAgentSession *session)
+{
+}
+
+static void kill_helper (PolkitAgentSession *session);
+
+static void
+polkit_agent_session_finalize (GObject *object)
+{
+ PolkitAgentSession *session;
+
+ session = POLKIT_AGENT_SESSION (object);
+
+ /* this releases resources related to the helper */
+ kill_helper (session);
+
+ g_free (session->cookie);
+ if (session->identity != NULL)
+ g_object_unref (session->identity);
+
+ if (G_OBJECT_CLASS (polkit_agent_session_parent_class)->finalize != NULL)
+ G_OBJECT_CLASS (polkit_agent_session_parent_class)->finalize (object);
+}
+
+static void
+polkit_agent_session_class_init (PolkitAgentSessionClass *klass)
+{
+ GObjectClass *gobject_class;
+
+ gobject_class = G_OBJECT_CLASS (klass);
+
+ gobject_class->finalize = polkit_agent_session_finalize;
+
+ /**
+ * PolkitAgentSession::request-echo-on:
+ * @session: A #PolkitAgentSession.
+ * @request: The request to show the user, e.g. "name: "
+ *
+ * Emitted when the user is requested to answer a question. User input
+ * should be echoed on the screen in the clear.
+ *
+ * When the response has been collected from the user, call
+ * polkit_agent_session_response().
+ */
+ signals[REQUEST_ECHO_ON_SIGNAL] = g_signal_new ("request-echo-on",
+ POLKIT_AGENT_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0, /* class offset */
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ /**
+ * PolkitAgentSession::request-echo-off:
+ * @session: A #PolkitAgentSession.
+ * @request: The request to show the user, e.g. "password: "
+ *
+ * Emitted when the user is requested to answer a question. User input
+ * MUST NOT be echoed on the screen in the clear.
+ *
+ * When the response has been collected from the user, call
+ * polkit_agent_session_response().
+ */
+ signals[REQUEST_ECHO_OFF_SIGNAL] = g_signal_new ("request-echo-off",
+ POLKIT_AGENT_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0, /* class offset */
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+
+ /**
+ * PolkitAgentSession::show-info:
+ * @session: A #PolkitAgentSession.
+ * @text: A string to display to the user.
+ *
+ * Emitted when there is information to be displayed to the user.
+ */
+ signals[SHOW_INFO_SIGNAL] = g_signal_new ("show-info",
+ POLKIT_AGENT_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0, /* class offset */
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ /**
+ * PolkitAgentSession::show-error:
+ * @session: A #PolkitAgentSession.
+ * @text: An error string to display to the user.
+ *
+ * Emitted when there is information related to an error condition to be displayed to the user.
+ */
+ signals[SHOW_ERROR_SIGNAL] = g_signal_new ("show-error",
+ POLKIT_AGENT_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0, /* class offset */
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_STRING);
+
+ /**
+ * PolkitAgentSession::completed:
+ * @session: A #PolkitAgentSession.
+ * @authentication_result: %TRUE only if the user sucessfully authenticated.
+ *
+ * Emitted when the authentication session has been completed or
+ * cancelled. The user should unref @session.
+ */
+ signals[COMPLETED_SIGNAL] = g_signal_new ("completed",
+ POLKIT_AGENT_TYPE_SESSION,
+ G_SIGNAL_RUN_LAST,
+ 0, /* class offset */
+ NULL, /* accumulator */
+ NULL, /* accumulator data */
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1,
+ G_TYPE_BOOLEAN);
+}
+
+PolkitAgentSession *
+polkit_agent_session_new (PolkitIdentity *identity,
+ const gchar *cookie)
+{
+ PolkitAgentSession *session;
+
+ session = POLKIT_AGENT_SESSION (g_object_new (POLKIT_AGENT_TYPE_SESSION, NULL));
+
+ session->identity = g_object_ref (identity);
+ session->cookie = g_strdup (cookie);
+
+ return session;
+}
+
+static void
+kill_helper (PolkitAgentSession *session)
+{
+ if (!session->helper_is_running)
+ goto out;
+
+ if (session->child_pid > 0)
+ {
+ gint status;
+ kill (session->child_pid, SIGTERM);
+ waitpid (session->child_pid, &status, 0);
+ session->child_pid = 0;
+ }
+
+ if (session->child_watch_id > 0)
+ {
+ g_source_remove (session->child_watch_id);
+ session->child_watch_id = 0;
+ }
+
+ if (session->child_stdout_watch_id > 0)
+ {
+ g_source_remove (session->child_stdout_watch_id);
+ session->child_stdout_watch_id = 0;
+ }
+
+ if (session->child_stdout_channel != NULL)
+ {
+ g_io_channel_unref (session->child_stdout_channel);
+ session->child_stdout_channel = NULL;
+ }
+
+ session->helper_is_running = FALSE;
+
+ out:
+ ;
+}
+
+static void
+complete_session (PolkitAgentSession *session,
+ gboolean result)
+{
+ kill_helper (session);
+ g_signal_emit_by_name (session, "completed", result);
+}
+
+static void
+child_watch_func (GPid pid,
+ gint status,
+ gpointer user_data)
+{
+ PolkitAgentSession *session = POLKIT_AGENT_SESSION (user_data);
+
+ /* kill all the watches we have set up, except for the child since it has exited already */
+ session->child_pid = 0;
+ kill_helper (session);
+}
+
+static gboolean
+io_watch_have_data (GIOChannel *channel,
+ GIOCondition condition,
+ gpointer user_data)
+{
+ PolkitAgentSession *session = POLKIT_AGENT_SESSION (user_data);
+ gchar *line;
+ GError *error;
+
+ error = NULL;
+ line = NULL;
+
+ if (!session->helper_is_running)
+ {
+ g_warning ("in io_watch_have_data() but helper is not supposed to be running");
+
+ complete_session (session, FALSE);
+ goto out;
+ }
+
+ g_io_channel_read_line (channel,
+ &line,
+ NULL,
+ NULL,
+ &error);
+ if (error != NULL)
+ {
+ g_warning ("Error reading line from helper: %s", error->message);
+ g_error_free (error);
+
+ complete_session (session, FALSE);
+ goto out;
+ }
+
+ /* remove terminator */
+ if (strlen (line) > 0 && line[strlen (line) - 1] == '\n')
+ line[strlen (line) - 1] = '\0';
+
+ if (g_str_has_prefix (line, "PAM_PROMPT_ECHO_OFF "))
+ {
+ g_signal_emit_by_name (session, "request-echo-off", line + sizeof "PAM_PROMPT_ECHO_OFF " - 1);
+ }
+ else if (g_str_has_prefix (line, "PAM_PROMPT_ECHO_ON "))
+ {
+ g_signal_emit_by_name (session, "request-echo-on", line + sizeof "PAM_PROMPT_ECHO_ON " - 1);
+ }
+ else if (g_str_has_prefix (line, "PAM_ERROR_MSG "))
+ {
+ g_signal_emit_by_name (session, "show-error", line + sizeof "PAM_ERROR_MSG " - 1);
+ }
+ else if (g_str_has_prefix (line, "PAM_TEXT_INFO "))
+ {
+ g_signal_emit_by_name (session, "show-info", line + sizeof "PAM_TEXT_INFO " - 1);
+ }
+ else if (g_str_has_prefix (line, "PAM_TEXT_INFO "))
+ {
+ g_signal_emit_by_name (session, "show-info", line + sizeof "PAM_TEXT_INFO " - 1);
+ }
+ else if (g_str_has_prefix (line, "SUCCESS"))
+ {
+ complete_session (session, TRUE);
+ }
+ else if (g_str_has_prefix (line, "FAILURE"))
+ {
+ complete_session (session, FALSE);
+ }
+ else
+ {
+ g_warning ("Unknown line '%s' from helper", line);
+ complete_session (session, FALSE);
+ goto out;
+ }
+
+ out:
+ g_free (line);
+
+ /* keep the IOChannel around */
+ return TRUE;
+}
+
+void
+polkit_agent_session_response (PolkitAgentSession *session,
+ const gchar *response)
+{
+ gboolean add_newline;
+ size_t response_len;
+ const char newline[] = "\n";
+
+ g_return_if_fail (response != NULL);
+
+ response_len = strlen (response);
+
+ add_newline = (response[response_len] != '\n');
+
+ write (session->child_stdin, response, response_len);
+ if (add_newline)
+ write (session->child_stdin, newline, 1);
+}
+
+void
+polkit_agent_session_initiate (PolkitAgentSession *session)
+{
+ uid_t uid;
+ GError *error;
+ gchar *helper_argv[4];
+ gboolean ret;
+ struct passwd *passwd;
+
+ ret = FALSE;
+
+ /* TODO: also support authorization for other kinds of identities */
+ if (!POLKIT_IS_UNIX_USER (session->identity))
+ {
+ g_warning ("Unsupported identity type");
+ goto error;
+ }
+
+ uid = polkit_unix_user_get_uid (POLKIT_UNIX_USER (session->identity));
+
+ passwd = getpwuid (uid);
+ if (passwd == NULL)
+ {
+ g_warning ("No user with uid %d", uid);
+ goto error;
+ }
+
+ 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;
+
+ session->child_stdin = -1;
+ session->child_stdout = -1;
+
+ error = NULL;
+ if (!g_spawn_async_with_pipes (NULL,
+ (char **) helper_argv,
+ NULL,
+ G_SPAWN_DO_NOT_REAP_CHILD |
+ 0,//G_SPAWN_STDERR_TO_DEV_NULL,
+ NULL,
+ NULL,
+ &session->child_pid,
+ &session->child_stdin,
+ &session->child_stdout,
+ NULL,
+ &error))
+ {
+ g_warning ("Cannot spawn helper: %s\n", error->message);
+ g_error_free (error);
+ goto error;
+ }
+
+ session->child_watch_id = g_child_watch_add (session->child_pid, child_watch_func, session);
+ session->child_stdout_channel = g_io_channel_unix_new (session->child_stdout);
+ session->child_stdout_watch_id = g_io_add_watch (session->child_stdout_channel, G_IO_IN, io_watch_have_data, session);
+
+ session->success = FALSE;
+
+ session->helper_is_running = TRUE;
+
+ return;
+
+error:
+ complete_session (session, FALSE);
+}
+
+
+void
+polkit_agent_session_cancel (PolkitAgentSession *session)
+{
+ complete_session (session, FALSE);
+}
diff --git a/src/polkitagent/polkitagentsession.h b/src/polkitagent/polkitagentsession.h
new file mode 100644
index 0000000..a3863bf
--- /dev/null
+++ b/src/polkitagent/polkitagentsession.h
@@ -0,0 +1,53 @@
+/*
+ * 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 at redhat.com>
+ */
+
+#ifndef __POLKIT_AGENT_SESSION_H
+#define __POLKIT_AGENT_SESSION_H
+
+#include <polkit/polkit.h>
+#include <polkitagent/polkitagenttypes.h>
+
+G_BEGIN_DECLS
+
+#define POLKIT_AGENT_TYPE_SESSION (polkit_agent_session_get_type())
+#define POLKIT_AGENT_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_AGENT_TYPE_SESSION, PolkitAgentSession))
+#define POLKIT_AGENT_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_AGENT_TYPE_SESSION, PolkitAgentSessionClass))
+#define POLKIT_AGENT_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_AGENT_TYPE_SESSION, PolkitAgentSessionClass))
+#define POLKIT_AGENT_IS_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_AGENT_TYPE_SESSION))
+#define POLKIT_AGENT_IS_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_AGENT_TYPE_SESSION))
+
+
+#if 0
+typedef struct _PolkitAgentSession PolkitAgentSession;
+#endif
+typedef struct _PolkitAgentSessionClass PolkitAgentSessionClass;
+
+GType polkit_agent_session_get_type (void) G_GNUC_CONST;
+PolkitAgentSession *polkit_agent_session_new (PolkitIdentity *identity,
+ const gchar *cookie);
+void polkit_agent_session_initiate (PolkitAgentSession *session);
+void polkit_agent_session_response (PolkitAgentSession *session,
+ const gchar *response);
+void polkit_agent_session_cancel (PolkitAgentSession *session);
+
+G_END_DECLS
+
+#endif /* __POLKIT_AGENT_SESSION_H */
diff --git a/src/polkitagent/polkitagenttypes.h b/src/polkitagent/polkitagenttypes.h
index c82ed1a..2405ebc 100644
--- a/src/polkitagent/polkitagenttypes.h
+++ b/src/polkitagent/polkitagenttypes.h
@@ -26,12 +26,11 @@
G_BEGIN_DECLS
-struct _PolkitAgentAuthenticationSession;
-typedef struct _PolkitAgentAuthenticationSession PolkitAgentAuthenticationSession;
-
-struct _PolkitAgentAuthenticationAgent;
-typedef struct _PolkitAgentAuthenticationAgent PolkitAgentAuthenticationAgent;
+struct _PolkitAgentListener;
+typedef struct _PolkitAgentListener PolkitAgentListener;
+struct _PolkitAgentSession;
+typedef struct _PolkitAgentSession PolkitAgentSession;
G_END_DECLS
diff --git a/src/polkitbackend/polkitbackendlocalauthority.c b/src/polkitbackend/polkitbackendlocalauthority.c
index 7c0c632..77b6315 100644
--- a/src/polkitbackend/polkitbackendlocalauthority.c
+++ b/src/polkitbackend/polkitbackendlocalauthority.c
@@ -1286,7 +1286,13 @@ authentication_agent_initiate_challenge (AuthenticationAgent *agent,
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));
+ identities = NULL;
+ identities = g_list_prepend (identities, g_object_ref (user_of_subject));
+ //#if 0
+ identities = g_list_prepend (identities, polkit_unix_user_new (501));
+ identities = g_list_prepend (identities, polkit_unix_user_new (502));
+ identities = g_list_prepend (identities, polkit_unix_user_new (0));
+ //#endif
session = authentication_session_new (agent,
cookie,
More information about the hal-commit
mailing list