aboutsummaryrefslogtreecommitdiffstats
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/edoc/src/edoc.erl2
-rw-r--r--lib/edoc/src/edoc_run.erl2
-rw-r--r--lib/hipe/icode/hipe_icode_type.erl2
-rw-r--r--lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java5
-rw-r--r--lib/mnesia/src/mnesia_controller.erl2
-rw-r--r--lib/mnesia/src/mnesia_locker.erl2
-rw-r--r--lib/mnesia/src/mnesia_log.erl2
-rw-r--r--lib/mnesia/src/mnesia_monitor.erl2
-rw-r--r--lib/mnesia/src/mnesia_recover.erl1
-rw-r--r--lib/mnesia/src/mnesia_subscr.erl2
-rw-r--r--lib/observer/src/Makefile3
-rw-r--r--lib/public_key/asn1/OTP-PKIX.asn113
-rw-r--r--lib/public_key/src/pubkey_cert.erl25
-rw-r--r--lib/public_key/src/public_key.appup.src44
-rw-r--r--lib/public_key/src/public_key.erl9
-rw-r--r--lib/public_key/test/erl_make_certs.erl6
-rw-r--r--lib/public_key/test/public_key_SUITE.erl6
-rw-r--r--lib/public_key/vsn.mk2
-rw-r--r--lib/ssl/doc/src/ssl.xml13
-rw-r--r--lib/ssl/src/ssl.appup.src27
-rw-r--r--lib/ssl/src/ssl.erl190
-rw-r--r--lib/ssl/src/ssl_certificate.erl21
-rw-r--r--lib/ssl/src/ssl_certificate_db.erl18
-rw-r--r--lib/ssl/src/ssl_connection.erl2
-rw-r--r--lib/ssl/src/ssl_handshake.erl139
-rw-r--r--lib/ssl/src/ssl_manager.erl2
-rw-r--r--lib/ssl/src/ssl_record.erl97
-rw-r--r--lib/ssl/test/erl_make_certs.erl4
-rw-r--r--lib/ssl/vsn.mk3
-rw-r--r--lib/stdlib/doc/src/supervisor.xml2
-rw-r--r--lib/syntax_tools/src/epp_dodger.erl2
31 files changed, 351 insertions, 299 deletions
diff --git a/lib/edoc/src/edoc.erl b/lib/edoc/src/edoc.erl
index ec452a5929..75b3bb451a 100644
--- a/lib/edoc/src/edoc.erl
+++ b/lib/edoc/src/edoc.erl
@@ -58,6 +58,8 @@
read_comments/1, read_comments/2,
read_source/1, read_source/2]).
+-compile({no_auto_import,[error/1]}).
+
-import(edoc_report, [report/2, report/3, error/1, error/3]).
-include("edoc.hrl").
diff --git a/lib/edoc/src/edoc_run.erl b/lib/edoc/src/edoc_run.erl
index 37025d6621..96e5ea4631 100644
--- a/lib/edoc/src/edoc_run.erl
+++ b/lib/edoc/src/edoc_run.erl
@@ -42,6 +42,8 @@
-export([file/1, application/1, packages/1, files/1, toc/1]).
+-compile({no_auto_import,[error/1]}).
+
-import(edoc_report, [report/2, error/1]).
diff --git a/lib/hipe/icode/hipe_icode_type.erl b/lib/hipe/icode/hipe_icode_type.erl
index 28198467f7..6726d62b53 100644
--- a/lib/hipe/icode/hipe_icode_type.erl
+++ b/lib/hipe/icode/hipe_icode_type.erl
@@ -39,6 +39,8 @@
update__info/2, new__info/1, return__info/1,
return_none/0, return_none_args/2, return_any_args/2]).
+-compile({no_auto_import,[min/2,max/2]}).
+
%%=====================================================================
-include("../main/hipe.hrl").
diff --git a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
index 4146bd3ced..a9712aa2ba 100644
--- a/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
+++ b/lib/jinterface/java_src/com/ericsson/otp/erlang/OtpMbox.java
@@ -678,6 +678,11 @@ public class OtpMbox {
return m.self.equals(self);
}
+ @Override
+ public int hashCode() {
+ return self.hashCode();
+ }
+
/*
* called by OtpNode to deliver message to this mailbox.
*
diff --git a/lib/mnesia/src/mnesia_controller.erl b/lib/mnesia/src/mnesia_controller.erl
index 0298b382a6..021be8af2a 100644
--- a/lib/mnesia/src/mnesia_controller.erl
+++ b/lib/mnesia/src/mnesia_controller.erl
@@ -98,6 +98,8 @@
connect_nodes2/3
]).
+-compile({no_auto_import,[error/2]}).
+
-import(mnesia_lib, [set/2, add/2]).
-import(mnesia_lib, [fatal/2, error/2, verbose/2, dbg_out/2]).
diff --git a/lib/mnesia/src/mnesia_locker.erl b/lib/mnesia/src/mnesia_locker.erl
index cfa3f171b2..6b5770d91e 100644
--- a/lib/mnesia/src/mnesia_locker.erl
+++ b/lib/mnesia/src/mnesia_locker.erl
@@ -49,6 +49,8 @@
system_code_change/4
]).
+-compile({no_auto_import,[error/2]}).
+
-include("mnesia.hrl").
-import(mnesia_lib, [dbg_out/2, error/2, verbose/2]).
diff --git a/lib/mnesia/src/mnesia_log.erl b/lib/mnesia/src/mnesia_log.erl
index 00ec4740ee..11b792026e 100644
--- a/lib/mnesia/src/mnesia_log.erl
+++ b/lib/mnesia/src/mnesia_log.erl
@@ -182,6 +182,8 @@
]).
+-compile({no_auto_import,[error/2]}).
+
-include("mnesia.hrl").
-import(mnesia_lib, [val/1, dir/1]).
-import(mnesia_lib, [exists/1, fatal/2, error/2, dbg_out/2]).
diff --git a/lib/mnesia/src/mnesia_monitor.erl b/lib/mnesia/src/mnesia_monitor.erl
index 5bd93d6b9b..b6eda9ad3a 100644
--- a/lib/mnesia/src/mnesia_monitor.erl
+++ b/lib/mnesia/src/mnesia_monitor.erl
@@ -70,6 +70,8 @@
negotiate_protocol_impl/2
]).
+-compile({no_auto_import,[error/2]}).
+
-import(mnesia_lib, [dbg_out/2, verbose/2, error/2, fatal/2, set/2]).
-include("mnesia.hrl").
diff --git a/lib/mnesia/src/mnesia_recover.erl b/lib/mnesia/src/mnesia_recover.erl
index 0ca7bf3f7f..7435b6896a 100644
--- a/lib/mnesia/src/mnesia_recover.erl
+++ b/lib/mnesia/src/mnesia_recover.erl
@@ -62,6 +62,7 @@
code_change/3
]).
+-compile({no_auto_import,[error/2]}).
-include("mnesia.hrl").
-import(mnesia_lib, [set/2, verbose/2, error/2, fatal/2]).
diff --git a/lib/mnesia/src/mnesia_subscr.erl b/lib/mnesia/src/mnesia_subscr.erl
index 93d4a86f7f..415c69d508 100644
--- a/lib/mnesia/src/mnesia_subscr.erl
+++ b/lib/mnesia/src/mnesia_subscr.erl
@@ -43,6 +43,8 @@
code_change/3
]).
+-compile({no_auto_import,[error/2]}).
+
-include("mnesia.hrl").
-import(mnesia_lib, [error/2]).
diff --git a/lib/observer/src/Makefile b/lib/observer/src/Makefile
index dde1ea17be..b4eb518dd7 100644
--- a/lib/observer/src/Makefile
+++ b/lib/observer/src/Makefile
@@ -111,7 +111,8 @@ release_spec: opt
$(INSTALL_DIR) $(RELSYSDIR)/src
$(INSTALL_DATA) $(ERL_FILES) $(RELSYSDIR)/src
$(INSTALL_DATA) $(INTERNAL_HRL_FILES) $(RELSYSDIR)/src
- $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/src
+ $(INSTALL_DIR) $(RELSYSDIR)/examples
+ $(INSTALL_DATA) $(EXAMPLE_FILES) $(RELSYSDIR)/examples
$(INSTALL_DIR) $(RELSYSDIR)/include
$(INSTALL_DATA) $(HRL_FILES) $(RELSYSDIR)/include
$(INSTALL_DIR) $(RELSYSDIR)/ebin
diff --git a/lib/public_key/asn1/OTP-PKIX.asn1 b/lib/public_key/asn1/OTP-PKIX.asn1
index c0cf440496..ad704191a9 100644
--- a/lib/public_key/asn1/OTP-PKIX.asn1
+++ b/lib/public_key/asn1/OTP-PKIX.asn1
@@ -302,18 +302,25 @@ SupportedPublicKeyAlgorithms PUBLIC-KEY-ALGORITHM-CLASS ::= {
-- DSA Keys and Signatures
+
+ DSAParams ::= CHOICE
+ {
+ params Dss-Parms,
+ null NULL
+ }
+
-- SubjectPublicKeyInfo:
dsa PUBLIC-KEY-ALGORITHM-CLASS ::= {
ID id-dsa
- TYPE Dss-Parms -- XXX Must be OPTIONAL
+ TYPE DSAParams -- XXX Must be OPTIONAL
PUBLIC-KEY-TYPE DSAPublicKey }
-- Certificate.signatureAlgorithm
dsa-with-sha1 SIGNATURE-ALGORITHM-CLASS ::= {
- ID id-dsa-with-sha1
- TYPE Dss-Parms }
+ ID id-dsa-with-sha1
+ TYPE DSAParams }
--
-- RSA Keys and Signatures
diff --git a/lib/public_key/src/pubkey_cert.erl b/lib/public_key/src/pubkey_cert.erl
index e704c168f1..ac59b6313d 100644
--- a/lib/public_key/src/pubkey_cert.erl
+++ b/lib/public_key/src/pubkey_cert.erl
@@ -223,10 +223,15 @@ validate_revoked_status(_OtpCert, UserState, _VerifyFun) ->
%%--------------------------------------------------------------------
validate_extensions(OtpCert, ValidationState, UserState, VerifyFun) ->
TBSCert = OtpCert#'OTPCertificate'.tbsCertificate,
- Extensions = TBSCert#'OTPTBSCertificate'.extensions,
- validate_extensions(OtpCert, Extensions, ValidationState, no_basic_constraint,
- is_self_signed(OtpCert), UserState, VerifyFun).
-
+ case TBSCert#'OTPTBSCertificate'.version of
+ N when N >= 3 ->
+ Extensions = TBSCert#'OTPTBSCertificate'.extensions,
+ validate_extensions(OtpCert, Extensions,
+ ValidationState, no_basic_constraint,
+ is_self_signed(OtpCert), UserState, VerifyFun);
+ _ -> %% Extensions not present in versions 1 & 2
+ {ValidationState, UserState}
+ end.
%%--------------------------------------------------------------------
-spec normalize_general_name({rdnSequence, term()}) -> {rdnSequence, term()}.
%%
@@ -290,7 +295,7 @@ is_fixed_dh_cert(#'OTPCertificate'{tbsCertificate =
%%--------------------------------------------------------------------
--spec verify_fun(#'OTPTBSCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}|
+-spec verify_fun(#'OTPCertificate'{}, {bad_cert, atom()} | {extension, #'Extension'{}}|
valid, term(), fun()) -> term().
%%
%% Description: Gives the user application the opportunity handle path
@@ -313,7 +318,7 @@ verify_fun(Otpcert, Result, UserState0, VerifyFun) ->
{extension, #'Extension'{critical = true}} ->
throw({bad_cert, unknown_critical_extension});
_ ->
- UserState
+ UserState
end
end.
@@ -389,10 +394,12 @@ public_key_info(PublicKeyInfo,
NewPublicKeyParams =
case PublicKeyParams of
- 'NULL' when WorkingAlgorithm == Algorithm ->
+ {null, 'NULL'} when WorkingAlgorithm == Algorithm ->
WorkingParams;
- _ ->
- PublicKeyParams
+ {params, Params} ->
+ Params;
+ Params ->
+ Params
end,
{Algorithm, PublicKey, NewPublicKeyParams}.
diff --git a/lib/public_key/src/public_key.appup.src b/lib/public_key/src/public_key.appup.src
index c9d15b8747..adc50d1d45 100644
--- a/lib/public_key/src/public_key.appup.src
+++ b/lib/public_key/src/public_key.appup.src
@@ -1,7 +1,7 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"0.7",
+ {"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
{update, public_key, soft, soft_purge, soft_purge, []},
@@ -9,29 +9,10 @@
{update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
{update, pubkey_cert, soft, soft_purge, soft_purge, []}
]
- },
- {"0.6",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.5",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_crypto, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
}
],
[
- {"0.7",
+ {"0.8",
[
{update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
{update, public_key, soft, soft_purge, soft_purge, []},
@@ -39,24 +20,5 @@
{update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
{update, pubkey_cert, soft, soft_purge, soft_purge, []}
]
- },
- {"0.6",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []}
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- },
- {"0.5",
- [
- {update, 'OTP-PUB-KEY', soft, soft_purge, soft_purge, []},
- {update, public_key, soft, soft_purge, soft_purge, []},
- {update, pubkey_crypto, soft, soft_purge, soft_purge, []},
- {update, pubkey_pem, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert_records, soft, soft_purge, soft_purge, []},
- {update, pubkey_cert, soft, soft_purge, soft_purge, []}
- ]
- }
+ }
]}.
diff --git a/lib/public_key/src/public_key.erl b/lib/public_key/src/public_key.erl
index 9c7817fa8e..aa3018bd2d 100644
--- a/lib/public_key/src/public_key.erl
+++ b/lib/public_key/src/public_key.erl
@@ -437,7 +437,7 @@ pkix_normalize_name(Issuer) ->
pubkey_cert:normalize_general_name(Issuer).
%%--------------------------------------------------------------------
--spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | unknown_ca,
+-spec pkix_path_validation(der_encoded()| #'OTPCertificate'{} | atom(),
CertChain :: [der_encoded()] ,
Options :: list()) ->
{ok, {PublicKeyInfo :: term(),
@@ -445,11 +445,11 @@ pkix_normalize_name(Issuer) ->
{error, {bad_cert, Reason :: term()}}.
%% Description: Performs a basic path validation according to RFC 5280.
%%--------------------------------------------------------------------
-pkix_path_validation(unknown_ca, [Cert | Chain], Options0) ->
+pkix_path_validation(PathErr, [Cert | Chain], Options0) when is_atom(PathErr)->
{VerifyFun, Userstat0} =
proplists:get_value(verify_fun, Options0, ?DEFAULT_VERIFYFUN),
Otpcert = pkix_decode_cert(Cert, otp),
- Reason = {bad_cert, unknown_ca},
+ Reason = {bad_cert, PathErr},
try VerifyFun(Otpcert, Reason, Userstat0) of
{valid, Userstate} ->
Options = proplists:delete(verify_fun, Options0),
@@ -528,7 +528,6 @@ path_validation([DerCert | _] = Path,
{error, Reason}
end.
-
validate(DerCert, #path_validation_state{working_issuer_name = Issuer,
working_public_key = Key,
working_public_key_parameters =
@@ -576,7 +575,7 @@ sized_binary(List) ->
%%--------------------------------------------------------------------
pem_to_der(CertSource) ->
{ok, Bin} = file:read_file(CertSource),
- pubkey_pem:decode(Bin).
+ {ok, pubkey_pem:decode(Bin)}.
decode_private_key(KeyInfo) ->
decode_private_key(KeyInfo, no_passwd).
diff --git a/lib/public_key/test/erl_make_certs.erl b/lib/public_key/test/erl_make_certs.erl
index e31e5552d3..8b01ca3ad4 100644
--- a/lib/public_key/test/erl_make_certs.erl
+++ b/lib/public_key/test/erl_make_certs.erl
@@ -66,7 +66,7 @@ make_cert(Opts) ->
%% @end
%%--------------------------------------------------------------------
write_pem(Dir, FileName, {Cert, Key = {_,_,not_encrypted}}) when is_binary(Cert) ->
- ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
+ ok = der_to_pem(filename:join(Dir, FileName ++ ".pem"),
[{'Certificate', Cert, not_encrypted}]),
ok = der_to_pem(filename:join(Dir, FileName ++ "_key.pem"), [Key]).
@@ -268,7 +268,7 @@ publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
subjectPublicKey = Public};
publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters=#'Dss-Parms'{p=P, q=Q, g=G}},
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
#'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
validity(Opts) ->
@@ -290,7 +290,7 @@ sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
end,
{Type, 'NULL'};
sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', #'Dss-Parms'{p=P, q=Q, g=G}}.
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
make_key(rsa, _Opts) ->
%% (OBS: for testing only)
diff --git a/lib/public_key/test/public_key_SUITE.erl b/lib/public_key/test/public_key_SUITE.erl
index ea6a925139..829b6a9215 100644
--- a/lib/public_key/test/public_key_SUITE.erl
+++ b/lib/public_key/test/public_key_SUITE.erl
@@ -411,11 +411,11 @@ deprecated(suite) ->
[];
deprecated(Config) when is_list(Config) ->
Datadir = ?config(data_dir, Config),
- [DsaKey = {'DSAPrivateKey', _DsaKey, _}] =
+ {ok, [DsaKey = {'DSAPrivateKey', _DsaKey, _}]} =
public_key:pem_to_der(filename:join(Datadir, "dsa.pem")),
- [RsaKey = {'RSAPrivateKey', _RsaKey,_}] =
+ {ok, [RsaKey = {'RSAPrivateKey', _RsaKey,_}]} =
public_key:pem_to_der(filename:join(Datadir, "client_key.pem")),
- [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}] =
+ {ok, [ProtectedRsaKey = {'RSAPrivateKey', _ProtectedRsaKey,_}]} =
public_key:pem_to_der(filename:join(Datadir, "rsa.pem")),
{ok, #'DSAPrivateKey'{}} = public_key:decode_private_key(DsaKey),
diff --git a/lib/public_key/vsn.mk b/lib/public_key/vsn.mk
index f70209d891..2810942171 100644
--- a/lib/public_key/vsn.mk
+++ b/lib/public_key/vsn.mk
@@ -1 +1 @@
-PUBLIC_KEY_VSN = 0.8
+PUBLIC_KEY_VSN = 0.9
diff --git a/lib/ssl/doc/src/ssl.xml b/lib/ssl/doc/src/ssl.xml
index d5b7253ef3..8348301aed 100644
--- a/lib/ssl/doc/src/ssl.xml
+++ b/lib/ssl/doc/src/ssl.xml
@@ -244,10 +244,8 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<p>The default verify_fun option in verify_none mode:</p>
<code>
-{fun(_,{bad_cert, unknown_ca}, UserState) ->
+{fun(_,{bad_cert, _}, UserState) ->
{valid, UserState};
- (_,{bad_cert, _} = Reason, _) ->
- {fail, Reason};
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
@@ -267,13 +265,14 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<section>
<title>SSL OPTION DESCRIPTIONS - CLIENT SIDE</title>
- <p>Option described here are client specific or has a slightly different
+ <p>Options described here are client specific or has a slightly different
meaning in the client than in the server.</p>
<taglist>
<tag>{verify, verify_type()}</tag>
- <item> In verify_none mode the x509-path validation error {bad_cert, unknown_ca}
- will automatically be accepted. See also the verify_fun option.
+ <item> In verify_none mode the default behavior will be to
+ allow all x509-path validation errors. See also the verify_fun
+ option.
</item>
<tag>{reuse_sessions, boolean()}</tag>
<item>Specifies if client should try to reuse sessions
@@ -286,7 +285,7 @@ fun(OtpCert :: #'OtpCertificate'{}, Event :: {bad_cert, Reason :: atom()} |
<section>
<title>SSL OPTION DESCRIPTIONS - SERVER SIDE</title>
- <p>Option described here are server specific or has a slightly different
+ <p>Options described here are server specific or has a slightly different
meaning in the server than in the client.</p>
<taglist>
diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src
index 88cd73be74..f4e6b59b6d 100644
--- a/lib/ssl/src/ssl.appup.src
+++ b/lib/ssl/src/ssl.appup.src
@@ -1,32 +1,9 @@
%% -*- erlang -*-
{"%VSN%",
[
- {"4.0", [{restart_application, ssl}]},
- {"3.11.1", [{restart_application, ssl}]},
- {"3.11", [{restart_application, ssl}]},
- {"3.10", [{restart_application, ssl}]},
- {"3.10.1", [{restart_application, ssl}]},
- {"3.10.2", [{restart_application, ssl}]},
- {"3.10.3", [{restart_application, ssl}]},
- {"3.10.4", [{restart_application, ssl}]},
- {"3.10.5", [{restart_application, ssl}]},
- {"3.10.6", [{restart_application, ssl}]},
- {"3.10.7", [{restart_application, ssl}]},
- {"3.10.8", [{restart_application, ssl}]},
- {"3.10.9", [{restart_application, ssl}]}
+ {"4.0.1", [{restart_application, ssl}]}
],
[
- {"4.0", [{restart_application, ssl}]},
- {"3.11.1", [{restart_application, ssl}]},
- {"3.11", [{restart_application, ssl}]},
- {"3.10", [{restart_application, ssl}]},
- {"3.10.1", [{restart_application, ssl}]},
- {"3.10.2", [{restart_application, ssl}]},
- {"3.10.3", [{restart_application, ssl}]},
- {"3.10.4", [{restart_application, ssl}]},
- {"3.10.5", [{restart_application, ssl}]},
- {"3.10.6", [{restart_application, ssl}]},
- {"3.10.8", [{restart_application, ssl}]},
- {"3.10.9", [{restart_application, ssl}]}
+ {"4.0.1", [{restart_application, ssl}]}
]}.
diff --git a/lib/ssl/src/ssl.erl b/lib/ssl/src/ssl.erl
index 12dffb413c..c13dee96f1 100644
--- a/lib/ssl/src/ssl.erl
+++ b/lib/ssl/src/ssl.erl
@@ -190,7 +190,8 @@ transport_accept(#sslsocket{} = ListenSocket, Timeout) ->
%%--------------------------------------------------------------------
-spec ssl_accept(#sslsocket{}) -> {ok, #sslsocket{}} | {error, reason()}.
--spec ssl_accept(#sslsocket{}, timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec ssl_accept(#sslsocket{}, list() | timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
+-spec ssl_accept(port(), list(), timeout()) -> {ok, #sslsocket{}} | {error, reason()}.
%%
%% Description: Performs accept on a ssl listen socket. e.i. performs
%% ssl handshake.
@@ -463,11 +464,102 @@ versions() ->
%%---------------------------------------------------------------
-spec renegotiate(#sslsocket{}) -> ok | {error, reason()}.
%%
-%% Description:
+%% Description: Initiates a renegotiation.
%%--------------------------------------------------------------------
renegotiate(#sslsocket{pid = Pid, fd = new_ssl}) ->
ssl_connection:renegotiation(Pid).
+%%---------------------------------------------------------------
+-spec format_error({error, term()}) -> list().
+%%
+%% Description: Creates error string.
+%%--------------------------------------------------------------------
+format_error({error, Reason}) ->
+ format_error(Reason);
+format_error(Reason) when is_list(Reason) ->
+ Reason;
+format_error(closed) ->
+ "The connection is closed";
+format_error(ecacertfile) ->
+ "Own CA certificate file is invalid.";
+format_error(ecertfile) ->
+ "Own certificate file is invalid.";
+format_error(ekeyfile) ->
+ "Own private key file is invalid.";
+format_error(esslaccept) ->
+ "Server SSL handshake procedure between client and server failed.";
+format_error(esslconnect) ->
+ "Client SSL handshake procedure between client and server failed.";
+format_error({eoptions, Options}) ->
+ lists:flatten(io_lib:format("Error in options list: ~p~n", [Options]));
+
+%%%%%%%%%%%% START OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+format_error(ebadsocket) ->
+ "Connection not found (internal error).";
+format_error(ebadstate) ->
+ "Connection not in connect state (internal error).";
+format_error(ebrokertype) ->
+ "Wrong broker type (internal error).";
+format_error(echaintoolong) ->
+ "The chain of certificates provided by peer is too long.";
+format_error(ecipher) ->
+ "Own list of specified ciphers is invalid.";
+format_error(ekeymismatch) ->
+ "Own private key does not match own certificate.";
+format_error(enoissuercert) ->
+ "Cannot find certificate of issuer of certificate provided by peer.";
+format_error(enoservercert) ->
+ "Attempt to do accept without having set own certificate.";
+format_error(enotlistener) ->
+ "Attempt to accept on a non-listening socket.";
+format_error(enoproxysocket) ->
+ "No proxy socket found (internal error or max number of file "
+ "descriptors exceeded).";
+format_error(enooptions) ->
+ "List of options is empty.";
+format_error(enotstarted) ->
+ "The SSL application has not been started.";
+format_error(eoptions) ->
+ "Invalid list of options.";
+format_error(epeercert) ->
+ "Certificate provided by peer is in error.";
+format_error(epeercertexpired) ->
+ "Certificate provided by peer has expired.";
+format_error(epeercertinvalid) ->
+ "Certificate provided by peer is invalid.";
+format_error(eselfsignedcert) ->
+ "Certificate provided by peer is self signed.";
+format_error(esslerrssl) ->
+ "SSL protocol failure. Typically because of a fatal alert from peer.";
+format_error(ewantconnect) ->
+ "Protocol wants to connect, which is not supported in this "
+ "version of the SSL application.";
+format_error(ex509lookup) ->
+ "Protocol wants X.509 lookup, which is not supported in this "
+ "version of the SSL application.";
+format_error({badcall, _Call}) ->
+ "Call not recognized for current mode (active or passive) and state "
+ "of socket.";
+format_error({badcast, _Cast}) ->
+ "Call not recognized for current mode (active or passive) and state "
+ "of socket.";
+
+format_error({badinfo, _Info}) ->
+ "Call not recognized for current mode (active or passive) and state "
+ "of socket.";
+
+%%%%%%%%%%%%%%%%%% END OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+format_error(Error) ->
+ case (catch inet:format_error(Error)) of
+ "unkknown POSIX" ++ _ ->
+ no_format(Error);
+ {'EXIT', _} ->
+ no_format(Error);
+ Other ->
+ Other
+ end.
+
%%%--------------------------------------------------------------
%%% Internal functions
%%%--------------------------------------------------------------------
@@ -529,17 +621,17 @@ handle_options(Opts0, _Role) ->
ReuseSessionFun = fun(_, _, _, _) -> true end,
- VerifyNoneFun =
- {fun(_,{bad_cert, unknown_ca}, UserState) ->
+ DefaultVerifyNoneFun =
+ {fun(_,{bad_cert, _}, UserState) ->
{valid, UserState};
- (_,{bad_cert, _} = Reason, _) ->
- {fail, Reason};
(_,{extension, _}, UserState) ->
{unknown, UserState};
(_, valid, UserState) ->
{valid, UserState}
end, []},
+ VerifyNoneFun = handle_option(verify_fun, Opts, DefaultVerifyNoneFun),
+
UserFailIfNoPeerCert = handle_option(fail_if_no_peer_cert, Opts, false),
UserVerifyFun = handle_option(verify_fun, Opts, undefined),
CaCerts = handle_option(cacerts, Opts, undefined),
@@ -810,92 +902,6 @@ cipher_suites(Version, Ciphers0) ->
Ciphers = [ssl_cipher:openssl_suite(C) || C <- string:tokens(Ciphers0, ":")],
cipher_suites(Version, Ciphers).
-format_error({error, Reason}) ->
- format_error(Reason);
-format_error(Reason) when is_list(Reason) ->
- Reason;
-format_error(closed) ->
- "The connection is closed";
-format_error(ecacertfile) ->
- "Own CA certificate file is invalid.";
-format_error(ecertfile) ->
- "Own certificate file is invalid.";
-format_error(ekeyfile) ->
- "Own private key file is invalid.";
-format_error(esslaccept) ->
- "Server SSL handshake procedure between client and server failed.";
-format_error(esslconnect) ->
- "Client SSL handshake procedure between client and server failed.";
-format_error({eoptions, Options}) ->
- lists:flatten(io_lib:format("Error in options list: ~p~n", [Options]));
-
-%%%%%%%%%%%% START OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-format_error(ebadsocket) ->
- "Connection not found (internal error).";
-format_error(ebadstate) ->
- "Connection not in connect state (internal error).";
-format_error(ebrokertype) ->
- "Wrong broker type (internal error).";
-format_error(echaintoolong) ->
- "The chain of certificates provided by peer is too long.";
-format_error(ecipher) ->
- "Own list of specified ciphers is invalid.";
-format_error(ekeymismatch) ->
- "Own private key does not match own certificate.";
-format_error(enoissuercert) ->
- "Cannot find certificate of issuer of certificate provided by peer.";
-format_error(enoservercert) ->
- "Attempt to do accept without having set own certificate.";
-format_error(enotlistener) ->
- "Attempt to accept on a non-listening socket.";
-format_error(enoproxysocket) ->
- "No proxy socket found (internal error or max number of file "
- "descriptors exceeded).";
-format_error(enooptions) ->
- "List of options is empty.";
-format_error(enotstarted) ->
- "The SSL application has not been started.";
-format_error(eoptions) ->
- "Invalid list of options.";
-format_error(epeercert) ->
- "Certificate provided by peer is in error.";
-format_error(epeercertexpired) ->
- "Certificate provided by peer has expired.";
-format_error(epeercertinvalid) ->
- "Certificate provided by peer is invalid.";
-format_error(eselfsignedcert) ->
- "Certificate provided by peer is self signed.";
-format_error(esslerrssl) ->
- "SSL protocol failure. Typically because of a fatal alert from peer.";
-format_error(ewantconnect) ->
- "Protocol wants to connect, which is not supported in this "
- "version of the SSL application.";
-format_error(ex509lookup) ->
- "Protocol wants X.509 lookup, which is not supported in this "
- "version of the SSL application.";
-format_error({badcall, _Call}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-format_error({badcast, _Cast}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-
-format_error({badinfo, _Info}) ->
- "Call not recognized for current mode (active or passive) and state "
- "of socket.";
-
-%%%%%%%%%%%%%%%%%% END OLD SSL format_error %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
-
-format_error(Error) ->
- case (catch inet:format_error(Error)) of
- "unkknown POSIX" ++ _ ->
- no_format(Error);
- {'EXIT', _} ->
- no_format(Error);
- Other ->
- Other
- end.
-
no_format(Error) ->
lists:flatten(io_lib:format("No format string for error: \"~p\" available.", [Error])).
diff --git a/lib/ssl/src/ssl_certificate.erl b/lib/ssl/src/ssl_certificate.erl
index 206024315e..3c7ce837e4 100644
--- a/lib/ssl/src/ssl_certificate.erl
+++ b/lib/ssl/src/ssl_certificate.erl
@@ -57,30 +57,32 @@
trusted_cert_and_path(CertChain, CertDbRef) ->
Path = [Cert | _] = lists:reverse(CertChain),
OtpCert = public_key:pkix_decode_cert(Cert, otp),
- IssuerID =
+ SignedAndIssuerID =
case public_key:pkix_is_self_signed(OtpCert) of
true ->
{ok, IssuerId} = public_key:pkix_issuer_id(OtpCert, self),
- IssuerId;
+ {self, IssuerId};
false ->
case public_key:pkix_issuer_id(OtpCert, other) of
{ok, IssuerId} ->
- IssuerId;
+ {other, IssuerId};
{error, issuer_not_found} ->
case find_issuer(OtpCert, no_candidate) of
{ok, IssuerId} ->
- IssuerId;
+ {other, IssuerId};
Other ->
Other
end
end
end,
- case IssuerID of
+ case SignedAndIssuerID of
{error, issuer_not_found} ->
%% The root CA was not sent and can not be found.
{unknown_ca, Path};
- {SerialNr, Issuer} ->
+ {self, _} when length(Path) == 1 ->
+ {selfsigned_peer, Path};
+ {_ ,{SerialNr, Issuer}} ->
case ssl_manager:lookup_trusted_cert(CertDbRef, SerialNr, Issuer) of
{ok, {BinCert,_}} ->
{BinCert, Path};
@@ -110,9 +112,10 @@ file_to_certificats(File) ->
{ok, List} = ssl_manager:cache_pem_file(File),
[Bin || {'Certificate', Bin, not_encrypted} <- List].
%%--------------------------------------------------------------------
--spec validate_extension(term(), #'Extension'{}, term()) -> {valid, term()} |
- {fail, tuple()} |
- {unknown, term()}.
+-spec validate_extension(term(), #'Extension'{} | {bad_cert, atom()} | valid,
+ term()) -> {valid, term()} |
+ {fail, tuple()} |
+ {unknown, term()}.
%%
%% Description: Validates ssl/tls specific extensions
%%--------------------------------------------------------------------
diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl
index 86477f369d..2a5a7f3394 100644
--- a/lib/ssl/src/ssl_certificate_db.erl
+++ b/lib/ssl/src/ssl_certificate_db.erl
@@ -216,9 +216,15 @@ add_certs_from_file(File, Ref, CertsDb) ->
[Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries].
add_certs(Cert, Ref, CertsDb) ->
- ErlCert = public_key:pkix_decode_cert(Cert, otp),
- TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
- SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
- Issuer = public_key:pkix_normalize_name(
- TBSCertificate#'OTPTBSCertificate'.issuer),
- insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb).
+ try ErlCert = public_key:pkix_decode_cert(Cert, otp),
+ TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate,
+ SerialNumber = TBSCertificate#'OTPTBSCertificate'.serialNumber,
+ Issuer = public_key:pkix_normalize_name(
+ TBSCertificate#'OTPTBSCertificate'.issuer),
+ insert({Ref, SerialNumber, Issuer}, {Cert,ErlCert}, CertsDb)
+ catch
+ error:_ ->
+ Report = io_lib:format("SSL WARNING: Ignoring a CA cert as "
+ "it could not be correctly decoded.~n", []),
+ error_logger:info_report(Report)
+ end.
diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl
index c94199c336..bd1ba6978a 100644
--- a/lib/ssl/src/ssl_connection.erl
+++ b/lib/ssl/src/ssl_connection.erl
@@ -75,7 +75,7 @@
session, % #session{} from ssl_handshake.hrl
session_cache, %
session_cache_cb, %
- negotiated_version, % #protocol_version{}
+ negotiated_version, % tls_version()
supported_protocol_versions, % [atom()]
client_certificate_requested = false,
key_algorithm, % atom as defined by cipher_suite
diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl
index 99bc47f04b..5b1a510034 100644
--- a/lib/ssl/src/ssl_handshake.erl
+++ b/lib/ssl/src/ssl_handshake.erl
@@ -276,9 +276,9 @@ client_certificate_verify(OwnCert, MasterSecret, Version, Algorithm,
end.
%%--------------------------------------------------------------------
-%% -spec certificate_verify(binary(), public_key_info(), tls_version(),
-%% binary(), key_algo(),
-%% {_, {binary(), binary()}}) -> valid | #alert{}.
+-spec certificate_verify(binary(), public_key_info(), tls_version(),
+ binary(), key_algo(),
+ {_, {binary(), binary()}}) -> valid | #alert{}.
%%
%% Description: Checks that the certificate_verify message is valid.
%%--------------------------------------------------------------------
@@ -474,6 +474,88 @@ decode_client_key(ClientKey, Type, Version) ->
dec_client_key(ClientKey, key_exchange_alg(Type), Version).
%%--------------------------------------------------------------------
+-spec init_hashes() ->{{binary(), binary()}, {binary(), binary()}}.
+
+%%
+%% Description: Calls crypto hash (md5 and sha) init functions to
+%% initalize the hash context.
+%%--------------------------------------------------------------------
+init_hashes() ->
+ T = {crypto:md5_init(), crypto:sha_init()},
+ {T, T}.
+
+%%--------------------------------------------------------------------
+-spec update_hashes({{binary(), binary()}, {binary(), binary()}}, Data ::term()) ->
+ {{binary(), binary()}, {binary(), binary()}}.
+%%
+%% Description: Calls crypto hash (md5 and sha) update functions to
+%% update the hash context with Data.
+%%--------------------------------------------------------------------
+update_hashes(Hashes, % special-case SSL2 client hello
+ <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(CSLength), ?UINT16(0),
+ ?UINT16(CDLength),
+ CipherSuites:CSLength/binary,
+ ChallengeData:CDLength/binary>>) ->
+ update_hashes(Hashes,
+ <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
+ ?UINT16(CSLength), ?UINT16(0),
+ ?UINT16(CDLength),
+ CipherSuites:CSLength/binary,
+ ChallengeData:CDLength/binary>>);
+update_hashes({{MD50, SHA0}, _Prev}, Data) ->
+ ?DBG_HEX(Data),
+ {MD51, SHA1} = {crypto:md5_update(MD50, Data),
+ crypto:sha_update(SHA0, Data)},
+ ?DBG_HEX(crypto:md5_final(MD51)),
+ ?DBG_HEX(crypto:sha_final(SHA1)),
+ {{MD51, SHA1}, {MD50, SHA0}}.
+
+%%--------------------------------------------------------------------
+-spec decrypt_premaster_secret(binary(), #'RSAPrivateKey'{}) -> binary().
+
+%%
+%% Description: Public key decryption using the private key.
+%%--------------------------------------------------------------------
+decrypt_premaster_secret(Secret, RSAPrivateKey) ->
+ try public_key:decrypt_private(Secret, RSAPrivateKey,
+ [{rsa_pad, rsa_pkcs1_padding}])
+ catch
+ _:_ ->
+ throw(?ALERT_REC(?FATAL, ?DECRYPTION_FAILED))
+ end.
+
+%%--------------------------------------------------------------------
+-spec server_key_exchange_hash(rsa | dhe_rsa| dhe_dss, binary()) -> binary().
+
+%%
+%% Description: Calculate server key exchange hash
+%%--------------------------------------------------------------------
+server_key_exchange_hash(Algorithm, Value) when Algorithm == rsa;
+ Algorithm == dhe_rsa ->
+ MD5 = crypto:md5(Value),
+ SHA = crypto:sha(Value),
+ <<MD5/binary, SHA/binary>>;
+
+server_key_exchange_hash(dhe_dss, Value) ->
+ crypto:sha(Value).
+
+%%--------------------------------------------------------------------
+-spec sig_alg(atom()) -> integer().
+
+%%
+%% Description: Translate atom representation to enum representation.
+%%--------------------------------------------------------------------
+sig_alg(dh_anon) ->
+ ?SIGNATURE_ANONYMOUS;
+sig_alg(Alg) when Alg == dhe_rsa; Alg == rsa ->
+ ?SIGNATURE_RSA;
+sig_alg(dhe_dss) ->
+ ?SIGNATURE_DSA;
+sig_alg(_) ->
+ ?NULL.
+
+%%--------------------------------------------------------------------
%%% Internal functions
%%--------------------------------------------------------------------
get_tls_handshake_aux(<<?BYTE(Type), ?UINT24(Length),
@@ -496,6 +578,8 @@ path_validation_alert({bad_cert, unknown_critical_extension}) ->
?ALERT_REC(?FATAL, ?UNSUPPORTED_CERTIFICATE);
path_validation_alert({bad_cert, cert_revoked}) ->
?ALERT_REC(?FATAL, ?CERTIFICATE_REVOKED);
+path_validation_alert({bad_cert, selfsigned_peer}) ->
+ ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE);
path_validation_alert({bad_cert, unknown_ca}) ->
?ALERT_REC(?FATAL, ?UNKNOWN_CA);
path_validation_alert(_) ->
@@ -859,14 +943,6 @@ encrypted_premaster_secret(Secret, RSAPublicKey) ->
throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE))
end.
-decrypt_premaster_secret(Secret, RSAPrivateKey) ->
- try public_key:decrypt_private(Secret, RSAPrivateKey,
- [{rsa_pad, rsa_pkcs1_padding}])
- catch
- _:_ ->
- throw(?ALERT_REC(?FATAL, ?DECRYPTION_FAILED))
- end.
-
%% encode/decode stream of certificate data to/from list of certificate data
certs_to_list(ASN1Certs) ->
certs_to_list(ASN1Certs, []).
@@ -985,29 +1061,6 @@ enc_hello_extensions([#renegotiation_info{renegotiated_connection = Info} | Rest
Len = InfoLen +1,
enc_hello_extensions(Rest, <<?UINT16(?RENEGOTIATION_EXT), ?UINT16(Len), ?BYTE(InfoLen), Info/binary, Acc/binary>>).
-init_hashes() ->
- T = {crypto:md5_init(), crypto:sha_init()},
- {T, T}.
-
-update_hashes(Hashes, % special-case SSL2 client hello
- <<?CLIENT_HELLO, ?UINT24(_), ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>) ->
- update_hashes(Hashes,
- <<?CLIENT_HELLO, ?BYTE(Major), ?BYTE(Minor),
- ?UINT16(CSLength), ?UINT16(0),
- ?UINT16(CDLength),
- CipherSuites:CSLength/binary,
- ChallengeData:CDLength/binary>>);
-update_hashes({{MD50, SHA0}, _Prev}, Data) ->
- ?DBG_HEX(Data),
- {MD51, SHA1} = {crypto:md5_update(MD50, Data),
- crypto:sha_update(SHA0, Data)},
- ?DBG_HEX(crypto:md5_final(MD51)),
- ?DBG_HEX(crypto:sha_final(SHA1)),
- {{MD51, SHA1}, {MD50, SHA0}}.
from_3bytes(Bin3) ->
from_3bytes(Bin3, []).
@@ -1096,24 +1149,6 @@ calc_certificate_verify({3, N}, _, Algorithm, Hashes)
when N == 1; N == 2 ->
ssl_tls1:certificate_verify(Algorithm, Hashes).
-server_key_exchange_hash(Algorithm, Value) when Algorithm == rsa;
- Algorithm == dhe_rsa ->
- MD5 = crypto:md5(Value),
- SHA = crypto:sha(Value),
- <<MD5/binary, SHA/binary>>;
-
-server_key_exchange_hash(dhe_dss, Value) ->
- crypto:sha(Value).
-
-sig_alg(dh_anon) ->
- ?SIGNATURE_ANONYMOUS;
-sig_alg(Alg) when Alg == dhe_rsa; Alg == rsa ->
- ?SIGNATURE_RSA;
-sig_alg(dhe_dss) ->
- ?SIGNATURE_DSA;
-sig_alg(_) ->
- ?NULL.
-
key_exchange_alg(rsa) ->
?KEY_EXCHANGE_RSA;
key_exchange_alg(Alg) when Alg == dhe_rsa; Alg == dhe_dss;
diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl
index 0116466677..3b02d96562 100644
--- a/lib/ssl/src/ssl_manager.erl
+++ b/lib/ssl/src/ssl_manager.erl
@@ -122,6 +122,7 @@ server_session_id(Port, SuggestedSessionId, SslOpts) ->
call({server_session_id, Port, SuggestedSessionId, SslOpts}).
%%--------------------------------------------------------------------
+-spec register_session(port_num(), #session{}) -> ok.
-spec register_session(host(), port_num(), #session{}) -> ok.
%%
%% Description: Make the session available for reuse.
@@ -132,6 +133,7 @@ register_session(Host, Port, Session) ->
register_session(Port, Session) ->
cast({register_session, Port, Session}).
%%--------------------------------------------------------------------
+-spec invalidate_session(port_num(), #session{}) -> ok.
-spec invalidate_session(host(), port_num(), #session{}) -> ok.
%%
%% Description: Make the session unavilable for reuse.
diff --git a/lib/ssl/src/ssl_record.erl b/lib/ssl/src/ssl_record.erl
index acd0d49c19..803baeb09c 100644
--- a/lib/ssl/src/ssl_record.erl
+++ b/lib/ssl/src/ssl_record.erl
@@ -497,6 +497,66 @@ decode_cipher_text(CipherText, ConnnectionStates0) ->
#alert{} = Alert ->
Alert
end.
+%%--------------------------------------------------------------------
+-spec encode_data(iolist(), tls_version(), #connection_states{}, integer()) ->
+ {iolist(), iolist(), #connection_states{}}.
+%%
+%% Description: Encodes data to send on the ssl-socket.
+%%--------------------------------------------------------------------
+encode_data(Frag, Version, ConnectionStates, RenegotiateAt)
+ when byte_size(Frag) < (?MAX_PLAIN_TEXT_LENGTH - 2048) ->
+ case encode_plain_text(?APPLICATION_DATA,Version,Frag,ConnectionStates, RenegotiateAt) of
+ {renegotiate, Data} ->
+ {[], Data, ConnectionStates};
+ {Msg, CS} ->
+ {Msg, [], CS}
+ end;
+
+encode_data(Frag, Version, ConnectionStates, RenegotiateAt) when is_binary(Frag) ->
+ Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH - 2048),
+ encode_data(Data, Version, ConnectionStates, RenegotiateAt);
+
+encode_data(Data, Version, ConnectionStates0, RenegotiateAt) when is_list(Data) ->
+ {ConnectionStates, EncodedMsg, NotEncdedData} =
+ lists:foldl(fun(B, {CS0, Encoded, Rest}) ->
+ case encode_plain_text(?APPLICATION_DATA,
+ Version, B, CS0, RenegotiateAt) of
+ {renegotiate, NotEnc} ->
+ {CS0, Encoded, [NotEnc | Rest]};
+ {Enc, CS1} ->
+ {CS1, [Enc | Encoded], Rest}
+ end
+ end, {ConnectionStates0, [], []}, Data),
+ {lists:reverse(EncodedMsg), lists:reverse(NotEncdedData), ConnectionStates}.
+
+%%--------------------------------------------------------------------
+-spec encode_handshake(iolist(), tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
+%%
+%% Description: Encodes a handshake message to send on the ssl-socket.
+%%--------------------------------------------------------------------
+encode_handshake(Frag, Version, ConnectionStates) ->
+ encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
+
+%%--------------------------------------------------------------------
+-spec encode_alert_record(#alert{}, tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
+%%
+%% Description: Encodes an alert message to send on the ssl-socket.
+%%--------------------------------------------------------------------
+encode_alert_record(#alert{level = Level, description = Description},
+ Version, ConnectionStates) ->
+ encode_plain_text(?ALERT, Version, <<?BYTE(Level), ?BYTE(Description)>>,
+ ConnectionStates).
+
+%%--------------------------------------------------------------------
+-spec encode_change_cipher_spec(tls_version(), #connection_states{}) ->
+ {iolist(), #connection_states{}}.
+%%
+%% Description: Encodes a change_cipher_spec-message to send on the ssl socket.
+%%--------------------------------------------------------------------
+encode_change_cipher_spec(Version, ConnectionStates) ->
+ encode_plain_text(?CHANGE_CIPHER_SPEC, Version, <<1:8>>, ConnectionStates).
%%--------------------------------------------------------------------
%%% Internal functions
@@ -550,43 +610,6 @@ split_bin(Bin, ChunkSize, Acc) ->
lists:reverse(Acc, [Bin])
end.
-encode_data(Frag, Version, ConnectionStates, RenegotiateAt)
- when byte_size(Frag) < (?MAX_PLAIN_TEXT_LENGTH - 2048) ->
- case encode_plain_text(?APPLICATION_DATA,Version,Frag,ConnectionStates, RenegotiateAt) of
- {renegotiate, Data} ->
- {[], Data, ConnectionStates};
- {Msg, CS} ->
- {Msg, [], CS}
- end;
-
-encode_data(Frag, Version, ConnectionStates, RenegotiateAt) when is_binary(Frag) ->
- Data = split_bin(Frag, ?MAX_PLAIN_TEXT_LENGTH - 2048),
- encode_data(Data, Version, ConnectionStates, RenegotiateAt);
-
-encode_data(Data, Version, ConnectionStates0, RenegotiateAt) when is_list(Data) ->
- {ConnectionStates, EncodedMsg, NotEncdedData} =
- lists:foldl(fun(B, {CS0, Encoded, Rest}) ->
- case encode_plain_text(?APPLICATION_DATA,
- Version, B, CS0, RenegotiateAt) of
- {renegotiate, NotEnc} ->
- {CS0, Encoded, [NotEnc | Rest]};
- {Enc, CS1} ->
- {CS1, [Enc | Encoded], Rest}
- end
- end, {ConnectionStates0, [], []}, Data),
- {lists:reverse(EncodedMsg), lists:reverse(NotEncdedData), ConnectionStates}.
-
-encode_handshake(Frag, Version, ConnectionStates) ->
- encode_plain_text(?HANDSHAKE, Version, Frag, ConnectionStates).
-
-encode_alert_record(#alert{level = Level, description = Description},
- Version, ConnectionStates) ->
- encode_plain_text(?ALERT, Version, <<?BYTE(Level), ?BYTE(Description)>>,
- ConnectionStates).
-
-encode_change_cipher_spec(Version, ConnectionStates) ->
- encode_plain_text(?CHANGE_CIPHER_SPEC, Version, <<1:8>>, ConnectionStates).
-
encode_plain_text(Type, Version, Data, ConnectionStates, RenegotiateAt) ->
#connection_states{current_write =
#connection_state{sequence_number = Num}} = ConnectionStates,
diff --git a/lib/ssl/test/erl_make_certs.erl b/lib/ssl/test/erl_make_certs.erl
index f8aef55754..8b01ca3ad4 100644
--- a/lib/ssl/test/erl_make_certs.erl
+++ b/lib/ssl/test/erl_make_certs.erl
@@ -268,7 +268,7 @@ publickey(#'RSAPrivateKey'{modulus=N, publicExponent=E}) ->
subjectPublicKey = Public};
publickey(#'DSAPrivateKey'{p=P, q=Q, g=G, y=Y}) ->
Algo = #'PublicKeyAlgorithm'{algorithm= ?'id-dsa',
- parameters=#'Dss-Parms'{p=P, q=Q, g=G}},
+ parameters={params, #'Dss-Parms'{p=P, q=Q, g=G}}},
#'OTPSubjectPublicKeyInfo'{algorithm = Algo, subjectPublicKey = Y}.
validity(Opts) ->
@@ -290,7 +290,7 @@ sign_algorithm(#'RSAPrivateKey'{}, Opts) ->
end,
{Type, 'NULL'};
sign_algorithm(#'DSAPrivateKey'{p=P, q=Q, g=G}, _Opts) ->
- {?'id-dsa-with-sha1', #'Dss-Parms'{p=P, q=Q, g=G}}.
+ {?'id-dsa-with-sha1', {params,#'Dss-Parms'{p=P, q=Q, g=G}}}.
make_key(rsa, _Opts) ->
%% (OBS: for testing only)
diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk
index 709a089892..dd75d44aca 100644
--- a/lib/ssl/vsn.mk
+++ b/lib/ssl/vsn.mk
@@ -1 +1,2 @@
-SSL_VSN = 4.0.1
+
+SSL_VSN = 4.0.2
diff --git a/lib/stdlib/doc/src/supervisor.xml b/lib/stdlib/doc/src/supervisor.xml
index c696434d49..45fa0847a8 100644
--- a/lib/stdlib/doc/src/supervisor.xml
+++ b/lib/stdlib/doc/src/supervisor.xml
@@ -156,7 +156,7 @@ child_spec() = {Id,StartFunc,Restart,Shutdown,Type,Modules}
the child process to terminate by calling
<c>exit(Child,shutdown)</c> and then wait for an exit signal
with reason <c>shutdown</c> back from the child process. If
- no exit signal is received within the specified time,
+ no exit signal is received within the specified number of milliseconds,
the child process is unconditionally terminated using
<c>exit(Child,kill)</c>.</p>
<p>If the child process is another supervisor, <c>Shutdown</c>
diff --git a/lib/syntax_tools/src/epp_dodger.erl b/lib/syntax_tools/src/epp_dodger.erl
index 6b0f2034f8..9f6f7d815e 100644
--- a/lib/syntax_tools/src/epp_dodger.erl
+++ b/lib/syntax_tools/src/epp_dodger.erl
@@ -809,6 +809,8 @@ tokens_to_string([{atom,_,A} | Ts]) ->
io_lib:write_atom(A) ++ " " ++ tokens_to_string(Ts);
tokens_to_string([{string, _, S} | Ts]) ->
io_lib:write_string(S) ++ " " ++ tokens_to_string(Ts);
+tokens_to_string([{char, _, C} | Ts]) ->
+ io_lib:write_char(C) ++ " " ++ tokens_to_string(Ts);
tokens_to_string([{float, _, F} | Ts]) ->
float_to_list(F) ++ " " ++ tokens_to_string(Ts);
tokens_to_string([{integer, _, N} | Ts]) ->