File 2778-ssh-Redesigned-ssh_file-is_host_key.patch of Package erlang
From 9a9dcf407600ab99b4ad6b2b44b1f2bd3bc6bbce Mon Sep 17 00:00:00 2001
From: Hans Nilsson <hans@erlang.org>
Date: Tue, 18 Feb 2020 17:57:08 +0100
Subject: [PATCH 08/10] ssh: Redesigned ssh_file:is_host_key
---
lib/ssh/src/ssh_file.erl | 94 +++++++++++++++++++++++++++++-------------------
1 file changed, 57 insertions(+), 37 deletions(-)
diff --git a/lib/ssh/src/ssh_file.erl b/lib/ssh/src/ssh_file.erl
index 367b821ead..14933023a3 100644
--- a/lib/ssh/src/ssh_file.erl
+++ b/lib/ssh/src/ssh_file.erl
@@ -75,20 +75,10 @@ user_key(Algorithm, Opts) ->
read_ssh_key_file(user, private, Algorithm, Opts).
is_host_key(Key, PeerName, Algorithm, Opts) ->
- case ssh_transport:valid_key_sha_alg(public, Key, Algorithm) of
- true ->
- case file:open(file_name(user, "known_hosts", Opts), [read, binary]) of
- {ok, Fd} ->
- Res = is_host_key_fd(Fd, Key, replace_localhost(PeerName)),
- file:close(Fd),
- Res;
- _ ->
- false
- end;
- false ->
- false
- end.
-
+ KeyType = erlang:atom_to_binary(Algorithm, latin1),
+ Host = list_to_binary(replace_localhost(PeerName)),
+ Dir = ssh_dir(user, Opts),
+ lookup_host_keys(Host, KeyType, Key, filename:join(Dir,"known_hosts")).
add_host_key(Host, Key, Opts) ->
Host1 = add_ip(replace_localhost(Host)),
@@ -149,31 +139,61 @@ decode_key(Base64EncodedKey) ->
%%%---------------- CLIENT FUNCTIONS ------------------------------
-is_host_key_fd(Fd, KeyToMatch, Host) ->
- case io:get_line(Fd, '') of
- eof ->
- false;
- {error,_} ->
- %% Rare... For example NFS errors
- false;
- Line ->
- try public_key:ssh_decode(Line, known_hosts) of
- [{Key, Attributes}] when KeyToMatch == Key ->
- HostList = proplists:get_value(hostnames, Attributes),
- case lists:member(Host, HostList) of
- true ->
- true;
- _ ->
- is_host_key_fd(Fd, KeyToMatch, Host)
- end;
- _ ->
- is_host_key_fd(Fd, KeyToMatch, Host)
- catch
- _:_ ->
- false
- end
+lookup_host_keys(Host, KeyType, Key, File) ->
+ case file:read_file(File) of
+ {ok,Bin} ->
+ Lines = binary:split(Bin, <<"\n">>, [global,trim_all]),
+ find_key(Host, KeyType, Key, Lines);
+ _ ->
+ false
end.
+find_key(Host, KeyType, Key, [Line|Lines]) ->
+ case find_key_in_line(Host, KeyType, Key, binary:split(Line, <<" ">>, [global,trim_all])) of
+ true ->
+ true;
+ false ->
+ find_key(Host, KeyType, Key, Lines)
+ end;
+find_key(_, _, _, _) ->
+ false.
+
+
+find_key_in_line(_Host, _KeyType, _Key, [<<"#",_/binary>> |_]) ->
+ false;
+find_key_in_line(Host, KeyType, Key, [HostNames, KeyType, Base64EncodedKey, _Comment]) ->
+ host_match(Host, HostNames) andalso
+ Key == decode_key(Base64EncodedKey);
+find_key_in_line(Host, KeyType, Key, [HostNames, KeyType, Base64EncodedKey]) ->
+ host_match(Host, HostNames) andalso
+ Key == decode_key(Base64EncodedKey);
+find_key_in_line(Host, KeyType, Key, [_Option | [_,_,_|_]=Rest]) ->
+ %% Dont care for options
+ find_key_in_line(Host, KeyType, Key, Rest);
+find_key_in_line(_, _, _, _) ->
+ false.
+
+
+host_match(Host, HostNames) ->
+ Sz = size(Host),
+ host_match1(Host, Sz, binary:split(HostNames, <<",">>, [global])).
+
+host_match1(Host, Sz, [Pat|Pats]) ->
+
+ case Pat of
+ Host ->
+ true;
+ <<Host:Sz/binary,":",_Port/binary>> ->
+ true;
+ <<"[",Host:Sz/binary,"]:",_Port/binary>> ->
+ true;
+ _ ->
+ host_match1(Host, Sz, Pats)
+ end;
+host_match1(_, _, []) ->
+ false.
+
+
%%%--------------------------------
%% in: "host" out: "host,1.2.3.4.
--
2.16.4