2013-12-02 16:20:26 -05:00
|
|
|
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
|
|
|
|
/*
|
|
|
|
|
* 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, see <http://www.gnu.org/licenses/>.
|
|
|
|
|
*
|
2015-11-23 17:47:00 +01:00
|
|
|
* Copyright 2013 - 2015 Red Hat, Inc.
|
2013-12-02 16:20:26 -05:00
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
/**
|
2015-11-23 17:47:00 +01:00
|
|
|
* SECTION:nm-vpn-helpers
|
2013-12-02 16:20:26 -05:00
|
|
|
* @short_description: VPN-related utilities
|
|
|
|
|
*/
|
|
|
|
|
|
2016-02-12 14:44:52 +01:00
|
|
|
#include "nm-default.h"
|
2016-02-19 14:57:48 +01:00
|
|
|
|
2016-02-12 14:44:52 +01:00
|
|
|
#include "nm-vpn-helpers.h"
|
|
|
|
|
|
2013-12-02 16:20:26 -05:00
|
|
|
#include <string.h>
|
|
|
|
|
|
2015-12-11 21:47:27 +01:00
|
|
|
#include "nm-utils.h"
|
2013-12-02 16:20:26 -05:00
|
|
|
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
/*****************************************************************************/
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2015-05-26 11:10:12 +02:00
|
|
|
NMVpnEditorPlugin *
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
nm_vpn_get_editor_plugin (const char *service_type, GError **error)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
2015-05-26 11:10:12 +02:00
|
|
|
NMVpnEditorPlugin *plugin = NULL;
|
|
|
|
|
NMVpnPluginInfo *plugin_info;
|
2016-05-19 11:17:46 +02:00
|
|
|
gs_free_error GError *local = NULL;
|
2015-05-26 11:10:12 +02:00
|
|
|
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
g_return_val_if_fail (service_type, NULL);
|
2015-11-30 16:20:10 +01:00
|
|
|
g_return_val_if_fail (error == NULL || *error == NULL, NULL);
|
2013-12-02 16:20:26 -05:00
|
|
|
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
plugin_info = nm_vpn_plugin_info_list_find_by_service (nm_vpn_get_plugin_infos (), service_type);
|
2015-11-30 16:39:55 +01:00
|
|
|
|
2016-05-19 11:17:46 +02:00
|
|
|
if (!plugin_info) {
|
2016-05-19 10:06:27 +02:00
|
|
|
g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_FAILED,
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
_("unknown VPN plugin \"%s\""), service_type);
|
2016-05-19 11:17:46 +02:00
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
plugin = nm_vpn_plugin_info_get_editor_plugin (plugin_info);
|
|
|
|
|
if (!plugin)
|
|
|
|
|
plugin = nm_vpn_plugin_info_load_editor_plugin (plugin_info, &local);
|
|
|
|
|
|
|
|
|
|
if (!plugin) {
|
|
|
|
|
if ( !nm_vpn_plugin_info_get_plugin (plugin_info)
|
|
|
|
|
&& nm_vpn_plugin_info_lookup_property (plugin_info, NM_VPN_PLUGIN_INFO_KF_GROUP_GNOME, "properties")) {
|
|
|
|
|
g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_FAILED,
|
2016-08-26 19:04:47 +03:00
|
|
|
_("cannot load legacy-only VPN plugin \"%s\" for \"%s\""),
|
2016-05-19 11:17:46 +02:00
|
|
|
nm_vpn_plugin_info_get_name (plugin_info),
|
|
|
|
|
nm_vpn_plugin_info_get_filename (plugin_info));
|
|
|
|
|
} else if (g_error_matches (local, G_FILE_ERROR, G_FILE_ERROR_NOENT)) {
|
|
|
|
|
g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_FAILED,
|
|
|
|
|
_("cannot load VPN plugin \"%s\" due to missing \"%s\". Missing client plugin?"),
|
|
|
|
|
nm_vpn_plugin_info_get_name (plugin_info),
|
|
|
|
|
nm_vpn_plugin_info_get_plugin (plugin_info));
|
|
|
|
|
} else {
|
|
|
|
|
g_set_error (error, NM_VPN_PLUGIN_ERROR, NM_VPN_PLUGIN_ERROR_FAILED,
|
|
|
|
|
_("failed to load VPN plugin \"%s\": %s"),
|
|
|
|
|
nm_vpn_plugin_info_get_name (plugin_info),
|
|
|
|
|
local->message);
|
|
|
|
|
}
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-05-26 11:10:12 +02:00
|
|
|
return plugin;
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
|
|
|
|
|
2015-05-26 11:10:12 +02:00
|
|
|
GSList *
|
2016-06-06 10:21:18 +02:00
|
|
|
nm_vpn_get_plugin_infos (void)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
static bool plugins_loaded;
|
|
|
|
|
static GSList *plugins = NULL;
|
|
|
|
|
|
2015-05-26 11:10:12 +02:00
|
|
|
if (G_LIKELY (plugins_loaded))
|
2013-12-02 16:20:26 -05:00
|
|
|
return plugins;
|
2015-05-26 11:10:12 +02:00
|
|
|
plugins_loaded = TRUE;
|
|
|
|
|
plugins = nm_vpn_plugin_info_list_load ();
|
2013-12-02 16:20:26 -05:00
|
|
|
return plugins;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
2015-11-23 17:47:00 +01:00
|
|
|
nm_vpn_supports_ipv6 (NMConnection *connection)
|
2013-12-02 16:20:26 -05:00
|
|
|
{
|
libnm, core, cli, tui: fix the capitalization of various types
GLib/Gtk have mostly settled on the convention that two-letter
acronyms in type names remain all-caps (eg, "IO"), but longer acronyms
become initial-caps-only (eg, "Tcp").
NM was inconsistent, with most long acronyms using initial caps only
(Adsl, Cdma, Dcb, Gsm, Olpc, Vlan), but others using all caps (DHCP,
PPP, PPPOE, VPN). Fix libnm and src/ to use initial-caps only for all
three-or-more-letter-long acronyms (and update nmcli and nmtui for the
libnm changes).
2014-06-26 13:44:36 -04:00
|
|
|
NMSettingVpn *s_vpn;
|
2013-12-02 16:20:26 -05:00
|
|
|
const char *service_type;
|
2015-05-26 11:10:12 +02:00
|
|
|
NMVpnEditorPlugin *plugin;
|
2013-12-02 16:20:26 -05:00
|
|
|
guint32 capabilities;
|
|
|
|
|
|
|
|
|
|
s_vpn = nm_connection_get_setting_vpn (connection);
|
|
|
|
|
g_return_val_if_fail (s_vpn != NULL, FALSE);
|
|
|
|
|
|
|
|
|
|
service_type = nm_setting_vpn_get_service_type (s_vpn);
|
2016-05-19 10:08:47 +02:00
|
|
|
if (!service_type)
|
|
|
|
|
return FALSE;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
cli: fix handling of VPN names in nmcli by using libnm functions
At various places, nmcli requires to specify a VPN type by name, for example
$ nmcli connection add type vpn ifname '*' vpn-type $VPN_TYPE
This $VPN_TYPE used to be a hard-coded list of known VPN plugin names.
But actually, it should be a VPN service-type. A service-type used to be
the D-Bus name of the VPN plugin. Now, with multiple VPN support that
is no longer the case, but it still has the form of a D-Bus bus name.
Alternativley, it could be an alias, which is just a way for plugins
to support multiple service-types.
Fix that, to support fully qualified service-types in the form
of D-Bus bus names. Also, support lookup by name, in which case
the present plugin-info instances are searched.
Finally, support a list of hard-code short-names.
All the logic how to translate a short-name to a fully qualified
service-type is now inside libnm, so that various user agree on
those names and don't have to hard-code them each.
2016-06-07 11:06:14 +02:00
|
|
|
plugin = nm_vpn_get_editor_plugin (service_type, NULL);
|
2016-05-19 10:08:47 +02:00
|
|
|
if (!plugin)
|
|
|
|
|
return FALSE;
|
2013-12-02 16:20:26 -05:00
|
|
|
|
2015-05-26 11:10:12 +02:00
|
|
|
capabilities = nm_vpn_editor_plugin_get_capabilities (plugin);
|
|
|
|
|
return NM_FLAGS_HAS (capabilities, NM_VPN_EDITOR_PLUGIN_CAPABILITY_IPV6);
|
2013-12-02 16:20:26 -05:00
|
|
|
}
|
2015-11-27 11:09:20 +01:00
|
|
|
|
|
|
|
|
const VpnPasswordName *
|
2016-06-20 19:04:34 +02:00
|
|
|
nm_vpn_get_secret_names (const char *service_type)
|
2015-11-27 11:09:20 +01:00
|
|
|
{
|
2017-04-05 13:40:01 +02:00
|
|
|
static const VpnPasswordName const generic_vpn_secrets[] = {
|
|
|
|
|
{ "password", N_("Password") },
|
|
|
|
|
{ 0 }
|
|
|
|
|
};
|
|
|
|
|
static const VpnPasswordName const openvpn_secrets[] = {
|
|
|
|
|
{ "password", N_("Password") },
|
|
|
|
|
{ "cert-pass", N_("Certificate password") },
|
|
|
|
|
{ "http-proxy-password", N_("HTTP proxy password") },
|
|
|
|
|
{ 0 }
|
|
|
|
|
};
|
|
|
|
|
static const VpnPasswordName const vpnc_secrets[] = {
|
|
|
|
|
{ "Xauth password", N_("Password") },
|
|
|
|
|
{ "IPSec secret", N_("Group password") },
|
|
|
|
|
{ 0 }
|
|
|
|
|
};
|
|
|
|
|
static const VpnPasswordName const swan_secrets[] = {
|
|
|
|
|
{ "xauthpassword", N_("Password") },
|
|
|
|
|
{ "pskvalue", N_("Group password") },
|
|
|
|
|
{ 0 }
|
|
|
|
|
};
|
|
|
|
|
static const VpnPasswordName const openconnect_secrets[] = {
|
|
|
|
|
{ "gateway", N_("Gateway") },
|
|
|
|
|
{ "cookie", N_("Cookie") },
|
|
|
|
|
{ "gwcert", N_("Gateway certificate hash") },
|
|
|
|
|
{ 0 }
|
|
|
|
|
};
|
2015-11-27 11:09:20 +01:00
|
|
|
const char *type;
|
|
|
|
|
|
2016-06-20 19:04:34 +02:00
|
|
|
if (!service_type)
|
2015-11-27 11:09:20 +01:00
|
|
|
return NULL;
|
|
|
|
|
|
2016-06-20 19:04:34 +02:00
|
|
|
if ( !g_str_has_prefix (service_type, NM_DBUS_INTERFACE)
|
|
|
|
|
|| service_type[NM_STRLEN (NM_DBUS_INTERFACE)] != '.') {
|
2016-06-20 19:02:40 +02:00
|
|
|
/* all our well-known, hard-coded vpn-types start with NM_DBUS_INTERFACE. */
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
2015-11-27 11:09:20 +01:00
|
|
|
|
2016-06-20 19:04:34 +02:00
|
|
|
type = service_type + (NM_STRLEN (NM_DBUS_INTERFACE) + 1);
|
2016-05-03 23:39:40 +02:00
|
|
|
if ( !g_strcmp0 (type, "pptp")
|
2015-11-27 11:09:20 +01:00
|
|
|
|| !g_strcmp0 (type, "iodine")
|
|
|
|
|
|| !g_strcmp0 (type, "ssh")
|
|
|
|
|
|| !g_strcmp0 (type, "l2tp")
|
|
|
|
|
|| !g_strcmp0 (type, "fortisslvpn"))
|
|
|
|
|
return generic_vpn_secrets;
|
2016-05-03 23:39:40 +02:00
|
|
|
else if (!g_strcmp0 (type, "openvpn"))
|
|
|
|
|
return openvpn_secrets;
|
2015-11-27 11:09:20 +01:00
|
|
|
else if (!g_strcmp0 (type, "vpnc"))
|
|
|
|
|
return vpnc_secrets;
|
|
|
|
|
else if ( !g_strcmp0 (type, "openswan")
|
|
|
|
|
|| !g_strcmp0 (type, "libreswan")
|
|
|
|
|
|| !g_strcmp0 (type, "strongswan"))
|
|
|
|
|
return swan_secrets;
|
|
|
|
|
else if (!g_strcmp0 (type, "openconnect"))
|
|
|
|
|
return openconnect_secrets;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2015-12-11 21:47:27 +01:00
|
|
|
static gboolean
|
|
|
|
|
_extract_variable_value (char *line, const char *tag, char **value)
|
|
|
|
|
{
|
|
|
|
|
char *p1, *p2;
|
|
|
|
|
|
|
|
|
|
if (g_str_has_prefix (line, tag)) {
|
|
|
|
|
p1 = line + strlen (tag);
|
|
|
|
|
p2 = line + strlen (line) - 1;
|
|
|
|
|
if ((*p1 == '\'' || *p1 == '"') && (*p1 == *p2)) {
|
|
|
|
|
p1++;
|
|
|
|
|
*p2 = '\0';
|
|
|
|
|
}
|
|
|
|
|
if (value)
|
|
|
|
|
*value = g_strdup (p1);
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
return FALSE;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
gboolean
|
|
|
|
|
nm_vpn_openconnect_authenticate_helper (const char *host,
|
|
|
|
|
char **cookie,
|
|
|
|
|
char **gateway,
|
|
|
|
|
char **gwcert,
|
|
|
|
|
int *status,
|
|
|
|
|
GError **error)
|
|
|
|
|
{
|
|
|
|
|
char *output = NULL;
|
|
|
|
|
gboolean ret;
|
|
|
|
|
char **strv = NULL, **iter;
|
|
|
|
|
char *argv[4];
|
|
|
|
|
const char *path;
|
|
|
|
|
const char *const DEFAULT_PATHS[] = {
|
|
|
|
|
"/sbin/",
|
|
|
|
|
"/usr/sbin/",
|
|
|
|
|
"/usr/local/sbin/",
|
|
|
|
|
"/bin/",
|
|
|
|
|
"/usr/bin/",
|
|
|
|
|
"/usr/local/bin/",
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
path = nm_utils_file_search_in_paths ("openconnect", "/usr/sbin/openconnect", DEFAULT_PATHS,
|
|
|
|
|
G_FILE_TEST_IS_EXECUTABLE, NULL, NULL, error);
|
|
|
|
|
if (!path)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
argv[0] = (char *) path;
|
|
|
|
|
argv[1] = "--authenticate";
|
|
|
|
|
argv[2] = (char *) host;
|
|
|
|
|
argv[3] = NULL;
|
|
|
|
|
|
|
|
|
|
ret = g_spawn_sync (NULL, argv, NULL,
|
|
|
|
|
G_SPAWN_SEARCH_PATH | G_SPAWN_CHILD_INHERITS_STDIN,
|
|
|
|
|
NULL, NULL, &output, NULL,
|
|
|
|
|
status, error);
|
|
|
|
|
|
|
|
|
|
if (!ret)
|
|
|
|
|
return FALSE;
|
|
|
|
|
|
|
|
|
|
/* Parse output and set cookie, gateway and gwcert
|
|
|
|
|
* output example:
|
|
|
|
|
* COOKIE='loremipsum'
|
|
|
|
|
* HOST='1.2.3.4'
|
|
|
|
|
* FINGERPRINT='sha1:32bac90cf09a722e10ecc1942c67fe2ac8c21e2e'
|
|
|
|
|
*/
|
|
|
|
|
strv = g_strsplit_set (output ? output : "", "\r\n", 0);
|
|
|
|
|
for (iter = strv; iter && *iter; iter++) {
|
|
|
|
|
_extract_variable_value (*iter, "COOKIE=", cookie);
|
|
|
|
|
_extract_variable_value (*iter, "HOST=", gateway);
|
|
|
|
|
_extract_variable_value (*iter, "FINGERPRINT=", gwcert);
|
|
|
|
|
}
|
|
|
|
|
g_strfreev (strv);
|
|
|
|
|
|
|
|
|
|
return TRUE;
|
|
|
|
|
}
|
|
|
|
|
|