diff options
Diffstat (limited to 'clients/cli')
-rw-r--r-- | clients/cli/Makefile.am | 8 | ||||
-rw-r--r-- | clients/cli/nmcli.c | 24 | ||||
-rw-r--r-- | clients/cli/nmcli.h | 10 | ||||
-rw-r--r-- | clients/cli/polkit-agent.c | 146 | ||||
-rw-r--r-- | clients/cli/polkit-agent.h | 28 |
5 files changed, 215 insertions, 1 deletions
diff --git a/clients/cli/Makefile.am b/clients/cli/Makefile.am index 4f4fcf4c6d..2060c4bfff 100644 --- a/clients/cli/Makefile.am +++ b/clients/cli/Makefile.am @@ -30,6 +30,8 @@ nmcli_SOURCES = \ nmcli.h \ utils.c \ utils.h \ + polkit-agent.c \ + polkit-agent.h \ \ $(srcdir)/../common/nm-secret-agent-simple.c \ $(srcdir)/../common/nm-secret-agent-simple.h \ @@ -40,6 +42,12 @@ nmcli_LDADD = \ $(READLINE_LIBS) \ $(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 settings-docs.c: settings-docs.xsl $(top_builddir)/libnm-util/nm-setting-docs.xml $(AM_V_GEN) xsltproc --output $@ $^ diff --git a/clients/cli/nmcli.c b/clients/cli/nmcli.c index 8410020fee..76033417ee 100644 --- a/clients/cli/nmcli.c +++ b/clients/cli/nmcli.c @@ -27,6 +27,8 @@ #include <stdlib.h> #include <signal.h> #include <pthread.h> +#include <termios.h> +#include <unistd.h> #include <locale.h> #include <readline/readline.h> #include <readline/history.h> @@ -34,6 +36,7 @@ #include <glib.h> #include <glib/gi18n.h> +#include "polkit-agent.h" #include "nmcli.h" #include "utils.h" #include "common.h" @@ -61,6 +64,7 @@ typedef struct { /* --- Global variables --- */ GMainLoop *loop = NULL; static sigset_t signal_set; +struct termios termios_orig; /* Get an error quark for use with GError */ @@ -261,8 +265,18 @@ parse_command_line (NmCli *nmc, int argc, char **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); + } usage (base); return nmc->return_value; @@ -332,6 +346,7 @@ signal_handling_thread (void *arg) { pthread_mutex_unlock (&sigint_mutex); } else { /* We can quit nmcli */ + tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_orig); nmc_cleanup_readline (); g_print (_("\nError: nmcli terminated by signal %s (%d)\n"), strsignal (signo), signo); @@ -340,6 +355,7 @@ signal_handling_thread (void *arg) { break; case SIGQUIT: case SIGTERM: + tcsetattr (STDIN_FILENO, TCSADRAIN, &termios_orig); nmc_cleanup_readline (); if (!nmcli_sigquit_internal) g_print (_("\nError: nmcli terminated by signal %s (%d)\n"), @@ -502,6 +518,7 @@ nmc_init (NmCli *nmc) nmc->secret_agent = NULL; nmc->pwds_hash = NULL; + nmc->pk_listener = NULL; nmc->should_wait = FALSE; nmc->nowait_flag = TRUE; @@ -539,6 +556,8 @@ nmc_cleanup (NmCli *nmc) g_free (nmc->required_fields); nmc_empty_output_fields (nmc); g_ptr_array_unref (nmc->output_data); + + nmc_polkit_agent_fini (nmc); } static gboolean @@ -576,6 +595,9 @@ main (int argc, char *argv[]) #if !GLIB_CHECK_VERSION (2, 35, 0) g_type_init (); #endif + + /* Save terminal settings */ + tcgetattr (STDIN_FILENO, &termios_orig); /* readline init */ rl_event_hook = event_hook_for_readline; diff --git a/clients/cli/nmcli.h b/clients/cli/nmcli.h index a18de18546..5cd7526a8d 100644 --- a/clients/cli/nmcli.h +++ b/clients/cli/nmcli.h @@ -20,8 +20,17 @@ #ifndef NMC_NMCLI_H #define NMC_NMCLI_H +#include "config.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 */ typedef enum { /* Indicates successful execution */ @@ -114,6 +123,7 @@ typedef struct _NmCli { NMSecretAgent *secret_agent; /* Secret agent */ 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 nowait_flag; /* '--nowait' option; used for passing to callbacks */ diff --git a/clients/cli/polkit-agent.c b/clients/cli/polkit-agent.c new file mode 100644 index 0000000000..e8502884e4 --- /dev/null +++ b/clients/cli/polkit-agent.c @@ -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 */ diff --git a/clients/cli/polkit-agent.h b/clients/cli/polkit-agent.h new file mode 100644 index 0000000000..2e0326bc97 --- /dev/null +++ b/clients/cli/polkit-agent.h @@ -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__ */ |