all: merge branch 'th/polkit-permissions-cleanup'

https://gitlab.freedesktop.org/NetworkManager/NetworkManager/merge_requests/355
This commit is contained in:
Thomas Haller 2019-12-10 09:21:24 +01:00
commit a5779595ce
29 changed files with 1643 additions and 1182 deletions

3
.gitignore vendored
View file

@ -128,7 +128,7 @@ test-*.trs
/examples/C/qt/monitor-nm-running
/examples/C/qt/monitor-nm-running.moc
/shared/nm-utils/tests/test-shared-general
/shared/nm-glib-aux/tests/test-shared-general
/shared/nm-version-macros.h
/introspection/org.freedesktop.NetworkManager*.[ch]
@ -325,6 +325,7 @@ test-*.trs
/libnm/tests/test-general
/policy/org.freedesktop.NetworkManager.policy
/policy/org.freedesktop.NetworkManager.policy.in
/shared/nm-utils/tests/test-shared-general
/src/devices/tests/test-arping
/src/devices/wifi/tests/test-general
/src/devices/wifi/tests/test-wifi-ap-utils

View file

@ -525,15 +525,52 @@ $(shared_nm_libnm_core_aux_libnm_libnm_core_aux_la_OBJECTS): $(libnm_core_lib_h_
###############################################################################
noinst_LTLIBRARIES += shared/nm-libnm-aux/libnm-libnm-aux.la
shared_nm_libnm_aux_libnm_libnm_aux_la_CPPFLAGS = \
$(dflt_cppflags) \
-I$(srcdir)/shared \
-I$(builddir)/shared \
-I$(srcdir)/libnm-core \
-I$(builddir)/libnm-core \
-I$(srcdir)/libnm \
-I$(builddir)/libnm \
$(CODE_COVERAGE_CFLAGS) \
$(GLIB_CFLAGS) \
$(SANITIZER_LIB_CFLAGS) \
-DG_LOG_DOMAIN=\""libnmc"\" \
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT \
$(NULL)
shared_nm_libnm_aux_libnm_libnm_aux_la_SOURCES = \
shared/nm-libnm-aux/nm-libnm-aux.c \
shared/nm-libnm-aux/nm-libnm-aux.h \
$(NULL)
shared_nm_libnm_aux_libnm_libnm_aux_la_LDFLAGS = \
$(CODE_COVERAGE_LDFLAGS) \
$(SANITIZER_LIB_LDFLAGS) \
$(NULL)
shared_nm_libnm_aux_libnm_libnm_aux_la_LIBADD = \
$(GLIB_LIBS) \
libnm/libnm.la \
$(NULL)
$(shared_nm_libnm_aux_libnm_libnm_aux_la_OBJECTS): $(libnm_core_lib_h_pub_mkenums)
$(shared_nm_libnm_aux_libnm_libnm_aux_la_OBJECTS): $(libnm_lib_h_pub_mkenums)
###############################################################################
EXTRA_DIST += \
shared/nm-utils/tests/meson.build \
shared/nm-glib-aux/tests/meson.build \
$(NULL)
###############################################################################
check_programs += shared/nm-utils/tests/test-shared-general
check_programs += shared/nm-glib-aux/tests/test-shared-general
shared_nm_utils_tests_test_shared_general_CPPFLAGS = \
shared_nm_glib_aux_tests_test_shared_general_CPPFLAGS = \
$(dflt_cppflags) \
-I$(srcdir)/shared \
-DNETWORKMANAGER_COMPILATION_TEST \
@ -543,12 +580,12 @@ shared_nm_utils_tests_test_shared_general_CPPFLAGS = \
$(SANITIZER_LIB_CFLAGS) \
$(NULL)
shared_nm_utils_tests_test_shared_general_LDFLAGS = \
shared_nm_glib_aux_tests_test_shared_general_LDFLAGS = \
$(CODE_COVERAGE_LDFLAGS) \
$(SANITIZER_EXEC_LDFLAGS) \
$(NULL)
shared_nm_utils_tests_test_shared_general_LDADD = \
shared_nm_glib_aux_tests_test_shared_general_LDADD = \
shared/nm-glib-aux/libnm-glib-aux.la \
shared/systemd/libnm-systemd-logging-stub.la \
shared/nm-std-aux/libnm-std-aux.la \
@ -4179,6 +4216,7 @@ clients_nm_online_LDFLAGS = \
-Wl,--version-script="$(srcdir)/linker-script-binary.ver"
clients_nm_online_LDADD = \
shared/nm-libnm-aux/libnm-libnm-aux.la \
libnm/libnm.la \
$(GLIB_LIBS)
@ -4401,6 +4439,7 @@ clients_cli_nmcli_LDADD = \
shared/nm-glib-aux/libnm-glib-aux.la \
shared/nm-std-aux/libnm-std-aux.la \
shared/libcsiphash.la \
shared/nm-libnm-aux/libnm-libnm-aux.la \
libnm/libnm.la \
$(GLIB_LIBS) \
$(READLINE_LIBS)
@ -4603,6 +4642,7 @@ clients_tui_nmtui_LDADD = \
clients/tui/newt/libnmt-newt.a \
clients/common/libnmc.la \
clients/common/libnmc-base.la \
shared/nm-libnm-aux/libnm-libnm-aux.la \
shared/nm-libnm-core-aux/libnm-libnm-core-aux.la \
shared/nm-libnm-core-intern/libnm-libnm-core-intern.la \
shared/nm-glib-aux/libnm-glib-aux.la \
@ -4669,6 +4709,7 @@ clients_cloud_setup_nm_cloud_setup_LDFLAGS = \
$(NULL)
clients_cloud_setup_nm_cloud_setup_LDADD = \
shared/nm-libnm-aux/libnm-libnm-aux.la \
shared/nm-libnm-core-aux/libnm-libnm-core-aux.la \
shared/nm-libnm-core-intern/libnm-libnm-core-intern.la \
shared/nm-glib-aux/libnm-glib-aux.la \

View file

@ -13,6 +13,8 @@
#include <readline/readline.h>
#include <readline/history.h>
#include "nm-libnm-aux/nm-libnm-aux.h"
#include "nm-vpn-helpers.h"
#include "nm-client-utils.h"
@ -1216,17 +1218,22 @@ got_client (GObject *source_object, GAsyncResult *res, gpointer user_data)
CmdCall *call = user_data;
NmCli *nmc;
nm_assert (NM_IS_CLIENT (source_object));
task = g_steal_pointer (&call->task);
nmc = g_task_get_task_data (task);
nmc->should_wait--;
nmc->client = nm_client_new_finish (res, &error);
if (!nmc->client) {
if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
res,
&error)) {
g_object_unref (source_object);
g_task_return_new_error (task, NMCLI_ERROR, NMC_RESULT_ERROR_UNKNOWN,
_("Error: Could not create NMClient object: %s."),
error->message);
} else {
nmc->client = NM_CLIENT (source_object);
call_cmd (nmc, g_steal_pointer (&task), call->cmd, call->argc, call->argv);
}
@ -1259,7 +1266,11 @@ call_cmd (NmCli *nmc, GTask *task, const NMCCommand *cmd, int argc, char **argv)
call->argc = argc;
call->argv = argv;
call->task = task;
nm_client_new_async (NULL, got_client, call);
nmc_client_new_async (NULL,
got_client,
call,
NM_CLIENT_INSTANCE_FLAGS, (guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
NULL);
}
}

View file

