Class: Trezor::Agent

Inherits:
Object
  • Object
show all
Includes:
Utils
Defined in:
lib/trezor/agent.rb

Constant Summary collapse

MAPPING =
{
  Net::SSH::Authentication::Agent::SSH2_AGENT_REQUEST_VERSION => :send_version,
  Net::SSH::Authentication::Agent::SSH2_AGENT_REQUEST_IDENTITIES => :list_identities,
  Net::SSH::Authentication::Agent::SSH2_AGENT_SIGN_REQUEST => :sign_challenge
}

Instance Method Summary collapse

Constructor Details

#initialize(socket_path:, key_manager:) ⇒ Agent

Returns a new instance of Agent.



19
20
21
22
# File 'lib/trezor/agent.rb', line 19

def initialize(socket_path:, key_manager:)
  @socket_path = socket_path
  @key_manager = key_manager
end

Instance Method Details

#failure_messageObject



66
67
68
# File 'lib/trezor/agent.rb', line 66

def failure_message
  Buffer.from(:byte, Net::SSH::Authentication::Agent::SSH_AGENT_FAILURE)
end

#list_identities(body) ⇒ Object



57
58
59
60
61
62
63
64
# File 'lib/trezor/agent.rb', line 57

def list_identities(body)
  Buffer.from(
    :byte, Net::SSH::Authentication::Agent::SSH2_AGENT_IDENTITIES_ANSWER,
    :long, @key_manager.identities.count,
    :string,
    @key_manager.map { |i| [i.key.to_blob, i.key_name] }.flatten
  )
end

#on_requestObject



28
29
30
31
32
33
34
# File 'lib/trezor/agent.rb', line 28

def on_request
  socket = server.accept
  Thread.new do
    yield(socket)
    socket.close
  end
end

#read_packet(socket) ⇒ Object



80
81
82
83
84
85
86
# File 'lib/trezor/agent.rb', line 80

def read_packet(socket)
  buffer = Buffer.new(socket.read(4))
  buffer.append(socket.read(buffer.read_long))
  type = buffer.read_byte
  #debug { "received agent packet #{type} len #{buffer.length - 4}" }
  return type, buffer
end

#runObject



36
37
38
39
40
41
42
43
44
45
46
47
48
49
# File 'lib/trezor/agent.rb', line 36

def run
  while true
    on_request do |socket|
      while true
        type, body = read_packet(socket)
        break unless method_name = MAPPING[type]
        response = send(method_name, body)
        socket.write(Buffer.from(:string, response.to_s))
      end
    end
  end
ensure
  File.unlink(@socket_path) if File.exists?(@socket_path)
end

#send_version(body) ⇒ Object



51
52
53
54
55
# File 'lib/trezor/agent.rb', line 51

def send_version(body)
  # Net::SSH::Authentication::Agent::SSH2_AGENT_VERSION_RESPONSE
  buffer = body.read
  Buffer.from(:byte, 2, :long, 0)
end

#serverObject



24
25
26
# File 'lib/trezor/agent.rb', line 24

def server
  @server ||= UNIXServer.new(@socket_path)
end

#sign_challenge(body) ⇒ Object



70
71
72
73
74
75
76
77
78
# File 'lib/trezor/agent.rb', line 70

def sign_challenge(body)
  server_key = body.read_buffer.read_key
  blob = body.read_buffer
  return failure_message unless signature = @key_manager.sign(server_key, blob)
  Buffer.from(
    :byte, Net::SSH::Authentication::Agent::SSH2_AGENT_SIGN_RESPONSE,
    :string, signature
  )
end