Begin attempting to implement encryption
All checks were successful
Build & Test / nix-build (push) Successful in 1m29s
All checks were successful
Build & Test / nix-build (push) Successful in 1m29s
This commit is contained in:
parent
6ad910d4b4
commit
c26fc23a33
@ -52,7 +52,7 @@ defmodule Amethyst.ConnectionHandler do
|
||||
Logger.info("Connection #{inspect(socket)} closed.")
|
||||
Process.exit(self(), :normal)
|
||||
{:disconnect, reason} ->
|
||||
disconnect(socket, reason, connstate, version)
|
||||
disconnect(socket, reason, connstate, version, state)
|
||||
Process.exit(self(), :normal)
|
||||
{:set_state, newstate} ->
|
||||
Logger.debug("Switching to state #{newstate} from #{connstate}")
|
||||
@ -60,6 +60,12 @@ defmodule Amethyst.ConnectionHandler do
|
||||
{:set_version, newversion} ->
|
||||
Logger.debug("Switching to version #{newversion} from #{version}")
|
||||
loop(socket, connstate, newversion, state)
|
||||
{:set_encryption, secret} ->
|
||||
Logger.debug("Enabling encryption with shared secret #{inspect(secret)}")
|
||||
encryption_state = :crypto.crypto_init(:aes_128_cfb8, secret, secret, true)
|
||||
decryption_state = :crypto.crypto_init(:aes_128_cfb8, secret, secret, false)
|
||||
state = state |> Map.put(:encryption_state, encryption_state) |> Map.put(:decryption_state, decryption_state)
|
||||
loop(socket, connstate, version, state)
|
||||
{:set_position, position} ->
|
||||
prev_position = Map.get(state, :position)
|
||||
state = Map.put(state, :position, position)
|
||||
@ -97,8 +103,8 @@ defmodule Amethyst.ConnectionHandler do
|
||||
end
|
||||
loop(socket, connstate, version, state)
|
||||
{:send_packet, packet} ->
|
||||
# Logger.debug("Sending packet #{inspect(packet)}")
|
||||
send_packet(socket, connstate, packet, version)
|
||||
Logger.debug("Sending packet #{inspect(packet)}")
|
||||
send_packet(socket, connstate, packet, version, state)
|
||||
loop(socket, connstate, version, state)
|
||||
after 0 ->
|
||||
receive do
|
||||
@ -210,7 +216,13 @@ defmodule Amethyst.ConnectionHandler do
|
||||
|
||||
defp handle_packet(id, data, connstate, version, state) do
|
||||
try do
|
||||
packet = connstate.deserialize(id, version, data)
|
||||
packet = case Map.get(state, :decryption_state) do
|
||||
nil ->
|
||||
connstate.deserialize(id, version, data)
|
||||
dstate ->
|
||||
data = :crypto.crypto_update(dstate, data)
|
||||
connstate.deserialize(id, version, data)
|
||||
end
|
||||
case connstate.handle(packet, version, state) do
|
||||
:ok -> state
|
||||
{:error, reason} ->
|
||||
@ -237,11 +249,17 @@ defmodule Amethyst.ConnectionHandler do
|
||||
end
|
||||
end
|
||||
|
||||
defp send_packet(socket, connstate, packet, version) do
|
||||
defp send_packet(socket, connstate, packet, version, state) do
|
||||
try do
|
||||
data = connstate.serialize(packet, version)
|
||||
length = byte_size(data) |> Amethyst.Minecraft.Write.varint()
|
||||
case Map.get(state, :encryption_state) do
|
||||
nil ->
|
||||
:gen_tcp.send(socket, length <> data)
|
||||
estate ->
|
||||
encrypted = :crypto.crypto_update(estate, length <> data)
|
||||
:gen_tcp.send(socket, encrypted)
|
||||
end
|
||||
rescue
|
||||
e ->
|
||||
Logger.error("Error sending packet #{inspect(packet)} in state #{connstate}: #{Exception.format(:error, e, __STACKTRACE__)}")
|
||||
@ -249,12 +267,12 @@ defmodule Amethyst.ConnectionHandler do
|
||||
end
|
||||
end
|
||||
|
||||
defp disconnect(socket, reason, connstate, version) do
|
||||
defp disconnect(socket, reason, connstate, version, state) do
|
||||
Logger.info("Disconnecting connection #{inspect(socket)}")
|
||||
Logger.debug("Disconnecting connection #{inspect(socket)}: #{reason}")
|
||||
case connstate.disconnect(reason) do
|
||||
nil -> nil
|
||||
packet -> send_packet(socket, connstate, packet, version)
|
||||
packet -> send_packet(socket, connstate, packet, version, state)
|
||||
end
|
||||
:gen_tcp.close(socket)
|
||||
end
|
||||
|
@ -60,10 +60,19 @@ defmodule Amethyst.ConnectionState.Login do
|
||||
Macros.defpacket_serverbound :login_acknowledged, 0x03, 767, []
|
||||
Macros.defpacket_serverbound :cookie_response, 0x04, 767, [identifier: :string, payload: {:optional, :byte_array}]
|
||||
|
||||
def handle(%{packet_type: :login_start, name: name, player_uuid: player_uuid}, 767, _state) do
|
||||
def handle(%{packet_type: :login_start, name: name, player_uuid: player_uuid}, 767, state) do
|
||||
Logger.debug("Received login start for #{name} with UUID #{player_uuid}")
|
||||
if Application.fetch_env!(:amethyst, :encryption) do
|
||||
raise RuntimeError, "Encryption is not currently supported"
|
||||
if Application.get_env(:amethyst, :encryption, true) do
|
||||
verify_token = :crypto.strong_rand_bytes(4)
|
||||
public_key = Amethyst.Keys.get_pub()
|
||||
send(self(), {:send_packet, %{
|
||||
packet_type: :encryption_request,
|
||||
server_id: "",
|
||||
public_key: public_key,
|
||||
verify_token: verify_token,
|
||||
should_authenticate: Application.get_env(:amethyst, :auth, false)
|
||||
}})
|
||||
state |> Map.put(:verify_token, verify_token) |> Map.put(:name, name) |> Map.put(:uuid, player_uuid)
|
||||
else
|
||||
send(self(), {:send_packet, %{
|
||||
packet_type: :login_success,
|
||||
@ -75,7 +84,23 @@ defmodule Amethyst.ConnectionState.Login do
|
||||
:ok
|
||||
end
|
||||
end
|
||||
|
||||
def handle(%{packet_type: :encryption_response, shared_secret: secret, verify_token: verify_token}, 767, state) do
|
||||
secret = Amethyst.Keys.decrypt(secret)
|
||||
verify_token = Amethyst.Keys.decrypt(verify_token)
|
||||
if verify_token == Map.get(state, :verify_token, :never) do
|
||||
send(self(), {:set_encryption, secret})
|
||||
send(self(), {:send_packet, %{
|
||||
packet_type: :login_success,
|
||||
uuid: Map.get(state, :uuid),
|
||||
username: Map.get(state, :name),
|
||||
properties: [],
|
||||
strict_error_handling: true
|
||||
}})
|
||||
:ok
|
||||
else
|
||||
raise RuntimeError, "Invalid verify token. Broken encryption?"
|
||||
end
|
||||
end
|
||||
def handle(%{packet_type: :login_acknowledged}, 767, _state) do
|
||||
Logger.debug("Received login acknowledged")
|
||||
send(self(), {:set_state, Amethyst.ConnectionState.Configuration})
|
||||
|
@ -2,6 +2,6 @@ import Config
|
||||
|
||||
config :amethyst,
|
||||
port: 25599, # Bogus port for testing, avoids unexpected conflicts
|
||||
encryption: false, # Whether or not to request encryption from clients.
|
||||
encryption: true, # Whether or not to request encryption from clients.
|
||||
auth: false, # Whether or not users should be authenticated with Mojang.
|
||||
default_game: Example.Game # Which game new players should be sent to
|
||||
|
Loading…
Reference in New Issue
Block a user