|
Packit Service |
d328f3 |
// SPDX-License-Identifier: GPL-2.0+
|
|
Packit Service |
d328f3 |
/* NetworkManager Applet -- allow user control over networking
|
|
Packit Service |
d328f3 |
*
|
|
Packit Service |
d328f3 |
* Dan Williams <dcbw@redhat.com>
|
|
Packit Service |
d328f3 |
*
|
|
Packit Service |
d328f3 |
* Copyright 2004 - 2019 Red Hat, Inc.
|
|
Packit Service |
d328f3 |
* (C) Copyright 2018 Lubomir Rintel
|
|
Packit Service |
d328f3 |
*/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "nm-default.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "applet-vpn-request.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include <stdio.h>
|
|
Packit Service |
d328f3 |
#include <stdlib.h>
|
|
Packit Service |
d328f3 |
#include <string.h>
|
|
Packit Service |
d328f3 |
#include <sys/types.h>
|
|
Packit Service |
d328f3 |
#include <sys/wait.h>
|
|
Packit Service |
d328f3 |
#include <unistd.h>
|
|
Packit Service |
d328f3 |
#include <errno.h>
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
#include "nma-vpn-password-dialog.h"
|
|
Packit Service |
d328f3 |
#include "nm-utils/nm-compat.h"
|
|
Packit Service |
d328f3 |
#include "nm-utils/nm-shared-utils.h"
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
char *name;
|
|
Packit Service |
d328f3 |
char *label;
|
|
Packit Service |
d328f3 |
char *value;
|
|
Packit Service |
d328f3 |
gboolean is_secret;
|
|
Packit Service |
d328f3 |
gboolean should_ask;
|
|
Packit Service |
d328f3 |
} EuiSecret;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
char *uuid;
|
|
Packit Service |
d328f3 |
char *id;
|
|
Packit Service |
d328f3 |
char *service_type;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
guint watch_id;
|
|
Packit Service |
d328f3 |
GPid pid;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
int child_stdout;
|
|
Packit Service |
d328f3 |
GString *child_response;
|
|
Packit Service |
d328f3 |
GIOChannel *channel;
|
|
Packit Service |
d328f3 |
guint channel_eventid;
|
|
Packit Service |
d328f3 |
GVariantBuilder secrets_builder;
|
|
Packit Service |
d328f3 |
gboolean external_ui_mode;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* These are just for the external UI mode */
|
|
Packit Service |
d328f3 |
EuiSecret *eui_secrets;
|
|
Packit Service |
d328f3 |
GtkDialog *dialog;
|
|
Packit Service |
d328f3 |
} RequestData;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
typedef struct {
|
|
Packit Service |
d328f3 |
SecretsRequest req;
|
|
Packit Service |
d328f3 |
RequestData *req_data;
|
|
Packit Service |
d328f3 |
} VpnSecretsInfo;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void complete_request (VpnSecretsInfo *info);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
size_t
|
|
Packit Service |
d328f3 |
applet_vpn_request_get_secrets_size (void)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
return sizeof (VpnSecretsInfo);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
external_ui_add_secrets (VpnSecretsInfo *info)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
EuiSecret *secret;
|
|
Packit Service |
d328f3 |
guint i;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
for (i = 0; req_data->eui_secrets[i].name; i++) {
|
|
Packit Service |
d328f3 |
secret = &req_data->eui_secrets[i];
|
|
Packit Service |
d328f3 |
if ( secret->is_secret
|
|
Packit Service |
d328f3 |
&& secret->value
|
|
Packit Service |
d328f3 |
&& secret->value[0]) {
|
|
Packit Service |
d328f3 |
g_variant_builder_add (&req_data->secrets_builder, "{ss}",
|
|
Packit Service |
d328f3 |
secret->name,
|
|
Packit Service |
d328f3 |
secret->value);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
external_ui_dialog_response (GtkDialog *dialog, int response_id, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
VpnSecretsInfo *info = user_data;
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
NMAVpnPasswordDialog *vpn_dialog = NMA_VPN_PASSWORD_DIALOG (dialog);
|
|
Packit Service |
d328f3 |
EuiSecret *secret;
|
|
Packit Service |
d328f3 |
const char *value;
|
|
Packit Service |
d328f3 |
guint i_secret, i_pw;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
for (i_secret = 0, i_pw = 0; req_data->eui_secrets[i_secret].name; i_secret++) {
|
|
Packit Service |
d328f3 |
secret = &req_data->eui_secrets[i_secret];
|
|
Packit Service |
d328f3 |
if ( secret->is_secret
|
|
Packit Service |
d328f3 |
&& secret->should_ask) {
|
|
Packit Service |
d328f3 |
switch (i_pw) {
|
|
Packit Service |
d328f3 |
case 0:
|
|
Packit Service |
d328f3 |
value = nma_vpn_password_dialog_get_password (vpn_dialog);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
case 1:
|
|
Packit Service |
d328f3 |
value = nma_vpn_password_dialog_get_password_secondary (vpn_dialog);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
case 2:
|
|
Packit Service |
d328f3 |
value = nma_vpn_password_dialog_get_password_ternary (vpn_dialog);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
default:
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_free (secret->value);
|
|
Packit Service |
d328f3 |
secret->value = g_strdup (value);
|
|
Packit Service |
d328f3 |
i_pw++;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gtk_widget_destroy (GTK_WIDGET (dialog));
|
|
Packit Service |
d328f3 |
g_clear_object (&req_data->dialog);
|
|
Packit Service |
d328f3 |
external_ui_add_secrets (info);
|
|
Packit Service |
d328f3 |
complete_request (info);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
external_ui_from_child_response (VpnSecretsInfo *info, GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
gs_unref_keyfile GKeyFile *keyfile = NULL;
|
|
Packit Service |
d328f3 |
gs_strfreev char **groups = NULL;
|
|
Packit Service |
d328f3 |
NMAVpnPasswordDialog *dialog = NULL;
|
|
Packit Service |
d328f3 |
gs_free char *version = NULL;
|
|
Packit Service |
d328f3 |
gs_free char *title = NULL;
|
|
Packit Service |
d328f3 |
gs_free char *message = NULL;
|
|
Packit Service |
d328f3 |
gsize num_groups;
|
|
Packit Service |
d328f3 |
guint num_ask = 0;
|
|
Packit Service |
d328f3 |
guint i_group, i_secret, i_pw;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Parse response key file */
|
|
Packit Service |
d328f3 |
keyfile = g_key_file_new ();
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!g_key_file_load_from_data (keyfile,
|
|
Packit Service |
d328f3 |
req_data->child_response->str,
|
|
Packit Service |
d328f3 |
req_data->child_response->len,
|
|
Packit Service |
d328f3 |
G_KEY_FILE_NONE,
|
|
Packit Service |
d328f3 |
error)) {
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
groups = g_key_file_get_groups (keyfile, &num_groups);
|
|
Packit Service |
d328f3 |
if (g_strcmp0 (groups[0], "VPN Plugin UI") != 0) {
|
|
Packit Service |
d328f3 |
g_set_error_literal (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
"Expected [VPN Plugin UI]");
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
version = g_key_file_get_string (keyfile, "VPN Plugin UI", "Version", error);
|
|
Packit Service |
d328f3 |
if (!version)
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
if (strcmp (version, "2") != 0) {
|
|
Packit Service |
d328f3 |
g_set_error_literal (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
"Expected Version=2");
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
title = g_key_file_get_string (keyfile, "VPN Plugin UI", "Title", error);
|
|
Packit Service |
d328f3 |
if (!title)
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
message = g_key_file_get_string (keyfile, "VPN Plugin UI", "Description", error);
|
|
Packit Service |
d328f3 |
if (!message)
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Create a secret instance for each group */
|
|
Packit Service |
d328f3 |
req_data->eui_secrets = g_new0 (EuiSecret, num_groups);
|
|
Packit Service |
d328f3 |
for (i_group = 1, i_secret = 0; i_group < num_groups; i_group++) {
|
|
Packit Service |
d328f3 |
EuiSecret *secret = &req_data->eui_secrets[i_secret];
|
|
Packit Service |
d328f3 |
const char *group = groups[i_group];
|
|
Packit Service |
d328f3 |
char *label;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
label = g_key_file_get_string (keyfile, group, "Label", NULL);
|
|
Packit Service |
d328f3 |
if (!label) {
|
|
Packit Service |
d328f3 |
g_warning ("Skipping entry: no label\n");
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
secret->name = g_strdup (group);
|
|
Packit Service |
d328f3 |
secret->label = label;
|
|
Packit Service |
d328f3 |
secret->value = g_key_file_get_string (keyfile, group, "Value", NULL);
|
|
Packit Service |
d328f3 |
secret->is_secret = g_key_file_get_boolean (keyfile, group, "IsSecret", NULL);
|
|
Packit Service |
d328f3 |
secret->should_ask = g_key_file_get_boolean (keyfile, group, "ShouldAsk", NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
i_secret++;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (secret->is_secret && secret->should_ask)
|
|
Packit Service |
d328f3 |
num_ask++;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* If there are any secrets that must be asked to user,
|
|
Packit Service |
d328f3 |
* create a dialog and display it. */
|
|
Packit Service |
d328f3 |
if (num_ask > 0) {
|
|
Packit Service |
d328f3 |
dialog = (NMAVpnPasswordDialog *) nma_vpn_password_dialog_new (title, message, NULL);
|
|
Packit Service |
d328f3 |
req_data->dialog = g_object_ref_sink (dialog);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_show_password (dialog, FALSE);
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_show_password_secondary (dialog, FALSE);
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_show_password_ternary (dialog, FALSE);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
for (i_secret = 0, i_pw = 0; req_data->eui_secrets[i_secret].name; i_secret++) {
|
|
Packit Service |
d328f3 |
EuiSecret *secret = &req_data->eui_secrets[i_secret];
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if ( secret->is_secret
|
|
Packit Service |
d328f3 |
&& secret->should_ask) {
|
|
Packit Service |
d328f3 |
switch (i_pw) {
|
|
Packit Service |
d328f3 |
case 0:
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_show_password (dialog, TRUE);
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_password_label (dialog, secret->label);
|
|
Packit Service |
d328f3 |
if (secret->value)
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_password (dialog, secret->value);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
case 1:
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_show_password_secondary (dialog, TRUE);
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_password_secondary_label (dialog, secret->label);
|
|
Packit Service |
d328f3 |
if (secret->value)
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_password_secondary (dialog, secret->value);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
case 2:
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_show_password_ternary (dialog, TRUE);
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_password_ternary_label (dialog, secret->label);
|
|
Packit Service |
d328f3 |
if (secret->value)
|
|
Packit Service |
d328f3 |
nma_vpn_password_dialog_set_password_ternary (dialog, secret->value);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
default:
|
|
Packit Service |
d328f3 |
g_warning ("Skipping entry: more than 3 passwords not supported\n");
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
i_pw++;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_signal_connect (dialog,
|
|
Packit Service |
d328f3 |
"response",
|
|
Packit Service |
d328f3 |
G_CALLBACK (external_ui_dialog_response),
|
|
Packit Service |
d328f3 |
info);
|
|
Packit Service |
d328f3 |
gtk_widget_show (GTK_WIDGET (dialog));
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Nothing to ask, return known secrets */
|
|
Packit Service |
d328f3 |
external_ui_add_secrets (info);
|
|
Packit Service |
d328f3 |
complete_request (info);
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
complete_request (VpnSecretsInfo *info)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
SecretsRequest *req = (SecretsRequest *) info;
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
GVariantBuilder settings_builder, vpn_builder;
|
|
Packit Service |
d328f3 |
gs_unref_variant GVariant *settings = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_variant_builder_init (&settings_builder, NM_VARIANT_TYPE_CONNECTION);
|
|
Packit Service |
d328f3 |
g_variant_builder_init (&vpn_builder, NM_VARIANT_TYPE_SETTING);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_variant_builder_add (&vpn_builder, "{sv}",
|
|
Packit Service |
d328f3 |
NM_SETTING_VPN_SECRETS,
|
|
Packit Service |
d328f3 |
g_variant_builder_end (&req_data->secrets_builder));
|
|
Packit Service |
d328f3 |
g_variant_builder_add (&settings_builder, "{sa{sv}}",
|
|
Packit Service |
d328f3 |
NM_SETTING_VPN_SETTING_NAME,
|
|
Packit Service |
d328f3 |
&vpn_builder);
|
|
Packit Service |
d328f3 |
settings = g_variant_ref_sink (g_variant_builder_end (&settings_builder));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
applet_secrets_request_complete (req, settings, NULL);
|
|
Packit Service |
d328f3 |
applet_secrets_request_free (req);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
process_child_response (VpnSecretsInfo *info)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
SecretsRequest *req = (SecretsRequest *) info;
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
gs_free_error GError *error = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (req_data->external_ui_mode) {
|
|
Packit Service |
d328f3 |
if (!external_ui_from_child_response (info, &error)) {
|
|
Packit Service |
d328f3 |
applet_secrets_request_complete (req, NULL, error);
|
|
Packit Service |
d328f3 |
applet_secrets_request_free (req);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
} else {
|
|
Packit Service |
d328f3 |
char **lines = g_strsplit (req_data->child_response->str, "\n", -1);
|
|
Packit Service |
d328f3 |
int i;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
for (i = 0; lines[i] && *(lines[i]); i += 2) {
|
|
Packit Service |
d328f3 |
if (lines[i + 1] == NULL)
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
g_variant_builder_add (&req_data->secrets_builder, "{ss}", lines[i], lines[i + 1]);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_strfreev (lines);
|
|
Packit Service |
d328f3 |
complete_request (info);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
child_finished_cb (GPid pid, int status, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
VpnSecretsInfo *info = user_data;
|
|
Packit Service |
d328f3 |
SecretsRequest *req = (SecretsRequest *) info;
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
gs_free_error GError *error = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
req_data->pid = 0;
|
|
Packit Service |
d328f3 |
req_data->watch_id = 0;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (status) {
|
|
Packit Service |
d328f3 |
error = g_error_new (NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_USER_CANCELED,
|
|
Packit Service |
d328f3 |
"%s.%d (%s): canceled", __FILE__, __LINE__, __func__);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
applet_secrets_request_complete (req, NULL, error);
|
|
Packit Service |
d328f3 |
applet_secrets_request_free (req);
|
|
Packit Service |
d328f3 |
} else if (req_data->channel_eventid == 0) {
|
|
Packit Service |
d328f3 |
/* We now have both the child response and its exit status. Process it. */
|
|
Packit Service |
d328f3 |
process_child_response (info);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
child_stdout_data_cb (GIOChannel *source, GIOCondition condition, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
SecretsRequest *req = user_data;
|
|
Packit Service |
d328f3 |
VpnSecretsInfo *info = (VpnSecretsInfo *) req;
|
|
Packit Service |
d328f3 |
RequestData *req_data = info->req_data;
|
|
Packit Service |
d328f3 |
GIOStatus status;
|
|
Packit Service |
d328f3 |
char buf[4096];
|
|
Packit Service |
d328f3 |
size_t bytes_read;
|
|
Packit Service |
d328f3 |
gs_free_error GError *error = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
status = g_io_channel_read_chars (source, buf, sizeof (buf)-1, &bytes_read, &error);
|
|
Packit Service |
d328f3 |
switch (status) {
|
|
Packit Service |
d328f3 |
case G_IO_STATUS_ERROR:
|
|
Packit Service |
d328f3 |
req_data->channel_eventid = 0;
|
|
Packit Service |
d328f3 |
applet_secrets_request_complete (req, NULL, error);
|
|
Packit Service |
d328f3 |
applet_secrets_request_free (req);
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
case G_IO_STATUS_EOF:
|
|
Packit Service |
d328f3 |
req_data->channel_eventid = 0;
|
|
Packit Service |
d328f3 |
if (req_data->pid == 0) {
|
|
Packit Service |
d328f3 |
/* We now have both the childe respons and
|
|
Packit Service |
d328f3 |
* its exit status. Process it. */
|
|
Packit Service |
d328f3 |
process_child_response (info);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
case G_IO_STATUS_NORMAL:
|
|
Packit Service |
d328f3 |
g_string_append_len (req_data->child_response, buf, bytes_read);
|
|
Packit Service |
d328f3 |
break;
|
|
Packit Service |
d328f3 |
default:
|
|
Packit Service |
d328f3 |
/* What just happened... */
|
|
Packit Service |
d328f3 |
g_return_val_if_reached (FALSE);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
_str_append (GString *str,
|
|
Packit Service |
d328f3 |
const char *tag,
|
|
Packit Service |
d328f3 |
const char *val)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
const char *s;
|
|
Packit Service |
d328f3 |
gsize i;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
nm_assert (str);
|
|
Packit Service |
d328f3 |
nm_assert (tag && tag[0]);
|
|
Packit Service |
d328f3 |
nm_assert (val);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_string_append (str, tag);
|
|
Packit Service |
d328f3 |
g_string_append_c (str, '=');
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s = strchr (val, '\n');
|
|
Packit Service |
d328f3 |
if (s) {
|
|
Packit Service |
d328f3 |
gs_free char *val2 = g_strdup (val);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
for (i = 0; val2[i]; i++) {
|
|
Packit Service |
d328f3 |
if (val2[i] == '\n')
|
|
Packit Service |
d328f3 |
val2[i] = ' ';
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_string_append (str, val2);
|
|
Packit Service |
d328f3 |
} else
|
|
Packit Service |
d328f3 |
g_string_append (str, val);
|
|
Packit Service |
d328f3 |
g_string_append_c (str, '\n');
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static char *
|
|
Packit Service |
d328f3 |
connection_to_data (NMConnection *connection,
|
|
Packit Service |
d328f3 |
gsize *out_length,
|
|
Packit Service |
d328f3 |
GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
NMSettingVpn *s_vpn;
|
|
Packit Service |
d328f3 |
GString *buf;
|
|
Packit Service |
d328f3 |
const char **keys;
|
|
Packit Service |
d328f3 |
guint i, len;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (NM_IS_CONNECTION (connection), NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_vpn = nm_connection_get_setting_vpn (connection);
|
|
Packit Service |
d328f3 |
if (!s_vpn) {
|
|
Packit Service |
d328f3 |
g_set_error_literal (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
_("Connection had no VPN setting"));
|
|
Packit Service |
d328f3 |
return NULL;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
buf = g_string_new_len (NULL, 100);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
keys = nm_setting_vpn_get_data_keys (s_vpn, &len;;
|
|
Packit Service |
d328f3 |
for (i = 0; i < len; i++) {
|
|
Packit Service |
d328f3 |
_str_append (buf, "DATA_KEY", keys[i]);
|
|
Packit Service |
d328f3 |
_str_append (buf, "DATA_VAL", nm_setting_vpn_get_data_item (s_vpn, keys[i]));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
nm_clear_g_free (&keys);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
keys = nm_setting_vpn_get_secret_keys (s_vpn, &len;;
|
|
Packit Service |
d328f3 |
for (i = 0; i < len; i++) {
|
|
Packit Service |
d328f3 |
_str_append (buf, "SECRET_KEY", keys[i]);
|
|
Packit Service |
d328f3 |
_str_append (buf, "SECRET_VAL", nm_setting_vpn_get_secret (s_vpn, keys[i]));
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
nm_clear_g_free (&keys);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_string_append (buf, "DONE\n\nQUIT\n\n");
|
|
Packit Service |
d328f3 |
NM_SET_OUT (out_length, buf->len);
|
|
Packit Service |
d328f3 |
return g_string_free (buf, FALSE);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
connection_to_fd (NMConnection *connection,
|
|
Packit Service |
d328f3 |
int fd,
|
|
Packit Service |
d328f3 |
GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
gs_free char *data = NULL;
|
|
Packit Service |
d328f3 |
gsize data_len;
|
|
Packit Service |
d328f3 |
gssize w;
|
|
Packit Service |
d328f3 |
int errsv;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
data = connection_to_data (connection, &data_len, error);
|
|
Packit Service |
d328f3 |
if (!data)
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
again:
|
|
Packit Service |
d328f3 |
w = write (fd, data, data_len);
|
|
Packit Service |
d328f3 |
if (w < 0) {
|
|
Packit Service |
d328f3 |
errsv = errno;
|
|
Packit Service |
d328f3 |
if (errsv == EINTR)
|
|
Packit Service |
d328f3 |
goto again;
|
|
Packit Service |
d328f3 |
g_set_error (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
_("Failed to write connection to VPN UI: %s (%d)"), g_strerror (errsv), errsv);
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if ((gsize) w != data_len) {
|
|
Packit Service |
d328f3 |
g_set_error_literal (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
_("Failed to write connection to VPN UI: incomplete write"));
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
vpn_child_setup (gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
/* We are in the child process at this point */
|
|
Packit Service |
d328f3 |
pid_t pid = getpid ();
|
|
Packit Service |
d328f3 |
setpgid (pid, pid);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
auth_dialog_spawn (const char *con_id,
|
|
Packit Service |
d328f3 |
const char *con_uuid,
|
|
Packit Service |
d328f3 |
const char *const*hints,
|
|
Packit Service |
d328f3 |
const char *auth_dialog,
|
|
Packit Service |
d328f3 |
const char *service_type,
|
|
Packit Service |
d328f3 |
gboolean supports_hints,
|
|
Packit Service |
d328f3 |
gboolean external_ui_mode,
|
|
Packit Service |
d328f3 |
guint32 flags,
|
|
Packit Service |
d328f3 |
GPid *out_pid,
|
|
Packit Service |
d328f3 |
int *out_stdin,
|
|
Packit Service |
d328f3 |
int *out_stdout,
|
|
Packit Service |
d328f3 |
GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
gsize hints_len;
|
|
Packit Service |
d328f3 |
gsize i, j;
|
|
Packit Service |
d328f3 |
gs_free const char **argv = NULL;
|
|
Packit Service |
d328f3 |
gs_free const char **envp = NULL;
|
|
Packit Service |
d328f3 |
gsize environ_len;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (con_id, FALSE);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (con_uuid, FALSE);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (auth_dialog, FALSE);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (service_type, FALSE);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (out_pid, FALSE);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (out_stdin, FALSE);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (out_stdout, FALSE);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
hints_len = NM_PTRARRAY_LEN (hints);
|
|
Packit Service |
d328f3 |
argv = g_new (const char *, 11 + (2 * hints_len));
|
|
Packit Service |
d328f3 |
i = 0;
|
|
Packit Service |
d328f3 |
argv[i++] = auth_dialog;
|
|
Packit Service |
d328f3 |
argv[i++] = "-u";
|
|
Packit Service |
d328f3 |
argv[i++] = con_uuid;
|
|
Packit Service |
d328f3 |
argv[i++] = "-n";
|
|
Packit Service |
d328f3 |
argv[i++] = con_id;
|
|
Packit Service |
d328f3 |
argv[i++] = "-s";
|
|
Packit Service |
d328f3 |
argv[i++] = service_type;
|
|
Packit Service |
d328f3 |
if (flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_ALLOW_INTERACTION)
|
|
Packit Service |
d328f3 |
argv[i++] = "-i";
|
|
Packit Service |
d328f3 |
if (flags & NM_SECRET_AGENT_GET_SECRETS_FLAG_REQUEST_NEW)
|
|
Packit Service |
d328f3 |
argv[i++] = "-r";
|
|
Packit Service |
d328f3 |
for (j = 0; supports_hints && (j < hints_len); j++) {
|
|
Packit Service |
d328f3 |
argv[i++] = "-t";
|
|
Packit Service |
d328f3 |
argv[i++] = hints[j];
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
if (external_ui_mode)
|
|
Packit Service |
d328f3 |
argv[i++] = "--external-ui-mode";
|
|
Packit Service |
d328f3 |
nm_assert (i <= 10 + (2 * hints_len));
|
|
Packit Service |
d328f3 |
argv[i++] = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
environ_len = NM_PTRARRAY_LEN (environ);
|
|
Packit Service |
d328f3 |
envp = g_new (const char *, environ_len + 1);
|
|
Packit Service |
d328f3 |
memcpy (envp, environ, sizeof (const char *) * environ_len);
|
|
Packit Service |
d328f3 |
for (i = 0, j = 0; i < environ_len; i++) {
|
|
Packit Service |
d328f3 |
const char *e = environ[i];
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (g_str_has_prefix (e, "G_MESSAGES_DEBUG=")) {
|
|
Packit Service |
d328f3 |
/* skip this environment variable. We interact with the auth-dialog via stdout.
|
|
Packit Service |
d328f3 |
* G_MESSAGES_DEBUG may enable additional debugging messages from GTK. */
|
|
Packit Service |
d328f3 |
continue;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
envp[j++] = e;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
envp[j] = NULL;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!g_spawn_async_with_pipes (NULL,
|
|
Packit Service |
d328f3 |
(char **) argv,
|
|
Packit Service |
d328f3 |
(char **) envp,
|
|
Packit Service |
d328f3 |
G_SPAWN_DO_NOT_REAP_CHILD,
|
|
Packit Service |
d328f3 |
vpn_child_setup,
|
|
Packit Service |
d328f3 |
NULL,
|
|
Packit Service |
d328f3 |
out_pid,
|
|
Packit Service |
d328f3 |
out_stdin,
|
|
Packit Service |
d328f3 |
out_stdout,
|
|
Packit Service |
d328f3 |
NULL,
|
|
Packit Service |
d328f3 |
error))
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/*****************************************************************************/
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static gboolean
|
|
Packit Service |
d328f3 |
ensure_killed (gpointer data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
pid_t pid = GPOINTER_TO_INT (data);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
kill (pid, SIGKILL);
|
|
Packit Service |
d328f3 |
waitpid (pid, NULL, 0);
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
dialog_response_destroy (GtkDialog *dialog, int response_id, gpointer user_data)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
gtk_widget_destroy (GTK_WIDGET (dialog));
|
|
Packit Service |
d328f3 |
g_object_unref (dialog);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
static void
|
|
Packit Service |
d328f3 |
free_vpn_secrets_info (SecretsRequest *req)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
RequestData *req_data;
|
|
Packit Service |
d328f3 |
guint i;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
req_data = ((VpnSecretsInfo *) req)->req_data;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!req_data)
|
|
Packit Service |
d328f3 |
return;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_free (req_data->uuid);
|
|
Packit Service |
d328f3 |
g_free (req_data->id);
|
|
Packit Service |
d328f3 |
g_free (req_data->service_type);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
nm_clear_g_source (&req_data->watch_id);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
nm_clear_g_source (&req_data->channel_eventid);
|
|
Packit Service |
d328f3 |
if (req_data->channel)
|
|
Packit Service |
d328f3 |
g_io_channel_unref (req_data->channel);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (req_data->pid) {
|
|
Packit Service |
d328f3 |
if (kill (req_data->pid, SIGTERM) == 0)
|
|
Packit Service |
d328f3 |
g_timeout_add_seconds (2, ensure_killed, GINT_TO_POINTER (req_data->pid));
|
|
Packit Service |
d328f3 |
else {
|
|
Packit Service |
d328f3 |
kill (req_data->pid, SIGKILL);
|
|
Packit Service |
d328f3 |
waitpid (req_data->pid, NULL, 0);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (req_data->child_response)
|
|
Packit Service |
d328f3 |
g_string_free (req_data->child_response, TRUE);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_variant_builder_clear (&req_data->secrets_builder);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (req_data->eui_secrets) {
|
|
Packit Service |
d328f3 |
for (i = 0; req_data->eui_secrets[i].name; i++) {
|
|
Packit Service |
d328f3 |
g_free (req_data->eui_secrets[i].name);
|
|
Packit Service |
d328f3 |
g_free (req_data->eui_secrets[i].label);
|
|
Packit Service |
d328f3 |
g_free (req_data->eui_secrets[i].value);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
g_free (req_data->eui_secrets);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (req_data->dialog) {
|
|
Packit Service |
d328f3 |
g_signal_handlers_disconnect_by_func (req_data->dialog,
|
|
Packit Service |
d328f3 |
external_ui_dialog_response,
|
|
Packit Service |
d328f3 |
req);
|
|
Packit Service |
d328f3 |
g_signal_connect (req_data->dialog,
|
|
Packit Service |
d328f3 |
"response",
|
|
Packit Service |
d328f3 |
G_CALLBACK (dialog_response_destroy),
|
|
Packit Service |
d328f3 |
NULL);
|
|
Packit Service |
d328f3 |
req_data->dialog = NULL;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_slice_free (RequestData, req_data);
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
gboolean
|
|
Packit Service |
d328f3 |
applet_vpn_request_get_secrets (SecretsRequest *req, GError **error)
|
|
Packit Service |
d328f3 |
{
|
|
Packit Service |
d328f3 |
VpnSecretsInfo *info = (VpnSecretsInfo *) req;
|
|
Packit Service |
d328f3 |
RequestData *req_data;
|
|
Packit Service |
d328f3 |
NMSettingConnection *s_con;
|
|
Packit Service |
d328f3 |
NMSettingVpn *s_vpn;
|
|
Packit Service |
d328f3 |
const char *connection_type;
|
|
Packit Service |
d328f3 |
const char *service_type;
|
|
Packit Service |
d328f3 |
const char *auth_dialog;
|
|
Packit Service |
d328f3 |
gs_unref_object NMVpnPluginInfo *plugin = NULL;
|
|
Packit Service |
d328f3 |
int child_stdin;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
applet_secrets_request_set_free_func (req, free_vpn_secrets_info);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
s_con = nm_connection_get_setting_connection (req->connection);
|
|
Packit Service |
d328f3 |
s_vpn = nm_connection_get_setting_vpn (req->connection);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
connection_type = nm_setting_connection_get_connection_type (s_con);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (nm_streq0 (connection_type, NM_SETTING_VPN_SETTING_NAME), FALSE);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
service_type = nm_setting_vpn_get_service_type (s_vpn);
|
|
Packit Service |
d328f3 |
g_return_val_if_fail (service_type, FALSE);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
plugin = nm_vpn_plugin_info_new_search_file (NULL, service_type);
|
|
Packit Service |
d328f3 |
auth_dialog = plugin ? nm_vpn_plugin_info_get_auth_dialog (plugin) : NULL;
|
|
Packit Service |
d328f3 |
if (!auth_dialog) {
|
|
Packit Service |
d328f3 |
g_set_error (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
"Could not find the authentication dialog for VPN connection type '%s'",
|
|
Packit Service |
d328f3 |
service_type);
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
info->req_data = g_slice_new0 (RequestData);
|
|
Packit Service |
d328f3 |
if (!info->req_data) {
|
|
Packit Service |
d328f3 |
g_set_error_literal (error,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR,
|
|
Packit Service |
d328f3 |
NM_SECRET_AGENT_ERROR_FAILED,
|
|
Packit Service |
d328f3 |
"Could not create VPN secrets request object");
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
}
|
|
Packit Service |
d328f3 |
req_data = info->req_data;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_variant_builder_init (&req_data->secrets_builder, G_VARIANT_TYPE ("a{ss}"));
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
req_data->external_ui_mode = _nm_utils_ascii_str_to_bool (
|
|
Packit Service |
d328f3 |
nm_vpn_plugin_info_lookup_property (plugin,
|
|
Packit Service |
d328f3 |
"GNOME",
|
|
Packit Service |
d328f3 |
"supports-external-ui-mode"),
|
|
Packit Service |
d328f3 |
FALSE);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!auth_dialog_spawn (nm_setting_connection_get_id (s_con),
|
|
Packit Service |
d328f3 |
nm_setting_connection_get_uuid (s_con),
|
|
Packit Service |
d328f3 |
(const char *const*) req->hints,
|
|
Packit Service |
d328f3 |
auth_dialog,
|
|
Packit Service |
d328f3 |
service_type,
|
|
Packit Service |
d328f3 |
nm_vpn_plugin_info_supports_hints (plugin),
|
|
Packit Service |
d328f3 |
req_data->external_ui_mode,
|
|
Packit Service |
d328f3 |
req->flags,
|
|
Packit Service |
d328f3 |
&req_data->pid,
|
|
Packit Service |
d328f3 |
&child_stdin,
|
|
Packit Service |
d328f3 |
&req_data->child_stdout,
|
|
Packit Service |
d328f3 |
error))
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* catch when child is reaped */
|
|
Packit Service |
d328f3 |
req_data->watch_id = g_child_watch_add (req_data->pid, child_finished_cb, info);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* listen to what child has to say */
|
|
Packit Service |
d328f3 |
req_data->channel = g_io_channel_unix_new (req_data->child_stdout);
|
|
Packit Service |
d328f3 |
req_data->child_response = g_string_sized_new (4096);
|
|
Packit Service |
d328f3 |
req_data->channel_eventid = g_io_add_watch (req_data->channel,
|
|
Packit Service |
d328f3 |
G_IO_IN | G_IO_ERR | G_IO_HUP | G_IO_NVAL,
|
|
Packit Service |
d328f3 |
child_stdout_data_cb,
|
|
Packit Service |
d328f3 |
info);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
if (!connection_to_fd (req->connection, child_stdin, error))
|
|
Packit Service |
d328f3 |
return FALSE;
|
|
Packit Service |
d328f3 |
close (child_stdin);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
g_io_channel_set_encoding (req_data->channel, NULL, NULL);
|
|
Packit Service |
d328f3 |
|
|
Packit Service |
d328f3 |
/* Dump parts of the connection to the child */
|
|
Packit Service |
d328f3 |
return TRUE;
|
|
Packit Service |
d328f3 |
}
|