Last active
November 11, 2017 07:19
-
-
Save pmeinhardt/8c746ebe8d7397a2a07dabb1ba7ab30c to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# Example code for connecting to OpenSSH ssh-agent and retrieving key information, | |
# quickly hacked together so please excuse bad naming and style etc. | |
# | |
# This is just intended to provide a starting point | |
# | |
# http://api.libssh.org/rfc/PROTOCOL.agent | |
# https://github.com/paramiko/paramiko/blob/master/paramiko/agent.py | |
# Message constants | |
ssh2_agentc_request_identities = 11 | |
ssh2_agent_identities_answer = 12 | |
# Set up connection | |
address = {:local, System.get_env("SSH_AUTH_SOCK")} | |
sockopts = [:local, :binary, {:packet, 4}, {:active, false}] | |
defmodule SSHAgent do | |
defmodule Message do | |
@type t :: %__MODULE__{type: integer, data: binary} | |
defstruct [:type, :data] | |
@spec init(integer) :: Message.t | |
def init(type), do: init(type, <<>>) | |
@spec init(integer, binary) :: Message.t | |
def init(type, data), do: %Message{type: type, data: data} | |
@spec decode(binary) :: Message.t | |
def decode(<<type::integer-size(8), data::binary>>), do: %Message{type: type, data: data} | |
@spec encode(%{type: integer, data: binary}) :: binary | |
def encode(%{type: type, data: data}), do: <<type::integer-size(8), data::binary>> | |
end | |
defmodule Key do | |
defstruct [:blob, :comment] | |
def read_all(data, count), do: read_all(data, count, []) | |
def read_all(_, 0, list), do: list | |
def read_all(data, count, list) do | |
<<len1::unsigned-big-integer-size(32), rem1::binary>> = data | |
<<blob::binary-size(len1), rem2::binary>> = rem1 | |
<<len2::unsigned-big-integer-size(32), rem3::binary>> = rem2 | |
<<comment::binary-size(len2), rest::binary>> = rem3 | |
key = %Key{blob: blob, comment: comment} | |
read_all(rest, count - 1, [key | list]) | |
end | |
end | |
end | |
alias SSHAgent.{Key,Message} | |
req = Message.init(ssh2_agentc_request_identities) | |
with {:ok, sock} <- :gen_tcp.connect(address, 0, sockopts), | |
:ok <- :gen_tcp.send(sock, Message.encode(req)) do | |
# IO.inspect :inet.getstat(sock) | |
case :gen_tcp.recv(sock, 0) do | |
{:ok, packet} -> | |
with msg <- Message.decode(packet) do | |
case msg.type do | |
^ssh2_agent_identities_answer -> | |
<<count::integer-size(32), keydata::binary>> = msg.data | |
keys = Key.read_all(keydata, count) | |
Enum.each(keys, fn key -> | |
IO.puts "Comment: #{key.comment}" | |
IO.puts Base.encode64(key.blob) | |
end) | |
_ -> IO.puts "could not get keys from ssh-agent" | |
end | |
end | |
other -> | |
IO.inspect other | |
end | |
# IO.inspect :inet.getstat(sock) | |
:ok = :gen_tcp.close(sock) | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment