merge: implement a polkit agent and use it in nmcli (bgo #739413)

The polkit agent listener code is generic and will be used by nmtui as well.

https://bugzilla.gnome.org/show_bug.cgi?id=739413
This commit is contained in:
Jiří Klimeš
2014-11-07 11:38:31 +01:00
9 changed files with 753 additions and 1 deletions

View File

@@ -30,6 +30,8 @@ nmcli_SOURCES = \
nmcli.h \ nmcli.h \
utils.c \ utils.c \
utils.h \ utils.h \
polkit-agent.c \
polkit-agent.h \
\ \
$(srcdir)/../common/nm-secret-agent-simple.c \ $(srcdir)/../common/nm-secret-agent-simple.c \
$(srcdir)/../common/nm-secret-agent-simple.h \ $(srcdir)/../common/nm-secret-agent-simple.h \
@@ -40,6 +42,12 @@ nmcli_LDADD = \
$(READLINE_LIBS) \ $(READLINE_LIBS) \
$(top_builddir)/libnm/libnm.la $(top_builddir)/libnm/libnm.la
if WITH_POLKIT_AGENT
AM_CPPFLAGS += $(POLKIT_CFLAGS)
nmcli_SOURCES += $(srcdir)/../common/nm-polkit-listener.c $(srcdir)/../common/nm-polkit-listener.h
nmcli_LDADD += $(POLKIT_LIBS)
endif
if BUILD_SETTING_DOCS if BUILD_SETTING_DOCS
settings-docs.c: settings-docs.xsl $(top_builddir)/libnm-util/nm-setting-docs.xml settings-docs.c: settings-docs.xsl $(top_builddir)/libnm-util/nm-setting-docs.xml
$(AM_V_GEN) xsltproc --output $@ $^ $(AM_V_GEN) xsltproc --output $@ $^

View File

@@ -27,6 +27,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <signal.h> #include <signal.h>
#include <pthread.h> #include <pthread.h>
#include <termios.h>
#include <unistd.h>
#include <locale.h> #include <locale.h>
#include <readline/readline.h> #include <readline/readline.h>
#include <readline/history.h> #include <readline/history.h>
@@ -34,6 +36,7 @@
#include <glib.h> #include <glib.h>
#include <glib/gi18n.h> #include <glib/gi18n.h>
#include "polkit-agent.h"
#include "nmcli.h" #include "nmcli.h"
#include "utils.h" #include "utils.h"
#include "common.h" #include "common.h"
@@ -61,6 +64,7 @@ typedef struct {
/* --- Global variables --- */ /* --- Global variables --- */
GMainLoop *loop = NULL; GMainLoop *loop = NULL;
static sigset_t signal_set; static sigset_t signal_set;
struct termios termios_orig;
/* Get an error quark for use with GError */ /* Get an error quark for use with GError */
@@ -261,8 +265,18 @@ parse_command_line (NmCli *nmc, int argc, char **argv)
argv++; argv++;
} }
if (argc > 1) if (argc > 1) {
GError *error = NULL;
/* Initialize polkit agent */
if (!nmc_polkit_agent_init (&nm_cli, FALSE, &error)) {
g_printerr ("Polkit agent initialization failed: %s\n", error->message);
g_error_free (error);
}
/* Now run the requested command */
return do_cmd (nmc, argv[1], argc-1, argv+1); return do_cmd (nmc, argv[1], argc-1, argv+1);
}
usage (base); usage (base);
return nmc->return_value; return nmc->return_value;
@@ -332,6 +346,7 @@ signal_handling_thread (void *arg) {
pthread_mutex_unlock (&sigint_mutex); pthread_mutex_unlock (&sigint_mutex);
} else { } else {
/* We can quit nmcli */ /* We can quit nmcli */
tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_orig);
nmc_cleanup_readline (); nmc_cleanup_readline ();
g_print (_("\nError: nmcli terminated by signal %s (%d)\n"), g_print (_("\nError: nmcli terminated by signal %s (%d)\n"),
strsignal (signo), signo); strsignal (signo), signo);
@@ -340,6 +355,7 @@ signal_handling_thread (void *arg) {
break; break;
case SIGQUIT: case SIGQUIT:
case SIGTERM: case SIGTERM:
tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_orig);
nmc_cleanup_readline (); nmc_cleanup_readline ();
if (!nmcli_sigquit_internal) if (!nmcli_sigquit_internal)
g_print (_("\nError: nmcli terminated by signal %s (%d)\n"), g_print (_("\nError: nmcli terminated by signal %s (%d)\n"),
@@ -502,6 +518,7 @@ nmc_init (NmCli *nmc)
nmc->secret_agent = NULL; nmc->secret_agent = NULL;
nmc->pwds_hash = NULL; nmc->pwds_hash = NULL;
nmc->pk_listener = NULL;
nmc->should_wait = FALSE; nmc->should_wait = FALSE;
nmc->nowait_flag = TRUE; nmc->nowait_flag = TRUE;
@@ -539,6 +556,8 @@ nmc_cleanup (NmCli *nmc)
g_free (nmc->required_fields); g_free (nmc->required_fields);
nmc_empty_output_fields (nmc); nmc_empty_output_fields (nmc);
g_ptr_array_unref (nmc->output_data); g_ptr_array_unref (nmc->output_data);
nmc_polkit_agent_fini (nmc);
} }
static gboolean static gboolean
@@ -577,6 +596,9 @@ main (int argc, char *argv[])
g_type_init (); g_type_init ();
#endif #endif
/* Save terminal settings */
tcgetattr (STDIN_FILENO, &termios_orig);
/* readline init */ /* readline init */
rl_event_hook = event_hook_for_readline; rl_event_hook = event_hook_for_readline;
/* Set 0.01s timeout to mitigate slowness in readline when a broken version is used. /* Set 0.01s timeout to mitigate slowness in readline when a broken version is used.

View File

@@ -20,8 +20,17 @@
#ifndef NMC_NMCLI_H #ifndef NMC_NMCLI_H
#define NMC_NMCLI_H #define NMC_NMCLI_H
#include "config.h"
#include <NetworkManager.h> #include <NetworkManager.h>
#if WITH_POLKIT_AGENT
#include "nm-polkit-listener.h"
#else
/* polkit agent is not available; define fake NMPolkitListener */
typedef gpointer NMPolkitListener;
#endif
/* nmcli exit codes */ /* nmcli exit codes */
typedef enum { typedef enum {
/* Indicates successful execution */ /* Indicates successful execution */
@@ -114,6 +123,7 @@ typedef struct _NmCli {
NMSecretAgent *secret_agent; /* Secret agent */ NMSecretAgent *secret_agent; /* Secret agent */
GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */ GHashTable *pwds_hash; /* Hash table with passwords in passwd-file */
NMPolkitListener *pk_listener ; /* polkit agent listener */
gboolean should_wait; /* Indication that nmcli should not end yet */ gboolean should_wait; /* Indication that nmcli should not end yet */
gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */ gboolean nowait_flag; /* '--nowait' option; used for passing to callbacks */

146
clients/cli/polkit-agent.c Normal file
View File

@@ -0,0 +1,146 @@
/* nmcli - command-line tool to control NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2014 Red Hat, Inc.
*/
#include "config.h"
#if WITH_POLKIT_AGENT
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <termios.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include "polkit-agent.h"
#include "nm-polkit-listener.h"
#include "common.h"
static char *
polkit_request (const char *request,
const char *action_id,
const char *message,
const char *icon_name,
const char *user,
gboolean echo_on,
gpointer user_data)
{
char *response, *tmp, *p;
struct termios termios_orig, termios_new;
g_print ("%s\n", message);
g_print ("(action_id: %s)\n", action_id);
if (!echo_on) {
tcgetattr (STDIN_FILENO, &termios_orig);
termios_new = termios_orig;
termios_new.c_lflag &= ~(ECHO);
tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_new);
}
/* Ask user for polkit authorization password */
if (user) {
/* chop of ": " if present */
tmp = g_strdup (request);
p = strrchr (tmp, ':');
if (p && !strcmp (p, ": "))
*p = '\0';
response = nmc_readline ("%s (%s): ", tmp, user);
g_free (tmp);
} else
response = nmc_readline ("%s", request);
g_print ("\n");
/* Restore original terminal settings */
if (!echo_on)
tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_orig);
return response;
}
static void
polkit_show_info (const char *text)
{
g_print (_("Authentication message: %s\n"), text);
}
static void
polkit_show_error (const char *text)
{
g_print (_("Authentication error: %s\n"), text);
}
static void
polkit_completed (gboolean gained_authorization)
{
/* We don't print anything here. The outcome will be evident from
* the operation result anyway. */
}
gboolean
nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error)
{
PolkitAgentListener *listener;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
/* We don't register polkit agent at all when running non-interactively */
if (!nmc->ask)
return TRUE;
listener = nm_polkit_listener_new (for_session, error);
if (!listener)
return FALSE;
nm_polkit_listener_set_request_callback (NM_POLKIT_LISTENER (listener), polkit_request, nmc);
nm_polkit_listener_set_show_info_callback (NM_POLKIT_LISTENER (listener), polkit_show_info);
nm_polkit_listener_set_show_error_callback (NM_POLKIT_LISTENER (listener), polkit_show_error);
nm_polkit_listener_set_completed_callback (NM_POLKIT_LISTENER (listener), polkit_completed);
nmc->pk_listener = NM_POLKIT_LISTENER (listener);
return TRUE;
}
void
nmc_polkit_agent_fini (NmCli* nmc)
{
g_clear_object (&nmc->pk_listener);
}
#else
/* polkit agent is not avalable; implement stub functions. */
#include <glib.h>
#include "nmcli.h"
#include "polkit-agent.h"
gboolean
nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error)
{
return TRUE;
}
void
nmc_polkit_agent_fini (NmCli* nmc)
{
}
#endif /* #if WITH_POLKIT_AGENT */

