supplicant: adjust fragment_size according to MTU (bgo #755145)

NetworkManager set wpa_supplicant's fragment_size option to 1300. But if MTU
was lower, wpa_supplicant failed with "l2_packet_send - sendto: Message too
long" due to fragmentation of EAP-TLS or EAP-PEAP packets.

Actually, MTU has to be 14 bytes bigger than the "fragment_size" parameter.

Ideally, wpa_supplicant would take MTU in the account and adjust the
fragmentation limit accordingly. See discussion in
http://lists.shmoo.com/pipermail/hostap/2015-August/033546.html

https://bugzilla.gnome.org/show_bug.cgi?id=755145
This commit is contained in:
Jiří Klimeš 2015-09-16 18:22:08 +02:00
parent d7b72b2a3e
commit 94bbe7465f
10 changed files with 204 additions and 9 deletions

View file

@ -1014,6 +1014,7 @@ src/dhcp-manager/Makefile
src/dhcp-manager/tests/Makefile
src/dnsmasq-manager/tests/Makefile
src/supplicant-manager/tests/Makefile
src/supplicant-manager/tests/certs/Makefile
src/ppp-manager/Makefile
src/settings/plugins/Makefile
src/settings/plugins/ifupdown/Makefile

View file

@ -566,15 +566,18 @@ build_supplicant_config (NMDeviceEthernet *self)
NMSupplicantConfig *config = NULL;
NMSetting8021x *security;
NMConnection *connection;
guint32 mtu;
connection = nm_device_get_applied_connection (NM_DEVICE (self));
g_assert (connection);
con_uuid = nm_connection_get_uuid (connection);
mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET,
nm_device_get_ifindex (NM_DEVICE (self)));
config = nm_supplicant_config_new ();
security = nm_connection_get_setting_802_1x (connection);
if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, TRUE)) {
if (!nm_supplicant_config_add_setting_8021x (config, security, con_uuid, mtu, TRUE)) {
_LOGW (LOGD_DEVICE, "Couldn't add 802.1X security setting to supplicant config.");
g_object_unref (config);
config = NULL;

View file

@ -2225,13 +2225,16 @@ build_supplicant_config (NMDeviceWifi *self,
if (s_wireless_sec) {
NMSetting8021x *s_8021x;
const char *con_uuid = nm_connection_get_uuid (connection);
guint32 mtu = nm_platform_link_get_mtu (NM_PLATFORM_GET,
nm_device_get_ifindex (NM_DEVICE (self)));
g_assert (con_uuid);
s_8021x = nm_connection_get_setting_802_1x (connection);
if (!nm_supplicant_config_add_setting_wireless_security (config,
s_wireless_sec,
s_8021x,
con_uuid)) {
con_uuid,
mtu)) {
_LOGE (LOGD_WIFI, "Couldn't add 802-11-wireless-security setting to supplicant config.");
goto error;
}

View file

@ -610,7 +610,8 @@ gboolean
nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
NMSettingWirelessSecurity *setting,
NMSetting8021x *setting_8021x,
const char *con_uuid)
const char *con_uuid,
guint32 mtu)
{
gboolean success = FALSE;
const char *key_mgmt, *auth_alg;
@ -727,7 +728,7 @@ nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
if (!strcmp (key_mgmt, "ieee8021x") || !strcmp (key_mgmt, "wpa-eap")) {
if (!setting_8021x)
return FALSE;
if (!nm_supplicant_config_add_setting_8021x (self, setting_8021x, con_uuid, FALSE))
if (!nm_supplicant_config_add_setting_8021x (self, setting_8021x, con_uuid, mtu, FALSE))
return FALSE;
}
@ -754,6 +755,7 @@ gboolean
nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
NMSetting8021x *setting,
const char *con_uuid,
guint32 mtu,
gboolean wired)
{
NMSupplicantConfigPrivate *priv;
@ -766,6 +768,8 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
guint32 i, num_eap;
gboolean fast_provisoning_allowed = FALSE;
const char *ca_path_override = NULL, *ca_cert_override = NULL;
guint32 frag, hdrs;
gs_free char *frag_str = NULL;
g_return_val_if_fail (NM_IS_SUPPLICANT_CONFIG (self), FALSE);
g_return_val_if_fail (setting != NULL, FALSE);
@ -817,8 +821,15 @@ nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
}
}
/* Drop the fragment size a bit for better compatibility */
if (!nm_supplicant_config_add_option (self, "fragment_size", "1300", -1, FALSE))
/* Adjust the fragment size according to MTU, but do not set it higher than 1280-14
* for better compatibility */
hdrs = 14; /* EAPOL + EAP-TLS */
frag = 1280 - hdrs;
if (mtu > hdrs)
frag = CLAMP (mtu - hdrs, 100, frag);
frag_str = g_strdup_printf ("%u", frag);
if (!nm_supplicant_config_add_option (self, "fragment_size", frag_str, -1, FALSE))
return FALSE;
phase1 = g_string_new (NULL);

