aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/mnesia/src/mnesia_locker.erl10
-rw-r--r--lib/mnesia/test/mnesia_recovery_test.erl13
-rw-r--r--lib/mnesia/test/mnesia_test_lib.hrl10
-rw-r--r--lib/public_key/doc/src/public_key.xml89
-rw-r--r--lib/public_key/src/pubkey_cert.erl21
-rw-r--r--lib/public_key/src/pubkey_crl.erl8
-rw-r--r--lib/public_key/src/public_key.erl103
-rw-r--r--lib/public_key/test/public_key_SUITE.erl40
-rw-r--r--lib/public_key/test/public_key_SUITE_data/crl_signer.pem25
-rw-r--r--lib/public_key/test/public_key_SUITE_data/idp_cert.pem30
-rw-r--r--lib/public_key/test/public_key_SUITE_data/idp_crl.pem18
-rw-r--r--lib/ssh/src/ssh_info.erl11
-rw-r--r--lib/ssh/test/ssh_basic_SUITE.erl32
-rw-r--r--lib/stdlib/src/ets.erl7
14 files changed, 357 insertions, 60 deletions
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index e27396731f..1efb939e00 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -982,8 +982,14 @@ sticky_flush(Ns=[Node | Tail], Store) ->
flush_remaining([], _SkipNode, Res) ->
del_debug(),
exit(Res);
-flush_remaining([SkipNode | Tail ], SkipNode, Res) ->
- flush_remaining(Tail, SkipNode, Res);
+flush_remaining(Ns=[SkipNode | Tail ], SkipNode, Res) ->
+ add_debug(Ns),
+ receive
+ {?MODULE, SkipNode, _} ->
+ flush_remaining(Tail, SkipNode, Res)
+ after 0 ->
+ flush_remaining(Tail, SkipNode, Res)
+ end;
flush_remaining(Ns=[Node | Tail], SkipNode, Res) ->
add_debug(Ns),
receive
diff --git a/lib/mnesia/test/mnesia_recovery_test.erl b/lib/mnesia/test/mnesia_recovery_test.erl
index 0d0ad32fb0..946a9f97ba 100644
--- a/lib/mnesia/test/mnesia_recovery_test.erl
+++ b/lib/mnesia/test/mnesia_recovery_test.erl
@@ -320,7 +320,9 @@ read_during_down(Op, Config) when is_list(Config) ->
?log("W2R ~p~n", [W2R]),
loop_and_kill_mnesia(10, hd(W2R), Tabs),
[Pid ! self() || Pid <- Readers],
- ?match([ok, ok, ok], [receive ok -> ok after 1000 -> {Pid, mnesia_lib:dist_coredump()} end || Pid <- Readers]),
+ ?match([ok, ok, ok],
+ [receive ok -> ok after 5000 -> {Pid, mnesia_lib:dist_coredump()} end
+ || Pid <- Readers]),
?verify_mnesia(Ns, []).
reader(Tab, OP) ->
@@ -338,8 +340,12 @@ reader(Tab, OP) ->
?error("Expected ~p Got ~p ~n", [[{Tab, key, val}], Else]),
erlang:error(test_failed)
end,
- receive Pid ->
- Pid ! ok
+ receive
+ Pid when is_pid(Pid) ->
+ Pid ! ok;
+ Other ->
+ io:format("Msg: ~p~n", [Other]),
+ error(Other)
after 50 ->
reader(Tab, OP)
end.
@@ -1537,6 +1543,7 @@ disc_less(Config) when is_list(Config) ->
timer:sleep(500),
?match(ok, rpc:call(Node3, mnesia, start, [[{extra_db_nodes, [Node1, Node2]}]])),
?match(ok, rpc:call(Node3, mnesia, wait_for_tables, [[Tab1, Tab2, Tab3], 20000])),
+ ?match(ok, rpc:call(Node1, mnesia, wait_for_tables, [[Tab1, Tab2, Tab3], 20000])),
?match(ok, rpc:call(Node3, ?MODULE, verify_data, [Tab1, 100])),
?match(ok, rpc:call(Node3, ?MODULE, verify_data, [Tab2, 100])),
diff --git a/lib/mnesia/test/mnesia_test_lib.hrl b/lib/mnesia/test/mnesia_test_lib.hrl
index 94a195f01f..cd76377df6 100644
--- a/lib/mnesia/test/mnesia_test_lib.hrl
+++ b/lib/mnesia/test/mnesia_test_lib.hrl
@@ -66,12 +66,14 @@
?verbose("ok, ~n Result as expected:~p~n",[_AR_2]),
{success,_AR_2};
_AR_2 ->
- ?error("Not Matching Actual result was:~n ~p~n", [_AR_2]),
+ ?error("Not Matching Actual result was:~n ~p~n ~p~n",
+ [_AR_2, erlang:get_stacktrace()]),
{fail,_AR_2}
end;
- _:_AR_1 ->
- ?error("Not Matching Actual result was:~n ~p~n", [_AR_1]),
- {fail,_AR_1}
+ _T1_:_AR_1 ->
+ ?error("Not Matching Actual result was:~n ~p~n ~p~n",
+ [{_T1_,_AR_1}, erlang:get_stacktrace()]),
+ {fail,{_T1_,_AR_1}}
end
end()).
diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml
index e3473f80d7..b86d0fe0ab 100644
--- a/lib/public_key/doc/src/public_key.xml
+++ b/lib/public_key/doc/src/public_key.xml
@@ -5,7 +5,7 @@
<header>
<copyright>
<year>2008</year>
- <year>2014</year>
+ <year>2015</year>
<holder>Ericsson AB, All Rights Reserved</holder>
</copyright>
<legalnotice>
@@ -127,6 +127,8 @@
affiliationChanged | superseded | cessationOfOperation |
certificateHold | privilegeWithdrawn | aACompromise</code></p>
+ <p><code>issuer_name() = {rdnSequence,[#'AttributeTypeAndValue'{}]} </code> </p>
+
<p><code>ssh_file() = openssh_public_key | rfc4716_public_key | known_hosts |
auth_keys</code></p>
@@ -368,8 +370,8 @@
<name>pkix_is_issuer(Cert, IssuerCert) -> boolean()</name>
<fsummary> Checks if <c>IssuerCert</c> issued <c>Cert</c> </fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
- <v>IssuerCert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
+ <v>IssuerCert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
<p> Checks if <c>IssuerCert</c> issued <c>Cert</c> </p>
@@ -380,7 +382,7 @@
<name>pkix_is_fixed_dh_cert(Cert) -> boolean()</name>
<fsummary> Checks if a Certificate is a fixed Diffie-Hellman Cert.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
<p> Checks if a Certificate is a fixed Diffie-Hellman Cert.</p>
@@ -391,7 +393,7 @@
<name>pkix_is_self_signed(Cert) -> boolean()</name>
<fsummary> Checks if a Certificate is self signed.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
</type>
<desc>
<p> Checks if a Certificate is self signed.</p>
@@ -402,24 +404,25 @@
<name>pkix_issuer_id(Cert, IssuedBy) -> {ok, IssuerID} | {error, Reason}</name>
<fsummary> Returns the issuer id.</fsummary>
<type>
- <v>Cert = der_encode() | #'OTPCertificate'{}</v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{}</v>
<v>IssuedBy = self | other</v>
- <v>IssuerID = {integer(), {rdnSequence, [#'AttributeTypeAndValue'{}]}}</v>
+ <v>IssuerID = {integer(), issuer_name()}</v>
<d>The issuer id consists of the serial number and the issuers name.</d>
<v>Reason = term()</v>
- </type>
- <desc>
- <p> Returns the issuer id.</p>
- </desc>
+ </type>
+ <desc>
+ <p> Returns the issuer id.</p>
+ </desc>
</func>
-
+
+
<func>
<name>pkix_normalize_name(Issuer) -> Normalized</name>
<fsummary>Normalizes a issuer name so that it can be easily
compared to another issuer name. </fsummary>
<type>
- <v>Issuer = {rdnSequence,[#'AttributeTypeAndValue'{}]}</v>
- <v>Normalized = {rdnSequence, [#'AttributeTypeAndValue'{}]}</v>
+ <v>Issuer = issuer_name()</v>
+ <v>Normalized = issuer_name()</v>
</type>
<desc>
<p>Normalizes a issuer name so that it can be easily
@@ -431,13 +434,13 @@
<name>pkix_path_validation(TrustedCert, CertChain, Options) -> {ok, {PublicKeyInfo, PolicyTree}} | {error, {bad_cert, Reason}} </name>
<fsummary> Performs a basic path validation according to RFC 5280.</fsummary>
<type>
- <v> TrustedCert = #'OTPCertificate'{} | der_encode() | atom() </v>
+ <v> TrustedCert = #'OTPCertificate'{} | der_encoded() | atom() </v>
<d>Normally a trusted certificate but it can also be a path validation
error that can be discovered while
constructing the input to this function and that should be run through the <c>verify_fun</c>.
For example <c>unknown_ca </c> or <c>selfsigned_peer </c>
</d>
- <v> CertChain = [der_encode()]</v>
+ <v> CertChain = [der_encoded()]</v>
<d>A list of DER encoded certificates in trust order ending with the peer certificate.</d>
<v> Options = proplists:proplist()</v>
<v>PublicKeyInfo = {?'rsaEncryption' | ?'id-dsa',
@@ -527,6 +530,17 @@ fun(OtpCert :: #'OTPCertificate'{},
</desc>
</func>
+ <func>
+ <name>pkix_crl_issuer(CRL) -> issuer_name()</name>
+ <fsummary>Returns the issuer of the <c>CRL</c>.</fsummary>
+ <type>
+ <v>CRL = der_encoded() | #'CertificateList'{} </v>
+ </type>
+ <desc>
+ <p>Returns the issuer of the <c>CRL</c>.</p>
+ </desc>
+ </func>
+
<func>
<name>pkix_crls_validate(OTPCertificate, DPAndCRLs, Options) -> CRLStatus()</name>
<fsummary> Performs CRL validation.</fsummary>
@@ -574,9 +588,48 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
</taglist>
</desc>
</func>
+
+ <func>
+ <name>pkix_crl_verify(CRL, Cert) -> boolean()</name>
+ <fsummary> Verify that <c>Cert</c> is the <c> CRL</c> signer. </fsummary>
+ <type>
+ <v>CRL = der_encoded() | #'CertificateList'{} </v>
+ <v>Cert = der_encoded() | #'OTPCertificate'{} </v>
+ </type>
+ <desc>
+ <p>Verify that <c>Cert</c> is the <c>CRL</c> signer.</p>
+ </desc>
+ </func>
+ <func>
+ <name>pkix_dist_point(Cert) -> DistPoint</name>
+ <fsummary>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.</fsummary>
+ <type>
+ <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
+ <v> DistPoint = #'DistributionPoint'{}</v>
+ </type>
+ <desc>
+ <p>Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
+ Can be used as input to <seealso
+ marker="#pkix_crls_validate-3">pkix_crls_validate/3 </seealso>
+ </p>
+ </desc>
+ </func>
+
+ <func>
+ <name>pkix_dist_points(Cert) -> DistPoints</name>
+ <fsummary> Extracts distribution points from the certificates extensions.</fsummary>
+ <type>
+ <v> Cert = der_encoded() | #'OTPCertificate'{} </v>
+ <v> DistPoints = [#'DistributionPoint'{}]</v>
+ </type>
+ <desc>
+ <p> Extracts distribution points from the certificates extensions.</p>
+ </desc>
+ </func>
+
<func>
- <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encode()</name>
+ <name>pkix_sign(#'OTPTBSCertificate'{}, Key) -> der_encoded()</name>
<fsummary>Signs certificate.</fsummary>
<type>
<v>Key = rsa_public_key() | dsa_public_key()</v>
@@ -606,7 +659,7 @@ fun(#'DistributionPoint'{}, #'CertificateList'{},
<name>pkix_verify(Cert, Key) -> boolean()</name>
<fsummary> Verify pkix x.509 certificate signature.</fsummary>
<type>
- <v>Cert = der_encode()</v>
+ <v>Cert = der_encoded()</v>
<v>Key = rsa_public_key() | dsa_public_key()</v>
</type>
<desc>
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index ae517ca642..8b11538499 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -28,8 +28,9 @@
validate_issuer/4, validate_names/6,
validate_extensions/4,
normalize_general_name/1, is_self_signed/1,
- is_issuer/2, issuer_id/2, is_fixed_dh_cert/1,
- verify_data/1, verify_fun/4, select_extension/2, match_name/3,
+ is_issuer/2, issuer_id/2, distribution_points/1,
+ is_fixed_dh_cert/1, verify_data/1, verify_fun/4,
+ select_extension/2, match_name/3,
extensions_list/1, cert_auth_key_id/1, time_str_2_gregorian_sec/1]).
-define(NULL, 0).
@@ -272,6 +273,16 @@ issuer_id(Otpcert, self) ->
SerialNr = TBSCert#'OTPTBSCertificate'.serialNumber,
{ok, {SerialNr, normalize_general_name(Issuer)}}.
+distribution_points(Otpcert) ->
+ TBSCert = Otpcert#'OTPCertificate'.tbsCertificate,
+ Extensions = extensions_list(TBSCert#'OTPTBSCertificate'.extensions),
+ case select_extension(?'id-ce-cRLDistributionPoints', Extensions) of
+ undefined ->
+ [];
+ #'Extension'{extnValue = Value} ->
+ Value
+ end.
+
%%--------------------------------------------------------------------
-spec is_fixed_dh_cert(#'OTPCertificate'{}) -> boolean().
%%
@@ -296,7 +307,9 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
%% --------------------------------------------------------------------
verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
case VerifyFun(Otpcert, Result, UserState0) of
- {valid,UserState} ->
+ {valid, UserState} ->
+ UserState;
+ {valid_peer, UserState} ->
UserState;
{fail, Reason} ->
case Reason of
diff --git a/lib/public_key/src/pubkey_crl.erl b/lib/public_key/src/pubkey_crl.erl
index f0df4bc3f2..488cc97c70 100644
--- a/lib/public_key/src/pubkey_crl.erl
+++ b/lib/public_key/src/pubkey_crl.erl
@@ -41,10 +41,10 @@ validate(OtpCert, OtherDPCRLs, DP, {DerCRL, CRL}, {DerDeltaCRL, DeltaCRL},
CRLIssuer = TBSCRL#'TBSCertList'.issuer,
AltNames = case pubkey_cert:select_extension(?'id-ce-subjectAltName',
TBSCert#'OTPTBSCertificate'.extensions) of
- undefined ->
- [];
- Ext ->
- Ext#'Extension'.extnValue
+ #'Extension'{extnValue = Value} ->
+ Value;
+ _ ->
+ []
end,
revoked_status(DP, IDP, {directoryName, CRLIssuer},
[ {directoryName, CertIssuer} | AltNames], SerialNumber, Revoked,
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 1bbf4ef416..a0a87e5351 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -46,7 +46,11 @@
pkix_normalize_name/1,
pkix_path_validation/3,
ssh_decode/2, ssh_encode/2,
- pkix_crls_validate/3
+ pkix_crls_validate/3,
+ pkix_dist_point/1,
+ pkix_dist_points/1,
+ pkix_crl_verify/2,
+ pkix_crl_issuer/1
]).
-export_type([public_key/0, private_key/0, pem_entry/0,
@@ -470,6 +474,45 @@ verify(DigestOrPlainText, sha = DigestType, Signature, {Key, #'Dss-Parms'{p = P
crypto:verify(dss, DigestType, DigestOrPlainText, Signature, [P, Q, G, Key]).
%%--------------------------------------------------------------------
+-spec pkix_dist_point(der_encoded() | #'OTPCertificate'{}) ->
+ #'DistributionPoint'{}.
+%% Description: Creates a distribution point for CRLs issued by the same issuer as <c>Cert</c>.
+%%--------------------------------------------------------------------
+pkix_dist_point(OtpCert) when is_binary(OtpCert) ->
+ pkix_dist_point(pkix_decode_cert(OtpCert, otp));
+pkix_dist_point(OtpCert) ->
+ Issuer = public_key:pkix_normalize_name(
+ pubkey_cert_records:transform(
+ OtpCert#'OTPCertificate'.tbsCertificate#'OTPTBSCertificate'.issuer, encode)),
+
+ TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
+ Extensions = pubkey_cert:extensions_list(TBSCert#'OTPTBSCertificate'.extensions),
+ AltNames = case pubkey_cert:select_extension(?'id-ce-issuerAltName', Extensions) of
+ undefined ->
+ [];
+ #'Extension'{extnValue = Value} ->
+ Value
+ end,
+ Point = {fullName, [{directoryName, Issuer} | AltNames]},
+ #'DistributionPoint'{cRLIssuer = asn1_NOVALUE,
+ reasons = asn1_NOVALUE,
+ distributionPoint = Point}.
+%%--------------------------------------------------------------------
+-spec pkix_dist_points(der_encoded() | #'OTPCertificate'{}) ->
+ [#'DistributionPoint'{}].
+%% Description: Extracts distributionpoints specified in the certificates extensions.
+%%--------------------------------------------------------------------
+pkix_dist_points(OtpCert) when is_binary(OtpCert) ->
+ pkix_dist_points(pkix_decode_cert(OtpCert, otp));
+pkix_dist_points(OtpCert) ->
+ Value = pubkey_cert:distribution_points(OtpCert),
+ lists:foldl(fun(Point, Acc0) ->
+ DistPoint = pubkey_cert_records:transform(Point, decode),
+ [DistPoint | Acc0]
+ end,
+ [], Value).
+
+%%--------------------------------------------------------------------
-spec pkix_sign(#'OTPTBSCertificate'{},
rsa_private_key() | dsa_private_key()) -> Der::binary().
%%
@@ -511,6 +554,25 @@ pkix_verify(DerCert, Key = {#'ECPoint'{}, _})
verify(PlainText, DigestType, Signature, Key).
%%--------------------------------------------------------------------
+-spec pkix_crl_verify(CRL::binary() | #'CertificateList'{}, Cert::binary() | #'OTPCertificate'{}) -> boolean().
+%%
+%% Description: Verify that Cert is the CRL signer.
+%%--------------------------------------------------------------------
+pkix_crl_verify(CRL, Cert) when is_binary(CRL) ->
+ pkix_crl_verify(der_decode('CertificateList', CRL), Cert);
+pkix_crl_verify(CRL, Cert) when is_binary(Cert) ->
+ pkix_crl_verify(CRL, pkix_decode_cert(Cert, otp));
+pkix_crl_verify(#'CertificateList'{} = CRL, #'OTPCertificate'{} = Cert) ->
+ TBSCert = Cert#'OTPCertificate'.tbsCertificate,
+ PublicKeyInfo = TBSCert#'OTPTBSCertificate'.subjectPublicKeyInfo,
+ PublicKey = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.subjectPublicKey,
+ AlgInfo = PublicKeyInfo#'OTPSubjectPublicKeyInfo'.algorithm,
+ PublicKeyParams = AlgInfo#'PublicKeyAlgorithm'.parameters,
+ pubkey_crl:verify_crl_signature(CRL,
+ der_encode('CertificateList', CRL),
+ PublicKey, PublicKeyParams).
+
+%%--------------------------------------------------------------------
-spec pkix_is_issuer(Cert :: der_encoded()| #'OTPCertificate'{} | #'CertificateList'{},
IssuerCert :: der_encoded()|
#'OTPCertificate'{}) -> boolean().
@@ -564,15 +626,21 @@ pkix_is_fixed_dh_cert(Cert) when is_binary(Cert) ->
%
%% Description: Returns the issuer id.
%%--------------------------------------------------------------------
-pkix_issuer_id(#'OTPCertificate'{} = OtpCert, self) ->
- pubkey_cert:issuer_id(OtpCert, self);
-
-pkix_issuer_id(#'OTPCertificate'{} = OtpCert, other) ->
- pubkey_cert:issuer_id(OtpCert, other);
+pkix_issuer_id(Cert, Signed)->
+ pkix_issuer_id(Cert, Signed, decode).
-pkix_issuer_id(Cert, Signed) when is_binary(Cert) ->
- OtpCert = pkix_decode_cert(Cert, otp),
- pkix_issuer_id(OtpCert, Signed).
+%%--------------------------------------------------------------------
+-spec pkix_crl_issuer(CRL::binary()| #'CertificateList'{}) ->
+ {rdnSequence,
+ [#'AttributeTypeAndValue'{}]}.
+%
+%% Description: Returns the issuer.
+%%--------------------------------------------------------------------
+pkix_crl_issuer(CRL) when is_binary(CRL) ->
+ pkix_crl_issuer(der_decode('CertificateList', CRL));
+pkix_crl_issuer(#'CertificateList'{} = CRL) ->
+ pubkey_cert_records:transform(
+ CRL#'CertificateList'.tbsCertList#'TBSCertList'.issuer, decode).
%%--------------------------------------------------------------------
-spec pkix_normalize_name({rdnSequence,
@@ -921,3 +989,18 @@ ec_key({PubKey, PrivateKey}, Params) ->
privateKey = binary_to_list(PrivateKey),
parameters = Params,
publicKey = {0, PubKey}}.
+
+pkix_issuer_id(#'OTPCertificate'{} = OtpCert, Signed, decode) when (Signed == self) or
+ (Signed == other) ->
+ pubkey_cert:issuer_id(OtpCert, Signed);
+pkix_issuer_id(#'OTPCertificate'{} = OtpCert, Signed, encode) when (Signed == self) or
+ (Signed == other) ->
+ case pubkey_cert:issuer_id(OtpCert, Signed) of
+ {ok, {Serial, Issuer}} ->
+ {ok, {Serial, pubkey_cert_records:transform(Issuer, encode)}};
+ Error ->
+ Error
+ end;
+pkix_issuer_id(Cert, Signed, Decode) when is_binary(Cert) ->
+ OtpCert = pkix_decode_cert(Cert, otp),
+ pkix_issuer_id(OtpCert, Signed, Decode).
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index 163f5f4413..40c28e86b3 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2013. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -42,7 +42,7 @@ all() ->
encrypt_decrypt,
{group, sign_verify},
pkix, pkix_countryname, pkix_emailaddress, pkix_path_validation,
- pkix_iso_rsa_oid, pkix_iso_dsa_oid].
+ pkix_iso_rsa_oid, pkix_iso_dsa_oid, pkix_crl].
groups() ->
[{pem_decode_encode, [], [dsa_pem, rsa_pem, encrypted_pem,
@@ -712,6 +712,42 @@ pkix_iso_dsa_oid(Config) when is_list(Config) ->
{_, dsa} = public_key:pkix_sign_types(SigAlg#'SignatureAlgorithm'.algorithm).
%%--------------------------------------------------------------------
+
+pkix_crl() ->
+ [{doc, "test pkix_crl_* functions"}].
+
+pkix_crl(Config) when is_list(Config) ->
+ Datadir = ?config(data_dir, Config),
+ {ok, PemCRL} = file:read_file(filename:join(Datadir, "idp_crl.pem")),
+ [{_, CRL, _}] = public_key:pem_decode(PemCRL),
+
+ {ok, IDPPemCert} = file:read_file(filename:join(Datadir, "idp_cert.pem")),
+ [{_, IDPCert, _}] = public_key:pem_decode(IDPPemCert),
+
+ {ok, SignPemCert} = file:read_file(filename:join(Datadir, "crl_signer.pem")),
+ [{_, SignCert, _}] = public_key:pem_decode(SignPemCert),
+
+ OTPIDPCert = public_key:pkix_decode_cert(IDPCert, otp),
+ OTPSignCert = public_key:pkix_decode_cert(SignCert, otp),
+ ERLCRL = public_key:der_decode('CertificateList',CRL),
+
+ {rdnSequence,_} = public_key:pkix_crl_issuer(CRL),
+ {rdnSequence,_} = public_key:pkix_crl_issuer(ERLCRL),
+
+ true = public_key:pkix_crl_verify(CRL, SignCert),
+ true = public_key:pkix_crl_verify(ERLCRL, OTPSignCert),
+
+ [#'DistributionPoint'{}|_] = public_key:pkix_dist_points(IDPCert),
+ [#'DistributionPoint'{}|_] = public_key:pkix_dist_points(OTPIDPCert),
+
+ #'DistributionPoint'{cRLIssuer = asn1_NOVALUE,
+ reasons = asn1_NOVALUE,
+ distributionPoint = Point} = public_key:pkix_dist_point(IDPCert),
+ #'DistributionPoint'{cRLIssuer = asn1_NOVALUE,
+ reasons = asn1_NOVALUE,
+ distributionPoint = Point} = public_key:pkix_dist_point(OTPIDPCert).
+
+%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
asn1_encode_decode({Asn1Type, Der, not_encrypted} = Entry) ->
diff --git a/lib/public_key/test/public_key_SUITE_data/crl_signer.pem b/lib/public_key/test/public_key_SUITE_data/crl_signer.pem
new file mode 100644
index 0000000000..d77f86b45d
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/crl_signer.pem
@@ -0,0 +1,25 @@
+-----BEGIN CERTIFICATE-----
+MIID8zCCAtugAwIBAgIJAKU8w89SmyPyMA0GCSqGSIb3DQEBBAUAMIGGMREwDwYD
+VQQDEwhlcmxhbmdDQTETMBEGA1UECxMKRXJsYW5nIE9UUDEUMBIGA1UEChMLRXJp
+Y3Nzb24gQUIxEjAQBgNVBAcTCVN0b2NraG9sbTELMAkGA1UEBhMCU0UxJTAjBgkq
+hkiG9w0BCQEWFnBldGVyQGVyaXguZXJpY3Nzb24uc2UwHhcNMTUwMjIzMTMyNTMx
+WhcNMTUwMzI1MTMyNTMxWjCBhjERMA8GA1UEAxMIZXJsYW5nQ0ExEzARBgNVBAsT
+CkVybGFuZyBPVFAxFDASBgNVBAoTC0VyaWNzc29uIEFCMRIwEAYDVQQHEwlTdG9j
+a2hvbG0xCzAJBgNVBAYTAlNFMSUwIwYJKoZIhvcNAQkBFhZwZXRlckBlcml4LmVy
+aWNzc29uLnNlMIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAyzwkmKzy
+WTLOafHmgqZVENdt3OYECPA4BamVKyEdi8zgXI0S71wzPZ+XvuGbHDTBzsTHf71L
+xRQgoG30tv5jqWSlfh8iyS6fO+FHxBKd+xg6hLJXk5PCUa5X1D4BO8B4aapEzev+
+T8+pTaOLeVPdfGfKp0yWF50eCpdSF/kMCCIIA8QNSahfcwuLbEEzUNZof6YPZBNm
+e+XUMXCjpb/mU7krfu8nLaspG1HgxQqErEEBzGJE7mguqSVETK/xpGXEMTNIuj8N
+ziFrfqAezDob3z48xHUaHKZRBb9NIxWIjVxkTYaqOtf9UNCT96CHeZ7rk9iNscQu
+USabMIamFY8cNQIDAQABo2IwYDAPBgNVHRMBAf8EBTADAQH/MAsGA1UdDwQEAwIB
+BjAdBgNVHQ4EFgQUm2M3f6UBEIsHI1HIvphbBz60RsAwIQYDVR0RBBowGIEWcGV0
+ZXJAZXJpeC5lcmljc3Nvbi5zZTANBgkqhkiG9w0BAQQFAAOCAQEAPmm0V36HZySF
+BoV03DGyeFUSeMtO0DO058NaXXv2VNPpUXT72Mt1ovXNvVFcReggb01polF7TFFI
+4NRb6qbsLPxny29Clf/9WKY4zDhbb2MIy8yueoOyyeNQtrzY+iQjo4q9U+Aa6xj1
+pxmG1URDfOmCgX33ItCrZXFGa4ic0HrbWgJMDNo4lSOiio8bl3IYN4vBcobRfhDs
+pw5jochE5ZpPh4i76Pg6D99EFkNaLyQioWEu4n2OxR0EBSFLJkVJQ0alUx18AKio
+bje+h5nzRgTm5HApYzcorF57KfUKPDaW1Q6tRckRyHApueDuK8p49ITQE71lmkLc
+ywxoJMrNnA==
+-----END CERTIFICATE-----
+
diff --git a/lib/public_key/test/public_key_SUITE_data/idp_cert.pem b/lib/public_key/test/public_key_SUITE_data/idp_cert.pem
new file mode 100644
index 0000000000..c2afc56a3a
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/idp_cert.pem
@@ -0,0 +1,30 @@
+-----BEGIN CERTIFICATE-----
+MIIFGjCCBAKgAwIBAgIBAzANBgkqhkiG9w0BAQQFADCBgzEOMAwGA1UEAxMFb3Rw
+Q0ExEzARBgNVBAsTCkVybGFuZyBPVFAxFDASBgNVBAoTC0VyaWNzc29uIEFCMQsw
+CQYDVQQGEwJTRTESMBAGA1UEBxMJU3RvY2tob2xtMSUwIwYJKoZIhvcNAQkBFhZw
+ZXRlckBlcml4LmVyaWNzc29uLnNlMB4XDTE1MDIyMzEzMjUzMVoXDTI1MDEwMTEz
+MjUzMVowgYQxDzANBgNVBAMTBnNlcnZlcjETMBEGA1UECxMKRXJsYW5nIE9UUDEU
+MBIGA1UEChMLRXJpY3Nzb24gQUIxCzAJBgNVBAYTAlNFMRIwEAYDVQQHEwlTdG9j
+a2hvbG0xJTAjBgkqhkiG9w0BCQEWFnBldGVyQGVyaXguZXJpY3Nzb24uc2UwggEi
+MA0GCSqGSIb3DQEBAQUAA4IBDwAwggEKAoIBAQDK8EDdNZEebdfxb57e3UA8uTCq
+TsFtJv5tyjnZtSFsGDrwrZYjRMOCJFh8Yv6Ddq4mZiAvUCJxMzW4zVzraMmmQC8z
+Hi3xQyuIq2UCW3ESxLvchCcuSjNOWke0z+rXHzA8Yz9y1fqhhO6AF8q5lLwGo+VQ
+sJkVV8QwB9UXZN4pAc3zTeqZkGCrNY/ZIgtCrk4jw7sY/gumS8BjhXCYGyFZRDvX
+jzIXQx6jn7/2huNbEAiBXbYYAMd7OEwhpHHAWOVA6g+/TNydgRO3W4xVmlEhDpYs
+bnMV/Tq570E1bhz1XWb642K2MnxI74g8FXmhN6x6P8d4zU/eFcs+gxO0X6KzAgMB
+AAGjggGUMIIBkDAJBgNVHRMEAjAAMAsGA1UdDwQEAwIF4DAdBgNVHQ4EFgQUo8dr
+DDQXK25dB6qMY8dNIjAKIPEwgbMGA1UdIwSBqzCBqIAU5YMIq7A5eYQhQsHsc/XC
+7GeZ+kuhgYykgYkwgYYxETAPBgNVBAMTCGVybGFuZ0NBMRMwEQYDVQQLEwpFcmxh
+bmcgT1RQMRQwEgYDVQQKEwtFcmljc3NvbiBBQjESMBAGA1UEBxMJU3RvY2tob2xt
+MQswCQYDVQQGEwJTRTElMCMGCSqGSIb3DQEJARYWcGV0ZXJAZXJpeC5lcmljc3Nv
+bi5zZYIBATAhBgNVHREEGjAYgRZwZXRlckBlcml4LmVyaWNzc29uLnNlMCEGA1Ud
+EgQaMBiBFnBldGVyQGVyaXguZXJpY3Nzb24uc2UwWwYDVR0fBFQwUjAkoCKgIIYe
+aHR0cDovL2xvY2FsaG9zdC9vdHBDQS9jcmwucGVtMCqgKKAmhiRodHRwOi8vbG9j
+YWxob3N0OjM3ODEzL290cENBL2NybC5wZW0wDQYJKoZIhvcNAQEEBQADggEBACwq
+o4nQTTereSIL8ZLQHweJKXYstTaZrRrAaoRUe9oClY7H++zXmMa8iZvUqqdT3fXW
+4KMXXyoB1o+cLxLnAPKOiFFL9rcbaeAMxZMIrTaFDQsOXAPVqJLSWWS5I5LsNvS6
+MlB6O6+0binTyilDKg683VV9nKNiNdL8WzGa5ig+HvK6xUpJwpOTmDmfdg09zQ+8
+aCbJrthXg0tNnGIorttAd2wFvmLUezoJrlfwLChB0M/qa+RVRCFMiPvkWupo5eVK
+Malwpz2xp2rAUlb6qQY7eI6lV8JsVK06QxBmUHP68Y9kYT5/gy5ketjOB0Ypin05
+6+3VrZKFxrkqKaEoL50=
+-----END CERTIFICATE-----
diff --git a/lib/public_key/test/public_key_SUITE_data/idp_crl.pem b/lib/public_key/test/public_key_SUITE_data/idp_crl.pem
new file mode 100644
index 0000000000..0872279501
--- /dev/null
+++ b/lib/public_key/test/public_key_SUITE_data/idp_crl.pem
@@ -0,0 +1,18 @@
+-----BEGIN X509 CRL-----
+MIIC3TCCAcUCAQEwDQYJKoZIhvcNAQEEBQAwgYYxETAPBgNVBAMTCGVybGFuZ0NB
+MRMwEQYDVQQLEwpFcmxhbmcgT1RQMRQwEgYDVQQKEwtFcmljc3NvbiBBQjESMBAG
+A1UEBxMJU3RvY2tob2xtMQswCQYDVQQGEwJTRTElMCMGCSqGSIb3DQEJARYWcGV0
+ZXJAZXJpeC5lcmljc3Nvbi5zZRcNMTUwMjIzMTMyNTMxWhcNMTUwMjI0MTMyNTMx
+WqCCAQgwggEEMIG7BgNVHSMEgbMwgbCAFJtjN3+lARCLByNRyL6YWwc+tEbAoYGM
+pIGJMIGGMREwDwYDVQQDEwhlcmxhbmdDQTETMBEGA1UECxMKRXJsYW5nIE9UUDEU
+MBIGA1UEChMLRXJpY3Nzb24gQUIxEjAQBgNVBAcTCVN0b2NraG9sbTELMAkGA1UE
+BhMCU0UxJTAjBgkqhkiG9w0BCQEWFnBldGVyQGVyaXguZXJpY3Nzb24uc2WCCQCl
+PMPPUpsj8jA4BgNVHRwBAf8ELjAsoCqgKIYmaHR0cDovL2xvY2FsaG9zdDo4MDAw
+L2VybGFuZ0NBL2NybC5wZW0wCgYDVR0UBAMCAQEwDQYJKoZIhvcNAQEEBQADggEB
+AE9WKJhW1oivBEE91akeDcYCtSVp98F7DxzQyJTBLQJGMEXSg8G/oAp64F4qs3oV
+LXS5YFYwxjD9tXByGVEJoIUUMtfMeCvZMgd2V8mBlAJiyHkTrFFA8PgBv+htrJji
+nrheAhrEedqZbqwmrcU34h9fWHp0Zl6UDYyF3I/S0/5ilIz3DvNZ9SBfKKt3DYeW
+hon7qpNo6YrtEzbXyOaa2mFX9c1w39LBZ1FdY0jEzUfh2eImBLxnBjZArNxzYuU8
+a+lNMjc6JUAJwITS6C1YfI4ECsqXe0K/n90pMcm/jgiGFCZhVbXq+Nrm/24qPKBA
+zqoNos7aV7LEYLYOjknaIhY=
+-----END X509 CRL-----
diff --git a/lib/ssh/src/ssh_info.erl b/lib/ssh/src/ssh_info.erl
index 9ed598b3ab..e5a8666af0 100644
--- a/lib/ssh/src/ssh_info.erl
+++ b/lib/ssh/src/ssh_info.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -179,7 +179,14 @@ line(Len, Char) ->
datetime() ->
- {{YYYY,MM,DD}, {H,M,S}} = calendar:now_to_universal_time(now()),
+ %% Adapt to new OTP 18 erlang time API and be back-compatible
+ TimeStamp = try
+ erlang:timestamp()
+ catch
+ error:undef ->
+ erlang:now()
+ end,
+ {{YYYY,MM,DD}, {H,M,S}} = calendar:now_to_universal_time(TimeStamp),
lists:flatten(io_lib:format('~4w-~2..0w-~2..0w ~2..0w:~2..0w:~2..0w UTC',[YYYY,MM,DD, H,M,S])).
diff --git a/lib/ssh/test/ssh_basic_SUITE.erl b/lib/ssh/test/ssh_basic_SUITE.erl
index cb1b4ae945..b449012ffc 100644
--- a/lib/ssh/test/ssh_basic_SUITE.erl
+++ b/lib/ssh/test/ssh_basic_SUITE.erl
@@ -1,7 +1,7 @@
%%
%% %CopyrightBegin%
%%
-%% Copyright Ericsson AB 2008-2014. All Rights Reserved.
+%% Copyright Ericsson AB 2008-2015. All Rights Reserved.
%%
%% The contents of this file are subject to the Erlang Public License,
%% Version 1.1, (the "License"); you may not use this file except in
@@ -715,7 +715,14 @@ ssh_connect_arg4_timeout(_Config) ->
%% try to connect with a timeout, but "supervise" it
Client = spawn(fun() ->
- T0 = now(),
+ %% Adapt to OTP 18 erlang time API and be back-compatible
+ T0 = try
+ erlang:monotonic_time()
+ catch
+ error:undef ->
+ %% Use Erlang system time as monotonic time
+ erlang:now()
+ end,
Rc = ssh:connect("localhost",Port,[],Timeout),
ct:log("Client ssh:connect got ~p",[Rc]),
Parent ! {done,self(),Rc,T0}
@@ -724,11 +731,12 @@ ssh_connect_arg4_timeout(_Config) ->
%% Wait for client reaction on the connection try:
receive
{done, Client, {error,timeout}, T0} ->
- Msp = ms_passed(T0, now()),
+ Msp = ms_passed(T0),
exit(Server,hasta_la_vista___baby),
Low = 0.9*Timeout,
High = 1.1*Timeout,
- ct:log("Timeout limits: ~p--~p, timeout was ~p, expected ~p",[Low,High,Msp,Timeout]),
+ ct:log("Timeout limits: ~.4f - ~.4f ms, timeout "
+ "was ~.4f ms, expected ~p ms",[Low,High,Msp,Timeout]),
if
Low<Msp, Msp<High -> ok;
true -> {fail, "timeout not within limits"}
@@ -748,12 +756,16 @@ ssh_connect_arg4_timeout(_Config) ->
end.
-%% Help function
-%% N2-N1
-ms_passed(N1={_,_,M1}, N2={_,_,M2}) ->
- {0,{0,Min,Sec}} = calendar:time_difference(calendar:now_to_local_time(N1),
- calendar:now_to_local_time(N2)),
- 1000 * (Min*60 + Sec + (M2-M1)/1000000).
+%% Help function, elapsed milliseconds since T0
+ms_passed({_,_,_} = T0 ) ->
+ %% OTP 17 and earlier
+ timer:now_diff(erlang:now(), T0)/1000;
+
+ms_passed(T0) ->
+ %% OTP 18
+ erlang:convert_time_resolution(erlang:monotonic_time() - T0,
+ erlang:time_resolution(),
+ 1000000)/1000.
%%--------------------------------------------------------------------
ssh_connect_negtimeout_parallel(Config) -> ssh_connect_negtimeout(Config,true).
diff --git a/lib/stdlib/src/ets.erl b/lib/stdlib/src/ets.erl
index 42b11a97e2..93c4f59896 100644
--- a/lib/stdlib/src/ets.erl
+++ b/lib/stdlib/src/ets.erl
@@ -1613,13 +1613,18 @@ choice(Height, Width, P, Mode, Tab, Key, Turn, Opos) ->
end.
get_line(P, Default) ->
- case io:get_line(P) of
+ case line_string(io:get_line(P)) of
"\n" ->
Default;
L ->
L
end.
+%% If the standard input is set to binary mode
+%% convert it to a list so we can properly match.
+line_string(Binary) when is_binary(Binary) -> unicode:characters_to_list(Binary);
+line_string(Other) -> Other.
+
nonl(S) -> string:strip(S, right, $\n).
print_number(Tab, Key, Num) ->