Sign Up
Log In
Log In
or
Sign Up
Places
All Projects
Status Monitor
Collapse sidebar
home:Ledest:erlang:23
erlang
3831-ssh-Disable-public_key-ssh-rsa-per-default...
Overview
Repositories
Revisions
Requests
Users
Attributes
Meta
File 3831-ssh-Disable-public_key-ssh-rsa-per-default.patch of Package erlang
From 59285df73841273adb111996cdb590ae1b86742b Mon Sep 17 00:00:00 2001 From: Hans Nilsson <hans@erlang.org> Date: Mon, 8 Mar 2021 12:56:13 +0100 Subject: [PATCH 1/3] ssh: Disable public_key ssh-rsa per default --- lib/ssh/src/ssh_auth.erl | 47 +++++++------- lib/ssh/src/ssh_transport.erl | 111 ++++++++++++++++++++++------------ 2 files changed, 100 insertions(+), 58 deletions(-) diff --git a/lib/ssh/src/ssh_auth.erl b/lib/ssh/src/ssh_auth.erl index 5bc2859b4e..fd0ca11e6e 100644 --- a/lib/ssh/src/ssh_auth.erl +++ b/lib/ssh/src/ssh_auth.erl @@ -172,26 +172,28 @@ publickey_msg([SigAlg, #ssh{user = User, SigAlgStr = atom_to_list(SigAlg), SigData = build_sig_data(SessionId, User, Service, PubKeyBlob, SigAlgStr), - Sig = case Key of - {ssh2_pubkey, PubKeyBlob} -> - ssh_transport:call_KeyCb(sign, [PubKeyBlob, SigData], Opts); - - {PrivKey, PubKeyBlob} -> - Hash = ssh_transport:sha(SigAlg), - ssh_transport:sign(SigData, Hash, PrivKey) - end, - - SigBlob = list_to_binary([?string(SigAlgStr), - ?binary(Sig)]), - - {#ssh_msg_userauth_request{user = User, - service = Service, - method = "publickey", - data = [?TRUE, - ?string(SigAlgStr), - ?binary(PubKeyBlob), - ?binary(SigBlob)]}, - Ssh}; + SigRes = case Key of + {ssh2_pubkey, PubKeyBlob} -> + {ok, ssh_transport:call_KeyCb(sign, [PubKeyBlob, SigData], Opts)}; + {PrivKey, PubKeyBlob} -> + ssh_transport:sign(SigData, SigAlg, PrivKey, Ssh) + end, + case SigRes of + {ok,Sig} -> + SigBlob = list_to_binary([?string(SigAlgStr), + ?binary(Sig)]), + + {#ssh_msg_userauth_request{user = User, + service = Service, + method = "publickey", + data = [?TRUE, + ?string(SigAlgStr), + ?binary(PubKeyBlob), + ?binary(SigBlob)]}, + Ssh}; + {error,_} -> + {not_ok, Ssh} + end; _ -> {not_ok, Ssh} @@ -545,13 +547,16 @@ pre_verify_sig(User, KeyBlob, #ssh{opts=Opts}) -> verify_sig(SessionId, User, Service, AlgBin, KeyBlob, SigWLen, #ssh{opts=Opts} = Ssh) -> try Alg = binary_to_list(AlgBin), + true = lists:member(list_to_existing_atom(Alg), + proplists:get_value(public_key, + ?GET_OPT(preferred_algorithms,Opts))), Key = ssh_message:ssh2_pubkey_decode(KeyBlob), % or exception true = ssh_transport:call_KeyCb(is_auth_key, [Key, User], Opts), PlainText = build_sig_data(SessionId, User, Service, KeyBlob, Alg), <<?UINT32(AlgSigLen), AlgSig:AlgSigLen/binary>> = SigWLen, <<?UINT32(AlgLen), _Alg:AlgLen/binary, ?UINT32(SigLen), Sig:SigLen/binary>> = AlgSig, - ssh_transport:verify(PlainText, ssh_transport:sha(Alg), Sig, Key, Ssh) + ssh_transport:verify(PlainText, list_to_existing_atom(Alg), Sig, Key, Ssh) catch _:_ -> false diff --git a/lib/ssh/src/ssh_transport.erl b/lib/ssh/src/ssh_transport.erl index 813d5ad350..65d695ecb1 100644 --- a/lib/ssh/src/ssh_transport.erl +++ b/lib/ssh/src/ssh_transport.erl @@ -52,7 +52,9 @@ extract_public_key/1, ssh_packet/2, pack/2, valid_key_sha_alg/3, - sha/1, sign/3, verify/5, + sign/3, sign/4, + verify/5, + sha/1, get_host_key/2, call_KeyCb/3, public_algo/1]). @@ -166,6 +168,7 @@ default_algorithms1(mac) -> default_algorithms1(public_key) -> supported_algorithms(public_key, [ + 'ssh-rsa', %% Gone in OpenSSH 7.3.p1: 'ssh-dss' ]); @@ -488,17 +491,22 @@ handle_kexdh_init(#ssh_msg_kexdh_init{e = E}, MyPrivHostKey = get_host_key(SignAlg, Opts), MyPubHostKey = extract_public_key(MyPrivHostKey), H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {E,Public,K}), - H_SIG = sign(H, sha(SignAlg), MyPrivHostKey), - {SshPacket, Ssh1} = - ssh_packet(#ssh_msg_kexdh_reply{public_host_key = {MyPubHostKey,SignAlg}, - f = Public, - h_sig = H_SIG - }, Ssh0), - {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}, - shared_secret = ssh_bits:mpint(K), - exchanged_hash = H, - session_id = sid(Ssh1, H)}}; - + case sign(H, SignAlg, MyPrivHostKey, Ssh0) of + {ok,H_SIG} -> + {SshPacket, Ssh1} = + ssh_packet(#ssh_msg_kexdh_reply{public_host_key = {MyPubHostKey,SignAlg}, + f = Public, + h_sig = H_SIG + }, Ssh0), + {ok, SshPacket, Ssh1#ssh{keyex_key = {{Private, Public}, {G, P}}, + shared_secret = ssh_bits:mpint(K), + exchanged_hash = H, + session_id = sid(Ssh1, H)}}; + {error,unsupported_sign_alg} -> + ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + io_lib:format("Unsupported algorithm ~p", [SignAlg]) + ) + end; true -> ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, io_lib:format("Kexdh init failed, received 'e' out of bounds~n E=~p~n P=~p", @@ -635,15 +643,21 @@ handle_kex_dh_gex_init(#ssh_msg_kex_dh_gex_init{e = E}, MyPrivHostKey = get_host_key(SignAlg, Opts), MyPubHostKey = extract_public_key(MyPrivHostKey), H = kex_hash(Ssh0, MyPubHostKey, sha(Kex), {Min,NBits,Max,P,G,E,Public,K}), - H_SIG = sign(H, sha(SignAlg), MyPrivHostKey), - {SshPacket, Ssh} = - ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = {MyPubHostKey,SignAlg}, - f = Public, - h_sig = H_SIG}, Ssh0), - {ok, SshPacket, Ssh#ssh{shared_secret = ssh_bits:mpint(K), - exchanged_hash = H, - session_id = sid(Ssh, H) - }}; + case sign(H, SignAlg, MyPrivHostKey, Ssh0) of + {ok,H_SIG} -> + {SshPacket, Ssh} = + ssh_packet(#ssh_msg_kex_dh_gex_reply{public_host_key = {MyPubHostKey,SignAlg}, + f = Public, + h_sig = H_SIG}, Ssh0), + {ok, SshPacket, Ssh#ssh{shared_secret = ssh_bits:mpint(K), + exchanged_hash = H, + session_id = sid(Ssh, H) + }}; + {error,unsupported_sign_alg} -> + ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + io_lib:format("Unsupported algorithm ~p", [SignAlg]) + ) + end; true -> ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, "Kexdh init failed, received 'k' out of bounds" @@ -712,16 +726,22 @@ handle_kex_ecdh_init(#ssh_msg_kex_ecdh_init{q_c = PeerPublic}, MyPrivHostKey = get_host_key(SignAlg, Opts), MyPubHostKey = extract_public_key(MyPrivHostKey), H = kex_hash(Ssh0, MyPubHostKey, sha(Curve), {PeerPublic, MyPublic, K}), - H_SIG = sign(H, sha(SignAlg), MyPrivHostKey), - {SshPacket, Ssh1} = - ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = {MyPubHostKey,SignAlg}, - q_s = MyPublic, - h_sig = H_SIG}, - Ssh0), - {ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve}, - shared_secret = ssh_bits:mpint(K), - exchanged_hash = H, - session_id = sid(Ssh1, H)}} + case sign(H, SignAlg, MyPrivHostKey, Ssh0) of + {ok,H_SIG} -> + {SshPacket, Ssh1} = + ssh_packet(#ssh_msg_kex_ecdh_reply{public_host_key = {MyPubHostKey,SignAlg}, + q_s = MyPublic, + h_sig = H_SIG}, + Ssh0), + {ok, SshPacket, Ssh1#ssh{keyex_key = {{MyPublic,MyPrivate},Curve}, + shared_secret = ssh_bits:mpint(K), + exchanged_hash = H, + session_id = sid(Ssh1, H)}}; + {error,unsupported_sign_alg} -> + ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, + io_lib:format("Unsupported algorithm ~p", [SignAlg]) + ) + end catch Class:Error -> ?DISCONNECT(?SSH_DISCONNECT_KEY_EXCHANGE_FAILED, @@ -864,7 +884,7 @@ extract_public_key(#{engine:=_, key_id:=_, algorithm:=Alg} = M) -> verify_host_key(#ssh{algorithms=Alg}=SSH, PublicKey, Digest, {AlgStr,Signature}) -> case atom_to_list(Alg#alg.hkey) of AlgStr -> - case verify(Digest, sha(Alg#alg.hkey), Signature, PublicKey, SSH) of + case verify(Digest, Alg#alg.hkey, Signature, PublicKey, SSH) of false -> {error, bad_signature}; true -> @@ -1402,6 +1422,19 @@ payload(<<PacketLen:32, PaddingLen:8, PayloadAndPadding/binary>>) -> Payload. %%%---------------------------------------------------------------- +%% sign(SigData, SignAlg, Key, Opts) when is_list(SignAlg) -> +%% sign(SigData, list_to_existing_atom(SignAlg), Key, Opts); + +sign(SigData, SignAlg, Key, #ssh{opts=Opts}) when is_atom(SignAlg) -> + case lists:member(SignAlg, + proplists:get_value(public_key, + ?GET_OPT(preferred_algorithms,Opts,[]))) of + true -> + {ok, sign(SigData, sha(SignAlg), Key)}; + false -> + {error, unsupported_sign_alg} + end. + sign(SigData, HashAlg, #{algorithm:=dss} = Key) -> mk_dss_sig(crypto:sign(dss, HashAlg, SigData, Key)); sign(SigData, HashAlg, #{algorithm:=SigAlg} = Key) -> @@ -1421,7 +1454,11 @@ mk_dss_sig(DerSignature) -> <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>>. %%%---------------------------------------------------------------- -verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key, _) -> +verify(PlainText, Alg, Sig, Key, Ssh) -> + do_verify(PlainText, sha(Alg), Sig, Key, Ssh). + + +do_verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key, _) -> case Sig of <<R:160/big-unsigned-integer, S:160/big-unsigned-integer>> -> Signature = public_key:der_encode('Dss-Sig-Value', #'Dss-Sig-Value'{r = R, s = S}), @@ -1429,7 +1466,7 @@ verify(PlainText, HashAlg, Sig, {_, #'Dss-Parms'{}} = Key, _) -> _ -> false end; -verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) -> +do_verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) -> case Sig of <<?UINT32(Rlen),R:Rlen/big-signed-integer-unit:8, ?UINT32(Slen),S:Slen/big-signed-integer-unit:8>> -> @@ -1440,14 +1477,14 @@ verify(PlainText, HashAlg, Sig, {#'ECPoint'{},_} = Key, _) -> false end; -verify(PlainText, HashAlg, Sig, #'RSAPublicKey'{}=Key, #ssh{role = server, - c_version = "SSH-2.0-OpenSSH_7."++_}) +do_verify(PlainText, HashAlg, Sig, #'RSAPublicKey'{}=Key, #ssh{role = server, + c_version = "SSH-2.0-OpenSSH_7."++_}) when HashAlg == sha256; HashAlg == sha512 -> %% Public key signing bug in in OpenSSH >= 7.2 public_key:verify(PlainText, HashAlg, Sig, Key) orelse public_key:verify(PlainText, sha, Sig, Key); -verify(PlainText, HashAlg, Sig, Key, _) -> +do_verify(PlainText, HashAlg, Sig, Key, _) -> public_key:verify(PlainText, HashAlg, Sig, Key). -- 2.26.2
Locations
Projects
Search
Status Monitor
Help
OpenBuildService.org
Documentation
API Documentation
Code of Conduct
Contact
Support
@OBShq
Terms
openSUSE Build Service is sponsored by
The Open Build Service is an
openSUSE project
.
Sign Up
Log In
Places
Places
All Projects
Status Monitor