File 3081-ssh-Add-size-guards-for-pre-authentication-messages.patch of Package erlang
From 5e05ecc4307fb0299a5f0bc288c2553544108179 Mon Sep 17 00:00:00 2001
From: Jakub Witczak <kuba@erlang.org>
Date: Mon, 9 Mar 2026 12:00:54 +0100
Subject: [PATCH] ssh: Add size guards for pre-authentication messages
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Add explicit size validation for SSH messages decoded before user
authentication to improve defense-in-depth against DoS attacks.
Changes:
- Add size limit constants in ssh.hrl with RFC references
- Update MAX_HOST_KEY_SIZE (4096→8192) and MAX_SIGNATURE_SIZE (1536→2048)
for general use beyond MLKEM
- Add size_error/1 helper for multi-field validation
- Add decode guards for pre-auth message types:
* Transport: DISCONNECT, IGNORE, DEBUG
* Key exchange: KEXINIT, DH (INIT/REPLY), DH-GEX (GROUP/INIT/REPLY),
ECDH (INIT/REPLY), MLKEM (REPLY refactored)
* Service: SERVICE_REQUEST, SERVICE_ACCEPT, EXT_INFO
All guards report specific error tuples with actual size and limit.
Backward compatibility maintained for ancient OpenSSH clients.
---
lib/ssh/src/ssh.hrl | 47 +++++++-
lib/ssh/src/ssh_message.erl | 221 +++++++++++++++++++++---------------
2 files changed, 172 insertions(+), 96 deletions(-)
diff --git a/lib/ssh/src/ssh.hrl b/lib/ssh/src/ssh.hrl
index ef911c5da4..f9e359bfb0 100644
--- a/lib/ssh/src/ssh.hrl
+++ b/lib/ssh/src/ssh.hrl
@@ -49,9 +49,52 @@
-define(MLKEM768_INIT_SIZE, ?MLKEM768_PUBLICKEY_SIZE + ?X25519_PUBLICKEY_SIZE). % NIST FIPS 203: 1184 + 32
-define(MLKEM768_REPLY_SIZE, ?MLKEM768_CIPHERTEXT_SIZE + ?X25519_PUBLICKEY_SIZE). % NIST FIPS 203: 1088 + 32
+%% Pre-authentication message size limits
+%% Transport layer (RFC 4253 Section 11)
+
+%% OpenSSH uses 1024-byte C buffer (packet.c, commit d4a8b7e34);
+%% vsnprintf reserves 1 byte for null terminator, max wire length is
+%% 1023
+-define(MAX_DISCONNECT_DESC_SIZE, 1023).
+%% Practical limit (RFC 3066: subtags max 8 chars, no overall limit
+%% specified)
+-define(MAX_LANG_SIZE, 64).
+% RFC 4253 Section 6.1 (32768 byte payload)
+-define(MAX_IGNORE_DATA_SIZE, 32768).
+%% Limit for receiving debug messages from peers; intentionally larger
+%% than OpenSSH (1023 bytes, packet.c commit d4a8b7e34) to accommodate
+%% verbose diagnostics from various SSH implementations
+-define(MAX_DEBUG_MSG_SIZE, 4096).
+
+%% Key exchange (RFC 4253 Section 7-8, RFC 4419, RFC 5656, RFC 8270)
+
+%% RFC 4253 Section 6.1 (32768 byte payload, real-world: 500-2000 bytes)
+-define(MAX_KEXINIT_SIZE, 32768).
+% RFC 4253 Section 8 (8192-bit = 1024 bytes + mpint encoding overhead)
+-define(MAX_DH_MPINT_SIZE, 1032).
+%% RFC 5656 Section 4 (P-521 uncompressed: 133 bytes)
+-define(MAX_ECDH_POINT_SIZE, 256).
+
+%% Service request (RFC 4253 Section 10, RFC 8308)
+
+%% RFC 4251 Section 6 (SSH name limit)
+-define(MAX_SERVICE_NAME_SIZE, 64).
+% Practical limit (RFC 8308 defines no maximum)
+-define(MAX_EXT_INFO_SIZE, 8192).
+% Practical limit (typical: 200-400 bytes, allows future extensions)
+-define(MAX_EXT_VALUE_SIZE, 1024).
+
%% Cryptographic limits
--define(MAX_HOST_KEY_SIZE, 4096). % RSA-4096 + ASN.1/SSH encoding
--define(MAX_SIGNATURE_SIZE, 1536). % RSA-8192 (1044) + margin for future algorithms
+
+%% Accommodates RSA-8192 keys (~1046 bytes, largest supported key type)
+%% and post-quantum algorithms (Dilithium5: 2592 bytes). Other key
+%% types are much smaller: DSA-1024 (~431 bytes), ECDSA P-521 (~172
+%% bytes), Ed25519 (~51 bytes)
+-define(MAX_HOST_KEY_SIZE, 4096).
+%% Accommodates RSA-8192 signatures (~1039 bytes) and post-quantum
+%% algorithms (Dilithium5: 4595 bytes). Provides consistent PQ
+%% readiness with MAX_HOST_KEY_SIZE.
+-define(MAX_SIGNATURE_SIZE, 5120).
-define(SUPPORTED_AUTH_METHODS, "publickey,keyboard-interactive,password").
diff --git a/lib/ssh/src/ssh_message.erl b/lib/ssh/src/ssh_message.erl
index 918560c84c..7de05f7052 100644
--- a/lib/ssh/src/ssh_message.erl
+++ b/lib/ssh/src/ssh_message.erl
@@ -469,32 +469,48 @@ decode(<<?BYTE(?SSH_MSG_USERAUTH_INFO_RESPONSE), ?UINT32(Num), Data/binary>>) ->
num_responses = Num,
data = Data};
-decode(<<?BYTE(?SSH_MSG_EXT_INFO), ?UINT32(N), BinData/binary>>) ->
+decode(<<?BYTE(?SSH_MSG_EXT_INFO), ?UINT32(N), BinData/binary>>)
+ when byte_size(BinData) =< ?MAX_EXT_INFO_SIZE ->
Data = bin_foldr(
fun(Bin,Acc) when length(Acc) == N ->
{Bin,Acc};
- (<<?DEC_BIN(V0,__0), ?DEC_BIN(V1,__1), Rest/binary>>, Acc) ->
- {Rest,[{binary_to_list(V0),binary_to_list(V1)}|Acc]}
+ (<<?DEC_BIN(V0, L0), ?DEC_BIN(V1, L1), Rest/binary>>, Acc)
+ when L0 =< ?MAX_SERVICE_NAME_SIZE, L1 =< ?MAX_EXT_VALUE_SIZE ->
+ {Rest,[{binary_to_list(V0),binary_to_list(V1)}|Acc]};
+ (<<?DEC_BIN(_, L0), ?DEC_BIN(_, L1), _/binary>>, _Acc) ->
+ throw({error,
+ size_error([{ext_info_name_too_large, L0, ?MAX_SERVICE_NAME_SIZE},
+ {ext_info_value_too_large, L1, ?MAX_EXT_VALUE_SIZE}])})
end, [], BinData),
- #ssh_msg_ext_info{
- nr_extensions = N,
- data = Data
- };
+ #ssh_msg_ext_info{nr_extensions = N, data = Data};
+decode(<<?BYTE(?SSH_MSG_EXT_INFO), ?UINT32(_), BinData/binary>>) ->
+ throw({error, {ext_info_too_large, byte_size(BinData), ?MAX_EXT_INFO_SIZE}});
%%% Keyexchange messages
-decode(<<?BYTE(?SSH_MSG_KEXINIT), Cookie:128, Data/binary>>) ->
+decode(<<?BYTE(?SSH_MSG_KEXINIT), Cookie:128, Data/binary>>)
+ when byte_size(Data) =< ?MAX_KEXINIT_SIZE ->
decode_kex_init(Data, [Cookie, ssh_msg_kexinit], 10);
+decode(<<?BYTE(?SSH_MSG_KEXINIT), _Cookie:128, Data/binary>>) ->
+ throw({error, {kexinit_too_large, byte_size(Data), ?MAX_KEXINIT_SIZE}});
-decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?DEC_MPINT(E,__0)>>) ->
- #ssh_msg_kexdh_init{e = E
- };
+decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?DEC_MPINT(E, ELen)>>)
+ when ELen =< ?MAX_DH_MPINT_SIZE ->
+ #ssh_msg_kexdh_init{e = E};
+decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_INIT), ?DEC_MPINT(_, ELen)>>) ->
+ throw({error, {kexdh_init_e_too_large, ELen, ?MAX_DH_MPINT_SIZE}});
-decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1), ?DEC_BIN(Hashsign,__2)>>) ->
- #ssh_msg_kexdh_reply{
- public_host_key = ssh2_pubkey_decode(Key),
- f = F,
- h_sig = decode_signature(Hashsign)
- };
+decode(<<"dh", ?BYTE(?SSH_MSG_KEXDH_REPLY),
+ ?DEC_BIN(Key, KLen), ?DEC_MPINT(F, FLen), ?DEC_BIN(Hashsign, HLen)>>)
+ when KLen =< ?MAX_HOST_KEY_SIZE,
+ FLen =< ?MAX_DH_MPINT_SIZE,
+ HLen =< ?MAX_SIGNATURE_SIZE ->
+ #ssh_msg_kexdh_reply{public_host_key = ssh2_pubkey_decode(Key), f = F,
+ h_sig = decode_signature(Hashsign)};
+decode(<<"dh",?BYTE(?SSH_MSG_KEXDH_REPLY),
+ ?DEC_BIN(_, KLen), ?DEC_MPINT(_, FLen), ?DEC_BIN(_, HLen)>>) ->
+ throw({error, size_error([{kexdh_host_key_too_large, KLen, ?MAX_HOST_KEY_SIZE},
+ {kexdh_f_too_large, FLen, ?MAX_DH_MPINT_SIZE},
+ {kexdh_signature_too_large, HLen, ?MAX_SIGNATURE_SIZE}])});
decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REQUEST), ?UINT32(Min), ?UINT32(N), ?UINT32(Max)>>) ->
#ssh_msg_kex_dh_gex_request{
@@ -508,42 +524,55 @@ decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_REQUEST_OLD), ?UINT32(N)>>) ->
n = N
};
-decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP), ?DEC_MPINT(Prime,__0), ?DEC_MPINT(Generator,__1) >>) ->
- #ssh_msg_kex_dh_gex_group{
- p = Prime,
- g = Generator
- };
-
-decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_INIT), ?DEC_MPINT(E,__0)>>) ->
- #ssh_msg_kex_dh_gex_init{
- e = E
- };
-
-decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY), ?DEC_BIN(Key,__0), ?DEC_MPINT(F,__1), ?DEC_BIN(Hashsign,__2)>>) ->
- #ssh_msg_kex_dh_gex_reply{
- public_host_key = ssh2_pubkey_decode(Key),
- f = F,
- h_sig = decode_signature(Hashsign)
- };
-
-decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_BIN(Q_c,__0)>>) ->
- #ssh_msg_kex_ecdh_init{
- q_c = Q_c
- };
+decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP),
+ ?DEC_MPINT(Prime, PLen), ?DEC_MPINT(Generator, GLen)>>)
+ when PLen =< ?MAX_DH_MPINT_SIZE, GLen =< ?MAX_DH_MPINT_SIZE ->
+ #ssh_msg_kex_dh_gex_group{p = Prime, g = Generator};
+decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_GROUP), ?DEC_MPINT(_, PLen), ?DEC_MPINT(_, GLen)>>) ->
+ throw({error, size_error([{gex_p_too_large, PLen, ?MAX_DH_MPINT_SIZE},
+ {gex_g_too_large, GLen, ?MAX_DH_MPINT_SIZE}])});
+
+decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_INIT), ?DEC_MPINT(E, ELen)>>)
+ when ELen =< ?MAX_DH_MPINT_SIZE ->
+ #ssh_msg_kex_dh_gex_init{e = E};
+decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_INIT), ?DEC_MPINT(_, ELen)>>) ->
+ throw({error, {gex_init_e_too_large, ELen, ?MAX_DH_MPINT_SIZE}});
+
+decode(<<?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY),
+ ?DEC_BIN(Key, KLen), ?DEC_MPINT(F, FLen), ?DEC_BIN(Hashsign, SLen)>>)
+ when KLen =< ?MAX_HOST_KEY_SIZE,
+ FLen =< ?MAX_DH_MPINT_SIZE,
+ SLen =< ?MAX_SIGNATURE_SIZE ->
+ #ssh_msg_kex_dh_gex_reply{public_host_key = ssh2_pubkey_decode(Key), f = F,
+ h_sig = decode_signature(Hashsign)};
+decode(<<"dh_gex",?BYTE(?SSH_MSG_KEX_DH_GEX_REPLY),
+ ?DEC_BIN(_, KLen), ?DEC_MPINT(_, FLen), ?DEC_BIN(_, SLen)>>) ->
+ throw({error, size_error([{gex_host_key_too_large, KLen, ?MAX_HOST_KEY_SIZE},
+ {gex_f_too_large, FLen, ?MAX_DH_MPINT_SIZE},
+ {gex_signature_too_large, SLen, ?MAX_SIGNATURE_SIZE}])});
+
+decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_BIN(Q_c, QLen)>>)
+ when QLen =< ?MAX_ECDH_POINT_SIZE ->
+ #ssh_msg_kex_ecdh_init{q_c = Q_c};
+decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_INIT), ?DEC_BIN(_, QLen)>>) ->
+ throw({error, {ecdh_init_point_too_large, QLen, ?MAX_ECDH_POINT_SIZE}});
decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY),
- ?DEC_BIN(Key,__1), ?DEC_BIN(Q_s,__2), ?DEC_BIN(Sig,__3)>>) ->
- #ssh_msg_kex_ecdh_reply{
- public_host_key = ssh2_pubkey_decode(Key),
- q_s = Q_s,
- h_sig = decode_signature(Sig)
- };
+ ?DEC_BIN(Key, KLen), ?DEC_BIN(Q_s, QLen), ?DEC_BIN(Sig, SLen)>>)
+ when KLen =< ?MAX_HOST_KEY_SIZE,
+ QLen =< ?MAX_ECDH_POINT_SIZE,
+ SLen =< ?MAX_SIGNATURE_SIZE ->
+ #ssh_msg_kex_ecdh_reply{public_host_key = ssh2_pubkey_decode(Key), q_s = Q_s,
+ h_sig = decode_signature(Sig)};
+decode(<<"ecdh",?BYTE(?SSH_MSG_KEX_ECDH_REPLY),
+ ?DEC_BIN(_, KLen), ?DEC_BIN(_, QLen), ?DEC_BIN(_, SLen)>>) ->
+ throw({error, size_error([{ecdh_host_key_too_large, KLen, ?MAX_HOST_KEY_SIZE},
+ {ecdh_point_too_large, QLen, ?MAX_ECDH_POINT_SIZE},
+ {ecdh_signature_too_large, SLen, ?MAX_SIGNATURE_SIZE}])});
decode(<<"mlkem",?BYTE(?SSH_MSG_KEX_HYBRID_INIT), ?DEC_BIN(C_init, CLen)>>)
when CLen =:= ?MLKEM768_INIT_SIZE->
- #ssh_msg_kex_hybrid_init{
- c_init = C_init
- };
+ #ssh_msg_kex_hybrid_init{c_init = C_init};
%% Reject invalid ML-KEM messages with proper error
decode(<<"mlkem", ?BYTE(?SSH_MSG_KEX_HYBRID_INIT), ?DEC_BIN(_, CLen)>>) ->
throw({error, {mlkem_init_invalid_size, CLen, ?MLKEM768_INIT_SIZE}});
@@ -553,45 +582,41 @@ decode(<<"mlkem",?BYTE(?SSH_MSG_KEX_HYBRID_REPLY),
when KLen =< ?MAX_HOST_KEY_SIZE,
SLen =:= ?MLKEM768_REPLY_SIZE,
SigLen =< ?MAX_SIGNATURE_SIZE ->
- #ssh_msg_kex_hybrid_reply{
- public_host_key = ssh2_pubkey_decode(Key),
- s_reply = S_reply,
- h_sig = decode_signature(Sig)
- };
+ #ssh_msg_kex_hybrid_reply{public_host_key = ssh2_pubkey_decode(Key), s_reply = S_reply,
+ h_sig = decode_signature(Sig)};
decode(<<"mlkem",?BYTE(?SSH_MSG_KEX_HYBRID_REPLY),
- ?DEC_BIN(_, KLen), ?DEC_BIN(_, SLen), ?DEC_BIN(_Sig, SigLen)>>) ->
- Error = if
- KLen > ?MAX_HOST_KEY_SIZE -> {mlkem_host_key_too_large, KLen, ?MAX_HOST_KEY_SIZE};
- SLen =/= ?MLKEM768_REPLY_SIZE -> {mlkem_reply_invalid_size, SLen, ?MLKEM768_REPLY_SIZE};
- SigLen > ?MAX_SIGNATURE_SIZE -> {mlkem_signature_too_large, SigLen, ?MAX_SIGNATURE_SIZE};
- true -> {mlkem_reply_invalid, KLen, SLen, SigLen}
- end,
- throw({error, Error});
-
-decode(<<?SSH_MSG_SERVICE_REQUEST, ?DEC_BIN(Service,__0)>>) ->
- #ssh_msg_service_request{
- name = binary:bin_to_list(Service)
- };
-
-decode(<<?SSH_MSG_SERVICE_ACCEPT, ?DEC_BIN(Service,__0)>>) ->
- #ssh_msg_service_accept{
- name = binary:bin_to_list(Service)
- };
-
-decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), ?DEC_BIN(Desc,__0), ?DEC_BIN(Lang,__1)>>) ->
- #ssh_msg_disconnect{
- code = Code,
- description = ?unicode_list(Desc),
- language = Lang
- };
-
-%% Accept bad disconnects from ancient openssh clients that doesn't send language tag. Use english as a work-around.
-decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), ?DEC_BIN(Desc,__0)>>) ->
- #ssh_msg_disconnect{
- code = Code,
- description = ?unicode_list(Desc),
- language = <<"en">>
- };
+ ?DEC_BIN(_, _KLen), ?DEC_BIN(_, SLen), ?DEC_BIN(_, _SigLen)>>)
+ when SLen =/= ?MLKEM768_REPLY_SIZE ->
+ throw({error, {mlkem_reply_invalid_size, SLen, ?MLKEM768_REPLY_SIZE}});
+decode(<<"mlkem",?BYTE(?SSH_MSG_KEX_HYBRID_REPLY),
+ ?DEC_BIN(_, KLen), ?DEC_BIN(_, _SLen), ?DEC_BIN(_, SigLen)>>) ->
+ throw({error, size_error([{mlkem_host_key_too_large, KLen, ?MAX_HOST_KEY_SIZE},
+ {mlkem_signature_too_large, SigLen, ?MAX_SIGNATURE_SIZE}])});
+
+decode(<<?SSH_MSG_SERVICE_REQUEST, ?DEC_BIN(Service, Len)>>)
+ when Len =< ?MAX_SERVICE_NAME_SIZE ->
+ #ssh_msg_service_request{name = binary:bin_to_list(Service)};
+decode(<<?SSH_MSG_SERVICE_REQUEST, ?DEC_BIN(_, Len)>>) ->
+ throw({error, {service_request_name_too_large, Len, ?MAX_SERVICE_NAME_SIZE}});
+decode(<<?SSH_MSG_SERVICE_ACCEPT, ?DEC_BIN(Service, Len)>>)
+ when Len =< ?MAX_SERVICE_NAME_SIZE ->
+ #ssh_msg_service_accept{name = binary:bin_to_list(Service)};
+decode(<<?SSH_MSG_SERVICE_ACCEPT, ?DEC_BIN(_, Len)>>) ->
+ throw({error, {service_accept_name_too_large, Len, ?MAX_SERVICE_NAME_SIZE}});
+
+decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), ?DEC_BIN(Desc, DLen), ?DEC_BIN(Lang, LLen)>>)
+ when DLen =< ?MAX_DISCONNECT_DESC_SIZE, LLen =< ?MAX_LANG_SIZE ->
+ #ssh_msg_disconnect{code = Code, description = ?unicode_list(Desc), language = Lang};
+decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(_), ?DEC_BIN(_, DLen), ?DEC_BIN(_, LLen)>>) ->
+ throw({error, size_error([{disconnect_desc_too_large, DLen, ?MAX_DISCONNECT_DESC_SIZE},
+ {disconnect_lang_too_large, LLen, ?MAX_LANG_SIZE}])});
+
+%% Accept bad disconnects from ancient openssh clients that doesn't send language tag. Use english as a work-around.
+decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(Code), ?DEC_BIN(Desc, DLen)>>)
+ when DLen =< ?MAX_DISCONNECT_DESC_SIZE ->
+ #ssh_msg_disconnect{code = Code, description = ?unicode_list(Desc), language = <<"en">>};
+decode(<<?BYTE(?SSH_MSG_DISCONNECT), ?UINT32(_), ?DEC_BIN(_, DLen)>>) ->
+ throw({error, {disconnect_desc_too_large, DLen, ?MAX_DISCONNECT_DESC_SIZE}});
decode(<<?SSH_MSG_NEWKEYS>>) ->
#ssh_msg_newkeys{};
@@ -599,17 +624,21 @@ decode(<<?SSH_MSG_NEWKEYS>>) ->
%% Accept SSH_MSG_IGNORE without data to have feature parity with other implementations like openssh
decode(<<?BYTE(?SSH_MSG_IGNORE)>>) ->
#ssh_msg_ignore{};
-decode(<<?BYTE(?SSH_MSG_IGNORE), ?DEC_BIN(Data,__0)>>) ->
+decode(<<?BYTE(?SSH_MSG_IGNORE), ?DEC_BIN(Data, Len)>>)
+ when Len =< ?MAX_IGNORE_DATA_SIZE ->
#ssh_msg_ignore{data = Data};
+decode(<<?BYTE(?SSH_MSG_IGNORE), ?DEC_BIN(_, Len)>>) ->
+ throw({error, {ignore_data_too_large, Len, ?MAX_IGNORE_DATA_SIZE}});
decode(<<?BYTE(?SSH_MSG_UNIMPLEMENTED), ?UINT32(Seq)>>) ->
#ssh_msg_unimplemented{sequence = Seq};
-decode(<<?BYTE(?SSH_MSG_DEBUG), ?BYTE(Bool), ?DEC_BIN(Msg,__0), ?DEC_BIN(Lang,__1)>>) ->
- #ssh_msg_debug{always_display = erl_boolean(Bool),
- message = Msg,
- language = Lang}.
-
+decode(<<?BYTE(?SSH_MSG_DEBUG), ?BYTE(Bool), ?DEC_BIN(Msg, MLen), ?DEC_BIN(Lang, LLen)>>)
+ when MLen =< ?MAX_DEBUG_MSG_SIZE, LLen =< ?MAX_LANG_SIZE ->
+ #ssh_msg_debug{always_display = erl_boolean(Bool), message = Msg, language = Lang};
+decode(<<?BYTE(?SSH_MSG_DEBUG), ?BYTE(_), ?DEC_BIN(_, MLen), ?DEC_BIN(_, LLen)>>) ->
+ throw({error, size_error([{debug_msg_too_large, MLen, ?MAX_DEBUG_MSG_SIZE},
+ {debug_lang_too_large, LLen, ?MAX_LANG_SIZE}])}).
%%%================================================================
%%%
@@ -829,6 +858,12 @@ oid2ssh_curvename(?'secp521r1') -> {<<"ecdsa-sha2-nistp521">>, <<"nistp521">>}.
%%%
%%% Helper functions
%%%
+size_error([{_, Actual, Max} | Rest]) when Actual =< Max ->
+ size_error(Rest);
+size_error([{Tag, Actual, Max} | _]) ->
+ {Tag, Actual, Max};
+size_error([]) ->
+ invalid_size_check.
bin_foldr(Fun, Acc, Bin) ->
lists:reverse(bin_foldl(Fun, Acc, Bin)).
@@ -892,8 +927,6 @@ decode_kex_init(<<?DEC_BIN(Data,__0), Rest/binary>>, Acc, N) when
decode_kex_init(<<?DEC_BIN(Data,__0), _Rest/binary>>, _Acc, N) ->
throw({error, {kexinit, N, {string_size, byte_size(Data)}}}).
-
-
%%%================================================================
%%%
%%% Signature decode/encode
--
2.51.0