moving onwards
This commit is contained in:
@@ -4,9 +4,6 @@ local program_string = program_name .. "_" .. program_version
|
||||
|
||||
local component = require("component")
|
||||
local internet = component.internet
|
||||
local event = require("event")
|
||||
local computer = require("computer")
|
||||
local serialize = require("serialize")
|
||||
|
||||
local function lazy_require(name)
|
||||
local this = {}
|
||||
@@ -16,15 +13,16 @@ local function lazy_require(name)
|
||||
module = module or require(name)
|
||||
return module[key]
|
||||
end,
|
||||
__call = function(_, ...)
|
||||
module = module or require(name)
|
||||
return module(...)
|
||||
end
|
||||
__call = function(_, ...)
|
||||
module = module or require(name)
|
||||
return module(...)
|
||||
end
|
||||
})
|
||||
return this
|
||||
end
|
||||
|
||||
local curve25519 = lazy_require("curve25519")
|
||||
local x25519 = lazy_require("x25519")
|
||||
local sha2 = lazy_require("sha256")
|
||||
|
||||
local function parse_ssh_version(str)
|
||||
local proto, software, comments = str:match("^SSH%-(%d+%.%d+)%-(%S+)%s?(.*)\r\n$")
|
||||
@@ -58,6 +56,79 @@ local SSH_MSG_SERVICE_ACCEPT = 6
|
||||
local SSH_MSG_KEXINIT = 20
|
||||
local SSH_MSG_NEWKEYS = 21
|
||||
|
||||
-- RFC 4253 7.1: first entry in client list that also appears in server_list wins
|
||||
local function negotiate_one(client_list, server_list)
|
||||
local server_set = {}
|
||||
for _, name in ipairs(server_list) do server_set[name] = true end
|
||||
for _, name in ipairs(client_list) do
|
||||
if server_set[name] then return name end
|
||||
end
|
||||
return nil
|
||||
end
|
||||
|
||||
local function negotiate(client_algs, server_kex)
|
||||
local chosen = {}
|
||||
for field, _ in pairs(client_algs) do
|
||||
chosen[field] = negotiate_one(client_algs[field] or {}, server_kex[field] or {})
|
||||
local is_language_field = field:find("^languages_")
|
||||
if not chosen[field] and not is_language_field then
|
||||
return nil, "no agreement on " .. field
|
||||
end
|
||||
end
|
||||
return chosen
|
||||
end
|
||||
|
||||
local function xor_with_byte(s, b)
|
||||
local out = {}
|
||||
for i = 1, #s do
|
||||
out[i] = string.char(string.byte(s, i) ~ b)
|
||||
end
|
||||
return table.concat(out)
|
||||
end
|
||||
|
||||
local function hmac(hash_fn, block_size, key, message)
|
||||
if #key > block_size then key = hash_fn(key) end
|
||||
if #key < block_size then key = key .. string.rep('\0', block_size - #key) end
|
||||
return hash_fn(xor_with_byte(key, 0x5c) .. hash_fn(xor_with_byte(key, 0x36) .. message))
|
||||
end
|
||||
|
||||
local mac_algorithms_priority = {
|
||||
"hmac-sha2-256",
|
||||
"hmac-sha2-512",
|
||||
--"hmac-sha1"
|
||||
}
|
||||
|
||||
local mac_algorithms = {
|
||||
["hmac-sha2-256"] = function(key, message) return hmac(sha2.sha256, 64, key, message) end,
|
||||
["hmac-sha2-512"] = function(key, message) return hmac(sha2.sha512, 128, key, message) end,
|
||||
--["hmac-sha1"] = function(key, message) return hmac(sha1, 64, key, message) end,
|
||||
}
|
||||
|
||||
local encryption_algorithms_priority = {
|
||||
"chacha20-poly1305@openssh.com",
|
||||
-- aes128-gcm@openssh.com
|
||||
-- aes256-gcm@openssh.com
|
||||
-- aes128-ctr
|
||||
-- aes192-ctr
|
||||
-- aes256-ctr
|
||||
}
|
||||
local encryption_algorithms = {
|
||||
["chacha20-poly1305@openssh.com"] = nil
|
||||
}
|
||||
|
||||
local server_host_key_algorithms_priority = {
|
||||
--[[
|
||||
"rsa-sha2-512",
|
||||
"rsa-sha2-256",
|
||||
"ecdsa-sha2-nistp256",
|
||||
"ssh-ed25519"
|
||||
]]
|
||||
}
|
||||
|
||||
local server_host_key_algorithms = {
|
||||
|
||||
}
|
||||
|
||||
local function socket()
|
||||
local this = {}
|
||||
local _sock
|
||||
@@ -89,7 +160,11 @@ local function socket()
|
||||
while #_read_buf < n do
|
||||
local chunk, err = _sock.read(n - #_read_buf)
|
||||
if chunk == nil then return nil, err end
|
||||
_read_buf = _read_buf .. chunk
|
||||
if chunk == "" then
|
||||
coroutine.yield()
|
||||
else
|
||||
_read_buf = _read_buf .. chunk
|
||||
end
|
||||
end
|
||||
local to_return = _read_buf:sub(1, n);
|
||||
_read_buf = _read_buf:sub(n + 1, -1)
|
||||
@@ -239,26 +314,47 @@ end
|
||||
local sock = socket()
|
||||
sock.connect("localhost", 22)
|
||||
-- RFC 4253: The maximum length of the string is 255 characters
|
||||
local server_protoversion, server_softwareversion, server_comments = parse_ssh_version(sock.read_until_crlf(255))
|
||||
local server_version_raw = sock.read_until_crlf(255)
|
||||
local server_protoversion, server_softwareversion, server_comments = parse_ssh_version(server_version_raw)
|
||||
if server_protoversion ~= "2.0" then
|
||||
return
|
||||
end
|
||||
sock.write(encode_ssh_version("2.0", program_string))
|
||||
print(sock.parse_kexinit(sock.read_packet()))
|
||||
--[[
|
||||
|
||||
local client_version_line = encode_ssh_version("2.0", program_string)
|
||||
sock.write(client_version_line)
|
||||
|
||||
local V_C = client_version_line:gsub("\r\n$", "")
|
||||
local V_S = server_version_raw:gsub("\r\n$", "")
|
||||
|
||||
local I_S, kerr = sock.read_packet()
|
||||
if not I_S then
|
||||
print("failed to read server KEXINIT: " .. tostring(kerr))
|
||||
return
|
||||
end
|
||||
local server_kex, perr = sock.parse_kexinit(I_S)
|
||||
if not server_kex then
|
||||
print("failed to parse server KEXINIT: " .. tostring(perr))
|
||||
return
|
||||
end
|
||||
|
||||
local my_algs = {
|
||||
kex_algorithms = {},
|
||||
server_host_key_algorithms = {},
|
||||
encryption_algorithms_client_to_server = {},
|
||||
encryption_algorithms_server_to_client = {},
|
||||
mac_algorithms_client_to_server = {},
|
||||
mac_algorithms_server_to_client = {},
|
||||
kex_algorithms = { "curve25519-sha256" },
|
||||
server_host_key_algorithms = server_host_key_algorithms,
|
||||
encryption_algorithms_client_to_server = encryption_algorithms_priority,
|
||||
encryption_algorithms_server_to_client = encryption_algorithms_priority,
|
||||
mac_algorithms_client_to_server = mac_algorithms_priority,
|
||||
mac_algorithms_server_to_client = mac_algorithms_priority,
|
||||
compression_algorithms_client_to_server = { "none" },
|
||||
compression_algorithms_server_to_client = { "none" },
|
||||
languages_client_to_server = {},
|
||||
languages_server_to_client = {},
|
||||
}
|
||||
|
||||
local my_kexinit_payload = sock.build_kexinit(my_algs)
|
||||
sock.write_packet(my_kexinit_payload)
|
||||
]]
|
||||
local I_C = sock.build_kexinit(my_algs)
|
||||
sock.write_packet(I_C)
|
||||
|
||||
local chosen, nerr = negotiate(my_algs, server_kex)
|
||||
if not chosen then
|
||||
print("algorithm negotiation failed: " .. tostring(nerr))
|
||||
return
|
||||
end
|
||||
|
||||
Reference in New Issue
Block a user