From f94176af3fdc3396d7f0b04db13a4d3b38f74b18 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Josef=20S=C3=B6ntgen?= Date: Fri, 6 Mar 2015 14:24:06 +0100 Subject: [PATCH] wifi_drv: handle invalid config_rom and psk * Only attach the config_rom dataspace if it is valid. * Check if PSK has a valid length. Issue #1439. --- repos/dde_linux/src/drivers/wifi/main.cc | 196 +++++++++++++++++------ 1 file changed, 147 insertions(+), 49 deletions(-) diff --git a/repos/dde_linux/src/drivers/wifi/main.cc b/repos/dde_linux/src/drivers/wifi/main.cc index c1d10ff2e..4577af01d 100644 --- a/repos/dde_linux/src/drivers/wifi/main.cc +++ b/repos/dde_linux/src/drivers/wifi/main.cc @@ -35,24 +35,68 @@ static Genode::Lock &wpa_startup_lock() } -static int update_conf(char **p, Genode::size_t *len, char const *ssid, - bool encryption = false, char const *psk = 0) +namespace { + template + class Buffer + { + private: + + char _data[CAPACITY] { 0 }; + Genode::size_t _length { 0 }; + + public: + + void reset() { _data[0] = 0; _length = 0; } + char const *data() const { return _data; } + Genode::size_t length() const { return _length; } + + void append(char const *format, ...) + { + va_list list; + va_start(list, format); + Genode::String_console sc(_data + _length, CAPACITY - _length); + sc.vprintf(format, list); + va_end(list); + + _length += sc.len(); + } + }; +} /* anonymous namespace */ + + +/** + * Generate wpa_supplicant.conf file + */ +static int generate_wpa_supplicant_conf(char const **p, Genode::size_t *len, char const *ssid, + char const *bssid, bool protection = false, char const *psk = 0) { - char const *ssid_fmt = "network={\n\tssid=\"%s\"\n\tkey_mgmt=%s\n"; - char const *psk_fmt = "psk=\"%s\"\n"; - char const *end_fmt = "}\n"; + static char const *start_fmt = "network={\n"; + static char const *ssid_fmt = "\tssid=\"%s\"\n"; + static char const *bssid_fmt = "\tbssid=%s\n"; + static char const *prot_fmt = "\tkey_mgmt=%s\n"; + static char const *psk_fmt = "\tpsk=\"%s\"\n"; + static char const *end_fmt = "}\n"; - static char buf[4096]; - Genode::size_t n = Genode::snprintf(buf, sizeof(buf), ssid_fmt, ssid, - encryption ? "WPA-PSK" : "NONE"); - if (encryption) { - n += Genode::snprintf(buf + n, sizeof(buf) - n, psk_fmt, psk); - } + static Buffer<256> buffer; + buffer.reset(); - n += Genode::snprintf(buf + n, sizeof(buf) - n, end_fmt); + buffer.append(start_fmt); - *p = buf; - *len = n; + if (ssid) + buffer.append(ssid_fmt, ssid); + + if (bssid) + buffer.append(bssid_fmt, bssid); + + if (protection) + buffer.append(psk_fmt, psk); + + buffer.append(prot_fmt, protection ? "WPA-PSK" : "NONE"); + + buffer.append(end_fmt); + + *p = buffer.data(); + *len = buffer.length(); return 0; } @@ -60,55 +104,109 @@ static int update_conf(char **p, Genode::size_t *len, char const *ssid, struct Wlan_configration { - Genode::Attached_rom_dataspace config_rom { "wlan_configuration" }; + Genode::Attached_rom_dataspace config_rom { "wlan_configuration" }; Genode::Signal_rpc_member dispatcher; + Genode::Lock update_lock; - void _update_conf() + char const *buffer; + Genode::size_t size; + + /** + * Write configuration buffer to conf file to activate the new configuration. + */ + void _activate_configuration() { - config_rom.update(); - Genode::size_t size = config_rom.size(); - - char *file_buffer; - Genode::size_t buffer_length; - - Genode::Xml_node node(config_rom.local_addr(), size); - - /** - * Since is empty we generate a dummy - * configuration to fool wpa_supplicant to keep it scanning for - * the non exisiting network. - */ - if (!node.has_attribute("ssid")) { - update_conf(&file_buffer, &buffer_length, "dummyssid"); - } else { - char ssid[32+1] = { 0 }; - node.attribute("ssid").value(ssid, sizeof(ssid)); - - bool use_protection = node.has_attribute("protection"); - - char psk[63+1] = { 0 }; - if (use_protection && node.has_attribute("psk")) - node.attribute("psk").value(psk, sizeof(psk)); - - if (update_conf(&file_buffer, &buffer_length, ssid, - use_protection, psk) != 0) - return; - } - - if (wpa_write_conf(file_buffer, buffer_length) == 0) { + if (wpa_write_conf(buffer, size) == 0) { PINF("reload wpa_supplicant configuration"); wpa_conf_reload(); } } - void _handle_update(unsigned) { _update_conf(); } + /** + * Write dummy configuration buffer to conf file to activate the new + * configuration. + */ + void _active_dummy_configuration() + { + generate_wpa_supplicant_conf(&buffer, &size, "dummyssid", "00:00:00:00:00:00"); + _activate_configuration(); + } + + /** + * Update the conf file used by the wpa_supplicant. + */ + void _update_configuration() + { + Genode::Lock::Guard guard(update_lock); + + config_rom.update(); + + /** + * We generate a dummy configuration because there is no valid + * configuration yet to fool wpa_supplicant to keep it scanning + * for the non exisiting network. + */ + if (!config_rom.is_valid()) { + _active_dummy_configuration(); + return; + } + + Genode::Xml_node node(config_rom.local_addr(), config_rom.size()); + + /** + * Since is empty we also generate a dummy + * configuration. + */ + bool use_ssid = node.has_attribute("ssid"); + bool use_bssid = node.has_attribute("bssid"); + if (!use_ssid && !use_bssid) { + _active_dummy_configuration(); + return; + } + + /** + * Try to generate a valid configuration. + */ + enum { MAX_SSID_LENGTH = 32, + BSSID_LENGTH = 12 + 5, + MIN_PSK_LENGTH = 8, + MAX_PSK_LENGTH = 63 }; + + char ssid[MAX_SSID_LENGTH + 1] = { 0 }; + if (use_ssid) + node.attribute("ssid").value(ssid, sizeof(ssid)); + + char bssid[BSSID_LENGTH + 1] = { 0 }; + if (use_bssid) + node.attribute("bssid").value(bssid, sizeof(bssid)); + + bool use_protection = node.has_attribute("protection"); + + char psk[MAX_PSK_LENGTH + 1] = { 0 }; + if (use_protection && node.has_attribute("psk")) + node.attribute("psk").value(psk, sizeof(psk)); + + /* psk must be between 8 and 63 characters long */ + if (Genode::strlen(psk) < MIN_PSK_LENGTH) { + _active_dummy_configuration(); + return; + } + + if (generate_wpa_supplicant_conf(&buffer, &size, + use_ssid ? ssid : 0, + use_bssid ? bssid : 0, + use_protection, psk) == 0) + _activate_configuration(); + } + + void _handle_update(unsigned) { _update_configuration(); } Wlan_configration(Server::Entrypoint &ep) : dispatcher(ep, *this, &Wlan_configration::_handle_update) { config_rom.sigh(dispatcher); - _update_conf(); + _update_configuration(); } };