From 10cdbe0e5087e6156f43214245bfda241972928b Mon Sep 17 00:00:00 2001 From: David Zeuthen Date: Tue, 20 Jan 2009 00:36:25 -0500 Subject: [PATCH] first cut at authentication helper library Not finished yet... --- src/Makefile.am | 2 +- src/polkitagent/Makefile.am | 63 +++++ src/polkitagent/polkitagent.h | 29 +++ src/polkitagent/polkitagenthelper.c | 255 +++++++++++++++++++ src/polkitagent/polkitagenttypes.h | 35 +++ src/polkitagent/polkitauthenticationsession.c | 354 ++++++++++++++++++++++++++ src/polkitagent/polkitauthenticationsession.h | 139 ++++++++++ 7 files changed, 876 insertions(+), 1 deletion(-) create mode 100644 src/polkitagent/Makefile.am create mode 100644 src/polkitagent/polkitagent.h create mode 100644 src/polkitagent/polkitagenthelper.c create mode 100644 src/polkitagent/polkitagenttypes.h create mode 100644 src/polkitagent/polkitauthenticationsession.c create mode 100644 src/polkitagent/polkitauthenticationsession.h diff --git a/src/Makefile.am b/src/Makefile.am index 7538232..33d3284 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -1,5 +1,5 @@ -SUBDIRS = polkit polkitbackend polkitd programs +SUBDIRS = polkit polkitbackend polkitagent polkitd programs clean-local : rm -f *~ diff --git a/src/polkitagent/Makefile.am b/src/polkitagent/Makefile.am new file mode 100644 index 0000000..ac74bd5 --- /dev/null +++ b/src/polkitagent/Makefile.am @@ -0,0 +1,63 @@ +NULL = + +INCLUDES = \ + -I$(top_builddir)/src \ + -I$(top_srcdir)/src \ + -DPACKAGE_LIBEXEC_DIR=\""$(libexecdir)"\" \ + -DPACKAGE_SYSCONF_DIR=\""$(sysconfdir)"\" \ + -DPACKAGE_DATA_DIR=\""$(datadir)"\" \ + -DPACKAGE_BIN_DIR=\""$(bindir)"\" \ + -DPACKAGE_LOCALSTATE_DIR=\""$(localstatedir)"\" \ + -DPACKAGE_LOCALE_DIR=\""$(localedir)"\" \ + -DPACKAGE_LIB_DIR=\""$(libdir)"\" \ + -D_POSIX_PTHREAD_SEMANTICS \ + -D_REENTRANT \ + $(NULL) + + +lib_LTLIBRARIES=libpolkit-agent-1.la + +libpolkit_agent_1includedir=$(includedir)/polkit-1/polkitagent + +libpolkit_agent_1include_HEADERS = \ + polkitagent.h \ + polkitagenttypes.h \ + polkitauthenticationsession.h \ + $(NULL) + +libpolkit_agent_1_la_SOURCES = \ + polkitagent.h \ + polkitagenttypes.h \ + polkitauthenticationsession.h polkitauthenticationsession.c \ + $(NULL) + +libpolkit_agent_1_la_CFLAGS = \ + -D_POLKIT_AGENT_COMPILATION \ + $(GLIB_CFLAGS) \ + $(EGG_DBUS_CFLAGS) \ + $(NULL) + +libpolkit_agent_1_la_LIBADD = \ + $(GLIB_LIBS) \ + $(EGG_DBUS_LIBS) \ + $(top_builddir)/src/polkit/libpolkit-gobject-1.la \ + $(EXPAT_LIBS) \ + $(NULL) + +libexec_PROGRAMS = polkit-agent-helper-1 + +polkit_agent_helper_1_SOURCES = polkitagenthelper.c +polkit_agent_helper_1_LDADD = $(AUTH_LIBS) + +# polkit-agent-helper-1 need to be setuid root because it's used to +# authenticate not only the invoking user, but possibly also root +# and/or other users. +# +install-exec-hook: + -chown root $(DESTDIR)$(libexecdir)/polkit-agent-helper-1 + -chmod 4755 $(DESTDIR)$(libexecdir)/polkit-agent-helper-1 + +CLEANFILES = $(BUILT_SOURCES) + +clean-local : + rm -f *~ diff --git a/src/polkitagent/polkitagent.h b/src/polkitagent/polkitagent.h new file mode 100644 index 0000000..b6c2ffb --- /dev/null +++ b/src/polkitagent/polkitagent.h @@ -0,0 +1,29 @@ +/* + * 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 + */ + +#ifndef __POLKIT_AGENT_H +#define __POLKIT_AGENT_H + +#define _POLKIT_AGENT_INSIDE_POLKIT_AGENT_H 1 +#include +#undef _POLKIT_AGENT_INSIDE_POLKIT_AGENT_H + +#endif /* __POLKIT_AGENT_H */ diff --git a/src/polkitagent/polkitagenthelper.c b/src/polkitagent/polkitagenthelper.c new file mode 100644 index 0000000..df59f18 --- /dev/null +++ b/src/polkitagent/polkitagenthelper.c @@ -0,0 +1,255 @@ +/* + * 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 + */ + +#include "config.h" +#include +#include +#include +#include +#include +#include +#include +#include + +#ifdef HAVE_SOLARIS +# define LOG_AUTHPRIV (10<<3) +#endif + +/* Development aid: define PAH_DEBUG to get debugging output. Do _NOT_ + * enable this in production builds; it may leak passwords and other + * sensitive information. + */ +#undef PAH_DEBUG +#define PAH_DEBUG + +static int conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data); + +int +main (int argc, char *argv[]) +{ + int rc; + const char *user_to_auth; + const char *cookie; + struct pam_conv pam_conversation; + pam_handle_t *pam_h; + const void *authed_user; + + rc = 0; + pam_h = NULL; + + /* clear the entire environment to avoid attacks using with libraries honoring environment variables */ + if (clearenv () != 0) + goto error; + + /* set a minimal environment */ + setenv ("PATH", "/usr/sbin:/usr/bin:/sbin:/bin", 1); + + /* check that we are setuid root */ + if (geteuid () != 0) + { + fprintf (stderr, "polkit-grant-helper-pam: needs to be setuid root\n"); + goto error; + } + + openlog ("polkit-agent-helper-1", LOG_CONS | LOG_PID, LOG_AUTHPRIV); + + /* check for correct invocation */ + if (argc != 3) + { + syslog (LOG_NOTICE, "inappropriate use of helper, wrong number of arguments [uid=%d]", getuid ()); + fprintf (stderr, "polkit-agent-helper-1: wrong number of arguments. This incident has been logged.\n"); + goto error; + } + + user_to_auth = argv[1]; + cookie = argv[2]; + + if (getuid () != 0) + { + /* check we're running with a non-tty stdin */ + if (isatty (STDIN_FILENO) != 0) + { + syslog (LOG_NOTICE, "inappropriate use of helper, stdin is a tty [uid=%d]", getuid ()); + fprintf (stderr, "polkit-agent-helper-1: inappropriate use of helper, stdin is a tty. This incident has been logged.\n"); + goto error; + } + } + +#ifdef PAH_DEBUG + fprintf (stderr, "polkit-agent-helper-1: user to auth is '%s'.\n", user_to_auth); +#endif /* PAH_DEBUG */ + + pam_conversation.conv = conversation_function; + pam_conversation.appdata_ptr = NULL; + + /* start the pam stack */ + rc = pam_start ("polkit-1", + user_to_auth, + &pam_conversation, + &pam_h); + if (rc != PAM_SUCCESS) + { + fprintf (stderr, "polkit-agent-helper-1: pam_start failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* set the requesting user */ + rc = pam_set_item (pam_h, PAM_RUSER, user_to_auth); + if (rc != PAM_SUCCESS) + { + fprintf (stderr, "polkit-agent-helper-1: pam_set_item failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* is user really user? */ + rc = pam_authenticate (pam_h, 0); + if (rc != PAM_SUCCESS) + { + fprintf (stderr, "polkit-agent-helper-1: pam_authenticated failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* permitted access? */ + rc = pam_acct_mgmt (pam_h, 0); + if (rc != PAM_SUCCESS) + { + fprintf (stderr, "polkit-agent-helper-1: pam_acct_mgmt failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + /* did we auth the right user? */ + rc = pam_get_item (pam_h, PAM_USER, &authed_user); + if (rc != PAM_SUCCESS) + { + fprintf (stderr, "polkit-agent-helper-1: pam_get_item failed: %s\n", pam_strerror (pam_h, rc)); + goto error; + } + + if (strcmp (authed_user, user_to_auth) != 0) + { + fprintf (stderr, "polkit-agent-helper-1: Tried to auth user '%s' but we got auth for user '%s' instead", + user_to_auth, (const char *) authed_user); + goto error; + } + +#ifdef PAH_DEBUG + 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 + */ + + fprintf (stdout, "SUCCESS\n"); + fflush (stdout); + + pam_end (pam_h, rc); + return 0; + +error: + if (pam_h != NULL) + pam_end (pam_h, rc); + + fprintf (stdout, "FAILURE\n"); + fflush (stdout); + return 1; +} + +static int +conversation_function (int n, const struct pam_message **msg, struct pam_response **resp, void *data) +{ + struct pam_response *aresp; + char buf[PAM_MAX_RESP_SIZE]; + int i; + + data = data; + if (n <= 0 || n > PAM_MAX_NUM_MSG) + return PAM_CONV_ERR; + + if ((aresp = calloc(n, sizeof *aresp)) == NULL) + return PAM_BUF_ERR; + + for (i = 0; i < n; ++i) + { + aresp[i].resp_retcode = 0; + aresp[i].resp = NULL; + switch (msg[i]->msg_style) + { + + case PAM_PROMPT_ECHO_OFF: + fprintf (stdout, "PAM_PROMPT_ECHO_OFF "); + goto conv1; + + case PAM_PROMPT_ECHO_ON: + fprintf (stdout, "PAM_PROMPT_ECHO_ON "); + conv1: + fputs (msg[i]->msg, stdout); + if (strlen (msg[i]->msg) > 0 && msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') + fputc ('\n', stdout); + fflush (stdout); + + if (fgets (buf, sizeof buf, stdin) == NULL) + goto error; + + if (strlen (buf) > 0 && + buf[strlen (buf) - 1] == '\n') + buf[strlen (buf) - 1] = '\0'; + + aresp[i].resp = strdup (buf); + if (aresp[i].resp == NULL) + goto error; + break; + + case PAM_ERROR_MSG: + fprintf (stdout, "PAM_ERROR_MSG "); + goto conv2; + + case PAM_TEXT_INFO: + fprintf (stdout, "PAM_TEXT_INFO "); + conv2: + fputs (msg[i]->msg, stdout); + if (strlen (msg[i]->msg) > 0 && + msg[i]->msg[strlen (msg[i]->msg) - 1] != '\n') + fputc ('\n', stdout); + fflush (stdout); + break; + + default: + goto error; + } + } + + *resp = aresp; + return PAM_SUCCESS; + +error: + + for (i = 0; i < n; ++i) + { + if (aresp[i].resp != NULL) { + memset (aresp[i].resp, 0, strlen(aresp[i].resp)); + free (aresp[i].resp); + } + } + memset (aresp, 0, n * sizeof *aresp); + *resp = NULL; + return PAM_CONV_ERR; +} diff --git a/src/polkitagent/polkitagenttypes.h b/src/polkitagent/polkitagenttypes.h new file mode 100644 index 0000000..de62caa --- /dev/null +++ b/src/polkitagent/polkitagenttypes.h @@ -0,0 +1,35 @@ +/* + * 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 + */ + +#ifndef __POLKIT_AGENT_TYPES_H +#define __POLKIT_AGENT_TYPES_H + +#include + +G_BEGIN_DECLS + +struct _PolkitAuthenticationSession; +typedef struct _PolkitAuthenticationSession PolkitAuthenticationSession; + + +G_END_DECLS + +#endif /* __POLKIT_AGENT_TYPES_H */ diff --git a/src/polkitagent/polkitauthenticationsession.c b/src/polkitagent/polkitauthenticationsession.c new file mode 100644 index 0000000..62dcd7a --- /dev/null +++ b/src/polkitagent/polkitauthenticationsession.c @@ -0,0 +1,354 @@ +/* + * 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 + */ + +/* 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... + */ + + +/* for getline(), see below */ +#define _GNU_SOURCE + +#include "config.h" +#include +#include +#include +#include +#include +#include + +#include "polkitauthenticationsession.h" + +struct _PolkitAuthenticationSession +{ + 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; + + PolkitAuthenticationSessionConversationPromptEchoOff func_prompt_echo_off; + PolkitAuthenticationSessionConversationPromptEchoOn func_prompt_echo_on; + PolkitAuthenticationSessionConversationErrorMessage func_error_message; + PolkitAuthenticationSessionConversationTextInfo func_text_info; + PolkitAuthenticationSessionDone func_done; + void *user_data; +}; + +struct _PolkitAuthenticationSessionClass +{ + GObjectClass parent_class; + +}; + +G_DEFINE_TYPE (PolkitAuthenticationSession, polkit_authentication_session, G_TYPE_OBJECT); + +static void +polkit_authentication_session_init (PolkitAuthenticationSession *session) +{ +} + +static void +polkit_authentication_session_finalize (GObject *object) +{ + PolkitAuthenticationSession *session; + + session = POLKIT_AUTHENTICATION_SESSION (object); + + g_free (session->cookie); + if (session->identity != NULL) + g_object_unref (session->identity); + + if (G_OBJECT_CLASS (polkit_authentication_session_parent_class)->finalize != NULL) + G_OBJECT_CLASS (polkit_authentication_session_parent_class)->finalize (object); +} + +static void +polkit_authentication_session_class_init (PolkitAuthenticationSessionClass *klass) +{ + GObjectClass *gobject_class; + + gobject_class = G_OBJECT_CLASS (klass); + + gobject_class->finalize = polkit_authentication_session_finalize; + + + +} + +PolkitAuthenticationSession * +polkit_authentication_session_new (PolkitIdentity *identity, + const gchar *cookie) +{ + PolkitAuthenticationSession *session; + + session = POLKIT_AUTHENTICATION_SESSION (g_object_new (POLKIT_TYPE_AUTHENTICATION_SESSION, NULL)); + + session->identity = g_object_ref (identity); + session->cookie = g_strdup (cookie); + + return session; +} + +void +polkit_authentication_session_set_functions (PolkitAuthenticationSession *session, + PolkitAuthenticationSessionConversationPromptEchoOff func_prompt_echo_off, + PolkitAuthenticationSessionConversationPromptEchoOn func_prompt_echo_on, + PolkitAuthenticationSessionConversationErrorMessage func_error_message, + PolkitAuthenticationSessionConversationTextInfo func_text_info, + PolkitAuthenticationSessionDone 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) +{ + PolkitAuthenticationSession *session = POLKIT_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) +{ + PolkitAuthenticationSession *session = POLKIT_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_authentication_session_initiate_auth (PolkitAuthenticationSession *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-session-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_authentication_session_cancel (PolkitAuthenticationSession *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/polkitauthenticationsession.h b/src/polkitagent/polkitauthenticationsession.h new file mode 100644 index 0000000..1ccc4ca --- /dev/null +++ b/src/polkitagent/polkitauthenticationsession.h @@ -0,0 +1,139 @@ +/* + * 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 + */ + +#ifndef __POLKIT_AUTHENTICATION_SESSION_H +#define __POLKIT_AUTHENTICATION_SESSION_H + +#include +#include + +G_BEGIN_DECLS + +#define POLKIT_TYPE_AUTHENTICATION_SESSION (polkit_authentication_session_get_type()) +#define POLKIT_AUTHENTICATION_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), POLKIT_TYPE_AUTHENTICATION_SESSION, PolkitAuthenticationSession)) +#define POLKIT_AUTHENTICATION_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), POLKIT_TYPE_AUTHENTICATION_SESSION, PolkitAuthenticationSessionClass)) +#define POLKIT_AUTHENTICATION_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), POLKIT_TYPE_AUTHENTICATION_SESSION, PolkitAuthenticationSessionClass)) +#define POLKIT_IS_AUTHENTICATION_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), POLKIT_TYPE_AUTHENTICATION_SESSION)) +#define POLKIT_IS_AUTHENTICATION_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), POLKIT_TYPE_AUTHENTICATION_SESSION)) + +/** + * PolkitAuthenticationSessionConversationPromptEchoOff: + * @session: A #PolkitAuthenticationSession. + * @prompt: prompt passed by the authentication layer; do not free this string + * @user_data: user data pointer as passed into polkit_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 #PolkitAuthenticationSession class. + **/ +typedef char* (*PolkitAuthenticationSessionConversationPromptEchoOff) (PolkitAuthenticationSession *session, + const gchar *prompt, + gpointer user_data); + +/** + * PolkitAuthenticationSessionConversationPromptEchoOn: + * @session: A #PolkitAuthenticationSession. + * @prompt: prompt passed by the authentication layer; do not free this string + * @user_data: user data pointer as passed into polkit_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 #PolkitAuthenticationSession class. + **/ +typedef char* (*PolkitAuthenticationSessionConversationPromptEchoOn) (PolkitAuthenticationSession *session, + const gchar *prompt, + gpointer user_data); + +/** + * PolkitAuthenticationSessionConversationErrorMessage: + * @session: A #PolkitAuthenticationSession. + * @error_message: error message passed by the authentication layer; do not free this string + * @user_data: user data pointer as passed into polkit_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 (*PolkitAuthenticationSessionConversationErrorMessage) (PolkitAuthenticationSession *session, + const gchar *error_message, + gpointer user_data); + +/** + * PolkitAuthenticationSessionConversationTextInfo: + * @session: A #PolkitAuthenticationSession. + * @text_info: information passed by the authentication layer; do not free this string + * @user_data: user data pointer as passed into polkit_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 (*PolkitAuthenticationSessionConversationTextInfo) (PolkitAuthenticationSession *session, + const gchar *text_info, + gpointer user_data); + +/** + * PolkitAuthenticationSessionDone: + * @session: A #PolkitAuthenticationSession. + * @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_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_authorization_session_cancel_auth(). + **/ +typedef void (*PolkitAuthenticationSessionDone) (PolkitAuthenticationSession *session, + gboolean gained_authorization, + gboolean invalid_data, + gpointer user_data); + + +#if 0 +typedef struct _PolkitAuthenticationSession PolkitAuthenticationSession; +#endif +typedef struct _PolkitAuthenticationSessionClass PolkitAuthenticationSessionClass; + +GType polkit_authentication_session_get_type (void) G_GNUC_CONST; +PolkitAuthenticationSession *polkit_authentication_session_new (PolkitIdentity *identity, + const gchar *cookie); + +/* TODO: would be much nicer to use signals here */ +void polkit_authentication_session_set_functions + (PolkitAuthenticationSession *session, + PolkitAuthenticationSessionConversationPromptEchoOff func_prompt_echo_off, + PolkitAuthenticationSessionConversationPromptEchoOn func_prompt_echo_on, + PolkitAuthenticationSessionConversationErrorMessage func_error_message, + PolkitAuthenticationSessionConversationTextInfo func_text_info, + PolkitAuthenticationSessionDone func_done, + void *user_data); + +gboolean polkit_authentication_session_initiate_auth (PolkitAuthenticationSession *session); + +void polkit_authentication_session_cancel (PolkitAuthenticationSession *session); + +G_END_DECLS + +#endif /* __POLKIT_AUTHENTICATION_SESSION_H */ -- 2.7.4