File 1328-public_key-Fix-case-insensitive-match-for-countrynam.patch of Package erlang

From 61f29a0a3ac0e1ca9e7b323882fd162947cdaf5e Mon Sep 17 00:00:00 2001
From: Ingela Anderton Andin <ingela@erlang.org>
Date: Fri, 11 Aug 2023 12:58:18 +0200
Subject: [PATCH 1/2] public_key: Fix case insensitive match for countryname

Modernizes string functions used.

Closes #7546
Closes #6149
---
 lib/public_key/src/pubkey_cert.erl       | 69 +++++++++++++++---------
 lib/public_key/test/pkits_SUITE.erl      |  5 +-
 lib/public_key/test/public_key_SUITE.erl | 21 ++++++++
 3 files changed, 68 insertions(+), 27 deletions(-)

diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index abe69d9ae2..7368f99bd3 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -408,9 +408,8 @@ match_name(emailAddress, Name, [PermittedName | Rest]) ->
 match_name(dNSName, Name, [PermittedName | Rest]) ->
     Fun = fun(Domain, [$.|Domain]) -> true;
 	     (Name1,Name2) ->
-		  lists:suffix(string:to_lower(Name2),
-			       string:to_lower(Name1))
-	  end,
+		  is_suffix(Name2, Name1)
+          end,
     match_name(Fun, Name, [$.|PermittedName], Rest);
 
 match_name(x400Address, OrAddress, [PermittedAddr | Rest]) ->
@@ -558,11 +557,11 @@ root_cert(Name, Opts) ->
 %%--------------------------------------------------------------------
 do_normalize_general_name(Issuer) ->
     Normalize = fun([{Description, Type, {printableString, Value}}]) ->
-			NewValue = string:to_lower(strip_spaces(Value)),
-			[{Description, Type, {printableString, NewValue}}];
-		   (Atter)  ->
-			Atter
-		end,
+            NewValue = string:casefold(strip_spaces(Value, false)),
+            [{Description, Type, {printableString, NewValue}}];
+           (Atter)  ->
+            Atter
+        end,
     lists:map(Normalize, Issuer).
 
 %% See rfc3280 4.1.2.6 Subject: regarding emails.
@@ -668,14 +667,28 @@ is_dir_name(_,[],false) ->
 is_dir_name(_,_,_) ->
     false.
 
-is_dir_name2(Value, Value) -> true;
-is_dir_name2({printableString, Value1}, {printableString, Value2}) ->
-    string:to_lower(strip_spaces(Value1)) =:= 
-	string:to_lower(strip_spaces(Value2));
-is_dir_name2({utf8String, Value1}, String) ->
-    is_dir_name2({printableString, unicode:characters_to_list(Value1)}, String);
-is_dir_name2(String, {utf8String, Value1}) ->
-    is_dir_name2(String, {printableString, unicode:characters_to_list(Value1)});
+%% attribute values in types other than PrintableString are case
+%% sensitive (this permits matching of attribute values as binary
+%% objects); that is term comparison will compare. Rules origninate
+%% from RFC 3280 section 4.1.24. However fallback to case insensite
+%% matching also for utf8 strings, as this is done by the
+%% pkits_suite interop suite
+is_dir_name2(Str, Str) ->
+    true;
+is_dir_name2({T1, Str1}, Str2)
+  when T1 == printableString; T1 == utf8String ->
+    is_dir_name2(Str1, Str2);
+is_dir_name2(Str1, {T2, Str2})
+  when T2 == printableString; T2 == utf8String ->
+    is_dir_name2(Str1, Str2);
+is_dir_name2(Str1, Str2)
+  when (is_list(Str1) orelse is_binary(Str1)) andalso
+       (is_list(Str2) orelse is_binary(Str2)) ->
+    %%attribute values in PrintableString are compared after
+    %%removing leading and trailing white space and converting internal
+    %%substrings of one or more consecutive white space characters to a
+    %%single space. They are case insensetive.
+    string:equal(strip_spaces(Str1, true), strip_spaces(Str2, true), true);
 is_dir_name2(_, _) ->
     false.
 
@@ -693,13 +706,19 @@ decode_general_name([{directoryName, Issuer}]) ->
 decode_general_name([{_, Issuer}]) ->
     Issuer.
 