@ -22,6 +22,12 @@
/*****************************************************************************/
static void permission_changed (GObject *gobject,
GParamSpec *pspec,
NmCli *nmc);
/*****************************************************************************/
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (nm_state_to_string, NMState,
NM_UTILS_LOOKUP_DEFAULT (N_("unknown")),
NM_UTILS_LOOKUP_ITEM (NM_STATE_ASLEEP, N_("asleep")),
@ -77,44 +83,8 @@ connectivity_to_color (NMConnectivityState connectivity)
static const char *
permission_to_string (NMClientPermission perm)
{
switch (perm) {
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK;
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI;
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN;
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX;
case NM_CLIENT_PERMISSION_SLEEP_WAKE:
return NM_AUTH_PERMISSION_SLEEP_WAKE;
case NM_CLIENT_PERMISSION_NETWORK_CONTROL:
return NM_AUTH_PERMISSION_NETWORK_CONTROL;
case NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED:
return NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED;
case NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN:
return NM_AUTH_PERMISSION_WIFI_SHARE_OPEN;
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM:
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM;
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN:
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN;
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME:
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME;
case NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS:
return NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS;
case NM_CLIENT_PERMISSION_RELOAD:
return NM_AUTH_PERMISSION_RELOAD;
case NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK:
return NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK;
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS;
case NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK:
return NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK;
case NM_CLIENT_PERMISSION_WIFI_SCAN:
return NM_AUTH_PERMISSION_WIFI_SCAN;
default:
return _("unknown");
}
return nm_auth_permission_to_string (perm)
?: _("unknown");
}
NM_UTILS_LOOKUP_STR_DEFINE_STATIC (permission_result_to_string, NMClientPermissionResult,
@ -534,30 +504,54 @@ timeout_cb (gpointer user_data)
{
NmCli *nmc = (NmCli *) user_data;
g_signal_handlers_disconnect_by_func (nmc->client,
G_CALLBACK (permission_changed),
nmc);
g_string_printf (nmc->return_text, _("Error: Timeout %d sec expired."), nmc->timeout);
nmc->return_value = NMC_RESULT_ERROR_TIMEOUT_EXPIRED;
quit ();
return FALSE;
}
static int
static void
print_permissions (void *user_data)
{
NmCli *nmc = user_data;
gs_free_error GError *error = NULL;
const char *fields_str = NULL;
NMClientPermission perm;
guint i;
gpointer permissions[NM_CLIENT_PERMISSION_LAST + 1];
gpointer permissions[G_N_ELEMENTS (nm_auth_permission_sorted) + 1];
gboolean is_running;
int i;
is_running = nm_client_get_nm_running (nmc->client);
if ( is_running
&& nm_client_get_permissions_state (nmc->client) != NM_TERNARY_TRUE) {
/* wait longer. Permissions are not up to date. */
return;
}
g_signal_handlers_disconnect_by_func (nmc->client,
G_CALLBACK (permission_changed),
nmc);
if (!is_running) {
/* NetworkManager quit while we were waiting. */
g_string_printf (nmc->return_text, _("NetworkManager is not running."));
nmc->return_value = NMC_RESULT_ERROR_NM_NOT_RUNNING;
quit ();
return;
}
if (!nmc->required_fields || strcasecmp (nmc->required_fields, "common") == 0) {
} else if (strcasecmp (nmc->required_fields, "all") == 0) {
} else
fields_str = nmc->required_fields;
for (i = 0, perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++)
permissions[i++] = GINT_TO_POINTER (perm);
permissions[i++] = NULL;
for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++)
permissions[i] = GINT_TO_POINTER (nm_auth_permission_sorted[i]);
permissions[i] = NULL;
nm_cli_spawn_pager (nmc);
@ -573,59 +567,43 @@ print_permissions (void *user_data)
}
quit ();
return G_SOURCE_REMOVE;
}
static gboolean
got_permissions (NmCli *nmc)
{
NMClientPermission perm;
/* The server returns all the permissions at once, so if at least one is there
* we already received the reply. */
for (perm = NM_CLIENT_PERMISSION_NONE + 1; perm <= NM_CLIENT_PERMISSION_LAST; perm++) {
if (nm_client_get_permission_result (nmc->client, perm) != NM_CLIENT_PERMISSION_RESULT_UNKNOWN)
return TRUE;
}
return FALSE;
}
static void
permission_changed (NMClient *client,
NMClientPermission permission,
NMClientPermissionResult result,
permission_changed (GObject *gobject,
GParamSpec *pspec,
NmCli *nmc)
{
if (got_permissions (nmc)) {
/* Defer the printing, so that we have a chance to process the other
* permission-changed signals. */
g_signal_handlers_disconnect_by_func (nmc->client,
G_CALLBACK (permission_changed),
nmc);
g_idle_remove_by_data (nmc);
g_idle_add (print_permissions, nmc);
}
if (NM_IN_STRSET (pspec->name, NM_CLIENT_NM_RUNNING,
NM_CLIENT_PERMISSIONS_STATE))
print_permissions (nmc);
}
static gboolean
show_nm_permissions (NmCli *nmc)
{
/* The permissions are available now, just print them. */
if (got_permissions (nmc)) {
print_permissions (nmc);
return TRUE;
}
NMClientInstanceFlags instance_flags;
/* The client didn't get the permissions reply yet. Subscribe to changes. */
g_signal_connect (nmc->client, NM_CLIENT_PERMISSION_CHANGED,
G_CALLBACK (permission_changed), nmc);
instance_flags = nm_client_get_instance_flags (nmc->client);
instance_flags &= ~NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS;
g_object_set (nmc->client,
NM_CLIENT_INSTANCE_FLAGS, (guint) instance_flags,
NULL);
g_signal_connect (nmc->client,
"notify",
G_CALLBACK (permission_changed),
nmc);
if (nmc->timeout == -1)
nmc->timeout = 10;
g_timeout_add_seconds (nmc->timeout, timeout_cb, nmc);
nmc->should_wait++;
print_permissions (nmc);
return TRUE;
}

View file

@ -22,11 +22,11 @@ deps = [
libnmc_base_dep,
libnmc_dep,
readline_dep,
libnm_libnm_aux_dep,
]
if enable_polkit_agent
sources += nm_polkit_listener
deps += polkit_agent_dep
endif

View file

@ -2,8 +2,9 @@
#include "nm-default.h"
#include "nm-cloud-setup-utils.h"
#include "nm-libnm-aux/nm-libnm-aux.h"
#include "nm-cloud-setup-utils.h"
#include "nmcs-provider-ec2.h"
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
@ -122,58 +123,6 @@ out:
/*****************************************************************************/
typedef struct {
GMainLoop *main_loop;
NMClient *nmc;
} ClientCreateData;
static void
_nmc_create_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
gs_unref_object NMClient *nmc = NULL;
ClientCreateData *data = user_data;
gs_free_error GError *error = NULL;
nmc = nm_client_new_finish (result, &error);
if (!nmc) {
if (!nm_utils_error_is_cancelled (error, FALSE))
_LOGI ("failure to talk to NetworkManager: %s", error->message);
goto out;
}
if (!nm_client_get_nm_running (nmc)) {
_LOGI ("NetworkManager is not running");
goto out;
}
_LOGD ("NetworkManager is running");
nmcs_wait_for_objects_register (nmc);
nmcs_wait_for_objects_register (nm_client_get_context_busy_watcher (nmc));
data->nmc = g_steal_pointer (&nmc);
out:
g_main_loop_quit (data->main_loop);
}
static NMClient *
_nmc_create (GCancellable *sigterm_cancellable)
{
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (NULL, FALSE);
ClientCreateData data = {
.main_loop = main_loop,
};
nm_client_new_async (sigterm_cancellable, _nmc_create_cb, &data);
g_main_loop_run (main_loop);
return data.nmc;
}
/*****************************************************************************/
static char **
_nmc_get_hwaddrs (NMClient *nmc)
{
@ -593,6 +542,7 @@ main (int argc, const char *const*argv)
gs_unref_object NMCSProvider *provider = NULL;
gs_unref_object NMClient *nmc = NULL;
gs_unref_hashtable GHashTable *config_dict = NULL;
gs_free_error GError *error = NULL;
_nm_logging_enabled_init (g_getenv (NMCS_ENV_VARIABLE ("NM_CLOUD_SETUP_LOG")));
@ -616,9 +566,25 @@ main (int argc, const char *const*argv)
if (!provider)
goto done;
nmc = _nmc_create (sigterm_cancellable);
if (!nmc)
nmc_client_new_waitsync (sigterm_cancellable,
&nmc,
&error,
NM_CLIENT_INSTANCE_FLAGS, (guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
NULL);
nmcs_wait_for_objects_register (nmc);
nmcs_wait_for_objects_register (nm_client_get_context_busy_watcher (nmc));
if (error) {
if (!nm_utils_error_is_cancelled (error, FALSE))
_LOGI ("failure to talk to NetworkManager: %s", error->message);
goto done;
}
if (!nm_client_get_nm_running (nmc)) {
_LOGI ("NetworkManager is not running");
goto done;
}
config_dict = _get_config (sigterm_cancellable, provider, nmc);
if (!config_dict)

View file

@ -29,16 +29,15 @@ sources = files(
'nmcs-provider.c',
)
deps = [
libnmc_base_dep,
libnmc_dep,
libcurl_dep,
]
executable(
name,
sources,
dependencies: deps,
dependencies: [
libnmc_base_dep,
libnmc_dep,
libcurl_dep,
libnm_libnm_aux_dep,
],
c_args: clients_c_flags +
['-DG_LOG_DOMAIN="@0@"'.format(name)],
link_with: libnm_systemd_logging_stub,

View file

@ -2,15 +2,14 @@ clients_c_flags = ['-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_C
name = 'nm-online'
deps = [
libnm_dep,
libnm_nm_default_dep,
]
executable(
name,
name + '.c',
dependencies: deps,
dependencies: [
libnm_dep,
libnm_nm_default_dep,
libnm_libnm_aux_dep,
],
c_args: clients_c_flags + ['-DG_LOG_DOMAIN="@0@"'.format(name)],
link_args: ldflags_linker_script_binary,
link_depends: linker_script_binary,

View file

@ -23,6 +23,8 @@
#include <getopt.h>
#include <locale.h>
#include "nm-libnm-aux/nm-libnm-aux.h"
#define PROGRESS_STEPS 15
#define EXIT_NONE -1
@ -198,13 +200,16 @@ got_client (GObject *source_object, GAsyncResult *res, gpointer user_data)
{
OnlineData *data = user_data;
gs_free_error GError *error = NULL;
NMClient *client;
nm_assert (NM_IS_CLIENT (source_object));
nm_assert (NM_CLIENT (source_object) == data->client);
nm_clear_g_source (&data->client_new_timeout_id);
g_clear_object (&data->client_new_cancellable);
client = nm_client_new_finish (res, &error);
if (!client) {
if (!g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
res,
&error)) {
if (g_error_matches (error, G_IO_ERROR, G_IO_ERROR_CANCELLED))
return;
data->quiet = TRUE;
@ -214,8 +219,6 @@ got_client (GObject *source_object, GAsyncResult *res, gpointer user_data)
return;
}
data->client = client;
if (quit_if_connected (data))
return;
@ -285,7 +288,12 @@ main (int argc, char *argv[])
data.client_new_cancellable = g_cancellable_new ();
data.client_new_timeout_id = g_timeout_add_seconds (30, got_client_timeout, &data);
nm_client_new_async (data.client_new_cancellable, got_client, &data);
data.client = nmc_client_new_async (data.client_new_cancellable,
got_client,
&data,
NM_CLIENT_INSTANCE_FLAGS, (guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
NULL);
g_main_loop_run (data.loop);

File diff suppressed because it is too large Load diff

View file

@ -51,6 +51,7 @@ deps = [
libnmc_base_dep,
libnmc_dep,
libnmt_newt_dep,
libnm_libnm_aux_dep,
]
executable(

View file

@ -18,6 +18,8 @@
#include <locale.h>
#include <stdlib.h>
#include "nm-libnm-aux/nm-libnm-aux.h"
#include "nmt-newt.h"
#include "nm-editor-bindings.h"
@ -231,8 +233,11 @@ main (int argc, char **argv)
nm_editor_bindings_init ();
nm_client = nm_client_new (NULL, &error);
if (!nm_client) {
if (!nmc_client_new_waitsync (NULL,
&nm_client,
&error,
NM_CLIENT_INSTANCE_FLAGS, (guint) NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS,
NULL)) {
g_printerr (_("Could not contact NetworkManager: %s.\n"), error->message);
g_error_free (error);
exit (1);

View file

@ -1177,4 +1177,85 @@ typedef enum { /*< flags >*/
NM_DEVICE_INTERFACE_FLAG_CARRIER = 0x10000,
} NMDeviceInterfaceFlags;
/**
* NMClientPermission:
* @NM_CLIENT_PERMISSION_NONE: unknown or no permission
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking
* can be globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be
* globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be
* globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be
* globally enabled or disabled
* @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask
* NetworkManager to sleep and wake
* @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections
* can be started, stopped, and changed
* @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password
* protected Wi-Fi hotspot can be created
* @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot
* can be created
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections
* that are available to all users can be modified
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections
* owned by the current user can be modified
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the
* persistent hostname can be changed
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global
* DNS configuration
* @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload.
* @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints.
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device
* statistics can be globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether
* connectivity check can be enabled or disabled
* @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed
* @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
*
* #NMClientPermission values indicate various permissions that NetworkManager
* clients can obtain to perform certain tasks on behalf of the current user.
**/
typedef enum {
NM_CLIENT_PERMISSION_NONE = 0,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4,
NM_CLIENT_PERMISSION_SLEEP_WAKE = 5,
NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6,
NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7,
NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12,
NM_CLIENT_PERMISSION_RELOAD = 13,
NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16,
NM_CLIENT_PERMISSION_WIFI_SCAN = 17,
NM_CLIENT_PERMISSION_LAST = 17,
} NMClientPermission;
/**
* NMClientPermissionResult:
* @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization
* @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available
* @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the
* permission is available
* @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is
* denied by system policy
*
* #NMClientPermissionResult values indicate what authorizations and permissions
* the user requires to obtain a given #NMClientPermission
**/
typedef enum {
NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0,
NM_CLIENT_PERMISSION_RESULT_YES,
NM_CLIENT_PERMISSION_RESULT_AUTH,
NM_CLIENT_PERMISSION_RESULT_NO
} NMClientPermissionResult;
#endif /* __NM_DBUS_INTERFACE_H__ */

View file

@ -1652,3 +1652,10 @@ global:
nm_setting_gsm_get_auto_config;
nm_setting_ip_config_get_dhcp_hostname_flags;
} libnm_1_20_0;
libnm_1_24_0 {
global:
nm_client_get_instance_flags;
nm_client_get_permissions_state;
nm_client_instance_flags_get_type;
} libnm_1_22_0;

View file

@ -278,3 +278,21 @@ endif
if enable_tests
subdir('tests')
endif
libnm_libnm_aux = static_library(
'nm-libnm-aux',
sources: nm_libnm_aux_source,
c_args: [
'-DG_LOG_DOMAIN="@0@"'.format('libnmc'),
'-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_CLIENT',
],
dependencies: [
libnm_core_nm_default_dep,
libnm_dep,
],
)
libnm_libnm_aux_dep = declare_dependency(
include_directories: [shared_inc],
link_with: [libnm_libnm_aux],
)

View file

@ -195,6 +195,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMClient,
PROP_DBUS_CONNECTION,
PROP_DBUS_NAME_OWNER,
PROP_VERSION,
PROP_INSTANCE_FLAGS,
PROP_STATE,
PROP_STARTUP,
PROP_NM_RUNNING,
@ -222,6 +223,7 @@ NM_GOBJECT_PROPERTIES_DEFINE (NMClient,
PROP_DNS_RC_MANAGER,
PROP_DNS_CONFIGURATION,
PROP_CHECKPOINTS,
PROP_PERMISSIONS_STATE,
);
enum {
@ -278,7 +280,7 @@ typedef struct {
NMLDBusObject *dbobj_settings;
NMLDBusObject *dbobj_dns_manager;
GHashTable *permissions;
guint8 *permissions;
GCancellable *permissions_cancellable;
char *name_owner;
@ -290,6 +292,12 @@ typedef struct {
guint dbsid_nm_vpn_connection_state_changed;
guint dbsid_nm_check_permissions;
NMClientInstanceFlags instance_flags:3;
NMTernary permissions_state:3;
bool instance_flags_constructed:1;
bool udev_inited:1;
bool notify_event_lst_changed:1;
bool check_dbobj_visible_all:1;
@ -3311,27 +3319,35 @@ _dbus_nm_vpn_connection_state_changed_cb (GDBusConnection *connection,
static void
_emit_permissions_changed (NMClient *self,
GHashTable *permissions,
gboolean force_unknown)
const guint8 *old_permissions,
const guint8 *permissions)
{
GHashTableIter iter;
gpointer key;
gpointer value;
int i;
if (!permissions)
return;
if (self->obj_base.is_disposing)
return;
g_hash_table_iter_init (&iter, permissions);
while (g_hash_table_iter_next (&iter, &key, &value)) {
if (old_permissions == permissions)
return;
for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) {
NMClientPermission perm = nm_auth_permission_sorted[i];
NMClientPermissionResult perm_result = NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
NMClientPermissionResult perm_result_old = NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
if (permissions)
perm_result = permissions[perm - 1];
if (old_permissions)
perm_result_old = old_permissions[perm - 1];
if (perm_result == perm_result_old)
continue;
g_signal_emit (self,
signals[PERMISSION_CHANGED],
0,
GPOINTER_TO_UINT (key),
force_unknown
? (guint) NM_CLIENT_PERMISSION_NONE
: GPOINTER_TO_UINT (value));
(guint) perm,
(guint) perm_result);
}
}
@ -3344,10 +3360,11 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe
NMClientPrivate *priv;
gs_unref_variant GVariant *ret = NULL;
nm_auto_free_variant_iter GVariantIter *v_permissions = NULL;
gs_unref_hashtable GHashTable *old_permissions = NULL;
gs_free guint8 *old_permissions = NULL;
gs_free_error GError *error = NULL;
const char *pkey;
const char *pvalue;
int i;
ret = g_dbus_connection_call_finish (G_DBUS_CONNECTION (source), result, &error);
if ( !ret
@ -3359,63 +3376,73 @@ _dbus_check_permissions_start_cb (GObject *source, GAsyncResult *result, gpointe
g_clear_object (&priv->permissions_cancellable);
old_permissions = g_steal_pointer (&priv->permissions);
if (!ret) {
/* when the call completes, we always pretend success. Even a failure means
* that we fetched the permissions, however they are all unknown. */
NML_NMCLIENT_LOG_T (self, "GetPermissions call failed: %s", error->message);
return;
goto out;
}
NML_NMCLIENT_LOG_T (self, "GetPermissions call finished with success");
/* get list of old permissions for change notification */
old_permissions = g_steal_pointer (&priv->permissions);
priv->permissions = g_hash_table_new (nm_direct_hash, NULL);
g_variant_get (ret, "(a{ss})", &v_permissions);
while (g_variant_iter_next (v_permissions, "{&s&s}", &pkey, &pvalue)) {
NMClientPermission perm;
NMClientPermissionResult perm_result;
perm = nm_permission_to_client (pkey);
perm = nm_auth_permission_from_string (pkey);
if (perm == NM_CLIENT_PERMISSION_NONE)
continue;
perm_result = nm_permission_result_to_client (pvalue);
perm_result = nm_client_permission_result_from_string (pvalue);
g_hash_table_insert (priv->permissions,
GUINT_TO_POINTER (perm),
GUINT_TO_POINTER (perm_result));
if (old_permissions) {
g_hash_table_remove (old_permissions,
GUINT_TO_POINTER (perm));
if (!priv->permissions) {
if (perm_result == NM_CLIENT_PERMISSION_RESULT_UNKNOWN)
continue;
priv->permissions = g_new (guint8, G_N_ELEMENTS (nm_auth_permission_sorted));
for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++)
priv->permissions[i] = NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
}
priv->permissions[perm - 1] = perm_result;
}
out:
priv->permissions_state = NM_TERNARY_TRUE;
dbus_context = nm_g_main_context_push_thread_default_if_necessary (priv->main_context);
_emit_permissions_changed (self, priv->permissions, FALSE);
_emit_permissions_changed (self, old_permissions, TRUE);
_emit_permissions_changed (self, old_permissions, priv->permissions);
_notify (self, PROP_PERMISSIONS_STATE);
}
static void
_dbus_check_permissions_start (NMClient *self)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
gboolean fetch;
fetch = !NM_FLAGS_HAS ((NMClientInstanceFlags) priv->instance_flags,
NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS);
nm_clear_g_cancellable (&priv->permissions_cancellable);
priv->permissions_cancellable = g_cancellable_new ();
NML_NMCLIENT_LOG_T (self, "GetPermissions() call started...");
if (fetch) {
NML_NMCLIENT_LOG_T (self, "GetPermissions() call started...");
_nm_client_dbus_call_simple (self,
priv->permissions_cancellable,
NM_DBUS_PATH,
NM_DBUS_INTERFACE,
"GetPermissions",
g_variant_new ("()"),
G_VARIANT_TYPE ("(a{ss})"),
G_DBUS_CALL_FLAGS_NONE,
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
_dbus_check_permissions_start_cb,
self);
priv->permissions_cancellable = g_cancellable_new ();
_nm_client_dbus_call_simple (self,
priv->permissions_cancellable,
NM_DBUS_PATH,
NM_DBUS_INTERFACE,
"GetPermissions",
g_variant_new ("()"),
G_VARIANT_TYPE ("(a{ss})"),
G_DBUS_CALL_FLAGS_NONE,
NM_DBUS_DEFAULT_TIMEOUT_MSEC,
_dbus_check_permissions_start_cb,
self);
}
}
static void
@ -3428,6 +3455,7 @@ _dbus_nm_check_permissions_cb (GDBusConnection *connection,
gpointer user_data)
{
NMClient *self = user_data;
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("()"))) {
NML_NMCLIENT_LOG_E (self, "ignore CheckPermissions signal with unexpected signature %s",
@ -3436,6 +3464,10 @@ _dbus_nm_check_permissions_cb (GDBusConnection *connection,
}
_dbus_check_permissions_start (self);
if (priv->permissions_state == NM_TERNARY_TRUE)
priv->permissions_state = NM_TERNARY_FALSE;
_notify (self, PROP_PERMISSIONS_STATE);
}
/*****************************************************************************/
@ -3748,6 +3780,22 @@ _request_wait_finish (NMClient *client,
/*****************************************************************************/
/**
* nm_client_get_instance_flags:
* @self: the #NMClient instance.
*
* Returns: the #NMClientInstanceFlags flags.
*
* Since: 1.24
*/
NMClientInstanceFlags
nm_client_get_instance_flags (NMClient *self)
{
g_return_val_if_fail (NM_IS_CLIENT (self), NM_CLIENT_INSTANCE_FLAGS_NONE);
return NM_CLIENT_GET_PRIVATE (self)->instance_flags;
}
/**
* nm_client_get_dbus_connection:
* @client: a #NMClient
@ -4271,18 +4319,39 @@ NMClientPermissionResult
nm_client_get_permission_result (NMClient *client, NMClientPermission permission)
{
NMClientPrivate *priv;
gpointer result;
NMClientPermissionResult result = NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
g_return_val_if_fail (NM_IS_CLIENT (client), NM_CLIENT_PERMISSION_RESULT_UNKNOWN);
priv = NM_CLIENT_GET_PRIVATE (client);
if ( !priv->permissions
|| !g_hash_table_lookup_extended (priv->permissions,
GUINT_TO_POINTER (permission),
NULL,
&result))
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
return GPOINTER_TO_UINT (result);
if ( permission > NM_CLIENT_PERMISSION_NONE
&& permission <= NM_CLIENT_PERMISSION_LAST) {
priv = NM_CLIENT_GET_PRIVATE (client);
if (priv->permissions)
result = priv->permissions[permission - 1];
}
return result;
}
/**
* nm_client_get_permissions_state:
* @self: the #NMClient instance
*
* Returns: the state of the cached permissions. %NM_TERNARY_DEFAULT
* means that no permissions result was yet received. All permissions
* are unknown. %NM_TERNARY_TRUE means that the permissions got received
* and are cached. %%NM_TERNARY_FALSE means that permissions are cached,
* but they are invalided as as "CheckPermissions" signal was received
* in the meantime.
*
* Since: 1.24
*/
NMTernary
nm_client_get_permissions_state (NMClient *self)
{
g_return_val_if_fail (NM_IS_CLIENT (self), NM_TERNARY_DEFAULT);
return NM_CLIENT_GET_PRIVATE (self)->permissions_state;
}
/**
@ -6533,6 +6602,7 @@ _init_release_all (NMClient *self)
CList **dbus_objects_lst_heads;
NMLDBusObject *dbobj;
int i;
gboolean permissions_state_changed = FALSE;
NML_NMCLIENT_LOG_D (self, "release all");
@ -6552,12 +6622,20 @@ _init_release_all (NMClient *self)
nm_clear_g_dbus_connection_signal (priv->dbus_connection,
&priv->dbsid_nm_check_permissions);
if (priv->permissions) {
gs_unref_hashtable GHashTable *old_permissions = g_steal_pointer (&priv->permissions);
_emit_permissions_changed (self, old_permissions, TRUE);
if (priv->permissions_state != NM_TERNARY_DEFAULT) {
priv->permissions_state = NM_TERNARY_DEFAULT;
permissions_state_changed = TRUE;
}
if (priv->permissions) {
gs_free guint8 *old_permissions = g_steal_pointer (&priv->permissions);
_emit_permissions_changed (self, old_permissions, NULL);
}
if (permissions_state_changed)
_notify (self, PROP_PERMISSIONS_STATE);
nm_assert (c_list_is_empty (&priv->obj_changed_lst_head));
dbus_objects_lst_heads = ((CList *[]) {
@ -6927,6 +7005,9 @@ get_property (GObject *object, guint prop_id,
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (object);
switch (prop_id) {
case PROP_INSTANCE_FLAGS:
g_value_set_uint (value, priv->instance_flags);
break;
case PROP_DBUS_CONNECTION:
g_value_set_object (value, priv->dbus_connection);
break;
@ -7001,6 +7082,9 @@ get_property (GObject *object, guint prop_id,
case PROP_CHECKPOINTS:
g_value_take_boxed (value, _nm_utils_copy_object_array (nm_client_get_checkpoints (self)));
break;
case PROP_PERMISSIONS_STATE:
g_value_set_enum (value, priv->permissions_state);
break;
/* Settings properties. */
case PROP_CONNECTIONS:
@ -7039,8 +7123,38 @@ set_property (GObject *object, guint prop_id,
NMClient *self = NM_CLIENT (object);
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
gboolean b;
guint v_uint;
switch (prop_id) {
case PROP_INSTANCE_FLAGS:
/* construct */
v_uint = g_value_get_uint (value);
g_return_if_fail (!NM_FLAGS_ANY (v_uint, ~((guint) NM_CLIENT_INSTANCE_FLAGS_ALL)));
v_uint &= ((guint) NM_CLIENT_INSTANCE_FLAGS_ALL);
if (!priv->instance_flags_constructed) {
priv->instance_flags_constructed = TRUE;
priv->instance_flags = v_uint;
nm_assert ((guint) priv->instance_flags == v_uint);
} else {
NMClientInstanceFlags flags = v_uint;
/* After object construction, we only allow to toggle certain flags and
* ignore all other flags. */
if ((priv->instance_flags ^ flags) & NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS) {
if (NM_FLAGS_HAS (flags, NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS))
priv->instance_flags |= NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS;
else
priv->instance_flags &= ~NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS;
if (priv->dbsid_nm_check_permissions != 0)
_dbus_check_permissions_start (self);
}
}
break;
case PROP_DBUS_CONNECTION:
/* construct-only */
priv->dbus_connection = g_value_dup_object (value);
@ -7223,6 +7337,8 @@ nm_client_init (NMClient *self)
{
NMClientPrivate *priv = NM_CLIENT_GET_PRIVATE (self);
priv->permissions_state = NM_TERNARY_DEFAULT;
priv->context_busy_watcher = g_object_new (G_TYPE_OBJECT, NULL);
c_list_init (&self->obj_base.queue_notify_lst);
@ -7372,7 +7488,7 @@ dispose (GObject *object)
nm_clear_pointer (&priv->dbus_context, g_main_context_unref);
nm_clear_pointer (&priv->main_context, g_main_context_unref);
nm_clear_pointer (&priv->permissions, g_hash_table_unref);
nm_clear_g_free (&priv->permissions);
g_clear_object (&priv->dbus_connection);
@ -7473,6 +7589,30 @@ nm_client_class_init (NMClientClass *client_class)
G_PARAM_CONSTRUCT_ONLY |
G_PARAM_STATIC_STRINGS);
/**
* NMClient:instance-flags:
*
* #NMClientInstanceFlags for the instance. These affect behavior of #NMClient.
* This is a construct property and you may only set most flags only during
* construction.
*
* The flag %NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS can be toggled any time,
* even after constructing the instance. Note that you may want to watch NMClient:permissions-state
* property to know whether permissions are ready. Note that permissions are only fetched
* when NMClient has a D-Bus name owner.
*
* Since: 1.24
*/
obj_properties[PROP_INSTANCE_FLAGS] =
g_param_spec_uint (NM_CLIENT_INSTANCE_FLAGS, "", "",
0,
G_MAXUINT32,
0,
G_PARAM_READABLE |
G_PARAM_WRITABLE |
G_PARAM_CONSTRUCT |
G_PARAM_STATIC_STRINGS);
/**
* NMClient:dbus-name-owner:
*
@ -7832,6 +7972,32 @@ nm_client_class_init (NMClientClass *client_class)
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
/**
* NMClient:permissions-state:
*
* The state of the cached permissions. The value %NM_TERNARY_DEFAULT
* means that no permissions are yet received (or not yet requested).
* %NM_TERNARY_TRUE means that permissions are received, cached and up
* to date. %NM_TERNARY_FALSE means that permissions were received and are
* cached, but in the meantime a "CheckPermissions" signal was received
* that invalidated the cached permissions.
* Note that NMClient will always emit a notify::permissions-state signal
* when a "CheckPermissions" signal got received or after new permissions
* got received (that is regardless whether the value of the permission state
* actually changed). With this you can watch the permissions-state property
* to know whether the permissions are ready. Note that while NMClient has
* no D-Bus name owner, no permissions are fetched (and this property won't
* change).
*
* Since: 1.24
*/
obj_properties[PROP_PERMISSIONS_STATE] =
g_param_spec_enum (NM_CLIENT_PERMISSIONS_STATE, "", "",
NM_TYPE_TERNARY,
NM_TERNARY_DEFAULT,
G_PARAM_READABLE |
G_PARAM_STATIC_STRINGS);
_nml_dbus_meta_class_init_with_properties (object_class, &_nml_dbus_meta_iface_nm,
&_nml_dbus_meta_iface_nm_settings,
&_nml_dbus_meta_iface_nm_dnsmanager);

View file

@ -15,6 +15,23 @@
G_BEGIN_DECLS
/**
* NMClientInstanceFlags:
* @NM_CLIENT_INSTANCE_FLAGS_NONE: special value to indicate no flags.
* @NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS: by default, NMClient
* will fetch the permissions via "GetPermissions" and refetch them when
* "CheckPermissions" signal gets received. By setting this flag, this behavior
* can be disabled. You can toggle this flag to enable and disable automatic
* fetching of the permissions. Watch also nm_client_get_permissions_state()
* to know whether the permissions are up to date.
*
* Since: 1.24
*/
typedef enum { /*< flags >*/
NM_CLIENT_INSTANCE_FLAGS_NONE = 0,
NM_CLIENT_INSTANCE_FLAGS_NO_AUTO_FETCH_PERMISSIONS = 1,
} NMClientInstanceFlags;
#define NM_TYPE_CLIENT (nm_client_get_type ())
#define NM_CLIENT(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_CLIENT, NMClient))
#define NM_CLIENT_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_CLIENT, NMClientClass))
@ -28,6 +45,7 @@ G_BEGIN_DECLS
#define NM_CLIENT_NM_RUNNING "nm-running"
#define NM_CLIENT_DBUS_CONNECTION "dbus-connection"
#define NM_CLIENT_DBUS_NAME_OWNER "dbus-name-owner"
#define NM_CLIENT_INSTANCE_FLAGS "instance-flags"
_NM_DEPRECATED_SYNC_WRITABLE_PROPERTY
#define NM_CLIENT_NETWORKING_ENABLED "networking-enabled"
@ -63,6 +81,7 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY
#define NM_CLIENT_DNS_RC_MANAGER "dns-rc-manager"
#define NM_CLIENT_DNS_CONFIGURATION "dns-configuration"
#define NM_CLIENT_CHECKPOINTS "checkpoints"
#define NM_CLIENT_PERMISSIONS_STATE "permissions-state"
#define NM_CLIENT_DEVICE_ADDED "device-added"
#define NM_CLIENT_DEVICE_REMOVED "device-removed"
@ -74,87 +93,6 @@ _NM_DEPRECATED_SYNC_WRITABLE_PROPERTY
#define NM_CLIENT_ACTIVE_CONNECTION_ADDED "active-connection-added"
#define NM_CLIENT_ACTIVE_CONNECTION_REMOVED "active-connection-removed"
/**
* NMClientPermission:
* @NM_CLIENT_PERMISSION_NONE: unknown or no permission
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK: controls whether networking
* can be globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI: controls whether Wi-Fi can be
* globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN: controls whether WWAN (3G) can be
* globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX: controls whether WiMAX can be
* globally enabled or disabled
* @NM_CLIENT_PERMISSION_SLEEP_WAKE: controls whether the client can ask
* NetworkManager to sleep and wake
* @NM_CLIENT_PERMISSION_NETWORK_CONTROL: controls whether networking connections
* can be started, stopped, and changed
* @NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED: controls whether a password
* protected Wi-Fi hotspot can be created
* @NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN: controls whether an open Wi-Fi hotspot
* can be created
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM: controls whether connections
* that are available to all users can be modified
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN: controls whether connections
* owned by the current user can be modified
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME: controls whether the
* persistent hostname can be changed
* @NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS: modify persistent global
* DNS configuration
* @NM_CLIENT_PERMISSION_RELOAD: controls access to Reload.
* @NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK: permission to create checkpoints.
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS: controls whether device
* statistics can be globally enabled or disabled
* @NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK: controls whether
* connectivity check can be enabled or disabled
* @NM_CLIENT_PERMISSION_WIFI_SCAN: controls whether wifi scans can be performed
* @NM_CLIENT_PERMISSION_LAST: a reserved boundary value
*
* #NMClientPermission values indicate various permissions that NetworkManager
* clients can obtain to perform certain tasks on behalf of the current user.
**/
typedef enum {
NM_CLIENT_PERMISSION_NONE = 0,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK = 1,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI = 2,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN = 3,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX = 4,
NM_CLIENT_PERMISSION_SLEEP_WAKE = 5,
NM_CLIENT_PERMISSION_NETWORK_CONTROL = 6,
NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED = 7,
NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN = 8,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM = 9,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN = 10,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME = 11,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS = 12,
NM_CLIENT_PERMISSION_RELOAD = 13,
NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK = 14,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS = 15,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK = 16,
NM_CLIENT_PERMISSION_WIFI_SCAN = 17,
NM_CLIENT_PERMISSION_LAST = 17,
} NMClientPermission;
/**
* NMClientPermissionResult:
* @NM_CLIENT_PERMISSION_RESULT_UNKNOWN: unknown or no authorization
* @NM_CLIENT_PERMISSION_RESULT_YES: the permission is available
* @NM_CLIENT_PERMISSION_RESULT_AUTH: authorization is necessary before the
* permission is available
* @NM_CLIENT_PERMISSION_RESULT_NO: permission to perform the operation is
* denied by system policy
*
* #NMClientPermissionResult values indicate what authorizations and permissions
* the user requires to obtain a given #NMClientPermission
**/
typedef enum {
NM_CLIENT_PERMISSION_RESULT_UNKNOWN = 0,
NM_CLIENT_PERMISSION_RESULT_YES,
NM_CLIENT_PERMISSION_RESULT_AUTH,
NM_CLIENT_PERMISSION_RESULT_NO
} NMClientPermissionResult;
/**
* NMClientError:
* @NM_CLIENT_ERROR_FAILED: unknown or unclassified error
@ -214,6 +152,10 @@ void nm_client_new_async (GCancellable *cancellable,
NMClient *nm_client_new_finish (GAsyncResult *result,
GError **error);
NM_AVAILABLE_IN_1_24
NMClientInstanceFlags nm_client_get_instance_flags (NMClient *self);
NM_AVAILABLE_IN_1_22
GDBusConnection *nm_client_get_dbus_connection (NMClient *client);
@ -294,6 +236,9 @@ gboolean nm_client_set_logging (NMClient *client,
NMClientPermissionResult nm_client_get_permission_result (NMClient *client,
NMClientPermission permission);
NM_AVAILABLE_IN_1_24
NMTernary nm_client_get_permissions_state (NMClient *self);
NMConnectivityState nm_client_get_connectivity (NMClient *client);
_NM_DEPRECATED_SYNC_METHOD

View file

@ -663,88 +663,6 @@ nm_utils_fixup_product_string (const char *desc)
/*****************************************************************************/
NMClientPermission
nm_permission_to_client (const char *nm)
{
static const struct {
const char *name;
NMClientPermission perm;
} list[] = {
{ NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX },
{ NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN },
{ NM_AUTH_PERMISSION_NETWORK_CONTROL, NM_CLIENT_PERMISSION_NETWORK_CONTROL },
{ NM_AUTH_PERMISSION_RELOAD, NM_CLIENT_PERMISSION_RELOAD },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN },
{ NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM },
{ NM_AUTH_PERMISSION_SLEEP_WAKE, NM_CLIENT_PERMISSION_SLEEP_WAKE },
{ NM_AUTH_PERMISSION_WIFI_SCAN, NM_CLIENT_PERMISSION_WIFI_SCAN },
{ NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN },
{ NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED },
};
gssize idx;
#if NM_MORE_ASSERTS > 10
{
static gboolean checked = FALSE;
int i, j;
if (!checked) {
checked = TRUE;
for (i = 0; i < G_N_ELEMENTS (list); i++) {
nm_assert (list[i].perm != NM_CLIENT_PERMISSION_NONE);
nm_assert (list[i].name && list[i].name[0]);
if (i > 0) {
if (strcmp (list[i - 1].name, list[i].name) >= 0) {
g_error ("list is not sorted by name: #%d (%s) should be after #%d (%s)",
i - 1, list[i - 1].name, i, list[i].name);
}
}
for (j = i + 1; j < G_N_ELEMENTS (list); j++) {
nm_assert (list[i].perm != list[j].perm);
}
}
}
}
#endif
if (nm) {
idx = nm_utils_array_find_binary_search (list,
sizeof (list[0]),
G_N_ELEMENTS (list),
&nm,
nm_strcmp_p_with_data,
NULL);
if (idx >= 0)
return list[idx].perm;
}
return NM_CLIENT_PERMISSION_NONE;
}
NMClientPermissionResult
nm_permission_result_to_client (const char *nm)
{
if (!nm)
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
if (nm_streq (nm, "yes"))
return NM_CLIENT_PERMISSION_RESULT_YES;
if (nm_streq (nm, "no"))
return NM_CLIENT_PERMISSION_RESULT_NO;
if (nm_streq (nm, "auth"))
return NM_CLIENT_PERMISSION_RESULT_AUTH;
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
}
/*****************************************************************************/
const NMLDBusMetaIface *const _nml_dbus_meta_ifaces[] = {
&_nml_dbus_meta_iface_nm,
&_nml_dbus_meta_iface_nm_accesspoint,

View file

@ -29,12 +29,6 @@ gboolean nm_utils_g_param_spec_is_default (const GParamSpec *pspec);
/*****************************************************************************/
NMClientPermission nm_permission_to_client (const char *nm);
NMClientPermissionResult nm_permission_result_to_client (const char *nm);
/*****************************************************************************/
typedef enum {
_NML_DBUS_LOG_LEVEL_INITIALIZED = 0x01,
@ -172,6 +166,8 @@ typedef enum {
/*****************************************************************************/
#define NM_CLIENT_INSTANCE_FLAGS_ALL ((NMClientInstanceFlags) 0x1)
typedef struct {
GType (*get_o_type_fcn) (void);

View file

@ -22,6 +22,7 @@
#include "nm-libnm-utils.h"
#include "nm-object.h"
#include "nm-vpn-service-plugin.h"
#include "nm-libnm-core-intern/nm-libnm-core-utils.h"
#include "nm-utils/nm-test-utils.h"
@ -3064,6 +3065,49 @@ test_dbus_meta_types (void)
g_assert (meta_iface->get_type_fcn() == d->gtype);
}
}
/*****************************************************************************/
static void
test_nm_auth_permissions (void)
{
int i, j;
G_STATIC_ASSERT (G_N_ELEMENTS (nm_auth_permission_names_by_idx) == NM_CLIENT_PERMISSION_LAST);
G_STATIC_ASSERT (G_N_ELEMENTS (nm_auth_permission_sorted) == NM_CLIENT_PERMISSION_LAST);
for (i = 0; i < NM_CLIENT_PERMISSION_LAST; i++) {
g_assert (nm_auth_permission_names_by_idx[i]);
g_assert (NM_STR_HAS_PREFIX (nm_auth_permission_names_by_idx[i], "org.freedesktop.NetworkManager."));
g_assert_cmpint (nm_auth_permission_sorted[i], >, 0);
g_assert_cmpint (nm_auth_permission_sorted[i], <=, NM_CLIENT_PERMISSION_LAST);
for (j = i + 1; j < NM_CLIENT_PERMISSION_LAST; j++) {
g_assert_cmpint (nm_auth_permission_sorted[i], !=, nm_auth_permission_sorted[j]);
g_assert_cmpstr (nm_auth_permission_names_by_idx[i], !=, nm_auth_permission_names_by_idx[j]);
}
}
for (i = 1; i < NM_CLIENT_PERMISSION_LAST; i++) {
NMClientPermission a = nm_auth_permission_sorted[i - 1];
NMClientPermission b = nm_auth_permission_sorted[i];
const char *s_a = nm_auth_permission_names_by_idx[a - 1];
const char *s_b = nm_auth_permission_names_by_idx[b - 1];
g_assert_cmpstr (s_a, <, s_b);
g_assert (a != b);
g_assert (s_a != s_b);
}
for (i = 1; i <= NM_CLIENT_PERMISSION_LAST; i++) {
const char *s = nm_auth_permission_to_string (i);
g_assert_cmpstr (s, ==, nm_auth_permission_names_by_idx[i - 1]);
g_assert (s == nm_auth_permission_names_by_idx[i - 1]);
g_assert_cmpint (nm_auth_permission_from_string (s), ==, i);
}
return;
for (i = 0; i < NM_CLIENT_PERMISSION_LAST; i++)
g_assert_cmpint (nm_auth_permission_from_string (nm_auth_permission_names_by_idx[i]), ==, i + 1);
}
/*****************************************************************************/
NMTST_DEFINE ();
@ -3078,6 +3122,7 @@ int main (int argc, char **argv)
g_test_add_func ("/libnm/general/test_types", test_types);
g_test_add_func ("/libnm/general/test_nml_dbus_meta", test_nml_dbus_meta);
g_test_add_func ("/libnm/general/test_dbus_meta_types", test_dbus_meta_types);
g_test_add_func ("/libnm/general/test_nm_auth_permissions", test_nm_auth_permissions);
return g_test_run ();
}

View file

@ -111,6 +111,8 @@ nm_libnm_core_aux_source = files('nm-libnm-core-aux/nm-libnm-core-aux.c')
nm_libnm_core_utils_source = files('nm-libnm-core-intern/nm-libnm-core-utils.c')
nm_libnm_aux_source = files('nm-libnm-aux/nm-libnm-aux.c')
nm_meta_setting_source = files('nm-meta-setting.c')
nm_test_utils_impl_source = files('nm-test-utils-impl.c')
@ -168,15 +170,14 @@ libnm_utils_base_dep = declare_dependency(
link_with: libnm_utils_base,
)
deps = [
glib_nm_default_dep,
libudev_dep,
]
libnm_udev_aux = static_library(
'nm-udev-aux',
sources: 'nm-udev-aux/nm-udev-utils.c',
dependencies: deps,
dependencies: [
glib_nm_default_dep,
libudev_dep,
],
c_args: c_flags,
)
@ -256,5 +257,5 @@ libnm_systemd_logging_stub = static_library(
)
if enable_tests
subdir('nm-utils/tests')
subdir('nm-glib-aux/tests')
endif

View file

@ -14,7 +14,7 @@ exe = executable(
)
test(
'shared/nm-utils/' + test_unit,
'shared/nm-glib-aux/' + test_unit,
test_script,
args: test_args + [exe.full_path()],
timeout: default_test_timeout,

View file

@ -0,0 +1,146 @@
// SPDX-License-Identifier: LGPL-2.1+
#include "nm-default.h"
#include "nm-libnm-aux.h"
/*****************************************************************************/
NMClient *
nmc_client_new_async_valist (GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
const char *first_property_name,
va_list ap)
{
NMClient *nmc;
nmc = NM_CLIENT (g_object_new_valist (NM_TYPE_CLIENT, first_property_name, ap));
g_async_initable_init_async (G_ASYNC_INITABLE (nmc),
G_PRIORITY_DEFAULT,
cancellable,
callback,
user_data);
return nmc;
}
NMClient *
nmc_client_new_async (GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
const char *first_property_name,
...)
{
NMClient *nmc;
va_list ap;
va_start (ap, first_property_name);
nmc = nmc_client_new_async_valist (cancellable,
callback,
user_data,
first_property_name,
ap);
va_end (ap);
return nmc;
}
/*****************************************************************************/
typedef struct {
GMainLoop *main_loop;
NMClient *nmc;
GError *error;
} ClientCreateData;
static void
_nmc_client_new_waitsync_cb (GObject *source_object,
GAsyncResult *result,
gpointer user_data)
{
ClientCreateData *data = user_data;
g_async_initable_init_finish (G_ASYNC_INITABLE (source_object),
result,
&data->error);
g_main_loop_quit (data->main_loop);
}
/**
* nmc_client_new:
* @cancellable: the cancellable to abort the creation.
* @out_nmc: (out): (transfer full): if give, transfers a reference
* to the NMClient instance. Note that this never fails to create
* the NMClient GObject, but depending on the return value,
* the instance was successfully initialized or not.
* @error: the error if creation fails.
* @first_property_name: the name of the first property
* @...: the value of the first property, followed optionally by more
* name/value pairs, followed by %NULL
*
* Returns: %TRUE, if the client was successfully initalized.
*
* This uses nm_client_new_async() to create a NMClient instance,
* but it iterates the current GMainContext until the client is
* ready. As such, it waits for the client creation to complete
* (like sync nm_client_new()) but it iterates the caller's GMainContext
* (unlike sync nm_client_new()). This is often preferable, because
* sync nm_client_new() needs to create an additional internal GMainContext
* that it can iterate instead. That has a performance overhead that
* is often unnecessary.
*/
gboolean
nmc_client_new_waitsync (GCancellable *cancellable,
NMClient **out_nmc,
GError **error,
const char *first_property_name,
...)
{
gs_unref_object NMClient *nmc = NULL;
nm_auto_unref_gmainloop GMainLoop *main_loop = g_main_loop_new (g_main_context_get_thread_default (), FALSE);
ClientCreateData data = {
.main_loop = main_loop,
};
va_list ap;
#if NM_MORE_ASSERTS > 10
/* The sync initialization of NMClient is generally a bad idea, because it
* brings the overhead of an additional GMainContext. Anyway, since our own
* code no longer uses that, we hardly test those code paths. But they should
* work just the same. Randomly use instead the sync initialization in a debug
* build... */
if ((g_random_int () % 2) == 0) {
gboolean success;
va_start (ap, first_property_name);
nmc = NM_CLIENT (g_object_new_valist (NM_TYPE_CLIENT, first_property_name, ap));
va_end (ap);
/* iterate the context at least once, just so that the behavior from POV of the
* caller is roughly the same. */
g_main_context_iteration (nm_client_get_main_context (nmc), FALSE);
success = g_initable_init (G_INITABLE (nmc),
cancellable,
error);
NM_SET_OUT (out_nmc, g_steal_pointer (&nmc));
return success;
}
#endif
va_start (ap, first_property_name);
nmc = nmc_client_new_async_valist (cancellable,
_nmc_client_new_waitsync_cb,
&data,
first_property_name,
ap);
va_end (ap);
g_main_loop_run (main_loop);
NM_SET_OUT (out_nmc, g_steal_pointer (&nmc));
if (data.error) {
g_propagate_error (error, data.error);
return FALSE;
}
return TRUE;
}

View file

@ -0,0 +1,24 @@
// SPDX-License-Identifier: LGPL-2.1+
#ifndef __NM_LIBNM_AUX_H__
#define __NM_LIBNM_AUX_H__
NMClient *nmc_client_new_async_valist (GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
const char *first_property_name,
va_list ap);
NMClient *nmc_client_new_async (GCancellable *cancellable,
GAsyncReadyCallback callback,
gpointer user_data,
const char *first_property_name,
...);
gboolean nmc_client_new_waitsync (GCancellable *cancellable,
NMClient **out_nmc,
GError **error,
const char *first_property_name,
...);
#endif /* __NM_LIBNM_AUX_H__ */

View file

@ -4,6 +4,8 @@
#include "nm-libnm-core-utils.h"
#include "nm-common-macros.h"
/*****************************************************************************/
gboolean
@ -59,3 +61,120 @@ nm_utils_vlan_priority_map_parse_str (NMVlanPriorityMap map_type,
NM_SET_OUT (out_has_wildcard_to, v2 < 0);
return TRUE;
}
/*****************************************************************************/
const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST] = {
[NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK - 1] = NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK,
[NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK,
[NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK,
[NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS,
[NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI,
[NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX,
[NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN - 1] = NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN,
[NM_CLIENT_PERMISSION_NETWORK_CONTROL - 1] = NM_AUTH_PERMISSION_NETWORK_CONTROL,
[NM_CLIENT_PERMISSION_RELOAD - 1] = NM_AUTH_PERMISSION_RELOAD,
[NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS,
[NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME,
[NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN,
[NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM - 1] = NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM,
[NM_CLIENT_PERMISSION_SLEEP_WAKE - 1] = NM_AUTH_PERMISSION_SLEEP_WAKE,
[NM_CLIENT_PERMISSION_WIFI_SCAN - 1] = NM_AUTH_PERMISSION_WIFI_SCAN,
[NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN - 1] = NM_AUTH_PERMISSION_WIFI_SHARE_OPEN,
[NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED - 1] = NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED,
};
const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST] = {
NM_CLIENT_PERMISSION_CHECKPOINT_ROLLBACK,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_NETWORK,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_STATISTICS,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIFI,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WIMAX,
NM_CLIENT_PERMISSION_ENABLE_DISABLE_WWAN,
NM_CLIENT_PERMISSION_NETWORK_CONTROL,
NM_CLIENT_PERMISSION_RELOAD,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_HOSTNAME,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_OWN,
NM_CLIENT_PERMISSION_SETTINGS_MODIFY_SYSTEM,
NM_CLIENT_PERMISSION_SLEEP_WAKE,
NM_CLIENT_PERMISSION_WIFI_SCAN,
NM_CLIENT_PERMISSION_WIFI_SHARE_OPEN,
NM_CLIENT_PERMISSION_WIFI_SHARE_PROTECTED,
};
const char *
nm_auth_permission_to_string (NMClientPermission permission)
{
if (permission < 1)
return NULL;
if (permission > NM_CLIENT_PERMISSION_LAST)
return NULL;
return nm_auth_permission_names_by_idx[permission - 1];
}
#define AUTH_PERMISSION_PREFIX "org.freedesktop.NetworkManager."
static int
_nm_auth_permission_from_string_cmp (gconstpointer a, gconstpointer b, gpointer user_data)
{
const NMClientPermission *const p = a;
const char *const needle = b;
const char *ss = nm_auth_permission_names_by_idx[*p - 1];
nm_assert (NM_STR_HAS_PREFIX (ss, AUTH_PERMISSION_PREFIX));
nm_assert (ss[NM_STRLEN (AUTH_PERMISSION_PREFIX)] != '\0');
return strcmp (&ss[NM_STRLEN (AUTH_PERMISSION_PREFIX)], needle);
}
NMClientPermission
nm_auth_permission_from_string (const char *str)
{
gssize idx;
if (!str)
return NM_CLIENT_PERMISSION_NONE;
if (!NM_STR_HAS_PREFIX (str, AUTH_PERMISSION_PREFIX))
return NM_CLIENT_PERMISSION_NONE;
idx = nm_utils_array_find_binary_search (nm_auth_permission_sorted,
sizeof (nm_auth_permission_sorted[0]),
G_N_ELEMENTS (nm_auth_permission_sorted),
&str[NM_STRLEN (AUTH_PERMISSION_PREFIX)],
_nm_auth_permission_from_string_cmp,
NULL);
if (idx < 0)
return NM_CLIENT_PERMISSION_NONE;
return nm_auth_permission_sorted[idx];
}
/*****************************************************************************/
NMClientPermissionResult
nm_client_permission_result_from_string (const char *nm)
{
if (!nm)
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
if (nm_streq (nm, "yes"))
return NM_CLIENT_PERMISSION_RESULT_YES;
if (nm_streq (nm, "no"))
return NM_CLIENT_PERMISSION_RESULT_NO;
if (nm_streq (nm, "auth"))
return NM_CLIENT_PERMISSION_RESULT_AUTH;
return NM_CLIENT_PERMISSION_RESULT_UNKNOWN;
}
const char *
nm_client_permission_result_to_string (NMClientPermissionResult permission)
{
switch (permission) {
case NM_CLIENT_PERMISSION_RESULT_YES: return "yes";
case NM_CLIENT_PERMISSION_RESULT_NO: return "no";
case NM_CLIENT_PERMISSION_RESULT_AUTH: return "auth";
case NM_CLIENT_PERMISSION_RESULT_UNKNOWN: return "unknown";
}
nm_assert_not_reached ();
return NULL;
}

View file

@ -95,4 +95,17 @@ nm_setting_ip_config_get_addr_family (NMSettingIPConfig *s_ip)
* depends on other factors. */
#define NM_INFINIBAND_MAX_MTU ((guint) 65520)
/*****************************************************************************/
extern const char *const nm_auth_permission_names_by_idx[NM_CLIENT_PERMISSION_LAST];
extern const NMClientPermission nm_auth_permission_sorted[NM_CLIENT_PERMISSION_LAST];
const char *nm_auth_permission_to_string (NMClientPermission permission);
NMClientPermission nm_auth_permission_from_string (const char *str);
/*****************************************************************************/
NMClientPermissionResult nm_client_permission_result_from_string (const char *nm);
const char *nm_client_permission_result_to_string (NMClientPermissionResult permission);
#endif /* __NM_LIBNM_SHARED_UTILS_H__ */

View file

@ -11,12 +11,18 @@
/*****************************************************************************/
typedef enum {
NM_AUTH_CALL_RESULT_UNKNOWN,
NM_AUTH_CALL_RESULT_YES,
NM_AUTH_CALL_RESULT_AUTH,
NM_AUTH_CALL_RESULT_NO,
NM_AUTH_CALL_RESULT_UNKNOWN = NM_CLIENT_PERMISSION_RESULT_UNKNOWN,
NM_AUTH_CALL_RESULT_YES = NM_CLIENT_PERMISSION_RESULT_YES,
NM_AUTH_CALL_RESULT_AUTH = NM_CLIENT_PERMISSION_RESULT_AUTH,
NM_AUTH_CALL_RESULT_NO = NM_CLIENT_PERMISSION_RESULT_NO,
} NMAuthCallResult;
static inline NMClientPermissionResult
nm_auth_call_result_to_client (NMAuthCallResult result)
{
return (NMClientPermissionResult) result;
}
static inline NMAuthCallResult
nm_auth_call_result_eval (gboolean is_authorized,
gboolean is_challenge,

View file

@ -6198,30 +6198,13 @@ done:
/* Permissions */
static void
get_perm_add_result (NMManager *self, NMAuthChain *chain, GVariantBuilder *results, const char *permission)
{
NMAuthCallResult result;
result = nm_auth_chain_get_result (chain, permission);
if (result == NM_AUTH_CALL_RESULT_YES)
g_variant_builder_add (results, "{ss}", permission, "yes");
else if (result == NM_AUTH_CALL_RESULT_NO)
g_variant_builder_add (results, "{ss}", permission, "no");
else if (result == NM_AUTH_CALL_RESULT_AUTH)
g_variant_builder_add (results, "{ss}", permission, "auth");
else {
_LOGD (LOGD_CORE, "unknown auth chain result %d", result);
}
}
static void
get_permissions_done_cb (NMAuthChain *chain,
GDBusMethodInvocation *context,
gpointer user_data)
{
NMManager *self = NM_MANAGER (user_data);
GVariantBuilder results;
int i;
nm_assert (G_IS_DBUS_METHOD_INVOCATION (context));
@ -6229,22 +6212,15 @@ get_permissions_done_cb (NMAuthChain *chain,
g_variant_builder_init (&results, G_VARIANT_TYPE ("a{ss}"));
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SLEEP_WAKE);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_NETWORK_CONTROL);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_RELOAD);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS);
get_perm_add_result (self, chain, &results, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK);
for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) {
const char *permission = nm_auth_permission_names_by_idx[nm_auth_permission_sorted[i] - 1];
NMAuthCallResult result;
const char *result_str;
result = nm_auth_chain_get_result (chain, permission);
result_str = nm_client_permission_result_to_string (nm_auth_call_result_to_client (result));
g_variant_builder_add (&results, "{ss}", permission, result_str);
}
g_dbus_method_invocation_return_value (context,
g_variant_new ("(a{ss})", &results));
@ -6262,6 +6238,7 @@ impl_manager_get_permissions (NMDBusObject *obj,
NMManager *self = NM_MANAGER (obj);
NMManagerPrivate *priv = NM_MANAGER_GET_PRIVATE (self);
NMAuthChain *chain;
int i;
chain = nm_auth_chain_new_context (invocation, get_permissions_done_cb, self);
if (!chain) {
@ -6273,22 +6250,12 @@ impl_manager_get_permissions (NMDBusObject *obj,
}
c_list_link_tail (&priv->auth_lst_head, nm_auth_chain_parent_lst_list (chain));
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_NETWORK, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SLEEP_WAKE, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIFI, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WWAN, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_WIMAX, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_NETWORK_CONTROL, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_PROTECTED, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_WIFI_SHARE_OPEN, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_SYSTEM, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_OWN, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_HOSTNAME, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_SETTINGS_MODIFY_GLOBAL_DNS, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_RELOAD, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_CHECKPOINT_ROLLBACK, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_STATISTICS, FALSE);
nm_auth_chain_add_call (chain, NM_AUTH_PERMISSION_ENABLE_DISABLE_CONNECTIVITY_CHECK, FALSE);
for (i = 0; i < (int) G_N_ELEMENTS (nm_auth_permission_sorted); i++) {
const char *permission = nm_auth_permission_names_by_idx[nm_auth_permission_sorted[i] - 1];
nm_auth_chain_add_call_unsafe (chain, permission, FALSE);
}
}
static void