mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager
synced 2024-10-04 23:31:19 +00:00
7e8a84ae10
On "nmcli agent all", when the polkit agent fails (while the NM agent succeeds), the failure is not communicated until the client exits.
236 lines
6.6 KiB
C
236 lines
6.6 KiB
C
/*
|
|
* nmcli - command-line tool for controlling NetworkManager
|
|
* Functions for running NM secret agent.
|
|
*
|
|
* 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 "nm-default.h"
|
|
|
|
#include "agent.h"
|
|
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <errno.h>
|
|
#include <readline/readline.h>
|
|
#include <readline/history.h>
|
|
|
|
#include "common.h"
|
|
#include "utils.h"
|
|
#include "nm-secret-agent-simple.h"
|
|
#include "polkit-agent.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 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);
|
|
}
|
|
pwd = nmc_readline ("%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 = (NmCli *) user_data;
|
|
gboolean success = FALSE;
|
|
|
|
if (nmc->nmc_config.print_output == NMC_PRINT_PRETTY)
|
|
nmc_terminal_erase_line ();
|
|
|
|
success = get_secrets_from_user (request_id, title, msg, secrets);
|
|
if (success)
|
|
nm_secret_agent_simple_response (agent, request_id, secrets);
|
|
else
|
|
nm_secret_agent_simple_response (agent, request_id, NULL);
|
|
}
|
|
|
|
|
|
static NMCResultCode
|
|
do_agent_secret (NmCli *nmc, int argc, char **argv)
|
|
{
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
if (nmc->complete)
|
|
return nmc->return_value;
|
|
|
|
/* 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 (NM_SECRET_AGENT_SIMPLE (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;
|
|
}
|
|
|
|
return nmc->return_value;
|
|
}
|
|
|
|
static NMCResultCode
|
|
do_agent_polkit (NmCli *nmc, int argc, char **argv)
|
|
{
|
|
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"),
|
|
error->message);
|
|
nmc->return_value = NMC_RESULT_ERROR_UNKNOWN;
|
|
g_error_free (error);
|
|
} else {
|
|
/* We keep running */
|
|
nmc->should_wait++;
|
|
|
|
g_print (_("nmcli successfully registered as a polkit agent.\n"));
|
|
}
|
|
|
|
return nmc->return_value;
|
|
}
|
|
|
|
static NMCResultCode
|
|
do_agent_all (NmCli *nmc, int argc, char **argv)
|
|
{
|
|
NMCResultCode secret_res;
|
|
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
if (nmc->complete)
|
|
return nmc->return_value;
|
|
|
|
/* Run both secret and polkit agent */
|
|
secret_res = do_agent_secret (nmc, argc, argv);
|
|
if (secret_res != NMC_RESULT_SUCCESS) {
|
|
g_printerr ("%s\n", nmc->return_text->str);
|
|
g_string_truncate (nmc->return_text, 0);
|
|
}
|
|
|
|
nmc->return_value = do_agent_polkit (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 (nmc->return_value == NMC_RESULT_SUCCESS && secret_res != NMC_RESULT_SUCCESS)
|
|
nmc->return_value = secret_res;
|
|
|
|
return nmc->return_value;
|
|
}
|
|
|
|
static const NMCCommand agent_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 },
|
|
};
|
|
|
|
NMCResultCode
|
|
do_agent (NmCli *nmc, int argc, char **argv)
|
|
{
|
|
next_arg (nmc, &argc, &argv, NULL);
|
|
nmc_do_cmd (nmc, agent_cmds, *argv, argc, argv);
|
|
|
|
return nmc->return_value;
|
|
}
|