View file

@ -70,13 +70,15 @@ gboolean nm_supplicant_config_add_setting_wireless (NMSupplicantConfig *self,
gboolean nm_supplicant_config_add_setting_wireless_security (NMSupplicantConfig *self,
NMSettingWirelessSecurity *setting,
NMSetting8021x *setting_8021x,
const char *con_uuid);
const char *con_uuid,
guint32 mtu);
gboolean nm_supplicant_config_add_no_security (NMSupplicantConfig *self);
gboolean nm_supplicant_config_add_setting_8021x (NMSupplicantConfig *self,
NMSetting8021x *setting,
const char *con_uuid,
guint32 mtu,
gboolean wired);
G_END_DECLS

View file

@ -1,3 +1,5 @@
SUBDIRS=certs
AM_CPPFLAGS = \
-I$(top_srcdir)/include \
-I$(top_srcdir)/libnm-core \
@ -7,6 +9,7 @@ AM_CPPFLAGS = \
-DG_LOG_DOMAIN=\""NetworkManager"\" \
-DNETWORKMANAGER_COMPILATION=NM_NETWORKMANAGER_COMPILATION_INSIDE_DAEMON \
-DNM_VERSION_MAX_ALLOWED=NM_VERSION_NEXT_STABLE \
-DTEST_CERT_DIR=\"$(srcdir)/certs/\" \
$(GLIB_CFLAGS)
noinst_PROGRAMS = test-supplicant-config

View file

@ -0,0 +1,6 @@
CERTS = \
test-ca-cert.pem \
test-cert.p12
EXTRA_DIST = $(CERTS)

View file

@ -0,0 +1,27 @@
-----BEGIN CERTIFICATE-----
MIIEjzCCA3egAwIBAgIJAOvnZPt59yIZMA0GCSqGSIb3DQEBBQUAMIGLMQswCQYD
VQQGEwJVUzESMBAGA1UECBMJQmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcw
FQYDVQQKEw5NeSBDb21wYW55IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UE
AxMEdGVzdDEcMBoGCSqGSIb3DQEJARYNdGVzdEB0ZXN0LmNvbTAeFw0wOTAzMTAx
NTEyMTRaFw0xOTAzMDgxNTEyMTRaMIGLMQswCQYDVQQGEwJVUzESMBAGA1UECBMJ
QmVya3NoaXJlMRAwDgYDVQQHEwdOZXdidXJ5MRcwFQYDVQQKEw5NeSBDb21wYW55
IEx0ZDEQMA4GA1UECxMHVGVzdGluZzENMAsGA1UEAxMEdGVzdDEcMBoGCSqGSIb3
DQEJARYNdGVzdEB0ZXN0LmNvbTCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoC
ggEBAKot9j+/+CX1/gZLgJHIXCRgCItKLGnf7qGbgqB9T2ACBqR0jllKWwDKrcWU
xjXNIc+GF9Wnv+lX6G0Okn4Zt3/uRNobL+2b/yOF7M3Td3/9W873zdkQQX930YZc
Rr8uxdRPP5bxiCgtcw632y21sSEbG9mjccAUnV/0jdvfmMNj0i8gN6E0fMBiJ9S3
FkxX/KFvt9JWE9CtoyL7ki7UIDq+6vj7Gd5N0B3dOa1y+rRHZzKlJPcSXQSEYUS4
HmKDwiKSVahft8c4tDn7KPi0vex91hlgZVd3usL2E/Vq7o5D9FAZ5kZY0AdFXwdm
J4lO4Mj7ac7GE4vNERNcXVIX59sCAwEAAaOB8zCB8DAdBgNVHQ4EFgQUuDU3Mr7P
T3n1e3Sy8hBauoDFahAwgcAGA1UdIwSBuDCBtYAUuDU3Mr7PT3n1e3Sy8hBauoDF
ahChgZGkgY4wgYsxCzAJBgNVBAYTAlVTMRIwEAYDVQQIEwlCZXJrc2hpcmUxEDAO
BgNVBAcTB05ld2J1cnkxFzAVBgNVBAoTDk15IENvbXBhbnkgTHRkMRAwDgYDVQQL
EwdUZXN0aW5nMQ0wCwYDVQQDEwR0ZXN0MRwwGgYJKoZIhvcNAQkBFg10ZXN0QHRl
c3QuY29tggkA6+dk+3n3IhkwDAYDVR0TBAUwAwEB/zANBgkqhkiG9w0BAQUFAAOC
AQEAVRG4aALIvCXCiKfe7K+iJxjBVRDFPEf7JWA9LGgbFOn6pNvbxonrR+0BETdc
JV1ET4ct2xsE7QNFIkp9GKRC+6J32zCo8qtLCD5+v436r8TUG2/t2JRMkb9I2XVT
p7RJoot6M0Ltf8KNQUPYh756xmKZ4USfQUwc58MOSDGY8VWEXJOYij9Pf0e0c52t
qiCEjXH7uXiS8Pgq9TYm7AkWSOrglYhSa83x0f8mtT8Q15nBESIHZ6o8FAS2bBgn
B0BkrKRjtBUkuJG3vTox+bYINh2Gxi1JZHWSV1tN5z3hd4VFcKqanW5OgQwToBqp
3nniskIjbH0xjgZf/nVMyLnjxg==
-----END CERTIFICATE-----

