clients: polkit-agent: implement polkit agent without using libpolkit

This commit is contained in:
Antonio Cardace
2019-12-17 16:42:05 +01:00
parent 1e45865e4f
commit df1d214b2e
11 changed files with 956 additions and 518 deletions

View File

@@ -4255,6 +4255,8 @@ clients_common_libnmc_base_la_SOURCES = \
clients/common/nm-vpn-helpers.h \
clients/common/nm-client-utils.c \
clients/common/nm-client-utils.h \
clients/common/nm-polkit-listener.c \
clients/common/nm-polkit-listener.h \
$(NULL)
EXTRA_DIST += \
@@ -4446,14 +4448,6 @@ clients_cli_nmcli_LDADD = \
$(GLIB_LIBS) \
$(READLINE_LIBS)
if WITH_POLKIT_AGENT
clients_cli_nmcli_CPPFLAGS += $(POLKIT_CFLAGS)
clients_cli_nmcli_SOURCES += \
clients/common/nm-polkit-listener.c \
clients/common/nm-polkit-listener.h
clients_cli_nmcli_LDADD += $(POLKIT_LIBS)
endif
clients_cli_nmcli_LDFLAGS = \
-Wl,--version-script="$(srcdir)/linker-script-binary.ver" \
$(SANITIZER_EXEC_LDFLAGS)

View File

