diff options
Diffstat (limited to 'lib')
33 files changed, 285 insertions, 137 deletions
diff --git a/lib/asn1/doc/src/notes.xml b/lib/asn1/doc/src/notes.xml index 26640acabc..03452648bb 100644 --- a/lib/asn1/doc/src/notes.xml +++ b/lib/asn1/doc/src/notes.xml @@ -32,6 +32,23 @@ <p>This document describes the changes made to the asn1 application.</p> +<section><title>Asn1 5.0.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p> + Fixed compilation error of generated code caused by a + missing quotation of function names as part of an + external call for encoding.</p> + <p> + Own Id: OTP-14519 Aux Id: ERIERL-49 </p> + </item> + </list> + </section> + +</section> + <section><title>Asn1 5.0</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/asn1/src/asn1ct_gen_per.erl b/lib/asn1/src/asn1ct_gen_per.erl index 28b4e46b0c..82e9326294 100644 --- a/lib/asn1/src/asn1ct_gen_per.erl +++ b/lib/asn1/src/asn1ct_gen_per.erl @@ -101,7 +101,7 @@ gen_encode_user(Erules,D) when is_record(D,typedef) -> #'Externaltypereference'{module=CurrMod,type=Etype} -> emit([{asis,enc_func(Etype)},"(Val).",nl]); #'Externaltypereference'{module=Emod,type=Etype} -> - emit([{asis,Emod},":",enc_func(Etype),"(Val).",nl]) + emit([{asis,Emod},":",{asis,enc_func(Etype)},"(Val).",nl]) end. diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 index 32b8f75dde..dee3cd5048 100644 --- a/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom.asn1 @@ -1,8 +1,9 @@ ImportsFrom DEFINITIONS AUTOMATIC TAGS ::= BEGIN -IMPORTS Int FROM ImportsFrom2; +IMPORTS Int, Quoted-Seq FROM ImportsFrom2; i Int ::= 42 +My-Seq ::= Quoted-Seq END diff --git a/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 index b0c29d24ae..a8e619e215 100644 --- a/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 +++ b/lib/asn1/test/asn1_SUITE_data/ImportsFrom2.asn1 @@ -2,6 +2,11 @@ ImportsFrom2 DEFINITIONS AUTOMATIC TAGS ::= BEGIN IMPORTS Int FROM ImportsFrom3; +Quoted-Seq ::= SEQUENCE { + x INTEGER(0..17), + y INTEGER(0..666) +} + LocalDef ::= OCTET STRING END diff --git a/lib/asn1/vsn.mk b/lib/asn1/vsn.mk index 7329a9f879..ec92d324eb 100644 --- a/lib/asn1/vsn.mk +++ b/lib/asn1/vsn.mk @@ -1 +1 @@ -ASN1_VSN = 5.0 +ASN1_VSN = 5.0.1 diff --git a/lib/crypto/c_src/crypto.c b/lib/crypto/c_src/crypto.c index 52ce00b937..1d9c1e0f88 100644 --- a/lib/crypto/c_src/crypto.c +++ b/lib/crypto/c_src/crypto.c @@ -4048,14 +4048,14 @@ printf("\r\n"); RSA *rsa = EVP_PKEY_get1_RSA(pkey); enif_alloc_binary(RSA_size(rsa), &sig_bin); len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); i = RSA_sign(md->type, tbs, len, sig_bin.data, &siglen, rsa); RSA_free(rsa); } else if (argv[0] == atom_dss) { DSA *dsa = EVP_PKEY_get1_DSA(pkey); enif_alloc_binary(DSA_size(dsa), &sig_bin); len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); i = DSA_sign(md->type, tbs, len, sig_bin.data, &siglen, dsa); DSA_free(dsa); } else if (argv[0] == atom_ecdsa) { @@ -4063,7 +4063,7 @@ printf("\r\n"); EC_KEY *ec = EVP_PKEY_get1_EC_KEY(pkey); enif_alloc_binary(ECDSA_size(ec), &sig_bin); len = EVP_MD_size(md); - ERL_VALGRIND_ASSERT_MEM_DEFINED(digest_bin.data, len); + ERL_VALGRIND_ASSERT_MEM_DEFINED(tbs, len); i = ECDSA_sign(md->type, tbs, len, sig_bin.data, &siglen, ec); EC_KEY_free(ec); #else diff --git a/lib/diameter/examples/code/node.erl b/lib/diameter/examples/code/node.erl index 246be4194b..fc5830f8e2 100644 --- a/lib/diameter/examples/code/node.erl +++ b/lib/diameter/examples/code/node.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2010-2015. All Rights Reserved. +%% Copyright Ericsson AB 2010-2016. All Rights Reserved. %% %% Licensed under the Apache License, Version 2.0 (the "License"); %% you may not use this file except in compliance with the License. @@ -30,6 +30,8 @@ connect/2, stop/1]). +-export([message/3]). + -type protocol() :: tcp | sctp. @@ -128,6 +130,8 @@ stop(Name) -> server_opts({T, Addr, Port}) -> [{transport_module, tmod(T)}, {transport_config, [{reuseaddr, true}, + {sender, true}, + {message_cb, [fun ?MODULE:message/3, 0]}, {ip, addr(Addr)}, {port, Port}]}]; @@ -173,3 +177,26 @@ addr(loopback) -> {127,0,0,1}; addr(A) -> A. + +%% --------------------------------------------------------------------------- + +%% message/3 +%% +%% Simple message callback that limits the number of concurrent +%% requests on the peer connection in question. + +%% Incoming request. +message(recv, <<_:32, 1:1, _/bits>> = Bin, N) -> + [Bin, N < 32, fun ?MODULE:message/3, N+1]; + +%% Outgoing request. +message(ack, <<_:32, 1:1, _/bits>>, _) -> + []; + +%% Incoming answer or request discarded. +message(ack, _, N) -> + [N =< 32, fun ?MODULE:message/3, N-1]; + +%% Outgoing message or incoming answer. +message(_, Bin, _) -> + [Bin]. diff --git a/lib/diameter/src/base/diameter_peer_fsm.erl b/lib/diameter/src/base/diameter_peer_fsm.erl index 1b0dc417e5..e43b3f54cf 100644 --- a/lib/diameter/src/base/diameter_peer_fsm.erl +++ b/lib/diameter/src/base/diameter_peer_fsm.erl @@ -542,11 +542,11 @@ put_route(Pid) -> MRef = monitor(process, Pid), put(Pid, MRef). -%% get_route/2 +%% get_route/3 -%% incoming answer -get_route(_, #diameter_packet{header = #diameter_header{is_request = false}} - = Pkt) -> +%% Incoming answer. +get_route(_, _, #diameter_packet{header = #diameter_header{is_request = false}} + = Pkt) -> Seqs = diameter_codec:sequence_numbers(Pkt), case erase(Seqs) of {Pid, Ref, MRef} -> @@ -557,8 +557,14 @@ get_route(_, #diameter_packet{header = #diameter_header{is_request = false}} false end; -%% incoming request -get_route(Ack, _) -> +%% Requests answered here ... +get_route(_, N, _) + when N == 'CER'; + N == 'DPR' -> + false; + +%% ... or not. +get_route(Ack, _, _) -> Ack. %% erase_route/1 @@ -650,7 +656,7 @@ encode(Rec, Opts, Dict) -> %% incoming/2 incoming({recv = T, Name, Pkt}, #state{parent = Pid, ack = Ack} = S) -> - Pid ! {T, self(), get_route(Ack, Pkt), Name, Pkt}, + Pid ! {T, self(), get_route(Ack, Name, Pkt), Name, Pkt}, rcv(Name, Pkt, S); incoming(#diameter_header{is_request = R}, #state{transport = TPid, diff --git a/lib/diameter/src/base/diameter_service.erl b/lib/diameter/src/base/diameter_service.erl index a976a8b998..788f697627 100644 --- a/lib/diameter/src/base/diameter_service.erl +++ b/lib/diameter/src/base/diameter_service.erl @@ -514,6 +514,13 @@ transition({tc_timeout, T}, S) -> tc_timeout(T, S), ok; +transition({nodeup, Node, _}, S) -> + nodeup(Node, S), + ok; + +transition({nodedown, _Node, _}, _) -> + ok; + transition(Req, S) -> unexpected(handle_info, [Req], S), ok. @@ -709,6 +716,8 @@ mref(P) -> init_shared(#state{options = #{use_shared_peers := T}, service_name = Svc}) -> + T == false orelse net_kernel:monitor_nodes(true, [{node_type, visible}, + nodedown_reason]), notify(T, Svc, {service, self()}). init_mod(#diameter_app{alias = Alias, @@ -728,6 +737,11 @@ notify(Share, SvcName, T) -> %% Test for the empty list for upgrade reasons: there's no %% diameter_peer:notify/3 in old code. +nodeup(Node, #state{options = #{share_peers := SP}, + service_name = SvcName}) -> + lists:member(Node, remotes(SP)) + andalso diameter_peer:notify([Node], SvcName, {service, self()}). + remotes(false) -> []; @@ -1400,9 +1414,15 @@ is_remote(Pid, T) -> %% # remote_peer_up/4 %% --------------------------------------------------------------------------- -remote_peer_up(TPid, Aliases, Caps, #state{options = #{use_shared_peers := T}} +remote_peer_up(TPid, Aliases, Caps, #state{options = #{use_shared_peers := T}, + remote = {PeerT, _, _}} = S) -> - is_remote(TPid, T) andalso rpu(TPid, Aliases, Caps, S). + is_remote(TPid, T) + andalso not ets:member(PeerT, TPid) + andalso rpu(TPid, Aliases, Caps, S). + +%% Notification can be duplicate since remote nodes push and the local +%% node pulls. rpu(TPid, Aliases, Caps, #state{service = Svc, remote = RT}) -> #diameter_service{applications = Apps} = Svc, @@ -1412,6 +1432,7 @@ rpu(TPid, Aliases, Caps, #state{service = Svc, remote = RT}) -> rpu(_, [] = No, _, _) -> No; + rpu(TPid, Aliases, Caps, {PeerT, _, _} = RT) -> monitor(process, TPid), ets:insert(PeerT, #peer{pid = TPid, diff --git a/lib/diameter/src/transport/diameter_sctp.erl b/lib/diameter/src/transport/diameter_sctp.erl index 6a9f1f940b..a0104fac6e 100644 --- a/lib/diameter/src/transport/diameter_sctp.erl +++ b/lib/diameter/src/transport/diameter_sctp.erl @@ -112,7 +112,7 @@ {transport :: pid(), ack = false :: boolean(), socket :: gen_sctp:sctp_socket(), - assoc_id :: gen_sctp:assoc_id()}). %% next output stream + assoc_id :: gen_sctp:assoc_id()}). %% Listener process state. -record(listener, @@ -565,7 +565,7 @@ transition(Msg, S) %% Deferred actions from a message_cb. transition({actions, Dir, Acts}, S) -> - actions(Acts, Dir, S); + setopts(ok, actions(Acts, Dir, S)); %% Request to close the transport connection. transition({diameter, {close, Pid}}, #transport{parent = Pid}) -> diff --git a/lib/diameter/src/transport/diameter_tcp.erl b/lib/diameter/src/transport/diameter_tcp.erl index a2f393d5d4..aa09a261a3 100644 --- a/lib/diameter/src/transport/diameter_tcp.erl +++ b/lib/diameter/src/transport/diameter_tcp.erl @@ -640,7 +640,7 @@ transition(Msg, S) %% Deferred actions from a message_cb. transition({actions, Dir, Acts}, S) -> - actions(Acts, Dir, S); + setopts(actions(Acts, Dir, S)); %% Request to close the transport connection. transition({diameter, {close, Pid}}, #transport{parent = Pid, diff --git a/lib/inets/doc/src/httpc.xml b/lib/inets/doc/src/httpc.xml index 66ec6cabd8..29e4b22632 100644 --- a/lib/inets/doc/src/httpc.xml +++ b/lib/inets/doc/src/httpc.xml @@ -408,7 +408,7 @@ <c>{self, once}</c>, the first message has an extra element, that is, <c>{http, {RequestId, stream_start, Headers, Pid}}</c>. This is the process id to be used as an argument to - <c>http:stream_next/1</c> to trigger the next message to be sent to + <c>httpc:stream_next/1</c> to trigger the next message to be sent to the calling process.</p> <p>Notice that chunked encoding can add headers so that there are more headers in the <c>stream_end</c> diff --git a/lib/inets/src/http_server/mod_log.erl b/lib/inets/src/http_server/mod_log.erl index ad7e9713d9..ec570504be 100644 --- a/lib/inets/src/http_server/mod_log.erl +++ b/lib/inets/src/http_server/mod_log.erl @@ -105,8 +105,8 @@ do(Info) -> Code = proplists:get_value(code,Head,unknown), transfer_log(Info, "-", AuthUser, Date, Code, Size), {proceed, Info#mod.data}; - {_StatusCode, Response} -> - transfer_log(Info,"-",AuthUser,Date,200, + {StatusCode, Response} -> + transfer_log(Info, "-", AuthUser, Date, StatusCode, httpd_util:flatlength(Response)), {proceed,Info#mod.data}; undefined -> diff --git a/lib/kernel/doc/src/disk_log.xml b/lib/kernel/doc/src/disk_log.xml index 1be28adfb8..884cb32c0c 100644 --- a/lib/kernel/doc/src/disk_log.xml +++ b/lib/kernel/doc/src/disk_log.xml @@ -972,7 +972,7 @@ <item> <p>Specifies if messages will be sent to <c>error_logger</c> on recoverable errors with - the log files. Defaults to <c>true</c>.</p> + the log files. Defaults to <c>false</c>.</p> </item> </taglist> <p><c>open/1</c> returns <c>{ok, <anno>Log</anno>}</c> if the diff --git a/lib/kernel/doc/src/inet.xml b/lib/kernel/doc/src/inet.xml index b71e8a1e5d..169a76463b 100644 --- a/lib/kernel/doc/src/inet.xml +++ b/lib/kernel/doc/src/inet.xml @@ -222,11 +222,18 @@ fe80::204:acff:fe17:bf38 <name name="get_rc" arity="0"/> <fsummary>Return a list of IP configuration parameters.</fsummary> <desc> - <p>Returns the state of the <c>Inet</c> configuration database in + <p> + Returns the state of the <c>Inet</c> configuration database in form of a list of recorded configuration parameters. For more information, see <seealso marker="erts:inet_cfg">ERTS User's Guide: Inet Configuration</seealso>. - Only parameters with other than default values are returned.</p> + </p> + <p> + Only actual parameters with other than default values + are returned, for example not directives that specify + other sources for configuration parameters nor + directives that clear parameters. + </p> </desc> </func> diff --git a/lib/kernel/doc/src/notes.xml b/lib/kernel/doc/src/notes.xml index e1cf45109d..9cd03ffcad 100644 --- a/lib/kernel/doc/src/notes.xml +++ b/lib/kernel/doc/src/notes.xml @@ -31,6 +31,21 @@ </header> <p>This document describes the changes made to the Kernel application.</p> +<section><title>Kernel 5.3.1</title> + + <section><title>Fixed Bugs and Malfunctions</title> + <list> + <item> + <p>The documentation for the 'quiet' option in + disk_log:open/1 had an incorrect default value.</p> + <p> + Own Id: OTP-14498</p> + </item> + </list> + </section> + +</section> + <section><title>Kernel 5.3</title> <section><title>Fixed Bugs and Malfunctions</title> diff --git a/lib/kernel/src/inet.erl b/lib/kernel/src/inet.erl index 6aef5476f1..dc20c21c77 100644 --- a/lib/kernel/src/inet.erl +++ b/lib/kernel/src/inet.erl @@ -151,7 +151,8 @@ %%% --------------------------------- --spec get_rc() -> [{Par :: any(), Val :: any()}]. +-spec get_rc() -> [{Par :: atom(), Val :: any()} | + {Par :: atom(), Val1 :: any(), Val2 :: any()}]. get_rc() -> inet_db:get_rc(). diff --git a/lib/kernel/src/kernel.appup.src b/lib/kernel/src/kernel.appup.src index 77085b2064..f1ef70a373 100644 --- a/lib/kernel/src/kernel.appup.src +++ b/lib/kernel/src/kernel.appup.src @@ -18,7 +18,7 @@ %% %CopyrightEnd% {"%VSN%", %% Up from - max one major revision back - [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.* + [{<<"5\\.[0-3](\\.[0-9]+)*">>,[restart_new_emulator]}], % OTP-19.*, OTP-20.0 %% Down to - max one major revision back - [{<<"5\\.[0-2](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.* + [{<<"5\\.[0-3](\\.[0-9]+)*">>,[restart_new_emulator]}] % OTP-19.*, OTP-20.0 }. diff --git a/lib/kernel/vsn.mk b/lib/kernel/vsn.mk index 4edecd8969..c9463241d1 100644 --- a/lib/kernel/vsn.mk +++ b/lib/kernel/vsn.mk @@ -1 +1 @@ -KERNEL_VSN = 5.3 +KERNEL_VSN = 5.3.1 diff --git a/lib/public_key/doc/src/public_key.xml b/lib/public_key/doc/src/public_key.xml index 35f9e86cad..942203bd12 100644 --- a/lib/public_key/doc/src/public_key.xml +++ b/lib/public_key/doc/src/public_key.xml @@ -634,8 +634,8 @@ fun(OtpCert :: #'OTPCertificate'{}, <v>OTPCertificate = #'OTPCertificate'{}</v> <v>DPAndCRLs = [{DP::#'DistributionPoint'{}, {DerCRL::der_encoded(), CRL::#'CertificateList'{}}}] </v> <v>Options = proplists:proplist()</v> - <v>CRLStatus() = valid | {bad_cert, revocation_status_undetermined} | - {bad_cert, {revoked, crl_reason()}}</v> + <v>CRLStatus() = valid | {bad_cert, revocation_status_undetermined} | {bad_cert, {revocation_status_undetermined, + {bad_crls, Details::term()}}} | {bad_cert, {revoked, crl_reason()}}</v> </type> <desc> <p>Performs CRL validation. It is intended to be called from @@ -663,7 +663,7 @@ fun(OtpCert :: #'OTPCertificate'{}, <tag>{issuer_fun, fun()}</tag> <item> <p>The fun has the following type specification:</p> - + <code> fun(#'DistributionPoint'{}, #'CertificateList'{}, {rdnSequence,[#'AttributeTypeAndValue'{}]}, term()) -> @@ -673,7 +673,15 @@ fun(#'DistributionPoint'{}, #'CertificateList'{}, that has signed the CRL. </p> <code> fun(DP, CRL, Issuer, UserState) -> {ok, RootCert, CertChain}</code> - </item> + </item> + + <tag>{undetermined_details, boolean()}</tag> + <item> + <p>Defaults to false. When revocation status can not be + determined, and this option is set to true, details of why no + CRLs where accepted are included in the return value.</p> + </item> + </taglist> </desc> </func> diff --git a/lib/public_key/include/public_key.hrl b/lib/public_key/include/public_key.hrl index a1e7dd31bc..663e1856ac 100644 --- a/lib/public_key/include/public_key.hrl +++ b/lib/public_key/include/public_key.hrl @@ -70,7 +70,8 @@ reasons_mask, cert_status, interim_reasons_mask, - valid_ext + valid_ext, + details }). -record('ECPoint', { diff --git a/lib/public_key/src/pubkey_crl.erl b/lib/public_key/src/pubkey_crl.erl index 33bef91827..3621e9c0da 100644 --- a/lib/public_key/src/pubkey_crl.erl +++ b/lib/public_key/src/pubkey_crl.erl @@ -58,7 +58,8 @@ validate(OtpCert, OtherDPCRLs, DP, {DerCRL, CRL}, {DerDeltaCRL, DeltaCRL}, init_revokation_state() -> #revoke_state{reasons_mask = sets:new(), interim_reasons_mask = sets:new(), - cert_status = unrevoked}. + cert_status = unrevoked, + details = []}. fresh_crl(_, {undefined, undefined}, _) -> %% Typically happens when there is no delta CRL that covers a CRL @@ -152,9 +153,10 @@ verify_crl(OtpCert, DP, CRL, DerCRL, DeltaCRL, DerDeltaCRL, OtherDPCRLs, RevokedState, CRL, DerCRL, DeltaCRL, DerDeltaCRL, IssuerFun, TrustedOtpCert, Path, OtherDPCRLs, IDP); - _ -> - {invalid, State0#revoke_state{valid_ext = ValidExt}} - end; + _ -> + Details = RevokedState#revoke_state.details, + {invalid, RevokedState#revoke_state{valid_ext = ValidExt, details = [{{bad_crl, no_issuer_cert_chain}, CRL} | Details]}} + end; {error, issuer_not_found} -> case Fun(DP, CRL, issuer_not_found, AdditionalArgs) of {ok, TrustedOtpCert, Path} -> @@ -163,13 +165,16 @@ verify_crl(OtpCert, DP, CRL, DerCRL, DeltaCRL, DerDeltaCRL, OtherDPCRLs, DerDeltaCRL, IssuerFun, TrustedOtpCert, Path, OtherDPCRLs, IDP); _ -> - {invalid, {skip, State0}} - end + Details = State0#revoke_state.details, + {invalid, {skip, State0#revoke_state{details = [{{bad_crl, no_issuer_cert_chain}, CRL} | Details] }}} + end catch - throw:{bad_crl, invalid_issuer} -> - {invalid, {skip, State0}}; - throw:_ -> - {invalid, State0#revoke_state{valid_ext = ValidExt}} + throw:{bad_crl, invalid_issuer} = Reason -> + Details = RevokedState#revoke_state.details, + {invalid, {skip, RevokedState#revoke_state{details = [{Reason, CRL} | Details]}}}; + throw:Reason -> + Details = RevokedState#revoke_state.details, + {invalid, RevokedState#revoke_state{details = [{Reason, CRL} | Details]}} end. verify_mask_and_signatures(Revoked, DeltaRevoked, RevokedState, CRL, DerCRL, DeltaCRL, DerDeltaCRL, @@ -183,10 +188,12 @@ verify_mask_and_signatures(Revoked, DeltaRevoked, RevokedState, CRL, DerCRL, Del TrustedOtpCert, Path, IssuerFun, OtherDPCRLs, IDP), {valid, Revoked, DeltaRevoked, RevokedState#revoke_state{reasons_mask = ReasonsMask}, IDP} catch - throw:_ -> - {invalid, RevokedState}; + throw:Reason -> + Details = RevokedState#revoke_state.details, + {invalid, RevokedState#revoke_state{details = [{Reason, CRL} | Details]}}; error:{badmatch, _} -> - {invalid, RevokedState} + Details = RevokedState#revoke_state.details, + {invalid, RevokedState#revoke_state{details = [{{bad_crl, invalid_signature}, CRL} | Details]}} end. @@ -356,7 +363,7 @@ verify_scope(#'OTPCertificate'{tbsCertificate = TBSCert}, #'DistributionPoint'{c verify_scope(DPName, IDPName, Names, TBSCert, IDP). verify_scope(asn1_NOVALUE, _, asn1_NOVALUE, _, _) -> - throw({bad_crl, scope_error1}); + throw({bad_crl, scope_error}); verify_scope(asn1_NOVALUE, IDPName, DPIssuerNames, TBSCert, IDP) -> verify_dp_name(IDPName, DPIssuerNames), verify_dp_bools(TBSCert, IDP); diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl index 834a75983e..1776baf830 100644 --- a/lib/public_key/src/public_key.erl +++ b/lib/public_key/src/public_key.erl @@ -823,8 +823,9 @@ pkix_path_validation(#'OTPCertificate'{} = TrustedCert, CertChain, Options) %-------------------------------------------------------------------- -spec pkix_crls_validate(#'OTPCertificate'{}, [{DP::#'DistributionPoint'{}, {DerCRL::binary(), CRL::#'CertificateList'{}}}], - Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined} - | {bad_cert, {revoked, crl_reason()}}. + Options :: proplists:proplist()) -> valid | {bad_cert, revocation_status_undetermined} | + {bad_cert, {revocation_status_undetermined, Reason::term()}} | + {bad_cert, {revoked, crl_reason()}}. %% Description: Performs a CRL validation according to RFC 5280. %%-------------------------------------------------------------------- @@ -1165,8 +1166,13 @@ der_cert(#'OTPCertificate'{} = Cert) -> der_cert(Der) when is_binary(Der) -> Der. -pkix_crls_validate(_, [],_, _, _) -> - {bad_cert, revocation_status_undetermined}; +pkix_crls_validate(_, [],_, Options, #revoke_state{details = Details}) -> + case proplists:get_value(undetermined_details, Options, false) of + false -> + {bad_cert, revocation_status_undetermined}; + true -> + {bad_cert, {revocation_status_undetermined, {bad_crls, format_details(Details)}}} + end; pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, RevokedState0) -> CallBack = proplists:get_value(update_crl, Options, fun(_, CurrCRL) -> CurrCRL @@ -1186,9 +1192,14 @@ pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, Revoked do_pkix_crls_validate(OtpCert, [{DP, CRL, DeltaCRL} | Rest], All, Options, RevokedState0) -> OtherDPCRLs = All -- [{DP, CRL, DeltaCRL}], case pubkey_crl:validate(OtpCert, OtherDPCRLs, DP, CRL, DeltaCRL, Options, RevokedState0) of - {undetermined, _, _} when Rest == []-> - {bad_cert, revocation_status_undetermined}; - {undetermined, _, RevokedState} when Rest =/= []-> + {undetermined, unrevoked, #revoke_state{details = Details}} when Rest == []-> + case proplists:get_value(undetermined_details, Options, false) of + false -> + {bad_cert, revocation_status_undetermined}; + true -> + {bad_cert, {revocation_status_undetermined, {bad_crls, Details}}} + end; + {undetermined, unrevoked, RevokedState} when Rest =/= []-> pkix_crls_validate(OtpCert, Rest, All, Options, RevokedState); {finished, unrevoked} -> valid; @@ -1461,3 +1472,7 @@ to_lower_ascii(C) -> C. to_string(S) when is_list(S) -> S; to_string(B) when is_binary(B) -> binary_to_list(B). +format_details([]) -> + no_relevant_crls; +format_details(Details) -> + Details. diff --git a/lib/ssl/src/dtls_connection.erl b/lib/ssl/src/dtls_connection.erl index e8cfbbe2e3..b6aafc3fa4 100644 --- a/lib/ssl/src/dtls_connection.erl +++ b/lib/ssl/src/dtls_connection.erl @@ -48,7 +48,7 @@ select_sni_extension/1]). %% Alert and close handling --export([encode_alert/3,send_alert/2, close/5]). +-export([encode_alert/3,send_alert/2, close/5, protocol_name/0]). %% Data handling @@ -208,6 +208,9 @@ setopts(Transport, Socket, Other) -> getopts(Transport, Socket, Tag) -> dtls_socket:getopts(Transport, Socket, Tag). +protocol_name() -> + "DTLS". + %%==================================================================== %% tls_connection_sup API %%==================================================================== diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl index 696a55e4b9..b923785e17 100644 --- a/lib/ssl/src/ssl_alert.erl +++ b/lib/ssl/src/ssl_alert.erl @@ -57,16 +57,16 @@ decode(Bin) -> reason_code(#alert{description = ?CLOSE_NOTIFY}, _) -> closed; reason_code(#alert{description = Description}, _) -> - {tls_alert, description_txt(Description)}. + {tls_alert, string:to_lower(description_txt(Description))}. %%-------------------------------------------------------------------- -spec alert_txt(#alert{}) -> string(). %% %% Description: Returns the error string for given alert. %%-------------------------------------------------------------------- -alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined}) -> - Mod ++ ":" ++ integer_to_list(Line) ++ ":" ++ - level_txt(Level) ++" "++ description_txt(Description); +alert_txt(#alert{level = Level, description = Description, where = {Mod,Line}, reason = undefined, role = Role}) -> + "at " ++ Mod ++ ":" ++ integer_to_list(Line) ++ " " ++ string:to_upper(atom_to_list(Role)) ++ " ALERT: " ++ + level_txt(Level) ++ description_txt(Description); alert_txt(#alert{reason = Reason} = Alert) -> BaseTxt = alert_txt(Alert#alert{reason = undefined}), FormatDepth = 9, % Some limit on printed representation of an error @@ -93,73 +93,73 @@ decode(<<>>, Acc, _) -> lists:reverse(Acc, []). level_txt(?WARNING) -> - "Warning:"; + "Warning - "; level_txt(?FATAL) -> - "Fatal error:". + "Fatal - ". description_txt(?CLOSE_NOTIFY) -> - "close notify"; + "Close Notify"; description_txt(?UNEXPECTED_MESSAGE) -> - "unexpected message"; + "Unexpected Message"; description_txt(?BAD_RECORD_MAC) -> - "bad record mac"; + "Bad Record MAC"; description_txt(?DECRYPTION_FAILED) -> - "decryption failed"; + "Decryption Failed"; description_txt(?RECORD_OVERFLOW) -> - "record overflow"; + "Record Overflow"; description_txt(?DECOMPRESSION_FAILURE) -> - "decompression failure"; + "Decompression Failure"; description_txt(?HANDSHAKE_FAILURE) -> - "handshake failure"; + "Handshake Failure"; description_txt(?NO_CERTIFICATE_RESERVED) -> - "No certificate reserved"; + "No Certificate Reserved"; description_txt(?BAD_CERTIFICATE) -> - "bad certificate"; + "Bad Certificate"; description_txt(?UNSUPPORTED_CERTIFICATE) -> - "unsupported certificate"; + "Unsupported Certificate"; description_txt(?CERTIFICATE_REVOKED) -> - "certificate revoked"; + "Certificate Revoked"; description_txt(?CERTIFICATE_EXPIRED) -> - "certificate expired"; + "Certificate Expired"; description_txt(?CERTIFICATE_UNKNOWN) -> - "certificate unknown"; + "Certificate Unknown"; description_txt(?ILLEGAL_PARAMETER) -> - "illegal parameter"; + "Illegal Parameter"; description_txt(?UNKNOWN_CA) -> - "unknown ca"; + "Unknown CA"; description_txt(?ACCESS_DENIED) -> - "access denied"; + "Access Denied"; description_txt(?DECODE_ERROR) -> - "decode error"; + "Decode Error"; description_txt(?DECRYPT_ERROR) -> - "decrypt error"; + "Decrypt Error"; description_txt(?EXPORT_RESTRICTION) -> - "export restriction"; + "Export Restriction"; description_txt(?PROTOCOL_VERSION) -> - "protocol version"; + "Protocol Version"; description_txt(?INSUFFICIENT_SECURITY) -> - "insufficient security"; + "Insufficient Security"; description_txt(?INTERNAL_ERROR) -> - "internal error"; + "Internal Error"; description_txt(?USER_CANCELED) -> - "user canceled"; + "User Canceled"; description_txt(?NO_RENEGOTIATION) -> - "no renegotiation"; + "No Renegotiation"; description_txt(?UNSUPPORTED_EXTENSION) -> - "unsupported extension"; + "Unsupported Extension"; description_txt(?CERTIFICATE_UNOBTAINABLE) -> - "certificate unobtainable"; + "Certificate Unobtainable"; description_txt(?UNRECOGNISED_NAME) -> - "unrecognised name"; + "Unrecognised Name"; description_txt(?BAD_CERTIFICATE_STATUS_RESPONSE) -> - "bad certificate status response"; + "Bad Certificate Status Response"; description_txt(?BAD_CERTIFICATE_HASH_VALUE) -> - "bad certificate hash value"; + "Bad Certificate Hash Value"; description_txt(?UNKNOWN_PSK_IDENTITY) -> - "unknown psk identity"; + "Unknown Psk Identity"; description_txt(?INAPPROPRIATE_FALLBACK) -> - "inappropriate fallback"; + "Inappropriate Fallback"; description_txt(?NO_APPLICATION_PROTOCOL) -> - "no application protocol"; + "No application protocol"; description_txt(Enum) -> lists:flatten(io_lib:format("unsupported/unknown alert: ~p", [Enum])). diff --git a/lib/ssl/src/ssl_alert.hrl b/lib/ssl/src/ssl_alert.hrl index f3743ba0f0..1aabb6c55a 100644 --- a/lib/ssl/src/ssl_alert.hrl +++ b/lib/ssl/src/ssl_alert.hrl @@ -118,6 +118,7 @@ level, description, where = {?FILE, ?LINE}, + role, reason }). -endif. % -ifdef(ssl_alert). diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index f3fbe254f3..1afc4ad2af 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1143,7 +1143,7 @@ handle_alert(#alert{level = ?FATAL} = Alert, StateName, port = Port, session = Session, user_application = {_Mon, Pid}, role = Role, socket_options = Opts, tracker = Tracker}) -> invalidate_session(Role, Host, Port, Session), - log_alert(SslOpts#ssl_options.log_alert, StateName, Alert), + log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), alert_user(Transport, Tracker, Socket, StateName, Opts, Pid, From, Alert, Role, Connection), {stop, normal}; @@ -1153,15 +1153,16 @@ handle_alert(#alert{level = ?WARNING, description = ?CLOSE_NOTIFY} = Alert, {stop, {shutdown, peer_close}}; handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName, - #state{ssl_options = SslOpts, renegotiation = {true, internal}} = State) -> - log_alert(SslOpts#ssl_options.log_alert, StateName, Alert), + #state{role = Role, ssl_options = SslOpts, protocol_cb = Connection, renegotiation = {true, internal}} = State) -> + log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), handle_normal_shutdown(Alert, StateName, State), {stop, {shutdown, peer_close}}; handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, StateName, - #state{ssl_options = SslOpts, renegotiation = {true, From}, + #state{role = Role, + ssl_options = SslOpts, renegotiation = {true, From}, protocol_cb = Connection} = State0) -> - log_alert(SslOpts#ssl_options.log_alert, StateName, Alert), + log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), gen_statem:reply(From, {error, renegotiation_rejected}), {Record, State} = Connection:next_record(State0), %% Go back to connection! @@ -1169,8 +1170,8 @@ handle_alert(#alert{level = ?WARNING, description = ?NO_RENEGOTIATION} = Alert, %% Gracefully log and ignore all other warning alerts handle_alert(#alert{level = ?WARNING} = Alert, StateName, - #state{ssl_options = SslOpts, protocol_cb = Connection} = State0) -> - log_alert(SslOpts#ssl_options.log_alert, StateName, Alert), + #state{ssl_options = SslOpts, protocol_cb = Connection, role = Role} = State0) -> + log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = opposite_role(Role)}), {Record, State} = Connection:next_record(State0), Connection:next_event(StateName, Record, State). @@ -2370,18 +2371,19 @@ alert_user(Transport, Tracker, Socket, Active, Pid, From, Alert, Role, Connectio Transport, Socket, Connection, Tracker), ReasonCode}) end. -log_alert(true, Info, Alert) -> +log_alert(true, ProtocolName, StateName, Alert) -> Txt = ssl_alert:alert_txt(Alert), - error_logger:format("SSL: ~p: ~s\n", [Info, Txt]); -log_alert(false, _, _) -> + error_logger:format("~s: In state ~p ~s\n", [ProtocolName, StateName, Txt]); +log_alert(false, _, _, _) -> ok. handle_own_alert(Alert, Version, StateName, - #state{transport_cb = Transport, - socket = Socket, - protocol_cb = Connection, - connection_states = ConnectionStates, - ssl_options = SslOpts} = State) -> + #state{role = Role, + transport_cb = Transport, + socket = Socket, + protocol_cb = Connection, + connection_states = ConnectionStates, + ssl_options = SslOpts} = State) -> try %% Try to tell the other side {BinMsg, _} = Connection:encode_alert(Alert, Version, ConnectionStates), @@ -2390,7 +2392,7 @@ handle_own_alert(Alert, Version, StateName, ignore end, try %% Try to tell the local user - log_alert(SslOpts#ssl_options.log_alert, StateName, Alert), + log_alert(SslOpts#ssl_options.log_alert, Connection:protocol_name(), StateName, Alert#alert{role = Role}), handle_normal_shutdown(Alert,StateName, State) catch _:_ -> ok diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index 3cf466e78f..b1661624b5 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -415,9 +415,11 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef, path_validation_alert(Reason) end catch - error:_ -> + error:{badmatch,{asn1, Asn1Reason}} -> %% ASN-1 decode of certificate somehow failed - ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, failed_to_decode_certificate) + ?ALERT_REC(?FATAL, ?CERTIFICATE_UNKNOWN, {failed_to_decode_certificate, Asn1Reason}); + error:OtherReason -> + ?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason}) end. %%-------------------------------------------------------------------- @@ -1611,8 +1613,11 @@ path_validation_alert({bad_cert, unknown_critical_extension}) -> ?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE); path_validation_alert({bad_cert, {revoked, _}}) -> ?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED); -path_validation_alert({bad_cert, revocation_status_undetermined}) -> - ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE); +%%path_validation_alert({bad_cert, revocation_status_undetermined}) -> +%% ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE); +path_validation_alert({bad_cert, {revocation_status_undetermined, Details}}) -> + Alert = ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE), + Alert#alert{reason = Details}; path_validation_alert({bad_cert, selfsigned_peer}) -> ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE); path_validation_alert({bad_cert, unknown_ca}) -> @@ -2189,7 +2194,8 @@ crl_check(OtpCert, Check, CertDbHandle, CertDbRef, {Callback, CRLDbHandle}, _, C ssl_crl:trusted_cert_and_path(CRL, Issuer, {CertPath, DBInfo}) end, {CertDbHandle, CertDbRef}}}, - {update_crl, fun(DP, CRL) -> Callback:fresh_crl(DP, CRL) end} + {update_crl, fun(DP, CRL) -> Callback:fresh_crl(DP, CRL) end}, + {undetermined_details, true} ], case dps_and_crls(OtpCert, Callback, CRLDbHandle, ext) of no_dps -> @@ -2199,7 +2205,7 @@ crl_check(OtpCert, Check, CertDbHandle, CertDbRef, {Callback, CRLDbHandle}, _, C DpsAndCRLs -> %% This DP list may be empty if relevant CRLs existed %% but could not be retrived, will result in {bad_cert, revocation_status_undetermined} case public_key:pkix_crls_validate(OtpCert, DpsAndCRLs, Options) of - {bad_cert, revocation_status_undetermined} -> + {bad_cert, {revocation_status_undetermined, _}} -> crl_check_same_issuer(OtpCert, Check, dps_and_crls(OtpCert, Callback, CRLDbHandle, same_issuer), Options); Other -> @@ -2209,7 +2215,7 @@ crl_check(OtpCert, Check, CertDbHandle, CertDbRef, {Callback, CRLDbHandle}, _, C crl_check_same_issuer(OtpCert, best_effort, Dps, Options) -> case public_key:pkix_crls_validate(OtpCert, Dps, Options) of - {bad_cert, revocation_status_undetermined} -> + {bad_cert, {revocation_status_undetermined, _}} -> valid; Other -> Other diff --git a/lib/ssl/src/tls_connection.erl b/lib/ssl/src/tls_connection.erl index 352874c77d..e3ffbea3d3 100644 --- a/lib/ssl/src/tls_connection.erl +++ b/lib/ssl/src/tls_connection.erl @@ -56,7 +56,7 @@ reinit_handshake_data/1, select_sni_extension/1]). %% Alert and close handling --export([send_alert/2, close/5]). +-export([send_alert/2, close/5, protocol_name/0]). %% Data handling -export([passive_receive/2, next_record_if_active/1, handle_common_event/4, send/3, @@ -164,6 +164,8 @@ encode_data(Data, Version, ConnectionStates0)-> encode_alert(#alert{} = Alert, Version, ConnectionStates) -> tls_record:encode_alert_record(Alert, Version, ConnectionStates). +protocol_name() -> + "TLS". %%==================================================================== %% tls_connection_sup API %%==================================================================== @@ -719,7 +721,7 @@ close(downgrade, _,_,_,_) -> %% Other close(_, Socket, Transport, _,_) -> Transport:close(Socket). - + convert_state(#state{ssl_options = Options} = State, up, "5.3.5", "5.3.6") -> State#state{ssl_options = convert_options_partial_chain(Options, up)}; convert_state(#state{ssl_options = Options} = State, down, "5.3.6", "5.3.5") -> diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index 3b9073ac0b..e61993598e 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -1429,7 +1429,7 @@ supports_ssl_tls_version(sslv2 = Version) -> Exe = "openssl", Args = ["s_client", VersionFlag], Port = ssl_test_lib:portable_open_port(Exe, Args), - do_supports_ssl_tls_version(Port) + do_supports_ssl_tls_version(Port, "") end; supports_ssl_tls_version(Version) -> @@ -1437,23 +1437,26 @@ supports_ssl_tls_version(Version) -> Exe = "openssl", Args = ["s_client", VersionFlag], Port = ssl_test_lib:portable_open_port(Exe, Args), - do_supports_ssl_tls_version(Port). + do_supports_ssl_tls_version(Port, ""). -do_supports_ssl_tls_version(Port) -> +do_supports_ssl_tls_version(Port, Acc) -> receive - {Port, {data, "u"}} -> - false; - {Port, {data, "unknown option" ++ _}} -> - false; - {Port, {data, Data}} -> - case lists:member("error", string:tokens(Data, ":")) of - true -> - false; - false -> - do_supports_ssl_tls_version(Port) - end + {Port, {data, Data}} -> + case Acc ++ Data of + "unknown option" ++ _ -> + false; + Error when length(Error) >= 11 -> + case lists:member("error", string:tokens(Data, ":")) of + true -> + false; + false -> + do_supports_ssl_tls_version(Port, Error) + end; + _ -> + do_supports_ssl_tls_version(Port, Acc ++ Data) + end after 1000 -> - true + true end. ssl_options(Option, Config) when is_atom(Option) -> diff --git a/lib/stdlib/doc/src/rand.xml b/lib/stdlib/doc/src/rand.xml index e06d7e467d..a68fb7d55f 100644 --- a/lib/stdlib/doc/src/rand.xml +++ b/lib/stdlib/doc/src/rand.xml @@ -66,7 +66,7 @@ <p>Jump function: equivalent to 2^64 calls</p> <p> This is a corrected version of the previous default algorithm, - that now has been superseeded by Xoroshiro116+ (<c>exrop</c>). + that now has been superseded by Xoroshiro116+ (<c>exrop</c>). Since there is no native 58 bit rotate instruction this algorithm executes a little (say < 15%) faster than <c>exrop</c>. See the diff --git a/lib/stdlib/src/array.erl b/lib/stdlib/src/array.erl index 079b761463..a237eaa489 100644 --- a/lib/stdlib/src/array.erl +++ b/lib/stdlib/src/array.erl @@ -1603,7 +1603,7 @@ foldl_2(I, E, A, Ix, F, D, N, R, S) -> Ix + S, F, D, N, R, S). -spec foldl_3(pos_integer(), _, A, array_indx(), - fun((array_indx, _, A) -> B), integer()) -> B. + fun((array_indx(), _, A) -> B), integer()) -> B. foldl_3(I, E, A, Ix, F, N) when I =< N -> foldl_3(I+1, E, F(Ix, element(I, E), A), Ix+1, F, N); diff --git a/lib/stdlib/src/otp_internal.erl b/lib/stdlib/src/otp_internal.erl index 9e9c0dc413..8933eb01b5 100644 --- a/lib/stdlib/src/otp_internal.erl +++ b/lib/stdlib/src/otp_internal.erl @@ -112,7 +112,7 @@ obsolete_1(crypto, rand_uniform, 2) -> %% *** CRYPTO added in OTP 19 *** obsolete_1(crypto, rand_bytes, 1) -> - {deprecated, {crypto, strong_rand_bytes, 1}}; + {removed, {crypto, strong_rand_bytes, 1}, "20.0"}; %% *** CRYPTO added in R16B01 *** |