Binary file not shown.

View file

@ -268,7 +268,8 @@ test_wifi_wep_key (const char *detail,
g_assert (nm_supplicant_config_add_setting_wireless_security (config,
s_wsec,
NULL,
"376aced7-b28c-46be-9a62-fcdf072571da"));
"376aced7-b28c-46be-9a62-fcdf072571da",
1500));
g_test_assert_expected_messages ();
config_dict = nm_supplicant_config_to_variant (config);
@ -408,7 +409,8 @@ test_wifi_wpa_psk (const char *detail,
g_assert (nm_supplicant_config_add_setting_wireless_security (config,
s_wsec,
NULL,
"376aced7-b28c-46be-9a62-fcdf072571da"));
"376aced7-b28c-46be-9a62-fcdf072571da",
1500));
g_test_assert_expected_messages ();
config_dict = nm_supplicant_config_to_variant (config);
@ -438,6 +440,142 @@ test_wifi_wpa_psk_types (void)
test_wifi_wpa_psk ("wifi-wep-psk-passphrase", TYPE_STRING, key2, (gconstpointer) key2, strlen (key2));
}
static void
test_wifi_eap (void)
{
gs_unref_object NMConnection *connection = NULL;
gs_unref_object NMSupplicantConfig *config = NULL;
gs_unref_variant GVariant *config_dict = NULL;
NMSettingConnection *s_con;
NMSettingWireless *s_wifi;
NMSettingWirelessSecurity *s_wsec;
NMSetting8021x *s_8021x;
NMSettingIPConfig *s_ip4;
char *uuid;
gboolean success;
GError *error = NULL;
GBytes *ssid;
const unsigned char ssid_data[] = { 0x54, 0x65, 0x73, 0x74, 0x20, 0x53, 0x53, 0x49, 0x44 };
const char *bssid_str = "11:22:33:44:55:66";
guint32 mtu = 1100;
connection = nm_simple_connection_new ();
/* Connection setting */
s_con = (NMSettingConnection *) nm_setting_connection_new ();
nm_connection_add_setting (connection, NM_SETTING (s_con));
uuid = nm_utils_uuid_generate ();
g_object_set (s_con,
NM_SETTING_CONNECTION_ID, "Test Wifi EAP-TLS",
NM_SETTING_CONNECTION_UUID, uuid,
NM_SETTING_CONNECTION_AUTOCONNECT, TRUE,
NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME,
NULL);
g_free (uuid);
/* Wifi setting */
s_wifi = (NMSettingWireless *) nm_setting_wireless_new ();
nm_connection_add_setting (connection, NM_SETTING (s_wifi));
ssid = g_bytes_new (ssid_data, sizeof (ssid_data));
g_object_set (s_wifi,
NM_SETTING_WIRELESS_SSID, ssid,
NM_SETTING_WIRELESS_BSSID, bssid_str,
NM_SETTING_WIRELESS_MODE, "infrastructure",
NM_SETTING_WIRELESS_BAND, "bg",
NULL);
g_bytes_unref (ssid);
/* Wifi Security setting */
s_wsec = (NMSettingWirelessSecurity *) nm_setting_wireless_security_new ();
nm_connection_add_setting (connection, NM_SETTING (s_wsec));
g_object_set (s_wsec,
NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, "wpa-eap",
NULL);
nm_setting_wireless_security_add_proto (s_wsec, "wpa");
nm_setting_wireless_security_add_proto (s_wsec, "rsn");
nm_setting_wireless_security_add_pairwise (s_wsec, "tkip");
nm_setting_wireless_security_add_pairwise (s_wsec, "ccmp");
nm_setting_wireless_security_add_group (s_wsec, "tkip");
nm_setting_wireless_security_add_group (s_wsec, "ccmp");
/* 802-1X setting */
s_8021x = (NMSetting8021x *) nm_setting_802_1x_new ();
nm_connection_add_setting (connection, NM_SETTING (s_8021x));
nm_setting_802_1x_add_eap_method (s_8021x, "tls");
nm_setting_802_1x_set_client_cert (s_8021x, TEST_CERT_DIR "test-cert.p12", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL);
nm_setting_802_1x_set_ca_cert (s_8021x, TEST_CERT_DIR "test-ca-cert.pem", NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL);
nm_setting_802_1x_set_private_key (s_8021x, TEST_CERT_DIR "test-cert.p12", NULL, NM_SETTING_802_1X_CK_SCHEME_PATH, NULL, NULL);
/* IP4 setting */
s_ip4 = (NMSettingIPConfig *) nm_setting_ip4_config_new ();
nm_connection_add_setting (connection, NM_SETTING (s_ip4));
g_object_set (s_ip4, NM_SETTING_IP_CONFIG_METHOD, NM_SETTING_IP4_CONFIG_METHOD_AUTO, NULL);
success = nm_connection_verify (connection, &error);
g_assert_no_error (error);
g_assert (success);
config = nm_supplicant_config_new ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'ssid' value 'Test SSID'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'scan_ssid' value '1'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'bssid' value '11:22:33:44:55:66'*");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'freq_list' value *");
g_assert (nm_supplicant_config_add_setting_wireless (config, s_wifi, 0));
g_test_assert_expected_messages ();
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'key_mgmt' value 'WPA-EAP'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'proto' value 'WPA RSN'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'pairwise' value 'TKIP CCMP'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*added 'group' value 'TKIP CCMP'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*Config: added 'eap' value 'TLS'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*Config: added 'fragment_size' value '1086'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"* Config: added 'ca_cert' value '*/test-ca-cert.pem'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"* Config: added 'private_key' value '*/test-cert.p12'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*Config: added 'bgscan' value 'simple:30:-65:300'");
g_test_expect_message ("NetworkManager", G_LOG_LEVEL_MESSAGE,
"*Config: added 'proactive_key_caching' value '1'");
g_assert (nm_supplicant_config_add_setting_wireless_security (config,
s_wsec,
s_8021x,
"d5b488af-9cab-41ed-bad4-97709c58430f",
mtu));
g_test_assert_expected_messages ();
config_dict = nm_supplicant_config_to_variant (config);
g_assert (config_dict);
validate_opt ("wifi-eap", config_dict, "scan_ssid", TYPE_INT, GINT_TO_POINTER (1), -1);
validate_opt ("wifi-eap", config_dict, "ssid", TYPE_BYTES, ssid_data, sizeof (ssid_data));
validate_opt ("wifi-eap", config_dict, "bssid", TYPE_KEYWORD, bssid_str, -1);
validate_opt ("wifi-eap", config_dict, "key_mgmt", TYPE_KEYWORD, "WPA-EAP", -1);
validate_opt ("wifi-eap", config_dict, "eap", TYPE_KEYWORD, "TLS", -1);
validate_opt ("wifi-eap", config_dict, "proto", TYPE_KEYWORD, "WPA RSN", -1);
validate_opt ("wifi-eap", config_dict, "pairwise", TYPE_KEYWORD, "TKIP CCMP", -1);
validate_opt ("wifi-eap", config_dict, "group", TYPE_KEYWORD, "TKIP CCMP", -1);
validate_opt ("wifi-eap", config_dict, "fragment_size", TYPE_INT, GINT_TO_POINTER(mtu-14), -1);
}
NMTST_DEFINE ();
int main (int argc, char **argv)
@ -447,6 +585,7 @@ int main (int argc, char **argv)
g_test_add_func ("/supplicant-config/wifi-open", test_wifi_open);
g_test_add_func ("/supplicant-config/wifi-wep", test_wifi_wep);
g_test_add_func ("/supplicant-config/wifi-wpa-psk-types", test_wifi_wpa_psk_types);
g_test_add_func ("/supplicant-config/wifi-eap", test_wifi_eap);
return g_test_run ();
}