View File

@@ -0,0 +1,28 @@
/* nmcli - command-line tool to control NetworkManager
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program 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 General Public License for more details.
*
* You should have received a copy of the GNU General Public License along
* with this program; if not, write to the Free Software Foundation, Inc.,
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Copyright 2014 Red Hat, Inc.
*/
#ifndef __NMC_POLKIT_AGENT_H__
#define __NMC_POLKIT_AGENT_H__
#include "nmcli.h"
gboolean nmc_polkit_agent_init (NmCli *nmc, gboolean for_session, GError **error);
void nmc_polkit_agent_fini (NmCli* nmc);
#endif /* __NMC_POLKIT_AGENT_H__ */

View File

@@ -0,0 +1,415 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2014 Red Hat, Inc.
*/
/**
* SECTION:nm-polkit-listener
* @short_description: A polkit agent listener
*
* #NMPolkitListener is the polkit agent listener used by nmcli and nmtui.
* http://www.freedesktop.org/software/polkit/docs/latest/index.html
*
* For an example polkit agent you can look at polkit source tree:
* http://cgit.freedesktop.org/polkit/tree/src/polkitagent/polkitagenttextlistener.c
* http://cgit.freedesktop.org/polkit/tree/src/programs/pkttyagent.c
* or LXDE polkit agent:
* http://git.lxde.org/gitweb/?p=debian/lxpolkit.git;a=blob;f=src/lxpolkit-listener.c
* https://github.com/lxde/lxqt-policykit/tree/master/src
*/
#include "config.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <glib.h>
#include <glib/gi18n-lib.h>
#include "nm-glib-compat.h"
#include "nm-polkit-listener.h"
G_DEFINE_TYPE (NMPolkitListener, nm_polkit_listener, POLKIT_AGENT_TYPE_LISTENER)
#define NM_POLKIT_LISTENER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerPrivate))
typedef struct {
gpointer reg_handle; /* handle of polkit agent registration */
GSimpleAsyncResult *simple;
PolkitAgentSession *active_session;
gulong cancel_id;
GCancellable *cancellable;
char *action_id;
char *message;
char *icon_name;
char *identity;
/* callbacks */
NMPolkitListenerOnRequestFunc on_request_callback;
NMPolkitListenerOnShowInfoFunc on_show_info_callback;
NMPolkitListenerOnShowErrorFunc on_show_error_callback;
NMPolkitListenerOnCompletedFunc on_completed_callback;
gpointer request_callback_data;
} NMPolkitListenerPrivate;
static void
on_request (PolkitAgentSession *session,
const char *request,
gboolean echo_on,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
char *response = NULL;
if (priv->on_request_callback) {
response = priv->on_request_callback (request, priv->action_id,
priv->message, priv->icon_name,
priv->identity, echo_on,
priv->request_callback_data);
}
if (response) {
polkit_agent_session_response (session, response);
g_free (response);
} else {
//FIXME: polkit_agent_session_cancel() should emit "completed", but it doesn't work for me ???
//polkit_agent_session_cancel (session);
polkit_agent_session_response (session, "");
}
}
static void
on_show_info (PolkitAgentSession *session,
const char *text,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
if (priv->on_show_info_callback)
priv->on_show_info_callback (text);
}
static void
on_show_error (PolkitAgentSession *session,
const char *text,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
if (priv->on_show_error_callback)
priv->on_show_error_callback (text);
}
static void
on_completed (PolkitAgentSession *session,
gboolean gained_authorization,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
if (priv->on_completed_callback)
priv->on_completed_callback (gained_authorization);
g_simple_async_result_complete_in_idle (priv->simple);
g_object_unref (priv->simple);
g_object_unref (priv->active_session);
if (priv->cancellable) {
g_cancellable_disconnect (priv->cancellable, priv->cancel_id);
g_object_unref (priv->cancellable);
}
priv->simple = NULL;
priv->active_session = NULL;
priv->cancel_id = 0;
g_clear_pointer (&priv->action_id, g_free);
g_clear_pointer (&priv->message, g_free);
g_clear_pointer (&priv->icon_name, g_free);
g_clear_pointer (&priv->identity, g_free);
}
static void
on_cancelled (GCancellable *cancellable, gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (user_data);
polkit_agent_session_cancel (priv->active_session);
}
static gint
compare_users (gconstpointer a, gconstpointer b)
{
char *user;
int ret;
if (POLKIT_IS_UNIX_USER (a))
user = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (a)));
else
user = polkit_identity_to_string (POLKIT_IDENTITY (a));
ret = g_strcmp0 ((const char *) user, (const char *) b);
g_free (user);
return ret;
}
static PolkitIdentity *
choose_identity (GList *identities)
{
const char *user;
GList *elem;
/* Choose identity. First try current user, then root, and else
* take the firts one */
user = getenv("USER");
elem = g_list_find_custom (identities, user, (GCompareFunc) compare_users);
if (!elem) {
elem = g_list_find_custom (identities, "root", (GCompareFunc) compare_users);
if (!elem)
elem = identities;
}
return elem->data;
}
static void
initiate_authentication (PolkitAgentListener *listener,
const char *action_id,
const char *message,
const char *icon_name,
PolkitDetails *details,
const char *cookie,
GList *identities,
GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener);
GSimpleAsyncResult *simple;
PolkitIdentity *identity;
simple = g_simple_async_result_new (G_OBJECT (listener),
callback,
user_data,
initiate_authentication);
if (priv->active_session != NULL) {
g_simple_async_result_set_error (simple,
POLKIT_ERROR,
POLKIT_ERROR_FAILED,
_("An authentication session is already underway."));
g_simple_async_result_complete_in_idle (simple);
g_object_unref (simple);
return;
}
/* Choose identity */
identity = choose_identity (identities);
priv->active_session = polkit_agent_session_new (identity, cookie);
g_signal_connect (priv->active_session,
"completed",
G_CALLBACK (on_completed),
listener);
g_signal_connect (priv->active_session,
"request",
G_CALLBACK (on_request),
listener);
g_signal_connect (priv->active_session,
"show-info",
G_CALLBACK (on_show_info),
listener);
g_signal_connect (priv->active_session,
"show-error",
G_CALLBACK (on_show_error),
listener);
priv->action_id = g_strdup (action_id);
priv->message = g_strdup (message);
priv->icon_name = g_strdup (icon_name);
if (POLKIT_IS_UNIX_USER (identity))
priv->identity = g_strdup (polkit_unix_user_get_name (POLKIT_UNIX_USER (identity)));
else
priv->identity = polkit_identity_to_string (identity);
priv->simple = simple;
priv->cancellable = g_object_ref (cancellable);
priv->cancel_id = g_cancellable_connect (cancellable,
G_CALLBACK (on_cancelled),
listener,
NULL);
polkit_agent_session_initiate (priv->active_session);
}
static gboolean
initiate_authentication_finish (PolkitAgentListener *listener,
GAsyncResult *result,
GError **error)
{
return !g_simple_async_result_propagate_error (G_SIMPLE_ASYNC_RESULT (result), error);
}
static void
nm_polkit_listener_init (NMPolkitListener *agent)
{
}
static void
nm_polkit_listener_finalize (GObject *object)
{
NMPolkitListenerPrivate *priv = NM_POLKIT_LISTENER_GET_PRIVATE (object);
if (priv->reg_handle)
polkit_agent_listener_unregister (priv->reg_handle);
g_free (priv->action_id);
g_free (priv->message);
g_free (priv->icon_name);
g_free (priv->identity);
G_OBJECT_CLASS (nm_polkit_listener_parent_class)->finalize (object);
}
static void
nm_polkit_listener_class_init (NMPolkitListenerClass *klass)
{
GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
PolkitAgentListenerClass *pkal_class = POLKIT_AGENT_LISTENER_CLASS (klass);
g_type_class_add_private (klass, sizeof (NMPolkitListenerPrivate));
gobject_class->finalize = nm_polkit_listener_finalize;
pkal_class->initiate_authentication = initiate_authentication;
pkal_class->initiate_authentication_finish = initiate_authentication_finish;
}
/**
* nm_polkit_listener_new:
* @for_session: %TRUE for registering the polkit agent for the user session,
* %FALSE for registering it for the running process
* @error: location to store error, or %NULL
*
* Creates a new #NMPolkitListener and registers it as a polkit agent.
*
* Returns: a new #NMPolkitListener
*/
PolkitAgentListener *
nm_polkit_listener_new (gboolean for_session, GError **error)
{
PolkitAgentListener *listener;
PolkitSubject* session;
NMPolkitListenerPrivate *priv;
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
listener = g_object_new (NM_TYPE_POLKIT_LISTENER, NULL);
priv = NM_POLKIT_LISTENER_GET_PRIVATE (listener);
if (for_session)
session = polkit_unix_session_new_for_process_sync (getpid (), NULL, NULL);
else
session = polkit_unix_process_new_for_owner (getpid (), 0, getuid ());
priv->reg_handle = polkit_agent_listener_register (listener, POLKIT_AGENT_REGISTER_FLAGS_NONE,
session, NULL, NULL, error);
if (!priv->reg_handle) {
g_object_unref (listener);
g_object_unref (session);
return NULL;
}
return listener;
}
/**
* nm_polkit_listener_set_request_callback:
* @self: a #NMPolkitListener object
* @request_callback: callback to install for polkit requests
* @request_callback_data: usaer data passed to request_callback when it is called
*
* Set a callback for "request" signal. The callback will be invoked when polkit
* requests an authorization.
*/
void
nm_polkit_listener_set_request_callback (NMPolkitListener *self,
NMPolkitListenerOnRequestFunc request_callback,
gpointer request_callback_data)
{
NMPolkitListenerPrivate *priv;
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
priv = NM_POLKIT_LISTENER_GET_PRIVATE (self);
priv->on_request_callback = request_callback;
priv->request_callback_data = request_callback_data;
}
/**
* nm_polkit_listener_set_show_info_callback:
* @self: a #NMPolkitListener object
* @show_info_callback: callback to install for polkit show info trigger
*
* Set a callback for "show-info" signal. The callback will be invoked when polkit
* has an info text to display.
*/
void
nm_polkit_listener_set_show_info_callback (NMPolkitListener *self,
NMPolkitListenerOnShowInfoFunc show_info_callback)
{
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
NM_POLKIT_LISTENER_GET_PRIVATE (self)->on_show_info_callback = show_info_callback;
}
/**
* nm_polkit_listener_set_show_error_callback:
* @self: a #NMPolkitListener object
* @show_error_callback: callback to install for polkit show error trigger
*
* Set a callback for "show-error" signal. The callback will be invoked when polkit
* has an error text to display.
*/
void
nm_polkit_listener_set_show_error_callback (NMPolkitListener *self,
NMPolkitListenerOnShowErrorFunc show_error_callback)
{
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
NM_POLKIT_LISTENER_GET_PRIVATE (self)->on_show_error_callback = show_error_callback;
}
/**
* nm_polkit_listener_set_completed_callback:
* @self: a #NMPolkitListener object
* @completed_callback: callback to install for polkit completing authorization
*
* Set a callback for "completed" signal. The callback will be invoked when polkit
* completed the request.
*/
void
nm_polkit_listener_set_completed_callback (NMPolkitListener *self,
NMPolkitListenerOnCompletedFunc completed_callback)
{
g_return_if_fail (NM_IS_POLKIT_LISTENER (self));
NM_POLKIT_LISTENER_GET_PRIVATE (self)->on_completed_callback = completed_callback;
}

