From c5fe2c9291e9f1f72045710f6389dad21e9270fb Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Thu, 28 Sep 2017 13:19:33 +0200
Subject: public_key: Added IP4 address checks to hostname_verification tests
---
lib/public_key/test/public_key_SUITE.erl | 40 ++++++++++++++++++++++
.../pkix_verify_hostname_subjAltName_IP.pem | 13 +++++++
.../public_key_SUITE_data/verify_hostname_ip.conf | 17 +++++++++
3 files changed, 70 insertions(+)
create mode 100644 lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
create mode 100644 lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 374fb20375..6741a2e30c 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -47,6 +47,7 @@ all() ->
pkix_iso_rsa_oid, pkix_iso_dsa_oid, pkix_crl, general_name,
pkix_verify_hostname_cn,
pkix_verify_hostname_subjAltName,
+ pkix_verify_hostname_subjAltName_IP,
pkix_verify_hostname_options,
pkix_test_data_all_default,
pkix_test_data,
@@ -984,6 +985,45 @@ pkix_verify_hostname_options(Config) ->
[{fqdn_fun, fun(_) -> default end}]),
false = public_key:pkix_verify_hostname(Cert, [{uri_id,"some://very.wrong.domain"}]).
+%%--------------------------------------------------------------------
+%% To generate the PEM file contents:
+%%
+%% openssl req -x509 -nodes -newkey rsa:1024 -keyout /dev/null -extensions SAN -config public_key_SUITE_data/verify_hostname_ip.conf 2>/dev/null > public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
+%%
+%% Subject: C=SE, CN=example.com
+%% Subject Alternative Name: DNS:1.2.3.4, IP=5.6.7.8, URI:https://10.11.12.13
+
+pkix_verify_hostname_subjAltName_IP(Config) ->
+ DataDir = proplists:get_value(data_dir, Config),
+ {ok,Bin} = file:read_file(filename:join(DataDir,"pkix_verify_hostname_subjAltName_IP.pem")),
+ Cert = public_key:pkix_decode_cert(element(2,hd(public_key:pem_decode(Bin))), otp),
+
+ %% Print the tests that a matchfun has to handle
+ catch public_key:pkix_verify_hostname(Cert, [{some_tag,"some.domain"},
+ {some_other_tag,[a,b,3,4]}],
+ [{match_fun,
+ fun(Ref,Pres) ->
+ ct:pal("~p:~p:~nRef : ~p~nPres: ~p",[?MODULE,?LINE,Ref,Pres]),
+ false
+ end}]),
+
+ false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://10.11.12.14"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://10.11.12.13"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,"1.2.3.4"}]),
+ false = public_key:pkix_verify_hostname(Cert, [{dns_id,"5.6.7.8"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip,[5,6,7,8]}],
+ [{match_fun,
+ fun({ip,IPref},{iPAddress,IPpres}) ->
+ ct:pal("~p:~p: IPref=~p, IPpres=~p",[?MODULE,?LINE,IPref,IPpres]),
+ IPref == IPpres;
+ (Ref,Pres) ->
+ ct:pal("~p:~p:~nRef : ~p~nPres: ~p",[?MODULE,?LINE,Ref,Pres]),
+ default
+ end}]).
+
+
+
+
%%--------------------------------------------------------------------
pkix_iso_rsa_oid() ->
[{doc, "Test workaround for supporting certs that use ISO oids"
diff --git a/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
new file mode 100644
index 0000000000..e83dfdb646
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
@@ -0,0 +1,13 @@
+-----BEGIN CERTIFICATE-----
+MIIB7TCCAVagAwIBAgIJAJftQyvUMLESMA0GCSqGSIb3DQEBCwUAMB8xCzAJBgNV
+BAYTAlNFMRAwDgYDVQQDEwc1LjYuNy44MB4XDTE3MDkyODExMTY0MFoXDTE3MTAy
+ODExMTY0MFowHzELMAkGA1UEBhMCU0UxEDAOBgNVBAMTBzUuNi43LjgwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAK1jLhGZcI0D5RzcUBjXuQ1636gaIlArdM4b
+woLpJIh2Tk4pCbEv6hOX0KTl8qPs8lCMOIOvQmoZwj0Ia1B5By9xHybJ30pNIoLy
+iqOdFwjlqTjhBVR1NjmcwgIRW1f/fqQ0pQznyIo/OwieNYlCwWzIUx1ZBLlwKAfZ
+YWozJaLZAgMBAAGjMTAvMC0GA1UdEQQmMCSCBzEuMi4zLjSHBAUGBwiGE2h0dHBz
+Oi8vMTAuMTEuMTIuMTMwDQYJKoZIhvcNAQELBQADgYEADapgA5dTBSrQMTAOGI7h
+SFpaF1y9EHSnCxofugR2EJNyNyPELFBQ9etIgU8fw67D495OSfy/3X3ngNAFOuds
+OENGq0JyBrO+HsgexslKF7LGc0oFlHfuZwyO7MLNFTG9dHG393dqduwGsEAuFh09
+SvMMJh3VTEHu6P+9O8YusdI=
+-----END CERTIFICATE-----
diff --git a/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf b/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
new file mode 100644
index 0000000000..2b905e2c4f
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
@@ -0,0 +1,17 @@
+[req]
+prompt = no
+distinguished_name = DN
+
+[DN]
+C=SE
+CN=example.com
+CN=5.6.7.8
+
+[SAN]
+subjectAltName = @alt_names
+
+[alt_names]
+DNS = 1.2.3.4
+IP = 5.6.7.8
+URI = https://10.11.12.13
+
--
cgit v1.2.3
From 8cee0d079821288d3aa9b6a039b11497d315d390 Mon Sep 17 00:00:00 2001
From: Hans Nilsson
Date: Thu, 28 Sep 2017 16:46:42 +0200
Subject: public_key: verify ip (both v4 and v6)
---
lib/public_key/doc/src/public_key.xml | 14 +++++---
lib/public_key/src/public_key.erl | 37 ++++++++++++++++++++--
lib/public_key/test/public_key_SUITE.erl | 24 ++++++--------
.../pkix_verify_hostname_subjAltName_IP.pem | 22 ++++++-------
.../public_key_SUITE_data/verify_hostname_ip.conf | 3 +-
5 files changed, 67 insertions(+), 33 deletions(-)
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index fcf37a7a4d..3040f2db0d 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -871,12 +871,13 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
Cert = der_encoded() | #'OTPCertificate'{}
ReferenceIDs = [ RefID ]
- RefID = {IdType,string()}
- IdType = dns_id | srv_id | uri_id
+ RefID = {dns_id,string()} | {srv_id,string()} | {uri_id,string()} | {ip,inet:ip_address()|string()} | {OtherRefID,term()}}
+ OtherRefID = atom()
Opts = [ PvhOpt() ]
PvhOpt = [MatchOpt | FailCallBackOpt | FqdnExtractOpt]
- MatchOpt = {fun(RefId | FQDN::string(), PresentedID) -> boolean() | default}
- PresentedID = {dNSName,string()} | {uniformResourceIdentifier,string()}
+ MatchOpt = {match_fun, fun(RefId | FQDN::string(), PresentedID) -> boolean() | default}
+ PresentedID = {dNSName,string()} | {uniformResourceIdentifier,string() | {iPAddress,list(byte())} | {OtherPresId,term()}}
+ OtherPresID = atom()
FailCallBackOpt = {fail_callback, fun(#'OTPCertificate'{}) -> boolean()}
FqdnExtractOpt = {fqdn_fun, fun(RefID) -> FQDN::string() | default | undefined}
@@ -893,6 +894,11 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
code examples
describes this function more detailed.
+ The {OtherRefId,term()} is defined by the user and is passed to the match_fun, if defined.
+ If that term is a binary, it will be converted to a string.
+
+ The ip takes a 4-tuple or a
+
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index cc01b61433..c3f2d791a3 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -1454,13 +1454,43 @@ verify_hostname_match_default0({dns_id,R}, {dNSName,P}) ->
R==P;
verify_hostname_match_default0({uri_id,R}, {uniformResourceIdentifier,P}) ->
R==P;
-verify_hostname_match_default0({srv_id,R}, {T,P}) when T == srvName ;
- T == ?srvName_OID ->
+verify_hostname_match_default0({ip,R}, {iPAddress,P}) when length(P) == 4 ->
+ %% IPv4
+ try
+ list_to_tuple(P)
+ == if is_tuple(R), size(R)==4 -> R;
+ is_list(R) -> ok(inet:parse_ipv4strict_address(R))
+ end
+ catch
+ _:_ ->
+ false
+ end;
+
+verify_hostname_match_default0({ip,R}, {iPAddress,P}) when length(P) == 16 ->
+ %% IPv6. The length 16 is due to the certificate specification.
+ try
+ l16_to_tup(P)
+ == if is_tuple(R), size(R)==8 -> R;
+ is_list(R) -> ok(inet:parse_ipv6strict_address(R))
+ end
+ catch
+ _:_ ->
+ false
+ end;
+verify_hostname_match_default0({srv_id,R}, {srvName,P}) ->
+ R==P;
+verify_hostname_match_default0({srv_id,R}, {?srvName_OID,P}) ->
R==P;
verify_hostname_match_default0(_, _) ->
false.
+ok({ok,X}) -> X.
+l16_to_tup(L) -> list_to_tuple(l16_to_tup(L, [])).
+%%
+l16_to_tup([A,B|T], Acc) -> l16_to_tup(T, [(A bsl 8) bor B | Acc]);
+l16_to_tup([], Acc) -> lists:reverse(Acc).
+
match_wild(A, [$*|B]) -> match_wild_suffixes(A, B);
match_wild([C|A], [ C|B]) -> match_wild(A, B);
match_wild([], []) -> true;
@@ -1505,7 +1535,8 @@ to_lower_ascii(C) when $A =< C,C =< $Z -> C + ($a-$A);
to_lower_ascii(C) -> C.
to_string(S) when is_list(S) -> S;
-to_string(B) when is_binary(B) -> binary_to_list(B).
+to_string(B) when is_binary(B) -> binary_to_list(B);
+to_string(X) -> X.
format_details([]) ->
no_relevant_crls;
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 6741a2e30c..0077c7908c 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -991,7 +991,7 @@ pkix_verify_hostname_options(Config) ->
%% openssl req -x509 -nodes -newkey rsa:1024 -keyout /dev/null -extensions SAN -config public_key_SUITE_data/verify_hostname_ip.conf 2>/dev/null > public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
%%
%% Subject: C=SE, CN=example.com
-%% Subject Alternative Name: DNS:1.2.3.4, IP=5.6.7.8, URI:https://10.11.12.13
+%% Subject Alternative Name: DNS:1.2.3.4, DNS: abcd:ef::1, IP:5.6.7.8, URI:https://10.11.12.13
pkix_verify_hostname_subjAltName_IP(Config) ->
DataDir = proplists:get_value(data_dir, Config),
@@ -1000,28 +1000,24 @@ pkix_verify_hostname_subjAltName_IP(Config) ->
%% Print the tests that a matchfun has to handle
catch public_key:pkix_verify_hostname(Cert, [{some_tag,"some.domain"},
- {some_other_tag,[a,b,3,4]}],
+ {ip, {5,6,7,8}}
+ ],
[{match_fun,
fun(Ref,Pres) ->
ct:pal("~p:~p:~nRef : ~p~nPres: ~p",[?MODULE,?LINE,Ref,Pres]),
false
end}]),
- false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://10.11.12.14"}]),
+ false = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://1.2.3.4"}]),
true = public_key:pkix_verify_hostname(Cert, [{uri_id,"https://10.11.12.13"}]),
true = public_key:pkix_verify_hostname(Cert, [{dns_id,"1.2.3.4"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{dns_id,<<"1.2.3.4">>}]),
false = public_key:pkix_verify_hostname(Cert, [{dns_id,"5.6.7.8"}]),
- true = public_key:pkix_verify_hostname(Cert, [{ip,[5,6,7,8]}],
- [{match_fun,
- fun({ip,IPref},{iPAddress,IPpres}) ->
- ct:pal("~p:~p: IPref=~p, IPpres=~p",[?MODULE,?LINE,IPref,IPpres]),
- IPref == IPpres;
- (Ref,Pres) ->
- ct:pal("~p:~p:~nRef : ~p~nPres: ~p",[?MODULE,?LINE,Ref,Pres]),
- default
- end}]).
-
-
+ true = public_key:pkix_verify_hostname(Cert, [{ip, "aBcD:ef:0::0:1"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, {16#abcd,16#ef,0,0,0,0,0,1}}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, "5.6.7.8"}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, <<"5.6.7.8">>}]),
+ true = public_key:pkix_verify_hostname(Cert, [{ip, {5,6,7,8}}]).
%%--------------------------------------------------------------------
diff --git a/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
index e83dfdb646..f9ffb257b5 100644
--- a/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
+++ b/lib/public_key/test/public_key_SUITE_data/pkix_verify_hostname_subjAltName_IP.pem
@@ -1,13 +1,13 @@
-----BEGIN CERTIFICATE-----
-MIIB7TCCAVagAwIBAgIJAJftQyvUMLESMA0GCSqGSIb3DQEBCwUAMB8xCzAJBgNV
-BAYTAlNFMRAwDgYDVQQDEwc1LjYuNy44MB4XDTE3MDkyODExMTY0MFoXDTE3MTAy
-ODExMTY0MFowHzELMAkGA1UEBhMCU0UxEDAOBgNVBAMTBzUuNi43LjgwgZ8wDQYJ
-KoZIhvcNAQEBBQADgY0AMIGJAoGBAK1jLhGZcI0D5RzcUBjXuQ1636gaIlArdM4b
-woLpJIh2Tk4pCbEv6hOX0KTl8qPs8lCMOIOvQmoZwj0Ia1B5By9xHybJ30pNIoLy
-iqOdFwjlqTjhBVR1NjmcwgIRW1f/fqQ0pQznyIo/OwieNYlCwWzIUx1ZBLlwKAfZ
-YWozJaLZAgMBAAGjMTAvMC0GA1UdEQQmMCSCBzEuMi4zLjSHBAUGBwiGE2h0dHBz
-Oi8vMTAuMTEuMTIuMTMwDQYJKoZIhvcNAQELBQADgYEADapgA5dTBSrQMTAOGI7h
-SFpaF1y9EHSnCxofugR2EJNyNyPELFBQ9etIgU8fw67D495OSfy/3X3ngNAFOuds
-OENGq0JyBrO+HsgexslKF7LGc0oFlHfuZwyO7MLNFTG9dHG393dqduwGsEAuFh09
-SvMMJh3VTEHu6P+9O8YusdI=
+MIIB/zCCAWigAwIBAgIJAMoSejmTjwAGMA0GCSqGSIb3DQEBCwUAMB8xCzAJBgNV
+BAYTAlNFMRAwDgYDVQQDEwc1LjYuNy44MB4XDTE3MDkyODE0MDAxNVoXDTE3MTAy
+ODE0MDAxNVowHzELMAkGA1UEBhMCU0UxEDAOBgNVBAMTBzUuNi43LjgwgZ8wDQYJ
+KoZIhvcNAQEBBQADgY0AMIGJAoGBAMUPU89KwVbTCDkyxQSz3wprMbZTLe35K6jm
+Q7oY1rJyVXjsFHwZrFqqNMScEyX40rJhczQ2Z9etEX6qYLbdb/DZeFcKo14fR583
+QMFZC+qqpLWHdvjaQN0KwD99VFeZIGpRgywG8SR+BXZjDHUkGsMrikAEJtf0Tgih
+IPyiFtiJAgMBAAGjQzBBMD8GA1UdEQQ4MDaCBzEuMi4zLjSHBAUGBwiHEKvNAO8A
+AAAAAAAAAAAAAAGGE2h0dHBzOi8vMTAuMTEuMTIuMTMwDQYJKoZIhvcNAQELBQAD
+gYEAtWVeQaRFZ0kH/pzSWMSsOCUrjbwlWRwDNbagNKoM6nCRv0QQ59fG6XrVZwR3
+c0s5arlMh3U2+bjKE+Iq9+b/lN1lGzf8iaAqBNa7KptwTSUEY3TiNG5X0zlSXKTI
+3z7AaUEtghL9ImCPj5V3tVksqWd7U0zLmeeLZnM+wGAL9Hc=
-----END CERTIFICATE-----
diff --git a/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf b/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
index 2b905e2c4f..0a738f2586 100644
--- a/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
+++ b/lib/public_key/test/public_key_SUITE_data/verify_hostname_ip.conf
@@ -12,6 +12,7 @@ subjectAltName = @alt_names
[alt_names]
DNS = 1.2.3.4
-IP = 5.6.7.8
+IP.1 = 5.6.7.8
+IP.2 = abcd:ef::1
URI = https://10.11.12.13
--
cgit v1.2.3