summaryrefslogtreecommitdiff
path: root/src/nmcli/agent.c
diff options
context:
space:
mode:
authorThomas Haller <thaller@redhat.com>2021-03-14 09:26:51 +0100
committerThomas Haller <thaller@redhat.com>2021-03-15 17:10:54 +0100
commit61f99307c6ce495be4c9c8d326665ccbd019f4e8 (patch)
treeb222db6f3dfdbd3c5ef497f2dad988399d4bf04c /src/nmcli/agent.c
parent71f0511b1faa008118fc0765f2b41c484715fc1a (diff)
downloadNetworkManager-61f99307c6ce495be4c9c8d326665ccbd019f4e8.tar.gz
cli: move from "clients/cli/" to "src/nmcli/"
Diffstat (limited to 'src/nmcli/agent.c')
-rw-r--r--src/nmcli/agent.c230
1 files changed, 230 insertions, 0 deletions
diff --git a/src/nmcli/agent.c b/src/nmcli/agent.c
new file mode 100644
index 0000000000..a0b23dd19b
--- /dev/null
+++ b/src/nmcli/agent.c
@@ -0,0 +1,230 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+/*
+ * Copyright (C) 2014 Red Hat, Inc.
+ */
+
+#include "libnm-client-aux-extern/nm-default-client.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <readline/readline.h>
+#include <readline/history.h>
+
+#include "common.h"
+#include "utils.h"
+#include "libnmc-base/nm-secret-agent-simple.h"
+#include "polkit-agent.h"
+#include "libnmc-base/nm-polkit-listener.h"
+
+static void
+usage(void)
+{
+ g_printerr(_("Usage: nmcli agent { COMMAND | help }\n\n"
+ "COMMAND := { secret | polkit | all }\n\n"));
+}
+
+static void
+usage_agent_secret(void)
+{
+ g_printerr(_("Usage: nmcli agent secret { help }\n"
+ "\n"
+ "Runs nmcli as NetworkManager secret agent. When NetworkManager requires\n"
+ "a password it asks registered agents for it. This command keeps nmcli running\n"
+ "and if a password is required asks the user for it.\n\n"));
+}
+
+static void
+usage_agent_polkit(void)
+{
+ g_printerr(_("Usage: nmcli agent polkit { help }\n"
+ "\n"
+ "Registers nmcli as a polkit action for the user session.\n"
+ "When a polkit daemon requires an authorization, nmcli asks the user and gives\n"
+ "the response back to polkit.\n\n"));
+}
+
+static void
+usage_agent_all(void)
+{
+ g_printerr(_("Usage: nmcli agent all { help }\n"
+ "\n"
+ "Runs nmcli as both NetworkManager secret and a polkit agent.\n\n"));
+}
+
+/* for pre-filling a string to readline prompt */
+static char *pre_input_deftext;
+static int
+set_deftext(void)
+{
+ if (pre_input_deftext && rl_startup_hook) {
+ rl_insert_text(pre_input_deftext);
+ g_free(pre_input_deftext);
+ pre_input_deftext = NULL;
+ rl_startup_hook = NULL;
+ }
+ return 0;
+}
+
+static gboolean
+get_secrets_from_user(const NmcConfig *nmc_config,
+ const char * request_id,
+ const char * title,
+ const char * msg,
+ GPtrArray * secrets)
+{
+ int i;
+
+ for (i = 0; i < secrets->len; i++) {
+ NMSecretAgentSimpleSecret *secret = secrets->pdata[i];
+ char * pwd = NULL;
+
+ /* Ask user for the password */
+ if (msg)
+ g_print("%s\n", msg);
+ if (secret->value) {
+ /* Prefill the password if we have it. */
+ rl_startup_hook = set_deftext;
+ pre_input_deftext = g_strdup(secret->value);
+ }
+ if (secret->no_prompt_entry_id)
+ pwd = nmc_readline(nmc_config, "%s: ", secret->pretty_name);
+ else
+ pwd = nmc_readline(nmc_config, "%s (%s): ", secret->pretty_name, secret->entry_id);
+
+ /* No password provided, cancel the secrets. */
+ if (!pwd)
+ return FALSE;
+ g_free(secret->value);
+ secret->value = pwd;
+ }
+ return TRUE;
+}
+
+static void
+secrets_requested(NMSecretAgentSimple *agent,
+ const char * request_id,
+ const char * title,
+ const char * msg,
+ GPtrArray * secrets,
+ gpointer user_data)
+{
+ NmCli * nmc = user_data;
+ gboolean success;
+
+ if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
+ nmc_terminal_erase_line();
+
+ success = get_secrets_from_user(&nmc->nmc_config, request_id, title, msg, secrets);
+ nm_secret_agent_simple_response(agent, request_id, success ? secrets : NULL);
+}
+
+static void
+do_agent_secret(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
+{
+ next_arg(nmc, &argc, &argv, NULL);
+ if (nmc->complete)
+ return;
+
+ /* Create secret agent */
+ nmc->secret_agent = nm_secret_agent_simple_new("nmcli-agent");
+ if (nmc->secret_agent) {
+ /* We keep running */
+ nmc->should_wait++;
+
+ nm_secret_agent_simple_enable(nmc->secret_agent, NULL);
+ g_signal_connect(nmc->secret_agent,
+ NM_SECRET_AGENT_SIMPLE_REQUEST_SECRETS,
+ G_CALLBACK(secrets_requested),
+ nmc);
+ g_print(_("nmcli successfully registered as a NetworkManager's secret agent.\n"));
+ } else {
+ g_string_printf(nmc->return_text, _("Error: secret agent initialization failed"));
+ nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
+ }
+}
+
+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 void
+do_agent_polkit(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
+{
+ gs_free_error GError *error = NULL;
+
+ next_arg(nmc, &argc, &argv, NULL);
+ if (nmc->complete)
+ return;
+
+ 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"),
+ error->message);
+ nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
+ } 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);
+
+ /* keep running */
+ nmc->should_wait++;
+ }
+}
+
+static void
+do_agent_all(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
+{
+ NMCResultCode r;
+
+ next_arg(nmc, &argc, &argv, NULL);
+ if (nmc->complete)
+ return;
+
+ /* Run both secret and polkit agent */
+ do_agent_secret(cmd, nmc, argc, argv);
+ r = nmc->return_value;
+ if (r != NMC_RESULT_SUCCESS) {
+ g_printerr("%s\n", nmc->return_text->str);
+ g_string_truncate(nmc->return_text, 0);
+ nmc->return_value = NMC_RESULT_SUCCESS;
+ }
+
+ do_agent_polkit(cmd, nmc, argc, argv);
+ if (nmc->return_value != NMC_RESULT_SUCCESS) {
+ g_printerr("%s\n", nmc->return_text->str);
+ g_string_truncate(nmc->return_text, 0);
+ }
+
+ if (r != NMC_RESULT_SUCCESS)
+ nmc->return_value = r;
+}
+
+void
+nmc_command_func_agent(const NMCCommand *cmd, NmCli *nmc, int argc, const char *const *argv)
+{
+ static const NMCCommand cmds[] = {
+ {"secret", do_agent_secret, usage_agent_secret, TRUE, TRUE},
+ {"polkit", do_agent_polkit, usage_agent_polkit, TRUE, TRUE},
+ {"all", do_agent_all, usage_agent_all, TRUE, TRUE},
+ {NULL, do_agent_all, usage, TRUE, TRUE},
+ };
+
+ next_arg(nmc, &argc, &argv, NULL);
+ nmc_do_cmd(nmc, cmds, *argv, argc, argv);
+}