View File

@@ -0,0 +1,104 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License as
* published by the Free Software Foundation; either version 2 of the
* License, or (at your option) any later version.
*
* This program 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
* General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
* Copyright 2014 Red Hat, Inc.
*/
#ifndef __NM_POLKIT_LISTENER_H__
#define __NM_POLKIT_LISTENER_H__
#include <glib.h>
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
#include <polkitagent/polkitagent.h>
G_BEGIN_DECLS
#define NM_TYPE_POLKIT_LISTENER (nm_polkit_listener_get_type ())
#define NM_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListener))
#define NM_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass))
#define NM_IS_POLKIT_LISTENER(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_POLKIT_LISTENER))
#define NM_IS_POLKIT_LISTENER_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((klass), NM_TYPE_POLKIT_LISTENER))
#define NM_POLKIT_LISTENER_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_POLKIT_LISTENER, NMPolkitListenerClass))
/**
* NMPolkitListenerOnRequestFunc:
* @request: the request asked by polkit agent
* @action_id: the action_id of the polkit request
* @message: the message of the polkit request
* @icon_name: the icon name of the polkit request
* @user: user name
* @echo_on: whether the response to the request should be echoed to the screen
* @user_data: user data for the callback
*
* Called as a result of a request by polkit. The function should obtain response
* to the request from user, i.e. get the password required.
*/
typedef char * (*NMPolkitListenerOnRequestFunc) (const char *request,
const char *action_id,
const char *message,
const char *icon_name,
const char *user,
gboolean echo_on,
gpointer user_data);
/**
* NMPolkitListenerOnShowInfoFunc:
* @text: the info text from polkit
*
* Called as a result of show-info signal by polkit.
*/
typedef void (*NMPolkitListenerOnShowInfoFunc) (const char *text);
/**
* NMPolkitListenerOnShowErrorFunc:
* @text: the error text from polkit
*
* Called as a result of show-error signal by polkit.
*/
typedef void (*NMPolkitListenerOnShowErrorFunc) (const char *text);
/**
* NMPolkitListenerCompletedFunc:
* @gained_authorization: whether the autorization was successful
*
* Called as a result of completed signal by polkit.
*/
typedef void (*NMPolkitListenerOnCompletedFunc) (gboolean gained_authorization);
typedef struct {
PolkitAgentListener parent;
} NMPolkitListener;
typedef struct {
PolkitAgentListenerClass parent;
} NMPolkitListenerClass;
GType nm_polkit_listener_get_type (void);
PolkitAgentListener* nm_polkit_listener_new (gboolean for_session, GError **error);
void nm_polkit_listener_set_request_callback (NMPolkitListener *self,
NMPolkitListenerOnRequestFunc request_callback,
gpointer request_callback_data);
void nm_polkit_listener_set_show_info_callback (NMPolkitListener *self,
NMPolkitListenerOnShowInfoFunc show_info_callback);
void nm_polkit_listener_set_show_error_callback (NMPolkitListener *self,
NMPolkitListenerOnShowErrorFunc show_error_callback);
void nm_polkit_listener_set_completed_callback (NMPolkitListener *self,
NMPolkitListenerOnCompletedFunc completed_callback);
G_END_DECLS
#endif /* __NM_POLKIT_LISTENER_H__ */

