From 3f02bd16e620ffb8e2082644c0416033bbe41f80 Mon Sep 17 00:00:00 2001 From: dg <dg@51575b47-30f0-44d4-a5cc-537603b46e54> Date: Tue, 29 Nov 2011 00:01:23 +0000 Subject: [PATCH] Addons are now validated just as the main module git-svn-id: http://svn.net-core.org/repos/t-engine4@4695 51575b47-30f0-44d4-a5cc-537603b46e54 --- game/engines/default/engine/Module.lua | 70 +++++++++++++++++-- game/engines/default/engine/PlayerProfile.lua | 15 ++++ game/modules/tome/class/Game.lua | 2 +- game/modules/tome/data/damage_types.lua | 2 +- game/profile-thread/Client.lua | 12 +++- 5 files changed, 94 insertions(+), 7 deletions(-) diff --git a/game/engines/default/engine/Module.lua b/game/engines/default/engine/Module.lua index 8a33888851..5a274d067b 100644 --- a/game/engines/default/engine/Module.lua +++ b/game/engines/default/engine/Module.lua @@ -287,14 +287,20 @@ function _M:loadAddons(mod) table.sort(adds, function(a, b) return a.weight < b.weight end) + mod.addons = {} for i, add in ipairs(adds) do - print("Binding addon", add.long_name, add.teaa) - local base + add.version_name = ("%s-%s-%d.%d.%d"):format(mod.short_name, add.short_name, add.version[1], add.version[2], add.version[3]) + + print("Binding addon", add.long_name, add.teaa, add.version_name) + local base, vbase if add.teaa then fs.mount(fs.getRealPath(add.teaa), "/loaded-addons/"..add.short_name, true) base = "bind::/loaded-addons/"..add.short_name + vbase = "/loaded-addons/"..add.short_name else base = fs.getRealPath(add.dir) + fs.mount(base, "/loaded-addons/"..add.short_name, true) + vbase = "/loaded-addons/"..add.short_name end if add.data then fs.mount(base.."/data", "/data-"..add.short_name, true) print(" * with data") end @@ -305,8 +311,46 @@ function _M:loadAddons(mod) dofile("/hooks/"..add.short_name.."/load.lua") print(" * with hooks") end + + -- Compute addon md5 + local md5 = require "md5" + local md5s = {} + local function fp(dir) + for i, file in ipairs(fs.list(dir)) do + local f = dir.."/"..file + if fs.isdir(f) then + fp(f) + elseif f:find("%.lua$") then + local fff = fs.open(f, "r") + if fff then + local data = fff:read(10485760) + if data and data ~= "" then + md5s[#md5s+1] = f..":"..md5.sumhexa(data) + end + fff:close() + end + end + end + end + local hash_valid, hash_err + local t = core.game.getTime() + if config.settings.cheat then + hash_valid, hash_err = false, "cheat mode skipping addon validation" + else + fp(vbase) + table.sort(md5s) + table.print(md5s) + local fmd5 = md5.sumhexa(table.concat(md5s)) + print("[MODULE LOADER] addon ", add.short_name, " MD5", fmd5, "computed in ", core.game.getTime() - t, vbase) + hash_valid, hash_err = profile:checkAddonHash(mod.short_name, add.version_name, fmd5) + end + + if hash_err then hash_err = hash_err .. " [addon: "..add.short_name.."]" end + add.hash_valid, add.hash_err = hash_valid, hash_err + + mod.addons[add.short_name] = add end - table.print(fs.getSearchPath(true)) +-- os.exit() end --- Make a module loadscreen @@ -469,10 +513,28 @@ function _M:instanciate(mod, name, new_game, no_reboot) self:loadAddons(mod) + -- Check addons + if hash_valid then + for name, add in pairs(mod.addons) do + if not add.hash_valid then + hash_valid = false + hash_err = add.hash_err or "?????? unknown ...." + profile.hash_valid = false + break + end + end + end + + local addl = {} + for name, add in pairs(mod.addons) do + addl[#addl+1] = add.version_name + end + mod.full_version_string = mod.version_string.." ["..table.concat(addl, ';').."]" + profile:addStatFields(unpack(mod.profile_stats_fields or {})) profile:setConfigsBatch(true) profile:loadModuleProfile(mod.short_name, mod) - profile:currentCharacter(mod.version_string, "game did not tell us") + profile:currentCharacter(mod.full_version_string, "game did not tell us") -- Init the module code local M, W = mod.load("init") diff --git a/game/engines/default/engine/PlayerProfile.lua b/game/engines/default/engine/PlayerProfile.lua index c095d67843..26ad34f6a1 100644 --- a/game/engines/default/engine/PlayerProfile.lua +++ b/game/engines/default/engine/PlayerProfile.lua @@ -580,6 +580,8 @@ function _M:syncOnline(module, mod_def) end function _M:checkModuleHash(module, md5) +do self.hash_valid = true return true end + self.hash_valid = false if not self.auth then return nil, "no online profile active" end if config.settings.cheat then return nil, "cheat mode active" end @@ -594,6 +596,19 @@ function _M:checkModuleHash(module, md5) return true end +function _M:checkAddonHash(module, addon, md5) + if not self.auth then return nil, "no online profile active" end + if config.settings.cheat then return nil, "cheat mode active" end + if game and game:isTainted() then return nil, "savefile tainted" end + core.profile.pushOrder(table.serialize{o="CheckAddonHash", module=module, addon=addon, md5=md5}) + + self:waitEvent("CheckAddonHash", function(e) ok = e.ok end, 10000) + + if not ok then return nil, "bad game addon version" end + print("[ONLINE PROFILE] addon hash is valid") + return true +end + function _M:sendError(what, err) print("[ONLINE PROFILE] sending error") core.profile.pushOrder(table.serialize{o="SendError", login=self.login, what=what, err=err, module=game.__mod_info.short_name, version=game.__mod_info.version_name}) diff --git a/game/modules/tome/class/Game.lua b/game/modules/tome/class/Game.lua index 3355bf4023..822c7f36db 100644 --- a/game/modules/tome/class/Game.lua +++ b/game/modules/tome/class/Game.lua @@ -533,7 +533,7 @@ end function _M:updateCurrentChar() if not self.party then return end local player = self.party:findMember{main=true} - profile:currentCharacter(self.__mod_info.version_string, ("%s the level %d %s %s"):format(player.name, player.level, player.descriptor.subrace, player.descriptor.subclass), player.__te4_uuid) + profile:currentCharacter(self.__mod_info.full_version_string, ("%s the level %d %s %s"):format(player.name, player.level, player.descriptor.subrace, player.descriptor.subclass), player.__te4_uuid) end function _M:getSaveDescription() diff --git a/game/modules/tome/data/damage_types.lua b/game/modules/tome/data/damage_types.lua index 6068e14779..06283f6e75 100644 --- a/game/modules/tome/data/damage_types.lua +++ b/game/modules/tome/data/damage_types.lua @@ -85,7 +85,7 @@ setDefaultProjector(function(src, x, y, type, dam, tmp, no_martyr) else game:delayedLogDamage(src, {name="Iceblock", x=src.x, y=src.y}, dam, ("%s%d %s#LAST#"):format(DamageType:get(type).text_color or "#aaaaaa#", math.ceil(dam), DamageType:get(type).name)) if eff.begone and eff.begone < game.turn and eff.hp < 0 then - game.logSeen(src, "%s forces2 the iceblock to shatter.", src.name:capitalize()) + game.logSeen(src, "%s forces the iceblock to shatter.", src.name:capitalize()) src:removeEffect(src.EFF_FROZEN) end end diff --git a/game/profile-thread/Client.lua b/game/profile-thread/Client.lua index 7be3e01048..a3f14c7194 100644 --- a/game/profile-thread/Client.lua +++ b/game/profile-thread/Client.lua @@ -204,7 +204,7 @@ end function _M:handleOrder(o) o = o:unserialize() - if not self.sock and o.o ~= "Login" and o.o ~= "CurrentCharacter" and o.o ~= "CheckModuleHash" then return end -- Dont do stuff without a connection, unless we try to auth + if not self.sock and o.o ~= "Login" and o.o ~= "CurrentCharacter" and o.o ~= "CheckModuleHash" and o.o ~= "CheckAddonHash" then return end -- Dont do stuff without a connection, unless we try to auth if self["order"..o.o] then self["order"..o.o](self, o) end end @@ -317,6 +317,16 @@ function _M:orderCheckModuleHash(o) end end +function _M:orderCheckAddonHash(o) + if not self.sock then cprofile.pushEvent("e='CheckAddonHash' ok=false not_connected=true") end + self:command("AMD5", o.md5, o.module, o.addon) + if self:read("200") then + cprofile.pushEvent("e='CheckAddonHash' ok=true") + else + cprofile.pushEvent("e='CheckAddonHash' ok=false") + end +end + function _M:orderRegisterNewCharacter(o) self:command("CHAR", "NEW", o.module) if self:read("200") then -- GitLab