From 51408076dc863022de5061643e4010911b79f4e3 Mon Sep 17 00:00:00 2001 From: flyc0r Date: Sun, 4 Oct 2020 04:32:19 +0200 Subject: [PATCH] updated wisp and tchat --- clientmods/mods.conf | 2 +- clientmods/tchat/init.lua | 55 ++++++---- clientmods/wisp/init.lua | 171 +++++++++++++++++++++++-------- clientmods/wisp/settingtypes.txt | 2 + 4 files changed, 163 insertions(+), 67 deletions(-) diff --git a/clientmods/mods.conf b/clientmods/mods.conf index 07621c364..6214fb825 100644 --- a/clientmods/mods.conf +++ b/clientmods/mods.conf @@ -11,9 +11,9 @@ load_mod_aflight = false load_mod_geass = false load_mod_autowarp = true load_mod_panicm = true +load_mod_wisp = true load_mod_tchat = true load_mod_esp = true load_mod_antigone = false load_mod_dte = true -load_mod_wisp = true load_mod_flightaura = false diff --git a/clientmods/tchat/init.lua b/clientmods/tchat/init.lua index 47a79a96d..723886ccf 100644 --- a/clientmods/tchat/init.lua +++ b/clientmods/tchat/init.lua @@ -1,7 +1,7 @@ --- -- coras teamchat .. indev v0.5 -- --- adds a team chat for you and a couple friends, also prevents accidental sending of coordinates +-- adds a team chat for you and a couple friends, also prevents accidental sending of coordinates -- to say something in teamchat either activate teammode in the dragonfire menu or use .t message -- -- supports the Wisp encrypted whisper mod @@ -86,9 +86,9 @@ init_settings({ tchat_view_team_list = true, tchat_view_player_list = true, tchat_team_mode = false, - + tchat_colorize_team = false, - + tchat_prefix_message = "TCHAT", tchat_prefix_receive = "From", tchat_prefix_self = "To Yourself", @@ -96,7 +96,7 @@ init_settings({ tchat_hide_sent = true, tchat_blacklist = "", - + tchat_chat_length = 6, tchat_chat_width = 80 }) @@ -146,8 +146,8 @@ tchat.team = minetest.parse_json(storage:get_string("tchat_team")) local message_confirmed_safe = false -- coordinate matching -local pattern = "[-]?%d[,.%d]*" -local space = "%s+" +local pattern = "[-]?%d[.%d]*" +local space = "[,%s]+" local pattern_three = pattern .. space .. pattern .. space .. pattern local pattern_two = pattern .. space .. pattern @@ -209,7 +209,7 @@ end local function display_chat() return minetest.localplayer:hud_add({ hud_elem_type = 'text', - name = "üüTeamüchat", + name = "Teamchat", text = "Team Chat\n\n" .. chat_str, number = 0xEEFFEE, direction = 0, @@ -233,7 +233,7 @@ local function display_player_list() }) end --- should prob have all team members with online ones colored +-- should prob have all team members with online ones colored local function display_team_list() return minetest.localplayer:hud_add({ hud_elem_type = 'text', @@ -284,7 +284,7 @@ local function update_chat_str() chat_str = table.concat(limit_list(string.split(chat_str, "\n"), chat_length - 1), "\n") -- update chat (do it here so external mods can add to the chat) - auto_update(chat_idx, "Teamüü Chat\n\n" .. chat_str) + auto_update(chat_idx, "Team Chat\n\n" .. chat_str) end local function team_add_self() @@ -313,11 +313,11 @@ local function dm(player, message) end -- send -function tchat.send(message) - if tchat.contains_coords(message) or in_list(blacklist, minetest.localplayer:get_name()) then +function tchat.send(message, force_coords) + if (tchat.contains_coords(message) and not force_coords) or in_list(blacklist, minetest.localplayer:get_name()) then return end - + local me = minetest.localplayer:get_name() if not in_list(tchat.team, minetest.localplayer:get_name()) then @@ -325,7 +325,7 @@ function tchat.send(message) end update_team_online() - + tchat.chat_append("L " .. me .. ": " .. message) for k, p in ipairs(tchat.team_online) do @@ -336,11 +336,13 @@ function tchat.send(message) return true end -function tchat.send_conditional(message, inverse) - if tchat.contains_coords(message) then +function tchat.send_conditional(message, inverse, force_coords) + if tchat.contains_coords(message) and not force_coords then return end + team_mode = minetest.settings:get_bool("tchat_team_mode") + local tm = team_mode if inverse then tm = not team_mode @@ -392,7 +394,7 @@ end function tchat.chat_append(message) tchat.chat[#tchat.chat + 1] = message autoclear_chat() - + minetest.log("action", "[tchat] " .. minetest.localplayer:get_name() .. "@" .. server_id .. " " .. message) update_chat_str() @@ -467,7 +469,7 @@ local function clean_message(message) message = message:gsub(message_prefix, "") message = message:gsub("^" .. message_receive, "") message = message:gsub("^" .. message_receive_self, minetest.localplayer:get_name()) - + message = message:gsub(": ", ": ") message = message:match("^%s*(.-)%s*$") @@ -486,15 +488,15 @@ table.insert(minetest.registered_on_receiving_chat_message, 1, function(message) end local player = message:match(message_receive .. " (.+): " .. message_prefix) - + local from_self = message:sub(1, message_receive_self:len()) == message_receive_self local received = message:sub(1, message_receive:len()) == message_receive local sent = message:sub(1, message_to:len()) == message_to - + if sent and not from_self then return true end - + if not from_self and not in_list(tchat.team_online, player) then return end @@ -524,7 +526,7 @@ minetest.register_globalstep(function() -- update HUD auto_update(player_list_idx, "Players\n\n" .. table.concat(tchat.players, "\n")) auto_update(team_list_idx, "Team\n\n" .. get_team_str()) - + player_list_epoch = os.time() end @@ -544,9 +546,20 @@ minetest.register_chatcommand("t", { params = "", description = "Send a message to your team chat, or regular chat if team mode is on.", func = function(message) + if tchat.contains_coords(message) then + minetest.display_chat_message("Message contained coordinates, be careful.") + return + end tchat.send_conditional(message, true) end }) +minetest.register_chatcommand("tcoords", { + params = "", + description = "Send a message containing coordinates to teamchat.", + func = function(message) + tchat.send(message, true) + end +}) minetest.register_chatcommand("tlist", { description = "List your team.", func = function(param) diff --git a/clientmods/wisp/init.lua b/clientmods/wisp/init.lua index 846f9c5bb..fffe4e808 100644 --- a/clientmods/wisp/init.lua +++ b/clientmods/wisp/init.lua @@ -1,10 +1,9 @@ local env = minetest.request_insecure_environment() -env.os.execute("echo test > test.txt") local openssl = env.require("openssl") -- Wisp by system32 -- CC0/Unlicense 2020 --- version 0.8 +-- version 1.0 -- -- a clientmod for minetest that lets people send 1 on 1 encrypted messages -- also has a public interface for other mods @@ -17,7 +16,9 @@ local openssl = env.require("openssl") -- -- Methods -- send(player, message) - send a message --- register_on_receive(function(message)) - register a callback +-- register_on_receive(function(message)) - register a receiving callback (includes To: messages), if it returns true the message will not be shown to the player +-- register_on_receive_split(function(player, message)) - register_on_receive but player and message are pre split +-- register_on_send_split(function(player, message)) - register a sending callback, if it returns true the message will not be sent -- -- Properties -- players - list of online players (updated every 2 seconds , when someone may have left, and when a message is queued) @@ -27,13 +28,17 @@ local openssl = env.require("openssl") -- PATCHING MINETEST -- --- in src/script/lua_api/l_util.cpp add the following to ModApiUtil:InitializeClient() --- API_FCT(request_insecure_environment); +-- in src/script/lua_api/l_util.cpp add the following to ModApiUtil:InitializeClient() below API_FCT(decompress); +--[[ + API_FCT(request_insecure_environment); +--]] -- -- in src/script/cpp_api/s_security.cpp add the following below int thread = getThread(L); in ScriptApiSecurity:initializeSecurityClient() --- // Backup globals to the registry --- lua_getglobal(L, "_G"); --- lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP); +--[[ + // Backup globals to the registry + lua_getglobal(L, "_G"); + lua_rawseti(L, LUA_REGISTRYINDEX, CUSTOM_RIDX_GLOBALS_BACKUP); +--]] -- -- Recompile Minetest (just using make -j$(nproc) is fine) @@ -90,7 +95,9 @@ init_settings({ wisp_curve = "prime256v1", wisp_cipher = "aes256", wisp_digest = "sha256", - wisp_whisper = "msg" + wisp_iv_size = 8, + wisp_whisper = "msg", + wisp_hide_sent = true }) -- players must agree on these @@ -98,7 +105,10 @@ local prefix = minetest.settings:get("wisp_prefix") local curve = minetest.settings:get("wisp_curve") local cipher = minetest.settings:get("wisp_cipher") local digest = minetest.settings:get("wisp_digest") + +local iv_size = minetest.settings:get("wisp_iv_size") local whisper = minetest.settings:get("wisp_whisper") +local hide_sent = minetest.settings:get_bool("wisp_hide_sent") local my_key = openssl.pkey.new("ec", curve) local my_ec = my_key:parse().ec @@ -134,6 +144,31 @@ local function in_list(list, value) return false end +local function append(list, item) + list[#list + 1] = item +end + +local function popfirst(t) + local out = {} + + for i = 2, #t do + out[#out + 1] = t[i] + end + + return out +end + +local function unpack(t, i) + if type(t) ~= "table" then + return t + end + + i = i or 1 + if t[i] ~= nil then + return t[i], unpack(t, i + 1) + end +end + -- key trading @@ -166,18 +201,51 @@ end -- encryption +local function run_callbacks(list, params) + for k, v in ipairs(list) do + if v(unpack(params)) then + return true + end + end +end + -- encrypt and send -local function message_send(player, message) +local function message_send(player, message, hide_to, force_send) + local me = minetest.localplayer:get_name() + + if run_callbacks(wisp.send_split_callbacks, {player, message}) then + return + end + + -- for displaying the To: stuff + if not hide_to then + local target = player + if target == me then + target = "Yourself" + end + local display_message = "To " .. target .. ": " .. message + + local callback_value = run_callbacks(wisp.receive_callbacks, display_message) + callback_value = callback_value or run_callbacks(wisp.receive_split_callbacks, {player, message}) + + if not callback_value then + minetest.display_chat_message(display_message) + end + end + + -- actual encryption local friend = friends[player] if friend == nil then return end - local nonce = openssl.random(8, true) - local message = openssl.cipher.encrypt(cipher, message, friend.key, nonce) - local final_message = b64_encode(nonce) .. " " .. b64_encode(message) + local nonce = openssl.random(iv_size, true) + local enc_message = openssl.cipher.encrypt(cipher, message, friend.key, nonce) + local final_message = b64_encode(nonce) .. " " .. b64_encode(enc_message) - dm(player, prefix .. "E " .. final_message) + if player ~= me or force_send then + dm(player, prefix .. "E " .. final_message) + end end -- decrypt and show @@ -188,17 +256,16 @@ local function message_receive(player, message) end local nonce = b64_decode(qsplit(message)[1]) - local message = b64_decode(qsplit(message)[2]) - local final_message = openssl.cipher.decrypt(cipher, message, friend.key, nonce) - final_message = "From " .. player .. ": " .. final_message + local enc_message = b64_decode(qsplit(message)[2]) + local dec_message = openssl.cipher.decrypt(cipher, enc_message, friend.key, nonce) + final_message = "From " .. player .. ": " .. dec_message - for k, v in ipairs(wisp.callbacks) do - if v(final_message) then - return - end + local callback_value = run_callbacks(wisp.receive_callbacks, final_message) + callback_value = callback_value or run_callbacks(wisp.receive_split_callbacks, {player, dec_message}) + + if not callback_value then + minetest.display_chat_message(final_message) end - - minetest.display_chat_message(final_message) end @@ -232,21 +299,17 @@ local function encrypted(message) end end - -local function popfirst(t) - local out = {} - - for i = 2, #t do - out[#out + 1] = t[i] - end - - return out +-- check if a message is 'Message sent.' or similar +local function message_sent(message) + return message == "Message sent." end wisp = {} -wisp.callbacks = {} +wisp.receive_callbacks = {} +wisp.receive_split_callbacks = {} +wisp.send_split_callbacks = {} wisp.players = {} @@ -256,8 +319,13 @@ local player_check_epoch = 0 -- messages are enqueued and dequeued once they can be sent local queue = {} -local function enqueue(player, message) - queue[#queue + 1] = {player = player, message = message} +local function enqueue(player, message, hide_to, force_send) + append(queue, { + player = player, + message = message, + hide_to = hide_to, + force_send = force_send + }) wisp.players = minetest.get_player_names() end @@ -266,7 +334,7 @@ local function dequeue() local out = queue[1] for k, v in ipairs(queue) do if k ~= 1 then - new_queue[#new_queue + 1] = v + append(new_queue, v) end end queue = new_queue @@ -278,15 +346,23 @@ local function peek() end -function wisp.send(player, message) - if friends[player] == nil then +function wisp.send(player, message, hide_to, force_send) + if (player ~= minetest.localplayer:get_name() or force_send) and friends[player] == nil then establish(player) end - enqueue(player, message) + enqueue(player, message, hide_to, force_send) end function wisp.register_on_receive(func) - wisp.callbacks[#wisp.callbacks + 1] = func + append(wisp.receive_callbacks, func) +end + +function wisp.register_on_receive_split(func) + append(wisp.receive_split_callbacks, func) +end + +function wisp.register_on_send_split(func) + append(wisp.send_split_callbacks, func) end @@ -294,6 +370,11 @@ end minetest.register_on_receiving_chat_message( function(message) + -- hide Message sent. + if hide_sent and message_sent(message) then + return true + end + -- if its a PM local player, msg = pm(message) if player and msg then @@ -331,16 +412,17 @@ minetest.register_globalstep( wisp.players = minetest.get_player_names() end - if peek() then + local p = peek() + if p then if not in_list(wisp.players, peek().player) then minetest.display_chat_message("Player " .. peek().player .. " is not online. If they are please resend the message.") dequeue() return end - if friends[peek().player] then + if (p.player == minetest.localplayer:get_name() and not p.force_send) or friends[p.player] then local v = dequeue() - message_send(v.player, v.message) + message_send(v.player, v.message, v.hide_to, v.force_send) end end end @@ -353,8 +435,7 @@ minetest.register_chatcommand("e", { func = function(param) local player = qsplit(param)[1] local message = table.concat(popfirst(qsplit(param)), " ") - minetest.log(".e " .. tostring(player) .. ": " .. tostring(message)) - if player == nil or message == nil then + if player == nil then minetest.display_chat_message("Player not specified.") return end diff --git a/clientmods/wisp/settingtypes.txt b/clientmods/wisp/settingtypes.txt index 82254af82..313795486 100644 --- a/clientmods/wisp/settingtypes.txt +++ b/clientmods/wisp/settingtypes.txt @@ -2,4 +2,6 @@ wisp_prefix (Prefix for encrypted messages) string &**& wisp_curve (Curve for ECDH) string prime256v1 wisp_cipher (Cipher for messages) string aes256 wisp_digest (Digest for shared secrets) string sha256 +wisp_iv_size (Size in bytes for initialization vector nonce) int 8 wisp_whisper (Whisper command) string msg +wisp_hide_sent (Hide "Message sent." server messages) bool true