mirror of
https://github.com/koreader/koreader.git
synced 2025-12-13 20:36:53 +01:00
Fix connection bug with non-ASCII SSIDs in wpa_supplicant (#11089)
* Bump base includes: koreader/koreader-base#1691 koreader/koreader-base#1692 koreader/koreader-base#1689 koreader/koreader-base#1690 koreader/koreader-base#1693 * Integrate decoding of SSIDs within wpa_supplicant The UTF-8 decoding of SSIDs is specific to wpa_supplicant. In this patch, we move all of this decoding logic to the wpa_supplicant module. We expose the raw bytes of the SSID to the NetworkMgr code, and make sure to always fix bad UTF-8 before we display the SSID to the user. Within the wpa_supplicant module, we replace the call to the wpa_passphrase binary to get the PSK with a direct function call to OpenSSL. This allows us to calculate the PSK over any arbitrary bytes, including UTF-8. In the same vein, we use the hex-encoded SSID to communicate with wpa_supplicant when setting up the network to support arbitrary bytes in the SSID. Unfortunately, we also remove the tests, as there is no way to unit test local functions.
This commit is contained in:
2
base
2
base
Submodule base updated: 90681b01b9...99578f7921
@@ -1067,7 +1067,7 @@ function NetworkMgr:reconnectOrShowNetworkMenu(complete_callback, interactive)
|
||||
end
|
||||
UIManager:show(InfoMessage:new{
|
||||
tag = "NetworkMgr", -- for crazy KOSync purposes
|
||||
text = T(_("Connected to network %1"), BD.wrap(self.decodeSSID(ssid))),
|
||||
text = T(_("Connected to network %1"), BD.wrap(util.fixUtf8(ssid, "<EFBFBD>"))),
|
||||
timeout = 3,
|
||||
})
|
||||
else
|
||||
@@ -1119,23 +1119,6 @@ function NetworkMgr:setWirelessBackend(name, options)
|
||||
require("ui/network/"..name).init(self, options)
|
||||
end
|
||||
|
||||
function NetworkMgr.decodeSSID(text)
|
||||
local decode = function(b)
|
||||
local c = string.char(tonumber(b, 16))
|
||||
-- This is a hack that allows us to make sure that any decoded backslash
|
||||
-- does not get replaced in the step that replaces double backslashes.
|
||||
if c == "\\" then
|
||||
return "\\\\"
|
||||
else
|
||||
return c
|
||||
end
|
||||
end
|
||||
|
||||
local decoded = text:gsub("%f[\\]\\x(%x%x)", decode)
|
||||
decoded = decoded:gsub("\\\\", "\\")
|
||||
return util.fixUtf8(decoded, "<EFBFBD>")
|
||||
end
|
||||
|
||||
-- set network proxy if global variable G_defaults:readSetting("NETWORK_PROXY") is defined
|
||||
if G_defaults:readSetting("NETWORK_PROXY") then
|
||||
NetworkMgr:setHTTPProxy(G_defaults:readSetting("NETWORK_PROXY"))
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
WPA client helper for Kobo.
|
||||
]]
|
||||
|
||||
local crypto = require("ffi/crypto")
|
||||
local bin_to_hex = require("ffi/sha2").bin_to_hex
|
||||
local FFIUtil = require("ffi/util")
|
||||
local InfoMessage = require("ui/widget/infomessage")
|
||||
local WpaClient = require("lj-wpaclient/wpaclient")
|
||||
@@ -13,6 +15,23 @@ local CLIENT_INIT_ERR_MSG = _("Failed to initialize network control client: %1."
|
||||
|
||||
local WpaSupplicant = {}
|
||||
|
||||
local function decodeSSID(ssid)
|
||||
local decode = function(b)
|
||||
local c = string.char(tonumber(b, 16))
|
||||
-- This is a hack that allows us to make sure that any decoded backslash
|
||||
-- does not get replaced in the step that replaces double backslashes.
|
||||
if c == "\\" then
|
||||
return "\\\\"
|
||||
else
|
||||
return c
|
||||
end
|
||||
end
|
||||
|
||||
local decoded = ssid:gsub("%f[\\]\\x(%x%x)", decode)
|
||||
decoded = decoded:gsub("\\\\", "\\")
|
||||
return decoded
|
||||
end
|
||||
|
||||
--- Gets network list.
|
||||
function WpaSupplicant:getNetworkList()
|
||||
local wcli, err = WpaClient.new(self.wpa_supplicant.ctrl_interface)
|
||||
@@ -31,6 +50,7 @@ function WpaSupplicant:getNetworkList()
|
||||
local curr_network = self:getCurrentNetwork()
|
||||
|
||||
for _, network in ipairs(list) do
|
||||
network.ssid = decodeSSID(network.ssid)
|
||||
network.signal_quality = network:getSignalQuality()
|
||||
local saved_nw = saved_networks:readSetting(network.ssid)
|
||||
if saved_nw then
|
||||
@@ -49,15 +69,7 @@ function WpaSupplicant:getNetworkList()
|
||||
end
|
||||
|
||||
local function calculatePsk(ssid, pwd)
|
||||
--- @todo calculate PSK with native function instead of shelling out
|
||||
-- hostap's reference implementation is available at:
|
||||
-- * /wpa_supplicant/wpa_passphrase.c
|
||||
-- * /src/crypto/sha1-pbkdf2.c
|
||||
-- see: <http://docs.ros.org/diamondback/api/wpa_supplicant/html/sha1-pbkdf2_8c_source.html>
|
||||
local fp = io.popen(("wpa_passphrase %q %q"):format(ssid, pwd))
|
||||
local out = fp:read("*a")
|
||||
fp:close()
|
||||
return string.match(out, "psk=([a-f0-9]+)")
|
||||
return bin_to_hex(crypto.pbkdf2_hmac_sha1(pwd, ssid, 4096, 32))
|
||||
end
|
||||
|
||||
--- Authenticates network.
|
||||
@@ -75,7 +87,7 @@ function WpaSupplicant:authenticateNetwork(network)
|
||||
end
|
||||
local nw_id = reply
|
||||
|
||||
reply, err = wcli:setNetwork(nw_id, "ssid", string.format("\"%s\"", network.ssid))
|
||||
reply, err = wcli:setNetwork(nw_id, "ssid", bin_to_hex(network.ssid))
|
||||
if reply == nil or reply == "FAIL" then
|
||||
wcli:removeNetwork(nw_id)
|
||||
return false, T("An error occurred while selecting network: %1.", err)
|
||||
@@ -185,6 +197,9 @@ function WpaSupplicant:getCurrentNetwork()
|
||||
end
|
||||
local nw = wcli:getCurrentNetwork()
|
||||
wcli:close()
|
||||
if nw ~= nil then
|
||||
nw.ssid = decodeSSID(nw.ssid)
|
||||
end
|
||||
return nw
|
||||
end
|
||||
|
||||
|
||||
@@ -56,6 +56,7 @@ local OverlapGroup = require("ui/widget/overlapgroup")
|
||||
local Size = require("ui/size")
|
||||
local TextWidget = require("ui/widget/textwidget")
|
||||
local UIManager = require("ui/uimanager")
|
||||
local util = require("util")
|
||||
local VerticalGroup = require("ui/widget/verticalgroup")
|
||||
local Widget = require("ui/widget/widget")
|
||||
local _ = require("gettext")
|
||||
@@ -106,7 +107,7 @@ local NetworkItem = InputContainer:extend{
|
||||
icon_size = Screen:scaleBySize(32),
|
||||
width = nil,
|
||||
info = nil,
|
||||
decoded_ssid = nil,
|
||||
display_ssid = nil,
|
||||
background = Blitbuffer.COLOR_WHITE,
|
||||
}
|
||||
|
||||
@@ -115,7 +116,7 @@ function NetworkItem:init()
|
||||
if not self.info.ssid then
|
||||
self.info.ssid = "[hidden]"
|
||||
end
|
||||
self.decoded_ssid = NetworkMgr.decodeSSID(self.info.ssid)
|
||||
self.display_ssid = util.fixUtf8(self.info.ssid, "<EFBFBD>")
|
||||
|
||||
local wifi_icon
|
||||
if string.find(self.info.flags, "WPA") then
|
||||
@@ -151,7 +152,7 @@ function NetworkItem:init()
|
||||
},
|
||||
horizontal_space,
|
||||
TextWidget:new{
|
||||
text = self.decoded_ssid,
|
||||
text = self.display_ssid,
|
||||
face = Font:getFace("cfont"),
|
||||
},
|
||||
},
|
||||
@@ -285,7 +286,7 @@ end
|
||||
function NetworkItem:onEditNetwork()
|
||||
local password_input
|
||||
password_input = InputDialog:new{
|
||||
title = self.decoded_ssid,
|
||||
title = self.display_ssid,
|
||||
input = self.info.password,
|
||||
input_hint = _("password (leave empty for open networks)"),
|
||||
input_type = "text",
|
||||
@@ -328,7 +329,7 @@ end
|
||||
function NetworkItem:onAddNetwork()
|
||||
local password_input
|
||||
password_input = InputDialog:new{
|
||||
title = self.decoded_ssid,
|
||||
title = self.display_ssid,
|
||||
input = "",
|
||||
input_hint = _("password (leave empty for open networks)"),
|
||||
input_type = "text",
|
||||
@@ -490,7 +491,7 @@ function NetworkSetting:init()
|
||||
UIManager:close(self, "ui", self.dimen)
|
||||
end
|
||||
UIManager:show(InfoMessage:new{
|
||||
text = T(_("Connected to network %1"), BD.wrap(connected_item.decoded_ssid)),
|
||||
text = T(_("Connected to network %1"), BD.wrap(connected_item.display_ssid)),
|
||||
timeout = 3,
|
||||
})
|
||||
if self.connect_callback then
|
||||
|
||||
@@ -73,30 +73,6 @@ describe("network_manager module", function()
|
||||
assert.is.same(release_ip_called, 0)
|
||||
end)
|
||||
|
||||
describe("decodeSSID()", function()
|
||||
local NetworkMgr = require("ui/network/manager")
|
||||
|
||||
it("should correctly unescape emoji", function()
|
||||
assert.is_equal("📚", NetworkMgr.decodeSSID("\\xf0\\x9f\\x93\\x9a"))
|
||||
end)
|
||||
|
||||
it("should correctly unescape multiple characters", function()
|
||||
assert.is_equal("神舟五号", NetworkMgr.decodeSSID("\\xe7\\xa5\\x9e\\xe8\\x88\\x9f\\xe4\\xba\\x94\\xe5\\x8f\\xb7"))
|
||||
end)
|
||||
|
||||
it("should ignore escaped backslashes", function()
|
||||
assert.is_equal("\\x61", NetworkMgr.decodeSSID("\\\\x61"))
|
||||
end)
|
||||
|
||||
it("should not remove encoded backslashes", function()
|
||||
assert.is_equal("\\\\", NetworkMgr.decodeSSID("\\x5c\\"))
|
||||
end)
|
||||
|
||||
it("should deal with invalid UTF-8 (relatively) gracefully", function()
|
||||
assert.is_equal("<EFBFBD><EFBFBD>", NetworkMgr.decodeSSID("\\xe2\\x82"))
|
||||
end)
|
||||
end)
|
||||
|
||||
teardown(function()
|
||||
function Device:initNetworkManager() end
|
||||
function Device:hasWifiRestore() return false end
|
||||
|
||||
Reference in New Issue
Block a user