mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-25 15:20:08 +01:00
Merge commit 'origin/master' into btdun
This commit is contained in:
commit
c6bf930b1f
31 changed files with 1898 additions and 1241 deletions
|
|
@ -1,6 +1,6 @@
|
|||
AC_PREREQ(2.52)
|
||||
|
||||
AC_INIT(NetworkManager, 0.7.996, dcbw@redhat.com, NetworkManager)
|
||||
AC_INIT(NetworkManager, 0.7.997, dcbw@redhat.com, NetworkManager)
|
||||
AM_INIT_AUTOMAKE([1.9 subdir-objects tar-ustar no-dist-gzip dist-bzip2])
|
||||
AM_MAINTAINER_MODE
|
||||
|
||||
|
|
|
|||
|
|
@ -1576,7 +1576,7 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *self,
|
|||
if (!value)
|
||||
return TRUE;
|
||||
|
||||
/* First verify private key password */
|
||||
/* Verify the key and the private key password */
|
||||
data = crypto_get_private_key (value,
|
||||
password,
|
||||
&key_type,
|
||||
|
|
@ -1591,77 +1591,69 @@ nm_setting_802_1x_set_private_key (NMSetting8021x *self,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
memset (data->data, 0, data->len);
|
||||
g_byte_array_free (data, TRUE);
|
||||
|
||||
/* Regular file verification */
|
||||
format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||
data = crypto_load_and_verify_certificate (value, &format, error);
|
||||
if (data) {
|
||||
/* wpa_supplicant can only use raw x509 CA certs */
|
||||
switch (format) {
|
||||
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_X509:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_PKCS12:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
|
||||
break;
|
||||
default:
|
||||
g_byte_array_free (data, TRUE);
|
||||
data = NULL;
|
||||
g_set_error (error,
|
||||
NM_SETTING_802_1X_ERROR,
|
||||
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
|
||||
NM_SETTING_802_1X_PRIVATE_KEY);
|
||||
break;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
priv->private_key = data;
|
||||
|
||||
/* Always update the private key for blob + pkcs12 since the
|
||||
* pkcs12 files are encrypted
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12)
|
||||
priv->private_key_password = g_strdup (password);
|
||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
/* Add the path scheme tag to the front, then the fielname */
|
||||
priv->private_key = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1);
|
||||
g_byte_array_append (priv->private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
||||
g_byte_array_append (priv->private_key, (const guint8 *) value, strlen (value));
|
||||
g_byte_array_append (priv->private_key, (const guint8 *) "\0", 1);
|
||||
|
||||
/* Always update the private key with paths since the key the
|
||||
* cert refers to is encrypted.
|
||||
*/
|
||||
priv->private_key_password = g_strdup (password);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
|
||||
/* As required by NM and wpa_supplicant, set the client-cert
|
||||
* property to the same PKCS#12 data.
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
|
||||
if (priv->client_cert)
|
||||
g_byte_array_free (priv->client_cert, TRUE);
|
||||
|
||||
priv->client_cert = g_byte_array_sized_new (priv->private_key->len);
|
||||
g_byte_array_append (priv->client_cert, priv->private_key->data, priv->private_key->len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* As a special case for private keys, even if the decrypt fails,
|
||||
* return the key's file type.
|
||||
*/
|
||||
if (out_format && crypto_is_pkcs12_file (value, NULL))
|
||||
switch (format) {
|
||||
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_X509:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_PKCS12:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
|
||||
break;
|
||||
default:
|
||||
memset (data->data, 0, data->len);
|
||||
g_byte_array_free (data, TRUE);
|
||||
g_set_error (error,
|
||||
NM_SETTING_802_1X_ERROR,
|
||||
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
|
||||
NM_SETTING_802_1X_PRIVATE_KEY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (data);
|
||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
priv->private_key = data;
|
||||
data = NULL;
|
||||
|
||||
/* Always update the private key for blob + pkcs12 since the
|
||||
* pkcs12 files are encrypted
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12)
|
||||
priv->private_key_password = g_strdup (password);
|
||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
/* Add the path scheme tag to the front, then the fielname */
|
||||
priv->private_key = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1);
|
||||
g_byte_array_append (priv->private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
||||
g_byte_array_append (priv->private_key, (const guint8 *) value, strlen (value));
|
||||
g_byte_array_append (priv->private_key, (const guint8 *) "\0", 1);
|
||||
|
||||
/* Always update the private key with paths since the key the
|
||||
* cert refers to is encrypted.
|
||||
*/
|
||||
priv->private_key_password = g_strdup (password);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
|
||||
/* Clear and free private key data if it's no longer needed */
|
||||
if (data) {
|
||||
memset (data->data, 0, data->len);
|
||||
g_byte_array_free (data, TRUE);
|
||||
}
|
||||
|
||||
/* As required by NM and wpa_supplicant, set the client-cert
|
||||
* property to the same PKCS#12 data.
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
|
||||
if (priv->client_cert)
|
||||
g_byte_array_free (priv->client_cert, TRUE);
|
||||
|
||||
priv->client_cert = g_byte_array_sized_new (priv->private_key->len);
|
||||
g_byte_array_append (priv->client_cert, priv->private_key->data, priv->private_key->len);
|
||||
}
|
||||
|
||||
return priv->private_key != NULL;
|
||||
|
|
@ -1956,7 +1948,7 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
|
|||
if (!value)
|
||||
return TRUE;
|
||||
|
||||
/* First verify private key password */
|
||||
/* Verify the key and the private key password */
|
||||
data = crypto_get_private_key (value,
|
||||
password,
|
||||
&key_type,
|
||||
|
|
@ -1971,76 +1963,69 @@ nm_setting_802_1x_set_phase2_private_key (NMSetting8021x *self,
|
|||
|
||||
return FALSE;
|
||||
}
|
||||
memset (data->data, 0, data->len);
|
||||
g_byte_array_free (data, TRUE);
|
||||
|
||||
format = NM_CRYPTO_FILE_FORMAT_UNKNOWN;
|
||||
data = crypto_load_and_verify_certificate (value, &format, error);
|
||||
if (data) {
|
||||
/* wpa_supplicant can only use raw x509 CA certs */
|
||||
switch (format) {
|
||||
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_X509:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_PKCS12:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
|
||||
break;
|
||||
default:
|
||||
g_byte_array_free (data, TRUE);
|
||||
data = NULL;
|
||||
g_set_error (error,
|
||||
NM_SETTING_802_1X_ERROR,
|
||||
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
|
||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
|
||||
break;
|
||||
}
|
||||
|
||||
if (data) {
|
||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
priv->phase2_private_key = data;
|
||||
|
||||
/* Always update the private key for blob + pkcs12 since the
|
||||
* pkcs12 files are encrypted
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12)
|
||||
priv->phase2_private_key_password = g_strdup (password);
|
||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
/* Add the path scheme tag to the front, then the fielname */
|
||||
priv->phase2_private_key = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1);
|
||||
g_byte_array_append (priv->phase2_private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
||||
g_byte_array_append (priv->phase2_private_key, (const guint8 *) value, strlen (value));
|
||||
g_byte_array_append (priv->phase2_private_key, (const guint8 *) "\0", 1);
|
||||
|
||||
/* Always update the private key with paths since the key the
|
||||
* cert refers to is encrypted.
|
||||
*/
|
||||
priv->phase2_private_key_password = g_strdup (password);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
|
||||
/* As required by NM and wpa_supplicant, set the client-cert
|
||||
* property to the same PKCS#12 data.
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
|
||||
if (priv->phase2_client_cert)
|
||||
g_byte_array_free (priv->phase2_client_cert, TRUE);
|
||||
|
||||
priv->phase2_client_cert = g_byte_array_sized_new (priv->phase2_private_key->len);
|
||||
g_byte_array_append (priv->phase2_client_cert, priv->phase2_private_key->data, priv->phase2_private_key->len);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
/* As a special case for private keys, even if the decrypt fails,
|
||||
* return the key's file type.
|
||||
*/
|
||||
if (out_format && crypto_is_pkcs12_file (value, NULL))
|
||||
switch (format) {
|
||||
case NM_CRYPTO_FILE_FORMAT_RAW_KEY:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_RAW_KEY;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_X509:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_X509;
|
||||
break;
|
||||
case NM_CRYPTO_FILE_FORMAT_PKCS12:
|
||||
if (out_format)
|
||||
*out_format = NM_SETTING_802_1X_CK_FORMAT_PKCS12;
|
||||
break;
|
||||
default:
|
||||
memset (data->data, 0, data->len);
|
||||
g_byte_array_free (data, TRUE);
|
||||
g_set_error (error,
|
||||
NM_SETTING_802_1X_ERROR,
|
||||
NM_SETTING_802_1X_ERROR_INVALID_PROPERTY,
|
||||
NM_SETTING_802_1X_PHASE2_PRIVATE_KEY);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
g_assert (data);
|
||||
if (scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB) {
|
||||
priv->phase2_private_key = data;
|
||||
data = NULL;
|
||||
|
||||
/* Always update the private key for blob + pkcs12 since the
|
||||
* pkcs12 files are encrypted
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12)
|
||||
priv->phase2_private_key_password = g_strdup (password);
|
||||
} else if (scheme == NM_SETTING_802_1X_CK_SCHEME_PATH) {
|
||||
/* Add the path scheme tag to the front, then the fielname */
|
||||
priv->phase2_private_key = g_byte_array_sized_new (strlen (value) + strlen (SCHEME_PATH) + 1);
|
||||
g_byte_array_append (priv->phase2_private_key, (const guint8 *) SCHEME_PATH, strlen (SCHEME_PATH));
|
||||
g_byte_array_append (priv->phase2_private_key, (const guint8 *) value, strlen (value));
|
||||
g_byte_array_append (priv->phase2_private_key, (const guint8 *) "\0", 1);
|
||||
|
||||
/* Always update the private key with paths since the key the
|
||||
* cert refers to is encrypted.
|
||||
*/
|
||||
priv->phase2_private_key_password = g_strdup (password);
|
||||
} else
|
||||
g_assert_not_reached ();
|
||||
|
||||
/* Clear and free private key data if it's no longer needed */
|
||||
if (data) {
|
||||
memset (data->data, 0, data->len);
|
||||
g_byte_array_free (data, TRUE);
|
||||
}
|
||||
|
||||
/* As required by NM and wpa_supplicant, set the client-cert
|
||||
* property to the same PKCS#12 data.
|
||||
*/
|
||||
if (format == NM_CRYPTO_FILE_FORMAT_PKCS12) {
|
||||
if (priv->phase2_client_cert)
|
||||
g_byte_array_free (priv->phase2_client_cert, TRUE);
|
||||
|
||||
priv->phase2_client_cert = g_byte_array_sized_new (priv->phase2_private_key->len);
|
||||
g_byte_array_append (priv->phase2_client_cert, priv->phase2_private_key->data, priv->phase2_private_key->len);
|
||||
}
|
||||
|
||||
return priv->phase2_private_key != NULL;
|
||||
|
|
|
|||
|
|
@ -8,7 +8,8 @@ noinst_PROGRAMS = \
|
|||
test-settings-defaults \
|
||||
test-crypto \
|
||||
test-need-secrets \
|
||||
test-general
|
||||
test-general \
|
||||
test-setting-8021x
|
||||
|
||||
test_settings_defaults_SOURCES = \
|
||||
test-settings-defaults.c
|
||||
|
|
@ -58,6 +59,18 @@ test_general_LDADD = \
|
|||
$(GLIB_LIBS) \
|
||||
$(DBUS_LIBS)
|
||||
|
||||
test_setting_8021x_SOURCES = \
|
||||
test-setting-8021x.c
|
||||
|
||||
test_setting_8021x_CPPFLAGS = \
|
||||
$(GLIB_CFLAGS) \
|
||||
$(DBUS_CFLAGS)
|
||||
|
||||
test_setting_8021x_LDADD = \
|
||||
$(top_builddir)/libnm-util/libnm-util.la \
|
||||
$(GLIB_LIBS) \
|
||||
$(DBUS_LIBS)
|
||||
|
||||
if WITH_TESTS
|
||||
|
||||
check-local: test-settings-defaults test-crypto test-need-secrets
|
||||
|
|
@ -65,6 +78,23 @@ check-local: test-settings-defaults test-crypto test-need-secrets
|
|||
$(abs_builddir)/test-need-secrets
|
||||
$(abs_builddir)/test-general
|
||||
|
||||
# Private key and CA certificate in the same file (PEM)
|
||||
$(abs_builddir)/test-setting-8021x \
|
||||
$(top_srcdir)/libnm-util/tests/certs/test_key_and_cert.pem \
|
||||
"test" \
|
||||
$(top_srcdir)/libnm-util/tests/certs/test-key-only-decrypted.der
|
||||
|
||||
# Private key by itself (PEM)
|
||||
$(abs_builddir)/test-setting-8021x \
|
||||
$(top_srcdir)/libnm-util/tests/certs/test-key-only.pem \
|
||||
"test" \
|
||||
$(top_srcdir)/libnm-util/tests/certs/test-key-only-decrypted.der
|
||||
|
||||
# Private key and CA certificate in the same file (pkcs12)
|
||||
$(abs_builddir)/test-setting-8021x \
|
||||
$(top_srcdir)/libnm-util/tests/certs/test-cert.p12 \
|
||||
"test"
|
||||
|
||||
# Normal CA certificate
|
||||
$(abs_builddir)/test-crypto --cert \
|
||||
$(top_srcdir)/libnm-util/tests/certs/test_ca_cert.pem
|
||||
|
|
|
|||
|
|
@ -14,5 +14,7 @@ EXTRA_DIST = \
|
|||
test2_ca_cert.pem \
|
||||
test2_key_and_cert.pem \
|
||||
test2-cert.p12 \
|
||||
ca-no-ending-newline.pem
|
||||
ca-no-ending-newline.pem \
|
||||
test-key-only.pem \
|
||||
test-key-only-decrypted.der
|
||||
|
||||
|
|
|
|||
BIN
libnm-util/tests/certs/test-key-only-decrypted.der
Normal file
BIN
libnm-util/tests/certs/test-key-only-decrypted.der
Normal file
Binary file not shown.
92
libnm-util/tests/certs/test-key-only.pem
Normal file
92
libnm-util/tests/certs/test-key-only.pem
Normal file
|
|
@ -0,0 +1,92 @@
|
|||
-----BEGIN RSA PRIVATE KEY-----
|
||||
Proc-Type: 4,ENCRYPTED
|
||||
DEK-Info: DES-EDE3-CBC,B29FCA6ECB7C0C48
|
||||
|
||||
KuRV4sEVQkY0r0E+E81Se2qpm54HeboUMIJcMVqAt/HIeYwpjEzmXHUywXgayA5k
|
||||
r5Uvru95vymFz80q/rl6i4Mt3ckEQ3/VHmBI4pPj/JeRbiDhqTyLqpB5zMgbuti+
|
||||
PsEemlbiaCMZFdJk8rJBWADTkirGbXs5ciLwTJyrJXhkBVTqoHtphSWMELxcrnQj
|
||||
5bAXZ+rnApWA7LR3yCY1UE0Nj39Yu8lkzDJtbsSXPJVO//OQiGuQRcY6roAUzeS/
|
||||
amLdIYqoZm3OF83Ro88XZCIDCG6XjgKoqojtekClVIytB6mHWk+IHhI7DgU/pDBj
|
||||
yOskzVRMja9ECnqaVX+bmlmJGZBgcd7+XiebCXNY9IAx/ZQDMbDJDoJusvH6npJR
|
||||
PBgag8QBSzwpFyEP/1LrlyVyggZcGuXDWfUiM2rt2UvLm8QYeT5WGfUI+QwW6JRV
|
||||
xEz2QwRiPsmj0uK2fXLKHbY0Pv79IMLqgesCAUbndWsi94kjAhpJGa/WfKVb8Dpg
|
||||
T+mVa2OT0pgewPWJ3h5f47ag27WDJthsIUHAvNZ03uM23DIqDh6o03/B3/4r1Uab
|
||||
HzsLWhUOzbLihO08qcPk/JqtDVCv579mpgvy7bL2ZsZUzefnmg+ah+1bhLguryZu
|
||||
Zrt1hTu5WTz27UbYwWNtkxWnWcM9sSF9y+KVwumYhIUGTvg3Jds/jmp/Z5ad8tev
|
||||
0RQuWmqnXVD51Y92tOXobJH7JwGbQ4GeRNG/UX7DS9Lvb6rPgmmxvGbXMcjEMapB
|
||||
m5DLjCD7Lz4++sfzhCic3/nL8e8fjoYZmCbL/SpYjGjTrfoNaGYaT0De8MxCSjPf
|
||||
rNT+ldWFD0oAOTmT0uqOFkeIx3vxczSQUyRfzGOLqtb9mAXk8lvdb8Myb5atfe8f
|
||||
FNBL5ocz6Szv2AmKmjZE5P6NKSllyryCYl+H2QU0e3OyY8S9aG2aG8fqeVKaA01S
|
||||
uOOjsK6IKMpkit+VFDP7RWvS8p1FTwTVRdbMZzASW8+D98OHsTlOENtQuuFyvNaN
|
||||
vPHrbHltTkwDlYVab9UpFr/ZRW3cNJrmcl0hyeCJxk5u8B9UwW6yZmd24hxda2xt
|
||||
1QjnxfWlX0i5KTmfWFyPmRYt1WH9rdVaH6wqRbGNbMRT7Lez0E/2+LXjFiiEe0Vh
|
||||
ZuryhyhUXpHY8yyHxFY92XT504Z3wPUaJ1tQxGhdziZ7HcqFT8f4oTNJdBNtzqNw
|
||||
l63gSTaKUkSB14CBOyR84cqpgSMwZvWZb3RQFYY4GSALWwhnn6PWeRhjWAXPms2v
|
||||
tRmfEyDUCyPxDarezvS9kUir3XbvnCkoJOrK/lw4a8ygGBCBqRKOdI0SRUf1Nnjm
|
||||
aZBrKrXHv5vP66fyC7cGMTq35+iiHbE//rRDGPrf9vpmw3ki3FlDMyAXOC5yWDco
|
||||
0n+cNDyHJDdIW3+3nfZvSgPPMwmTdfNO90X3YczSmMTGjnIuhQMf7FMFmMZOSrqD
|
||||
u234vYCjIIlph3aVpbzjOqKg3d4nuP9oouyAgRAr+vShgHRmq0jvsAiGH3Q6RqEj
|
||||
DvkM1NgoloMy5RhKF4hIeaQM/UlgoXrcEx0RGCJHykQcQmVa5cf5EwjrO7b+w2Lg
|
||||
-----END RSA PRIVATE KEY-----
|
||||
Certificate:
|
||||
Data:
|
||||
Version: 3 (0x2)
|
||||
Serial Number: 1 (0x1)
|
||||
Signature Algorithm: md5WithRSAEncryption
|
||||
Issuer: C=US, ST=Berkshire, L=Newbury, O=My Company Ltd, OU=test, CN=test/emailAddress=test@test.com
|
||||
Validity
|
||||
Not Before: Feb 2 02:22:25 2009 GMT
|
||||
Not After : Jan 31 02:22:25 2019 GMT
|
||||
Subject: C=US, ST=Berkshire, O=My Company Ltd, OU=test-client, CN=test-client/emailAddress=test-client@test.com
|
||||
Subject Public Key Info:
|
||||
Public Key Algorithm: rsaEncryption
|
||||
RSA Public Key: (2048 bit)
|
||||
Modulus (2048 bit):
|
||||
00:ce:d2:e9:fb:f4:a4:ce:66:87:cc:8b:2d:d2:c3:
|
||||
b8:fa:be:ea:53:08:95:9e:27:4a:04:78:31:a1:36:
|
||||
d2:e5:42:f5:76:f7:24:71:b8:d3:10:fd:b7:57:86:
|
||||
68:29:02:1b:e9:93:2b:af:c0:7e:3d:58:16:34:10:
|
||||
25:85:7e:28:2d:42:fc:34:7f:d6:4f:0a:e7:b6:b9:
|
||||
40:51:c8:e5:89:60:cd:73:51:63:67:e1:59:36:31:
|
||||
5e:d0:87:4b:5d:97:8a:42:22:d3:42:f2:83:62:79:
|
||||
84:45:5b:d8:20:97:e2:d1:34:23:5e:ec:bf:8a:41:
|
||||
7c:ad:80:50:f3:9b:1c:51:5d:e4:29:1c:c1:c6:7c:
|
||||
a1:00:70:0f:f6:79:77:03:22:f5:4b:ab:76:ca:20:
|
||||
ab:e1:4e:53:6c:86:68:e9:d6:0f:6e:95:4b:b5:b5:
|
||||
cf:d3:6c:d4:73:db:c0:3d:1d:20:20:72:ab:3e:25:
|
||||
bb:3f:cd:5f:2d:77:fd:d7:0b:a8:eb:0c:73:c0:3f:
|
||||
74:27:17:56:cf:31:9a:a9:ed:c1:39:27:c7:aa:e9:
|
||||
77:48:f4:6d:56:89:35:5c:79:5b:f6:2f:8c:9f:93:
|
||||
bc:13:1c:d0:74:5f:30:1b:15:43:71:8e:ff:1a:df:
|
||||
65:65:69:c2:8a:5a:ab:04:4a:80:de:20:29:8d:48:
|
||||
1c:83
|
||||
Exponent: 65537 (0x10001)
|
||||
X509v3 extensions:
|
||||
X509v3 Basic Constraints:
|
||||
CA:FALSE
|
||||
Netscape Comment:
|
||||
OpenSSL Generated Certificate
|
||||
X509v3 Subject Key Identifier:
|
||||
34:E9:5C:D8:FC:C7:AF:F7:5D:F4:13:D3:82:1A:CD:52:0F:4A:BB:0B
|
||||
X509v3 Authority Key Identifier:
|
||||
keyid:52:33:2E:22:66:79:82:E5:41:2E:8D:3B:B2:E5:CC:FA:BE:99:33:8E
|
||||
DirName:/C=US/ST=Berkshire/L=Newbury/O=My Company Ltd/OU=test/CN=test/emailAddress=test@test.com
|
||||
serial:E6:4C:5C:96:26:5E:D6:D0
|
||||
|
||||
Signature Algorithm: md5WithRSAEncryption
|
||||
88:c4:dd:c5:4a:a6:8e:1f:36:62:80:31:6b:2b:85:34:0d:6c:
|
||||
a7:dc:e1:5a:3c:dd:74:57:db:59:be:8b:f2:79:40:2d:bd:9b:
|
||||
e1:ab:0e:03:75:20:75:2f:ea:97:f9:d4:7e:15:75:c2:82:f5:
|
||||
b1:37:e4:8b:24:d4:ef:02:3b:19:6a:56:bb:9f:c3:a5:b4:c4:
|
||||
39:a0:64:96:5b:c3:a8:19:74:ec:0b:cf:33:df:f3:12:f3:e2:
|
||||
ab:1d:7d:de:21:64:cd:b1:a0:6f:7a:77:84:d4:62:8a:50:e6:
|
||||
76:5d:af:3a:ef:1a:87:0e:1a:38:c4:f9:0d:2f:14:e0:20:32:
|
||||
4c:2e:70:d2:71:82:d5:e5:c9:13:2c:4e:b4:c8:63:65:1d:48:
|
||||
e8:c3:56:6d:88:84:57:65:13:1e:42:48:b4:03:25:71:4e:12:
|
||||
9d:1a:88:65:d5:71:21:3b:0e:be:37:1c:f0:88:6b:45:0c:0e:
|
||||
6c:e5:60:cb:86:bf:bf:40:30:c4:cf:94:f8:1c:60:d4:1b:df:
|
||||
88:02:7a:45:7e:d1:c6:f3:07:b9:b1:8f:2a:55:2f:be:77:9f:
|
||||
d1:46:64:05:b7:67:c5:b2:ac:8c:42:8f:6a:51:a4:0d:2b:16:
|
||||
a4:d6:39:a5:f8:25:ed:68:25:13:b5:19:ac:6c:e9:ec:ee:03:
|
||||
6b:80:38:6e
|
||||
|
||||
163
libnm-util/tests/test-setting-8021x.c
Normal file
163
libnm-util/tests/test-setting-8021x.c
Normal file
|
|
@ -0,0 +1,163 @@
|
|||
/* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
|
||||
/*
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2, or (at your option)
|
||||
* any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along
|
||||
* with this program; if not, write to the Free Software Foundation, Inc.,
|
||||
* 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
|
||||
*
|
||||
* Copyright (C) 2008 - 2009 Red Hat, Inc.
|
||||
*
|
||||
*/
|
||||
|
||||
#include <glib.h>
|
||||
#include <dbus/dbus-glib.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "nm-test-helpers.h"
|
||||
#include <nm-utils.h>
|
||||
|
||||
#include "nm-setting-connection.h"
|
||||
#include "nm-setting-8021x.h"
|
||||
|
||||
static void
|
||||
compare_decrypted (const char *test,
|
||||
const char *decrypted_path,
|
||||
const GByteArray *key)
|
||||
{
|
||||
char *contents = NULL;
|
||||
gsize len = 0;
|
||||
GError *error = NULL;
|
||||
gboolean success;
|
||||
|
||||
success = g_file_get_contents (decrypted_path, &contents, &len, &error);
|
||||
ASSERT (success == TRUE,
|
||||
test, "failed to read decrypted key file: %s", error->message);
|
||||
|
||||
ASSERT (len > 0, test, "decrypted key file invalid (size 0)");
|
||||
|
||||
ASSERT (len == key->len,
|
||||
test, "decrypted key file (%d) and decrypted key data (%d) lengths don't match",
|
||||
len, key->len);
|
||||
|
||||
ASSERT (memcmp (contents, key->data, len) == 0,
|
||||
test, "decrypted key file and decrypted key data don't match");
|
||||
|
||||
g_free (contents);
|
||||
}
|
||||
|
||||
static void
|
||||
test_private_key_import (const char *path,
|
||||
const char *password,
|
||||
const char *decrypted_path,
|
||||
NMSetting8021xCKScheme scheme)
|
||||
{
|
||||
NMSetting8021x *s_8021x;
|
||||
gboolean success;
|
||||
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
|
||||
GError *error = NULL;
|
||||
|
||||
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
|
||||
ASSERT (s_8021x != NULL, "private-key-import", "setting was NULL");
|
||||
|
||||
success = nm_setting_802_1x_set_private_key (s_8021x,
|
||||
path,
|
||||
password,
|
||||
scheme,
|
||||
&format,
|
||||
&error);
|
||||
ASSERT (success == TRUE,
|
||||
"private-key-import", "error reading private key: %s", error->message);
|
||||
|
||||
if ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|
||||
&& format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
|
||||
const GByteArray *key;
|
||||
|
||||
ASSERT (decrypted_path != NULL, "private-key-import", "missing decrypted key file");
|
||||
|
||||
key = nm_setting_802_1x_get_private_key_blob (s_8021x);
|
||||
ASSERT (key != NULL, "private-key-import", "missing private key blob");
|
||||
compare_decrypted ("private-key-import", decrypted_path, key);
|
||||
}
|
||||
|
||||
g_object_unref (s_8021x);
|
||||
}
|
||||
|
||||
static void
|
||||
test_phase2_private_key_import (const char *path,
|
||||
const char *password,
|
||||
const char *decrypted_path,
|
||||
NMSetting8021xCKScheme scheme)
|
||||
{
|
||||
NMSetting8021x *s_8021x;
|
||||
gboolean success;
|
||||
NMSetting8021xCKFormat format = NM_SETTING_802_1X_CK_FORMAT_UNKNOWN;
|
||||
GError *error = NULL;
|
||||
|
||||
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
|
||||
ASSERT (s_8021x != NULL, "phase2-private-key-import", "setting was NULL");
|
||||
|
||||
success = nm_setting_802_1x_set_phase2_private_key (s_8021x,
|
||||
path,
|
||||
password,
|
||||
scheme,
|
||||
&format,
|
||||
&error);
|
||||
ASSERT (success == TRUE,
|
||||
"phase2-private-key-import", "error reading private key: %s", error->message);
|
||||
|
||||
if ( scheme == NM_SETTING_802_1X_CK_SCHEME_BLOB
|
||||
&& format != NM_SETTING_802_1X_CK_FORMAT_PKCS12) {
|
||||
const GByteArray *key;
|
||||
|
||||
ASSERT (decrypted_path != NULL, "phase2-private-key-import", "missing decrypted key file");
|
||||
|
||||
key = nm_setting_802_1x_get_phase2_private_key_blob (s_8021x);
|
||||
ASSERT (key != NULL, "phase2-private-key-import", "missing private key blob");
|
||||
compare_decrypted ("phase2-private-key-import", decrypted_path, key);
|
||||
}
|
||||
|
||||
g_object_unref (s_8021x);
|
||||
}
|
||||
|
||||
int main (int argc, char **argv)
|
||||
{
|
||||
GError *error = NULL;
|
||||
DBusGConnection *bus;
|
||||
char *base;
|
||||
const char *decrypted = NULL;
|
||||
|
||||
if (argc < 3)
|
||||
FAIL ("init", "need at least two arguments: <path> <password> [decrypted private key]");
|
||||
|
||||
if (argc == 4)
|
||||
decrypted = argv[3];
|
||||
|
||||
g_type_init ();
|
||||
bus = dbus_g_bus_get (DBUS_BUS_SESSION, NULL);
|
||||
|
||||
if (!nm_utils_init (&error))
|
||||
FAIL ("nm-utils-init", "failed to initialize libnm-util: %s", error->message);
|
||||
|
||||
/* The tests */
|
||||
test_private_key_import (argv[1], argv[2], NULL, NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
test_phase2_private_key_import (argv[1], argv[2], NULL, NM_SETTING_802_1X_CK_SCHEME_PATH);
|
||||
|
||||
test_private_key_import (argv[1], argv[2], decrypted, NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||
test_phase2_private_key_import (argv[1], argv[2], decrypted, NM_SETTING_802_1X_CK_SCHEME_BLOB);
|
||||
|
||||
base = g_path_get_basename (argv[0]);
|
||||
fprintf (stdout, "%s: SUCCESS\n", base);
|
||||
g_free (base);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
|
@ -18,9 +18,7 @@ libsupplicant_manager_la_SOURCES = \
|
|||
nm-supplicant-interface.c \
|
||||
nm-supplicant-interface.h \
|
||||
nm-supplicant-settings-verify.h \
|
||||
nm-supplicant-settings-verify.c \
|
||||
gnome-keyring-md5.h \
|
||||
gnome-keyring-md5.c
|
||||
nm-supplicant-settings-verify.c
|
||||
|
||||
libsupplicant_manager_la_CPPFLAGS = \
|
||||
$(DBUS_CFLAGS) \
|
||||
|
|
|
|||
|
|
@ -1,291 +0,0 @@
|
|||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* GnomeKeyringMD5Context structure, pass it to gnome_keyring_md5_init, call
|
||||
* gnome_keyring_md5_update as needed on buffers full of bytes, and then call
|
||||
* gnome_keyring_md5_final, which will fill a supplied 32-byte array with the
|
||||
* digest in ascii form.
|
||||
*
|
||||
*/
|
||||
|
||||
#include "gnome-keyring-md5.h"
|
||||
#include <string.h>
|
||||
|
||||
static void gnome_keyring_md5_transform (guint32 buf[4],
|
||||
guint32 const in[16]);
|
||||
|
||||
void
|
||||
gnome_keyring_md5_string (const char *string, unsigned char digest[16])
|
||||
{
|
||||
struct GnomeKeyringMD5Context md5_context;
|
||||
|
||||
gnome_keyring_md5_init (&md5_context);
|
||||
gnome_keyring_md5_update (&md5_context, (const unsigned char *)string, strlen (string));
|
||||
gnome_keyring_md5_final (digest, &md5_context);
|
||||
}
|
||||
|
||||
#if G_BYTE_ORDER == G_LITTLE_ENDIAN
|
||||
#define byteReverse(buf, len) /* Nothing */
|
||||
#else
|
||||
|
||||
/*
|
||||
* Note: this code is harmless on little-endian machines.
|
||||
*/
|
||||
static void
|
||||
byteReverse(unsigned char *buf, unsigned longs)
|
||||
{
|
||||
guint32 t;
|
||||
do {
|
||||
t = (guint32) ((unsigned) buf[3] << 8 | buf[2]) << 16 |
|
||||
((unsigned) buf[1] << 8 | buf[0]);
|
||||
*(guint32 *) buf = t;
|
||||
buf += 4;
|
||||
} while (--longs);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
char *
|
||||
gnome_keyring_md5_digest_to_ascii (unsigned char digest[16])
|
||||
{
|
||||
static char hex_digits[] = "0123456789abcdef";
|
||||
char *res;
|
||||
int i;
|
||||
|
||||
res = g_malloc (33);
|
||||
|
||||
for (i = 0; i < 16; i++) {
|
||||
res[2*i] = hex_digits[digest[i] >> 4];
|
||||
res[2*i+1] = hex_digits[digest[i] & 0xf];
|
||||
}
|
||||
|
||||
res[32] = 0;
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
|
||||
* initialization constants.
|
||||
*/
|
||||
void
|
||||
gnome_keyring_md5_init (struct GnomeKeyringMD5Context *ctx)
|
||||
{
|
||||
ctx->buf[0] = 0x67452301;
|
||||
ctx->buf[1] = 0xefcdab89;
|
||||
ctx->buf[2] = 0x98badcfe;
|
||||
ctx->buf[3] = 0x10325476;
|
||||
|
||||
ctx->bits[0] = 0;
|
||||
ctx->bits[1] = 0;
|
||||
}
|
||||
|
||||
/*
|
||||
* Update context to reflect the concatenation of another buffer full
|
||||
* of bytes.
|
||||
*/
|
||||
void
|
||||
gnome_keyring_md5_update (struct GnomeKeyringMD5Context *ctx,
|
||||
unsigned char const *buf,
|
||||
unsigned len)
|
||||
{
|
||||
guint32 t;
|
||||
|
||||
/* Update bitcount */
|
||||
|
||||
t = ctx->bits[0];
|
||||
if ((ctx->bits[0] = t + ((guint32) len << 3)) < t)
|
||||
ctx->bits[1]++; /* Carry from low to high */
|
||||
ctx->bits[1] += len >> 29;
|
||||
|
||||
t = (t >> 3) & 0x3f; /* Bytes already in shsInfo->data */
|
||||
|
||||
/* Handle any leading odd-sized chunks */
|
||||
|
||||
if (t) {
|
||||
unsigned char *p = (unsigned char *) ctx->in + t;
|
||||
|
||||
t = 64 - t;
|
||||
if (len < t) {
|
||||
memcpy (p, buf, len);
|
||||
return;
|
||||
}
|
||||
memcpy (p, buf, t);
|
||||
byteReverse (ctx->in, 16);
|
||||
gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
|
||||
buf += t;
|
||||
len -= t;
|
||||
}
|
||||
|
||||
/* Process data in 64-byte chunks */
|
||||
|
||||
while (len >= 64) {
|
||||
memcpy (ctx->in, buf, 64);
|
||||
byteReverse (ctx->in, 16);
|
||||
gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
|
||||
buf += 64;
|
||||
len -= 64;
|
||||
}
|
||||
|
||||
/* Handle any remaining bytes of data. */
|
||||
|
||||
memcpy(ctx->in, buf, len);
|
||||
}
|
||||
|
||||
/*
|
||||
* Final wrapup - pad to 64-byte boundary with the bit pattern
|
||||
* 1 0* (64-bit count of bits processed, MSB-first)
|
||||
*/
|
||||
void
|
||||
gnome_keyring_md5_final (unsigned char digest[16], struct GnomeKeyringMD5Context *ctx)
|
||||
{
|
||||
unsigned count;
|
||||
unsigned char *p;
|
||||
|
||||
/* Compute number of bytes mod 64 */
|
||||
count = (ctx->bits[0] >> 3) & 0x3F;
|
||||
|
||||
/* Set the first char of padding to 0x80. This is safe since there is
|
||||
always at least one byte free */
|
||||
p = ctx->in + count;
|
||||
*p++ = 0x80;
|
||||
|
||||
/* Bytes of padding needed to make 64 bytes */
|
||||
count = 64 - 1 - count;
|
||||
|
||||
/* Pad out to 56 mod 64 */
|
||||
if (count < 8) {
|
||||
/* Two lots of padding: Pad the first block to 64 bytes */
|
||||
memset (p, 0, count);
|
||||
byteReverse (ctx->in, 16);
|
||||
gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
|
||||
|
||||
/* Now fill the next block with 56 bytes */
|
||||
memset(ctx->in, 0, 56);
|
||||
} else {
|
||||
/* Pad block to 56 bytes */
|
||||
memset(p, 0, count - 8);
|
||||
}
|
||||
byteReverse(ctx->in, 14);
|
||||
|
||||
/* Append length in bits and transform */
|
||||
((guint32 *) ctx->in)[14] = ctx->bits[0];
|
||||
((guint32 *) ctx->in)[15] = ctx->bits[1];
|
||||
|
||||
gnome_keyring_md5_transform (ctx->buf, (guint32 *) ctx->in);
|
||||
byteReverse ((unsigned char *) ctx->buf, 4);
|
||||
memcpy (digest, ctx->buf, 16);
|
||||
memset (ctx, 0, sizeof(ctx)); /* In case it's sensitive */
|
||||
}
|
||||
|
||||
|
||||
/* The four core functions - F1 is optimized somewhat */
|
||||
|
||||
#define F1(x, y, z) (z ^ (x & (y ^ z)))
|
||||
#define F2(x, y, z) F1 (z, x, y)
|
||||
#define F3(x, y, z) (x ^ y ^ z)
|
||||
#define F4(x, y, z) (y ^ (x | ~z))
|
||||
|
||||
/* This is the central step in the MD5 algorithm. */
|
||||
#define gnome_keyring_md5_step(f, w, x, y, z, data, s) \
|
||||
( w += f(x, y, z) + data, w = w<<s | w>>(32-s), w += x )
|
||||
|
||||
/*
|
||||
* The core of the MD5 algorithm, this alters an existing MD5 hash to
|
||||
* reflect the addition of 16 longwords of new data. GnomeKeyringMD5Update blocks
|
||||
* the data and converts bytes into longwords for this routine.
|
||||
*/
|
||||
static void
|
||||
gnome_keyring_md5_transform (guint32 buf[4], guint32 const in[16])
|
||||
{
|
||||
register guint32 a, b, c, d;
|
||||
|
||||
a = buf[0];
|
||||
b = buf[1];
|
||||
c = buf[2];
|
||||
d = buf[3];
|
||||
|
||||
gnome_keyring_md5_step(F1, a, b, c, d, in[0] + 0xd76aa478, 7);
|
||||
gnome_keyring_md5_step(F1, d, a, b, c, in[1] + 0xe8c7b756, 12);
|
||||
gnome_keyring_md5_step(F1, c, d, a, b, in[2] + 0x242070db, 17);
|
||||
gnome_keyring_md5_step(F1, b, c, d, a, in[3] + 0xc1bdceee, 22);
|
||||
gnome_keyring_md5_step(F1, a, b, c, d, in[4] + 0xf57c0faf, 7);
|
||||
gnome_keyring_md5_step(F1, d, a, b, c, in[5] + 0x4787c62a, 12);
|
||||
gnome_keyring_md5_step(F1, c, d, a, b, in[6] + 0xa8304613, 17);
|
||||
gnome_keyring_md5_step(F1, b, c, d, a, in[7] + 0xfd469501, 22);
|
||||
gnome_keyring_md5_step(F1, a, b, c, d, in[8] + 0x698098d8, 7);
|
||||
gnome_keyring_md5_step(F1, d, a, b, c, in[9] + 0x8b44f7af, 12);
|
||||
gnome_keyring_md5_step(F1, c, d, a, b, in[10] + 0xffff5bb1, 17);
|
||||
gnome_keyring_md5_step(F1, b, c, d, a, in[11] + 0x895cd7be, 22);
|
||||
gnome_keyring_md5_step(F1, a, b, c, d, in[12] + 0x6b901122, 7);
|
||||
gnome_keyring_md5_step(F1, d, a, b, c, in[13] + 0xfd987193, 12);
|
||||
gnome_keyring_md5_step(F1, c, d, a, b, in[14] + 0xa679438e, 17);
|
||||
gnome_keyring_md5_step(F1, b, c, d, a, in[15] + 0x49b40821, 22);
|
||||
|
||||
gnome_keyring_md5_step(F2, a, b, c, d, in[1] + 0xf61e2562, 5);
|
||||
gnome_keyring_md5_step(F2, d, a, b, c, in[6] + 0xc040b340, 9);
|
||||
gnome_keyring_md5_step(F2, c, d, a, b, in[11] + 0x265e5a51, 14);
|
||||
gnome_keyring_md5_step(F2, b, c, d, a, in[0] + 0xe9b6c7aa, 20);
|
||||
gnome_keyring_md5_step(F2, a, b, c, d, in[5] + 0xd62f105d, 5);
|
||||
gnome_keyring_md5_step(F2, d, a, b, c, in[10] + 0x02441453, 9);
|
||||
gnome_keyring_md5_step(F2, c, d, a, b, in[15] + 0xd8a1e681, 14);
|
||||
gnome_keyring_md5_step(F2, b, c, d, a, in[4] + 0xe7d3fbc8, 20);
|
||||
gnome_keyring_md5_step(F2, a, b, c, d, in[9] + 0x21e1cde6, 5);
|
||||
gnome_keyring_md5_step(F2, d, a, b, c, in[14] + 0xc33707d6, 9);
|
||||
gnome_keyring_md5_step(F2, c, d, a, b, in[3] + 0xf4d50d87, 14);
|
||||
gnome_keyring_md5_step(F2, b, c, d, a, in[8] + 0x455a14ed, 20);
|
||||
gnome_keyring_md5_step(F2, a, b, c, d, in[13] + 0xa9e3e905, 5);
|
||||
gnome_keyring_md5_step(F2, d, a, b, c, in[2] + 0xfcefa3f8, 9);
|
||||
gnome_keyring_md5_step(F2, c, d, a, b, in[7] + 0x676f02d9, 14);
|
||||
gnome_keyring_md5_step(F2, b, c, d, a, in[12] + 0x8d2a4c8a, 20);
|
||||
|
||||
gnome_keyring_md5_step(F3, a, b, c, d, in[5] + 0xfffa3942, 4);
|
||||
gnome_keyring_md5_step(F3, d, a, b, c, in[8] + 0x8771f681, 11);
|
||||
gnome_keyring_md5_step(F3, c, d, a, b, in[11] + 0x6d9d6122, 16);
|
||||
gnome_keyring_md5_step(F3, b, c, d, a, in[14] + 0xfde5380c, 23);
|
||||
gnome_keyring_md5_step(F3, a, b, c, d, in[1] + 0xa4beea44, 4);
|
||||
gnome_keyring_md5_step(F3, d, a, b, c, in[4] + 0x4bdecfa9, 11);
|
||||
gnome_keyring_md5_step(F3, c, d, a, b, in[7] + 0xf6bb4b60, 16);
|
||||
gnome_keyring_md5_step(F3, b, c, d, a, in[10] + 0xbebfbc70, 23);
|
||||
gnome_keyring_md5_step(F3, a, b, c, d, in[13] + 0x289b7ec6, 4);
|
||||
gnome_keyring_md5_step(F3, d, a, b, c, in[0] + 0xeaa127fa, 11);
|
||||
gnome_keyring_md5_step(F3, c, d, a, b, in[3] + 0xd4ef3085, 16);
|
||||
gnome_keyring_md5_step(F3, b, c, d, a, in[6] + 0x04881d05, 23);
|
||||
gnome_keyring_md5_step(F3, a, b, c, d, in[9] + 0xd9d4d039, 4);
|
||||
gnome_keyring_md5_step(F3, d, a, b, c, in[12] + 0xe6db99e5, 11);
|
||||
gnome_keyring_md5_step(F3, c, d, a, b, in[15] + 0x1fa27cf8, 16);
|
||||
gnome_keyring_md5_step(F3, b, c, d, a, in[2] + 0xc4ac5665, 23);
|
||||
|
||||
gnome_keyring_md5_step(F4, a, b, c, d, in[0] + 0xf4292244, 6);
|
||||
gnome_keyring_md5_step(F4, d, a, b, c, in[7] + 0x432aff97, 10);
|
||||
gnome_keyring_md5_step(F4, c, d, a, b, in[14] + 0xab9423a7, 15);
|
||||
gnome_keyring_md5_step(F4, b, c, d, a, in[5] + 0xfc93a039, 21);
|
||||
gnome_keyring_md5_step(F4, a, b, c, d, in[12] + 0x655b59c3, 6);
|
||||
gnome_keyring_md5_step(F4, d, a, b, c, in[3] + 0x8f0ccc92, 10);
|
||||
gnome_keyring_md5_step(F4, c, d, a, b, in[10] + 0xffeff47d, 15);
|
||||
gnome_keyring_md5_step(F4, b, c, d, a, in[1] + 0x85845dd1, 21);
|
||||
gnome_keyring_md5_step(F4, a, b, c, d, in[8] + 0x6fa87e4f, 6);
|
||||
gnome_keyring_md5_step(F4, d, a, b, c, in[15] + 0xfe2ce6e0, 10);
|
||||
gnome_keyring_md5_step(F4, c, d, a, b, in[6] + 0xa3014314, 15);
|
||||
gnome_keyring_md5_step(F4, b, c, d, a, in[13] + 0x4e0811a1, 21);
|
||||
gnome_keyring_md5_step(F4, a, b, c, d, in[4] + 0xf7537e82, 6);
|
||||
gnome_keyring_md5_step(F4, d, a, b, c, in[11] + 0xbd3af235, 10);
|
||||
gnome_keyring_md5_step(F4, c, d, a, b, in[2] + 0x2ad7d2bb, 15);
|
||||
gnome_keyring_md5_step(F4, b, c, d, a, in[9] + 0xeb86d391, 21);
|
||||
|
||||
buf[0] += a;
|
||||
buf[1] += b;
|
||||
buf[2] += c;
|
||||
buf[3] += d;
|
||||
}
|
||||
|
||||
|
|
@ -1,41 +0,0 @@
|
|||
/*
|
||||
* This code implements the MD5 message-digest algorithm.
|
||||
* The algorithm is due to Ron Rivest. This code was
|
||||
* written by Colin Plumb in 1993, no copyright is claimed.
|
||||
* This code is in the public domain; do with it what you wish.
|
||||
*
|
||||
* Equivalent code is available from RSA Data Security, Inc.
|
||||
* This code has been tested against that, and is equivalent,
|
||||
* except that you don't need to include two pages of legalese
|
||||
* with every copy.
|
||||
*
|
||||
* To compute the message digest of a chunk of bytes, declare an
|
||||
* GnomeKeyringMD5Context structure, pass it to gnome_keyring_md5_init, call
|
||||
* gnome_keyring_md5_update as needed on buffers full of bytes, and then call
|
||||
* gnome_keyring_md5_final, which will fill a supplied 32-byte array with the
|
||||
* digest in ascii form.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef GNOME_KEYRING_MD5_H
|
||||
#define GNOME_KEYRING_MD5_H
|
||||
|
||||
#include <glib.h>
|
||||
|
||||
struct GnomeKeyringMD5Context {
|
||||
guint32 buf[4];
|
||||
guint32 bits[2];
|
||||
unsigned char in[64];
|
||||
};
|
||||
|
||||
char *gnome_keyring_md5_digest_to_ascii (unsigned char digest[16]);
|
||||
void gnome_keyring_md5_string (const char *string,
|
||||
unsigned char digest[16]);
|
||||
void gnome_keyring_md5_init (struct GnomeKeyringMD5Context *ctx);
|
||||
void gnome_keyring_md5_update (struct GnomeKeyringMD5Context *ctx,
|
||||
unsigned char const *buf,
|
||||
unsigned len);
|
||||
void gnome_keyring_md5_final (unsigned char digest[16],
|
||||
struct GnomeKeyringMD5Context *ctx);
|
||||
|
||||
#endif /* GNOME_KEYRING_MD5_H */
|
||||
|
|
@ -35,8 +35,6 @@
|
|||
#include "nm-setting.h"
|
||||
#include "NetworkManagerUtils.h"
|
||||
|
||||
#include "gnome-keyring-md5.h"
|
||||
|
||||
static char *hexstr2bin (const char *hex, size_t len);
|
||||
|
||||
#define NM_SUPPLICANT_CONFIG_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), \
|
||||
|
|
@ -502,24 +500,34 @@ get_blob_id (const char *name, const char *seed_uid)
|
|||
}
|
||||
|
||||
|
||||
static unsigned char *
|
||||
wep128_passphrase_hash (const char *input, size_t input_len, size_t *out_len)
|
||||
static gboolean
|
||||
wep128_passphrase_hash (const char *input,
|
||||
size_t input_len,
|
||||
guint8 *out_digest,
|
||||
size_t *out_digest_len)
|
||||
{
|
||||
char md5_data[65];
|
||||
unsigned char *digest;
|
||||
GChecksum *sum;
|
||||
guint8 data[64];
|
||||
int i;
|
||||
|
||||
*out_len = 16;
|
||||
digest = g_malloc0 (*out_len);
|
||||
g_return_val_if_fail (out_digest != NULL, FALSE);
|
||||
g_return_val_if_fail (out_digest_len != NULL, FALSE);
|
||||
g_return_val_if_fail (*out_digest_len >= 16, FALSE);
|
||||
|
||||
/* Get at least 64 bytes */
|
||||
for (i = 0; i < 64; i++)
|
||||
md5_data[i] = input[i % input_len];
|
||||
/* Get at least 64 bytes by repeating the passphrase into the buffer */
|
||||
for (i = 0; i < sizeof (data); i++)
|
||||
data[i] = input[i % input_len];
|
||||
|
||||
/* Null terminate md5 seed data and hash it */
|
||||
md5_data[64] = 0;
|
||||
gnome_keyring_md5_string (md5_data, digest);
|
||||
return digest;
|
||||
sum = g_checksum_new (G_CHECKSUM_MD5);
|
||||
g_assert (sum);
|
||||
g_checksum_update (sum, data, sizeof (data));
|
||||
g_checksum_get_digest (sum, out_digest, out_digest_len);
|
||||
g_checksum_free (sum);
|
||||
|
||||
g_assert (*out_digest_len == 16);
|
||||
/* WEP104 keys are 13 bytes in length (26 hex characters) */
|
||||
*out_digest_len = 13;
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
|
|
@ -555,12 +563,12 @@ add_wep_key (NMSupplicantConfig *self,
|
|||
return FALSE;
|
||||
}
|
||||
} else if (wep_type == NM_WEP_KEY_TYPE_PASSPHRASE) {
|
||||
char *digest;
|
||||
size_t digest_len;
|
||||
guint8 digest[16];
|
||||
size_t digest_len = sizeof (digest);
|
||||
|
||||
digest = (char *) wep128_passphrase_hash (key, key_len, &digest_len);
|
||||
success = nm_supplicant_config_add_option (self, name, digest, 13, TRUE);
|
||||
g_free (digest);
|
||||
success = wep128_passphrase_hash (key, key_len, digest, &digest_len);
|
||||
if (success)
|
||||
success = nm_supplicant_config_add_option (self, name, (const char *) digest, digest_len, TRUE);
|
||||
if (!success) {
|
||||
nm_warning ("Error adding %s to supplicant config.", name);
|
||||
return FALSE;
|
||||
|
|
|
|||
|
|
@ -11,8 +11,6 @@ libifcfg_rh_io_la_SOURCES = \
|
|||
reader.h \
|
||||
writer.c \
|
||||
writer.h \
|
||||
sha1.c \
|
||||
sha1.h \
|
||||
errors.c \
|
||||
common.h \
|
||||
utils.c \
|
||||
|
|
|
|||
|
|
@ -25,6 +25,7 @@
|
|||
|
||||
#define IFCFG_TAG "ifcfg-"
|
||||
#define KEYS_TAG "keys-"
|
||||
#define ROUTE_TAG "route-"
|
||||
#define BAK_TAG ".bak"
|
||||
#define TILDE_TAG "~"
|
||||
#define ORIG_TAG ".orig"
|
||||
|
|
|
|||
|
|
@ -60,6 +60,9 @@ typedef struct {
|
|||
char *keyfile;
|
||||
int keyfile_wd;
|
||||
|
||||
char *routefile;
|
||||
int routefile_wd;
|
||||
|
||||
char *udi;
|
||||
char *unmanaged;
|
||||
} NMIfcfgConnectionPrivate;
|
||||
|
|
@ -90,7 +93,7 @@ files_changed_cb (NMInotifyHelper *ih,
|
|||
NMIfcfgConnection *self = NM_IFCFG_CONNECTION (user_data);
|
||||
NMIfcfgConnectionPrivate *priv = NM_IFCFG_CONNECTION_GET_PRIVATE (self);
|
||||
|
||||
if ((evt->wd != priv->file_wd) && (evt->wd != priv->keyfile_wd))
|
||||
if ((evt->wd != priv->file_wd) && (evt->wd != priv->keyfile_wd) && (evt->wd != priv->routefile_wd))
|
||||
return;
|
||||
|
||||
/* push the event up to the plugin */
|
||||
|
|
@ -107,11 +110,12 @@ nm_ifcfg_connection_new (const char *filename,
|
|||
NMConnection *tmp;
|
||||
char *unmanaged = NULL;
|
||||
char *keyfile = NULL;
|
||||
char *routefile = NULL;
|
||||
NMInotifyHelper *ih;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, NULL);
|
||||
|
||||
tmp = connection_from_file (filename, NULL, NULL, NULL, &unmanaged, &keyfile, error, ignore_error);
|
||||
tmp = connection_from_file (filename, NULL, NULL, NULL, &unmanaged, &keyfile, &routefile, error, ignore_error);
|
||||
if (!tmp)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -138,6 +142,9 @@ nm_ifcfg_connection_new (const char *filename,
|
|||
priv->keyfile = keyfile;
|
||||
priv->keyfile_wd = nm_inotify_helper_add_watch (ih, keyfile);
|
||||
|
||||
priv->routefile = routefile;
|
||||
priv->routefile_wd = nm_inotify_helper_add_watch (ih, routefile);
|
||||
|
||||
return NM_IFCFG_CONNECTION (object);
|
||||
}
|
||||
|
||||
|
|
@ -169,6 +176,7 @@ update (NMSettingsConnectionInterface *connection,
|
|||
IFCFG_DIR,
|
||||
priv->filename,
|
||||
priv->keyfile,
|
||||
priv->routefile,
|
||||
&error)) {
|
||||
callback (connection, error, user_data);
|
||||
g_error_free (error);
|
||||
|
|
@ -188,6 +196,8 @@ do_delete (NMSettingsConnectionInterface *connection,
|
|||
g_unlink (priv->filename);
|
||||
if (priv->keyfile)
|
||||
g_unlink (priv->keyfile);
|
||||
if (priv->routefile)
|
||||
g_unlink (priv->routefile);
|
||||
|
||||
return parent_settings_connection_iface->delete (connection, callback, user_data);
|
||||
}
|
||||
|
|
@ -229,6 +239,10 @@ finalize (GObject *object)
|
|||
if (priv->keyfile_wd >= 0)
|
||||
nm_inotify_helper_remove_watch (ih, priv->keyfile_wd);
|
||||
|
||||
g_free (priv->routefile);
|
||||
if (priv->routefile_wd >= 0)
|
||||
nm_inotify_helper_remove_watch (ih, priv->routefile_wd);
|
||||
|
||||
G_OBJECT_CLASS (nm_ifcfg_connection_parent_class)->finalize (object);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -603,6 +603,256 @@ error:
|
|||
return addr;
|
||||
}
|
||||
|
||||
static NMIP4Route *
|
||||
read_one_ip4_route (shvarFile *ifcfg,
|
||||
const char *network_file,
|
||||
guint32 which,
|
||||
GError **error)
|
||||
{
|
||||
NMIP4Route *route;
|
||||
char *ip_tag, *netmask_tag, *gw_tag, *metric_tag, *value;
|
||||
guint32 tmp;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail (ifcfg != NULL, NULL);
|
||||
g_return_val_if_fail (network_file != NULL, NULL);
|
||||
g_return_val_if_fail (which >= 0, NULL);
|
||||
|
||||
route = nm_ip4_route_new ();
|
||||
|
||||
ip_tag = g_strdup_printf ("ADDRESS%u", which);
|
||||
netmask_tag = g_strdup_printf ("NETMASK%u", which);
|
||||
gw_tag = g_strdup_printf ("GATEWAY%u", which);
|
||||
metric_tag = g_strdup_printf ("METRIC%u", which);
|
||||
|
||||
/* Destination */
|
||||
if (!read_ip4_address (ifcfg, ip_tag, &tmp, error))
|
||||
goto out;
|
||||
if (!tmp) {
|
||||
/* Check whether IP is missing or 0.0.0.0 */
|
||||
char *val;
|
||||
val = svGetValue (ifcfg, ip_tag, FALSE);
|
||||
if (!val) {
|
||||
nm_ip4_route_unref (route);
|
||||
route = NULL;
|
||||
success = TRUE; /* done */
|
||||
goto out;
|
||||
}
|
||||
g_free (val);
|
||||
}
|
||||
nm_ip4_route_set_dest (route, tmp);
|
||||
|
||||
/* Next hop */
|
||||
if (!read_ip4_address (ifcfg, gw_tag, &tmp, error))
|
||||
goto out;
|
||||
if (!tmp) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Missing or invalid IP4 gateway address '%d'",
|
||||
tmp);
|
||||
goto out;
|
||||
}
|
||||
nm_ip4_route_set_next_hop (route, tmp);
|
||||
|
||||
/* Prefix */
|
||||
if (!read_ip4_address (ifcfg, netmask_tag, &tmp, error))
|
||||
goto out;
|
||||
nm_ip4_route_set_prefix (route, nm_utils_ip4_netmask_to_prefix (tmp));
|
||||
|
||||
/* Validate the prefix */
|
||||
if ( !nm_ip4_route_get_prefix (route)
|
||||
|| nm_ip4_route_get_prefix (route) > 32) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Missing or invalid IP4 prefix '%d'",
|
||||
nm_ip4_route_get_prefix (route));
|
||||
goto out;
|
||||
}
|
||||
|
||||
/* Metric */
|
||||
value = svGetValue (ifcfg, metric_tag, FALSE);
|
||||
if (value) {
|
||||
long int metric;
|
||||
|
||||
errno = 0;
|
||||
metric = strtol (value, NULL, 10);
|
||||
if (errno || metric < 0) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Invalid IP4 route metric '%s'", value);
|
||||
g_free (value);
|
||||
goto out;
|
||||
}
|
||||
nm_ip4_route_set_metric (route, (guint32) metric);
|
||||
g_free (value);
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
if (!success) {
|
||||
nm_ip4_route_unref (route);
|
||||
route = NULL;
|
||||
}
|
||||
|
||||
g_free (ip_tag);
|
||||
g_free (netmask_tag);
|
||||
g_free (gw_tag);
|
||||
g_free (metric_tag);
|
||||
return route;
|
||||
}
|
||||
|
||||
static gboolean
|
||||
read_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError **error)
|
||||
{
|
||||
char *contents = NULL;
|
||||
gsize len = 0;
|
||||
char **lines = NULL, **iter;
|
||||
GRegex *regex_to1, *regex_to2, *regex_via, *regex_metric;
|
||||
GMatchInfo *match_info;
|
||||
NMIP4Route *route;
|
||||
struct in_addr ip4_addr;
|
||||
char *dest = NULL, *prefix = NULL, *next_hop = NULL, *metric = NULL;
|
||||
long int prefix_int, metric_int;
|
||||
gboolean success = FALSE;
|
||||
|
||||
const char *pattern_empty = "^\\s*(\\#.*)?$";
|
||||
const char *pattern_to1 = "^\\s*(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|default)" /* IP or 'default' keyword */
|
||||
"(?:/(\\d{1,2}))?"; /* optional prefix */
|
||||
const char *pattern_to2 = "to\\s+(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}|default)" /* IP or 'default' keyword */
|
||||
"(?:/(\\d{1,2}))?"; /* optional prefix */
|
||||
const char *pattern_via = "via\\s+(\\d{1,3}\\.\\d{1,3}\\.\\d{1,3}\\.\\d{1,3})"; /* IP of gateway */
|
||||
const char *pattern_metric = "metric\\s+(\\d+)"; /* metric */
|
||||
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
g_return_val_if_fail (s_ip4 != NULL, FALSE);
|
||||
g_return_val_if_fail (error != NULL, FALSE);
|
||||
g_return_val_if_fail (*error == NULL, FALSE);
|
||||
|
||||
/* Read the route file */
|
||||
if (!g_file_get_contents (filename, &contents, &len, NULL))
|
||||
return FALSE;
|
||||
|
||||
if (len == 0) {
|
||||
g_free (contents);
|
||||
return FALSE;
|
||||
}
|
||||
|
||||
/* Create regexes for pieces to be matched */
|
||||
regex_to1 = g_regex_new (pattern_to1, 0, 0, NULL);
|
||||
regex_to2 = g_regex_new (pattern_to2, 0, 0, NULL);
|
||||
regex_via = g_regex_new (pattern_via, 0, 0, NULL);
|
||||
regex_metric = g_regex_new (pattern_metric, 0, 0, NULL);
|
||||
|
||||
/* New NMIP4Route structure */
|
||||
route = nm_ip4_route_new ();
|
||||
|
||||
/* Iterate through file lines */
|
||||
lines = g_strsplit_set (contents, "\n\r", -1);
|
||||
for (iter = lines; iter && *iter; iter++) {
|
||||
|
||||
/* Skip empty lines */
|
||||
if (g_regex_match_simple (pattern_empty, *iter, 0, 0))
|
||||
continue;
|
||||
|
||||
/* Destination */
|
||||
g_regex_match (regex_to1, *iter, 0, &match_info);
|
||||
if (!g_match_info_matches (match_info)) {
|
||||
g_match_info_free (match_info);
|
||||
g_regex_match (regex_to2, *iter, 0, &match_info);
|
||||
if (!g_match_info_matches (match_info)) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Missing IP4 route destination address in record: '%s'", *iter);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
dest = g_match_info_fetch (match_info, 1);
|
||||
g_match_info_free (match_info);
|
||||
if (!strcmp (dest, "default"))
|
||||
strcpy (dest, "0.0.0.0");
|
||||
if (inet_pton (AF_INET, dest, &ip4_addr) != 1) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Invalid IP4 route destination address '%s'", dest);
|
||||
g_free (dest);
|
||||
goto error;
|
||||
}
|
||||
nm_ip4_route_set_dest (route, ip4_addr.s_addr);
|
||||
g_free (dest);
|
||||
|
||||
/* Prefix - is optional; 32 if missing */
|
||||
prefix = g_match_info_fetch (match_info, 2);
|
||||
prefix_int = 32;
|
||||
if (prefix) {
|
||||
errno = 0;
|
||||
prefix_int = strtol (prefix, NULL, 10);
|
||||
if (errno || prefix_int < 0 || prefix_int > 32) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Invalid IP4 route destination prefix '%s'", prefix);
|
||||
g_free (prefix);
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
nm_ip4_route_set_prefix (route, (guint32) prefix_int);
|
||||
g_free (prefix);
|
||||
|
||||
/* Next hop */
|
||||
g_regex_match (regex_via, *iter, 0, &match_info);
|
||||
if (!g_match_info_matches (match_info)) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Missing IP4 route gateway address in record: '%s'", *iter);
|
||||
goto error;
|
||||
}
|
||||
next_hop = g_match_info_fetch (match_info, 1);
|
||||
g_match_info_free (match_info);
|
||||
if (inet_pton (AF_INET, next_hop, &ip4_addr) != 1) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Invalid IP4 route gateway address '%s'", next_hop);
|
||||
g_free (next_hop);
|
||||
goto error;
|
||||
}
|
||||
nm_ip4_route_set_next_hop (route, ip4_addr.s_addr);
|
||||
g_free (next_hop);
|
||||
|
||||
/* Metric */
|
||||
g_regex_match (regex_metric, *iter, 0, &match_info);
|
||||
metric_int = 0;
|
||||
if (g_match_info_matches (match_info)) {
|
||||
metric = g_match_info_fetch (match_info, 1);
|
||||
errno = 0;
|
||||
metric_int = strtol (metric, NULL, 10);
|
||||
if (errno || metric_int < 0) {
|
||||
g_match_info_free (match_info);
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Invalid IP4 route metric '%s'", metric);
|
||||
g_free (metric);
|
||||
goto error;
|
||||
}
|
||||
g_free (metric);
|
||||
}
|
||||
|
||||
nm_ip4_route_set_metric (route, (guint32) metric_int);
|
||||
g_match_info_free (match_info);
|
||||
|
||||
if (!nm_setting_ip4_config_add_route (s_ip4, route))
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP4 route");
|
||||
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
error:
|
||||
g_free (contents);
|
||||
g_strfreev (lines);
|
||||
nm_ip4_route_unref (route);
|
||||
g_regex_unref (regex_to1);
|
||||
g_regex_unref (regex_to2);
|
||||
g_regex_unref (regex_via);
|
||||
g_regex_unref (regex_metric);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
|
||||
static NMSetting *
|
||||
make_ip4_setting (shvarFile *ifcfg,
|
||||
const char *network_file,
|
||||
|
|
@ -611,9 +861,11 @@ make_ip4_setting (shvarFile *ifcfg,
|
|||
{
|
||||
NMSettingIP4Config *s_ip4 = NULL;
|
||||
char *value = NULL;
|
||||
char *route_path = NULL;
|
||||
char *method = NM_SETTING_IP4_CONFIG_METHOD_MANUAL;
|
||||
guint32 i;
|
||||
shvarFile *network_ifcfg;
|
||||
shvarFile *route_ifcfg;
|
||||
gboolean never_default = FALSE, tmp_success;
|
||||
|
||||
s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new ();
|
||||
|
|
@ -775,6 +1027,43 @@ make_ip4_setting (shvarFile *ifcfg,
|
|||
g_free (value);
|
||||
}
|
||||
|
||||
/* Static routes - route-<name> file */
|
||||
route_path = utils_get_route_path (ifcfg->fileName);
|
||||
if (!route_path) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Could not get route file path for '%s'", ifcfg->fileName);
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* First test new/legacy syntax */
|
||||
if (utils_has_route_file_new_syntax (route_path)) {
|
||||
/* Parse route file in new syntax */
|
||||
g_free (route_path);
|
||||
route_ifcfg = utils_get_route_ifcfg (ifcfg->fileName, FALSE);
|
||||
if (route_ifcfg) {
|
||||
NMIP4Route *route;
|
||||
for (i = 0; i < 256; i++) {
|
||||
route = read_one_ip4_route (route_ifcfg, network_file, i, error);
|
||||
if (error && *error) {
|
||||
svCloseFile (route_ifcfg);
|
||||
goto error;
|
||||
}
|
||||
if (!route)
|
||||
break;
|
||||
|
||||
if (!nm_setting_ip4_config_add_route (s_ip4, route))
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: duplicate IP4 route");
|
||||
nm_ip4_route_unref (route);
|
||||
}
|
||||
svCloseFile (route_ifcfg);
|
||||
}
|
||||
} else {
|
||||
read_route_file_legacy (route_path, s_ip4, error);
|
||||
g_free (route_path);
|
||||
if (error && *error)
|
||||
goto error;
|
||||
}
|
||||
|
||||
/* Legacy value NM used for a while but is incorrect (rh #459370) */
|
||||
if (!nm_setting_ip4_config_get_num_dns_searches (s_ip4)) {
|
||||
value = svGetValue (ifcfg, "SEARCH", FALSE);
|
||||
|
|
@ -1851,6 +2140,11 @@ make_wireless_setting (shvarFile *ifcfg,
|
|||
}
|
||||
|
||||
g_byte_array_free (array, TRUE);
|
||||
} else if (!nm_controlled) {
|
||||
/* If NM_CONTROLLED=no but there wasn't a MAC address, notify
|
||||
* the user that the device cannot be unmanaged.
|
||||
*/
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed");
|
||||
}
|
||||
} else {
|
||||
g_object_unref (s_wireless);
|
||||
|
|
@ -1936,11 +2230,11 @@ make_wireless_setting (shvarFile *ifcfg,
|
|||
|
||||
if (!strcmp (lcase, "ad-hoc")) {
|
||||
mode = "adhoc";
|
||||
} else if (!strcmp (lcase, "managed")) {
|
||||
} else if (!strcmp (lcase, "managed") || !strcmp (lcase, "auto")) {
|
||||
mode = "infrastructure";
|
||||
} else {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Invalid mode '%s' (not 'Ad-Hoc' or 'Managed')",
|
||||
"Invalid mode '%s' (not 'Ad-Hoc', 'Managed', or 'Auto')",
|
||||
lcase);
|
||||
g_free (lcase);
|
||||
goto error;
|
||||
|
|
@ -2138,6 +2432,11 @@ make_wired_setting (shvarFile *ifcfg,
|
|||
}
|
||||
|
||||
g_byte_array_free (mac, TRUE);
|
||||
} else if (!nm_controlled) {
|
||||
/* If NM_CONTROLLED=no but there wasn't a MAC address, notify
|
||||
* the user that the device cannot be unmanaged.
|
||||
*/
|
||||
PLUGIN_WARN (IFCFG_PLUGIN_NAME, " warning: NM_CONTROLLED was false but HWADDR was missing; device will be managed");
|
||||
}
|
||||
} else {
|
||||
g_object_unref (s_wired);
|
||||
|
|
@ -2263,6 +2562,7 @@ connection_from_file (const char *filename,
|
|||
const char *iscsiadm_path, /* for unit tests only */
|
||||
char **unmanaged,
|
||||
char **keyfile,
|
||||
char **routefile,
|
||||
GError **error,
|
||||
gboolean *ignore_error)
|
||||
{
|
||||
|
|
@ -2278,6 +2578,8 @@ connection_from_file (const char *filename,
|
|||
g_return_val_if_fail (*unmanaged == NULL, NULL);
|
||||
g_return_val_if_fail (keyfile != NULL, NULL);
|
||||
g_return_val_if_fail (*keyfile == NULL, NULL);
|
||||
g_return_val_if_fail (routefile != NULL, NULL);
|
||||
g_return_val_if_fail (*routefile == NULL, NULL);
|
||||
|
||||
/* Non-NULL only for unit tests; normally use /etc/sysconfig/network */
|
||||
if (!network_file)
|
||||
|
|
@ -2402,6 +2704,7 @@ connection_from_file (const char *filename,
|
|||
}
|
||||
|
||||
*keyfile = utils_get_keys_path (filename);
|
||||
*routefile = utils_get_route_path (filename);
|
||||
|
||||
done:
|
||||
svCloseFile (parsed);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@ NMConnection *connection_from_file (const char *filename,
|
|||
const char *iscsiadm_path, /* for unit tests only */
|
||||
char **unmanaged,
|
||||
char **keyfile,
|
||||
char **routefile,
|
||||
GError **error,
|
||||
gboolean *ignore_error);
|
||||
|
||||
|
|
|
|||
|
|
@ -1,692 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
||||
|
|
@ -1,34 +0,0 @@
|
|||
/*
|
||||
* 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 */
|
||||
|
|
@ -15,6 +15,7 @@ EXTRA_DIST = \
|
|||
keys-test-wired-8021x-peap-mschapv2 \
|
||||
ifcfg-test-onboot-no \
|
||||
ifcfg-test-wifi-open \
|
||||
ifcfg-test-wifi-open-auto \
|
||||
ifcfg-test-wifi-open-ssid-quoted \
|
||||
ifcfg-test-wifi-open-ssid-long-quoted \
|
||||
ifcfg-test-wifi-open-ssid-hex \
|
||||
|
|
@ -41,10 +42,19 @@ EXTRA_DIST = \
|
|||
test_ca_cert.pem \
|
||||
test1_key_and_cert.pem \
|
||||
ifcfg-test-ibft-dhcp \
|
||||
ifcfg-test-ibft-static
|
||||
ifcfg-test-ibft-static \
|
||||
ifcfg-test-static-routes-legacy \
|
||||
route-test-static-routes-legacy \
|
||||
ifcfg-test-wired-static-routes \
|
||||
route-test-wired-static-routes \
|
||||
ifcfg-test-wired-static-routes-legacy \
|
||||
route-test-wired-static-routes-legacy
|
||||
|
||||
check-local:
|
||||
@for f in $(EXTRA_DIST); do \
|
||||
chmod 0600 $(abs_srcdir)/$$f; \
|
||||
done
|
||||
|
||||
# Make the special temp dir for some written connections
|
||||
mkdir -p $(abs_builddir)/tmp
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,11 @@
|
|||
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
|
||||
DEVICE=eth0
|
||||
HWADDR=00:16:41:11:22:33
|
||||
NAME="test-static-routes-legacy"
|
||||
TYPE=Ethernet
|
||||
BOOTPROTO=dhcp
|
||||
DEFROUTE=yes
|
||||
UUID=ba60d05a-7898-820d-c2db-427a88f8f2a5
|
||||
ONBOOT=yes
|
||||
PEERDNS=yes
|
||||
PEERROUTES=yes
|
||||
|
|
@ -0,0 +1,13 @@
|
|||
TYPE=Wireless
|
||||
DEVICE=eth2
|
||||
HWADDR=00:16:41:11:22:33
|
||||
NM_CONTROLLED=yes
|
||||
BOOTPROTO=dhcp
|
||||
ESSID=blahblah
|
||||
CHANNEL=1
|
||||
MODE=Auto
|
||||
RATE=auto
|
||||
ONBOOT=yes
|
||||
USERCTL=yes
|
||||
PEERDNS=yes
|
||||
IPV6INIT=no
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
|
||||
TYPE=Ethernet
|
||||
DEVICE=eth0
|
||||
HWADDR=00:11:22:33:44:ee
|
||||
BOOTPROTO=none
|
||||
ONBOOT=yes
|
||||
USERCTL=yes
|
||||
IPV6INIT=no
|
||||
MTU=1492
|
||||
NM_CONTROLLED=yes
|
||||
DNS1=4.2.2.1
|
||||
DNS2=4.2.2.2
|
||||
IPADDR=192.168.1.5
|
||||
NETMASK=255.255.255.0
|
||||
GATEWAY=192.168.1.1
|
||||
|
|
@ -0,0 +1,15 @@
|
|||
# Intel Corporation 82540EP Gigabit Ethernet Controller (Mobile)
|
||||
TYPE=Ethernet
|
||||
DEVICE=eth0
|
||||
HWADDR=00:11:22:33:44:ee
|
||||
BOOTPROTO=none
|
||||
ONBOOT=yes
|
||||
USERCTL=yes
|
||||
IPV6INIT=no
|
||||
MTU=1492
|
||||
NM_CONTROLLED=yes
|
||||
DNS1=4.2.2.1
|
||||
DNS2=4.2.2.2
|
||||
IPADDR=192.168.1.5
|
||||
NETMASK=255.255.255.0
|
||||
GATEWAY=192.168.1.1
|
||||
|
|
@ -0,0 +1,3 @@
|
|||
1.2.3.0/24 via 222.173.190.239 metric 0
|
||||
3.2.1.0/24 via 202.254.171.190 metric 77
|
||||
7.7.7.7/32 via 10.0.2.2 metric 11
|
||||
|
|
@ -0,0 +1,8 @@
|
|||
ADDRESS0=11.22.33.0
|
||||
NETMASK0=255.255.255.0
|
||||
GATEWAY0=192.168.1.5
|
||||
|
||||
ADDRESS1=44.55.66.77
|
||||
NETMASK1=255.255.255.255
|
||||
GATEWAY1=192.168.1.7
|
||||
METRIC1=3
|
||||
|
|
@ -0,0 +1,7 @@
|
|||
# Test route file in legacy format; i.e. lines passed as argumet to "ip route add"
|
||||
|
||||
|
||||
21.31.41.0/24 via 9.9.9.9 metric 1
|
||||
via 8.8.8.8 to 32.42.52.62
|
||||
43.53.0.0/16 metric 3 via 7.7.7.7 dev eth2
|
||||
|
||||
File diff suppressed because it is too large
Load diff
|
|
@ -22,7 +22,6 @@
|
|||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "utils.h"
|
||||
#include "sha1.h"
|
||||
#include "shvar.h"
|
||||
|
||||
/*
|
||||
|
|
@ -144,11 +143,15 @@ utils_get_ifcfg_name (const char *file)
|
|||
return ifcfg_name;
|
||||
}
|
||||
|
||||
/* Used to get an extra file path for ifcfg-<name> in the form <tag><name>.
|
||||
* Currently used for: keys-<name>
|
||||
* route-<name>
|
||||
*/
|
||||
char *
|
||||
utils_get_keys_path (const char *parent)
|
||||
utils_get_extra_path (const char *parent, const char *tag)
|
||||
{
|
||||
char *ifcfg_name;
|
||||
char *keys_file = NULL;
|
||||
char *extra_file = NULL;
|
||||
char *tmp = NULL;
|
||||
|
||||
ifcfg_name = utils_get_ifcfg_name (parent);
|
||||
|
|
@ -159,21 +162,33 @@ utils_get_keys_path (const char *parent)
|
|||
if (!tmp)
|
||||
goto out;
|
||||
|
||||
keys_file = g_strdup_printf ("%s/" KEYS_TAG "%s", tmp, ifcfg_name);
|
||||
extra_file = g_strdup_printf ("%s/%s%s", tmp, tag, ifcfg_name);
|
||||
|
||||
out:
|
||||
g_free (tmp);
|
||||
g_free (ifcfg_name);
|
||||
return keys_file;
|
||||
return extra_file;
|
||||
}
|
||||
|
||||
char *
|
||||
utils_get_keys_path (const char *parent)
|
||||
{
|
||||
return utils_get_extra_path (parent, KEYS_TAG);
|
||||
}
|
||||
|
||||
char *
|
||||
utils_get_route_path (const char *parent)
|
||||
{
|
||||
return utils_get_extra_path (parent, ROUTE_TAG);
|
||||
}
|
||||
|
||||
shvarFile *
|
||||
utils_get_keys_ifcfg (const char *parent, gboolean should_create)
|
||||
utils_get_extra_ifcfg (const char *parent, const char *tag, gboolean should_create)
|
||||
{
|
||||
shvarFile *ifcfg = NULL;
|
||||
char *path;
|
||||
|
||||
path = utils_get_keys_path (parent);
|
||||
path = utils_get_extra_path (parent, tag);
|
||||
if (!path)
|
||||
return NULL;
|
||||
|
||||
|
|
@ -187,3 +202,45 @@ utils_get_keys_ifcfg (const char *parent, gboolean should_create)
|
|||
return ifcfg;
|
||||
}
|
||||
|
||||
shvarFile *
|
||||
utils_get_keys_ifcfg (const char *parent, gboolean should_create)
|
||||
{
|
||||
return utils_get_extra_ifcfg (parent, KEYS_TAG, should_create);
|
||||
}
|
||||
|
||||
shvarFile *
|
||||
utils_get_route_ifcfg (const char *parent, gboolean should_create)
|
||||
{
|
||||
return utils_get_extra_ifcfg (parent, ROUTE_TAG, should_create);
|
||||
}
|
||||
|
||||
/* Finds out if route file has new or older format
|
||||
* Returns TRUE - new syntax (ADDRESS<n>=a.b.c.d ...), error opening file or empty
|
||||
* FALSE - legacy syntax (1.2.3.0/24 via 11.22.33.44)
|
||||
*/
|
||||
gboolean
|
||||
utils_has_route_file_new_syntax (const char *filename)
|
||||
{
|
||||
char *contents = NULL;
|
||||
gsize len = 0;
|
||||
gboolean ret = FALSE;
|
||||
const char *pattern = "^[[:space:]]*ADDRESS[0-9]+=";
|
||||
|
||||
g_return_val_if_fail (filename != NULL, TRUE);
|
||||
|
||||
if (!g_file_get_contents (filename, &contents, &len, NULL))
|
||||
return TRUE;
|
||||
|
||||
if (len <= 0) {
|
||||
ret = TRUE;
|
||||
goto gone;
|
||||
}
|
||||
|
||||
if (g_regex_match_simple (pattern, contents, G_REGEX_MULTILINE, 0))
|
||||
ret = TRUE;
|
||||
|
||||
gone:
|
||||
g_free (contents);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -33,9 +33,15 @@ char *utils_cert_path (const char *parent, const char *suffix);
|
|||
|
||||
char *utils_get_ifcfg_name (const char *file);
|
||||
|
||||
char *utils_get_extra_path (const char *parent, const char *tag);
|
||||
char *utils_get_keys_path (const char *parent);
|
||||
char *utils_get_route_path (const char *parent);
|
||||
|
||||
shvarFile *utils_get_extra_ifcfg (const char *parent, const char *tag, gboolean should_create);
|
||||
shvarFile *utils_get_keys_ifcfg (const char *parent, gboolean should_create);
|
||||
shvarFile *utils_get_route_ifcfg (const char *parent, gboolean should_create);
|
||||
|
||||
gboolean utils_has_route_file_new_syntax (const char *filename);
|
||||
|
||||
#endif /* _UTILS_H_ */
|
||||
|
||||
|
|
|
|||
|
|
@ -844,14 +844,73 @@ write_connection_setting (NMSettingConnection *s_con, shvarFile *ifcfg)
|
|||
}
|
||||
}
|
||||
|
||||
static gboolean
|
||||
write_route_file_legacy (const char *filename, NMSettingIP4Config *s_ip4, GError **error)
|
||||
{
|
||||
char dest[INET_ADDRSTRLEN];
|
||||
char next_hop[INET_ADDRSTRLEN];
|
||||
char **route_items;
|
||||
char *route_contents;
|
||||
NMIP4Route *route;
|
||||
guint32 ip, prefix, metric;
|
||||
guint32 i, num;
|
||||
gboolean success = FALSE;
|
||||
|
||||
g_return_val_if_fail (filename != NULL, FALSE);
|
||||
g_return_val_if_fail (s_ip4 != NULL, FALSE);
|
||||
g_return_val_if_fail (error != NULL, FALSE);
|
||||
g_return_val_if_fail (*error == NULL, FALSE);
|
||||
|
||||
num = nm_setting_ip4_config_get_num_routes (s_ip4);
|
||||
if (num == 0)
|
||||
return TRUE;
|
||||
|
||||
route_items = g_malloc0 (sizeof (char*) * (num + 1));
|
||||
for (i = 0; i < num; i++) {
|
||||
route = nm_setting_ip4_config_get_route (s_ip4, i);
|
||||
|
||||
memset (dest, 0, sizeof (dest));
|
||||
ip = nm_ip4_route_get_dest (route);
|
||||
inet_ntop (AF_INET, (const void *) &ip, &dest[0], sizeof (dest));
|
||||
|
||||
prefix = nm_ip4_route_get_prefix (route);
|
||||
|
||||
memset (next_hop, 0, sizeof (next_hop));
|
||||
ip = nm_ip4_route_get_next_hop (route);
|
||||
inet_ntop (AF_INET, (const void *) &ip, &next_hop[0], sizeof (next_hop));
|
||||
|
||||
metric = nm_ip4_route_get_metric (route);
|
||||
|
||||
route_items[i] = g_strdup_printf ("%s/%u via %s metric %u\n", dest, prefix, next_hop, metric);
|
||||
}
|
||||
route_items[num] = NULL;
|
||||
route_contents = g_strjoinv (NULL, route_items);
|
||||
g_strfreev (route_items);
|
||||
|
||||
if (!g_file_set_contents (filename, route_contents, -1, NULL)) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Writing route file '%s' failed", filename);
|
||||
goto error;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
error:
|
||||
g_free (route_contents);
|
||||
|
||||
return success;
|
||||
}
|
||||
|
||||
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;
|
||||
char *addr_key, *prefix_key, *netmask_key, *gw_key, *metric_key, *tmp;
|
||||
char *route_path = NULL;
|
||||
guint32 i, num;
|
||||
GString *searches;
|
||||
gboolean success = FALSE;
|
||||
|
||||
s_ip4 = (NMSettingIP4Config *) nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG);
|
||||
if (!s_ip4) {
|
||||
|
|
@ -976,8 +1035,93 @@ write_ip4_setting (NMConnection *connection, shvarFile *ifcfg, GError **error)
|
|||
svSetValue (ifcfg, "DHCP_CLIENT_ID", value, FALSE);
|
||||
}
|
||||
|
||||
/* Static routes - route-<name> file */
|
||||
route_path = utils_get_route_path (ifcfg->fileName);
|
||||
if (!route_path) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Could not get route file path for '%s'", ifcfg->fileName);
|
||||
goto out;
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
if (utils_has_route_file_new_syntax (route_path)) {
|
||||
shvarFile *routefile;
|
||||
|
||||
g_free (route_path);
|
||||
routefile = utils_get_route_ifcfg (ifcfg->fileName, TRUE);
|
||||
if (!routefile) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Could not create route file '%s'", routefile->fileName);
|
||||
goto out;
|
||||
}
|
||||
|
||||
num = nm_setting_ip4_config_get_num_routes (s_ip4);
|
||||
for (i = 0; i < 256; i++) {
|
||||
char buf[INET_ADDRSTRLEN];
|
||||
NMIP4Route *route;
|
||||
guint32 ip, metric;
|
||||
|
||||
addr_key = g_strdup_printf ("ADDRESS%d", i);
|
||||
netmask_key = g_strdup_printf ("NETMASK%d", i);
|
||||
gw_key = g_strdup_printf ("GATEWAY%d", i);
|
||||
metric_key = g_strdup_printf ("METRIC%d", i);
|
||||
|
||||
if (i >= num) {
|
||||
svSetValue (routefile, addr_key, NULL, FALSE);
|
||||
svSetValue (routefile, netmask_key, NULL, FALSE);
|
||||
svSetValue (routefile, gw_key, NULL, FALSE);
|
||||
svSetValue (routefile, metric_key, NULL, FALSE);
|
||||
} else {
|
||||
route = nm_setting_ip4_config_get_route (s_ip4, i);
|
||||
|
||||
memset (buf, 0, sizeof (buf));
|
||||
ip = nm_ip4_route_get_dest (route);
|
||||
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
|
||||
svSetValue (routefile, addr_key, &buf[0], FALSE);
|
||||
|
||||
memset (buf, 0, sizeof (buf));
|
||||
ip = nm_utils_ip4_prefix_to_netmask (nm_ip4_route_get_prefix (route));
|
||||
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
|
||||
svSetValue (routefile, netmask_key, &buf[0], FALSE);
|
||||
|
||||
memset (buf, 0, sizeof (buf));
|
||||
ip = nm_ip4_route_get_next_hop (route);
|
||||
inet_ntop (AF_INET, (const void *) &ip, &buf[0], sizeof (buf));
|
||||
svSetValue (routefile, gw_key, &buf[0], FALSE);
|
||||
|
||||
memset (buf, 0, sizeof (buf));
|
||||
metric = nm_ip4_route_get_metric (route);
|
||||
if (metric == 0)
|
||||
svSetValue (routefile, metric_key, NULL, FALSE);
|
||||
else {
|
||||
tmp = g_strdup_printf ("%u", metric);
|
||||
svSetValue (routefile, metric_key, tmp, FALSE);
|
||||
g_free (tmp);
|
||||
}
|
||||
}
|
||||
|
||||
g_free (addr_key);
|
||||
g_free (netmask_key);
|
||||
g_free (gw_key);
|
||||
g_free (metric_key);
|
||||
}
|
||||
if (svWriteFile (routefile, 0644)) {
|
||||
g_set_error (error, ifcfg_plugin_error_quark (), 0,
|
||||
"Could not update route file '%s'", routefile->fileName);
|
||||
svCloseFile (routefile);
|
||||
goto out;
|
||||
}
|
||||
svCloseFile (routefile);
|
||||
} else {
|
||||
write_route_file_legacy (route_path, s_ip4, error);
|
||||
g_free (route_path);
|
||||
if (error && *error)
|
||||
goto out;
|
||||
}
|
||||
|
||||
success = TRUE;
|
||||
|
||||
out:
|
||||
return success;
|
||||
}
|
||||
|
||||
static char *
|
||||
|
|
@ -1005,6 +1149,7 @@ write_connection (NMConnection *connection,
|
|||
const char *ifcfg_dir,
|
||||
const char *filename,
|
||||
const char *keyfile,
|
||||
const char *routefile,
|
||||
char **out_filename,
|
||||
GError **error)
|
||||
{
|
||||
|
|
@ -1105,7 +1250,7 @@ writer_new_connection (NMConnection *connection,
|
|||
char **out_filename,
|
||||
GError **error)
|
||||
{
|
||||
return write_connection (connection, ifcfg_dir, NULL, NULL, out_filename, error);
|
||||
return write_connection (connection, ifcfg_dir, NULL, NULL, NULL, out_filename, error);
|
||||
}
|
||||
|
||||
gboolean
|
||||
|
|
@ -1113,8 +1258,9 @@ writer_update_connection (NMConnection *connection,
|
|||
const char *ifcfg_dir,
|
||||
const char *filename,
|
||||
const char *keyfile,
|
||||
const char *routefile,
|
||||
GError **error)
|
||||
{
|
||||
return write_connection (connection, ifcfg_dir, filename, keyfile, NULL, error);
|
||||
return write_connection (connection, ifcfg_dir, filename, keyfile, routefile, NULL, error);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -34,6 +34,7 @@ gboolean writer_update_connection (NMConnection *connection,
|
|||
const char *ifcfg_dir,
|
||||
const char *filename,
|
||||
const char *keyfile,
|
||||
const char *routefile,
|
||||
GError **error);
|
||||
|
||||
#endif /* _WRITER_H_ */
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue