aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--OTP_VERSION2
-rw-r--r--erts/doc/src/notes.xml30
-rw-r--r--erts/emulator/beam/dist.c23
-rw-r--r--erts/emulator/beam/dist.h2
-rw-r--r--erts/emulator/beam/erl_node_tables.c83
-rw-r--r--erts/emulator/sys/unix/erl_child_setup.c11
-rw-r--r--erts/vsn.mk2
-rw-r--r--lib/compiler/doc/src/notes.xml16
-rw-r--r--lib/compiler/src/compile.erl1
-rw-r--r--lib/compiler/vsn.mk2
-rw-r--r--lib/ssl/src/ssl_certificate.erl97
-rw-r--r--lib/ssl/src/ssl_handshake.erl54
-rw-r--r--lib/ssl/test/ssl_certificate_verify_SUITE.erl36
-rw-r--r--lib/ssl/test/ssl_handshake_SUITE.erl26
-rw-r--r--lib/syntax_tools/src/erl_syntax.erl2
-rw-r--r--lib/syntax_tools/test/merl_SUITE.erl14
-rw-r--r--otp_versions.table1
17 files changed, 300 insertions, 102 deletions
diff --git a/OTP_VERSION b/OTP_VERSION
index 7f4e82686d..a36f82fcac 100644
--- a/OTP_VERSION
+++ b/OTP_VERSION
@@ -1 +1 @@
-21.0.8
+21.0.9
diff --git a/erts/doc/src/notes.xml b/erts/doc/src/notes.xml
index 653a917823..3d336aed65 100644
--- a/erts/doc/src/notes.xml
+++ b/erts/doc/src/notes.xml
@@ -31,6 +31,36 @@
</header>
<p>This document describes the changes made to the ERTS application.</p>
+<section><title>Erts 10.0.8</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>
+ As of ERTS version 10.0 (OTP 21.0) the
+ <c>erl_child_setup</c> program, which creates port
+ programs, ignores <c>TERM</c> signals. This setting was
+ unintentionally inherited by port programs. Handling of
+ <c>TERM</c> signals in port programs has now been
+ restored to the default behavior. That is, terminate the
+ process.</p>
+ <p>
+ Own Id: OTP-15289 Aux Id: ERIERL-235, OTP-14943, ERL-576 </p>
+ </item>
+ <item>
+ <p>
+ The fix made for OTP-15279 in erts-10.07 (OTP-21.0.8) was
+ not complete. It could cause a new connection attempt to
+ be incorrectly aborted in certain cases. This fix will
+ amend that flaw.</p>
+ <p>
+ Own Id: OTP-15296 Aux Id: OTP-15279, ERIERL-226 </p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Erts 10.0.7</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index ceb89a6910..f041e92375 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -3550,20 +3550,18 @@ BIF_RETTYPE erts_internal_new_connection_1(BIF_ALIST_1)
BIF_RET(TUPLE2(hp, make_small(conn_id), dhandle));
}
-static Sint abort_connection(DistEntry* dep, Uint32 conn_id)
+Sint erts_abort_connection_rwunlock(DistEntry* dep)
{
- erts_de_rwlock(dep);
+ Sint reds = 0;
+ ERTS_LC_ASSERT(erts_lc_is_de_rwlocked(dep));
- if (dep->connection_id != conn_id)
- ;
- else if (dep->state == ERTS_DE_STATE_CONNECTED) {
+ if (dep->state == ERTS_DE_STATE_CONNECTED) {
kill_connection(dep);
}
else if (dep->state == ERTS_DE_STATE_PENDING) {
ErtsAtomCache *cache;
ErtsDistOutputBuf *obuf;
ErtsProcList *resume_procs;
- Sint reds = 0;
ErtsMonLnkDist *mld;
ASSERT(is_nil(dep->cid));
@@ -3608,17 +3606,18 @@ static Sint abort_connection(DistEntry* dep, Uint32 conn_id)
erts_de_rwlock(dep);
ASSERT(dep->state == ERTS_DE_STATE_EXITING);
dep->state = ERTS_DE_STATE_IDLE;
- erts_de_rwunlock(dep);
- return reds;
}
erts_de_rwunlock(dep);
- return 0;
+ return reds;
}
-Sint
-erts_abort_connection(DistEntry *dep, Uint32 conn_id)
+static Sint abort_connection(DistEntry *dep, Uint32 conn_id)
{
- return abort_connection(dep, conn_id);
+ erts_de_rwlock(dep);
+ if (dep->connection_id == conn_id)
+ return erts_abort_connection_rwunlock(dep);
+ erts_de_rwunlock(dep);
+ return 0;
}
BIF_RETTYPE erts_internal_abort_connection_2(BIF_ALIST_2)
diff --git a/erts/emulator/beam/dist.h b/erts/emulator/beam/dist.h
index 30b4b35c20..75cb865390 100644
--- a/erts/emulator/beam/dist.h
+++ b/erts/emulator/beam/dist.h
@@ -399,7 +399,7 @@ extern void erts_kill_dist_connection(DistEntry *dep, Uint32);
extern Uint erts_dist_cache_size(void);
-extern Sint erts_abort_connection(DistEntry *dep, Uint32 conn_id);
+extern Sint erts_abort_connection_rwunlock(DistEntry *dep);
#endif
diff --git a/erts/emulator/beam/erl_node_tables.c b/erts/emulator/beam/erl_node_tables.c
index 9b34af1480..f4a36d124a 100644
--- a/erts/emulator/beam/erl_node_tables.c
+++ b/erts/emulator/beam/erl_node_tables.c
@@ -60,6 +60,10 @@ static int references_atoms_need_init = 1;
static ErtsMonotonicTime orig_node_tab_delete_delay;
static ErtsMonotonicTime node_tab_delete_delay;
+
+static void report_gc_active_dist_entry(Eterm sysname, enum dist_entry_state);
+
+
/* -- The distribution table ---------------------------------------------- */
#define ErtsBin2DistEntry(B) \
@@ -412,44 +416,6 @@ static void schedule_delete_dist_entry(DistEntry* dep)
static void
start_timer_delete_dist_entry(void *vdep)
{
- DistEntry *dep = vdep;
- Eterm sysname;
- enum dist_entry_state state;
- Uint32 connection_id;
-
- erts_de_rlock(dep);
- state = dep->state;
- connection_id = dep->connection_id;
- sysname = dep->sysname;
- erts_de_runlock(dep);
-
- if (state != ERTS_DE_STATE_IDLE) {
- char *state_str;
- erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
- switch (state) {
- case ERTS_DE_STATE_CONNECTED:
- state_str = "connected";
- break;
- case ERTS_DE_STATE_PENDING:
- state_str = "pending connect";
- break;
- case ERTS_DE_STATE_EXITING:
- state_str = "exiting";
- break;
- case ERTS_DE_STATE_IDLE:
- state_str = "idle";
- break;
- default:
- state_str = "unknown";
- break;
- }
- erts_dsprintf(dsbuf, "Garbage collecting distribution "
- "entry for node %T in state: %s",
- sysname, state_str);
- erts_send_error_to_logger_nogl(dsbuf);
- erts_abort_connection(dep, connection_id);
- }
-
if (node_tab_delete_delay == 0) {
prepare_try_delete_dist_entry(vdep);
}
@@ -489,6 +455,19 @@ static void try_delete_dist_entry(DistEntry* dep)
{
erts_aint_t refc;
+ erts_de_rwlock(dep);
+ if (dep->state != ERTS_DE_STATE_IDLE && de_refc_read(dep,0) == 0) {
+ Eterm sysname = dep->sysname;
+ enum dist_entry_state state = dep->state;
+
+ if (dep->state != ERTS_DE_STATE_PENDING)
+ ERTS_INTERNAL_ERROR("Garbage collecting connected distribution entry");
+ erts_abort_connection_rwunlock(dep);
+ report_gc_active_dist_entry(sysname, state);
+ }
+ else
+ erts_de_rwunlock(dep);
+
erts_rwmtx_rwlock(&erts_dist_table_rwmtx);
/*
* Another thread might have looked up this dist entry after
@@ -515,6 +494,34 @@ static void try_delete_dist_entry(DistEntry* dep)
}
}
+static void report_gc_active_dist_entry(Eterm sysname,
+ enum dist_entry_state state)
+{
+ char *state_str;
+ erts_dsprintf_buf_t *dsbuf = erts_create_logger_dsbuf();
+ switch (state) {
+ case ERTS_DE_STATE_CONNECTED:
+ state_str = "connected";
+ break;
+ case ERTS_DE_STATE_PENDING:
+ state_str = "pending connect";
+ break;
+ case ERTS_DE_STATE_EXITING:
+ state_str = "exiting";
+ break;
+ case ERTS_DE_STATE_IDLE:
+ state_str = "idle";
+ break;
+ default:
+ state_str = "unknown";
+ break;
+ }
+ erts_dsprintf(dsbuf, "Garbage collecting distribution "
+ "entry for node %T in state: %s",
+ sysname, state_str);
+ erts_send_error_to_logger_nogl(dsbuf);
+}
+
int erts_dist_entry_destructor(Binary *bin)
{
DistEntry *dep = ErtsBin2DistEntry(bin);
diff --git a/erts/emulator/sys/unix/erl_child_setup.c b/erts/emulator/sys/unix/erl_child_setup.c
index 221ee2a69d..129861ebd5 100644
--- a/erts/emulator/sys/unix/erl_child_setup.c
+++ b/erts/emulator/sys/unix/erl_child_setup.c
@@ -133,6 +133,7 @@ static int sigchld_pipe[2];
static int
start_new_child(int pipes[])
{
+ struct sigaction sa;
int errln = -1;
int size, res, i, pos = 0;
char *buff, *o_buff;
@@ -143,6 +144,16 @@ start_new_child(int pipes[])
/* only child executes here */
+ /* Restore default handling of sigterm... */
+ sa.sa_handler = SIG_DFL;
+ sigemptyset(&sa.sa_mask);
+ sa.sa_flags = 0;
+
+ if (sigaction(SIGTERM, &sa, 0) == -1) {
+ perror(NULL);
+ exit(1);
+ }
+
do {
res = read(pipes[0], (char*)&size, sizeof(size));
} while(res < 0 && (errno == EINTR || errno == ERRNO_BLOCK));
diff --git a/erts/vsn.mk b/erts/vsn.mk
index 293b555b18..e28716c37f 100644
--- a/erts/vsn.mk
+++ b/erts/vsn.mk
@@ -18,7 +18,7 @@
# %CopyrightEnd%
#
-VSN = 10.0.7
+VSN = 10.0.8
# Port number 4365 in 4.2
# Port number 4366 in 4.3
diff --git a/lib/compiler/doc/src/notes.xml b/lib/compiler/doc/src/notes.xml
index 671126b73b..023e28e702 100644
--- a/lib/compiler/doc/src/notes.xml
+++ b/lib/compiler/doc/src/notes.xml
@@ -32,6 +32,22 @@
<p>This document describes the changes made to the Compiler
application.</p>
+<section><title>Compiler 7.2.4</title>
+
+ <section><title>Fixed Bugs and Malfunctions</title>
+ <list>
+ <item>
+ <p>Fix a regression in OTP-15204 that removed
+ <c>.beam</c> file metadata that some external build tools
+ relied on.</p>
+ <p>
+ Own Id: OTP-15292</p>
+ </item>
+ </list>
+ </section>
+
+</section>
+
<section><title>Compiler 7.2.3</title>
<section><title>Fixed Bugs and Malfunctions</title>
diff --git a/lib/compiler/src/compile.erl b/lib/compiler/src/compile.erl
index e1c1f7338e..562d57a6ef 100644
--- a/lib/compiler/src/compile.erl
+++ b/lib/compiler/src/compile.erl
@@ -1603,7 +1603,6 @@ effects_code_generation(Option) ->
binary -> false;
verbose -> false;
{cwd,_} -> false;
- {i,_} -> false;
{outdir, _} -> false;
_ -> true
end.
diff --git a/lib/compiler/vsn.mk b/lib/compiler/vsn.mk
index 355113a94d..bb6ee00cd7 100644
--- a/lib/compiler/vsn.mk
+++ b/lib/compiler/vsn.mk
@@ -1 +1 @@
-COMPILER_VSN = 7.2.3
+COMPILER_VSN = 7.2.4
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index c15e8a2138..549e557beb 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -33,6 +33,7 @@
-export([trusted_cert_and_path/4,
certificate_chain/3,
+ certificate_chain/4,
file_to_certificats/2,
file_to_crls/2,
validate/3,
@@ -40,7 +41,8 @@
is_valid_key_usage/2,
select_extension/2,
extensions_list/1,
- public_key_type/1
+ public_key_type/1,
+ foldl_db/3
]).
%%====================================================================
@@ -79,7 +81,8 @@ trusted_cert_and_path(CertChain, CertDbHandle, CertDbRef, PartialChainHandler) -
%% Trusted must be selfsigned or it is an incomplete chain
handle_path(Trusted, Path, PartialChainHandler);
_ ->
- %% Root CA could not be verified
+ %% Root CA could not be verified, but partial
+ %% chain handler may trusted a cert that we got
handle_incomplete_chain(Path, PartialChainHandler)
end
end.
@@ -94,10 +97,23 @@ certificate_chain(undefined, _, _) ->
{error, no_cert};
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) when is_binary(OwnCert) ->
ErlCert = public_key:pkix_decode_cert(OwnCert, otp),
- certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert]);
+ certificate_chain(ErlCert, OwnCert, CertDbHandle, CertsDbRef, [OwnCert], []);
certificate_chain(OwnCert, CertDbHandle, CertsDbRef) ->
DerCert = public_key:pkix_encode('OTPCertificate', OwnCert, otp),
- certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert]).
+ certificate_chain(OwnCert, DerCert, CertDbHandle, CertsDbRef, [DerCert], []).
+
+%%--------------------------------------------------------------------
+-spec certificate_chain(undefined | binary() | #'OTPCertificate'{} , db_handle(), certdb_ref(), [der_cert()]) ->
+ {error, no_cert} | {ok, #'OTPCertificate'{} | undefined, [der_cert()]}.
+%%
+%% Description: Create certificate chain with certs from
+%%--------------------------------------------------------------------
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) when is_binary(Cert) ->
+ ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ certificate_chain(ErlCert, Cert, CertDbHandle, CertsDbRef, [Cert], Candidates);
+certificate_chain(Cert, CertDbHandle, CertsDbRef, Candidates) ->
+ DerCert = public_key:pkix_encode('OTPCertificate', Cert, otp),
+ certificate_chain(Cert, DerCert, CertDbHandle, CertsDbRef, [DerCert], Candidates).
%%--------------------------------------------------------------------
-spec file_to_certificats(binary(), term()) -> [der_cert()].
%%
@@ -187,9 +203,20 @@ public_key_type(?'id-ecPublicKey') ->
ec.
%%--------------------------------------------------------------------
+-spec foldl_db(fun(), db_handle() | {extracted, list()}, list()) ->
+ {ok, term()} | issuer_not_found.
+%%
+%% Description:
+%%--------------------------------------------------------------------
+foldl_db(IsIssuerFun, CertDbHandle, []) ->
+ ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle);
+foldl_db(IsIssuerFun, _, [_|_] = ListDb) ->
+ lists:foldl(IsIssuerFun, issuer_not_found, ListDb).
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
-certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
+certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain, ListDb) ->
IssuerAndSelfSigned =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
@@ -200,12 +227,12 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
case IssuerAndSelfSigned of
{_, true = SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, ignore, ignore, SelfSigned, ListDb);
{{error, issuer_not_found}, SelfSigned} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) of
{ok, {SerialNr, Issuer}} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain,
- SerialNr, Issuer, SelfSigned);
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain,
+ SerialNr, Issuer, SelfSigned, ListDb);
_ ->
%% Guess the the issuer must be the root
%% certificate. The verification of the
@@ -214,19 +241,19 @@ certificate_chain(OtpCert, BinCert, CertDbHandle, CertsDbRef, Chain) ->
{ok, undefined, lists:reverse(Chain)}
end;
{{ok, {SerialNr, Issuer}}, SelfSigned} ->
- certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned)
+ do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, SelfSigned, ListDb)
end.
-certificate_chain(_, _, [RootCert | _] = Chain, _, _, true) ->
+do_certificate_chain(_, _, [RootCert | _] = Chain, _, _, true, _) ->
{ok, RootCert, lists:reverse(Chain)};
-certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned) ->
+do_certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _, ListDb) ->
case ssl_manager:lookup_trusted_cert(CertDbHandle, CertsDbRef,
SerialNr, Issuer) of
{ok, {IssuerCert, ErlCert}} ->
ErlCert = public_key:pkix_decode_cert(IssuerCert, otp),
certificate_chain(ErlCert, IssuerCert,
- CertDbHandle, CertsDbRef, [IssuerCert | Chain]);
+ CertDbHandle, CertsDbRef, [IssuerCert | Chain], ListDb);
_ ->
%% The trusted cert may be obmitted from the chain as the
%% counter part needs to have it anyway to be able to
@@ -234,7 +261,8 @@ certificate_chain(CertDbHandle, CertsDbRef, Chain, SerialNr, Issuer, _SelfSigned
{ok, undefined, lists:reverse(Chain)}
end.
-find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
+
+find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef, ListDb) ->
IsIssuerFun =
fun({_Key, {_Der, #'OTPCertificate'{} = ErlCertCandidate}}, Acc) ->
case public_key:pkix_is_issuer(OtpCert, ErlCertCandidate) of
@@ -252,26 +280,29 @@ find_issuer(OtpCert, BinCert, CertDbHandle, CertsDbRef) ->
Acc
end,
- if is_reference(CertsDbRef) -> % actual DB exists
- try ssl_pkix_db:foldl(IsIssuerFun, issuer_not_found, CertDbHandle) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end;
- is_tuple(CertsDbRef), element(1,CertsDbRef) =:= extracted -> % cache bypass byproduct
- {extracted, CertsData} = CertsDbRef,
- DB = [Entry || {decoded, Entry} <- CertsData],
- try lists:foldl(IsIssuerFun, issuer_not_found, DB) of
- issuer_not_found ->
- {error, issuer_not_found}
- catch
- {ok, _IssuerId} = Return ->
- Return
- end
+ Result = case is_reference(CertsDbRef) of
+ true ->
+ do_find_issuer(IsIssuerFun, CertDbHandle, ListDb);
+ false ->
+ {extracted, CertsData} = CertsDbRef,
+ DB = [Entry || {decoded, Entry} <- CertsData],
+ do_find_issuer(IsIssuerFun, CertDbHandle, DB)
+ end,
+ case Result of
+ issuer_not_found ->
+ {error, issuer_not_found};
+ Result ->
+ Result
end.
+do_find_issuer(IssuerFun, CertDbHandle, CertDb) ->
+ try
+ foldl_db(IssuerFun, CertDbHandle, CertDb)
+ catch
+ throw:{ok, _} = Return ->
+ Return
+ end.
+
is_valid_extkey_usage(KeyUse, client) ->
%% Client wants to verify server
is_valid_key_usage(KeyUse,?'id-kp-serverAuth');
@@ -300,7 +331,7 @@ other_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) ->
{ok, IssuerId} ->
{other, IssuerId};
{error, issuer_not_found} ->
- case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef) of
+ case find_issuer(OtpCert, BinCert, CertDbHandle, CertDbRef, []) of
{ok, IssuerId} ->
{other, IssuerId};
Other ->
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 3888f9dcf6..dc89fb0029 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -338,7 +338,7 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
Opts, CRLDbHandle, Role, Host) ->
ServerName = server_name(Opts#ssl_options.server_name_indication, Host, Role),
- [PeerCert | _] = ASN1Certs,
+ [PeerCert | ChainCerts ] = ASN1Certs,
try
{TrustedCert, CertPath} =
ssl_certificate:trusted_cert_and_path(ASN1Certs, CertDbHandle, CertDbRef,
@@ -347,14 +347,14 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
CertDbHandle, CertDbRef, ServerName,
Opts#ssl_options.customize_hostname_check,
Opts#ssl_options.crl_check, CRLDbHandle, CertPath),
- case public_key:pkix_path_validation(TrustedCert,
- CertPath,
- [{max_path_length, Opts#ssl_options.depth},
- {verify_fun, ValidationFunAndState}]) of
+ Options = [{max_path_length, Opts#ssl_options.depth},
+ {verify_fun, ValidationFunAndState}],
+ case public_key:pkix_path_validation(TrustedCert, CertPath, Options) of
{ok, {PublicKeyInfo,_}} ->
{PeerCert, PublicKeyInfo};
{error, Reason} ->
- path_validation_alert(Reason)
+ handle_path_validation_error(Reason, PeerCert, ChainCerts, Opts, Options,
+ CertDbHandle, CertDbRef)
end
catch
error:{badmatch,{asn1, Asn1Reason}} ->
@@ -363,7 +363,6 @@ certify(#certificate{asn1_certificates = ASN1Certs}, CertDbHandle, CertDbRef,
error:OtherReason ->
?ALERT_REC(?FATAL, ?INTERNAL_ERROR, {unexpected_error, OtherReason})
end.
-
%%--------------------------------------------------------------------
-spec certificate_verify(binary(), public_key_info(), ssl_record:ssl_version(), term(),
binary(), ssl_handshake_history()) -> valid | #alert{}.
@@ -1312,6 +1311,45 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState, _CertPath)
{unknown, {SslState, UserState}}
end.
+handle_path_validation_error({bad_cert, unknown_ca} = Reason, PeerCert, Chain,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ handle_incomplete_chain(PeerCert, Chain, Opts, Options, CertDbHandle, CertsDbRef, Reason);
+handle_path_validation_error({bad_cert, invalid_issuer} = Reason, PeerCert, Chain0,
+ Opts, Options, CertDbHandle, CertsDbRef) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef, Chain0) of
+ {ok, _, [PeerCert | Chain] = OrdedChain} when Chain =/= Chain0 -> %% Chain appaears to be unorded
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(OrdedChain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ handle_path_validation_error(PathError, PeerCert, Path,
+ Opts, Options, CertDbHandle, CertsDbRef)
+ end;
+ _ ->
+ path_validation_alert(Reason)
+ end;
+handle_path_validation_error(Reason, _, _, _, _,_, _) ->
+ path_validation_alert(Reason).
+
+handle_incomplete_chain(PeerCert, Chain0, Opts, Options, CertDbHandle, CertsDbRef, PathError0) ->
+ case ssl_certificate:certificate_chain(PeerCert, CertDbHandle, CertsDbRef) of
+ {ok, _, [PeerCert | _] = Chain} when Chain =/= Chain0 -> %% Chain candidate found
+ {Trusted, Path} = ssl_certificate:trusted_cert_and_path(Chain,
+ CertDbHandle, CertsDbRef,
+ Opts#ssl_options.partial_chain),
+ case public_key:pkix_path_validation(Trusted, Path, Options) of
+ {ok, {PublicKeyInfo,_}} ->
+ {PeerCert, PublicKeyInfo};
+ {error, PathError} ->
+ path_validation_alert(PathError)
+ end;
+ _ ->
+ path_validation_alert(PathError0)
+ end.
+
path_validation_alert({bad_cert, cert_expired}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_EXPIRED);
path_validation_alert({bad_cert, invalid_issuer}) ->
@@ -1324,8 +1362,6 @@ 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, Details}}) ->
Alert = ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE),
Alert#alert{reason = Details};
diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
index 63e9d07d0b..b387feb97a 100644
--- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl
+++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl
@@ -88,7 +88,8 @@ tests() ->
critical_extension_verify_client,
critical_extension_verify_server,
critical_extension_verify_none,
- customize_hostname_check
+ customize_hostname_check,
+ incomplete_chain
].
error_handling_tests()->
@@ -1198,6 +1199,39 @@ customize_hostname_check(Config) when is_list(Config) ->
ssl_test_lib:close(Server),
ssl_test_lib:close(Client).
+incomplete_chain() ->
+ [{doc,"Test option verify_peer"}].
+incomplete_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := ClientConf} = public_key:pkix_test_data(CertChainConf),
+ [ServerRoot| _] = ServerCas = proplists:get_value(cacerts, ServerConf),
+ ClientCas = proplists:get_value(cacerts, ClientConf),
+
+ Active = proplists:get_value(active, Config),
+ ReceiveFunction = proplists:get_value(receive_function, Config),
+ {ClientNode, ServerNode, Hostname} = ssl_test_lib:run_where(Config),
+ Server = ssl_test_lib:start_server([{node, ServerNode}, {port, 0},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active}, {verify, verify_peer},
+ {cacerts, [ServerRoot]} |
+ proplists:delete(cacerts, ServerConf)]}]),
+ Port = ssl_test_lib:inet_port(Server),
+ Client = ssl_test_lib:start_client([{node, ClientNode}, {port, Port},
+ {host, Hostname},
+ {from, self()},
+ {mfa, {ssl_test_lib, ReceiveFunction, []}},
+ {options, [{active, Active},
+ {verify, verify_peer},
+ {cacerts, ServerCas ++ ClientCas} |
+ proplists:delete(cacerts, ClientConf)]}]),
+ ssl_test_lib:check_result(Server, ok, Client, ok),
+ ssl_test_lib:close(Server),
+ ssl_test_lib:close(Client).
+
+
%%--------------------------------------------------------------------
%% Internal functions ------------------------------------------------
%%--------------------------------------------------------------------
diff --git a/lib/ssl/test/ssl_handshake_SUITE.erl b/lib/ssl/test/ssl_handshake_SUITE.erl
index 9ae04184e2..b8b9989d30 100644
--- a/lib/ssl/test/ssl_handshake_SUITE.erl
+++ b/lib/ssl/test/ssl_handshake_SUITE.erl
@@ -40,7 +40,8 @@ all() -> [decode_hello_handshake,
decode_single_hello_sni_extension_correctly,
decode_empty_server_sni_correctly,
select_proper_tls_1_2_rsa_default_hashsign,
- ignore_hassign_extension_pre_tls_1_2].
+ ignore_hassign_extension_pre_tls_1_2,
+ unorded_chain].
%%--------------------------------------------------------------------
init_per_suite(Config) ->
@@ -173,6 +174,29 @@ ignore_hassign_extension_pre_tls_1_2(Config) ->
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,2}), {3,2}),
{md5sha, rsa} = ssl_handshake:select_hashsign(HashSigns, Cert, ecdhe_rsa, tls_v1:default_signature_algs({3,0}), {3,0}).
+unorded_chain(Config) when is_list(Config) ->
+ DefConf = ssl_test_lib:default_cert_chain_conf(),
+ CertChainConf = ssl_test_lib:gen_conf(rsa, rsa, DefConf, DefConf),
+ #{server_config := ServerConf,
+ client_config := _ClientConf} = public_key:pkix_test_data(CertChainConf),
+ PeerCert = proplists:get_value(cert, ServerConf),
+ CaCerts = [_, C1, C2] = proplists:get_value(cacerts, ServerConf),
+ {ok, ExtractedCerts} = ssl_pkix_db:extract_trusted_certs({der, CaCerts}),
+ UnordedChain = case public_key:pkix_is_self_signed(C1) of
+ true ->
+ [C1, C2];
+ false ->
+ [C2, C1]
+ end,
+ OrderedChain = [PeerCert | lists:reverse(UnordedChain)],
+ {ok, _, OrderedChain} =
+ ssl_certificate:certificate_chain(PeerCert, ets:new(foo, []), ExtractedCerts, UnordedChain).
+
+
+%%--------------------------------------------------------------------
+%% Internal functions ------------------------------------------------
+%%--------------------------------------------------------------------
+
is_supported(Hash) ->
Algos = crypto:supports(),
Hashs = proplists:get_value(hashs, Algos),
diff --git a/lib/syntax_tools/src/erl_syntax.erl b/lib/syntax_tools/src/erl_syntax.erl
index 758aff32fd..331081a07e 100644
--- a/lib/syntax_tools/src/erl_syntax.erl
+++ b/lib/syntax_tools/src/erl_syntax.erl
@@ -3897,7 +3897,7 @@ unfold_try_clauses(Cs) ->
unfold_try_clause({clause, Pos, [{tuple, _, [{atom, _, throw},
V,
- [{var, _, '_'}]]}],
+ {var, _, '_'}]}],
Guard, Body}) ->
{clause, Pos, [V], Guard, Body};
unfold_try_clause({clause, Pos, [{tuple, _, [C, V, Stacktrace]}],
diff --git a/lib/syntax_tools/test/merl_SUITE.erl b/lib/syntax_tools/test/merl_SUITE.erl
index 52bbd9b3b8..6389ad7738 100644
--- a/lib/syntax_tools/test/merl_SUITE.erl
+++ b/lib/syntax_tools/test/merl_SUITE.erl
@@ -30,13 +30,14 @@
%% Test cases
-export([merl_smoke_test/1,
- transform_parse_error_test/1]).
+ transform_parse_error_test/1, otp_15291/1]).
suite() -> [{ct_hooks,[ts_install_cth]}].
all() ->
[merl_smoke_test,
- transform_parse_error_test].
+ transform_parse_error_test,
+ otp_15291].
groups() ->
[].
@@ -101,6 +102,15 @@ transform_parse_error_test(_Config) ->
[?Q("merl:qquote(2, \"{\", [{var, V}])")], []))),
ok.
+otp_15291(_Config) ->
+ C0 = merl:quote("() -> ok"),
+ {clause,1,[],[],[{atom,1,ok}]} = C0,
+ C2 = merl:quote("(_,_) -> ok"),
+ {clause,1,[{var,1,'_'},{var,1,'_'}],[],[{atom,1,ok}]} = C2,
+ C1 = merl:quote("(_) -> ok"),
+ {clause,1,[{var,1,'_'}],[],[{atom,1,ok}]} = C1,
+ ok.
+
%% utilities
f(Ts) when is_list(Ts) ->
diff --git a/otp_versions.table b/otp_versions.table
index c33bb63002..7e2e20e8be 100644
--- a/otp_versions.table
+++ b/otp_versions.table
@@ -1,3 +1,4 @@
+OTP-21.0.9 : compiler-7.2.4 erts-10.0.8 # asn1-5.0.6 common_test-1.16 crypto-4.3.2 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 inets-7.0.1 jinterface-1.9 kernel-6.0.1 megaco-3.18.3 mnesia-4.15.4 observer-2.8 odbc-2.12.1 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 public_key-1.6.1 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 snmp-5.2.11 ssh-4.7 ssl-9.0.1 stdlib-3.5.1 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 :
OTP-21.0.8 : erts-10.0.7 kernel-6.0.1 # asn1-5.0.6 common_test-1.16 compiler-7.2.3 crypto-4.3.2 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 inets-7.0.1 jinterface-1.9 megaco-3.18.3 mnesia-4.15.4 observer-2.8 odbc-2.12.1 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 public_key-1.6.1 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 snmp-5.2.11 ssh-4.7 ssl-9.0.1 stdlib-3.5.1 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 :
OTP-21.0.7 : erts-10.0.6 # asn1-5.0.6 common_test-1.16 compiler-7.2.3 crypto-4.3.2 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 inets-7.0.1 jinterface-1.9 kernel-6.0 megaco-3.18.3 mnesia-4.15.4 observer-2.8 odbc-2.12.1 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 public_key-1.6.1 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 snmp-5.2.11 ssh-4.7 ssl-9.0.1 stdlib-3.5.1 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 :
OTP-21.0.6 : crypto-4.3.2 inets-7.0.1 ssl-9.0.1 # asn1-5.0.6 common_test-1.16 compiler-7.2.3 debugger-4.2.5 dialyzer-3.3 diameter-2.1.5 edoc-0.9.3 eldap-1.2.4 erl_docgen-0.8 erl_interface-3.10.3 erts-10.0.5 et-1.6.2 eunit-2.3.6 ftp-1.0 hipe-3.18 jinterface-1.9 kernel-6.0 megaco-3.18.3 mnesia-4.15.4 observer-2.8 odbc-2.12.1 os_mon-2.4.5 otp_mibs-1.2 parsetools-2.1.7 public_key-1.6.1 reltool-0.7.6 runtime_tools-1.13 sasl-3.2 snmp-5.2.11 ssh-4.7 stdlib-3.5.1 syntax_tools-2.1.5 tftp-1.0 tools-3.0 wx-1.8.4 xmerl-1.3.17 :