diff options
Diffstat (limited to 'lib')
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]) -> |