2008-05-08 Tambet Ingo <tambet@gmail.com>

Rewrite the suse system settings plugin.

	* system-settings/plugins/ifcfg-suse/plugin.c: Rewrite.

	* system-settings/plugins/ifcfg-suse/parser.c: Rewrite.

	* system-settings/plugins/ifcfg-suse/nm-suse-connection.[ch]: Implement.

	* system-settings/plugins/ifcfg-suse/Makefile.am: Add new files to build.

	* system-settings/src/dbus-settings.c: Fix connection reference counting.

	* system-settings/src/main.c (load_plugins): Improve error reporting.

	* system-settings/src/sha1.[ch] Add.

	* system-settings/src/Makefile.am: Add sha1[ch] to build.


git-svn-id: http://svn-archive.gnome.org/svn/NetworkManager/trunk@3644 4912f4e0-d625-0410-9fb7-b9a5a253dbdc
This commit is contained in:
Tambet Ingo 2008-05-08 07:20:02 +00:00
parent 9559a7a260
commit 8928b8dbe7
12 changed files with 1468 additions and 650 deletions

View file

@ -1,3 +1,23 @@
2008-05-08 Tambet Ingo <tambet@gmail.com>
Rewrite the suse system settings plugin.
* system-settings/plugins/ifcfg-suse/plugin.c: Rewrite.
* system-settings/plugins/ifcfg-suse/parser.c: Rewrite.
* system-settings/plugins/ifcfg-suse/nm-suse-connection.[ch]: Implement.
* system-settings/plugins/ifcfg-suse/Makefile.am: Add new files to build.
* system-settings/src/dbus-settings.c: Fix connection reference counting.
* system-settings/src/main.c (load_plugins): Improve error reporting.
* system-settings/src/sha1.[ch] Add.
* system-settings/src/Makefile.am: Add sha1[ch] to build.
2008-05-07 Dan Williams <dcbw@redhat.com>
* system-settings/plugins/keyfile/reader.c

View file

@ -2,6 +2,8 @@
pkglib_LTLIBRARIES = libnm-settings-plugin-ifcfg-suse.la
libnm_settings_plugin_ifcfg_suse_la_SOURCES = \
nm-suse-connection.c \
nm-suse-connection.h \
shvar.c \
shvar.h \
parser.c \
@ -17,7 +19,7 @@ libnm_settings_plugin_ifcfg_suse_la_CPPFLAGS = \
-I${top_srcdir}/system-settings/src \
-I$(top_srcdir)/include \
-I$(top_srcdir)/libnm-util \
-I${top_srcdir}/libnm-glib \
-I$(top_srcdir)/libnm-glib \
-DSYSCONFDIR=\"$(sysconfdir)\"
libnm_settings_plugin_ifcfg_suse_la_LDFLAGS = -module -avoid-version

View file

@ -0,0 +1,144 @@
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
#include <string.h>
#include <glib/gstdio.h>
#include <gio/gio.h>
#include <NetworkManager.h>
#include "nm-suse-connection.h"
#include "parser.h"
G_DEFINE_TYPE (NMSuseConnection, nm_suse_connection, NM_TYPE_EXPORTED_CONNECTION)
#define NM_SUSE_CONNECTION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionPrivate))
typedef struct {
GFileMonitor *monitor;
guint monitor_id;
const char *iface;
NMDeviceType dev_type;
char *filename;
} NMSuseConnectionPrivate;
static void
file_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (user_data);
NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported);
NMConnection *new_connection;
GHashTable *new_settings;
switch (event_type) {
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
new_connection = parse_ifcfg (priv->iface, priv->dev_type);
if (new_connection) {
new_settings = nm_connection_to_hash (new_connection);
nm_exported_connection_update (exported, new_settings);
g_hash_table_destroy (new_settings);
g_object_unref (new_connection);
} else
nm_exported_connection_delete (exported);
break;
case G_FILE_MONITOR_EVENT_DELETED:
nm_exported_connection_delete (exported);
break;
default:
break;
}
}
NMSuseConnection *
nm_suse_connection_new (const char *iface, NMDeviceType dev_type)
{
NMConnection *connection;
GFile *file;
GFileMonitor *monitor;
NMSuseConnection *exported;
NMSuseConnectionPrivate *priv;
g_return_val_if_fail (iface != NULL, NULL);
connection = parse_ifcfg (iface, dev_type);
if (!connection)
return NULL;
exported = (NMSuseConnection *) g_object_new (NM_TYPE_SUSE_CONNECTION,
NM_EXPORTED_CONNECTION_CONNECTION, connection,
NULL);
g_object_unref (connection);
if (!exported)
return NULL;
priv = NM_SUSE_CONNECTION_GET_PRIVATE (exported);
priv->iface = g_strdup (iface);
priv->dev_type = dev_type;
priv->filename = g_strdup_printf (SYSCONFDIR "/sysconfig/network/ifcfg-%s", iface);
file = g_file_new_for_path (priv->filename);
monitor = g_file_monitor_file (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
if (monitor) {
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (file_changed), exported);
priv->monitor = monitor;
}
return exported;
}
static GHashTable *
get_settings (NMExportedConnection *exported)
{
return nm_connection_to_hash (nm_exported_connection_get_connection (exported));
}
static const char *
get_id (NMExportedConnection *exported)
{
return NM_SUSE_CONNECTION_GET_PRIVATE (exported)->filename;
}
/* GObject */
static void
nm_suse_connection_init (NMSuseConnection *connection)
{
}
static void
finalize (GObject *object)
{
NMSuseConnectionPrivate *priv = NM_SUSE_CONNECTION_GET_PRIVATE (object);
if (priv->monitor) {
if (priv->monitor_id)
g_signal_handler_disconnect (priv->monitor, priv->monitor_id);
g_file_monitor_cancel (priv->monitor);
g_object_unref (priv->monitor);
}
g_free (priv->filename);
G_OBJECT_CLASS (nm_suse_connection_parent_class)->finalize (object);
}
static void
nm_suse_connection_class_init (NMSuseConnectionClass *suse_connection_class)
{
GObjectClass *object_class = G_OBJECT_CLASS (suse_connection_class);
NMExportedConnectionClass *connection_class = NM_EXPORTED_CONNECTION_CLASS (suse_connection_class);
g_type_class_add_private (suse_connection_class, sizeof (NMSuseConnectionPrivate));
/* Virtual methods */
object_class->finalize = finalize;
connection_class->get_settings = get_settings;
connection_class->get_id = get_id;
}

View file

@ -0,0 +1,33 @@
/* -*- Mode: C; tab-width: 5; indent-tabs-mode: t; c-basic-offset: 5 -*- */
#ifndef NM_SUSE_CONNECTION_H
#define NM_SUSE_CONNECTION_H
#include <NetworkManager.h>
#include <nm-settings.h>
G_BEGIN_DECLS
#define NM_TYPE_SUSE_CONNECTION (nm_suse_connection_get_type ())
#define NM_SUSE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_CAST ((obj), NM_TYPE_SUSE_CONNECTION, NMSuseConnection))
#define NM_SUSE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST ((klass), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionClass))
#define NM_IS_SUSE_CONNECTION(obj) (G_TYPE_CHECK_INSTANCE_TYPE ((obj), NM_TYPE_SUSE_CONNECTION))
#define NM_IS_SUSE_CONNECTION_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE ((obj), NM_TYPE_SUSE_CONNECTION))
#define NM_SUSE_CONNECTION_GET_CLASS(obj) (G_TYPE_INSTANCE_GET_CLASS ((obj), NM_TYPE_SUSE_CONNECTION, NMSuseConnectionClass))
typedef struct {
NMExportedConnection parent;
} NMSuseConnection;
typedef struct {
NMExportedConnectionClass parent;
} NMSuseConnectionClass;
GType nm_suse_connection_get_type (void);
NMSuseConnection *nm_suse_connection_new (const char *iface,
NMDeviceType dev_type);
G_END_DECLS
#endif /* NM_SUSE_CONNECTION_H */

View file

