ifcfg-rh: initial write support for wifi & wired

This commit is contained in:
Dan Williams
2009-03-26 16:57:55 -04:00
parent 1974b257e0
commit 44964d3b5e
19 changed files with 1537 additions and 152 deletions

View File

@@ -14,7 +14,9 @@ libifcfg_rh_io_la_SOURCES = \
sha1.c \ sha1.c \
sha1.h \ sha1.h \
errors.c \ errors.c \
common.h common.h \
utils.c \
utils.h
libifcfg_rh_io_la_CPPFLAGS = \ libifcfg_rh_io_la_CPPFLAGS = \
$(GLIB_CFLAGS) \ $(GLIB_CFLAGS) \

View File

@@ -21,6 +21,8 @@
#ifndef __COMMON_H__ #ifndef __COMMON_H__
#define __COMMON_H__ #define __COMMON_H__
#include <glib.h>
#define IFCFG_TAG "ifcfg-" #define IFCFG_TAG "ifcfg-"
#define KEYS_TAG "keys-" #define KEYS_TAG "keys-"
#define BAK_TAG ".bak" #define BAK_TAG ".bak"
@@ -33,7 +35,26 @@
#define IFCFG_PLUGIN_NAME "ifcfg-rh" #define IFCFG_PLUGIN_NAME "ifcfg-rh"
#define IFCFG_PLUGIN_INFO "(c) 2007 - 2008 Red Hat, Inc. To report bugs please use the NetworkManager mailing list." #define IFCFG_PLUGIN_INFO "(c) 2007 - 2008 Red Hat, Inc. To report bugs please use the NetworkManager mailing list."
#include <glib.h> #define TYPE_ETHERNET "Ethernet"
#define TYPE_WIRELESS "Wireless"
#define TAG_CA_CERT_PATH "ca-cert-path"
#define TAG_CA_CERT_HASH "ca-cert-hash"
#define TAG_CLIENT_CERT_PATH "client-cert-path"
#define TAG_CLIENT_CERT_HASH "client-cert-hash"
#define TAG_PRIVATE_KEY_PATH "private-key-path"
#define TAG_PRIVATE_KEY_HASH "private-key-hash"
#define TAG_PHASE2_CA_CERT_PATH "phase2-ca-cert-path"
#define TAG_PHASE2_CA_CERT_HASH "phase2-ca-cert-hash"
#define TAG_PHASE2_CLIENT_CERT_PATH "phase2-client-cert-path"
#define TAG_PHASE2_CLIENT_CERT_HASH "phase2-client-cert-hash"
#define TAG_PHASE2_PRIVATE_KEY_PATH "phase2-private-key-path"
#define TAG_PHASE2_PRIVATE_KEY_HASH "phase2-private-key-hash"
GQuark ifcfg_plugin_error_quark (void); GQuark ifcfg_plugin_error_quark (void);

View File

@@ -522,7 +522,7 @@ plugin_set_hostname (SCPluginIfcfg *plugin, const char *hostname)
return FALSE; return FALSE;
} }
svSetValue (network, "HOSTNAME", hostname); svSetValue (network, "HOSTNAME", hostname, FALSE);
svWriteFile (network, 0644); svWriteFile (network, 0644);
svCloseFile (network); svCloseFile (network);
@@ -640,7 +640,7 @@ get_property (GObject *object, guint prop_id,
g_value_set_string (value, IFCFG_PLUGIN_INFO); g_value_set_string (value, IFCFG_PLUGIN_INFO);
break; break;
case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES: case NM_SYSTEM_CONFIG_INTERFACE_PROP_CAPABILITIES:
g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME); g_value_set_uint (value, NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_CONNECTIONS | NM_SYSTEM_CONFIG_INTERFACE_CAP_MODIFY_HOSTNAME);
break; break;
case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME: case NM_SYSTEM_CONFIG_INTERFACE_PROP_HOSTNAME:
g_value_set_string (value, priv->hostname); g_value_set_string (value, priv->hostname);

View File

