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

openSUSE Build Service is sponsored by