-%% Strip all leading and trailing spaces and make
-%% sure there is no double spaces in between. 
-strip_spaces(String) ->   
-    NewString = 
-	lists:foldl(fun(Char, Acc) -> Acc ++ Char ++ " " end, [], 
-		    string:tokens(String, " ")),
-    string:strip(NewString).
+strip_spaces(String0, KeepDeep) ->
+    Trimmed = string:trim(String0),
+    strip_many_spaces(string:split(Trimmed, "  ", all), KeepDeep).
+
+strip_many_spaces([OnlySingleSpace], _) ->
+    OnlySingleSpace;
+strip_many_spaces(Strings, KeepDeep) ->
+    Split = [string:trim(Str, leading, " ") || Str <- Strings, Str /= []],
+    DeepList = lists:join(" ", Split),
+    case KeepDeep of
+        true -> DeepList;
+        false -> unicode:characters_to_list(DeepList)
+    end.
 
 %% No extensions present
 validate_extensions(OtpCert, asn1_NOVALUE, ValidationState, ExistBasicCon,
@@ -1047,9 +1066,9 @@ is_valid_email_address(Canditate, Permitted, [_, _]) ->
     case_insensitive_match(Canditate, Permitted).
 
 is_suffix(Suffix, Str) ->
-    lists:suffix(string:to_lower(Suffix), string:to_lower(Str)).
+    lists:suffix(string:casefold(Suffix), string:casefold(Str)).
 case_insensitive_match(Str1, Str2) ->
-    string:to_lower(Str1) == string:to_lower(Str2).
+    string:equal(Str1, Str2, true).
 
 is_or_address(Address, Canditate) ->
     %% TODO: Is case_insensitive_match sufficient?
diff --git a/lib/public_key/test/pkits_SUITE.erl b/lib/public_key/test/pkits_SUITE.erl
index ba3efdba09..667dc12a7e 100644
--- a/lib/public_key/test/pkits_SUITE.erl
+++ b/lib/public_key/test/pkits_SUITE.erl
@@ -379,7 +379,7 @@ string_name_chain() ->
     [{doc,"Test name chaining"}].
 string_name_chain(Config) when is_list(Config) ->
     run([{ "4.3.9", "Valid UTF8String Encoded Names Test9 EE", ok},
-	 %%{ "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10 EE", ok},
+         %%{ "4.3.10", "Valid Rollover from PrintableString to UTF8String Test10 EE", ok},
 	 { "4.3.11", "Valid UTF8String Case Insensitive Match Test11 EE", ok}]).
 
 %%----------------------------verifying_paths_with_self_issued_certificates-------------------------------------------------
@@ -1463,7 +1463,8 @@ intermidiate_cas(Chap) when Chap == "4.5.8" ->
 
 
 %%%%%%%%%%%%%%% CRL mappings %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
+crl_names("4.3.10") ->
+    ["PrintableString to UTF8String CA CRL"];
 crl_names("4.4.1") ->
     ["Trust Anchor Root CRL"];
 crl_names("4.4.2") ->
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 80c76827c6..35534171a2 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -112,6 +112,8 @@
          pkix_test_data_all_default/1,
          pkix_test_data/0,
          pkix_test_data/1,
+         pkix_is_issuer/0,
+         pkix_is_issuer/1,
          short_cert_issuer_hash/0,
          short_cert_issuer_hash/1,
          short_crl_issuer_hash/0,
@@ -156,6 +158,7 @@ all() ->
      pkix_dist_point_uri,
      pkix_test_data_all_default,
      pkix_test_data,
+     pkix_is_issuer,
      short_cert_issuer_hash, 
      short_crl_issuer_hash
     ].
@@ -1123,6 +1126,7 @@ pkix_test_data_all_default(Config) when is_list(Config) ->
     check_conf_member(ServerConf1, [key, cert, cacerts]),
     check_conf_member(ClientConf1, [key, cert, cacerts]).
     
+%%--------------------------------------------------------------------
 
 pkix_test_data() ->
     [{doc, "Test API function pkix_test_data/1"}].
@@ -1167,6 +1171,23 @@ check_conf_member(Conf, [Member | Rest]) ->
             ct:fail({misssing_conf, Member})
     end.
                               
+%%--------------------------------------------------------------------
+pkix_is_issuer() ->
+    [{doc, "Test pubkey_cert:pkix_is_issuer with cert that have diffent cases on countryname"}].
+
+pkix_is_issuer(Config) when is_list(Config) ->
+    Upper = {rdnSequence,
+             [[{'AttributeTypeAndValue',{2,5,4,6},"GB"}],
+              [{'AttributeTypeAndValue',{2,5,4,10},{utf8String,<<"MYORG">>}}],
+              [{'AttributeTypeAndValue',{2,5,4,11},{utf8String,<<"INTERMEDIATE">>}}],
+              [{'AttributeTypeAndValue',{2,5,4,3},{utf8String,<<"INTERMEDIATE">>}}]]},
+    Lower = {rdnSequence,
+             [[{'AttributeTypeAndValue',{2,5,4,6},"gb"}],
+              [{'AttributeTypeAndValue',{2,5,4,10},{utf8String,<<"MYORG">>}}],
+              [{'AttributeTypeAndValue',{2,5,4,11},{utf8String,<<"INTERMEDIATE">>}}],
+              [{'AttributeTypeAndValue',{2,5,4,3},{utf8String,<<"INTERMEDIATE">>}}]]},
+    true = pubkey_cert:is_issuer(Upper, Lower).
+
 %%--------------------------------------------------------------------
 short_cert_issuer_hash() ->
     [{doc, "Test OpenSSL-style hash for certificate issuer"}].
-- 
2.35.3

openSUSE Build Service is sponsored by