From 67779ab81409ed7054bb31461e7a3361e40d71c0 Mon Sep 17 00:00:00 2001 From: "kepler155c@gmail.com" Date: Sat, 29 Jun 2019 23:43:21 -0400 Subject: [PATCH] secure telnet --- sys/apps/network/telnet.lua | 23 ++++++++++++++++--- sys/apps/network/transport.lua | 8 +++++-- sys/apps/telnet.lua | 7 +++--- sys/modules/opus/crypto/chacha20.lua | 6 ++--- sys/modules/opus/security.lua | 34 ++++++++-------------------- sys/modules/opus/socket.lua | 14 ++++++++---- 6 files changed, 51 insertions(+), 41 deletions(-) diff --git a/sys/apps/network/telnet.lua b/sys/apps/network/telnet.lua index dc2bda0..8bd11de 100644 --- a/sys/apps/network/telnet.lua +++ b/sys/apps/network/telnet.lua @@ -6,7 +6,7 @@ local kernel = _G.kernel local term = _G.term local window = _G.window -local function telnetHost(socket) +local function telnetHost(socket, mode) local methods = { 'clear', 'clearLine', 'setCursorPos', 'write', 'blit', 'setTextColor', 'setTextColour', 'setBackgroundColor', 'setBackgroundColour', 'scroll', 'setCursorBlink', } @@ -43,7 +43,7 @@ local function telnetHost(socket) local shellThread = kernel.run({ terminal = win, window = win, - title = 'Telnet client', + title = mode .. ' client', hidden = true, co = coroutine.create(function() Util.run(_ENV, 'sys/apps/shell.lua', table.unpack(termInfo.program)) @@ -68,6 +68,23 @@ local function telnetHost(socket) end) end +Event.addRoutine(function() + print('ssh: listening on port 22') + while true do + local socket = Socket.server(22, { ENCRYPT = true }) + + print('ssh: connection from ' .. socket.dhost) + + Event.addRoutine(function() + local s, m = pcall(telnetHost, socket, 'SSH') + if not s and m then + print('ssh error') + _G.printError(m) + end + end) + end +end) + Event.addRoutine(function() print('telnet: listening on port 23') while true do @@ -76,7 +93,7 @@ Event.addRoutine(function() print('telnet: connection from ' .. socket.dhost) Event.addRoutine(function() - local s, m = pcall(telnetHost, socket) + local s, m = pcall(telnetHost, socket, 'Telnet') if not s and m then print('Telnet error') _G.printError(m) diff --git a/sys/apps/network/transport.lua b/sys/apps/network/transport.lua index 3858383..9717e4e 100644 --- a/sys/apps/network/transport.lua +++ b/sys/apps/network/transport.lua @@ -5,7 +5,8 @@ * background read buffering ]]-- -local Event = require('opus.event') +local Crypto = require('opus.crypto.chacha20') +local Event = require('opus.event') local network = _G.network local os = _G.os @@ -32,7 +33,10 @@ end function transport.read(socket) local data = table.remove(socket.messages, 1) if data then - return unpack(data) + if socket.options.ENCRYPT then + return table.unpack(Crypto.decrypt(data[1], socket.enckey)), data[2] + end + return table.unpack(data) end end diff --git a/sys/apps/telnet.lua b/sys/apps/telnet.lua index 91b163e..ab9f024 100644 --- a/sys/apps/telnet.lua +++ b/sys/apps/telnet.lua @@ -9,7 +9,7 @@ local read = _G.read local shell = _ENV.shell local term = _G.term -local args = { ... } +local args, options = Util.parse(...) local remoteId = tonumber(table.remove(args, 1) or '') if not remoteId then @@ -22,13 +22,14 @@ if not remoteId then end if multishell then - multishell.setTitle(multishell.getCurrent(), 'Telnet ' .. remoteId) + multishell.setTitle(multishell.getCurrent(), + (options.s and 'Secure ' or 'Telnet ') .. remoteId) end local socket, msg, reason while true do - socket, msg, reason = Socket.connect(remoteId, 23) + socket, msg, reason = Socket.connect(remoteId, options.s and 22 or 23) if socket then break diff --git a/sys/modules/opus/crypto/chacha20.lua b/sys/modules/opus/crypto/chacha20.lua index c99a854..f28f8dc 100644 --- a/sys/modules/opus/crypto/chacha20.lua +++ b/sys/modules/opus/crypto/chacha20.lua @@ -166,10 +166,10 @@ local function decrypt(data, key) end local obj = {} -local mt = {['__index'] = obj} +local rng_mt = {['__index'] = obj} function obj:nextInt(byte) - if byte < 1 or byte > 6 then error("Can only return 1-6 bytes", 2) end + if not byte or byte < 1 or byte > 6 then error("Can only return 1-6 bytes", 2) end local output = 0 for i = 0, byte-1 do if #self.block == 0 then @@ -189,7 +189,7 @@ local function newRNG(seed) o.cnt = 0 o.block = {} - return setmetatable(o, mt) + return setmetatable(o, rng_mt) end return { diff --git a/sys/modules/opus/security.lua b/sys/modules/opus/security.lua index 599f793..4fb6f8d 100644 --- a/sys/modules/opus/security.lua +++ b/sys/modules/opus/security.lua @@ -1,6 +1,4 @@ local Config = require('opus.config') -local ECC = require('opus.crypto.ecc') -local Util = require('opus.util') local Security = { } @@ -13,32 +11,18 @@ function Security.hasPassword() return not not Security.getPassword() end -local function genKey() - local key = { } - for _ = 1, 32 do - table.insert(key, ("%02x"):format(math.random(0, 0xFF))) - end - return table.concat(key) -end - -function Security.getSecretKey() - local config = Config.load('os') - if not config.secretKey then - config.secretKey = genKey() - Config.update('os', config) - end - return Util.hexToByteArray(config.secretKey) -end - function Security.getIdentifier() local config = Config.load('os') - if config.identifier then - return config.identifier + + if not config.identifier then + local key = { } + for _ = 1, 32 do + table.insert(key, ("%02x"):format(math.random(0, 0xFF))) + end + config.identifier = table.concat(key) + + Config.update('os', config) end - -- preserve the hash the user generated - local identifier = ECC.publicKey(Security.getSecretKey()) - config.identifier = Util.byteArrayToHex(identifier) - Config.update('os', config) return config.identifier end diff --git a/sys/modules/opus/socket.lua b/sys/modules/opus/socket.lua index c1518fb..9f77f99 100644 --- a/sys/modules/opus/socket.lua +++ b/sys/modules/opus/socket.lua @@ -47,6 +47,9 @@ end function socketClass:write(data) if self.connected then + if self.options.ENCRYPT then + data = Crypto.encrypt({ data }, self.enckey) + end network.getTransport().write(self, { type = 'DATA', seq = self.wseq, @@ -70,7 +73,7 @@ function socketClass:setupEncryption(x) SHA.pbkdf2(self.sharedKey, x and "4sseed" or "3rseed", 1)) self.sharedKey = ECC.exchange(self.privKey, self.remotePubKey) - --self.enckey = SHA.pbkdf2(self.sharedKey, "1enc", 1) + self.enckey = SHA.pbkdf2(self.sharedKey, "1enc", 1) --self.hmackey = SHA.pbkdf2(self.sharedKey, "2hmac", 1) self.rseq = self.rrng:nextInt(5) self.wseq = self.wrng:nextInt(5) @@ -144,15 +147,15 @@ function Socket.connect(host, port, options) if e == 'modem_message' and sport == socket.sport and type(msg) == 'table' and - msg.dhost == socket.shost and - type(msg.pk) == 'string' then + msg.dhost == socket.shost then os.cancelTimer(timerId) - if msg.type == 'CONN' then + if msg.type == 'CONN' and type(msg.pk) == 'string' then socket.dport = dport socket.connected = true socket.remotePubKey = Util.hexToByteArray(msg.pk) + socket.options = msg.options or { } socket:setupEncryption(true) network.getTransport().open(socket) return socket @@ -210,7 +213,7 @@ function Socket.server(port, options) local socket = newSocket(msg.shost == os.getComputerID()) socket.dport = dport socket.dhost = msg.shost - socket.options = options + socket.options = options or { } if not Security.hasPassword() then socket.transmit(socket.dport, socket.sport, { @@ -227,6 +230,7 @@ function Socket.server(port, options) dhost = socket.dhost, shost = socket.shost, pk = Util.byteArrayToHex(socket.pubKey), + options = socket.options.ENCRYPT and { ENCRYPT = true }, }) network.getTransport().open(socket)