@@ -16,6 +16,7 @@
#include "utils.h"
#include "nm-secret-agent-simple.h"
#include "polkit-agent.h"
#include "nm-polkit-listener.h"
static void
usage (void)
@@ -149,27 +150,50 @@ do_agent_secret (NmCli *nmc, int argc, char **argv)
return nmc->return_value;
}
static void
polkit_registered (gpointer instance,
gpointer user_data)
{
g_print (_("nmcli successfully registered as a polkit agent.\n"));
}
static void
polkit_error (gpointer instance,
const char *error,
gpointer user_data)
{
g_main_loop_quit (loop);
}
static NMCResultCode
do_agent_polkit (NmCli *nmc, int argc, char **argv)
{
GError *error = NULL;
gs_free_error GError *error = NULL;
next_arg (nmc, &argc, &argv, NULL);
if (nmc->complete)
return nmc->return_value;
/* Initialize polkit agent */
if (!nmc_polkit_agent_init (nmc, TRUE, &error)) {
g_dbus_error_strip_remote_error (error);
g_string_printf (nmc->return_text, _("Error: polkit agent initialization failed: %s"),
g_string_printf (nmc->return_text,
_("Error: polkit agent initialization failed: %s"),
error->message);
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
g_error_free (error);
} else {
/* We keep running */
nmc->should_wait++;
g_signal_connect (nmc->pk_listener,
NM_POLKIT_LISTENER_SIGNAL_ERROR,
G_CALLBACK (polkit_error),
NULL);
g_signal_connect (nmc->pk_listener,
NM_POLKIT_LISTENER_SIGNAL_REGISTERED,
G_CALLBACK (polkit_registered),
NULL);
g_print (_("nmcli successfully registered as a polkit agent.\n"));
/* keep running */
nmc->should_wait++;
}
return nmc->return_value;

View File

@@ -6,18 +6,6 @@ install_data(
install_dir: join_paths(nm_datadir, 'bash-completion', 'completions'),
)
sources = files(
'agent.c',
'common.c',
'connections.c',
'devices.c',
'general.c',
'nmcli.c',
'polkit-agent.c',
'settings.c',
'utils.c',
)
deps = [
libnmc_base_dep,
libnmc_dep,
@@ -25,14 +13,19 @@ deps = [
libnm_libnm_aux_dep,
]
if enable_polkit_agent
sources += nm_polkit_listener
deps += polkit_agent_dep
endif
executable(
name,
sources,
files(
'agent.c',
'common.c',
'connections.c',
'devices.c',
'general.c',
'nmcli.c',
'polkit-agent.c',
'settings.c',
'utils.c',
),
dependencies: deps,
c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)],
link_args: ldflags_linker_script_binary,

View File

@@ -14,15 +14,11 @@
#include "nm-polkit-listener.h"
#include "common.h"
#if WITH_POLKIT_AGENT
static char *
polkit_request (NMPolkitListener *listener,
const char *request,
polkit_read_passwd (gpointer instance,
const char *action_id,
const char *message,
const char *icon_name,
const char *user,
gboolean echo_on,
gpointer user_data)
{
NmCli *nmc = user_data;
@@ -32,87 +28,68 @@ polkit_request (NMPolkitListener *listener,
/* Ask user for polkit authorization password */
if (user) {
gs_free char *tmp = NULL;
char *p;
/* chop of ": " if present */
tmp = g_strdup (request);
p = strrchr (tmp, ':');
if (p && nm_streq (p, ": "))
*p = '\0';
return nmc_readline_echo (&nmc->nmc_config, echo_on, "%s (%s): ", tmp, user);
return nmc_readline_echo (&nmc->nmc_config, FALSE, "password (%s): ", user);
}
return nmc_readline_echo (&nmc->nmc_config, echo_on, "%s", request);
return nmc_readline_echo (&nmc->nmc_config, FALSE, "password: ");
}
static void
polkit_show_info (NMPolkitListener *listener,
const char *text,
polkit_error (gpointer instance,
const char *error,
gpointer user_data)
{
g_print (_("Authentication message: %s\n"), text);
g_printerr (_("Error: polkit agent failed: %s\n"), error);
}
static void
polkit_show_error (NMPolkitListener *listener,
const char *text,
gpointer user_data)
{
g_print (_("Authentication error: %s\n"), text);
}
static void
polkit_completed (NMPolkitListener *listener,
gboolean gained_authorization,
gpointer user_data)
{
/* We don't print anything here. The outcome will be evident from
* the operation result anyway. */
}
#endif
gboolean
nmc_polkit_agent_init (NmCli* nmc, gboolean for_session, GError **error)
{
#if WITH_POLKIT_AGENT
static const NMPolkitListenVtable vtable = {
.on_request = polkit_request,
.on_show_info = polkit_show_info,
.on_show_error = polkit_show_error,
.on_completed = polkit_completed,
};
NMPolkitListener *listener;
GDBusConnection *dbus_connection = NULL;
g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
listener = nm_polkit_listener_new (for_session, error);
if (!listener)
return FALSE;
if (nmc->client && nm_client_get_dbus_connection (nmc->client)) {
dbus_connection = nm_client_get_dbus_connection (nmc->client);
listener = nm_polkit_listener_new (dbus_connection, for_session);
} else {
dbus_connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM,
NULL,
error);
nm_polkit_listener_set_vtable (listener, &vtable, nmc);
if (!dbus_connection) {
return FALSE;
}
listener = nm_polkit_listener_new (dbus_connection, for_session);
g_object_unref (dbus_connection);
}
g_signal_connect (listener,
NM_POLKIT_LISTENER_SIGNAL_REQUEST,
G_CALLBACK (polkit_read_passwd),
nmc);
g_signal_connect (listener,
NM_POLKIT_LISTENER_SIGNAL_ERROR,
G_CALLBACK (polkit_error),
NULL);
nmc->pk_listener = listener;
#endif
return TRUE;
}
void
nmc_polkit_agent_fini (NmCli* nmc)
{
#if WITH_POLKIT_AGENT
if (nmc->pk_listener) {
nm_polkit_listener_set_vtable (nmc->pk_listener, NULL, NULL);
g_clear_object (&nmc->pk_listener);
}
#endif
}
gboolean
nmc_start_polkit_agent_start_try (NmCli *nmc)
{
#if WITH_POLKIT_AGENT
GError *error = NULL;
gs_free_error GError *error = NULL;
/* We don't register polkit agent at all when running non-interactively */
if (!nmc->ask)
@@ -121,9 +98,7 @@ nmc_start_polkit_agent_start_try (NmCli *nmc)
if (!nmc_polkit_agent_init (nmc, FALSE, &error)) {
g_printerr (_("Warning: polkit agent initialization failed: %s\n"),
error->message);
g_error_free (error);
return FALSE;
}
#endif
return TRUE;
}

View File

@@ -1,7 +1,5 @@
common_inc = include_directories('.')
nm_polkit_listener = files('nm-polkit-listener.c')
common_deps = [
libnm_dep,
libnm_nm_default_dep,
@@ -13,6 +11,7 @@ sources = files(
'nm-client-utils.c',
'nm-secret-agent-simple.c',
'nm-vpn-helpers.c',
'nm-polkit-listener.c',
)
libnmc_base = static_library(

File diff suppressed because it is too large Load Diff

View File

@@ -6,133 +6,16 @@
#ifndef __NM_POLKIT_LISTENER_H__
#define __NM_POLKIT_LISTENER_H__
#if WITH_POLKIT_AGENT
typedef struct _NMPolkitListener NMPolkitListener;
typedef struct _NMPolkitListenerClass NMPolkitListenerClass;
typedef struct {
/*
* @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.
*/
char *(*on_request) (NMPolkitListener *self,
const char *request,
const char *action_id,
const char *message,
const char *icon_name,
const char *user,
gboolean echo_on,
gpointer user_data);
/*
* @text: the info text from polkit
*
* Called as a result of show-info signal by polkit.
*/
void (*on_show_info) (NMPolkitListener *self,
const char *text,
gpointer user_data);
/*
* @text: the error text from polkit
*
* Called as a result of show-error signal by polkit.
*/
void (*on_show_error) (NMPolkitListener *self,
const char *text,
gpointer user_data);
/*
* @gained_authorization: whether the authorization was successful
*
* Called as a result of completed signal by polkit.
*/
void (*on_completed) (NMPolkitListener *self,
gboolean gained_authorization,
gpointer user_data);
} NMPolkitListenVtable;
/*****************************************************************************/
#define POLKIT_AGENT_I_KNOW_API_IS_SUBJECT_TO_CHANGE
#include <polkitagent/polkitagent.h>
#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))
G_DECLARE_FINAL_TYPE (NMPolkitListener, nm_polkit_listener, NM, POLKIT_LISTENER, GObject)
/**
* 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 authorization was successful
*
* Called as a result of completed signal by polkit.
*/
typedef void (*NMPolkitListenerOnCompletedFunc) (gboolean gained_authorization);
NMPolkitListener *nm_polkit_listener_new (GDBusConnection *dbus_connection, gboolean session_agent);
struct _NMPolkitListener {
PolkitAgentListener parent;
};
struct _NMPolkitListenerClass {
PolkitAgentListenerClass parent;
};
GType nm_polkit_listener_get_type (void);
NMPolkitListener *nm_polkit_listener_new (gboolean for_session,
GError **error);
void nm_polkit_listener_set_vtable (NMPolkitListener *self,
const NMPolkitListenVtable *vtable,
gpointer user_data);
#endif
/* Signals */
#define NM_POLKIT_LISTENER_SIGNAL_REGISTERED "registered"
#define NM_POLKIT_LISTENER_SIGNAL_REQUEST "secret-request"
#define NM_POLKIT_LISTENER_SIGNAL_AUTH_SUCCESS "auth-success"
#define NM_POLKIT_LISTENER_SIGNAL_AUTH_FAILURE "auth-failure"
#define NM_POLKIT_LISTENER_SIGNAL_ERROR "error"
#endif /* __NM_POLKIT_LISTENER_H__ */

View File

@@ -221,8 +221,8 @@
/* Define if you have oFono support (experimental) */
#mesondefine WITH_OFONO
/* Define if you have polkit agent */
#mesondefine WITH_POLKIT_AGENT
/* Define the polkit agent package prefix */
#mesondefine POLKIT_PACKAGE_PREFIX
/* Define if you have PPP support */
#mesondefine WITH_PPP

View File

@@ -655,18 +655,13 @@ AC_DEFINE_UNQUOTED(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT, "$enable_polkit", [The de
AC_SUBST(NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT_TEXT, "$enable_polkit")
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
if test x"$have_pk_agent" = x"no"; then
AC_MSG_ERROR(Polkit agent is required)
fi
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")
POLKIT_PACKAGE_PREFIX=`$PKG_CONFIG --variable=prefix polkit-agent-1`
AC_DEFINE_UNQUOTED([POLKIT_PACKAGE_PREFIX],
["$POLKIT_PACKAGE_PREFIX"],
[polkit-agent package prefix])
AC_ARG_ENABLE(modify-system, AS_HELP_STRING([--enable-modify-system], [Allow users to modify system connections]))
if test "${enable_modify_system}" = "yes"; then
@@ -1323,7 +1318,6 @@ if test "${enable_modify_system}" = "yes"; then
else
echo " policykit: main.auth-polkit=${enable_polkit} (restrictive modify.system)"
fi
echo " polkit agent: ${enable_polkit_agent}"
echo " selinux: $have_selinux"
echo " systemd-journald: $have_systemd_journal (default: logging.backend=${nm_config_logging_backend_default})"
echo " hostname persist: ${hostname_persist}"

View File

@@ -586,7 +586,6 @@ This tool is still experimental.
-Dselinux=true \
-Dpolkit=true \
-Dconfig_auth_polkit_default=true \
-Dpolkit_agent=true \
-Dmodify_system=true \
-Dconcheck=true \
%if 0%{?fedora}
@@ -717,7 +716,6 @@ intltoolize --automake --copy --force
%endif
--with-selinux=yes \
--enable-polkit=yes \
--enable-polkit-agent \
--enable-modify-system=yes \
--enable-concheck \
%if 0%{?fedora}

View File

@@ -494,11 +494,12 @@ config_h.set_quoted('NM_CONFIG_DEFAULT_MAIN_AUTH_POLKIT', config_auth_polkit_def
enable_modify_system = get_option('modify_system')
enable_polkit_agent = get_option('polkit_agent')
if enable_polkit_agent
polkit_agent_dep = dependency('polkit-agent-1', version: '>= 0.97')
polkit_agent_dep = dependency('polkit-agent-1', version: '>= 0.97', required : false)
if polkit_agent_dep.found()
config_h.set_quoted('POLKIT_PACKAGE_PREFIX', polkit_agent_dep.get_pkgconfig_variable('prefix'))
else
config_h.set_quoted('POLKIT_PACKAGE_PREFIX', '/usr')
endif
config_h.set10('WITH_POLKIT_AGENT', enable_polkit_agent)
crypto = get_option('crypto')
@@ -971,7 +972,6 @@ if enable_polkit
output += ' modify.system)'
endif
output += '\n'
output += ' polkit agent: ' + enable_polkit_agent.to_string() + '\n'
output += ' selinux: ' + enable_selinux.to_string() + '\n'
output += ' systemd-journald: ' + enable_systemd_journal.to_string() + ' (default: logging.backend=' + config_logging_backend_default + ')\n'
output += ' hostname persist: ' + hostname_persist + '\n'