@@ -52,6 +52,7 @@
#include "common.h" #include "common.h"
#include "shvar.h" #include "shvar.h"
#include "sha1.h" #include "sha1.h"
#include "utils.h"
#include "reader.h" #include "reader.h"
@@ -90,21 +91,6 @@ static gboolean eap_ttls_reader (const char *eap_method,
GError **error); GError **error);
static char *
get_ifcfg_name (const char *file)
{
char *ifcfg_name;
char *basename;
basename = g_path_get_basename (file);
if (!basename)
return NULL;
ifcfg_name = g_strdup (basename + strlen (IFCFG_TAG));
g_free (basename);
return ifcfg_name;
}
static gboolean static gboolean
get_int (const char *str, int *value) get_int (const char *str, int *value)
{ {
@@ -128,7 +114,7 @@ make_connection_setting (const char *file,
char *new_id = NULL, *uuid = NULL, *value; char *new_id = NULL, *uuid = NULL, *value;
char *ifcfg_id; char *ifcfg_id;
ifcfg_name = get_ifcfg_name (file); ifcfg_name = utils_get_ifcfg_name (file);
if (!ifcfg_name) if (!ifcfg_name)
return NULL; return NULL;
@@ -279,6 +265,14 @@ make_ip4_setting (shvarFile *ifcfg, const char *network_file, GError **error)
NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default, NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
NULL); NULL);
return NM_SETTING (s_ip4); return NM_SETTING (s_ip4);
} else if (!g_ascii_strcasecmp (value, "shared")) {
g_free (value);
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
g_object_set (s_ip4,
NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_SHARED,
NM_SETTING_IP4_CONFIG_NEVER_DEFAULT, never_default,
NULL);
return NM_SETTING (s_ip4);
} }
g_free (value); g_free (value);
} else { } else {
@@ -443,39 +437,6 @@ error:
return NULL; return NULL;
} }
/*
* utils_bin2hexstr
*
* Convert a byte-array into a hexadecimal string.
*
* Code originally by Alex Larsson <alexl@redhat.com> and
* copyright Red Hat, Inc. under terms of the LGPL.
*
*/
static char *
utils_bin2hexstr (const char *bytes, int len, int final_len)
{
static char hex_digits[] = "0123456789abcdef";
char * result;
int i;
g_return_val_if_fail (bytes != NULL, NULL);
g_return_val_if_fail (len > 0, NULL);
g_return_val_if_fail (len < 256, NULL); /* Arbitrary limit */
result = g_malloc0 (len * 2 + 1);
for (i = 0; i < len; i++)
{
result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
result[2*i+1] = hex_digits[bytes[i] & 0xf];
}
/* Cut converted key off at the correct length for this cipher type */
if (final_len > -1)
result[final_len] = '\0';
return result;
}
static gboolean static gboolean
read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error) read_mac_address (shvarFile *ifcfg, GByteArray **array, GError **error)
{ {
@@ -573,44 +534,6 @@ out:
return success; return success;
} }
static char *
get_keys_file_path (const char *parent)
{
char *ifcfg_name;
char *keys_file = NULL;
char *tmp = NULL;
ifcfg_name = get_ifcfg_name (parent);
if (!ifcfg_name)
return NULL;
tmp = g_path_get_dirname (parent);
if (!tmp)
goto out;
keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name);
out:
g_free (tmp);
g_free (ifcfg_name);
return keys_file;
}
static shvarFile *
get_keys_ifcfg (const char *parent)
{
shvarFile *ifcfg = NULL;
char *keys_file;
keys_file = get_keys_file_path (parent);
if (!keys_file)
return NULL;
ifcfg = svNewFile (keys_file);
g_free (keys_file);
return ifcfg;
}
static gboolean static gboolean
read_wep_keys (shvarFile *ifcfg, read_wep_keys (shvarFile *ifcfg,
guint8 def_idx, guint8 def_idx,
@@ -666,7 +589,7 @@ make_wep_setting (shvarFile *ifcfg,
goto error; goto error;
/* Try to get keys from the "shadow" key file */ /* Try to get keys from the "shadow" key file */
keys_ifcfg = get_keys_ifcfg (file); keys_ifcfg = utils_get_keys_ifcfg (file, FALSE);
if (keys_ifcfg) { if (keys_ifcfg) {
if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wireless_sec, error)) { if (!read_wep_keys (keys_ifcfg, default_key_idx, s_wireless_sec, error)) {
svCloseFile (keys_ifcfg); svCloseFile (keys_ifcfg);
@@ -703,7 +626,7 @@ make_wep_setting (shvarFile *ifcfg,
g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", NULL); g_object_set (s_wireless_sec, NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "shared", NULL);
} else { } else {
g_set_error (error, ifcfg_plugin_error_quark (), 0, g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid WEP authentication algoritm '%s'", "Invalid WEP authentication algorithm '%s'",
lcase); lcase);
g_free (lcase); g_free (lcase);
goto error; goto error;
@@ -822,7 +745,7 @@ parse_wpa_psk (shvarFile *ifcfg,
*/ */
/* Try to get keys from the "shadow" key file */ /* Try to get keys from the "shadow" key file */
keys_ifcfg = get_keys_ifcfg (file); keys_ifcfg = utils_get_keys_ifcfg (file, FALSE);
if (keys_ifcfg) { if (keys_ifcfg) {
psk = svGetValue (keys_ifcfg, "WPA_PSK", TRUE); psk = svGetValue (keys_ifcfg, "WPA_PSK", TRUE);
svCloseFile (keys_ifcfg); svCloseFile (keys_ifcfg);
@@ -897,7 +820,7 @@ static EAPReader eap_readers[] = {
{ "chap", eap_simple_reader, TRUE }, { "chap", eap_simple_reader, TRUE },
{ "mschap", eap_simple_reader, TRUE }, { "mschap", eap_simple_reader, TRUE },
{ "mschapv2", eap_simple_reader, TRUE }, { "mschapv2", eap_simple_reader, TRUE },
{ "leap", eap_simple_reader, FALSE }, { "leap", eap_simple_reader, TRUE },
{ "tls", eap_tls_reader, FALSE }, { "tls", eap_tls_reader, FALSE },
{ "peap", eap_peap_reader, FALSE }, { "peap", eap_peap_reader, FALSE },
{ "ttls", eap_ttls_reader, FALSE }, { "ttls", eap_ttls_reader, FALSE },
@@ -965,6 +888,21 @@ get_cert_file (const char *ifcfg_path, const char *cert_path)
return ret; return ret;
} }
static void
set_file_path (NMSetting8021x *s_8021x,
const char *path_tag,
const char *hash_tag,
const char *path,
const char *setting_key)
{
GByteArray *data = NULL;
g_object_set_data_full (G_OBJECT (s_8021x), path_tag, g_strdup (path), g_free);
g_object_get (G_OBJECT (s_8021x), setting_key, &data, NULL);
if (data)
g_object_set_data_full (G_OBJECT (s_8021x), hash_tag, utils_hash_byte_array (data), g_free);
}
static gboolean static gboolean
eap_tls_reader (const char *eap_method, eap_tls_reader (const char *eap_method,
shvarFile *ifcfg, shvarFile *ifcfg,
@@ -989,9 +927,19 @@ eap_tls_reader (const char *eap_method,
if (phase2) { if (phase2) {
if (!nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, real_path, NULL, error)) if (!nm_setting_802_1x_set_phase2_ca_cert_from_file (s_8021x, real_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_PHASE2_CA_CERT_PATH,
TAG_PHASE2_CA_CERT_HASH,
real_path,
NM_SETTING_802_1X_PHASE2_CA_CERT);
} else { } else {
if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_path, NULL, error)) if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_CA_CERT_PATH,
TAG_CA_CERT_HASH,
real_path,
NM_SETTING_802_1X_CA_CERT);
} }
} else { } else {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing %s for EAP" PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing %s for EAP"
@@ -1036,9 +984,19 @@ eap_tls_reader (const char *eap_method,
if (phase2) { if (phase2) {
if (!nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error)) if (!nm_setting_802_1x_set_phase2_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_PHASE2_PRIVATE_KEY_PATH,
TAG_PHASE2_PRIVATE_KEY_HASH,
real_path,
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
} else { } else {
if (!nm_setting_802_1x_set_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error)) if (!nm_setting_802_1x_set_private_key_from_file (s_8021x, real_path, privkey_password, &privkey_type, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_PRIVATE_KEY_PATH,
TAG_PRIVATE_KEY_HASH,
real_path,
NM_SETTING_802_1X_PRIVATE_KEY);
} }
/* Per NM requirements, if the private key is pkcs12, set the client cert to the /* Per NM requirements, if the private key is pkcs12, set the client cert to the
@@ -1048,9 +1006,19 @@ eap_tls_reader (const char *eap_method,
if (phase2) { if (phase2) {
if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error)) if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_PHASE2_CLIENT_CERT_PATH,
TAG_PHASE2_CLIENT_CERT_HASH,
real_path,
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
} else { } else {
if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error)) if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_CLIENT_CERT_PATH,
TAG_CLIENT_CERT_HASH,
real_path,
NM_SETTING_802_1X_CLIENT_CERT);
} }
} else { } else {
/* Set the private key password if not PKCS#12 */ /* Set the private key password if not PKCS#12 */
@@ -1078,9 +1046,19 @@ eap_tls_reader (const char *eap_method,
if (phase2) { if (phase2) {
if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error)) if (!nm_setting_802_1x_set_phase2_client_cert_from_file (s_8021x, real_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_PHASE2_CLIENT_CERT_PATH,
TAG_PHASE2_CLIENT_CERT_HASH,
real_path,
NM_SETTING_802_1X_PHASE2_CLIENT_CERT);
} else { } else {
if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error)) if (!nm_setting_802_1x_set_client_cert_from_file (s_8021x, real_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_CLIENT_CERT_PATH,
TAG_CLIENT_CERT_HASH,
real_path,
NM_SETTING_802_1X_CLIENT_CERT);
} }
} }
@@ -1116,6 +1094,11 @@ eap_peap_reader (const char *eap_method,
real_cert_path = get_cert_file (ifcfg->fileName, ca_cert); real_cert_path = get_cert_file (ifcfg->fileName, ca_cert);
if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error)) if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_CA_CERT_PATH,
TAG_CA_CERT_HASH,
real_cert_path,
NM_SETTING_802_1X_CA_CERT);
} else { } else {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing " PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing "
"IEEE_8021X_CA_CERT for EAP method '%s'; this is" "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
@@ -1212,6 +1195,11 @@ eap_ttls_reader (const char *eap_method,
real_cert_path = get_cert_file (ifcfg->fileName, ca_cert); real_cert_path = get_cert_file (ifcfg->fileName, ca_cert);
if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error)) if (!nm_setting_802_1x_set_ca_cert_from_file (s_8021x, real_cert_path, NULL, error))
goto done; goto done;
set_file_path (s_8021x,
TAG_CA_CERT_PATH,
TAG_CA_CERT_HASH,
real_cert_path,
NM_SETTING_802_1X_CA_CERT);
} else { } else {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing " PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: missing "
"IEEE_8021X_CA_CERT for EAP method '%s'; this is" "IEEE_8021X_CA_CERT for EAP method '%s'; this is"
@@ -1301,7 +1289,7 @@ fill_8021x (shvarFile *ifcfg,
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new (); s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
/* Read in the lookaside keys file, if present */ /* Read in the lookaside keys file, if present */
keys = get_keys_ifcfg (file); keys = utils_get_keys_ifcfg (file, FALSE);
/* Validate and handle each EAP method */ /* Validate and handle each EAP method */
for (iter = list; iter && *iter; iter++) { for (iter = list; iter && *iter; iter++) {
@@ -1437,6 +1425,64 @@ error:
return NULL; return NULL;
} }
static NMSetting *
make_leap_setting (shvarFile *ifcfg,
const char *file,
GError **error)
{
NMSettingWirelessSecurity *wsec;
shvarFile *keys_ifcfg;
char *value;
wsec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
value = svGetValue (ifcfg, "KEY_MGMT", FALSE);
if (!value || strcmp (value, "IEEE8021X"))
goto error; /* Not LEAP */
g_free (value);
value = svGetValue (ifcfg, "SECURITYMODE", FALSE);
if (!value || strcasecmp (value, "leap"))
goto error; /* Not LEAP */
g_free (value);
value = svGetValue (ifcfg, "IEEE_8021X_PASSWORD", FALSE);
if (!value) {
/* Try to get keys from the "shadow" key file */
keys_ifcfg = utils_get_keys_ifcfg (file, FALSE);
if (keys_ifcfg) {
value = svGetValue (keys_ifcfg, "IEEE_8021X_PASSWORD", FALSE);
svCloseFile (keys_ifcfg);
}
}
if (value && strlen (value))
g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD, value, NULL);
g_free (value);
value = svGetValue (ifcfg, "IEEE_8021X_IDENTITY", FALSE);
if (!value || !strlen (value)) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing LEAP identity");
goto error;
}
g_object_set (wsec, NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME, value, NULL);
g_free (value);
g_object_set (wsec,
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "ieee8021x",
NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, "leap",
NULL);
return (NMSetting *) wsec;
error:
g_free (value);
if (wsec)
g_object_unref (wsec);
return NULL;
}
static NMSetting * static NMSetting *
make_wireless_security_setting (shvarFile *ifcfg, make_wireless_security_setting (shvarFile *ifcfg,
const char *file, const char *file,
@@ -1447,6 +1493,14 @@ make_wireless_security_setting (shvarFile *ifcfg,
{ {
NMSetting *wsec; NMSetting *wsec;
if (!adhoc) {
wsec = make_leap_setting (ifcfg, file, error);
if (wsec)
return wsec;
else if (*error)
return NULL;
}
wsec = make_wpa_setting (ifcfg, file, ssid, adhoc, s_8021x, error); wsec = make_wpa_setting (ifcfg, file, ssid, adhoc, s_8021x, error);
if (wsec) if (wsec)
return wsec; return wsec;
@@ -1481,23 +1535,64 @@ make_wireless_setting (shvarFile *ifcfg,
return NULL; return NULL;
} }
value = svGetValue (ifcfg, "ESSID", FALSE); value = svGetValue (ifcfg, "ESSID", TRUE);
if (value) { if (value) {
gsize len = strlen (value); gsize ssid_len = 0, value_len = strlen (value);
char *p = value, *tmp;
gboolean quoted = FALSE;
char buf[33];
if (len > 32 || len == 0) { ssid_len = value_len;
if ( (value_len >= 2)
&& (value[0] == '"')
&& (value[value_len - 1] == '"')) {
/* Strip the quotes and unescape */
p = value + 1;
value[value_len - 1] = '\0';
svUnescape (p);
ssid_len = strlen (p);
quoted = TRUE;
} else if ((value_len > 2) && (strncmp (value, "0x", 2) == 0)) {
/* Hex representation */
if (value_len % 2) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid SSID '%s' size (looks like hex but length not multiple of 2)",
value);
g_free (value);
goto error;
}
p = value + 2;
while (*p) {
if (!isxdigit (*p)) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid SSID '%s' character (looks like hex SSID but '%c' isn't a hex digit)",
value, *p);
g_free (value);
goto error;
}
p++;
}
tmp = utils_hexstr2bin (value + 2, value_len - 2);
ssid_len = (value_len - 2) / 2;
memcpy (buf, tmp, ssid_len);
p = &buf[0];
}
if (ssid_len > 32 || ssid_len == 0) {
g_set_error (error, ifcfg_plugin_error_quark (), 0, g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)", "Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)",
value, len); value, ssid_len);
g_free (value); g_free (value);
goto error; goto error;
} }
array = g_byte_array_sized_new (strlen (value)); array = g_byte_array_sized_new (strlen (p));
g_byte_array_append (array, (const guint8 *) value, len); g_byte_array_append (array, (const guint8 *) p, ssid_len);
g_free (value);
g_object_set (s_wireless, NM_SETTING_WIRELESS_SSID, array, NULL); g_object_set (s_wireless, NM_SETTING_WIRELESS_SSID, array, NULL);
g_byte_array_free (array, TRUE); g_byte_array_free (array, TRUE);
g_free (value);
} else { } else {
/* Only fail on lack of SSID if device is managed */ /* Only fail on lack of SSID if device is managed */
if (!unmanaged) { if (!unmanaged) {
@@ -1506,33 +1601,53 @@ make_wireless_setting (shvarFile *ifcfg,
} }
} }
if (!unmanaged) { if (unmanaged)
value = svGetValue (ifcfg, "MODE", FALSE); goto done;
if (value) {
char *lcase;
const char *mode = NULL;
lcase = g_ascii_strdown (value, -1); value = svGetValue (ifcfg, "MODE", FALSE);
g_free (value); if (value) {
char *lcase;
const char *mode = NULL;
if (!strcmp (lcase, "ad-hoc")) { lcase = g_ascii_strdown (value, -1);
mode = "adhoc"; g_free (value);
} else if (!strcmp (lcase, "managed")) {
mode = "infrastructure"; if (!strcmp (lcase, "ad-hoc")) {
} else { mode = "adhoc";
g_set_error (error, ifcfg_plugin_error_quark (), 0, } else if (!strcmp (lcase, "managed")) {
"Invalid mode '%s' (not 'Ad-Hoc' or 'Managed')", mode = "infrastructure";
lcase); } else {
g_free (lcase); g_set_error (error, ifcfg_plugin_error_quark (), 0,
goto error; "Invalid mode '%s' (not 'Ad-Hoc' or 'Managed')",
} lcase);
g_free (lcase); g_free (lcase);
goto error;
g_object_set (s_wireless, NM_SETTING_WIRELESS_MODE, mode, NULL);
} }
// FIXME: channel/freq, other L2 parameters like RTS g_free (lcase);
g_object_set (s_wireless, NM_SETTING_WIRELESS_MODE, mode, NULL);
} }
value = svGetValue (ifcfg, "BSSID", FALSE);
if (value) {
struct ether_addr *eth;
GByteArray *bssid;
eth = ether_aton (value);
if (!eth) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid BSSID '%s'", value);
goto error;
}
bssid = g_byte_array_sized_new (ETH_ALEN);
g_byte_array_append (bssid, eth->ether_addr_octet, ETH_ALEN);
g_object_set (s_wireless, NM_SETTING_WIRELESS_BSSID, bssid, NULL);
g_byte_array_free (bssid, TRUE);
}
// FIXME: channel/freq, other L2 parameters like RTS
done:
return NM_SETTING (s_wireless); return NM_SETTING (s_wireless);
error: error:
@@ -1655,8 +1770,10 @@ make_wired_setting (shvarFile *ifcfg,
} }
if (read_mac_address (ifcfg, &mac, error)) { if (read_mac_address (ifcfg, &mac, error)) {
g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL); if (mac) {
g_byte_array_free (mac, TRUE); g_object_set (s_wired, NM_SETTING_WIRED_MAC_ADDRESS, mac, NULL);
g_byte_array_free (mac, TRUE);
}
} else { } else {
g_object_unref (s_wired); g_object_unref (s_wired);
s_wired = NULL; s_wired = NULL;
@@ -1783,7 +1900,6 @@ connection_from_file (const char *filename,
gboolean *ignore_error) gboolean *ignore_error)
{ {
NMConnection *connection = NULL; NMConnection *connection = NULL;
NMSettingConnection *s_con;
shvarFile *parsed; shvarFile *parsed;
char *type; char *type;
char *nmc = NULL; char *nmc = NULL;
@@ -1799,7 +1915,7 @@ connection_from_file (const char *filename,
if (!network_file) if (!network_file)
network_file = SYSCONFDIR "/sysconfig/network"; network_file = SYSCONFDIR "/sysconfig/network";
ifcfg_name = get_ifcfg_name (filename); ifcfg_name = utils_get_ifcfg_name (filename);
if (!ifcfg_name) { if (!ifcfg_name) {
g_set_error (error, ifcfg_plugin_error_quark (), 0, g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Ignoring connection '%s' because it's not an ifcfg file.", filename); "Ignoring connection '%s' because it's not an ifcfg file.", filename);
@@ -1876,13 +1992,6 @@ connection_from_file (const char *filename,
g_free (type); g_free (type);
/* We don't write connections yet */
if (connection) {
s_con = (NMSettingConnection *) nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION);
if (s_con)
g_object_set (s_con, NM_SETTING_CONNECTION_READ_ONLY, TRUE, NULL);
}
/* Don't bother reading the connection fully if it's unmanaged */ /* Don't bother reading the connection fully if it's unmanaged */
if (!connection || *ignored) if (!connection || *ignored)
goto done; goto done;
@@ -1901,7 +2010,7 @@ connection_from_file (const char *filename,
connection = NULL; connection = NULL;
} }
*keyfile = get_keys_file_path (filename); *keyfile = utils_get_keys_path (filename);
done: done:
svCloseFile (parsed); svCloseFile (parsed);

View File

@@ -24,8 +24,7 @@
#include <glib.h> #include <glib.h>
#include <nm-connection.h> #include <nm-connection.h>
#define TYPE_ETHERNET "Ethernet" #include "shvar.h"
#define TYPE_WIRELESS "Wireless"
NMConnection *connection_from_file (const char *filename, NMConnection *connection_from_file (const char *filename,
const char *network_file, const char *network_file,

View File

@@ -112,8 +112,8 @@ svCreateFile(const char *name)
} }
/* remove escaped characters in place */ /* remove escaped characters in place */
static void void
unescape(char *s) { svUnescape(char *s) {
int len, i; int len, i;
len = strlen(s); len = strlen(s);
@@ -142,8 +142,8 @@ unescape(char *s) {
*/ */
static const char escapees[] = "\"'\\$~`"; /* must be escaped */ static const char escapees[] = "\"'\\$~`"; /* must be escaped */
static const char spaces[] = " \t|&;()<>"; /* only require "" */ static const char spaces[] = " \t|&;()<>"; /* only require "" */
static char * char *
escape(const char *s) { svEscape(const char *s) {
char *new; char *new;
int i, j, mangle = 0, space = 0; int i, j, mangle = 0, space = 0;
int newlen, slen; int newlen, slen;
@@ -202,7 +202,7 @@ svGetValue(shvarFile *s, const char *key, gboolean verbatim)
if (!strncmp(keyString, line, len)) { if (!strncmp(keyString, line, len)) {
value = g_strdup(line + len); value = g_strdup(line + len);
if (!verbatim) if (!verbatim)
unescape(value); svUnescape(value);
break; break;
} }
} }
@@ -272,7 +272,7 @@ svTrueValue(shvarFile *s, const char *key, int def)
* *
*/ */
void void
svSetValue(shvarFile *s, const char *key, const char *value) svSetValue(shvarFile *s, const char *key, const char *value, gboolean verbatim)
{ {
char *newval = NULL, *val1 = NULL, *val2 = NULL; char *newval = NULL, *val1 = NULL, *val2 = NULL;
char *keyValue; char *keyValue;
@@ -281,7 +281,8 @@ svSetValue(shvarFile *s, const char *key, const char *value)
g_assert(key); g_assert(key);
/* value may be NULL */ /* value may be NULL */
if (value) newval = escape(value); if (value)
newval = verbatim ? g_strdup(value) : svEscape(value);
keyValue = g_strdup_printf("%s=%s", key, newval ? newval : ""); keyValue = g_strdup_printf("%s=%s", key, newval ? newval : "");
val1 = svGetValue(s, key, FALSE); val1 = svGetValue(s, key, FALSE);

View File

@@ -77,7 +77,7 @@ svTrueValue(shvarFile *s, const char *key, int def);
* to the top of the file. * to the top of the file.
*/ */
void void
svSetValue(shvarFile *s, const char *key, const char *value); svSetValue(shvarFile *s, const char *key, const char *value, gboolean verbatim);
/* Write the current contents iff modified. Returns -1 on error /* Write the current contents iff modified. Returns -1 on error
@@ -95,6 +95,14 @@ svWriteFile(shvarFile *s, int mode);
int int
svCloseFile(shvarFile *s); svCloseFile(shvarFile *s);
/* Return a new escaped string */
char *
svEscape(const char *s);
/* Unescape a string in-place */
void
svUnescape(char *s);
#ifdef __cplusplus #ifdef __cplusplus
} }
#endif /* __cplusplus */ #endif /* __cplusplus */

View File

@@ -11,12 +11,19 @@ EXTRA_DIST = \
keys-test-wired-8021x-peap-mschapv2 \ keys-test-wired-8021x-peap-mschapv2 \
ifcfg-test-onboot-no \ ifcfg-test-onboot-no \
ifcfg-test-wifi-open \ ifcfg-test-wifi-open \
ifcfg-test-wifi-open-ssid-quoted \
ifcfg-test-wifi-open-ssid-long-quoted \
ifcfg-test-wifi-open-ssid-hex \
ifcfg-test-wifi-open-ssid-long-hex \
ifcfg-test-wifi-open-ssid-bad-hex \
ifcfg-test-wifi-wep \ ifcfg-test-wifi-wep \
keys-test-wifi-wep \ keys-test-wifi-wep \
ifcfg-test-wifi-wep-adhoc \ ifcfg-test-wifi-wep-adhoc \
keys-test-wifi-wep-adhoc \ keys-test-wifi-wep-adhoc \
ifcfg-test-wifi-wep-eap-ttls-chap \ ifcfg-test-wifi-wep-eap-ttls-chap \
keys-test-wifi-wep-eap-ttls-chap \ keys-test-wifi-wep-eap-ttls-chap \
ifcfg-test-wifi-leap \
keys-test-wifi-leap \
ifcfg-test-wifi-wpa-psk \ ifcfg-test-wifi-wpa-psk \
keys-test-wifi-wpa-psk \ keys-test-wifi-wpa-psk \
ifcfg-test-wifi-wpa-psk-adhoc \ ifcfg-test-wifi-wpa-psk-adhoc \

View File

@@ -0,0 +1,17 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID=blahblah
CHANNEL=1
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no
KEY_MGMT=IEEE8021X
SECURITYMODE=LEAP
IEEE_8021X_IDENTITY="Bill Smith"

View File

@@ -0,0 +1,13 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID=0x626cxx
CHANNEL=1
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no

View File

@@ -0,0 +1,13 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID=0x626c6168626c6168
CHANNEL=1
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no

View File

@@ -0,0 +1,13 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID=0x626c6168626c6168626c6168626c6168626c6168626c6168626c6168626c6168AA
CHANNEL=1
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no

View File

@@ -0,0 +1,13 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID="foo\"bar\\foo\"bar\\foo\"bar\\foo\"bar\\1"
CHANNEL=1
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no

View File

@@ -0,0 +1,13 @@
TYPE=Wireless
DEVICE=eth2
HWADDR=00:16:41:11:22:33
NM_CONTROLLED=yes
BOOTPROTO=dhcp
ESSID="foo\"bar\\"
CHANNEL=1
MODE=Managed
RATE=auto
ONBOOT=yes
USERCTL=yes
PEERDNS=yes
IPV6INIT=no

View File

@@ -0,0 +1 @@
IEEE_8021X_PASSWORD="foobarblah"

View File

@@ -39,6 +39,7 @@
#include "nm-test-helpers.h" #include "nm-test-helpers.h"
#include "common.h"
#include "reader.h" #include "reader.h"
typedef enum { typedef enum {
@@ -1191,7 +1192,7 @@ test_read_wired_8021x_peap_mschapv2 (void)
#define TEST_IFCFG_WIFI_OPEN TEST_DIR"/network-scripts/ifcfg-test-wifi-open" #define TEST_IFCFG_WIFI_OPEN TEST_DIR"/network-scripts/ifcfg-test-wifi-open"
static void static void
test_read_wifi_unencrypted (void) test_read_wifi_open (void)
{ {
NMConnection *connection; NMConnection *connection;
NMSettingConnection *s_con; NMSettingConnection *s_con;
@@ -1361,6 +1362,180 @@ test_read_wifi_unencrypted (void)
g_object_unref (connection); g_object_unref (connection);
} }
#define TEST_IFCFG_WIFI_OPEN_SSID_HEX TEST_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-hex"
static void
test_read_wifi_open_ssid_hex (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
gboolean unmanaged = FALSE;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const GByteArray *array;
const char *expected_id = "System blahblah (test-wifi-open-ssid-hex)";
const char *expected_ssid = "blahblah";
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NULL,
TYPE_WIRELESS,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"wifi-open-ssid-hex-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_HEX, error->message);
ASSERT (nm_connection_verify (connection, &error),
"wifi-open-ssid-hex-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_HEX, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"wifi-open-ssid-hex-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"wifi-open-ssid-hex-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"wifi-open-ssid-hex-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* ===== WIRELESS SETTING ===== */
s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
ASSERT (s_wireless != NULL,
"wifi-open-ssid-hex-verify-wireless", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_WIRELESS_SETTING_NAME);
/* SSID */
array = nm_setting_wireless_get_ssid (s_wireless);
ASSERT (array != NULL,
"wifi-open-ssid-hex-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID);
ASSERT (array->len == strlen (expected_ssid),
"wifi-open-ssid-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID);
ASSERT (memcmp (array->data, expected_ssid, strlen (expected_ssid)) == 0,
"wifi-open-ssid-hex-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_OPEN_SSID_HEX,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID);
g_object_unref (connection);
}
static void
test_read_wifi_open_ssid_bad (const char *file, const char *test)
{
NMConnection *connection;
gboolean unmanaged = FALSE;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
connection = connection_from_file (file, NULL, TYPE_WIRELESS, &unmanaged, &keyfile, &error, &ignore_error);
ASSERT (connection == NULL, test, "unexpected success reading %s", file);
g_clear_error (&error);
}
#define TEST_IFCFG_WIFI_OPEN_SSID_QUOTED TEST_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-quoted"
static void
test_read_wifi_open_ssid_quoted (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
gboolean unmanaged = FALSE;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const GByteArray *array;
const char *expected_id = "System foo\"bar\\ (test-wifi-open-ssid-quoted)";
const char *expected_ssid = "foo\"bar\\";
connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NULL,
TYPE_WIRELESS,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"wifi-open-ssid-quoted-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, error->message);
ASSERT (nm_connection_verify (connection, &error),
"wifi-open-ssid-quoted-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_SSID_QUOTED, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"wifi-open-ssid-quoted-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"wifi-open-ssid-quoted-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"wifi-open-ssid-quoted-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* ===== WIRELESS SETTING ===== */
s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
ASSERT (s_wireless != NULL,
"wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_WIRELESS_SETTING_NAME);
/* SSID */
array = nm_setting_wireless_get_ssid (s_wireless);
ASSERT (array != NULL,
"wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID);
ASSERT (array->len == strlen (expected_ssid),
"wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value length",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID);
ASSERT (memcmp (array->data, expected_ssid, strlen (expected_ssid)) == 0,
"wifi-open-ssid-quoted-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_OPEN_SSID_QUOTED,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SSID);
g_object_unref (connection);
}
#define TEST_IFCFG_WIFI_WEP TEST_DIR"/network-scripts/ifcfg-test-wifi-wep" #define TEST_IFCFG_WIFI_WEP TEST_DIR"/network-scripts/ifcfg-test-wifi-wep"
static void static void
@@ -1880,6 +2055,137 @@ test_read_wifi_wep_adhoc (void)
g_object_unref (connection); g_object_unref (connection);
} }
#define TEST_IFCFG_WIFI_LEAP TEST_DIR"/network-scripts/ifcfg-test-wifi-leap"
static void
test_read_wifi_leap (void)
{
NMConnection *connection;
NMSettingConnection *s_con;
NMSettingWireless *s_wireless;
NMSettingWirelessSecurity *s_wsec;
gboolean unmanaged = FALSE;
char *keyfile = NULL;
gboolean ignore_error = FALSE;
GError *error = NULL;
const char *tmp;
const char *expected_id = "System blahblah (test-wifi-leap)";
const char *expected_identity = "Bill Smith";
const char *expected_password = "foobarblah";
connection = connection_from_file (TEST_IFCFG_WIFI_LEAP,
NULL,
TYPE_WIRELESS,
&unmanaged,
&keyfile,
&error,
&ignore_error);
ASSERT (connection != NULL,
"wifi-leap-read", "failed to read %s: %s", TEST_IFCFG_WIFI_LEAP, error->message);
ASSERT (nm_connection_verify (connection, &error),
"wifi-leap-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_LEAP, error->message);
/* ===== CONNECTION SETTING ===== */
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
ASSERT (s_con != NULL,
"wifi-leap-verify-connection", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_CONNECTION_SETTING_NAME);
/* ID */
tmp = nm_setting_connection_get_id (s_con);
ASSERT (tmp != NULL,
"wifi-leap-verify-connection", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
ASSERT (strcmp (tmp, expected_id) == 0,
"wifi-leap-verify-connection", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_CONNECTION_SETTING_NAME,
NM_SETTING_CONNECTION_ID);
/* ===== WIRELESS SETTING ===== */
s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS));
ASSERT (s_wireless != NULL,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SETTING_NAME);
/* Security */
tmp = nm_setting_wireless_get_security (s_wireless);
ASSERT (tmp != NULL,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SEC);
ASSERT (strcmp (tmp, NM_SETTING_WIRELESS_SECURITY_SETTING_NAME) == 0,
"wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SETTING_NAME,
NM_SETTING_WIRELESS_SEC);
/* ===== WIRELESS SECURITY SETTING ===== */
s_wsec = NM_SETTING_WIRELESS_SECURITY (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY));
ASSERT (s_wsec != NULL,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s setting",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
/* Key management */
ASSERT (strcmp (nm_setting_wireless_security_get_key_mgmt (s_wsec), "ieee8021x") == 0,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT);
/* WEP Authentication mode */
tmp = nm_setting_wireless_security_get_auth_alg (s_wsec);
ASSERT (tmp != NULL,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
ASSERT (strcmp (tmp, "leap") == 0,
"wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_AUTH_ALG);
/* LEAP Username */
tmp = nm_setting_wireless_security_get_leap_username (s_wsec);
ASSERT (tmp != NULL,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
ASSERT (strcmp (tmp, expected_identity) == 0,
"wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_LEAP_USERNAME);
/* LEAP Password */
tmp = nm_setting_wireless_security_get_leap_password (s_wsec);
ASSERT (tmp != NULL,
"wifi-leap-verify-wireless", "failed to verify %s: missing %s / %s key",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
ASSERT (strcmp (tmp, expected_password) == 0,
"wifi-leap-verify-wireless", "failed to verify %s: unexpected %s / %s key value",
TEST_IFCFG_WIFI_LEAP,
NM_SETTING_WIRELESS_SECURITY_SETTING_NAME,
NM_SETTING_WIRELESS_SECURITY_LEAP_PASSWORD);
g_object_unref (connection);
}
#define TEST_IFCFG_WIFI_WPA_PSK TEST_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk" #define TEST_IFCFG_WIFI_WPA_PSK TEST_DIR"/network-scripts/ifcfg-test-wifi-wpa-psk"
static void static void
@@ -2951,6 +3257,10 @@ test_read_wifi_wep_eap_ttls_chap (void)
g_object_unref (connection); g_object_unref (connection);
} }
#define TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX TEST_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-bad-hex"
#define TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED TEST_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-quoted"
#define TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX TEST_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-long-hex"
int main (int argc, char **argv) int main (int argc, char **argv)
{ {
GError *error = NULL; GError *error = NULL;
@@ -2972,9 +3282,15 @@ int main (int argc, char **argv)
test_read_wired_never_default (); test_read_wired_never_default ();
test_read_onboot_no (); test_read_onboot_no ();
test_read_wired_8021x_peap_mschapv2 (); test_read_wired_8021x_peap_mschapv2 ();
test_read_wifi_unencrypted (); test_read_wifi_open ();
test_read_wifi_open_ssid_hex ();
test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX, "wifi-open-ssid-bad-hex-read");
test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX, "wifi-open-ssid-long-hex-read");
test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_QUOTED, "wifi-open-ssid-long-quoted-read");
test_read_wifi_open_ssid_quoted ();
test_read_wifi_wep (); test_read_wifi_wep ();
test_read_wifi_wep_adhoc (); test_read_wifi_wep_adhoc ();
test_read_wifi_leap ();
test_read_wifi_wpa_psk (); test_read_wifi_wpa_psk ();
test_read_wifi_wpa_psk_adhoc (); test_read_wifi_wpa_psk_adhoc ();
test_read_wifi_wpa_psk_hex (); test_read_wifi_wpa_psk_hex ();

View File

@@ -0,0 +1,195 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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.
*
* (C) Copyright 2008 - 2009 Red Hat, Inc.
*/
#include <glib.h>
#include <stdlib.h>
#include <string.h>
#include "utils.h"
#include "sha1.h"
#include "shvar.h"
/*
* utils_bin2hexstr
*
* Convert a byte-array into a hexadecimal string.
*
* Code originally by Alex Larsson <alexl@redhat.com> and
* copyright Red Hat, Inc. under terms of the LGPL.
*
*/
char *
utils_bin2hexstr (const char *bytes, int len, int final_len)
{
static char hex_digits[] = "0123456789abcdef";
char * result;
int i;
g_return_val_if_fail (bytes != NULL, NULL);
g_return_val_if_fail (len > 0, NULL);
g_return_val_if_fail (len < 256, NULL); /* Arbitrary limit */
result = g_malloc0 (len * 2 + 1);
for (i = 0; i < len; i++)
{
result[2*i] = hex_digits[(bytes[i] >> 4) & 0xf];
result[2*i+1] = hex_digits[bytes[i] & 0xf];
}
/* Cut converted key off at the correct length for this cipher type */
if (final_len > -1)
result[final_len] = '\0';
return result;
}
/* From hostap, Copyright (c) 2002-2005, Jouni Malinen <jkmaline@cc.hut.fi> */
static int hex2num (char c)
{
if (c >= '0' && c <= '9')
return c - '0';
if (c >= 'a' && c <= 'f')
return c - 'a' + 10;
if (c >= 'A' && c <= 'F')
return c - 'A' + 10;
return -1;
}
static int hex2byte (const char *hex)
{
int a, b;
a = hex2num(*hex++);
if (a < 0)
return -1;
b = hex2num(*hex++);
if (b < 0)
return -1;
return (a << 4) | b;
}
char *
utils_hexstr2bin (const char *hex, size_t len)
{
size_t i;
int a;
const char * ipos = hex;
char * buf = NULL;
char * opos;
/* Length must be a multiple of 2 */
if ((len % 2) != 0)
return NULL;
opos = buf = g_malloc0 ((len / 2) + 1);
for (i = 0; i < len; i += 2) {
a = hex2byte (ipos);
if (a < 0) {
g_free (buf);
return NULL;
}
*opos++ = a;
ipos += 2;
}
return buf;
}
/* End from hostap */
char *
utils_hash_byte_array (const GByteArray *data)
{
unsigned char buf[SHA1_MAC_LEN];
static const char *key = "0123456789abcdefghijklmnopqrstuvwxyz";
memset (buf, 0, sizeof (buf));
sha1_mac ((const unsigned char *) key, strlen (key), (const u_int8_t *) data->data, data->len, &buf[0]);
return utils_bin2hexstr ((const char *) &buf[0], SHA1_MAC_LEN, SHA1_MAC_LEN * 2);
}
char *
utils_cert_path (const char *parent, const char *prefix, const char *suffix)
{
char *name, *dir, *path;
name = utils_get_ifcfg_name (parent);
dir = g_path_get_dirname (parent);
path = g_strdup_printf ("%s/%s-%s.%s", dir, prefix, name, suffix);
g_free (dir);
g_free (name);
return path;
}
char *
utils_get_ifcfg_name (const char *file)
{
char *ifcfg_name;
char *basename;
basename = g_path_get_basename (file);
if (!basename)
return NULL;
ifcfg_name = g_strdup (basename + strlen (IFCFG_TAG));
g_free (basename);
return ifcfg_name;
}
char *
utils_get_keys_path (const char *parent)
{
char *ifcfg_name;
char *keys_file = NULL;
char *tmp = NULL;
ifcfg_name = utils_get_ifcfg_name (parent);
if (!ifcfg_name)
return NULL;
tmp = g_path_get_dirname (parent);
if (!tmp)
goto out;
keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name);
out:
g_free (tmp);
g_free (ifcfg_name);
return keys_file;
}
shvarFile *
utils_get_keys_ifcfg (const char *parent, gboolean should_create)
{
shvarFile *ifcfg = NULL;
char *path;
path = utils_get_keys_path (parent);
if (!path)
return NULL;
if (should_create && !g_file_test (path, G_FILE_TEST_EXISTS))
ifcfg = svCreateFile (path);
if (!ifcfg)
ifcfg = svNewFile (path);
g_free (path);
return ifcfg;
}

View File

@@ -0,0 +1,43 @@
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
/* NetworkManager system settings service
*
* 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.
*
* (C) Copyright 2008 - 2009 Red Hat, Inc.
*/
#ifndef _UTILS_H_
#define _UTILS_H_
#include <glib.h>
#include "shvar.h"
#include "common.h"
char *utils_bin2hexstr (const char *bytes, int len, int final_len);
char *utils_hexstr2bin (const char *hex, size_t len);
char *utils_hash_byte_array (const GByteArray *data);
char *utils_cert_path (const char *parent, const char *prefix, const char *suffix);
char *utils_get_ifcfg_name (const char *file);
char *utils_get_keys_path (const char *parent);
shvarFile *utils_get_keys_ifcfg (const char *parent, gboolean should_create);
#endif /* _UTILS_H_ */

View File

@@ -20,28 +20,607 @@
#include <ctype.h> #include <ctype.h>
#include <string.h> #include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <nm-setting-connection.h> #include <nm-setting-connection.h>
#include <nm-setting-wired.h> #include <nm-setting-wired.h>
#include <nm-setting-wireless.h> #include <nm-setting-wireless.h>
#include <nm-setting-8021x.h>
#include <nm-setting-ip4-config.h>
#include "common.h" #include "common.h"
#include "shvar.h" #include "shvar.h"
#include "reader.h"
#include "writer.h" #include "writer.h"
#include "utils.h"
#define PLUGIN_WARN(pname, fmt, args...) \
{ g_warning (" " pname ": " fmt, ##args); }
static void
set_secret (shvarFile *ifcfg, const char *key, const char *value)
{
shvarFile *keyfile;
keyfile = utils_get_keys_ifcfg (ifcfg->fileName, TRUE);
if (!keyfile) {
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: could not create key file for '%s'",
ifcfg->fileName);
goto error;
}
/* Clear the secret from the actual ifcfg */
svSetValue (ifcfg, key, NULL, FALSE);
svSetValue (keyfile, key, value, FALSE);
if (!svWriteFile (keyfile, 0600)) {
svCloseFile (keyfile);
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: could not update key file '%s'",
keyfile->fileName);
goto error;
}
svCloseFile (keyfile);
return;
error:
/* Try setting the secret in the actual ifcfg */
svSetValue (ifcfg, key, value, FALSE);
}
static gboolean
write_cert (NMSetting8021x *s_8021x,
shvarFile *ifcfg,
const char *setting_key,
const char *ifcfg_key,
const char *path_tag,
const char *hash_tag,
const char *prefix,
gboolean is_pkcs12,
gboolean *wrote,
GError **error)
{
const char *orig_hash, *orig_file;
char *new_hash = NULL, *new_file = NULL;
const GByteArray *cert = NULL;
gboolean success = FALSE;
GError *write_error = NULL;
*wrote = FALSE;
g_object_get (G_OBJECT (s_8021x), setting_key, &cert, NULL);
if (!cert) {
svSetValue (ifcfg, ifcfg_key, NULL, FALSE);
return TRUE;
}
new_hash = utils_hash_byte_array (cert);
if (!new_hash) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Could not hash certificate data for %s / %s",
NM_SETTING_802_1X_SETTING_NAME, setting_key);
return FALSE;
}
orig_hash = g_object_get_data (G_OBJECT (s_8021x), TAG_CA_CERT_HASH);
orig_file = g_object_get_data (G_OBJECT (s_8021x), TAG_CA_CERT_PATH);
if (!orig_hash || !orig_file || strcmp (new_hash, orig_hash)) {
/* if the cert data has changed, or there wasn't a cert
* originally, write data out to the standard file.
*/
new_file = utils_cert_path (ifcfg->fileName, prefix, is_pkcs12 ? "p12" : "der");
if (!new_file) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Could not create file path for %s / %s",
NM_SETTING_802_1X_SETTING_NAME, setting_key);
goto out;
}
if (!g_file_set_contents (new_file, (const char *) cert->data, cert->len, &write_error)) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Could not write certificate for %s / %s: %s",
NM_SETTING_802_1X_SETTING_NAME, setting_key,
(write_error && write_error->message) ? write_error->message : "(unknown)");
g_clear_error (&write_error);
goto out;
}
*wrote = TRUE;
svSetValue (ifcfg, ifcfg_key, new_file, FALSE);
g_object_set_data_full (G_OBJECT (s_8021x), path_tag, new_file, g_free);
new_file = NULL; /* g_object_set_data_full() took ownership */
g_object_set_data_full (G_OBJECT (s_8021x), hash_tag, new_hash, g_free);
new_hash = NULL; /* g_object_set_data_full() took ownership */
} else {
/* cert data hasn't changed */
svSetValue (ifcfg, ifcfg_key, orig_file, FALSE);
}
success = TRUE;
out:
g_free (new_hash);
g_free (new_file);
return success;
}
static gboolean
write_8021x_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
{
NMSetting8021x *s_8021x;
const char *value;
char *tmp;
gboolean success = FALSE, is_pkcs12 = FALSE, wrote;
s_8021x = (NMSetting8021x *) nm_connection_get_setting (connection, NM_TYPE_SETTING_802_1X);
if (!s_8021x)
return TRUE;
/* EAP method */
if (nm_setting_802_1x_get_num_eap_methods (s_8021x)) {
value = nm_setting_802_1x_get_eap_method (s_8021x, 0);
if (value)
tmp = g_ascii_strup (value, -1);
}
svSetValue (ifcfg, "IEEE_8021X_EAP_METHODS", tmp ? tmp : NULL, FALSE);
g_free (tmp);
svSetValue (ifcfg, "IEEE_8021X_IDENTITY",
nm_setting_802_1x_get_identity (s_8021x),
FALSE);
svSetValue (ifcfg, "IEEE_8021X_ANON_IDENTITY",
nm_setting_802_1x_get_anonymous_identity (s_8021x),
FALSE);
set_secret (ifcfg, "IEEE_8021X_PASSWORD", nm_setting_802_1x_get_password (s_8021x));
/* CA certificate */
if (!write_cert (s_8021x, ifcfg,
NM_SETTING_802_1X_CA_CERT,
"IEEE_8021X_CA_CERT",
TAG_CA_CERT_PATH,
TAG_CA_CERT_HASH,
"ca-cert",
FALSE, &wrote,
error))
goto out;
/* Private key */
if (nm_setting_802_1x_get_private_key (s_8021x)) {
if (nm_setting_802_1x_get_private_key_type (s_8021x) == NM_SETTING_802_1X_CK_TYPE_PKCS12)
is_pkcs12 = TRUE;
}
if (!write_cert (s_8021x, ifcfg,
NM_SETTING_802_1X_PRIVATE_KEY,
"IEEE_8021X_PRIVATE_KEY",
TAG_PRIVATE_KEY_PATH,
TAG_PRIVATE_KEY_HASH,
"private-key",
is_pkcs12, &wrote,
error))
goto out;
if (is_pkcs12) {
svSetValue (ifcfg, "IEEE_8021X_PRIVATE_KEY_PASSWORD",
nm_setting_802_1x_get_private_key_password (s_8021x), FALSE);
} else {
/* Clear the private key password for non-pkcs12 private keys that
* we just wrote out, since it will be unencrypted.
*/
if (wrote)
svSetValue (ifcfg, "IEEE_8021X_PRIVATE_KEY_PASSWORD", NULL, FALSE);
/* Client certificate */
if (!write_cert (s_8021x, ifcfg,
NM_SETTING_802_1X_CA_CERT,
"IEEE_8021X_CA_CERT",
TAG_CA_CERT_PATH,
TAG_CA_CERT_HASH,
"ca-cert",
FALSE, &wrote,
error))
goto out;
}
success = TRUE;
out:
return success;
}
static gboolean
write_wireless_security_setting (NMConnection *connection,
shvarFile *ifcfg,
gboolean adhoc,
gboolean *no_8021x,
GError **error)
{
NMSettingWirelessSecurity *s_wsec;
const char *key_mgmt, *auth_alg, *key, *proto, *cipher, *psk;
gboolean wep = FALSE, wpa = FALSE, first;
char *tmp;
guint32 i, num;
GString *str;
s_wsec = (NMSettingWirelessSecurity *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS_SECURITY);
if (!s_wsec) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing '%s' setting", NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
return FALSE;
}
key_mgmt = nm_setting_wireless_security_get_key_mgmt (s_wsec);
g_assert (key_mgmt);
auth_alg = nm_setting_wireless_security_get_auth_alg (s_wsec);
svSetValue (ifcfg, "DEFAULTKEY", NULL, FALSE);
if (!strcmp (key_mgmt, "none")) {
wep = TRUE;
*no_8021x = TRUE;
} else if (!strcmp (key_mgmt, "wpa-none") || !strcmp (key_mgmt, "wpa-psk")) {
svSetValue (ifcfg, "KEY_MGMT", "WPA-PSK", FALSE);
wpa = TRUE;
*no_8021x = TRUE;
} else if (!strcmp (key_mgmt, "ieee8021x")) {
svSetValue (ifcfg, "KEY_MGMT", "IEEE8021X", FALSE);
} else if (!strcmp (key_mgmt, "wpa-eap")) {
svSetValue (ifcfg, "KEY_MGMT", "WPA-EAP", FALSE);
wpa = TRUE;
}
svSetValue (ifcfg, "SECURITYMODE", NULL, FALSE);
if (auth_alg) {
if (!strcmp (auth_alg, "shared"))
svSetValue (ifcfg, "SECURITYMODE", "restricted", FALSE);
else if (!strcmp (auth_alg, "open"))
svSetValue (ifcfg, "SECURITYMODE", "open", FALSE);
else if (!strcmp (auth_alg, "leap")) {
svSetValue (ifcfg, "SECURITYMODE", "leap", FALSE);
svSetValue (ifcfg, "IEEE_8021X_USERNAME",
nm_setting_wireless_security_get_leap_username (s_wsec),
FALSE);
set_secret (ifcfg, "IEEE_8021X_PASSWORD",
nm_setting_wireless_security_get_leap_password (s_wsec));
*no_8021x = TRUE;
}
}
if (wep) {
/* Default WEP TX key index */
tmp = g_strdup_printf ("%d", nm_setting_wireless_security_get_wep_tx_keyidx (s_wsec) + 1);
svSetValue (ifcfg, "DEFAULTKEY", tmp, FALSE);
g_free (tmp);
}
/* WEP keys */
set_secret (ifcfg, "KEY", NULL); /* Clear any default key */
for (i = 0; i < 4; i++) {
key = nm_setting_wireless_security_get_wep_key (s_wsec, i);
tmp = g_strdup_printf ("KEY%d", i + 1);
set_secret (ifcfg, tmp, (wep && key) ? key : NULL);
g_free (tmp);
}
/* WPA protos */
svSetValue (ifcfg, "WPA_ALLOW_WPA", NULL, FALSE);
svSetValue (ifcfg, "WPA_ALLOW_WPA2", NULL, FALSE);
num = nm_setting_wireless_security_get_num_protos (s_wsec);
for (i = 0; i < num; i++) {
proto = nm_setting_wireless_security_get_proto (s_wsec, i);
if (proto && !strcmp (proto, "wpa"))
svSetValue (ifcfg, "WPA_ALLOW_WPA", "yes", FALSE);
else if (proto && !strcmp (proto, "rsn"))
svSetValue (ifcfg, "WPA_ALLOW_WPA2", "yes", FALSE);
}
/* WPA Pairwise ciphers */
svSetValue (ifcfg, "CIPHER_PAIRWISE", NULL, FALSE);
str = g_string_new (NULL);
num = nm_setting_wireless_security_get_num_pairwise (s_wsec);
for (i = 0, first = TRUE; i < num; i++) {
if (!first)
g_string_append_c (str, ' ');
cipher = nm_setting_wireless_security_get_pairwise (s_wsec, i);
tmp = g_ascii_strup (cipher, -1);
g_string_append (str, tmp);
g_free (tmp);
}
if (strlen (str->str))
svSetValue (ifcfg, "CIPHER_PAIRWISE", str->str, FALSE);
g_string_free (str, TRUE);
/* WPA Group ciphers */
svSetValue (ifcfg, "CIPHER_GROUP", NULL, FALSE);
str = g_string_new (NULL);
num = nm_setting_wireless_security_get_num_groups (s_wsec);
for (i = 0, first = TRUE; i < num; i++) {
if (!first)
g_string_append_c (str, ' ');
cipher = nm_setting_wireless_security_get_group (s_wsec, i);
tmp = g_ascii_strup (cipher, -1);
g_string_append (str, tmp);
g_free (tmp);
}
if (strlen (str->str))
svSetValue (ifcfg, "CIPHER_GROUP", str->str, FALSE);
g_string_free (str, TRUE);
/* WPA Passphrase */
psk = nm_setting_wireless_security_get_psk (s_wsec);
set_secret (ifcfg, "WPA_PSK", (wpa && psk) ? psk : NULL);
return TRUE;
}
static gboolean
write_wireless_setting (NMConnection *connection,
shvarFile *ifcfg,
gboolean *no_8021x,
GError **error)
{
NMSettingWireless *s_wireless;
char *tmp, *tmp2;
const GByteArray *ssid, *mac, *bssid;
const char *mode;
char buf[33];
guint32 mtu, chan, i;
gboolean adhoc = FALSE, hex_ssid = FALSE;
s_wireless = (NMSettingWireless *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS);
if (!s_wireless) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
return FALSE;
}
mac = nm_setting_wireless_get_mac_address (s_wireless);
if (mac) {
tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
mac->data[0], mac->data[1], mac->data[2],
mac->data[3], mac->data[4], mac->data[5]);
svSetValue (ifcfg, "HWADDR", tmp, FALSE);
g_free (tmp);
}
mtu = nm_setting_wireless_get_mtu (s_wireless);
if (mtu) {
tmp = g_strdup_printf ("%u", mtu);
svSetValue (ifcfg, "MTU", tmp, FALSE);
g_free (tmp);
}
ssid = nm_setting_wireless_get_ssid (s_wireless);
if (!ssid) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
return FALSE;
}
if (!ssid->len || ssid->len > 32) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid SSID in '%s' setting", NM_SETTING_WIRELESS_SETTING_NAME);
return FALSE;
}
/* If the SSID contains any non-printable characters, we need to use the
* hex notation of the SSID instead.
*/
for (i = 0; i < ssid->len; i++) {
if (!isprint (ssid->data[i])) {
hex_ssid = TRUE;
break;
}
}
if (hex_ssid) {
GString *str;
/* Hex SSIDs don't get quoted */
str = g_string_sized_new (ssid->len * 2 + 3);
g_string_append (str, "0x");
for (i = 0; i < ssid->len; i++)
g_string_append_printf (str, "%02X", ssid->data[i]);
svSetValue (ifcfg, "ESSID", str->str, TRUE);
g_string_free (str, TRUE);
} else {
/* Printable SSIDs get quoted */
memset (buf, 0, sizeof (buf));
memcpy (buf, ssid->data, ssid->len);
tmp2 = svEscape (buf);
tmp = g_strdup_printf ("\"%s\"", tmp2);
svSetValue (ifcfg, "ESSID", tmp, TRUE);
g_free (tmp2);
g_free (tmp);
}
mode = nm_setting_wireless_get_mode (s_wireless);
if (!mode || !strcmp (mode, "infrastructure")) {
svSetValue (ifcfg, "MODE", "Managed", FALSE);
} else if (!strcmp (mode, "adhoc")) {
svSetValue (ifcfg, "MODE", "Ad-Hoc", FALSE);
adhoc = TRUE;
} else {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Invalid mode '%s' in '%s' setting",
mode, NM_SETTING_WIRELESS_SETTING_NAME);
return FALSE;
}
chan = nm_setting_wireless_get_channel (s_wireless);
if (chan) {
tmp = g_strdup_printf ("%d", chan);
svSetValue (ifcfg, "CHANNEL", tmp, FALSE);
g_free (tmp);
}
bssid = nm_setting_wireless_get_bssid (s_wireless);
if (bssid) {
tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
bssid->data[0], bssid->data[1], bssid->data[2],
bssid->data[3], bssid->data[4], bssid->data[5]);
svSetValue (ifcfg, "BSSID", tmp, FALSE);
g_free (tmp);
}
// FIXME: channel/freq, other L2 parameters like RTS
if (nm_setting_wireless_get_security (s_wireless)) {
if (!write_wireless_security_setting (connection, ifcfg, adhoc, no_8021x, error))
return FALSE;
}
svSetValue (ifcfg, "TYPE", TYPE_WIRELESS, FALSE);
return TRUE;
}
static gboolean
write_wired_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
{
NMSettingWired *s_wired;
const GByteArray *mac;
char *tmp;
guint32 mtu;
s_wired = (NMSettingWired *) nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED);
if (!s_wired) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing '%s' setting", NM_SETTING_WIRED_SETTING_NAME);
return FALSE;
}
mac = nm_setting_wired_get_mac_address (s_wired);
if (mac) {
tmp = g_strdup_printf ("%02X:%02X:%02X:%02X:%02X:%02X",
mac->data[0], mac->data[1], mac->data[2],
mac->data[3], mac->data[4], mac->data[5]);
svSetValue (ifcfg, "HWADDR", tmp, FALSE);
g_free (tmp);
}
mtu = nm_setting_wired_get_mtu (s_wired);
if (mtu) {
tmp = g_strdup_printf ("%u", mtu);
svSetValue (ifcfg, "MTU", tmp, FALSE);
g_free (tmp);
}
svSetValue (ifcfg, "TYPE", TYPE_ETHERNET, FALSE);
return TRUE;
}
static void static void
write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg) write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
{ {
char *tmp; char *tmp;
svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con)); svSetValue (ifcfg, "NAME", nm_setting_connection_get_id (s_con), FALSE);
svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con)); svSetValue (ifcfg, "UUID", nm_setting_connection_get_uuid (s_con), FALSE);
svSetValue (ifcfg, "ONBOOT", svSetValue (ifcfg, "ONBOOT",
nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no"); nm_setting_connection_get_autoconnect (s_con) ? "yes" : "no",
FALSE);
tmp = g_strdup_printf ("%llu", nm_setting_connection_get_timestamp (s_con)); tmp = g_strdup_printf ("%llu", nm_setting_connection_get_timestamp (s_con));
svSetValue (ifcfg, "LAST_CONNECTION", tmp); svSetValue (ifcfg, "LAST_CONNECTION", tmp, FALSE);
g_free (tmp); g_free (tmp);
} }
static gboolean
write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
{
NMSettingIP4Config *s_ip4;
const char *value;
char *addr_key, *prefix_key, *gw_key, *tmp;
guint32 i, num;
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (!s_ip4) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Missing '%s' setting", NM_SETTING_IP4_CONFIG_SETTING_NAME);
return FALSE;
}
value = nm_setting_ip4_config_get_method (s_ip4);
g_assert (value);
if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_AUTO))
svSetValue (ifcfg, "BOOTPROTO", "dhcp", FALSE);
else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_MANUAL))
svSetValue (ifcfg, "BOOTPROTO", "none", FALSE);
else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_LINK_LOCAL))
svSetValue (ifcfg, "BOOTPROTO", "autoip", FALSE);
else if (!strcmp (value, NM_SETTING_IP4_CONFIG_METHOD_SHARED))
svSetValue (ifcfg, "BOOTPROTO", "shared", FALSE);
num = nm_setting_ip4_config_get_num_addresses (s_ip4);
for (i = 0; i < 254; i++) {
char buf[INET_ADDRSTRLEN + 1];
NMIP4Address *addr;
guint32 ip;
if (i == 0) {
addr_key = g_strdup ("IPADDR");
prefix_key = g_strdup ("PREFIX");
gw_key = g_strdup ("GATEWAY");
} else {
addr_key = g_strdup_printf ("IPADDR%d", i);
prefix_key = g_strdup_printf ("PREFIX%d", i);
gw_key = g_strdup_printf ("GATEWAY%d", i);
}
if (i >= num) {
svSetValue (ifcfg, addr_key, NULL, FALSE);
svSetValue (ifcfg, prefix_key, NULL, FALSE);
svSetValue (ifcfg, gw_key, NULL, FALSE);
} else {
addr = nm_setting_ip4_config_get_address (s_ip4, i);
memset (buf, 0, sizeof (buf));
ip = nm_ip4_address_get_address (addr);
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
svSetValue (ifcfg, addr_key, &buf[0], FALSE);
tmp = g_strdup_printf ("%u", nm_ip4_address_get_prefix (addr));
svSetValue (ifcfg, prefix_key, tmp, FALSE);
g_free (tmp);
if (nm_ip4_address_get_gateway (addr)) {
memset (buf, 0, sizeof (buf));
ip = nm_ip4_address_get_gateway (addr);
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
svSetValue (ifcfg, gw_key, &buf[0], FALSE);
} else
svSetValue (ifcfg, gw_key, NULL, FALSE);
}
g_free (addr_key);
g_free (prefix_key);
g_free (gw_key);
}
num = nm_setting_ip4_config_get_num_dns (s_ip4);
for (i = 0; i < 254; i++) {
char buf[INET_ADDRSTRLEN + 1];
guint32 ip;
addr_key = g_strdup_printf ("DNS%d", i);
if (i >= num)
svSetValue (ifcfg, addr_key, NULL, FALSE);
else {
ip = nm_setting_ip4_config_get_dns (s_ip4, i);
memset (buf, 0, sizeof (buf));
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
svSetValue (ifcfg, addr_key, &buf[0], FALSE);
}
g_free (addr_key);
}
return TRUE;
}
static char * static char *
escape_id (const char *id) escape_id (const char *id)
{ {
@@ -56,6 +635,7 @@ escape_id (const char *id)
*p = '-'; *p = '-';
else if (*p == '\\') else if (*p == '\\')
*p = '-'; *p = '-';
p++;
} }
return escaped; return escaped;
@@ -73,6 +653,7 @@ write_connection (NMConnection *connection,
shvarFile *ifcfg = NULL; shvarFile *ifcfg = NULL;
char *ifcfg_name = NULL; char *ifcfg_name = NULL;
const char *type; const char *type;
gboolean no_8021x = FALSE;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
if (!s_con) { if (!s_con) {
@@ -108,15 +689,35 @@ write_connection (NMConnection *connection,
} }
if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) { if (!strcmp (type, NM_SETTING_WIRED_SETTING_NAME)) {
if (!write_wired_setting (connection, ifcfg, error))
goto out;
} else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) { } else if (!strcmp (type, NM_SETTING_WIRELESS_SETTING_NAME)) {
if (!write_wireless_setting (connection, ifcfg, &no_8021x, error))
goto out;
} else { } else {
g_set_error (error, ifcfg_plugin_error_quark (), 0, g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Can't write connection type '%s'", type); "Can't write connection type '%s'", type);
goto out; goto out;
} }
if (!no_8021x) {
if (!write_8021x_setting (connection, ifcfg, error))
goto out;
}
if (!write_ip4_setting (connection, ifcfg, error))
goto out;
write_connection_setting (s_con, ifcfg); write_connection_setting (s_con, ifcfg);
if (svWriteFile (ifcfg, 0644)) {
g_set_error (error, ifcfg_plugin_error_quark (), 0,
"Can't write connection '%s'", ifcfg->fileName);
goto out;
}
svCloseFile (ifcfg);
success = TRUE;
out: out:
g_free (ifcfg_name); g_free (ifcfg_name);