View File

@@ -498,6 +498,22 @@ else
fi fi
AC_SUBST(NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT) AC_SUBST(NM_CONFIG_DEFAULT_AUTH_POLKIT_TEXT)
PKG_CHECK_MODULES(POLKIT, [polkit-agent-1 >= 0.97], [have_pk_agent=yes],[have_pk_agent=no])
AC_ARG_ENABLE(polkit-agent, AS_HELP_STRING([--enable-polkit-agent], [enable polkit agent for clients]),
[enable_polkit_agent=${enableval}], [enable_polkit_agent=${have_pk_agent}])
if (test "${enable_polkit_agent}" = "yes"); then
if test x"$have_pk_agent" = x"no"; then
AC_MSG_ERROR(Polkit agent is required)
fi
AC_SUBST(POLKIT_CFLAGS)
AC_SUBST(POLKIT_LIBS)
AC_DEFINE(WITH_POLKIT_AGENT, 1, [Define if you have polkit agent])
else
AC_DEFINE(WITH_POLKIT_AGENT, 0, [Define if you have polkit agent])
fi
AM_CONDITIONAL(WITH_POLKIT_AGENT, test "${enable_polkit_agent}" = "yes")
AC_ARG_ENABLE(modify-system, AC_ARG_ENABLE(modify-system,
AS_HELP_STRING([--enable-modify-system], [Allow users to modify system connections])) AS_HELP_STRING([--enable-modify-system], [Allow users to modify system connections]))
if test "${enable_modify_system}" = "yes"; then if test "${enable_modify_system}" = "yes"; then
@@ -1013,6 +1029,7 @@ if test "${enable_polkit}" = "yes"; then
else else
echo " policykit: no" echo " policykit: no"
fi fi
echo " polkit agent: ${enable_polkit_agent}"
echo " selinux: $have_selinux" echo " selinux: $have_selinux"
echo echo

View File

@@ -6,8 +6,10 @@ clients/cli/connections.c
clients/cli/devices.c clients/cli/devices.c
clients/cli/general.c clients/cli/general.c
clients/cli/nmcli.c clients/cli/nmcli.c
clients/cli/polkit-agent.c
clients/cli/settings.c clients/cli/settings.c
clients/cli/utils.c clients/cli/utils.c
clients/common/nm-polkit-listener.c
clients/common/nm-secret-agent-simple.c clients/common/nm-secret-agent-simple.c
clients/nm-online.c clients/nm-online.c
clients/tui/newt/nmt-newt-utils.c clients/tui/newt/nmt-newt-utils.c