diff --git a/configure.ac b/configure.ac index 45e236555a..2d59fa1b9c 100644 --- a/configure.ac +++ b/configure.ac @@ -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 diff --git a/libnm-util/nm-setting-8021x.c b/libnm-util/nm-setting-8021x.c index 19c86994b5..eea6ba5e7c 100644 --- a/libnm-util/nm-setting-8021x.c +++ b/libnm-util/nm-setting-8021x.c @@ -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; diff --git a/libnm-util/tests/Makefile.am b/libnm-util/tests/Makefile.am index e805199f80..378a7388a4 100644 --- a/libnm-util/tests/Makefile.am +++ b/libnm-util/tests/Makefile.am @@ -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 diff --git a/libnm-util/tests/certs/Makefile.am b/libnm-util/tests/certs/Makefile.am index b0dda3658f..4cd8a24bc6 100644 --- a/libnm-util/tests/certs/Makefile.am +++ b/libnm-util/tests/certs/Makefile.am @@ -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 diff --git a/libnm-util/tests/certs/test-key-only-decrypted.der b/libnm-util/tests/certs/test-key-only-decrypted.der new file mode 100644 index 0000000000..c8652537a6 Binary files /dev/null and b/libnm-util/tests/certs/test-key-only-decrypted.der differ diff --git a/libnm-util/tests/certs/test-key-only.pem b/libnm-util/tests/certs/test-key-only.pem new file mode 100644 index 0000000000..5ef530e9ab --- /dev/null +++ b/libnm-util/tests/certs/test-key-only.pem @@ -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 + diff --git a/libnm-util/tests/test-setting-8021x.c b/libnm-util/tests/test-setting-8021x.c new file mode 100644 index 0000000000..6202a1427f --- /dev/null +++ b/libnm-util/tests/test-setting-8021x.c @@ -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 +#include +#include + +#include "nm-test-helpers.h" +#include + +#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: [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; +} + diff --git a/src/supplicant-manager/Makefile.am b/src/supplicant-manager/Makefile.am index c6b623933f..540ef76481 100644 --- a/src/supplicant-manager/Makefile.am +++ b/src/supplicant-manager/Makefile.am @@ -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) \ diff --git a/src/supplicant-manager/gnome-keyring-md5.c b/src/supplicant-manager/gnome-keyring-md5.c deleted file mode 100644 index 0a3dd71dc0..0000000000 --- a/src/supplicant-manager/gnome-keyring-md5.c +++ /dev/null @@ -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 - -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<>(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; -} - diff --git a/src/supplicant-manager/gnome-keyring-md5.h b/src/supplicant-manager/gnome-keyring-md5.h deleted file mode 100644 index 3dff998458..0000000000 --- a/src/supplicant-manager/gnome-keyring-md5.h +++ /dev/null @@ -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 - -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 */ diff --git a/src/supplicant-manager/nm-supplicant-config.c b/src/supplicant-manager/nm-supplicant-config.c index 3bf92794d2..94bfbadf2d 100644 --- a/src/supplicant-manager/nm-supplicant-config.c +++ b/src/supplicant-manager/nm-supplicant-config.c @@ -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; diff --git a/system-settings/plugins/ifcfg-rh/Makefile.am b/system-settings/plugins/ifcfg-rh/Makefile.am index 2368b308a8..9998236fb7 100644 --- a/system-settings/plugins/ifcfg-rh/Makefile.am +++ b/system-settings/plugins/ifcfg-rh/Makefile.am @@ -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 \ diff --git a/system-settings/plugins/ifcfg-rh/common.h b/system-settings/plugins/ifcfg-rh/common.h index 33d52910f1..d16e881954 100644 --- a/system-settings/plugins/ifcfg-rh/common.h +++ b/system-settings/plugins/ifcfg-rh/common.h @@ -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" diff --git a/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c b/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c index cb8371e731..0abf6d4565 100644 --- a/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c +++ b/system-settings/plugins/ifcfg-rh/nm-ifcfg-connection.c @@ -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); } diff --git a/system-settings/plugins/ifcfg-rh/reader.c b/system-settings/plugins/ifcfg-rh/reader.c index 28b28d594d..33e822022f 100644 --- a/system-settings/plugins/ifcfg-rh/reader.c +++ b/system-settings/plugins/ifcfg-rh/reader.c @@ -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- 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); diff --git a/system-settings/plugins/ifcfg-rh/reader.h b/system-settings/plugins/ifcfg-rh/reader.h index f453045571..a5df59c632 100644 --- a/system-settings/plugins/ifcfg-rh/reader.h +++ b/system-settings/plugins/ifcfg-rh/reader.h @@ -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); diff --git a/system-settings/plugins/ifcfg-rh/sha1.c b/system-settings/plugins/ifcfg-rh/sha1.c deleted file mode 100644 index f7ceaa60df..0000000000 --- a/system-settings/plugins/ifcfg-rh/sha1.c +++ /dev/null @@ -1,692 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * 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 -#include - -#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 -100% Public Domain - ------------------ -Modified 7/98 -By James H. Brown -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 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 -Still 100% public domain - -1- Removed #include 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 -Still 100% PD -Modified to run on Compaq Alpha hardware. - ------------------ -Modified 4/01 -By Jouni Malinen -Minor changes to match the coding style used in Dynamics. - -Modified September 24, 2004 -By Jouni Malinen -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 */ diff --git a/system-settings/plugins/ifcfg-rh/sha1.h b/system-settings/plugins/ifcfg-rh/sha1.h deleted file mode 100644 index 40863c860f..0000000000 --- a/system-settings/plugins/ifcfg-rh/sha1.h +++ /dev/null @@ -1,34 +0,0 @@ -/* - * SHA1 hash implementation and interface functions - * Copyright (c) 2003-2005, Jouni Malinen - * - * 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 - - -#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 */ diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am b/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am index b6473d2caa..80a4054a2d 100644 --- a/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/Makefile.am @@ -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 + diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy new file mode 100644 index 0000000000..606f56b798 --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-static-routes-legacy @@ -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 diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto new file mode 100644 index 0000000000..42ee200afc --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wifi-open-auto @@ -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 diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes new file mode 100644 index 0000000000..7faf49bdae --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes @@ -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 diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy new file mode 100644 index 0000000000..7faf49bdae --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/ifcfg-test-wired-static-routes-legacy @@ -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 diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy b/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy new file mode 100644 index 0000000000..3db42ab5bc --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-static-routes-legacy @@ -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 diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes b/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes new file mode 100644 index 0000000000..ee2a32d8e2 --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes @@ -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 diff --git a/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy b/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy new file mode 100644 index 0000000000..cb7d42bde2 --- /dev/null +++ b/system-settings/plugins/ifcfg-rh/tests/network-scripts/route-test-wired-static-routes-legacy @@ -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 + diff --git a/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c b/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c index fd80a64ef9..1d3b8d44a7 100644 --- a/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c +++ b/system-settings/plugins/ifcfg-rh/tests/test-ifcfg-rh.c @@ -186,6 +186,7 @@ test_read_minimal (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -200,6 +201,7 @@ test_read_minimal (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -316,6 +318,7 @@ test_read_unmanaged (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -330,6 +333,7 @@ test_read_unmanaged (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -428,6 +432,7 @@ test_read_wired_static (const char *file, const char *expected_id) NMSettingIP4Config *s_ip4; char *unmanaged = FALSE; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const GByteArray *array; @@ -446,6 +451,7 @@ test_read_wired_static (const char *file, const char *expected_id) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -625,6 +631,7 @@ test_read_wired_dhcp (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const GByteArray *array; @@ -642,6 +649,7 @@ test_read_wired_dhcp (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -793,6 +801,7 @@ test_read_wired_global_gateway (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -808,6 +817,7 @@ test_read_wired_global_gateway (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -915,6 +925,7 @@ test_read_wired_never_default (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -926,6 +937,7 @@ test_read_wired_never_default (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1009,6 +1021,7 @@ test_read_wired_defroute_no (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1020,6 +1033,7 @@ test_read_wired_defroute_no (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1097,6 +1111,7 @@ test_read_wired_defroute_no_gatewaydev_yes (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1108,6 +1123,7 @@ test_read_wired_defroute_no_gatewaydev_yes (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1181,6 +1197,369 @@ test_read_wired_defroute_no_gatewaydev_yes (void) g_object_unref (connection); } +#define TEST_IFCFG_WIRED_STATIC_ROUTES TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-routes" + +static void +test_read_wired_static_routes (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + char *unmanaged = NULL; + char *keyfile = NULL; + char *routefile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + NMIP4Route *ip4_route; + struct in_addr addr; + const char *expected_id = "System test-wired-static-routes"; + const char *expected_dst1 = "11.22.33.0"; + const char *expected_dst2 = "44.55.66.77"; + const char *expected_gw1 = "192.168.1.5"; + const char *expected_gw2 = "192.168.1.7"; + + connection = connection_from_file (TEST_IFCFG_WIRED_STATIC_ROUTES, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile, + &routefile, + &error, + &ignore_error); + + ASSERT (connection != NULL, + "wired-static-routes-read", + "failed to read %s: %s", + TEST_IFCFG_WIRED_STATIC_ROUTES, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wired-static-routes-verify", "failed to verify %s: %s", + TEST_IFCFG_WIRED_STATIC_ROUTES, error->message); + + ASSERT (unmanaged == NULL, + "wired-static-routes-verify", + "failed to verify %s: unexpected unmanaged value", + TEST_IFCFG_WIRED_STATIC_ROUTES); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wired-static-routes-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wired-static-routes-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wired-static-routes-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRED SETTING ===== */ + + s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED)); + ASSERT (s_wired != NULL, + "wired-static-routes-verify-wired", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_WIRED_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "wired-static-routes-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME); + + /* Method */ + tmp = nm_setting_ip4_config_get_method (s_ip4); + ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + + /* Routes */ + ASSERT (nm_setting_ip4_config_get_num_routes (s_ip4) == 2, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ip4_route = nm_setting_ip4_config_get_route (s_ip4, 0); + ASSERT (ip4_route, + "wired-static-routes-verify-ip4", "failed to verify %s: missing IP4 route #1", + TEST_IFCFG_WIRED_STATIC_ROUTES); + + ASSERT (inet_pton (AF_INET, expected_dst1, &addr) > 0, + "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert destination IP address #1", + TEST_IFCFG_WIRED_STATIC_ROUTES); + ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_prefix (ip4_route) == 24, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected destination route #1 prefix", + TEST_IFCFG_WIRED_STATIC_ROUTES); + + ASSERT (inet_pton (AF_INET, expected_gw1, &addr) > 0, + "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #1", + TEST_IFCFG_WIRED_STATIC_ROUTES); + ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ip4_route = nm_setting_ip4_config_get_route (s_ip4, 1); + ASSERT (ip4_route, + "wired-static-routes-verify-ip4", "failed to verify %s: missing IP4 route #2", + TEST_IFCFG_WIRED_STATIC_ROUTES); + + ASSERT (inet_pton (AF_INET, expected_dst2, &addr) > 0, + "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert destination IP address #2", + TEST_IFCFG_WIRED_STATIC_ROUTES); + ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_prefix (ip4_route) == 32, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected destination route #2 prefix", + TEST_IFCFG_WIRED_STATIC_ROUTES); + + ASSERT (inet_pton (AF_INET, expected_gw2, &addr) > 0, + "wired-static-routes-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #2", + TEST_IFCFG_WIRED_STATIC_ROUTES); + ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2", + TEST_IFCFG_WIRED_STATIC_ROUTES, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + ASSERT (nm_ip4_route_get_metric (ip4_route) == 3, + "wired-static-routes-verify-ip4", "failed to verify %s: unexpected route metric #2", + TEST_IFCFG_WIRED_STATIC_ROUTES); + + g_free (keyfile); + g_free (routefile); + g_object_unref (connection); +} + +#define TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wired-static-routes-legacy" + +static void +test_read_wired_static_routes_legacy (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + char *unmanaged = NULL; + char *keyfile = NULL; + char *routefile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + NMIP4Route *ip4_route; + struct in_addr addr; + const char *expected_id = "System test-wired-static-routes-legacy"; + const char *expected_dst1 = "21.31.41.0"; + const char *expected_dst2 = "32.42.52.62"; + const char *expected_dst3 = "43.53.0.0"; + const char *expected_gw1 = "9.9.9.9"; + const char *expected_gw2 = "8.8.8.8"; + const char *expected_gw3 = "7.7.7.7"; + + connection = connection_from_file (TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile, + &routefile, + &error, + &ignore_error); + + ASSERT (connection != NULL, + "wired-static-routes-legacy-read", + "failed to read %s: %s", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wired-static-routes-legacy-verify", "failed to verify %s: %s", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, error->message); + + ASSERT (unmanaged == NULL, + "wired-static-routes-legacy-verify", + "failed to verify %s: unexpected unmanaged value", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wired-static-routes-legacy-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wired-static-routes-legacy-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wired-static-routes-legacy-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRED SETTING ===== */ + + s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED)); + ASSERT (s_wired != NULL, + "wired-static-routes-legacy-verify-wired", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_WIRED_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME); + + /* Method */ + tmp = nm_setting_ip4_config_get_method (s_ip4); + ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_MANUAL) == 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + + /* Routes */ + ASSERT (nm_setting_ip4_config_get_num_routes (s_ip4) == 3, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + /* Route #1 */ + ip4_route = nm_setting_ip4_config_get_route (s_ip4, 0); + ASSERT (ip4_route, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: missing IP4 route #1", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + ASSERT (inet_pton (AF_INET, expected_dst1, &addr) > 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert destination IP address #1", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_prefix (ip4_route) == 24, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected destination route #1 prefix", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + ASSERT (inet_pton (AF_INET, expected_gw1, &addr) > 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #1", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #1", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_metric (ip4_route) == 1, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected destination route #1 metric", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + /* Route #2 */ + ip4_route = nm_setting_ip4_config_get_route (s_ip4, 1); + ASSERT (ip4_route, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: missing IP4 route #2", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + ASSERT (inet_pton (AF_INET, expected_dst2, &addr) > 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert destination IP address #2", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_prefix (ip4_route) == 32, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected destination route #2 prefix", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + ASSERT (inet_pton (AF_INET, expected_gw2, &addr) > 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #2", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #2", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_metric (ip4_route) == 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected destination route #2 metric", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + /* Route #3 */ + ip4_route = nm_setting_ip4_config_get_route (s_ip4, 2); + ASSERT (ip4_route, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: missing IP4 route #3", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + ASSERT (inet_pton (AF_INET, expected_dst3, &addr) > 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert destination IP address #3", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + ASSERT (nm_ip4_route_get_dest (ip4_route) == addr.s_addr, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #3", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_prefix (ip4_route) == 16, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected destination route #3 prefix", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + ASSERT (inet_pton (AF_INET, expected_gw3, &addr) > 0, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: couldn't convert next hop IP address #3", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + ASSERT (nm_ip4_route_get_next_hop (ip4_route) == addr.s_addr, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value #3", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_ROUTES); + + ASSERT (nm_ip4_route_get_metric (ip4_route) == 3, + "wired-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected destination route #3 metric", + TEST_IFCFG_WIRED_STATIC_ROUTES_LEGACY); + + g_free (keyfile); + g_free (routefile); + g_object_unref (connection); +} + #define TEST_IFCFG_ONBOOT_NO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-onboot-no" static void @@ -1190,6 +1569,7 @@ test_read_onboot_no (void) NMSettingConnection *s_con; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; @@ -1199,6 +1579,7 @@ test_read_onboot_no (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1241,6 +1622,7 @@ test_read_wired_8021x_peap_mschapv2 (void) NMSetting8021x *tmp_8021x; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1256,6 +1638,7 @@ test_read_wired_8021x_peap_mschapv2 (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1421,6 +1804,7 @@ test_read_wifi_open (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1438,6 +1822,7 @@ test_read_wifi_open (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1584,6 +1969,82 @@ test_read_wifi_open (void) g_object_unref (connection); } +#define TEST_IFCFG_WIFI_OPEN_AUTO TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-auto" + +static void +test_read_wifi_open_auto (void) +{ + NMConnection *connection; + NMSettingConnection *s_con; + NMSettingWireless *s_wireless; + char *unmanaged = NULL; + char *keyfile = NULL; + char *routefile = NULL; + gboolean ignore_error = FALSE; + GError *error = NULL; + const char *tmp; + const char *expected_id = "System blahblah (test-wifi-open-auto)"; + const char *expected_mode = "infrastructure"; + + connection = connection_from_file (TEST_IFCFG_WIFI_OPEN_AUTO, + NULL, + TYPE_WIRELESS, + NULL, + &unmanaged, + &keyfile, + &routefile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "wifi-open-auto-read", "failed to read %s: %s", TEST_IFCFG_WIFI_OPEN_AUTO, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "wifi-open-auto-verify", "failed to verify %s: %s", TEST_IFCFG_WIFI_OPEN_AUTO, error->message); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "wifi-open-auto-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_OPEN_AUTO, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "wifi-open-auto-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_OPEN_AUTO, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + ASSERT (strcmp (tmp, expected_id) == 0, + "wifi-open-auto-verify-connection", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_OPEN_AUTO, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* ===== WIRELESS SETTING ===== */ + + s_wireless = NM_SETTING_WIRELESS (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRELESS)); + ASSERT (s_wireless != NULL, + "wifi-open-auto-verify-wireless", "failed to verify %s: missing %s setting", + TEST_IFCFG_WIFI_OPEN_AUTO, + NM_SETTING_WIRELESS_SETTING_NAME); + + tmp = nm_setting_wireless_get_mode (s_wireless); + ASSERT (tmp != NULL, + "wifi-open-auto-verify-wireless", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_WIFI_OPEN_AUTO, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MODE); + ASSERT (strcmp (tmp, expected_mode) == 0, + "wifi-open-auto-verify-wireless", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_WIFI_OPEN_AUTO, + NM_SETTING_WIRELESS_SETTING_NAME, + NM_SETTING_WIRELESS_MODE); + + g_object_unref (connection); +} + #define TEST_IFCFG_WIFI_OPEN_SSID_HEX TEST_IFCFG_DIR"/network-scripts/ifcfg-test-wifi-open-ssid-hex" static void @@ -1594,6 +2055,7 @@ test_read_wifi_open_ssid_hex (void) NMSettingWireless *s_wireless; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1607,6 +2069,7 @@ test_read_wifi_open_ssid_hex (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1671,6 +2134,7 @@ test_read_wifi_open_ssid_bad (const char *file, const char *test) NMConnection *connection; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; @@ -1680,6 +2144,7 @@ test_read_wifi_open_ssid_bad (const char *file, const char *test) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection == NULL, test, "unexpected success reading %s", file); @@ -1696,6 +2161,7 @@ test_read_wifi_open_ssid_quoted (void) NMSettingWireless *s_wireless; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1709,6 +2175,7 @@ test_read_wifi_open_ssid_quoted (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -1779,6 +2246,7 @@ test_read_wifi_wep (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -1797,6 +2265,7 @@ test_read_wifi_wep (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -2040,6 +2509,7 @@ test_read_wifi_wep_adhoc (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -2058,6 +2528,7 @@ test_read_wifi_wep_adhoc (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -2299,6 +2770,7 @@ test_read_wifi_leap (void) NMSettingWirelessSecurity *s_wsec; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -2312,6 +2784,7 @@ test_read_wifi_leap (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -2432,6 +2905,7 @@ test_read_wifi_wpa_psk (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -2460,6 +2934,7 @@ test_read_wifi_wpa_psk (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -2743,6 +3218,7 @@ test_read_wifi_wpa_psk_adhoc (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -2759,6 +3235,7 @@ test_read_wifi_wpa_psk_adhoc (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -2927,6 +3404,7 @@ test_read_wifi_wpa_psk_hex (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -2942,6 +3420,7 @@ test_read_wifi_wpa_psk_hex (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -3077,6 +3556,7 @@ test_read_wifi_wpa_eap_tls (void) NMSetting8021x *s_8021x; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp, *password; @@ -3089,6 +3569,7 @@ test_read_wifi_wpa_eap_tls (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -3219,6 +3700,7 @@ test_read_wifi_wpa_eap_ttls_tls (void) NMSetting8021x *s_8021x; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp, *password; @@ -3231,6 +3713,7 @@ test_read_wifi_wpa_eap_ttls_tls (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -3383,6 +3866,7 @@ test_read_wifi_wep_eap_ttls_chap (void) NMSetting8021x *s_8021x; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -3396,6 +3880,7 @@ test_read_wifi_wep_eap_ttls_chap (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -3554,6 +4039,7 @@ test_write_wired_static (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; connection = nm_connection_new (); @@ -3647,6 +4133,7 @@ test_write_wired_static (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -3679,6 +4166,7 @@ test_write_wired_dhcp (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; connection = nm_connection_new (); @@ -3746,6 +4234,7 @@ test_write_wired_dhcp (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -3764,6 +4253,312 @@ test_write_wired_dhcp (void) g_object_unref (reread); } +#define TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY TEST_IFCFG_DIR"/network-scripts/ifcfg-test-static-routes-legacy" + +static void +test_read_write_static_routes_legacy (void) +{ + NMConnection *connection, *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + char *unmanaged = NULL; + char *testfile = NULL; + char *keyfile = NULL; + char *keyfile2 = NULL; + char *routefile = NULL; + char *routefile2 = NULL; + gboolean ignore_error = FALSE; + gboolean success; + GError *error = NULL; + const char *tmp; + + connection = connection_from_file (TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile, + &routefile, + &error, + &ignore_error); + ASSERT (connection != NULL, + "read-write-static-routes-legacy-read", "failed to read %s: %s", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, error->message); + + ASSERT (nm_connection_verify (connection, &error), + "read-write-static-routes-legacy-verify", "failed to verify %s: %s", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, error->message); + + /* ===== CONNECTION SETTING ===== */ + + s_con = NM_SETTING_CONNECTION (nm_connection_get_setting (connection, NM_TYPE_SETTING_CONNECTION)); + ASSERT (s_con != NULL, + "read-write-static-routes-legacy-verify-connection", "failed to verify %s: missing %s setting", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_CONNECTION_SETTING_NAME); + + /* ID */ + tmp = nm_setting_connection_get_id (s_con); + ASSERT (tmp != NULL, + "read-write-static-routes-legacy-verify-connection", "failed to verify %s: missing %s / %s key", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_ID); + + /* Autoconnect */ + ASSERT (nm_setting_connection_get_autoconnect (s_con) == TRUE, + "read_write-static-routes-legacy-verify-connection", "failed to verify %s: unexpected %s /%s key value", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_CONNECTION_SETTING_NAME, + NM_SETTING_CONNECTION_AUTOCONNECT); + + /* ===== WIRED SETTING ===== */ + + s_wired = NM_SETTING_WIRED (nm_connection_get_setting (connection, NM_TYPE_SETTING_WIRED)); + ASSERT (s_wired != NULL, + "read-write-static-routes-legacy-verify-wired", "failed to verify %s: missing %s setting", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_WIRED_SETTING_NAME); + + /* ===== IPv4 SETTING ===== */ + + s_ip4 = NM_SETTING_IP4_CONFIG (nm_connection_get_setting (connection, NM_TYPE_SETTING_IP4_CONFIG)); + ASSERT (s_ip4 != NULL, + "read-write-static-routes-legacy-verify-ip4", "failed to verify %s: missing %s setting", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME); + + /* Method */ + tmp = nm_setting_ip4_config_get_method (s_ip4); + ASSERT (strcmp (tmp, NM_SETTING_IP4_CONFIG_METHOD_AUTO) == 0, + "read-write-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_METHOD); + + ASSERT (nm_setting_ip4_config_get_never_default (s_ip4) == FALSE, + "read-write-static-routes-legacy-verify-ip4", "failed to verify %s: unexpected %s / %s key value", + TEST_IFCFG_READ_WRITE_STATIC_ROUTES_LEGACY, + NM_SETTING_IP4_CONFIG_SETTING_NAME, + NM_SETTING_IP4_CONFIG_NEVER_DEFAULT); + + /* Save the ifcfg; use a special different scratch dir to ensure that + * we can clean up after the written connection in both the original + * source tree and for 'make distcheck'. + */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/tmp", + &testfile, + &error); + ASSERT (success == TRUE, + "read-write-static-routes-legacy-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "read-write-static-routes-legacy-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile2, + &routefile2, + &error, + &ignore_error); + unlink (testfile); + unlink (routefile2); + + ASSERT (reread != NULL, + "read-write-static-routes-legacy-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (routefile2 != NULL, + "read-write-static-routes-legacy-reread", "expected routefile for '%s'", testfile); + + ASSERT (nm_connection_verify (reread, &error), + "read-write-static-routes-legacy-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "read-write-static-routes-legacy-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_free (keyfile); + g_free (keyfile2); + g_free (routefile); + g_free (routefile2); + g_object_unref (connection); + g_object_unref (reread); +} + +static void +test_write_wired_static_routes (void) +{ + NMConnection *connection; + NMConnection *reread; + NMSettingConnection *s_con; + NMSettingWired *s_wired; + NMSettingIP4Config *s_ip4; + static unsigned char tmpmac[] = { 0x31, 0x33, 0x33, 0x37, 0xbe, 0xcd }; + GByteArray *mac; + guint32 mtu = 1492; + char *uuid; + guint64 timestamp = 0x12344433L; + const guint32 ip1 = htonl (0x01010103); + const guint32 ip2 = htonl (0x01010105); + const guint32 gw = htonl (0x01010101); + const guint32 dns1 = htonl (0x04020201); + const guint32 dns2 = htonl (0x04020202); + const guint32 route_dst1 = htonl (0x01020300); + const guint32 route_dst2= htonl (0x03020100); + const guint32 route_gw1 = htonl (0xdeadbeef); + const guint32 route_gw2 = htonl (0xcafeabbe); + const guint32 prefix = 24; + const char *dns_search1 = "foobar.com"; + const char *dns_search2 = "lab.foobar.com"; + NMIP4Address *addr; + NMIP4Route *route; + gboolean success; + GError *error = NULL; + char *testfile = NULL; + char *unmanaged = NULL; + char *keyfile = NULL; + char *routefile = NULL; + gboolean ignore_error = FALSE; + + connection = nm_connection_new (); + ASSERT (connection != NULL, + "wired-static-routes-write", "failed to allocate new connection"); + + /* Connection setting */ + s_con = (NMSettingConnection *) nm_setting_connection_new (); + ASSERT (s_con != NULL, + "wired-static-routes-write", "failed to allocate new %s setting", + NM_SETTING_CONNECTION_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_con)); + + uuid = nm_utils_uuid_generate (); + g_object_set (s_con, + NM_SETTING_CONNECTION_ID, "Test Write Wired Static Routes", + NM_SETTING_CONNECTION_UUID, uuid, + NM_SETTING_CONNECTION_AUTOCONNECT, TRUE, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRED_SETTING_NAME, + NM_SETTING_CONNECTION_TIMESTAMP, timestamp, + NULL); + g_free (uuid); + + /* Wired setting */ + s_wired = (NMSettingWired *) nm_setting_wired_new (); + ASSERT (s_wired != NULL, + "wired-static-routes-write", "failed to allocate new %s setting", + NM_SETTING_WIRED_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_wired)); + + mac = g_byte_array_sized_new (sizeof (tmpmac)); + g_byte_array_append (mac, &tmpmac[0], sizeof (tmpmac)); + + g_object_set (s_wired, + NM_SETTING_WIRED_MAC_ADDRESS, mac, + NM_SETTING_WIRED_MTU, mtu, + NULL); + g_byte_array_free (mac, TRUE); + + /* IP4 setting */ + s_ip4 = (NMSettingIP4Config *) nm_setting_ip4_config_new (); + ASSERT (s_ip4 != NULL, + "wired-static-routes-write", "failed to allocate new %s setting", + NM_SETTING_IP4_CONFIG_SETTING_NAME); + nm_connection_add_setting (connection, NM_SETTING (s_ip4)); + + g_object_set (s_ip4, + NM_SETTING_IP4_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_MANUAL, + NULL); + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip1); + nm_ip4_address_set_prefix (addr, prefix); + nm_ip4_address_set_gateway (addr, gw); + nm_setting_ip4_config_add_address (s_ip4, addr); + nm_ip4_address_unref (addr); + + addr = nm_ip4_address_new (); + nm_ip4_address_set_address (addr, ip2); + nm_ip4_address_set_prefix (addr, prefix); + nm_ip4_address_set_gateway (addr, gw); + nm_setting_ip4_config_add_address (s_ip4, addr); + nm_ip4_address_unref (addr); + + /* Write out routes */ + route = nm_ip4_route_new (); + nm_ip4_route_set_dest (route, route_dst1); + nm_ip4_route_set_prefix (route, prefix); + nm_ip4_route_set_next_hop (route, route_gw1); + nm_setting_ip4_config_add_route (s_ip4, route); + nm_ip4_route_unref (route); + + route = nm_ip4_route_new (); + nm_ip4_route_set_dest (route, route_dst2); + nm_ip4_route_set_prefix (route, prefix); + nm_ip4_route_set_next_hop (route, route_gw2); + nm_ip4_route_set_metric (route, 77); + nm_setting_ip4_config_add_route (s_ip4, route); + nm_ip4_route_unref (route); + + nm_setting_ip4_config_add_dns (s_ip4, dns1); + nm_setting_ip4_config_add_dns (s_ip4, dns2); + + nm_setting_ip4_config_add_dns_search (s_ip4, dns_search1); + nm_setting_ip4_config_add_dns_search (s_ip4, dns_search2); + + ASSERT (nm_connection_verify (connection, &error) == TRUE, + "wired-static-routes-write", "failed to verify connection: %s", + (error && error->message) ? error->message : "(unknown)"); + + /* Save the ifcfg */ + success = writer_new_connection (connection, + TEST_SCRATCH_DIR "/network-scripts/", + &testfile, + &error); + ASSERT (success == TRUE, + "wired-static-routes-write", "failed to write connection to disk: %s", + (error && error->message) ? error->message : "(unknown)"); + + ASSERT (testfile != NULL, + "wired-static-routes-write", "didn't get ifcfg file path back after writing connection"); + + /* re-read the connection for comparison */ + reread = connection_from_file (testfile, + NULL, + TYPE_ETHERNET, + NULL, + &unmanaged, + &keyfile, + &routefile, + &error, + &ignore_error); + unlink (testfile); + + ASSERT (reread != NULL, + "wired-static-routes-write-reread", "failed to read %s: %s", testfile, error->message); + + ASSERT (routefile != NULL, + "wired-static-routes-write-reread", "expected routefile for '%s'", testfile); + unlink (routefile); + + ASSERT (nm_connection_verify (reread, &error), + "wired-static-routes-write-reread-verify", "failed to verify %s: %s", testfile, error->message); + + ASSERT (nm_connection_compare (connection, reread, NM_SETTING_COMPARE_FLAG_EXACT) == TRUE, + "wired-static-routes-write", "written and re-read connection weren't the same."); + + g_free (testfile); + g_free (keyfile); + g_free (routefile); + g_object_unref (connection); + g_object_unref (reread); +} + static void test_write_wired_dhcp_8021x_peap_mschapv2 (void) { @@ -3779,6 +4574,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; connection = nm_connection_new (); @@ -3866,6 +4662,7 @@ test_write_wired_dhcp_8021x_peap_mschapv2 (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -3902,6 +4699,7 @@ test_write_wifi_open (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 }; @@ -3991,6 +4789,7 @@ test_write_wifi_open (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4023,6 +4822,7 @@ test_write_wifi_open_hex_ssid (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd }; @@ -4096,6 +4896,7 @@ test_write_wifi_open_hex_ssid (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4129,6 +4930,7 @@ test_write_wifi_wep (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = "blahblah"; @@ -4221,6 +5023,7 @@ test_write_wifi_wep (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4266,6 +5069,7 @@ test_write_wifi_wep_adhoc (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = "blahblah"; @@ -4366,6 +5170,7 @@ test_write_wifi_wep_adhoc (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4411,6 +5216,7 @@ test_write_wifi_leap (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = "blahblah"; @@ -4500,6 +5306,7 @@ test_write_wifi_leap (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4550,6 +5357,7 @@ test_write_wifi_wpa_psk (const char *name, char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = "blahblah"; @@ -4653,6 +5461,7 @@ test_write_wifi_wpa_psk (const char *name, NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4692,6 +5501,7 @@ test_write_wifi_wpa_psk_adhoc (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const unsigned char ssid_data[] = "blahblah"; @@ -4798,6 +5608,7 @@ test_write_wifi_wpa_psk_adhoc (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4836,6 +5647,7 @@ test_write_wifi_wpa_eap_tls (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const char *ssid_data = "blahblah"; @@ -4961,6 +5773,7 @@ test_write_wifi_wpa_eap_tls (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -4999,6 +5812,7 @@ test_write_wifi_wpa_eap_ttls_tls (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const char *ssid_data = "blahblah"; @@ -5142,6 +5956,7 @@ test_write_wifi_wpa_eap_ttls_tls (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -5180,6 +5995,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void) char *testfile = NULL; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GByteArray *ssid; const char *ssid_data = "blahblah"; @@ -5295,6 +6111,7 @@ test_write_wifi_wpa_eap_ttls_mschapv2 (void) NULL, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); unlink (testfile); @@ -5328,6 +6145,7 @@ test_read_ibft_dhcp (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -5342,6 +6160,7 @@ test_read_ibft_dhcp (void) TEST_IFCFG_DIR "/iscsiadm-test-dhcp", &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -5459,6 +6278,7 @@ test_read_ibft_static (void) NMSettingIP4Config *s_ip4; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; const char *tmp; @@ -5479,6 +6299,7 @@ test_read_ibft_static (void) TEST_IFCFG_DIR "/iscsiadm-test-static", &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection != NULL, @@ -5662,6 +6483,7 @@ test_read_ibft_malformed (const char *name, const char *iscsiadm_path) NMConnection *connection; char *unmanaged = NULL; char *keyfile = NULL; + char *routefile = NULL; gboolean ignore_error = FALSE; GError *error = NULL; @@ -5671,6 +6493,7 @@ test_read_ibft_malformed (const char *name, const char *iscsiadm_path) iscsiadm_path, &unmanaged, &keyfile, + &routefile, &error, &ignore_error); ASSERT (connection == NULL, @@ -5971,9 +6794,12 @@ int main (int argc, char **argv) test_read_wired_never_default (); test_read_wired_defroute_no (); test_read_wired_defroute_no_gatewaydev_yes (); + test_read_wired_static_routes (); + test_read_wired_static_routes_legacy (); test_read_onboot_no (); test_read_wired_8021x_peap_mschapv2 (); test_read_wifi_open (); + test_read_wifi_open_auto (); test_read_wifi_open_ssid_hex (); test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_BAD_HEX, "wifi-open-ssid-bad-hex-read"); test_read_wifi_open_ssid_bad (TEST_IFCFG_WIFI_OPEN_SSID_LONG_HEX, "wifi-open-ssid-long-hex-read"); @@ -5990,6 +6816,8 @@ int main (int argc, char **argv) test_read_wifi_wep_eap_ttls_chap (); test_write_wired_static (); + test_write_wired_static_routes (); + test_read_write_static_routes_legacy (); test_write_wired_dhcp (); test_write_wired_dhcp_8021x_peap_mschapv2 (); test_write_wifi_open (); diff --git a/system-settings/plugins/ifcfg-rh/utils.c b/system-settings/plugins/ifcfg-rh/utils.c index 956c53e26a..b0e5a3379b 100644 --- a/system-settings/plugins/ifcfg-rh/utils.c +++ b/system-settings/plugins/ifcfg-rh/utils.c @@ -22,7 +22,6 @@ #include #include #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- in the form . + * Currently used for: keys- + * route- + */ 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=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; +} + diff --git a/system-settings/plugins/ifcfg-rh/utils.h b/system-settings/plugins/ifcfg-rh/utils.h index 3424c6078d..2c7eaee62e 100644 --- a/system-settings/plugins/ifcfg-rh/utils.h +++ b/system-settings/plugins/ifcfg-rh/utils.h @@ -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_ */ diff --git a/system-settings/plugins/ifcfg-rh/writer.c b/system-settings/plugins/ifcfg-rh/writer.c index d3f00337ca..1c3331da66 100644 --- a/system-settings/plugins/ifcfg-rh/writer.c +++ b/system-settings/plugins/ifcfg-rh/writer.c @@ -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- 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); } diff --git a/system-settings/plugins/ifcfg-rh/writer.h b/system-settings/plugins/ifcfg-rh/writer.h index edeac0cccc..2762705312 100644 --- a/system-settings/plugins/ifcfg-rh/writer.h +++ b/system-settings/plugins/ifcfg-rh/writer.h @@ -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_ */