Skip to content

Commit 352c8aa

Browse files
committed
ssl: Skip undecodable certificate_authorities names
The TLS CertificateRequest certificate_authorities list is only a hint for client certificate selection. Some real servers advertise CA names that violate PKIX type constraints, for example countryName encoded as UTF8String. Previously ssl_handshake decoded every advertised CA name with public_key:pkix_normalize_name/1. One malformed advisory name could therefore abort the whole handshake with a fatal decode_error, even when the client had no certificate configured. Catch normalization failures and drop only the bad CA name, keeping any valid names in the list. Add a regression test covering a malformed DN from GH-11338 alongside a valid CA name. Fixes #11338
1 parent fef08ae commit 352c8aa

2 files changed

Lines changed: 37 additions & 3 deletions

File tree

lib/ssl/src/ssl_handshake.erl

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3480,7 +3480,13 @@ decode_psk_binders(<<?BYTE(Len), Binder:Len/binary, Rest/binary>>, Acc) ->
34803480
decode_cert_auths(<<>>, Acc) ->
34813481
lists:reverse(Acc);
34823482
decode_cert_auths(<<?UINT16(Len), Auth:Len/binary, Rest/binary>>, Acc) ->
3483-
decode_cert_auths(Rest, [public_key:pkix_normalize_name(Auth) | Acc]).
3483+
try public_key:pkix_normalize_name(Auth) of
3484+
CertAuth ->
3485+
decode_cert_auths(Rest, [CertAuth | Acc])
3486+
catch
3487+
_:_ ->
3488+
decode_cert_auths(Rest, Acc)
3489+
end.
34843490

34853491
%% encode/decode stream of certificate data to/from list of certificate data
34863492
certs_to_list(ASN1Certs) ->

lib/ssl/test/ssl_handshake_SUITE.erl

Lines changed: 30 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,8 @@
5555
select_proper_tls_1_2_rsa_default_hashsign/1,
5656
ignore_hassign_extension_pre_tls_1_2/1,
5757
signature_algorithms/1,
58-
drop_unassigned_signature_algorithms/1]).
58+
drop_unassigned_signature_algorithms/1,
59+
drop_undecodable_certificate_authorities/1]).
5960

6061
%%--------------------------------------------------------------------
6162
%% Common Test interface functions -----------------------------------
@@ -70,7 +71,8 @@ all() -> [decode_hello_handshake,
7071
select_proper_tls_1_2_rsa_default_hashsign,
7172
ignore_hassign_extension_pre_tls_1_2,
7273
signature_algorithms,
73-
drop_unassigned_signature_algorithms].
74+
drop_unassigned_signature_algorithms,
75+
drop_undecodable_certificate_authorities].
7476

7577
%%--------------------------------------------------------------------
7678
init_per_suite(Config) ->
@@ -294,6 +296,26 @@ drop_unassigned_signature_algorithms(_Config) ->
294296
end,
295297
SigAlgs).
296298

299+
drop_undecodable_certificate_authorities(_Config) ->
300+
GoodAuth0 = {rdnSequence,
301+
[[{'AttributeTypeAndValue', ?'id-at-commonName',
302+
{utf8String, <<"Good CA">>}}]]},
303+
GoodDN = public_key:pkix_encode('Name', GoodAuth0, otp),
304+
BadDN = base64:decode(<<"MHAxCzAJBgNVBAYMAkJSMRMwEQYDVQQKDApJQ1AtQnJhc2lsMTQwMgY",
305+
"DVQQLDCtBdXRvcmlkYWRlIENlcnRpZmljYWRvcmEgUmFpeiBCcmFz",
306+
"aWxlaXJhIHY1MRYwFAYDVQQDDA1BQyBTeW5ndWxhcklE">>),
307+
CertAuths = cert_auths_vector([BadDN, GoodDN]),
308+
HashSigns = <<(ssl_cipher:signature_scheme({sha256, rsa})):16>>,
309+
HashSignsLen = byte_size(HashSigns),
310+
CertAuthsLen = byte_size(CertAuths),
311+
CertReq = <<?BYTE(1), ?BYTE(?RSA_SIGN),
312+
?UINT16(HashSignsLen), HashSigns/binary,
313+
?UINT16(CertAuthsLen), CertAuths/binary>>,
314+
GoodAuth = public_key:pkix_normalize_name(GoodAuth0),
315+
316+
#certificate_request{certificate_authorities = [GoodAuth]} =
317+
ssl_handshake:decode_handshake(?TLS_1_2, ?CERTIFICATE_REQUEST, CertReq).
318+
297319

298320
%%--------------------------------------------------------------------
299321
%% Internal functions ------------------------------------------------
@@ -302,3 +324,9 @@ drop_unassigned_signature_algorithms(_Config) ->
302324
is_supported(Hash) ->
303325
Hashs = crypto:supports(hashs),
304326
lists:member(Hash, Hashs).
327+
328+
cert_auths_vector(Auths) ->
329+
list_to_binary([begin
330+
Len = byte_size(Auth),
331+
<<?UINT16(Len), Auth/binary>>
332+
end || Auth <- Auths]).

0 commit comments

Comments
 (0)