diff options
author | Thomas Haller <thaller@redhat.com> | 2021-03-14 09:26:51 +0100 |
---|---|---|
committer | Thomas Haller <thaller@redhat.com> | 2021-03-15 17:10:54 +0100 |
commit | 61f99307c6ce495be4c9c8d326665ccbd019f4e8 (patch) | |
tree | b222db6f3dfdbd3c5ef497f2dad988399d4bf04c /src/nmcli/agent.c | |
parent | 71f0511b1faa008118fc0765f2b41c484715fc1a (diff) | |
download | NetworkManager-61f99307c6ce495be4c9c8d326665ccbd019f4e8.tar.gz |
cli: move from "clients/cli/" to "src/nmcli/"
Diffstat (limited to 'src/nmcli/agent.c')
-rw-r--r-- | src/nmcli/agent.c | 230 |
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); +} |