@ -38,12 +38,17 @@
#include <nm-setting-ip4-config.h>
#include <nm-setting-wired.h>
#include <nm-setting-wireless.h>
#include <nm-setting-8021x.h>
#include <nm-utils.h>
#include "shvar.h"
#include "parser.h"
#include "plugin.h"
#include "sha1.h"
#define WPA_PMK_LEN 32
/* Common */
static gboolean
get_int (const char *str, int *value)
@ -57,81 +62,37 @@ get_int (const char *str, int *value)
return TRUE;
}
#if 0
static gboolean
read_startmode (shvarFile *file)
{
char *value;
gboolean automatic = TRUE;
value = svGetValue (file, "STARTMODE");
if (value) {
if (!g_ascii_strcasecmp (value, "manual"))
automatic = FALSE;
else if (!g_ascii_strcasecmp (value, "off")) {
// FIXME: actually ignore the device, not the connection
g_message ("Ignoring connection '%s' because NM_CONTROLLED was false", file);
automatic = FALSE;
}
g_free (value);
}
return automatic;
}
#endif
static NMSetting *
make_connection_setting (const char *file,
shvarFile *ifcfg,
make_connection_setting (shvarFile *file,
const char *iface,
const char *type,
const char *suggested)
{
NMSettingConnection *s_con;
char *basename = NULL;
int len;
char *ifcfg_name;
basename = g_path_get_basename (file);
if (!basename)
goto error;
len = strlen (basename);
if (len < strlen (IFCFG_TAG) + 1)
goto error;
if (strncmp (basename, IFCFG_TAG, strlen (IFCFG_TAG)))
goto error;
/* ignore .bak files */
if ((len > 4) && !strcmp (basename + len - 4, BAK_TAG))
goto error;
char *str;
s_con = NM_SETTING_CONNECTION (nm_setting_connection_new ());
ifcfg_name = (char *) (basename + strlen (IFCFG_TAG));
if (suggested) {
/* For cosmetic reasons, if the suggested name is the same as
* the ifcfg files name, don't use it.
*/
if (strcmp (ifcfg_name, suggested)) {
s_con->id = g_strdup_printf ("System %s (%s)", suggested, ifcfg_name);
ifcfg_name = NULL;
}
if (strcmp (iface, suggested))
s_con->id = g_strdup_printf ("System %s (%s)", suggested, iface);
}
if (ifcfg_name)
s_con->id = g_strdup_printf ("System %s", ifcfg_name);
if (!s_con->id)
s_con->id = g_strdup_printf ("System %s", iface);
s_con->type = g_strdup (type);
s_con->autoconnect = TRUE;
str = svGetValue (file, "STARTMODE");
if (str && !g_ascii_strcasecmp (str, "manual"))
s_con->autoconnect = FALSE;
else
s_con->autoconnect = TRUE;
g_free (str);
return (NMSetting *) s_con;
error:
g_free (basename);
return NULL;
}
static guint32
@ -150,70 +111,73 @@ ip4_prefix_to_netmask (int prefix)
}
static NMSetting *
make_ip4_setting (shvarFile *ifcfg, GError **error)
make_ip4_setting (shvarFile *ifcfg)
{
NMSettingIP4Config *s_ip4 = NULL;
char *value = NULL;
NMSettingIP4Config *s_ip4;
char *str;
NMSettingIP4Address tmp = { 0, 0, 0 };
char *method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
value = svGetValue (ifcfg, "BOOTPROTO");
if (!value)
return NULL;
s_ip4 = NM_SETTING_IP4_CONFIG (nm_setting_ip4_config_new ());
if (!g_ascii_strcasecmp (value, "bootp") || !g_ascii_strcasecmp (value, "dhcp")) {
method = NM_SETTING_IP4_CONFIG_METHOD_DHCP;
return NULL;
str = svGetValue (ifcfg, "BOOTPROTO");
if (str) {
if (!g_ascii_strcasecmp (str, "bootp") || !g_ascii_strcasecmp (str, "dhcp"))
s_ip4->method = g_strdup (NM_SETTING_IP4_CONFIG_METHOD_DHCP);
else if (!g_ascii_strcasecmp (str, "static"))
s_ip4->method = g_strdup (NM_SETTING_IP4_CONFIG_METHOD_MANUAL);
else if (!g_ascii_strcasecmp (str, "autoip"))
s_ip4->method = g_strdup (NM_SETTING_IP4_CONFIG_METHOD_AUTOIP);
g_free (str);
}
value = svGetValue (ifcfg, "IPADDR");
if (value) {
if (!s_ip4->method)
s_ip4->method = g_strdup (NM_SETTING_IP4_CONFIG_METHOD_DHCP);
str = svGetValue (ifcfg, "IPADDR");
if (str) {
char **pieces;
struct in_addr ip4_addr;
pieces = g_strsplit (value, "/", 2);
pieces = g_strsplit (str, "/", 2);
if (inet_pton (AF_INET, pieces[0], &ip4_addr))
if (inet_pton (AF_INET, pieces[0], &ip4_addr)) {
tmp.address = ip4_addr.s_addr;
else {
g_strfreev (pieces);
g_set_error (error, ifcfg_plugin_error_quark (), 0, "Invalid IP4 address '%s'", value);
goto error;
}
if (g_strv_length (pieces) == 2)
tmp.netmask = ip4_prefix_to_netmask (atoi (pieces[1]));
if (g_strv_length (pieces) == 2)
tmp.netmask = ip4_prefix_to_netmask (atoi (pieces[1]));
} else
g_warning ("Ignoring invalid IP4 address '%s'", str);
g_strfreev (pieces);
g_free (value);
g_free (str);
}
if (tmp.netmask == 0) {
value = svGetValue (ifcfg, "PREFIXLEN");
if (value) {
tmp.netmask = ip4_prefix_to_netmask (atoi (value));
g_free (value);
if (tmp.address && tmp.netmask == 0) {
str = svGetValue (ifcfg, "PREFIXLEN");
if (str) {
tmp.netmask = ip4_prefix_to_netmask (atoi (str));
g_free (str);
}
}
if (tmp.netmask == 0) {
value = svGetValue (ifcfg, "NETMASK");
if (value) {
if (tmp.address && tmp.netmask == 0) {
str = svGetValue (ifcfg, "NETMASK");
if (str) {
struct in_addr mask_addr;
if (inet_pton (AF_INET, value, &mask_addr))
if (inet_pton (AF_INET, str, &mask_addr))
tmp.netmask = mask_addr.s_addr;
else {
g_set_error (error, ifcfg_plugin_error_quark (), 0, "Invalid IP4 netmask '%s'", value);
goto error;
g_warning ("Ignoring invalid IP4 addres: invalid netmask: '%s'", str);
tmp.address = 0;
tmp.netmask = 0;
}
g_free (value);
g_free (str);
}
}
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
s_ip4->method = g_strdup (method);
if (tmp.address || tmp.netmask || tmp.gateway) {
if (tmp.address || tmp.netmask) {
NMSettingIP4Address *addr;
addr = g_new0 (NMSettingIP4Address, 1);
memcpy (addr, &tmp, sizeof (NMSettingIP4Address));
@ -221,48 +185,51 @@ make_ip4_setting (shvarFile *ifcfg, GError **error)
}
return NM_SETTING (s_ip4);
error:
g_free (value);
if (s_ip4)
g_object_unref (s_ip4);
return NULL;
}
#if 0
/*
* 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)
/* Ethernet */
static NMSetting *
make_wired_setting (shvarFile *ifcfg)
{
static char hex_digits[] = "0123456789abcdef";
char * result;
int i;
NMSettingWired *s_wired;
char *str;
int mtu;
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 */
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
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];
str = svGetValue (ifcfg, "MTU");
if (str) {
if (strlen (str) < 1)
/* Ignore empty MTU */
;
else if (get_int (str, &mtu)) {
if (mtu >= 0 && mtu < G_MAXINT)
s_wired->mtu = mtu;
} else
g_warning ("Ignoring invalid MTU: '%s'", str);
g_free (str);
}
/* Cut converted key off at the correct length for this cipher type */
if (final_len > -1)
result[final_len] = '\0';
return result;
return (NMSetting *) s_wired;
}
#endif
static void
parse_ethernet (NMConnection *connection, shvarFile *file, const char *iface)
{
NMSetting *setting;
setting = make_connection_setting (file, iface, NM_SETTING_WIRED_SETTING_NAME, NULL);
nm_connection_add_setting (connection, setting);
setting = make_wired_setting (file);
nm_connection_add_setting (connection, setting);
setting = make_ip4_setting (file);
nm_connection_add_setting (connection, setting);
}
/* Wireless */
static char *
get_one_wep_key (shvarFile *ifcfg, guint8 idx, GError **err)
@ -342,23 +309,23 @@ get_one_wep_key (shvarFile *ifcfg, guint8 idx, GError **err)
#define READ_WEP_KEY(idx) \
{ \
char *key = get_one_wep_key (ifcfg, idx, err); \
if (*err) \
char *key = get_one_wep_key (ifcfg, idx, &err); \
if (err) \
goto error; \
if (key) { \
g_object_set_data_full (G_OBJECT (security), \
NM_SETTING_WIRELESS_SECURITY_WEP_KEY##idx, \
key, \
g_free); \
g_object_set (G_OBJECT (security), \
NM_SETTING_WIRELESS_SECURITY_WEP_KEY##idx, \
key, \
NULL); \
have_key = TRUE; \
} \
}
static void
read_wep_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security, GError **err)
read_wep_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security)
{
char *value;
GError *err = NULL;
gboolean have_key = FALSE;
READ_WEP_KEY(0)
@ -378,13 +345,16 @@ read_wep_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security, GError
if (success && (key_idx >= 0) && (key_idx <= 3))
security->wep_tx_keyidx = key_idx;
else
g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid defualt WEP key '%s'", value);
g_warning ("Invalid default WEP key: '%s'", value);
g_free (value);
}
error:
return;
if (err) {
g_warning ("%s", err->message);
g_error_free (err);
}
}
/* Copied from applet/src/wireless-secuirty/wireless-security.c */
@ -406,384 +376,320 @@ ws_wpa_fill_default_ciphers (NMSettingWirelessSecurity *s_wireless_sec)
s_wireless_sec->group = g_slist_append (s_wireless_sec->group, g_strdup ("ccmp"));
}
/*
* 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 void
read_wpa_psk_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security, GError **err)
read_wpa_psk_settings (shvarFile *ifcfg,
NMSettingWirelessSecurity *security,
NMSettingWireless *s_wireless)
{
char *value;
value = svGetValue (ifcfg, "WIRELESS_WPA_PSK");
if (value) {
if (strlen (value) == 64) {
/* HEX key */
security->psk = value;
/* Hex PSK */
security->psk = g_strdup (value);
} else {
/* passphrase */
/* FIXME: */
/* unsigned char *buf = g_malloc0 (WPA_PMK_LEN * 2); */
/* pbkdf2_sha1 (value, (char *) s_wireless->ssid->data, s_wireless->ssid->len, 4096, buf, WPA_PMK_LEN); */
/* security->psk = utils_bin2hexstr ((const char *) buf, WPA_PMK_LEN, WPA_PMK_LEN * 2); */
/* g_free (buf); */
g_free (value);
unsigned char *buf = g_malloc0 (WPA_PMK_LEN * 2);
pbkdf2_sha1 (value, (char *) s_wireless->ssid->data, s_wireless->ssid->len, 4096, buf, WPA_PMK_LEN);
security->psk = utils_bin2hexstr ((const char *) buf, WPA_PMK_LEN, WPA_PMK_LEN * 2);
g_free (buf);
}
g_free (value);
ws_wpa_fill_default_ciphers (security);
} else
g_set_error (err, ifcfg_plugin_error_quark (), 0, "Missing WPA-PSK key.");
g_warning ("Missing WPA-PSK key");
}
#if 0
static void
read_wpa_eap_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security, GError **err)
read_wpa_eap_settings (shvarFile *ifcfg, NMSettingWirelessSecurity *security)
{
char *value;
char *str;
value = svGetValue (ifcfg, "WIRELESS_EAP_AUTH");
if (value) {
/* valid values are TLS PEAP TTLS */
security->eap = g_slist_append (NULL, value);
str = svGetValue (ifcfg, "WIRELESS_EAP_MODE");
if (str) {
char **pieces;
int i;
pieces = g_strsplit (str, " ", 0);
for (i = 0; pieces[i]; i++)
s_8021x->eap = g_slist_append (s_8021x->eap, pieces[i]);
g_free (pieces);
g_free (str);
}
value = svGetValue (ifcfg, "WIRELESS_WPA_PROTO");
if (value) {
/* valid values are WPA RSN (WPA2) */
security->proto = g_slist_append (NULL, value);
}
s_802_1x->anonymous_identity = svGetValue (ifcfg, "WIRELESS_WPA_ANONID");
security->identity = svGetValue (ifcfg, "WIRELESS_WPA_IDENTITY");
char *ca_path;
/* FIXME: This should be in get_secrets? */
value = svGetValue (ifcfg, "WIRELESS_WPA_PASSWORD");
if (value) {
g_free (value);
}
GByteArray *ca_cert;
"WIRELESS_CA_CERT";
security->anonymous_identity = svGetValue (ifcfg, "WIRELESS_WPA_ANONID");
GByteArray *client_cert;
"WIRELESS_CLIENT_CERT";
value = svGetValue (ifcfg, "WIRELESS_CA_CERT");
if (value) {
g_free (value);
}
GByteArray *private_key;
"WIRELESS_CLIENT_KEY";
value = svGetValue (ifcfg, "WIRELESS_CLIENT_CERT");
if (value) {
g_free (value);
}
private_key_passwd
"WIRELESS_CLIENT_KEY_PASSWORD";
/* FIXME: This should be in get_secrets? */
value = svGetValue (ifcfg, "WIRELESS_CLIENT_KEY");
if (value) {
g_free (value);
}
/* FIXME: This should be in get_secrets? */
value = svGetValue (ifcfg, "WIRELESS_CLIENT_KEY_PASSWORD");
if (value) {
g_free (value);
}
ws_wpa_fill_default_ciphers (security);
s_802_1x->phase1_peapver = svGetValue (ifcfg, "WIRELESS_PEAP_VERSION");
s_802_1x->phase2_auth = svGetValue (ifcfg, "WIRELESS_EAP_AUTH");
s_802_1x->identity = svGetValue (ifcfg, "WIRELESS_WPA_IDENTITY");
s_802_1x->password = svGetValue (ifcfg, "WIRELESS_WPA_PASSWORD");
}
#endif
static NMSetting *
make_wireless_security_setting (shvarFile *ifcfg, GError **err)
make_wireless_security_setting (shvarFile *ifcfg, NMSettingWireless *s_wireless)
{
NMSettingWirelessSecurity *s_wireless_sec = NULL;
char *value;
NMSettingWirelessSecurity *security;
char *str;
value = svGetValue (ifcfg, "WIRELESS_AUTH_MODE");
if (!value)
return NULL;
if (!g_ascii_strcasecmp (value, "no-encryption")) {
g_free (value);
str = svGetValue (ifcfg, "WIRELESS_AUTH_MODE");
if (!str || !g_ascii_strcasecmp (str, "no-encryption")) {
g_free (str);
return NULL;
}
s_wireless_sec = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
security = NM_SETTING_WIRELESS_SECURITY (nm_setting_wireless_security_new ());
if (!g_ascii_strcasecmp (value, "open")) {
s_wireless_sec->auth_alg = g_strdup ("open");
read_wep_settings (ifcfg, s_wireless_sec, err);
} else if (!g_ascii_strcasecmp (value, "sharedkey")) {
s_wireless_sec->auth_alg = g_strdup ("shared");
read_wep_settings (ifcfg, s_wireless_sec, err);
if (!g_ascii_strcasecmp (str, "open")) {
security->auth_alg = g_strdup ("open");
read_wep_settings (ifcfg, security);
} else if (!g_ascii_strcasecmp (str, "sharedkey")) {
security->auth_alg = g_strdup ("shared");
read_wep_settings (ifcfg, security);
}
else if (!g_ascii_strcasecmp (value, "psk")) {
s_wireless_sec->key_mgmt = g_strdup ("wpa-psk");
read_wpa_psk_settings (ifcfg, s_wireless_sec, err);
} else if (!g_ascii_strcasecmp (value, "eap")) {
s_wireless_sec->key_mgmt = g_strdup ("wps-eap");
/* read_wpa_eap_settings (ifcfg, s_wireless_sec, err); */
else if (!g_ascii_strcasecmp (str, "psk")) {
security->key_mgmt = g_strdup ("wpa-psk");
read_wpa_psk_settings (ifcfg, security, s_wireless);
} else if (!g_ascii_strcasecmp (str, "eap")) {
/* FIXME */
/* security->key_mgmt = g_strdup ("wps-eap"); */
/* read_wpa_eap_settings (ifcfg, security); */
g_warning ("WPA-EAP is currently not supported.");
g_object_unref (security);
security = NULL;
} else
g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid authentication algoritm '%s'", value);
g_warning ("Invalid authentication algorithm: '%s'", str);
g_free (value);
g_free (str);
if (*err == NULL)
return NM_SETTING (s_wireless_sec);
if (s_wireless_sec)
g_object_unref (s_wireless_sec);
return NULL;
return (NMSetting *) security;
}
static NMSetting *
make_wireless_setting (shvarFile *ifcfg,
NMSetting *security,
GError **err)
make_wireless_setting (shvarFile *ifcfg)
{
NMSettingWireless *s_wireless;
char *value;
char *str;
s_wireless = NM_SETTING_WIRELESS (nm_setting_wireless_new ());
value = svGetValue (ifcfg, "WIRELESS_ESSID");
if (value) {
gsize len = strlen (value);
str = svGetValue (ifcfg, "WIRELESS_ESSID");
if (str) {
gsize len = strlen (str);
if (len > 32 || len == 0) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Invalid SSID '%s' (size %zu not between 1 and 32 inclusive)",
value, len);
goto error;
}
if (len > 0 && len <= 32) {
s_wireless->ssid = g_byte_array_sized_new (len);
g_byte_array_append (s_wireless->ssid, (const guint8 *) str, len);
} else
g_warning ("Ignoring invalid ESSID '%s', (size %zu not between 1 and 32 inclusive)", str, len);
s_wireless->ssid = g_byte_array_sized_new (strlen (value));
g_byte_array_append (s_wireless->ssid, (const guint8 *) value, len);
g_free (value);
g_free (str);
}
value = svGetValue (ifcfg, "WIRLESS_MODE");
if (value) {
if (!g_ascii_strcasecmp (value, "ad-hoc")) {
str = svGetValue (ifcfg, "WIRLESS_MODE");
if (str) {
if (!g_ascii_strcasecmp (str, "ad-hoc"))
s_wireless->mode = g_strdup ("adhoc");
} else if (!g_ascii_strcasecmp (value, "managed")) {
else if (!g_ascii_strcasecmp (str, "managed"))
s_wireless->mode = g_strdup ("infrastructure");
} else {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Invalid mode '%s' (not ad-hoc or managed)", value);
g_free (value);
goto error;
}
g_free (value);
}
if (security)
s_wireless->security = g_strdup (NM_SETTING_WIRELESS_SECURITY_SETTING_NAME);
g_free (str);
}
// FIXME: channel/freq, other L2 parameters like RTS
return NM_SETTING (s_wireless);
error:
if (s_wireless)
g_object_unref (s_wireless);
return NULL;
}
static NMConnection *
wireless_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **err)
static char *
get_printable_ssid (NMSetting *setting)
{
NMConnection *connection = NULL;
NMSetting *con_setting = NULL;
NMSetting *wireless_setting = NULL;
NMSettingWireless *tmp;
NMSetting *security_setting = NULL;
NMSettingWireless *s_wireless = NM_SETTING_WIRELESS (setting);
char *printable_ssid = NULL;
connection = nm_connection_new ();
if (!connection) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Failed to allocate new connection for %s.", file);
return NULL;
if (s_wireless->ssid)
printable_ssid = nm_utils_ssid_to_utf8 ((const char *) s_wireless->ssid->data,
(guint32) s_wireless->ssid->len);
return printable_ssid;
}
static void
parse_wireless (NMConnection *connection, shvarFile *file, const char *iface)
{
NMSetting *setting;
NMSetting *security;
char *printable_ssid;
setting = make_wireless_setting (file);
nm_connection_add_setting (connection, setting);
security = make_wireless_security_setting (file, NM_SETTING_WIRELESS (setting));
if (security) {
const char *security_str;
if (NM_IS_SETTING_802_1X (security))
security_str = NM_SETTING_802_1X_SETTING_NAME;
else if (NM_IS_SETTING_WIRELESS_SECURITY (security))
security_str = NM_SETTING_WIRELESS_SECURITY_SETTING_NAME;
else {
security_str = NULL;
g_warning ("Invalid security type: '%s'", G_OBJECT_TYPE_NAME (security));
}
g_object_set (G_OBJECT (setting), NM_SETTING_WIRELESS_SEC, security_str, NULL);
nm_connection_add_setting (connection, security);
}
/* Wireless security */
security_setting = make_wireless_security_setting (ifcfg, err);
if (*err)
goto error;
if (security_setting)
nm_connection_add_setting (connection, security_setting);
/* Wireless */
wireless_setting = make_wireless_setting (ifcfg, security_setting, err);
if (!wireless_setting)
goto error;
nm_connection_add_setting (connection, wireless_setting);
tmp = NM_SETTING_WIRELESS (wireless_setting);
printable_ssid = nm_utils_ssid_to_utf8 ((const char *) tmp->ssid->data,
(guint32) tmp->ssid->len);
con_setting = make_connection_setting (file, ifcfg,
NM_SETTING_WIRELESS_SETTING_NAME,
printable_ssid);
printable_ssid = get_printable_ssid (setting);
setting = make_connection_setting (file, iface, NM_SETTING_WIRELESS_SETTING_NAME, printable_ssid);
nm_connection_add_setting (connection, setting);
g_free (printable_ssid);
if (!con_setting) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Failed to create connection setting.");
goto error;
}
nm_connection_add_setting (connection, con_setting);
if (!nm_connection_verify (connection)) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Connection from %s was invalid.", file);
goto error;
}
return connection;
error:
g_object_unref (connection);
if (con_setting)
g_object_unref (con_setting);
if (wireless_setting)
g_object_unref (wireless_setting);
return NULL;
setting = make_ip4_setting (file);
nm_connection_add_setting (connection, setting);
}
static NMSetting *
make_wired_setting (shvarFile *ifcfg, GError **err)
static shvarFile *
parser_get_ifcfg_for_iface (const char *iface)
{
NMSettingWired *s_wired;
char *value;
int mtu;
char *filename;
shvarFile *file = NULL;
s_wired = NM_SETTING_WIRED (nm_setting_wired_new ());
filename = g_strdup_printf (SYSCONFDIR "/sysconfig/network/ifcfg-%s", iface);
if (g_file_test (filename, G_FILE_TEST_IS_REGULAR))
file = svNewFile (filename);
value = svGetValue (ifcfg, "MTU");
if (value) {
if (strlen (value) < 1)
/* Ignore empty MTU */
;
else if (get_int (value, &mtu)) {
if (mtu >= 0 && mtu < 65536)
s_wired->mtu = mtu;
} else {
g_set_error (err, ifcfg_plugin_error_quark (), 0, "Invalid MTU '%s'", value);
g_object_unref (s_wired);
s_wired = NULL;
}
g_free (value);
}
g_free (filename);
return (NMSetting *) s_wired;
return file;
}
static NMConnection *
wired_connection_from_ifcfg (const char *file, shvarFile *ifcfg, GError **err)
NMConnection *
parse_ifcfg (const char *iface, NMDeviceType type)
{
NMConnection *connection = NULL;
NMSetting *con_setting = NULL;
NMSetting *wired_setting = NULL;
shvarFile *file;
NMConnection *connection;
g_return_val_if_fail (iface != NULL, NULL);
file = parser_get_ifcfg_for_iface (iface);
if (!file)
return NULL;
connection = nm_connection_new ();
con_setting = make_connection_setting (file, ifcfg, NM_SETTING_WIRED_SETTING_NAME, NULL);
if (!con_setting) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Failed to create connection setting.");
goto error;
switch (type) {
case DEVICE_TYPE_802_3_ETHERNET:
parse_ethernet (connection, file, iface);
break;
case DEVICE_TYPE_802_11_WIRELESS:
parse_wireless (connection, file, iface);
break;
default:
break;
}
nm_connection_add_setting (connection, con_setting);
wired_setting = make_wired_setting (ifcfg, err);
if (!wired_setting)
goto error;
nm_connection_add_setting (connection, wired_setting);
svCloseFile (file);
if (!nm_connection_verify (connection)) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Connection from %s was invalid.", file);
goto error;
g_object_unref (connection);
connection = NULL;
}
return connection;
error:
g_object_unref (connection);
if (con_setting)
g_object_unref (con_setting);
if (wired_setting)
g_object_unref (wired_setting);
return NULL;
}
NMConnection *
parser_parse_ifcfg (const char *file, GError **err)
gboolean
parser_ignore_device (const char *iface)
{
NMConnection *connection = NULL;
shvarFile *parsed;
char *type;
char *nmc = NULL;
NMSetting *s_ip4;
shvarFile *file;
gboolean ignore = FALSE;
g_return_val_if_fail (file != NULL, NULL);
file = parser_get_ifcfg_for_iface (iface);
if (file) {
char *str;
parsed = svNewFile (file);
if (!parsed) {
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Couldn't parse file '%s'", file);
return NULL;
if (!svTrueValue (file, "NM_CONTROLLED", 1))
ignore = TRUE;
str = svGetValue (file, "STARTMODE");
if (str && !g_ascii_strcasecmp (str, "off"))
ignore = TRUE;
g_free (str);
svCloseFile (file);
}
nmc = svGetValue (parsed, "NM_CONTROLLED");
if (nmc) {
if (!svTrueValue (parsed, nmc, 1)) {
g_free (nmc);
// FIXME: actually ignore the device, not the connection
g_message ("Ignoring connection '%s' because NM_CONTROLLED was false", file);
goto done;
}
g_free (nmc);
}
type = svGetValue (parsed, "WIRELESS_ESSID");
if (type) {
g_free (type);
connection = wireless_connection_from_ifcfg (file, parsed, err);
} else
connection = wired_connection_from_ifcfg (file, parsed, err);
if (!connection)
goto done;
s_ip4 = make_ip4_setting (parsed, err);
if (*err) {
g_object_unref (connection);
connection = NULL;
goto done;
} else if (s_ip4) {
nm_connection_add_setting (connection, s_ip4);
}
if (!nm_connection_verify (connection)) {
g_object_unref (connection);
connection = NULL;
g_set_error (err, ifcfg_plugin_error_quark (), 0,
"Connection was invalid");
}
done:
svCloseFile (parsed);
return connection;
return ignore;
}
guint32
parser_parse_routes (const char *file, GError **err)
parser_parse_routes (const char *filename)
{
FILE *f;
char *buf;
char buffer[512];
guint route = 0;
if ((f = fopen (SYSCONFDIR"/sysconfig/network/routes", "r"))) {
g_return_val_if_fail (filename != NULL, 0);
if ((f = fopen (filename, "r"))) {
while (fgets (buffer, 512, f) && !feof (f)) {
buf = strtok (buffer, " ");
if (strcmp (buf, "default") == 0) {

View file

@ -23,13 +23,15 @@
#define _PARSER_H_
#include <glib.h>
#include <NetworkManager.h>
#include <nm-connection.h>
#define IFCFG_TAG "ifcfg-"
#define BAK_TAG ".bak"
NMConnection * parser_parse_ifcfg (const char *file, GError **error);
guint32 parser_parse_routes (const char *file, GError **err);
NMConnection *parse_ifcfg (const char *iface, NMDeviceType type);
gboolean parser_ignore_device (const char *iface);
guint32 parser_parse_routes (const char *filename);
#endif /* _PARSER_H_ */

View file

@ -34,6 +34,7 @@
#include "plugin.h"
#include "parser.h"
#include "nm-suse-connection.h"
#include "nm-system-config-interface.h"
#define IFCFG_PLUGIN_NAME "ifcfg-suse"
@ -52,14 +53,18 @@ G_DEFINE_TYPE_EXTENDED (SCPluginIfcfg, sc_plugin_ifcfg, G_TYPE_OBJECT, 0,
#define IFCFG_FILE_PATH_TAG "ifcfg-file-path"
typedef struct {
DBusGConnection *dbus_connection;
NMSystemConfigHalManager *hal_manager;
gboolean initialized;
GSList *connections;
GHashTable *connections;
GHashTable *unmanaged_devices;
GFileMonitor *monitor;
guint monitor_id;
guint32 default_gw;
GFileMonitor *default_gw_monitor;
guint default_gw_monitor_id;
} SCPluginIfcfgPrivate;
GQuark
ifcfg_plugin_error_quark (void)
{
@ -71,118 +76,74 @@ ifcfg_plugin_error_quark (void)
return error_quark;
}
struct FindInfo {
const char *path;
gboolean found;
};
static gboolean
is_ifcfg_file (const char *file)
{
return g_str_has_prefix (file, IFCFG_TAG) && strcmp (file, IFCFG_TAG "lo");
}
static NMConnection *
build_one_connection (const char *ifcfg_file)
{
NMConnection *connection;
GError *err = NULL;
PLUGIN_PRINT (PLUGIN_NAME, "parsing %s ... ", ifcfg_file);
connection = parser_parse_ifcfg (ifcfg_file, &err);
if (connection) {
NMSettingConnection *s_con;
s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION));
g_assert (s_con);
g_assert (s_con->id);
PLUGIN_PRINT (PLUGIN_NAME, " found connection '%s'", s_con->id);
} else
PLUGIN_PRINT (PLUGIN_NAME, " error: %s", err->message ? err->message : "(unknown)");
return connection;
}
typedef struct {
SCPluginIfcfg *plugin;
NMConnection *connection;
GFileMonitor *monitor;
guint monitor_id;
} ConnectionMonitor;
static void
connection_monitor_destroy (gpointer data)
update_one_connection (gpointer key, gpointer val, gpointer user_data)
{
ConnectionMonitor *monitor = (ConnectionMonitor *) data;
NMExportedConnection *exported = NM_EXPORTED_CONNECTION (val);
NMConnection *connection;
NMSettingIP4Config *ip4_config;
g_signal_handler_disconnect (monitor->monitor, monitor->monitor_id);
g_file_monitor_cancel (monitor->monitor);
g_object_unref (monitor->monitor);
connection = nm_exported_connection_get_connection (exported);
ip4_config = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (!ip4_config)
return;
g_free (monitor);
if (ip4_config->addresses) {
/* suse only has one address per device */
NMSettingIP4Address *ip4_address = (NMSettingIP4Address *) ip4_config->addresses->data;
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (user_data);
GHashTable *settings;
if (ip4_address->gateway != priv->default_gw) {
ip4_address->gateway = priv->default_gw;
settings = nm_connection_to_hash (connection);
nm_exported_connection_signal_updated (exported, settings);
g_hash_table_destroy (settings);
}
}
}
static void
connection_file_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
update_connections (SCPluginIfcfg *self)
{
ConnectionMonitor *cm = (ConnectionMonitor *) user_data;
gboolean remove_connection = FALSE;
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
g_hash_table_foreach (priv->connections, update_one_connection, self);
}
static void
routes_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
{
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
char *filename;
guint32 new_gw;
switch (event_type) {
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT: {
NMConnection *new_connection;
GHashTable *new_settings;
char *filename;
char *ifcfg_file;
/* In case anything goes wrong */
remove_connection = TRUE;
filename = g_file_get_basename (file);
ifcfg_file = g_build_filename (IFCFG_DIR, filename, NULL);
case G_FILE_MONITOR_EVENT_CHANGES_DONE_HINT:
case G_FILE_MONITOR_EVENT_DELETED:
filename = g_file_get_path (file);
new_gw = parser_parse_routes (filename);
g_free (filename);
new_connection = build_one_connection (ifcfg_file);
g_free (ifcfg_file);
if (new_connection) {
new_settings = nm_connection_to_hash (new_connection);
if (nm_connection_replace_settings (cm->connection, new_settings)) {
/* Nothing went wrong */
remove_connection = FALSE;
g_signal_emit_by_name (cm->plugin, "connection-updated", cm->connection);
}
g_object_unref (new_connection);
if (priv->default_gw != new_gw) {
priv->default_gw = new_gw;
update_connections (self);
}
break;
}
case G_FILE_MONITOR_EVENT_DELETED:
remove_connection = TRUE;
break;
default:
break;
}
if (remove_connection) {
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (cm->plugin);
priv->connections = g_slist_remove (priv->connections, cm->connection);
g_signal_emit_by_name (cm->plugin, "connection-removed", cm->connection);
g_object_unref (cm->connection);
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " removed connection");
}
}
static void
monitor_connection (NMSystemConfigInterface *config, NMConnection *connection, const char *filename)
monitor_routes (SCPluginIfcfg *self, const char *filename)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
GFile *file;
GFileMonitor *monitor;
@ -191,170 +152,190 @@ monitor_connection (NMSystemConfigInterface *config, NMConnection *connection, c
g_object_unref (file);
if (monitor) {
ConnectionMonitor *cm;
cm = g_new (ConnectionMonitor, 1);
cm->plugin = SC_PLUGIN_IFCFG (config);
cm->connection = connection;
cm->monitor = monitor;
cm->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (connection_file_changed), cm);
g_object_set_data_full (G_OBJECT (connection), "file-monitor", cm, connection_monitor_destroy);
priv->default_gw_monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (routes_changed), self);
priv->default_gw_monitor = monitor;
}
}
static void
add_one_connection (NMSystemConfigInterface *config, const char *filename, gboolean emit_added)
static char *
get_iface_by_udi (SCPluginIfcfg *self, const char *udi)
{
char *ifcfg_file;
NMConnection *connection;
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
DBusGProxy *proxy;
char *iface = NULL;
if (!is_ifcfg_file (filename))
return;
ifcfg_file = g_build_filename (IFCFG_DIR, filename, NULL);
connection = build_one_connection (ifcfg_file);
if (connection) {
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
proxy = dbus_g_proxy_new_for_name (priv->dbus_connection,
"org.freedesktop.Hal",
udi,
"org.freedesktop.Hal.Device");
monitor_connection (config, connection, ifcfg_file);
priv->connections = g_slist_append (priv->connections, connection);
dbus_g_proxy_call_with_timeout (proxy, "GetPropertyString", 10000, NULL,
G_TYPE_STRING, "net.interface", G_TYPE_INVALID,
G_TYPE_STRING, &iface, G_TYPE_INVALID);
g_object_unref (proxy);
if (emit_added)
g_signal_emit_by_name (config, "connection-added", connection);
}
g_free (ifcfg_file);
return iface;
}
static void
update_default_routes (NMSystemConfigInterface *config, gboolean emit_updated)
read_connection (SCPluginIfcfg *self, const char *udi, NMDeviceType dev_type)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
GSList *iter;
NMConnection *connection;
NMSettingIP4Config *ip4_setting;
gboolean got_manual = FALSE;
guint32 default_route;
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
char *iface;
/* First, make sure we have any non-DHCP connections */
for (iter = priv->connections; iter; iter = iter->next) {
connection = NM_CONNECTION (iter->data);
ip4_setting = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (ip4_setting && !strcmp (ip4_setting->method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
got_manual = TRUE;
break;
}
}
iface = get_iface_by_udi (self, udi);
if (iface) {
if (parser_ignore_device (iface)) {
g_hash_table_insert (priv->unmanaged_devices, g_strdup (udi), GINT_TO_POINTER (1));
g_signal_emit_by_name (self, "unmanaged-devices-changed");
} else {
NMSuseConnection *connection;
if (!got_manual)
return;
default_route = parser_parse_routes (IFCFG_DIR "/routes", NULL);
if (!default_route)
return;
for (iter = priv->connections; iter; iter = iter->next) {
connection = NM_CONNECTION (iter->data);
ip4_setting = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
if (ip4_setting && !strcmp (ip4_setting->method, NM_SETTING_IP4_CONFIG_METHOD_MANUAL)) {
GSList *address_iter;
for (address_iter = ip4_setting->addresses; address_iter; address_iter = address_iter->next) {
NMSettingIP4Address *addr = (NMSettingIP4Address *) address_iter->data;
addr->gateway = default_route;
if (emit_updated)
g_signal_emit_by_name (config, "connection-updated", connection);
connection = nm_suse_connection_new (iface, dev_type);
if (connection) {
g_hash_table_insert (priv->connections, g_strdup (udi), connection);
g_signal_emit_by_name (self, "connection-added", connection);
}
}
}
}
static GSList *
get_connections (NMSystemConfigInterface *config)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
if (!priv->initialized) {
GDir *dir;
const char *item;
GError *err = NULL;
dir = g_dir_open (IFCFG_DIR, 0, &err);
if (!dir) {
PLUGIN_WARN (PLUGIN_NAME, "couldn't access network directory '%s': %s.", IFCFG_DIR, err->message);
g_error_free (err);
return NULL;
}
while ((item = g_dir_read_name (dir)))
add_one_connection (config, item, FALSE);
g_dir_close (dir);
priv->initialized = TRUE;
}
if (!priv->connections)
/* No need to do any futher work, we have nothing. */
return priv->connections;
update_default_routes (config, FALSE);
return priv->connections;
g_free (iface);
}
static void
ifcfg_dir_changed (GFileMonitor *monitor,
GFile *file,
GFile *other_file,
GFileMonitorEvent event_type,
gpointer user_data)
read_connections_by_type (SCPluginIfcfg *self, NMDeviceType dev_type)
{
NMSystemConfigInterface *config = NM_SYSTEM_CONFIG_INTERFACE (user_data);
char *name;
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
GSList *list;
GSList *iter;
name = g_file_get_basename (file);
if (event_type == G_FILE_MONITOR_EVENT_CREATED) {
add_one_connection (config, name, TRUE);
list = nm_system_config_hal_manager_get_devices_of_type (priv->hal_manager, dev_type);
for (iter = list; iter; iter = iter->next) {
read_connection (self, (char *) iter->data, dev_type);
g_free (iter->data);
}
if (!strcmp (name, "routes"))
update_default_routes (config, TRUE);
g_slist_free (list);
}
g_free (name);
static void
device_added_cb (NMSystemConfigHalManager *hal_mgr,
const char *udi,
NMDeviceType dev_type,
gpointer user_data)
{
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data);
if (dev_type != DEVICE_TYPE_802_3_ETHERNET && dev_type != DEVICE_TYPE_802_11_WIRELESS)
return;
read_connection (self, udi, dev_type);
}
static void
device_removed_cb (NMSystemConfigHalManager *hal_mgr,
const char *udi,
NMDeviceType dev_type,
gpointer user_data)
{
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (user_data);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
NMExportedConnection *exported;
if (dev_type != DEVICE_TYPE_802_3_ETHERNET && dev_type != DEVICE_TYPE_802_11_WIRELESS)
return;
if (g_hash_table_remove (priv->unmanaged_devices, udi))
g_signal_emit_by_name (self, "unmanaged-devices-changed");
exported = (NMExportedConnection *) g_hash_table_lookup (priv->connections, udi);
if (exported) {
nm_exported_connection_signal_removed (exported);
g_hash_table_remove (priv->connections, udi);
}
}
static void
init (NMSystemConfigInterface *config, NMSystemConfigHalManager *hal_manager)
{
GFile *file;
GFileMonitor *monitor;
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (config);
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
file = g_file_new_for_path (IFCFG_DIR);
monitor = g_file_monitor_directory (file, G_FILE_MONITOR_NONE, NULL, NULL);
g_object_unref (file);
priv->hal_manager = g_object_ref (hal_manager);
if (monitor) {
priv->monitor_id = g_signal_connect (monitor, "changed", G_CALLBACK (ifcfg_dir_changed), config);
priv->monitor = monitor;
g_signal_connect (priv->hal_manager, "device-added", G_CALLBACK (device_added_cb), self);
g_signal_connect (priv->hal_manager, "device-removed", G_CALLBACK (device_removed_cb), self);
}
static void
get_connections_cb (gpointer key, gpointer val, gpointer user_data)
{
GSList **list = (GSList **) user_data;
*list = g_slist_prepend (*list, val);
}
static GSList *
get_connections (NMSystemConfigInterface *config)
{
SCPluginIfcfg *self = SC_PLUGIN_IFCFG (config);
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
GSList *list = NULL;
if (!priv->initialized) {
const char *filename;
read_connections_by_type (self, DEVICE_TYPE_802_3_ETHERNET);
read_connections_by_type (self, DEVICE_TYPE_802_11_WIRELESS);
filename = SYSCONFDIR"/sysconfig/network/routes";
monitor_routes (self, filename);
priv->default_gw = parser_parse_routes (filename);
if (priv->default_gw)
update_connections (self);
priv->initialized = TRUE;
}
g_hash_table_foreach (priv->connections, get_connections_cb, &list);
return list;
}
static void
release_one_connection (gpointer item, gpointer user_data)
get_unamanged_devices_cb (gpointer key, gpointer val, gpointer user_data)
{
NMConnection *connection = NM_CONNECTION (item);
SCPluginIfcfg *plugin = SC_PLUGIN_IFCFG (user_data);
GSList **list = (GSList **) key;
g_signal_emit_by_name (plugin, "connection-removed", connection);
g_object_unref (connection);
*list = g_slist_prepend (*list, g_strdup ((char *) val));
}
static GSList *
get_unmanaged_devices (NMSystemConfigInterface *config)
{
GSList *list = NULL;
g_hash_table_foreach (SC_PLUGIN_IFCFG_GET_PRIVATE (config)->unmanaged_devices,
get_unamanged_devices_cb, &list);
return list;
}
static void
sc_plugin_ifcfg_init (SCPluginIfcfg *plugin)
sc_plugin_ifcfg_init (SCPluginIfcfg *self)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (self);
GError *err = NULL;
priv->connections = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, g_object_unref);
priv->unmanaged_devices = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
priv->dbus_connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &err);
if (!priv->dbus_connection) {
PLUGIN_PRINT (IFCFG_PLUGIN_NAME, " dbus-glib error: %s",
err->message ? err->message : "(unknown)");
g_error_free (err);
}
}
static void
@ -362,18 +343,21 @@ dispose (GObject *object)
{
SCPluginIfcfgPrivate *priv = SC_PLUGIN_IFCFG_GET_PRIVATE (object);
if (priv->connections) {
g_slist_foreach (priv->connections, release_one_connection, object);
g_slist_free (priv->connections);
g_hash_table_destroy (priv->connections);
g_hash_table_destroy (priv->unmanaged_devices);
if (priv->default_gw_monitor) {
if (priv->default_gw_monitor_id)
g_signal_handler_disconnect (priv->default_gw_monitor, priv->default_gw_monitor_id);
g_file_monitor_cancel (priv->default_gw_monitor);
g_object_unref (priv->default_gw_monitor);
}
if (priv->monitor) {
if (priv->monitor_id)
g_signal_handler_disconnect (priv->monitor, priv->monitor_id);
if (priv->hal_manager)
g_object_unref (priv->hal_manager);
g_file_monitor_cancel (priv->monitor);
g_object_unref (priv->monitor);
}
dbus_g_connection_unref (priv->dbus_connection);
G_OBJECT_CLASS (sc_plugin_ifcfg_parent_class)->dispose (object);
}
@ -419,6 +403,7 @@ system_config_interface_init (NMSystemConfigInterface *system_config_interface_c
{
/* interface implementation */
system_config_interface_class->get_connections = get_connections;
system_config_interface_class->get_unmanaged_devices = get_unmanaged_devices;
system_config_interface_class->init = init;
}

View file

@ -17,7 +17,9 @@ nm_system_settings_SOURCES = \
nm-system-config-interface.h \
nm-system-config-hal-manager.c \
nm-system-config-hal-manager.h \
nm-system-config-hal-manager-private.h
nm-system-config-hal-manager-private.h \
sha1.c \
sha1.h
nm_system_settings_CPPFLAGS = \
$(DBUS_CFLAGS) \

View file

@ -363,13 +363,11 @@ nm_sysconfig_settings_add_connection (NMSysconfigSettings *self,
g_return_if_fail (NM_IS_SYSCONFIG_SETTINGS (self));
g_return_if_fail (NM_IS_EXPORTED_CONNECTION (connection));
if (g_hash_table_lookup (priv->connections, connection)) {
/* A plugin is lying to us */
g_message ("Connection is already added, ignoring");
if (g_hash_table_lookup (priv->connections, connection))
/* A plugin is lying to us. */
return;
}
g_hash_table_insert (priv->connections, connection, GINT_TO_POINTER (1));
g_hash_table_insert (priv->connections, g_object_ref (connection), GINT_TO_POINTER (1));
g_signal_connect (connection, "removed", G_CALLBACK (connection_removed), self);
nm_exported_connection_register_object (connection, NM_CONNECTION_SCOPE_SYSTEM, priv->g_connection);

View file

@ -130,8 +130,8 @@ load_plugins (Application *app, const char *plugins, GError **error)
plugin = g_module_open (path, G_MODULE_BIND_LOCAL);
if (!plugin) {
g_set_error (error, plugins_error_quark (), 0,
"Could not find plugin '%s' as %s!",
*pname, path);
"Could not load plugin '%s': %s",
*pname, g_module_error ());
g_free (full_name);
g_free (path);
break;

692
system-settings/src/sha1.c Normal file
View file

@ -0,0 +1,692 @@
/*
* SHA1 hash implementation and interface functions
* Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#include <stdlib.h>
#include <string.h>
#include "config.h"
#include "sha1.h"
/* Define types for stupid code. Userspace should
* be using u_*_t rather than kernel-space u* types.
*/
typedef u_int8_t u8;
typedef u_int16_t u16;
typedef u_int32_t u32;
typedef u_int64_t u64;
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len, u8 *mac);
void sha1_transform(u8 *state, const u8 data[64]);
void sha1_mac(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac)
{
const u8 *addr[3];
size_t len[3];
addr[0] = key;
len[0] = key_len;
addr[1] = data;
len[1] = data_len;
addr[2] = key;
len[2] = key_len;
sha1_vector(3, addr, len, mac);
}
/* HMAC code is based on RFC 2104 */
void hmac_sha1_vector(const u8 *key, size_t key_len, size_t num_elem,
const u8 *addr[], const size_t *len, u8 *mac)
{
unsigned char k_pad[64]; /* padding - key XORd with ipad/opad */
unsigned char tk[20];
const u8 *_addr[6];
size_t _len[6], i;
if (num_elem > 5) {
/*
* Fixed limit on the number of fragments to avoid having to
* allocate memory (which could fail).
*/
return;
}
/* if key is longer than 64 bytes reset it to key = SHA1(key) */
if (key_len > 64) {
sha1_vector(1, &key, &key_len, tk);
key = tk;
key_len = 20;
}
/* the HMAC_SHA1 transform looks like:
*
* SHA1(K XOR opad, SHA1(K XOR ipad, text))
*
* where K is an n byte key
* ipad is the byte 0x36 repeated 64 times
* opad is the byte 0x5c repeated 64 times
* and text is the data being protected */
/* start out by storing key in ipad */
memset(k_pad, 0, sizeof(k_pad));
memcpy(k_pad, key, key_len);
/* XOR key with ipad values */
for (i = 0; i < 64; i++)
k_pad[i] ^= 0x36;
/* perform inner SHA1 */
_addr[0] = k_pad;
_len[0] = 64;
for (i = 0; i < num_elem; i++) {
_addr[i + 1] = addr[i];
_len[i + 1] = len[i];
}
sha1_vector(1 + num_elem, _addr, _len, mac);
memset(k_pad, 0, sizeof(k_pad));
memcpy(k_pad, key, key_len);
/* XOR key with opad values */
for (i = 0; i < 64; i++)
k_pad[i] ^= 0x5c;
/* perform outer SHA1 */
_addr[0] = k_pad;
_len[0] = 64;
_addr[1] = mac;
_len[1] = SHA1_MAC_LEN;
sha1_vector(2, _addr, _len, mac);
}
void hmac_sha1(const u8 *key, size_t key_len, const u8 *data, size_t data_len,
u8 *mac)
{
hmac_sha1_vector(key, key_len, 1, &data, &data_len, mac);
}
void sha1_prf(const u8 *key, size_t key_len, const char *label,
const u8 *data, size_t data_len, u8 *buf, size_t buf_len)
{
u8 zero = 0, counter = 0;
size_t pos, plen;
u8 hash[SHA1_MAC_LEN];
size_t label_len = strlen(label);
const unsigned char *addr[4];
size_t len[4];
addr[0] = (u8 *) label;
len[0] = label_len;
addr[1] = &zero;
len[1] = 1;
addr[2] = data;
len[2] = data_len;
addr[3] = &counter;
len[3] = 1;
pos = 0;
while (pos < buf_len) {
plen = buf_len - pos;
if (plen >= SHA1_MAC_LEN) {
hmac_sha1_vector(key, key_len, 4, addr, len,
&buf[pos]);
pos += SHA1_MAC_LEN;
} else {
hmac_sha1_vector(key, key_len, 4, addr, len,
hash);
memcpy(&buf[pos], hash, plen);
break;
}
counter++;
}
}
static void pbkdf2_sha1_f(const char *passphrase, const char *ssid,
size_t ssid_len, int iterations, int count,
u8 *digest)
{
unsigned char tmp[SHA1_MAC_LEN], tmp2[SHA1_MAC_LEN];
int i, j;
unsigned char count_buf[4];
const u8 *addr[2];
size_t len[2];
size_t passphrase_len = strlen(passphrase);
addr[0] = (u8 *) ssid;
len[0] = ssid_len;
addr[1] = count_buf;
len[1] = 4;
/* F(P, S, c, i) = U1 xor U2 xor ... Uc
* U1 = PRF(P, S || i)
* U2 = PRF(P, U1)
* Uc = PRF(P, Uc-1)
*/
count_buf[0] = (count >> 24) & 0xff;
count_buf[1] = (count >> 16) & 0xff;
count_buf[2] = (count >> 8) & 0xff;
count_buf[3] = count & 0xff;
hmac_sha1_vector((u8 *) passphrase, passphrase_len, 2, addr, len, tmp);
memcpy(digest, tmp, SHA1_MAC_LEN);
for (i = 1; i < iterations; i++) {
hmac_sha1((u8 *) passphrase, passphrase_len, tmp, SHA1_MAC_LEN,
tmp2);
memcpy(tmp, tmp2, SHA1_MAC_LEN);
for (j = 0; j < SHA1_MAC_LEN; j++)
digest[j] ^= tmp2[j];
}
}
void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
int iterations, u8 *buf, size_t buflen)
{
int count = 0;
unsigned char *pos = buf;
size_t left = buflen;
size_t plen;
unsigned char digest[SHA1_MAC_LEN];
while (left > 0) {
count++;
pbkdf2_sha1_f(passphrase, ssid, ssid_len, iterations, count,
digest);
plen = left > SHA1_MAC_LEN ? SHA1_MAC_LEN : left;
memcpy(pos, digest, plen);
pos += plen;
left -= plen;
}
}
#ifndef EAP_TLS_FUNCS
typedef struct {
u32 state[5];
u32 count[2];
unsigned char buffer[64];
} SHA1_CTX;
static void SHA1Init(SHA1_CTX *context);
static void SHA1Update(SHA1_CTX *context, const void *data, u32 len);
static void SHA1Final(unsigned char digest[20], SHA1_CTX* context);
static void SHA1Transform(u32 state[5], const unsigned char buffer[64]);
/**
* sha1_vector - SHA-1 hash for data vector
* @num_elem: Number of elements in the data vector
* @addr: Pointers to the data areas
* @len: Lengths of the data blocks
* @mac: Buffer for the hash
*/
void sha1_vector(size_t num_elem, const u8 *addr[], const size_t *len,
u8 *mac)
{
SHA1_CTX ctx;
size_t i;
SHA1Init(&ctx);
for (i = 0; i < num_elem; i++)
SHA1Update(&ctx, addr[i], len[i]);
SHA1Final(mac, &ctx);
}
/**
* sha1_transform - Perform one SHA-1 transform step
* @state: SHA-1 state
* @data: Input data for the SHA-1 transform
*
* This function is used to implement random number generation specified in
* NIST FIPS Publication 186-2 for EAP-SIM. This PRF uses a function that is
* similar to SHA-1, but has different message padding and as such, access to
* just part of the SHA-1 is needed.
*/
void sha1_transform(u8 *state, const u8 data[64])
{
SHA1Transform((u32 *) state, data);
}
/* ===== start - public domain SHA1 implementation ===== */
/*
SHA-1 in C
By Steve Reid <sreid@sea-to-sky.net>
100% Public Domain
-----------------
Modified 7/98
By James H. Brown <jbrown@burgoyne.com>
Still 100% Public Domain
Corrected a problem which generated improper hash values on 16 bit machines
Routine SHA1Update changed from
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned int
len)
to
void SHA1Update(SHA1_CTX* context, unsigned char* data, unsigned
long len)
The 'len' parameter was declared an int which works fine on 32 bit machines.
However, on 16 bit machines an int is too small for the shifts being done
against
it. This caused the hash function to generate incorrect values if len was
greater than 8191 (8K - 1) due to the 'len << 3' on line 3 of SHA1Update().
Since the file IO in main() reads 16K at a time, any file 8K or larger would
be guaranteed to generate the wrong hash (e.g. Test Vector #3, a million
"a"s).
I also changed the declaration of variables i & j in SHA1Update to
unsigned long from unsigned int for the same reason.
These changes should make no difference to any 32 bit implementations since
an
int and a long are the same size in those environments.
--
I also corrected a few compiler warnings generated by Borland C.
1. Added #include <process.h> for exit() prototype
2. Removed unused variable 'j' in SHA1Final
3. Changed exit(0) to return(0) at end of main.
ALL changes I made can be located by searching for comments containing 'JHB'
-----------------
Modified 8/98
By Steve Reid <sreid@sea-to-sky.net>
Still 100% public domain
1- Removed #include <process.h> and used return() instead of exit()
2- Fixed overwriting of finalcount in SHA1Final() (discovered by Chris Hall)
3- Changed email address from steve@edmweb.com to sreid@sea-to-sky.net
-----------------
Modified 4/01
By Saul Kravitz <Saul.Kravitz@celera.com>
Still 100% PD
Modified to run on Compaq Alpha hardware.
-----------------
Modified 4/01
By Jouni Malinen <jkmaline@cc.hut.fi>
Minor changes to match the coding style used in Dynamics.
Modified September 24, 2004
By Jouni Malinen <jkmaline@cc.hut.fi>
Fixed alignment issue in SHA1Transform when SHA1HANDSOFF is defined.
*/
/*
Test Vectors (from FIPS PUB 180-1)
"abc"
A9993E36 4706816A BA3E2571 7850C26C 9CD0D89D
"abcdbcdecdefdefgefghfghighijhijkijkljklmklmnlmnomnopnopq"
84983E44 1C3BD26E BAAE4AA1 F95129E5 E54670F1
A million repetitions of "a"
34AA973C D4C4DAA4 F61EEB2B DBAD2731 6534016F
*/
#define SHA1HANDSOFF
#define rol(value, bits) (((value) << (bits)) | ((value) >> (32 - (bits))))
/* blk0() and blk() perform the initial expand. */
/* I got the idea of expanding during the round function from SSLeay */
#ifndef WORDS_BIGENDIAN
#define blk0(i) (block->l[i] = (rol(block->l[i], 24) & 0xFF00FF00) | \
(rol(block->l[i], 8) & 0x00FF00FF))
#else
#define blk0(i) block->l[i]
#endif
#define blk(i) (block->l[i & 15] = rol(block->l[(i + 13) & 15] ^ \
block->l[(i + 8) & 15] ^ block->l[(i + 2) & 15] ^ block->l[i & 15], 1))
/* (R0+R1), R2, R3, R4 are the different operations used in SHA1 */
#define R0(v,w,x,y,z,i) \
z += ((w & (x ^ y)) ^ y) + blk0(i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R1(v,w,x,y,z,i) \
z += ((w & (x ^ y)) ^ y) + blk(i) + 0x5A827999 + rol(v, 5); \
w = rol(w, 30);
#define R2(v,w,x,y,z,i) \
z += (w ^ x ^ y) + blk(i) + 0x6ED9EBA1 + rol(v, 5); w = rol(w, 30);
#define R3(v,w,x,y,z,i) \
z += (((w | x) & y) | (w & x)) + blk(i) + 0x8F1BBCDC + rol(v, 5); \
w = rol(w, 30);
#define R4(v,w,x,y,z,i) \
z += (w ^ x ^ y) + blk(i) + 0xCA62C1D6 + rol(v, 5); \
w=rol(w, 30);
#ifdef VERBOSE /* SAK */
void SHAPrintContext(SHA1_CTX *context, char *msg)
{
printf("%s (%d,%d) %x %x %x %x %x\n",
msg,
context->count[0], context->count[1],
context->state[0],
context->state[1],
context->state[2],
context->state[3],
context->state[4]);
}
#endif
/* Hash a single 512-bit block. This is the core of the algorithm. */
void SHA1Transform(u32 state[5], const unsigned char buffer[64])
{
u32 a, b, c, d, e;
typedef union {
unsigned char c[64];
u32 l[16];
} CHAR64LONG16;
CHAR64LONG16* block;
#ifdef SHA1HANDSOFF
u32 workspace[16];
block = (CHAR64LONG16 *) workspace;
memcpy(block, buffer, 64);
#else
block = (CHAR64LONG16 *) buffer;
#endif
/* Copy context->state[] to working vars */
a = state[0];
b = state[1];
c = state[2];
d = state[3];
e = state[4];
/* 4 rounds of 20 operations each. Loop unrolled. */
R0(a,b,c,d,e, 0); R0(e,a,b,c,d, 1); R0(d,e,a,b,c, 2); R0(c,d,e,a,b, 3);
R0(b,c,d,e,a, 4); R0(a,b,c,d,e, 5); R0(e,a,b,c,d, 6); R0(d,e,a,b,c, 7);
R0(c,d,e,a,b, 8); R0(b,c,d,e,a, 9); R0(a,b,c,d,e,10); R0(e,a,b,c,d,11);
R0(d,e,a,b,c,12); R0(c,d,e,a,b,13); R0(b,c,d,e,a,14); R0(a,b,c,d,e,15);
R1(e,a,b,c,d,16); R1(d,e,a,b,c,17); R1(c,d,e,a,b,18); R1(b,c,d,e,a,19);
R2(a,b,c,d,e,20); R2(e,a,b,c,d,21); R2(d,e,a,b,c,22); R2(c,d,e,a,b,23);
R2(b,c,d,e,a,24); R2(a,b,c,d,e,25); R2(e,a,b,c,d,26); R2(d,e,a,b,c,27);
R2(c,d,e,a,b,28); R2(b,c,d,e,a,29); R2(a,b,c,d,e,30); R2(e,a,b,c,d,31);
R2(d,e,a,b,c,32); R2(c,d,e,a,b,33); R2(b,c,d,e,a,34); R2(a,b,c,d,e,35);
R2(e,a,b,c,d,36); R2(d,e,a,b,c,37); R2(c,d,e,a,b,38); R2(b,c,d,e,a,39);
R3(a,b,c,d,e,40); R3(e,a,b,c,d,41); R3(d,e,a,b,c,42); R3(c,d,e,a,b,43);
R3(b,c,d,e,a,44); R3(a,b,c,d,e,45); R3(e,a,b,c,d,46); R3(d,e,a,b,c,47);
R3(c,d,e,a,b,48); R3(b,c,d,e,a,49); R3(a,b,c,d,e,50); R3(e,a,b,c,d,51);
R3(d,e,a,b,c,52); R3(c,d,e,a,b,53); R3(b,c,d,e,a,54); R3(a,b,c,d,e,55);
R3(e,a,b,c,d,56); R3(d,e,a,b,c,57); R3(c,d,e,a,b,58); R3(b,c,d,e,a,59);
R4(a,b,c,d,e,60); R4(e,a,b,c,d,61); R4(d,e,a,b,c,62); R4(c,d,e,a,b,63);
R4(b,c,d,e,a,64); R4(a,b,c,d,e,65); R4(e,a,b,c,d,66); R4(d,e,a,b,c,67);
R4(c,d,e,a,b,68); R4(b,c,d,e,a,69); R4(a,b,c,d,e,70); R4(e,a,b,c,d,71);
R4(d,e,a,b,c,72); R4(c,d,e,a,b,73); R4(b,c,d,e,a,74); R4(a,b,c,d,e,75);
R4(e,a,b,c,d,76); R4(d,e,a,b,c,77); R4(c,d,e,a,b,78); R4(b,c,d,e,a,79);
/* Add the working vars back into context.state[] */
state[0] += a;
state[1] += b;
state[2] += c;
state[3] += d;
state[4] += e;
/* Wipe variables */
a = b = c = d = e = 0;
#ifdef SHA1HANDSOFF
memset(block, 0, 64);
#endif
}
/* SHA1Init - Initialize new context */
static void SHA1Init(SHA1_CTX* context)
{
/* SHA1 initialization constants */
context->state[0] = 0x67452301;
context->state[1] = 0xEFCDAB89;
context->state[2] = 0x98BADCFE;
context->state[3] = 0x10325476;
context->state[4] = 0xC3D2E1F0;
context->count[0] = context->count[1] = 0;
}
/* Run your data through this. */
static void SHA1Update(SHA1_CTX* context, const void *_data, u32 len)
{
u32 i, j;
const unsigned char *data = _data;
#ifdef VERBOSE
SHAPrintContext(context, "before");
#endif
j = (context->count[0] >> 3) & 63;
if ((context->count[0] += len << 3) < (len << 3))
context->count[1]++;
context->count[1] += (len >> 29);
if ((j + len) > 63) {
memcpy(&context->buffer[j], data, (i = 64-j));
SHA1Transform(context->state, context->buffer);
for ( ; i + 63 < len; i += 64) {
SHA1Transform(context->state, &data[i]);
}
j = 0;
}
else i = 0;
memcpy(&context->buffer[j], &data[i], len - i);
#ifdef VERBOSE
SHAPrintContext(context, "after ");
#endif
}
/* Add padding and return the message digest. */
static void SHA1Final(unsigned char digest[20], SHA1_CTX* context)
{
u32 i;
unsigned char finalcount[8];
for (i = 0; i < 8; i++) {
finalcount[i] = (unsigned char)
((context->count[(i >= 4 ? 0 : 1)] >>
((3-(i & 3)) * 8) ) & 255); /* Endian independent */
}
SHA1Update(context, (unsigned char *) "\200", 1);
while ((context->count[0] & 504) != 448) {
SHA1Update(context, (unsigned char *) "\0", 1);
}
SHA1Update(context, finalcount, 8); /* Should cause a SHA1Transform()
*/
for (i = 0; i < 20; i++) {
digest[i] = (unsigned char)
((context->state[i >> 2] >> ((3 - (i & 3)) * 8)) &
255);
}
/* Wipe variables */
i = 0;
memset(context->buffer, 0, 64);
memset(context->state, 0, 20);
memset(context->count, 0, 8);
memset(finalcount, 0, 8);
}
/* ===== end - public domain SHA1 implementation ===== */
#endif /* EAP_TLS_FUNCS */
#ifdef TEST_MAIN
static u8 key0[] =
{
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b,
0x0b, 0x0b, 0x0b, 0x0b
};
static u8 data0[] = "Hi There";
static u8 prf0[] =
{
0xbc, 0xd4, 0xc6, 0x50, 0xb3, 0x0b, 0x96, 0x84,
0x95, 0x18, 0x29, 0xe0, 0xd7, 0x5f, 0x9d, 0x54,
0xb8, 0x62, 0x17, 0x5e, 0xd9, 0xf0, 0x06, 0x06,
0xe1, 0x7d, 0x8d, 0xa3, 0x54, 0x02, 0xff, 0xee,
0x75, 0xdf, 0x78, 0xc3, 0xd3, 0x1e, 0x0f, 0x88,
0x9f, 0x01, 0x21, 0x20, 0xc0, 0x86, 0x2b, 0xeb,
0x67, 0x75, 0x3e, 0x74, 0x39, 0xae, 0x24, 0x2e,
0xdb, 0x83, 0x73, 0x69, 0x83, 0x56, 0xcf, 0x5a
};
static u8 key1[] = "Jefe";
static u8 data1[] = "what do ya want for nothing?";
static u8 prf1[] =
{
0x51, 0xf4, 0xde, 0x5b, 0x33, 0xf2, 0x49, 0xad,
0xf8, 0x1a, 0xeb, 0x71, 0x3a, 0x3c, 0x20, 0xf4,
0xfe, 0x63, 0x14, 0x46, 0xfa, 0xbd, 0xfa, 0x58,
0x24, 0x47, 0x59, 0xae, 0x58, 0xef, 0x90, 0x09,
0xa9, 0x9a, 0xbf, 0x4e, 0xac, 0x2c, 0xa5, 0xfa,
0x87, 0xe6, 0x92, 0xc4, 0x40, 0xeb, 0x40, 0x02,
0x3e, 0x7b, 0xab, 0xb2, 0x06, 0xd6, 0x1d, 0xe7,
0xb9, 0x2f, 0x41, 0x52, 0x90, 0x92, 0xb8, 0xfc
};
static u8 key2[] =
{
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa,
0xaa, 0xaa, 0xaa, 0xaa
};
static u8 data2[] =
{
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd,
0xdd, 0xdd
};
static u8 prf2[] =
{
0xe1, 0xac, 0x54, 0x6e, 0xc4, 0xcb, 0x63, 0x6f,
0x99, 0x76, 0x48, 0x7b, 0xe5, 0xc8, 0x6b, 0xe1,
0x7a, 0x02, 0x52, 0xca, 0x5d, 0x8d, 0x8d, 0xf1,
0x2c, 0xfb, 0x04, 0x73, 0x52, 0x52, 0x49, 0xce,
0x9d, 0xd8, 0xd1, 0x77, 0xea, 0xd7, 0x10, 0xbc,
0x9b, 0x59, 0x05, 0x47, 0x23, 0x91, 0x07, 0xae,
0xf7, 0xb4, 0xab, 0xd4, 0x3d, 0x87, 0xf0, 0xa6,
0x8f, 0x1c, 0xbd, 0x9e, 0x2b, 0x6f, 0x76, 0x07
};
struct passphrase_test {
char *passphrase;
char *ssid;
char psk[32];
};
static struct passphrase_test passphrase_tests[] =
{
{
"password",
"IEEE",
{
0xf4, 0x2c, 0x6f, 0xc5, 0x2d, 0xf0, 0xeb, 0xef,
0x9e, 0xbb, 0x4b, 0x90, 0xb3, 0x8a, 0x5f, 0x90,
0x2e, 0x83, 0xfe, 0x1b, 0x13, 0x5a, 0x70, 0xe2,
0x3a, 0xed, 0x76, 0x2e, 0x97, 0x10, 0xa1, 0x2e
}
},
{
"ThisIsAPassword",
"ThisIsASSID",
{
0x0d, 0xc0, 0xd6, 0xeb, 0x90, 0x55, 0x5e, 0xd6,
0x41, 0x97, 0x56, 0xb9, 0xa1, 0x5e, 0xc3, 0xe3,
0x20, 0x9b, 0x63, 0xdf, 0x70, 0x7d, 0xd5, 0x08,
0xd1, 0x45, 0x81, 0xf8, 0x98, 0x27, 0x21, 0xaf
}
},
{
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa",
"ZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ",
{
0xbe, 0xcb, 0x93, 0x86, 0x6b, 0xb8, 0xc3, 0x83,
0x2c, 0xb7, 0x77, 0xc2, 0xf5, 0x59, 0x80, 0x7c,
0x8c, 0x59, 0xaf, 0xcb, 0x6e, 0xae, 0x73, 0x48,
0x85, 0x00, 0x13, 0x00, 0xa9, 0x81, 0xcc, 0x62
}
},
};
#define NUM_PASSPHRASE_TESTS \
(sizeof(passphrase_tests) / sizeof(passphrase_tests[0]))
int main(int argc, char *argv[])
{
u8 res[512];
int ret = 0, i;
printf("PRF-SHA1 test cases:\n");
sha1_prf(key0, sizeof(key0), "prefix", data0, sizeof(data0) - 1,
res, sizeof(prf0));
if (memcmp(res, prf0, sizeof(prf0)) == 0)
printf("Test case 0 - OK\n");
else {
printf("Test case 0 - FAILED!\n");
ret++;
}
sha1_prf(key1, sizeof(key1) - 1, "prefix", data1, sizeof(data1) - 1,
res, sizeof(prf1));
if (memcmp(res, prf1, sizeof(prf1)) == 0)
printf("Test case 1 - OK\n");
else {
printf("Test case 1 - FAILED!\n");
ret++;
}
sha1_prf(key2, sizeof(key2), "prefix", data2, sizeof(data2),
res, sizeof(prf2));
if (memcmp(res, prf2, sizeof(prf2)) == 0)
printf("Test case 2 - OK\n");
else {
printf("Test case 2 - FAILED!\n");
ret++;
}
ret += test_eap_fast();
printf("PBKDF2-SHA1 Passphrase test cases:\n");
for (i = 0; i < NUM_PASSPHRASE_TESTS; i++) {
u8 psk[32];
struct passphrase_test *test = &passphrase_tests[i];
pbkdf2_sha1(test->passphrase,
test->ssid, strlen(test->ssid),
4096, psk, 32);
if (memcmp(psk, test->psk, 32) == 0)
printf("Test case %d - OK\n", i);
else {
printf("Test case %d - FAILED!\n", i);
ret++;
}
}
return ret;
}
#endif /* TEST_MAIN */

View file

@ -0,0 +1,34 @@
/*
* SHA1 hash implementation and interface functions
* Copyright (c) 2003-2005, Jouni Malinen <jkmaline@cc.hut.fi>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*
* Alternatively, this software may be distributed under the terms of BSD
* license.
*
* See README and COPYING for more details.
*/
#ifndef SHA1_H
#define SHA1_H
#include <sys/types.h>
#define SHA1_MAC_LEN 20
void sha1_mac(const u_int8_t *key, size_t key_len, const u_int8_t *data, size_t data_len,
u_int8_t *mac);
void hmac_sha1_vector(const u_int8_t *key, size_t key_len, size_t num_elem,
const u_int8_t *addr[], const size_t *len, u_int8_t *mac);
void hmac_sha1(const u_int8_t *key, size_t key_len, const u_int8_t *data, size_t data_len,
u_int8_t *mac);
void sha1_prf(const u_int8_t *key, size_t key_len, const char *label,
const u_int8_t *data, size_t data_len, u_int8_t *buf, size_t buf_len);
void pbkdf2_sha1(const char *passphrase, const char *ssid, size_t ssid_len,
int iterations, u_int8_t *buf, size_t buflen);
#endif /* SHA1_H */