diff options
Diffstat (limited to 'lib/ssl')
-rw-r--r-- | lib/ssl/doc/src/notes.xml | 1284 | ||||
-rw-r--r-- | lib/ssl/src/Makefile | 4 | ||||
-rw-r--r-- | lib/ssl/src/ssl.appup.src | 15 | ||||
-rw-r--r-- | lib/ssl/src/ssl_alert.erl | 11 | ||||
-rw-r--r-- | lib/ssl/src/ssl_certificate_db.erl | 51 | ||||
-rw-r--r-- | lib/ssl/src/ssl_connection.erl | 130 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.erl | 188 | ||||
-rw-r--r-- | lib/ssl/src/ssl_handshake.hrl | 9 | ||||
-rw-r--r-- | lib/ssl/src/ssl_manager.erl | 46 | ||||
-rw-r--r-- | lib/ssl/src/ssl_tls_dist_proxy.erl | 50 | ||||
-rw-r--r-- | lib/ssl/test/ssl_basic_SUITE.erl | 55 | ||||
-rw-r--r-- | lib/ssl/test/ssl_certificate_verify_SUITE.erl | 44 | ||||
-rw-r--r-- | lib/ssl/test/ssl_test_lib.erl | 81 | ||||
-rw-r--r-- | lib/ssl/test/ssl_to_openssl_SUITE.erl | 2 | ||||
-rw-r--r-- | lib/ssl/vsn.mk | 2 |
15 files changed, 418 insertions, 1554 deletions
diff --git a/lib/ssl/doc/src/notes.xml b/lib/ssl/doc/src/notes.xml index 49bbd5d27d..73cda03b2f 100644 --- a/lib/ssl/doc/src/notes.xml +++ b/lib/ssl/doc/src/notes.xml @@ -4,7 +4,7 @@ <chapter> <header> <copyright> - <year>1999</year><year>2012</year> + <year>1999</year><year>2013</year> <holder>Ericsson AB. All Rights Reserved.</holder> </copyright> <legalnotice> @@ -22,10 +22,6 @@ </legalnotice> <title>SSL Release Notes</title> - <prepared>Peter Högfeldt</prepared> - <docno></docno> - <date>2003-08-03</date> - <rev>G</rev> <file>notes.xml</file> </header> <p>This document describes the changes made to the SSL application.</p> @@ -605,1285 +601,7 @@ </item> </list> </section> - - </section> - - - <section><title>SSL 3.11.1</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Fixed handling of several ssl/tls packets arriving at the - same time. This was broken during a refactoring of the - code.</p> - <p> - Own Id: OTP-8679</p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Added missing checks for padding and Mac value. Removed - code for export ciphers and DH certificates as we decided - not to support them.</p> - <p> - Own Id: OTP-7047</p> - </item> - <item> - <p> - New ssl will no longer return esslerrssl to be backwards - compatible with old ssl as this hids infomation from the - user. format_error/1 has been updated to support new ssl.</p> - <p> - *** POTENTIAL INCOMPATIBILITY ***</p> - <p> - Own Id: OTP-7049</p> - </item> - <item> - <p> - New ssl now supports secure renegotiation as described by - RFC 5746.</p> - <p> - Own Id: OTP-8568</p> - </item> - <item> - <p> - Alert handling has been improved to better handle - unexpected but valid messages and the implementation is - also changed to avoid timing related issues that could - cause different error messages depending on network - latency. Packet handling was sort of broken but would - mostly work as expected when socket was in binary mode. - This has now been fixed.</p> - <p> - Own Id: OTP-8588</p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.11</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Fixes handling of the option fail_if_no_peer_cert and - some undocumented options. Thanks to Rory Byrne.</p> - <p> - Own Id: OTP-8557</p> - </item> - </list> - </section> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - Support for Diffie-Hellman. ssl-3.11 requires - public_key-0.6.</p> - <p> - Own Id: OTP-7046</p> - </item> - <item> - <p> - New ssl now properly handles ssl renegotiation, and - initiates a renegotiation if ssl/ltls-sequence numbers - comes close to the max value. However RFC-5746 is not yet - supported, but will be in an upcoming release.</p> - <p> - Own Id: OTP-8517</p> - </item> - <item> - <p> - When gen_tcp is configured with the {packet,http} option, - it automatically switches to expect HTTP Headers after a - HTTP Request/Response line has been received. This update - fixes ssl to behave in the same way. Thanks to Rory - Byrne.</p> - <p> - Own Id: OTP-8545</p> - </item> - <item> - <p> - Ssl now correctly verifies the extended_key_usage - extension and also allows the user to verify application - specific extensions by supplying an appropriate fun.</p> - <p> - Own Id: OTP-8554 Aux Id: OTP-8553 </p> - </item> - <item> - <p> - Fixed ssl:transport_accept/2 to return properly when - socket is closed. Thanks to Rory Byrne.</p> - <p> - Own Id: OTP-8560</p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.9</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Fixed a crash in the certificate certification part.</p> - <p> - Own Id: OTP-8510 Aux Id: seq11525 </p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.8</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p><c>ssl:send/2</c> ignored packet option, fix provided - by YAMASHINA Hio.</p> - <p>Fixed a file cache bug which caused problems when the - same file was used for both cert and cacert.</p> - <p>Allow <c>ssl:listen/2</c> to be called with option - {ssl_imp, old}.</p> - <p> Fixed ssl:setopts(Socket, binary) which didn't work - for 'new' ssl.</p>. - <p> - Own Id: OTP-8441</p> - </item> - <item> - <p> - Do a controlled shutdown if a non ssl packet arrives as - the first packet.</p> - <p> - Own Id: OTP-8459 Aux Id: seq11505 </p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p>Fixed session reuse (in new_ssl), thanks Wil Tan.</p> - <p>Send CA list during Certificate Request (in new_ssl) , - thanks Wil Tan.</p> <p><c>NOTE</c>: SSL (new_ssl) - requires public_key-0.5.</p> - <p> - Own Id: OTP-8372</p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.7</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - A ticker process could potentially be blocked - indefinitely trying to send a tick to a node not - responding. If this happened, the connection would not be - brought down as it should.</p> - <p> This requires erts-5.7.4 and kernel-2.13.4 or later - to be able to get the erlang distribution over ssl to work.</p> - <p> - Own Id: OTP-8218</p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - The documentation is now built with open source tools - (xsltproc and fop) that exists on most platforms. One - visible change is that the frames are removed.</p> - <p> - Own Id: OTP-8250</p> - </item> - <item> - <p> - Code cleanup from Kostis.</p> - <p> - Own Id: OTP-8260</p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.6</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - The ssl:ssl_accept/3 issue was not properly fixed in the - previous patch, see OTP-8244.</p> - <p> - Own Id: OTP-8275 Aux Id: seq11451 </p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.5</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Allow clients to not send certificates if option - <c>fail_if_no_peer_cert</c> was not set.</p> - <p> - Own Id: OTP-8224</p> - </item> - <item> - <p>An ssl:ssl_accept/3 could crash a connection if the - timing was wrong.</p> <p>Removed info message if the - socket closed without a proper disconnect from the ssl - layer. </p> <p>ssl:send/2 is now blocking until the - message is sent.</p> - <p> - Own Id: OTP-8244 Aux Id: seq11420 </p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.4</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - A client could avoid a certificate check if the client - code didn't send the requested certificate.</p> - <p> - Own Id: OTP-8137</p> - </item> - </list> - </section> - -</section> - -<section><title>SSL 3.10.3</title> - - <section><title>Improvements and New Features</title> - <list> - <item> - <p>Packet handling was not implemented correctly.</p> - <p>Inet option handling support have been improved.</p> - <p>The <c>verify_fun</c> is now invoked even if - verify_peer is used, that implies that by default - {bad_cert,unknown_ca} is an accepted fault during the - client connection phase. The check can still be done by - suppling another verify_fun.</p> - <p> - Own Id: OTP-8011 Aux Id: seq11287 </p> - </item> - </list> - </section> - -</section> - - -<section><title>SSL 3.10.2</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - A "new_ssl" socket was not closed if the controlling - process died without calling ssl:close/1.</p> - <p> - Own Id: OTP-7963 Aux Id: seq11276 </p> - </item> - </list> </section> - -</section> - -<section><title>SSL 3.10.1</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Fixed bug that caused the ssl handshake finished message - to be calculated wrongly under the circumstances that the - server did not send the trusted cert and that the - previous cert did not have the extension telling us the - trusted certs name. This manifested it self as - bad_record_mac alert from the server.</p> - <p> - Own Id: OTP-7878</p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - The cacertsfile option is now optional for ssl servers.</p> - <p> - Own Id: OTP-7656</p> - </item> - <item> - <p> - For the ssl client the options cacertfile, certfile and - keyfile are now optional as they are not always needed - depending on configuration of the client itself and the - configuration of the server. Also as PEM-files may - contain more than one entry the keyfile option will - default to the same file as given by the certfile option.</p> - <p> - Own Id: OTP-7870</p> - </item> - <item> - <p> - Added new ssl client option verify_fun.</p> - <p> - Own Id: OTP-7871</p> - </item> - </list> - </section> - -</section> - - <section><title>SSL 3.10</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - Error log entries are now formatted correctly.</p> - <p> - Own Id: OTP-7258</p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - All handling of X509-certificates and public keys have - been moved to the new application public_key.</p> - <p> - Own Id: OTP-6894</p> - </item> - <item> - <p> - New ssl now supports SSL-3.0 and TLS-1.0</p> - <p> - Own Id: OTP-7037</p> - </item> - <item> - <p> - New ssl now supports all inet-packet types.</p> - <p> - Own Id: OTP-7039</p> - </item> - <item> - <p> - The new ssl-server is now able to send a certificate - request to the client. However new options may be - introduced later to fully support all features regarding - certificate requests.</p> - <p> - Own Id: OTP-7150</p> - </item> - </list> - </section> - - - <section><title>Known Bugs and Problems</title> - <list> - <item> - <p> - Running erlang distribution over ssl don't work as - described in the documentation.</p> - <p> - Own Id: OTP-7536</p> - </item> - </list> - </section> - - </section> - - - <section><title>SSL 3.9</title> - - <section><title>Fixed Bugs and Malfunctions</title> - <list> - <item> - <p> - ssl_prim.erl was passing an FD rather than an #sslsocket - to ssl_broker:ssl_accept_prim. This could cause problems - in the deprecated accept function, this will not cause - any more problems however this function is deprecated!</p> - <p> - Own Id: OTP-6926</p> - </item> - <item> - <p> - Erlang distribution over ssl was broken after R11B-0, - this has now been fixed.</p> - <p> - Own Id: OTP-7004</p> - </item> - </list> - </section> - - - <section><title>Improvements and New Features</title> - <list> - <item> - <p> - All inet options are available in the new ssl - implementation that is released as a alfa in ssl-3.9 and - will replace the old implementation in ssl-4.0. This will - not be fixed in the old implementation.</p> - <p> - Own Id: OTP-4677</p> - </item> - <item> - <p> - The new ssl implementation released as a alfa in this - version supports upgrading of a tcp connection to an ssl - connection so that http client and servers may implement - RFC 2817.</p> - <p> - Own Id: OTP-5510</p> - </item> - <item> - <p>A new implementation of ssl is released as a alfa - version in ssl-3.9 it will later replace the old - implementation in ssl-4.0. The new implementation can be - accessed by providing the option {ssl_imp, new} to the - ssl:connect and ssl:listen functions.</p> - <p>The new implementation is Erlang based and all logic - is in Erlang and only payload encryption calculations are - done in C via the crypto application. The main reason for - making a new implementation is that the old solution was - very crippled as the control of the ssl-socket was deep - down in openssl making it hard if not impossible to - support all inet options, ipv6 and upgrade of a tcp - connection to an ssl connection. The alfa version has a - few limitations that will be removed before the ssl-4.0 - release. Main differences and limitations in the alfa are - listed below.</p> - - <list type="bulleted"> <item>New ssl requires the crypto - application.</item> <item>The option reuseaddr is - supported and the default value is false as in gen_tcp. - Old ssl is patched to accept that the option is set to - true to provide a smoother migration between the - versions. In old ssl the option is hard coded to - true.</item> <item>ssl:version/0 is replaced by - ssl:versions/0</item> <item>ssl:ciphers/0 is replaced by - ssl:cipher_suites/0</item> <item>ssl:pid/1 is a - meaningless function in new ssl and will be deprecated in - ssl-4.0 until it is removed it will return a valid but - meaningless pid.</item> <item>New API functions are - ssl:shutdown/2, ssl:cipher_suites/[0,1] and - ssl:versions/0</item> <item>Diffie-Hellman keyexchange is - not supported.</item> <item>Not all inet packet types are - supported.</item> <item>CRL and policy certificate - extensions are not supported.</item> <item>In this alfa - only sslv3 is enabled, although tlsv1 and tlsv1.1 - versions are implemented and will be supported in future - versions.</item> <item>For security reasons sslv2 is not - supported.</item> </list> - <p> - Own Id: OTP-6619</p> - </item> - <item> - <p> - New ssl implementation, released as alfa in ssl-3.9, - supports ipv6. It will not be supported in the old - implementation.</p> - <p> - Own Id: OTP-6637 Aux Id: OTP-6636 </p> - </item> - </list> - </section> - - </section> - - <section> - <title>SSL 3.1.1.1</title> - - <section> - <title>Minor Makefile changes</title> - <list type="bulleted"> - <item> - <p>Removed use of <c>erl_flags</c> from Makefile.</p> - <p>Own Id: OTP-6689</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.1.1</title> - - <section> - <title>Crash on error in ssl_accept</title> - <list type="bulleted"> - <item> - <p>A bug in ssl_accept could cause all ssl - connections to hang when a connection - attempt was closed by the client while - the server was in <c>ssl_accept</c>.</p> - <p>Own Id: OTP-6612 Aux Id: seq10599</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>SSL now uses a two-phase accept, with a separate accept - calls for the socket and the ssl protocol. This avoids - timeouts when a client doesn't initiate ssl handshake.</p> - <p>With the old implementation of accept, the server - was locked by a client, if the client didn't do - proper ssl handshake.</p> - <p>Own Id: OTP-6418 Aux Id: seq10105</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.0.12</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>An integer array pointing to a struct pollfd array, is - now reset before file descriptors are collected to be - included in a call to poll(). This is to prevent file - descriptors to be mixed up.</p> - <p>Own Id: OTP-6084</p> - </item> - <item> - <p>The generation of the module ssl_pkix_oid contained - multiple identifiers, which made the mapping between - atoms and identifiers not one-to-one.</p> - <p>Own Id: OTP-6085</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.0.11</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The state of a connection in active mode could be in a - restrictive state, so that an internal tcp_closed message - was incorrectly considered illegal, resulting in a - premature termination of the connection process.</p> - <p>Own Id: OTP-5972 Aux Id: seq10188 </p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.0.10</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Erlang distribution over SSL was broken. Corrected. - (Thanks to Fredrik Thulin.)</p> - <p>Own Id: OTP-5863</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.0.9</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The port program for the ssl application could waste huge - amounts of CPU time if a write could not be completed - directly and was put in the write queue. (Only on platforms - where poll() is used, such as Solaris and Linux.)</p> - <p>Own Id: OTP-5784</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.0.8</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A process reading only a portion of a sufficiently large - amount of data from an accepted socket, and then quering - the ssl library (e.g. ssl:getpeername()), would cause a - global deadlock in the esock port program.</p> - <p>Own Id: OTP-5702</p> - </item> - <item> - <p>A spelling error in the module <c>ssl_pkix</c> caused the - call to <c>ssl:peercert/2</c> to fail when the option - <c>subject</c> was used.</p> - <p>Own Id: OTP-5708</p> - </item> - <item> - <p>Because fopen() on Solaris 8 can't handle file - descriptor numbers above 255, reading of certificate - files would fail if all file descriptors below 256 were - in use (typically, if many connections were open). This - problem has been worked around.</p> - <p>The ssl application's port program used to use - select(), which meant that it could not handle more than - FD_SETSIZE file descriptors (usually 1024). To eliminate - that limitation, poll() is now used on all platforms that - support it.</p> - <p>Solaris/Sparc, 64-bit emulator: The SO_REUSEADDR - option was not set for listen sockets, which essentially - made the ssl application unusable. Corrected.</p> - <p>The default listen queue size for ssl port program was - changed to 128 (from 5).</p> - <p>Own Id: OTP-5755 Aux Id: seq10068 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssl 3.0.7</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The R/W buffer length i esock.c was too small. It has - been increased from 4k to 32k.</p> - <p>Own Id: OTP-5620</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssl 3.0.6</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>A configuration option for choosing protocol versions has - been added (<c>sslv2</c>, <c>sslv3</c>, and - <c>tlsv1</c>).</p> - <p>Own Id: OTP-5429 Aux Id: seq9755 </p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssl 3.0.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Linked in drivers in the crypto, and asn1 applications - are now compiled with the -D_THREAD_SAFE and -D_REENTRANT - switches on unix when the emulator has thread support - enabled.</p> - <p>Linked in drivers on MacOSX are not compiled with the - undocumented -lbundle1.o switch anymore. Thanks to Sean - Hinde who sent us a patch.</p> - <p>Linked in driver in crypto, and port programs in ssl, now - compiles on OSF1.</p> - <p>Minor makefile improvements in runtime_tools.</p> - <p>Own Id: OTP-5346</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssl 3.0.4</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p><c>ssl:recv/3</c> with finite timeout value, closed the - connection at timeout.</p> - <p>Own Id: OTP-4882</p> - </item> - </list> - </section> - </section> - - <section> - <title>Ssl 3.0.3</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>When a file descriptor was marked for closing, and - end-of-file condition had already been detected, the file - descriptor was never closed.</p> - <p>Own Id: OTP-5093 Aux Id: seq8806 </p> - </item> - <item> - <p>When the number of open file descriptors reached - FD_SETSIZE, the SSL port program entered a busy loop.</p> - <p>Own Id: OTP-5094 Aux Id: seq8806 </p> - </item> - </list> - </section> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The SSL application now supports SSL sessions for - servers, which typically speeds up HTTP requests from - browsers.</p> - <p>Own Id: OTP-5095</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 3.0.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The UTF8String type is now defined in asn1-1.4.4.2 and - later. Therefore the definitions of UTF8String has been - removed from the ASN.1 modules PKIX1Explicit88.asn1 and - PKIXAttributeCertificate.asn1. The SSL application can now - only be built using asn-1.4.4.2 or later.</p> - <p>OwnId: OTP-4971.</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <p>See SSL-3.0. - </p> - </section> - </section> - - <section> - <title>SSL 3.0.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>An unexpected object identifier would crash <c>ssl:peercert</c>. </p> - <p>OwnId: OTP-4771.</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <p>See SSL-3.0. - </p> - </section> - </section> - - <section> - <title>SSL 3.0</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The <c>cache_timout</c> option was silently ignored. It had - to do with SSL sessions, where multiple connections can occur. - Since the Erlang SSL application does not support sessions the - option is still ignored, and consequently the documentation - about it has been removed.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>The Erlang SSL application is now based on OpenSSL version - 0.9.7a. OpenSSL 0.9.6 should also work.</p> - <p>OwnId: OTP-4002</p> - </item> - <item> - <p>When connecting it is now possible to bind to a local address - and local port. </p> - <p>OwnId: OTP-4675</p> - </item> - <item> - <p>The <c>ssl_esock</c> port program is now part of the - distribution and thus does not have to be created - explicitly. It is dynamically linked to OpenSSL - libraries in a "standard" location (typically - <c>/usr/local/lib</c> on UNIX; in the path on Win32).</p> - <p>OwnId: - OTP-4676</p> - </item> - <item> - <p>The new functions <c>ssl:peercert/1/2</c> provide information - from the certificate of a peer of a connection.</p> - <p>OwnId: OTP-4680 - <br></br> -Aux Id: seq7688</p> - </item> - <item> - <p>The function <c>ssl:port/1</c> has been removed from the - documentation, but not from the <c>ssl</c> interface module. - The recommendation is to use <c>ssl:peername/1</c> - instead, which provides both address and port of the peer.</p> - <p>OwnId: OTP-4681 </p> - </item> - <item> - <p>New User's Guide documentation has been added.</p> - <p>OwnId: OTP-4682 </p> - </item> - <item> - <p>The old <c>ssl_socket</c> interface has been removed and also - the documentation of it. </p> - <p>OwnId: OTP-4683 </p> - </item> - <item> - <p>The use of ephemeral RSA keys is now supported. It is - a global configuration option (see the ssl(6) manual page).</p> - <p>OwnId: OTP-4691.</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The option <c>cacertfile</c> is now in effect, and can - therefore no longer be set with the OS environment - variable SSL_CERT_FILE (which did set the same value for - all connections). </p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>There was a synchronization error at closing of an SSL - connection. </p> - <p>OwnId: OTP-4435 - <br></br> -Aux Id: seq7534</p> - </item> - <item> - <p>C macros in <c>debuglog.c</c> were not ANSI C compliant.</p> - <p>OwnId: OTP-4674</p> - </item> - <item> - <p>The <c>binary</c> option was not properly handled.</p> - <p>OwnId: OTP-4678</p> - </item> - <item> - <p>The <c>ssl:format_error/1</c> did not consider <c>inet</c> - error codes, nor did it have a catch all for unknown error - codes.</p> - <p>OwnId: OTP-4679</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <list type="bulleted"> - <item> - <p>Change of controlling process in not OTP compliant. </p> - <p>OwnId; OTP-4712</p> - </item> - <item> - <p>There is still no way to restrict the cipher sizes. </p> - <p>OwnId: OTP-4712</p> - </item> - <item> - <p>The <c>keep_alive</c> and <c>reuse_addr</c> options will be - added in a future release. </p> - <p>OwnId: OTP-4677</p> - </item> - <item> - <p>There is currently no way to restrict the SSL/TLS - protocol versions to use. In a future release this will be - supported as a configuration option, and as an option for - each connection as well. </p> - <p>OwnId: OTP-4711.</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.3.6</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>There was a synchronization error at closing, which could - result in that an SSL socket was removed prematurely, resulting - in that a user process referring to it received an unexpected - exit.</p> - <p>OwnId: OTP-4435 - <br></br> -Aux Id: seq7600</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <p>See SSL 2.2 . </p> - </section> - </section> - - <section> - <title>SSL 2.3.5</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Setting of the option `nodelay' caused the SSL port program - to dump core.</p> - <p>OwnId: OTP-4380 - <br></br> -Aux Id: -</p> - </item> - <item> - <p>Setting of the option '{active, once}' in <c>setopts</c> was - wrong, causing a correct socket message to be regarded as - erroneous. </p> - <p>OwnId: OTP-4380 - <br></br> -Aux Id: -</p> - </item> - <item> - <p>A self-signed peer certificate was always rejected with the - error `eselfsignedcert', irrespective of the `depth' value. </p> - <p>OwnId: OTP-4374 - <br></br> -Aux Id: seq7417</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <p>See SSL 2.2 . </p> - </section> - </section> - - <section> - <title>SSL 2.3.4</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>All TCP options allowed in gen_tcp, are now also allowed in - SSL, except the option <c>{reuseaddr, Boolean}</c>. A new - function <c>getopts</c> has been added to the SSL interface - module <c>ssl</c>. </p> - <p>OwnId: OTP-4305, OTP-4159</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.3.3</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The roles of the SSLeay and OpenSSL packages has been - clarified in the ssl(6) application manual page. Also - the URLs from which to download SSLeay has been updated.</p> - <p>OwnId: OTP-4002 - <br></br> -Aux Id: seq5269</p> - </item> - <item> - <p>A call to <c>ssl:listen(Port, Options)</c> with - <c>Options = []</c> resulted in the cryptic <c>{error, ebadf}</c> return value. The return value has been changed - to <c>{error, enooptions}</c>, and the behaviour has been - documented in the <c>listen/2</c> function.</p> - <p>OwnId: OTP-4016 - <br></br> -Aux Id: seq7006</p> - </item> - <item> - <p>Use of the option <c>{nodelay, boolean()}</c> crashed - the <c>ssl_server</c>.</p> - <p>OwnId: OTP-4070 - <br></br> -Aux Id:</p> - </item> - <item> - <p>A bug caused the Erlang distribution over ssl to fail. - This bug has now been fixed.</p> - <p>OwnId: OTP-4072 - <br></br> -Aux Id:</p> - </item> - <item> - <p>On Windows when the SSL port program encountered an - error code not anticipated it crashed. </p> - <p>OwnId: OTP-4132 - <br></br> -Aux Id:</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.3.2</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>The <c>ssl:accept/1-2</c> function sometimes returned - <c>{error, {What, Where}}</c> instead of <c>{error, What}</c>, where <c>What</c> is an atom. </p> - <p>OwnId: OTP-3775 - <br></br> -Aux Id: seq4991</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.3.1</title> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>Sometimes the SSL portprogram would loop in an accept - loop, without terminating even when the SSL application - was stopped.. </p> - <p>OwnId: OTP-3691</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.3</title> - <p>Functions have been added to SSL to experimentally support - Erlang distribution. - </p> - </section> - - <section> - <title>SSL 2.2.1</title> - <p>The 2.2.1 version of SSL provides code replacement in runtime - by upgrading from, or downgrading to, versions 2.1 and 2.2. - </p> - </section> - - <section> - <title>SSL 2.2</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The restriction that only the creator of an SSL socket can - read from and write to the socket has been lifted.</p> - <p>OwnId: OTP-3301</p> - </item> - <item> - <p>The option <c>{packet, cdr}</c> for SSL sockets has been added, - which means that SSL sockets also supports CDR encoded packets.</p> - <p>OwnId: OTP-3302</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <list type="bulleted"> - <item> - <p>Setting of a CA certificate file with the <c>cacertfile</c> - option (in calls to <c>ssl:accept/1/2</c> or - <c>ssl:connect/3/4</c>) does not work due to weaknesses - in the SSLeay package. </p> - <p>A work-around is to set the OS environment variable - <c>SSL_CERT_FILE</c> before SSL is started. However, then - the CA certificate file will be global for all connections.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>When changing controlling process of an SSL socket, a - temporary process is started, which is not gen_server - compliant.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>Although there is a <c>cache</c> timeout option, it is - silently ignored.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>There is currently no way to restrict the cipher sizes.</p> - <p>OwnId: OTP-3146</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.1</title> - - <section> - <title>Improvements and New Features</title> - <list type="bulleted"> - <item> - <p>The set of possible error reasons has been extended to - contain diagnostics on erroneous certificates and failures - to verify certificates.</p> - <p>OwnId: OTP-3145</p> - </item> - <item> - <p>The maximum number of simultaneous SSL connections on - Windows has been increased from 31 to 127.</p> - <p>OwnId: OTP-3145</p> - </item> - </list> - </section> - - <section> - <title>Fixed Bugs and Malfunctions</title> - <list type="bulleted"> - <item> - <p>A dead-lock occurring when write queues are not empty has - been removed. </p> - <p>OwnId: OTP-3145</p> - </item> - <item> - <p>Error reasons have been unified and changed.</p> - <p>(** POTENTIAL INCOMPATIBILITY **)</p> - <p>OwnId: OTP-3145</p> - </item> - <item> - <p>On Windows a check of the existence of the environment - variable <c>ERLSRV_SERVICE_NAME</c> has been added. If - that variable is defined, the port program of the SSL - application will not terminated when a user logs off.</p> - <p>OwnId: OTP-3145</p> - </item> - <item> - <p>An error in the setting of the <c>nodelay</c> option - has been corrected.</p> - <p>OwnId: OTP-3145</p> - </item> - <item> - <p>The confounded notions of verify mode and verify depth has - been corrected. The option <c>verifydepth</c> has been - removed, and the two separate options <c>verify</c> and - <c>depth</c> has been added.</p> - <p>(** POTENTIAL INCOMPATIBILITY **)</p> - <p>OwnId: OTP-3145</p> - </item> - </list> - </section> - - <section> - <title>Known Bugs and Problems</title> - <list type="bulleted"> - <item> - <p>Setting of a CA certificate file with the <c>cacertfile</c> - option (in calls to <c>ssl:accept/1/2</c> or - <c>ssl:connect/3/4</c>) does not work due to weaknesses - in the SSLeay package. </p> - <p>A work-around is to set the OS environment variable - <c>SSL_CERT_FILE</c> before SSL is started. However, then - the CA certificate file will be global for all connections.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>When changing controlling process of an SSL socket, a - temporary process is started, which is not gen_server - compliant.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>Although there is a <c>cache</c> timeout option, it is - silently ignored.</p> - <p>OwnId: OTP-3146</p> - </item> - <item> - <p>There is currently no way to restrict the cipher sizes.</p> - <p>OwnId: OTP-3146</p> - </item> - </list> - </section> - </section> - - <section> - <title>SSL 2.0</title> - <p>A complete new version of SSL with separate I/O channels - for all connections with non-blocking I/O multiplexing.</p> - </section> </chapter> diff --git a/lib/ssl/src/Makefile b/lib/ssl/src/Makefile index 6be8a1456e..043645be41 100644 --- a/lib/ssl/src/Makefile +++ b/lib/ssl/src/Makefile @@ -108,10 +108,10 @@ clean: rm -f errs core *~ $(APP_TARGET): $(APP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ $(APPUP_TARGET): $(APPUP_SRC) ../vsn.mk - sed -e 's;%VSN%;$(VSN);' $< > $@ + $(vsn_verbose)sed -e 's;%VSN%;$(VSN);' $< > $@ docs: diff --git a/lib/ssl/src/ssl.appup.src b/lib/ssl/src/ssl.appup.src index 9b1227fa7f..76e14860ec 100644 --- a/lib/ssl/src/ssl.appup.src +++ b/lib/ssl/src/ssl.appup.src @@ -1,24 +1,13 @@ %% -*- erlang -*- {"%VSN%", [ - {"5.1.1", [{restart_application, ssl}] - }, - {"5.1", [ - {load_module, ssl_connection, soft_purge, soft_purge, []} - ] - }, + {<<"5.1\\*">>, [{restart_application, ssl}]}, {<<"5.0\\*">>, [{restart_application, ssl}]}, {<<"4\\.*">>, [{restart_application, ssl}]}, {<<"3\\.*">>, [{restart_application, ssl}]} ], [ - {"5.1.1", [{restart_application, ssl}] - }, - {"5.1", [ - {load_module, ssl_connection, soft_purge, soft_purge, []} - ] - }, - {"5.1", [{restart_application, ssl}]}, + {<<"5.1\\*">>, [{restart_application, ssl}]}, {<<"5.0\\*">>, [{restart_application, ssl}]}, {<<"4\\.*">>, [{restart_application, ssl}]}, {<<"3\\.*">>, [{restart_application, ssl}]} diff --git a/lib/ssl/src/ssl_alert.erl b/lib/ssl/src/ssl_alert.erl index 222b3f1ad7..f94a1136a0 100644 --- a/lib/ssl/src/ssl_alert.erl +++ b/lib/ssl/src/ssl_alert.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -36,8 +36,7 @@ %% Internal application API %%==================================================================== %%-------------------------------------------------------------------- --spec reason_code(#alert{}, client | server) -> closed | esslconnect | - esslaccept | string(). +-spec reason_code(#alert{}, client | server) -> closed | {essl, string()}. %% %% Description: Returns the error reason that will be returned to the %% user. @@ -45,12 +44,8 @@ reason_code(#alert{description = ?CLOSE_NOTIFY}, _) -> closed; -reason_code(#alert{description = ?HANDSHAKE_FAILURE}, client) -> - esslconnect; -reason_code(#alert{description = ?HANDSHAKE_FAILURE}, server) -> - esslaccept; reason_code(#alert{description = Description}, _) -> - description_txt(Description). + {essl, description_txt(Description)}. %%-------------------------------------------------------------------- -spec alert_txt(#alert{}) -> string(). diff --git a/lib/ssl/src/ssl_certificate_db.erl b/lib/ssl/src/ssl_certificate_db.erl index 67d00f0da7..ff36b5ee26 100644 --- a/lib/ssl/src/ssl_certificate_db.erl +++ b/lib/ssl/src/ssl_certificate_db.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -18,10 +18,11 @@ %% %%---------------------------------------------------------------------- -%% Purpose: Storage for trused certificats +%% Purpose: Storage for trusted certificates %%---------------------------------------------------------------------- -module(ssl_certificate_db). + -include("ssl_internal.hrl"). -include_lib("public_key/include/public_key.hrl"). -include_lib("kernel/include/file.hrl"). @@ -37,7 +38,7 @@ %%==================================================================== %%-------------------------------------------------------------------- --spec create() -> [db_handle()]. +-spec create() -> [db_handle(),...]. %% %% Description: Creates a new certificate db. %% Note: lookup_trusted_cert/4 may be called from any process but only @@ -54,7 +55,7 @@ create() -> ]. %%-------------------------------------------------------------------- --spec remove([db_handle()]) -> term(). +-spec remove([db_handle()]) -> ok. %% %% Description: Removes database db %%-------------------------------------------------------------------- @@ -114,8 +115,8 @@ add_trusted_certs(_Pid, File, [CertsDb, RefDb, PemChache] = Db) -> new_trusted_cert_entry({MD5, File}, Db) end. %%-------------------------------------------------------------------- --spec cache_pem_file({binary(), binary()}, [db_handle()]) -> term(). --spec cache_pem_file(reference(), {binary(), binary()}, [db_handle()]) -> term(). +-spec cache_pem_file({binary(), binary()}, [db_handle()]) -> {ok, term()}. +-spec cache_pem_file(reference(), {binary(), binary()}, [db_handle()]) -> {ok, term()}. %% %% Description: Cache file as binary in DB %%-------------------------------------------------------------------- @@ -131,19 +132,25 @@ cache_pem_file(Ref, {MD5, File}, [_CertsDb, _RefDb, PemChache]) -> insert(MD5, {Content, Ref}, PemChache), {ok, Content}. +%%-------------------------------------------------------------------- +-spec remove_trusted_certs(reference(), db_handle()) -> ok. +%% +%% Description: Removes all trusted certificates refernced by <Ref>. +%%-------------------------------------------------------------------- remove_trusted_certs(Ref, CertsDb) -> remove_certs(Ref, CertsDb). %%-------------------------------------------------------------------- --spec remove(term(), db_handle()) -> term(). +-spec remove(term(), db_handle()) -> ok. %% %% Description: Removes an element in a <Db>. %%-------------------------------------------------------------------- remove(Key, Db) -> - _ = ets:delete(Db, Key). + ets:delete(Db, Key), + ok. %%-------------------------------------------------------------------- --spec lookup(term(), db_handle()) -> term() | undefined. +-spec lookup(term(), db_handle()) -> [term()] | undefined. %% %% Description: Looks up an element in a <Db>. %%-------------------------------------------------------------------- @@ -158,7 +165,7 @@ lookup(Key, Db) -> [Pick(Data) || Data <- Contents] end. %%-------------------------------------------------------------------- --spec foldl(fun(), term(), db_handle()) -> term(). +-spec foldl(fun((_,_) -> term()), term(), db_handle()) -> term(). %% %% Description: Calls Fun(Elem, AccIn) on successive elements of the %% cache, starting with AccIn == Acc0. Fun/2 must return a new @@ -178,12 +185,13 @@ ref_count(Key, Db, N) -> ets:update_counter(Db,Key,N). %%-------------------------------------------------------------------- --spec clear(db_handle()) -> term(). +-spec clear(db_handle()) -> ok. %% %% Description: Clears the cache %%-------------------------------------------------------------------- clear(Db) -> - ets:delete_all_objects(Db). + true = ets:delete_all_objects(Db), + ok. %%-------------------------------------------------------------------- -spec db_size(db_handle()) -> integer(). @@ -194,30 +202,35 @@ db_size(Db) -> ets:info(Db, size). %%-------------------------------------------------------------------- -%%-spec insert(Key::term(), Data::term(), Db::db_handle()) -> no_return(). +-spec insert(Key::term(), Data::term(), Db::db_handle()) -> ok. %% %% Description: Inserts data into <Db> %%-------------------------------------------------------------------- insert(Key, Data, Db) -> - true = ets:insert(Db, {Key, Data}). + true = ets:insert(Db, {Key, Data}), + ok. %%-------------------------------------------------------------------- %%% Internal functions %%-------------------------------------------------------------------- update_counter(Key, Count, Db) -> - true = ets:insert(Db, {Key, Count}). + true = ets:insert(Db, {Key, Count}), + ok. remove_certs(Ref, CertsDb) -> - ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}). + true = ets:match_delete(CertsDb, {{Ref, '_', '_'}, '_'}), + ok. add_certs_from_der(DerList, Ref, CertsDb) -> Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end, - [Add(Cert) || Cert <- DerList]. + [Add(Cert) || Cert <- DerList], + ok. add_certs_from_pem(PemEntries, Ref, CertsDb) -> Add = fun(Cert) -> add_certs(Cert, Ref, CertsDb) end, - [Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries]. - + [Add(Cert) || {'Certificate', Cert, not_encrypted} <- PemEntries], + ok. + add_certs(Cert, Ref, CertsDb) -> try ErlCert = public_key:pkix_decode_cert(Cert, otp), TBSCertificate = ErlCert#'OTPCertificate'.tbsCertificate, diff --git a/lib/ssl/src/ssl_connection.erl b/lib/ssl/src/ssl_connection.erl index cde13069b5..e5a6181a88 100644 --- a/lib/ssl/src/ssl_connection.erl +++ b/lib/ssl/src/ssl_connection.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -372,8 +372,7 @@ hello(#server_hello{cipher_suite = CipherSuite, ssl_options = SslOptions} = State0) -> case ssl_handshake:hello(Hello, SslOptions, ConnectionStates0, Renegotiation) of #alert{} = Alert -> - handle_own_alert(Alert, ReqVersion, hello, State0), - {stop, {shutdown, own_alert}, State0}; + handle_own_alert(Alert, ReqVersion, hello, State0); {Version, NewId, ConnectionStates, NextProtocol} -> {KeyAlgorithm, _, _, _} = ssl_cipher:suite_definition(CipherSuite), @@ -1135,7 +1134,7 @@ init_certificates(#ssl_options{cacerts = CaCerts, {ok, _, _, _, _, _} = ssl_manager:connection_init(Certs, Role) catch Error:Reason -> - handle_file_error(?LINE, Error, Reason, CACertFile, ecacertfile, + handle_file_error(?LINE, Error, Reason, CACertFile, {ecacertfile, Reason}, erlang:get_stacktrace()) end, init_certificates(Cert, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheHandle, CertFile, Role). @@ -1157,7 +1156,7 @@ init_certificates(undefined, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHan {ok, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, OwnCert} catch Error:Reason -> - handle_file_error(?LINE, Error, Reason, CertFile, ecertfile, + handle_file_error(?LINE, Error, Reason, CertFile, {ecertfile, Reason}, erlang:get_stacktrace()) end; init_certificates(Cert, CertDbRef, CertDbHandle, FileRefHandle, PemCacheHandle, CacheRef, _, _) -> @@ -1176,7 +1175,7 @@ init_private_key(DbHandle, undefined, KeyFile, Password, _) -> private_key(public_key:pem_entry_decode(PemEntry, Password)) catch Error:Reason -> - handle_file_error(?LINE, Error, Reason, KeyFile, ekeyfile, + handle_file_error(?LINE, Error, Reason, KeyFile, {ekeyfile, Reason}, erlang:get_stacktrace()) end; @@ -1234,7 +1233,7 @@ init_diffie_hellman(DbHandle,_, DHParamFile, server) -> catch Error:Reason -> handle_file_error(?LINE, Error, Reason, - DHParamFile, edhfile, erlang:get_stacktrace()) + DHParamFile, {edhfile, Reason}, erlang:get_stacktrace()) end. sync_send_all_state_event(FsmPid, Event) -> @@ -1628,78 +1627,49 @@ save_verify_data(client, #finished{verify_data = Data}, ConnectionStates, abbrev save_verify_data(server, #finished{verify_data = Data}, ConnectionStates, abbreviated) -> ssl_record:set_server_verify_data(current_write, Data, ConnectionStates). -handle_server_key(#server_key_exchange{params = - #server_dh_params{dh_p = P, - dh_g = G, - dh_y = ServerPublicDhKey}, - signed_params = <<>>}, - #state{key_algorithm = dh_anon} = State) -> - dh_master_secret(P, G, ServerPublicDhKey, undefined, State); - -handle_server_key( - #server_key_exchange{params = - #server_dh_params{dh_p = P, - dh_g = G, - dh_y = ServerPublicDhKey}, - signed_params = Signed, - hashsign = HashSign}, - #state{negotiated_version = Version, - public_key_info = PubKeyInfo, - connection_states = ConnectionStates} = State) -> - - PLen = size(P), - GLen = size(G), - YLen = size(ServerPublicDhKey), - HashAlgo = connection_hash_algo(HashSign, State), +handle_server_key(#server_key_exchange{exchange_keys = Keys}, + #state{key_algorithm = KeyAlg, + negotiated_version = Version} = State) -> + Params = ssl_handshake:decode_server_key(Keys, KeyAlg, Version), + HashSign = connection_hashsign(Params#server_key_params.hashsign, State), + case HashSign of + {_, anon} -> + server_master_secret(Params#server_key_params.params, State); + _ -> + verify_server_key(Params, HashSign, State) + end. - ConnectionState = +verify_server_key(#server_key_params{params = Params, + params_bin = EncParams, + signature = Signature}, + HashSign = {HashAlgo, _}, + #state{negotiated_version = Version, + public_key_info = PubKeyInfo, + connection_states = ConnectionStates} = State) -> + ConnectionState = ssl_record:pending_connection_state(ConnectionStates, read), SecParams = ConnectionState#connection_state.security_parameters, #security_parameters{client_random = ClientRandom, server_random = ServerRandom} = SecParams, Hash = ssl_handshake:server_key_exchange_hash(HashAlgo, - <<ClientRandom/binary, - ServerRandom/binary, - ?UINT16(PLen), P/binary, - ?UINT16(GLen), G/binary, - ?UINT16(YLen), - ServerPublicDhKey/binary>>), - - case verify_dh_params(Version, Signed, Hash, HashAlgo, PubKeyInfo) of + <<ClientRandom/binary, + ServerRandom/binary, + EncParams/binary>>), + case ssl_handshake:verify_signature(Version, Hash, HashSign, Signature, PubKeyInfo) of true -> - dh_master_secret(P, G, ServerPublicDhKey, undefined, State); + server_master_secret(Params, State); false -> ?ALERT_REC(?FATAL, ?DECRYPT_ERROR) end. -verify_dh_params({3, Minor}, Signed, Hashes, HashAlgo, {?rsaEncryption, PubKey, _PubKeyParams}) - when Minor >= 3 -> - public_key:verify({digest, Hashes}, HashAlgo, Signed, PubKey); -verify_dh_params(_Version, Signed, Hashes, _HashAlgo, {?rsaEncryption, PubKey, _PubKeyParams}) -> - case public_key:decrypt_public(Signed, PubKey, - [{rsa_pad, rsa_pkcs1_padding}]) of - Hashes -> - true; - _ -> - false - end; -verify_dh_params(_Version, Signed, Hash, HashAlgo, {?'id-dsa', PublicKey, PublicKeyParams}) -> - public_key:verify({digest, Hash}, HashAlgo, Signed, {PublicKey, PublicKeyParams}). - -dh_master_secret(Prime, Base, PublicDhKey, undefined, State) -> - PMpint = mpint_binary(Prime), - GMpint = mpint_binary(Base), - Keys = {_, PrivateDhKey} = - crypto:dh_generate_key([PMpint,GMpint]), - dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys}); +server_master_secret(#server_dh_params{dh_p = P, dh_g = G, dh_y = ServerPublicDhKey}, + State) -> + dh_master_secret(P, G, ServerPublicDhKey, undefined, State). -dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, - #state{session = Session, - negotiated_version = Version, role = Role, - connection_states = ConnectionStates0} = State) -> - PremasterSecret = - crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey, - [PMpint, GMpint]), +master_from_premaster_secret(PremasterSecret, + #state{session = Session, + negotiated_version = Version, role = Role, + connection_states = ConnectionStates0} = State) -> case ssl_handshake:master_secret(Version, PremasterSecret, ConnectionStates0, Role) of {MasterSecret, ConnectionStates} -> @@ -1711,6 +1681,19 @@ dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, Alert end. +dh_master_secret(Prime, Base, PublicDhKey, undefined, State) -> + PMpint = mpint_binary(Prime), + GMpint = mpint_binary(Base), + Keys = {_, PrivateDhKey} = + crypto:dh_generate_key([PMpint,GMpint]), + dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State#state{diffie_hellman_keys = Keys}); + +dh_master_secret(PMpint, GMpint, PublicDhKey, PrivateDhKey, State) -> + PremasterSecret = + crypto:dh_compute_key(mpint_binary(PublicDhKey), PrivateDhKey, + [PMpint, GMpint]), + master_from_premaster_secret(PremasterSecret, State). + cipher_role(client, Data, Session, #state{connection_states = ConnectionStates0} = State) -> ConnectionStates = ssl_record:set_server_verify_data(current_both, Data, ConnectionStates0), next_state_connection(cipher, ack_connection(State#state{session = Session, @@ -2485,10 +2468,10 @@ get_pending_connection_state_prf(CStates, Direction) -> CS = ssl_record:pending_connection_state(CStates, Direction), CS#connection_state.security_parameters#security_parameters.prf_algorithm. -connection_hash_algo({HashAlgo, _}, _State) -> - HashAlgo; -connection_hash_algo(_, #state{hashsign_algorithm = {HashAlgo, _}}) -> - HashAlgo. +connection_hashsign(HashSign = {_, _}, _State) -> + HashSign; +connection_hashsign(_, #state{hashsign_algorithm = HashSign}) -> + HashSign. %% RFC 5246, Sect. 7.4.1.4.1. Signature Algorithms %% If the client does not send the signature_algorithms extension, the @@ -2526,12 +2509,13 @@ default_hashsign(_Version, KeyExchange) start_or_recv_cancel_timer(infinity, _RecvFrom) -> undefined; start_or_recv_cancel_timer(Timeout, RecvFrom) -> - erlang:send_after(Timeout, self(), {cancel_start_or_recv, RecvFrom}). + erlang:send_after(Timeout, self(), {cancel_start_or_recv, RecvFrom}). cancel_timer(undefined) -> ok; cancel_timer(Timer) -> - erlang:cancel_timer(Timer). + erlang:cancel_timer(Timer), + ok. handle_unrecv_data(StateName, #state{socket = Socket, transport_cb = Transport} = State) -> inet:setopts(Socket, [{active, false}]), diff --git a/lib/ssl/src/ssl_handshake.erl b/lib/ssl/src/ssl_handshake.erl index db21dac942..1929370991 100644 --- a/lib/ssl/src/ssl_handshake.erl +++ b/lib/ssl/src/ssl_handshake.erl @@ -32,10 +32,10 @@ -export([master_secret/4, client_hello/8, server_hello/5, hello/4, hello_request/0, certify/7, certificate/4, - client_certificate_verify/6, certificate_verify/6, + client_certificate_verify/6, certificate_verify/6, verify_signature/5, certificate_request/3, key_exchange/3, server_key_exchange_hash/2, finished/5, verify_connection/6, get_tls_handshake/3, - decode_client_key/3, server_hello_done/0, + decode_client_key/3, decode_server_key/3, server_hello_done/0, encode_handshake/2, init_handshake_history/0, update_handshake_history/2, decrypt_premaster_secret/2, prf/5, next_protocol/1]). @@ -320,25 +320,36 @@ client_certificate_verify(OwnCert, MasterSecret, Version, %% %% Description: Checks that the certificate_verify message is valid. %%-------------------------------------------------------------------- -certificate_verify(Signature, {?'rsaEncryption', PublicKey, _}, Version, - {HashAlgo, _SignAlgo}, MasterSecret, {_, Handshake}) -> - Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake), - case certificate_verify_rsa(Hashes, HashAlgo, Signature, PublicKey, Version) of +certificate_verify(Signature, PublicKeyInfo, Version, + HashSign = {HashAlgo, _}, MasterSecret, {_, Handshake}) -> + Hash = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake), + case verify_signature(Version, Hash, HashSign, Signature, PublicKeyInfo) of true -> valid; _ -> - ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE) - end; -certificate_verify(Signature, {?'id-dsa', PublicKey, PublicKeyParams}, Version, - {HashAlgo, _SignAlgo}, MasterSecret, {_, Handshake}) -> - Hashes = calc_certificate_verify(Version, HashAlgo, MasterSecret, Handshake), - case public_key:verify({digest, Hashes}, sha, Signature, {PublicKey, PublicKeyParams}) of - true -> - valid; - false -> ?ALERT_REC(?FATAL, ?BAD_CERTIFICATE) end. +%%-------------------------------------------------------------------- +-spec verify_signature(tls_version(), binary(), {term(), term()}, binary(), + public_key_info()) -> true | false. +%% +%% Description: Checks that a public_key signature is valid. +%%-------------------------------------------------------------------- +verify_signature(_Version, _Hash, {_HashAlgo, anon}, _Signature, _) -> + true; +verify_signature({3, Minor}, Hash, {HashAlgo, rsa}, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) + when Minor >= 3 -> + public_key:verify({digest, Hash}, HashAlgo, Signature, PubKey); +verify_signature(_Version, Hash, _HashAlgo, Signature, {?rsaEncryption, PubKey, _PubKeyParams}) -> + case public_key:decrypt_public(Signature, PubKey, + [{rsa_pad, rsa_pkcs1_padding}]) of + Hash -> true; + _ -> false + end; +verify_signature(_Version, Hash, {HashAlgo, dsa}, Signature, {?'id-dsa', PublicKey, PublicKeyParams}) -> + public_key:verify({digest, Hash}, HashAlgo, Signature, {PublicKey, PublicKeyParams}). + %%-------------------------------------------------------------------- -spec certificate_request(#connection_states{}, db_handle(), certdb_ref()) -> @@ -382,31 +393,33 @@ key_exchange(client, _Version, {dh, <<?UINT32(Len), PublicKey:Len/binary>>}) -> key_exchange(server, Version, {dh, {<<?UINT32(Len), PublicKey:Len/binary>>, _}, #'DHParameter'{prime = P, base = G}, - {HashAlgo, SignAlgo}, ClientRandom, ServerRandom, PrivateKey}) -> + HashSign, ClientRandom, ServerRandom, PrivateKey}) -> <<?UINT32(_), PBin/binary>> = crypto:mpint(P), <<?UINT32(_), GBin/binary>> = crypto:mpint(G), - PLen = byte_size(PBin), - GLen = byte_size(GBin), - YLen = byte_size(PublicKey), ServerDHParams = #server_dh_params{dh_p = PBin, dh_g = GBin, dh_y = PublicKey}, + enc_server_key_exchange(Version, ServerDHParams, HashSign, + ClientRandom, ServerRandom, PrivateKey). +enc_server_key_exchange(Version, Params, {HashAlgo, SignAlgo}, + ClientRandom, ServerRandom, PrivateKey) -> + EncParams = enc_server_key(Params), case HashAlgo of null -> - #server_key_exchange{params = ServerDHParams, - signed_params = <<>>, - hashsign = {null, anon}}; + #server_key_params{params = Params, + params_bin = EncParams, + hashsign = {null, anon}, + signature = <<>>}; _ -> Hash = server_key_exchange_hash(HashAlgo, <<ClientRandom/binary, - ServerRandom/binary, - ?UINT16(PLen), PBin/binary, - ?UINT16(GLen), GBin/binary, - ?UINT16(YLen), PublicKey/binary>>), - Signed = digitally_signed(Version, Hash, HashAlgo, PrivateKey), - #server_key_exchange{params = ServerDHParams, - signed_params = Signed, - hashsign = {HashAlgo, SignAlgo}} + ServerRandom/binary, + EncParams/binary>>), + Signature = digitally_signed(Version, Hash, HashAlgo, PrivateKey), + #server_key_params{params = Params, + params_bin = EncParams, + hashsign = {HashAlgo, SignAlgo}, + signature = Signature} end. %%-------------------------------------------------------------------- @@ -523,6 +536,15 @@ decode_client_key(ClientKey, Type, Version) -> dec_client_key(ClientKey, key_exchange_alg(Type), Version). %%-------------------------------------------------------------------- +-spec decode_server_key(binary(), key_algo(), tls_version()) -> + #server_key_params{}. +%% +%% Description: Decode server_key data and return appropriate type +%%-------------------------------------------------------------------- +decode_server_key(ServerKey, Type, Version) -> + dec_server_key(ServerKey, key_exchange_alg(Type), Version). + +%%-------------------------------------------------------------------- -spec init_handshake_history() -> tls_handshake_history(). %% @@ -975,31 +997,8 @@ dec_hs(_Version, ?SERVER_HELLO, <<?BYTE(Major), ?BYTE(Minor), Random:32/binary, next_protocol_negotiation = NextProtocolNegotiation}; dec_hs(_Version, ?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>) -> #certificate{asn1_certificates = certs_to_list(ASN1Certs)}; - -dec_hs(_Version, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary, - ?UINT16(GLen), G:GLen/binary, - ?UINT16(YLen), Y:YLen/binary, - ?UINT16(0)>>) -> %% May happen if key_algorithm is dh_anon - #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G, - dh_y = Y}, - signed_params = <<>>, hashsign = {null, anon}}; -dec_hs({Major, Minor}, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary, - ?UINT16(GLen), G:GLen/binary, - ?UINT16(YLen), Y:YLen/binary, - ?BYTE(HashAlgo), ?BYTE(SignAlgo), - ?UINT16(Len), Sig:Len/binary>>) - when Major == 3, Minor >= 3 -> - #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G, - dh_y = Y}, - signed_params = Sig, - hashsign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}}; -dec_hs(_Version, ?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P:PLen/binary, - ?UINT16(GLen), G:GLen/binary, - ?UINT16(YLen), Y:YLen/binary, - ?UINT16(Len), Sig:Len/binary>>) -> - #server_key_exchange{params = #server_dh_params{dh_p = P,dh_g = G, - dh_y = Y}, - signed_params = Sig, hashsign = undefined}; +dec_hs(_Version, ?SERVER_KEY_EXCHANGE, Keys) -> + #server_key_exchange{exchange_keys = Keys}; dec_hs({Major, Minor}, ?CERTIFICATE_REQUEST, <<?BYTE(CertTypesLen), CertTypes:CertTypesLen/binary, ?UINT16(HashSignsLen), HashSigns:HashSignsLen/binary, @@ -1039,6 +1038,42 @@ dec_client_key(<<?UINT16(DH_YLen), DH_Y:DH_YLen/binary>>, ?KEY_EXCHANGE_DIFFIE_HELLMAN, _) -> #client_diffie_hellman_public{dh_public = DH_Y}. +dec_ske_params(Len, Keys, Version) -> + <<Params:Len/bytes, Signature/binary>> = Keys, + dec_ske_signature(Params, Signature, Version). + +dec_ske_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo), + ?UINT16(0)>>, {Major, Minor}) + when Major == 3, Minor >= 3 -> + HashSign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}, + {Params, HashSign, <<>>}; +dec_ske_signature(Params, <<?BYTE(HashAlgo), ?BYTE(SignAlgo), + ?UINT16(Len), Signature:Len/binary>>, {Major, Minor}) + when Major == 3, Minor >= 3 -> + HashSign = {ssl_cipher:hash_algorithm(HashAlgo), ssl_cipher:sign_algorithm(SignAlgo)}, + {Params, HashSign, Signature}; +dec_ske_signature(Params, <<>>, _) -> + {Params, {null, anon}, <<>>}; +dec_ske_signature(Params, <<?UINT16(0)>>, _) -> + {Params, {null, anon}, <<>>}; +dec_ske_signature(Params, <<?UINT16(Len), Signature:Len/binary>>, _) -> + {Params, undefined, Signature}; +dec_ske_signature(_, _, _) -> + throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)). + +dec_server_key(<<?UINT16(PLen), P:PLen/binary, + ?UINT16(GLen), G:GLen/binary, + ?UINT16(YLen), Y:YLen/binary, _/binary>> = KeyStruct, + ?KEY_EXCHANGE_DIFFIE_HELLMAN, Version) -> + Params = #server_dh_params{dh_p = P, dh_g = G, dh_y = Y}, + {BinMsg, HashSign, Signature} = dec_ske_params(PLen + GLen + YLen + 6, KeyStruct, Version), + #server_key_params{params = Params, + params_bin = BinMsg, + hashsign = HashSign, + signature = Signature}; +dec_server_key(_, _, _) -> + throw(?ALERT_REC(?FATAL, ?HANDSHAKE_FAILURE)). + dec_hello_extensions(<<>>) -> []; dec_hello_extensions(<<?UINT16(ExtLen), Extensions:ExtLen/binary>>) -> @@ -1156,18 +1191,12 @@ enc_hs(#certificate{asn1_certificates = ASN1CertList}, _Version) -> ASN1Certs = certs_from_list(ASN1CertList), ACLen = erlang:iolist_size(ASN1Certs), {?CERTIFICATE, <<?UINT24(ACLen), ASN1Certs:ACLen/binary>>}; -enc_hs(#server_key_exchange{params = #server_dh_params{ - dh_p = P, dh_g = G, dh_y = Y}, - signed_params = SignedParams, hashsign = HashSign}, Version) -> - PLen = byte_size(P), - GLen = byte_size(G), - YLen = byte_size(Y), - Signature = enc_sign(HashSign, SignedParams, Version), - {?SERVER_KEY_EXCHANGE, <<?UINT16(PLen), P/binary, - ?UINT16(GLen), G/binary, - ?UINT16(YLen), Y/binary, - Signature/binary>> - }; +enc_hs(#server_key_exchange{exchange_keys = Keys}, _Version) -> + {?SERVER_KEY_EXCHANGE, Keys}; +enc_hs(#server_key_params{params_bin = Keys, hashsign = HashSign, + signature = Signature}, Version) -> + EncSign = enc_sign(HashSign, Signature, Version), + {?SERVER_KEY_EXCHANGE, <<Keys/binary, EncSign/binary>>}; enc_hs(#certificate_request{certificate_types = CertTypes, hashsign_algorithms = #hash_sign_algos{hash_sign_algos = HashSignAlgos}, certificate_authorities = CertAuths}, @@ -1211,6 +1240,14 @@ enc_cke(#client_diffie_hellman_public{dh_public = DHPublic}, _) -> Len = byte_size(DHPublic), <<?UINT16(Len), DHPublic/binary>>. +enc_server_key(#server_dh_params{dh_p = P, dh_g = G, dh_y = Y}) -> + PLen = byte_size(P), + GLen = byte_size(G), + YLen = byte_size(Y), + <<?UINT16(PLen), P/binary, ?UINT16(GLen), G/binary, ?UINT16(YLen), Y/binary>>. + +enc_sign({_, anon}, _Sign, _Version) -> + <<>>; enc_sign({HashAlg, SignAlg}, Signature, _Version = {Major, Minor}) when Major == 3, Minor >= 3-> SignLen = byte_size(Signature), @@ -1328,8 +1365,8 @@ certificate_authorities_from_db(CertDbHandle, CertDbRef) -> digitally_signed({3, Minor}, Hash, HashAlgo, Key) when Minor >= 3 -> public_key:sign({digest, Hash}, HashAlgo, Key); -digitally_signed(_Version, Hash, _HashAlgo, #'DSAPrivateKey'{} = Key) -> - public_key:sign({digest, Hash}, sha, Key); +digitally_signed(_Version, Hash, HashAlgo, #'DSAPrivateKey'{} = Key) -> + public_key:sign({digest, Hash}, HashAlgo, Key); digitally_signed(_Version, Hash, _HashAlgo, #'RSAPrivateKey'{} = Key) -> public_key:encrypt_private(Hash, Key, [{rsa_pad, rsa_pkcs1_padding}]). @@ -1378,19 +1415,6 @@ apply_user_fun(Fun, OtpCert, ExtensionOrError, UserState0, SslState) -> {unknown, {SslState, UserState}} end. -certificate_verify_rsa(Hashes, sha, Signature, PublicKey, {Major, Minor}) - when Major == 3, Minor >= 3 -> - public_key:verify({digest, Hashes}, sha, Signature, PublicKey); -certificate_verify_rsa(Hashes, HashAlgo, Signature, PublicKey, {Major, Minor}) - when Major == 3, Minor >= 3 -> - public_key:verify({digest, Hashes}, HashAlgo, Signature, PublicKey); -certificate_verify_rsa(Hashes, _HashAlgo, Signature, PublicKey, _Version) -> - case public_key:decrypt_public(Signature, PublicKey, - [{rsa_pad, rsa_pkcs1_padding}]) of - Hashes -> true; - _ -> false - end. - -define(TLSEXT_SIGALG_RSA(MD), {MD, rsa}). -define(TLSEXT_SIGALG_DSA(MD), {MD, dsa}). diff --git a/lib/ssl/src/ssl_handshake.hrl b/lib/ssl/src/ssl_handshake.hrl index 9af6511d68..2414d5b666 100644 --- a/lib/ssl/src/ssl_handshake.hrl +++ b/lib/ssl/src/ssl_handshake.hrl @@ -141,9 +141,14 @@ }). -record(server_key_exchange, { + exchange_keys + }). + +-record(server_key_params, { params, %% #server_rsa_params{} | #server_dh_params{} - signed_params, %% #signature{} - hashsign %% term(atom(), atom()) + params_bin, + hashsign, %% term(atom(), atom()) + signature %% #signature{} }). %% enum { anonymous, rsa, dsa } SignatureAlgorithm; diff --git a/lib/ssl/src/ssl_manager.erl b/lib/ssl/src/ssl_manager.erl index 13689ce7d8..aa9da65bb8 100644 --- a/lib/ssl/src/ssl_manager.erl +++ b/lib/ssl/src/ssl_manager.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2007-2012. All Rights Reserved. +%% Copyright Ericsson AB 2007-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -142,8 +142,15 @@ lookup_trusted_cert(DbHandle, Ref, SerialNumber, Issuer) -> new_session_id(Port) -> call({new_session_id, Port}). +%%-------------------------------------------------------------------- +-spec clean_cert_db(reference(), binary()) -> ok. +%% +%% Description: Send clean request of cert db to ssl_manager process should +%% be called by ssl-connection processes. +%%-------------------------------------------------------------------- clean_cert_db(Ref, File) -> - erlang:send_after(?CLEAN_CERT_DB, self(), {clean_cert_db, Ref, File}). + erlang:send_after(?CLEAN_CERT_DB, get(ssl_manager), {clean_cert_db, Ref, File}), + ok. %%-------------------------------------------------------------------- -spec register_session(inet:port_number(), #session{}) -> ok. @@ -320,19 +327,12 @@ handle_info(clear_pem_cache, #state{certificate_db = [_,_,PemChace]} = State) -> handle_info({clean_cert_db, Ref, File}, #state{certificate_db = [CertDb,RefDb, PemCache]} = State) -> - case ssl_certificate_db:ref_count(Ref, RefDb, 0) of - 0 -> - MD5 = crypto:md5(File), - case ssl_certificate_db:lookup_cached_pem(PemCache, MD5) of - [{Content, Ref}] -> - ssl_certificate_db:insert(MD5, Content, PemCache); - undefined -> - ok - end, - ssl_certificate_db:remove(Ref, RefDb), - ssl_certificate_db:remove_trusted_certs(Ref, CertDb); + + case ssl_certificate_db:lookup(Ref, RefDb) of + undefined -> %% Alredy cleaned + ok; _ -> - ok + clean_cert_db(Ref, CertDb, RefDb, PemCache, File) end, {noreply, State}; @@ -345,7 +345,7 @@ handle_info(_Info, State) -> {noreply, State}. %%-------------------------------------------------------------------- --spec terminate(reason(), #state{}) -> term(). +-spec terminate(reason(), #state{}) -> ok. %% %% Description: This function is called by a gen_server when it is about to %% terminate. It should be the opposite of Module:init/1 and do any necessary @@ -464,3 +464,19 @@ new_id(Port, Tries, Cache, CacheCb) -> _ -> new_id(Port, Tries - 1, Cache, CacheCb) end. + +clean_cert_db(Ref, CertDb, RefDb, PemCache, File) -> + case ssl_certificate_db:ref_count(Ref, RefDb, 0) of + 0 -> + MD5 = crypto:md5(File), + case ssl_certificate_db:lookup_cached_pem(PemCache, MD5) of + [{Content, Ref}] -> + ssl_certificate_db:insert(MD5, Content, PemCache); + _ -> + ok + end, + ssl_certificate_db:remove(Ref, RefDb), + ssl_certificate_db:remove_trusted_certs(Ref, CertDb); + _ -> + ok + end. diff --git a/lib/ssl/src/ssl_tls_dist_proxy.erl b/lib/ssl/src/ssl_tls_dist_proxy.erl index a8476b104f..a22af6b960 100644 --- a/lib/ssl/src/ssl_tls_dist_proxy.erl +++ b/lib/ssl/src/ssl_tls_dist_proxy.erl @@ -1,7 +1,7 @@ %% %% %CopyrightBegin% %% -%% Copyright Ericsson AB 2011-2012. All Rights Reserved. +%% Copyright Ericsson AB 2011-2013. All Rights Reserved. %% %% The contents of this file are subject to the Erlang Public License, %% Version 1.1, (the "License"); you may not use this file except in @@ -89,7 +89,7 @@ handle_call({connect, Ip, Port}, {From, _}, State) -> ok -> flush_old_controller(From, Socket), {reply, Res, State} - end; + end; {Pid, Error} -> {reply, Error, State} end; @@ -115,13 +115,13 @@ code_change(_OldVsn, St, _Extra) -> get_tcp_address(Socket) -> case inet:sockname(Socket) of {ok, Address} -> - {ok, Host} = inet:gethostname(), + {ok, Host} = inet:gethostname(), NetAddress = #net_address{ - address = Address, - host = Host, - protocol = proxy, - family = inet - }, + address = Address, + host = Host, + protocol = proxy, + family = inet + }, {ok, NetAddress}; {error, _} = Error -> Error end. @@ -129,17 +129,17 @@ get_tcp_address(Socket) -> accept_loop(Proxy, erts = Type, Listen, Extra) -> process_flag(priority, max), case gen_tcp:accept(Listen) of - {ok, Socket} -> - Extra ! {accept,self(),Socket,inet,proxy}, - receive - {_Kernel, controller, Pid} -> - ok = gen_tcp:controlling_process(Socket, Pid), - flush_old_controller(Pid, Socket), - Pid ! {self(), controller}; - {_Kernel, unsupported_protocol} -> - exit(unsupported_protocol) - end; - Error -> + {ok, Socket} -> + Extra ! {accept,self(),Socket,inet,proxy}, + receive + {_Kernel, controller, Pid} -> + ok = gen_tcp:controlling_process(Socket, Pid), + flush_old_controller(Pid, Socket), + Pid ! {self(), controller}; + {_Kernel, unsupported_protocol} -> + exit(unsupported_protocol) + end; + Error -> exit(Error) end, accept_loop(Proxy, Type, Listen, Extra); @@ -242,7 +242,7 @@ loop_conn(World, Erts) -> ssl:close(World); {ssl_closed, World} -> gen_tcp:close(Erts) - end. + end. get_ssl_options(Type) -> case init:get_argument(ssl_dist_opt) of @@ -255,7 +255,7 @@ get_ssl_options(Type) -> ssl_options(_,[]) -> []; ssl_options(server, ["client_" ++ _, _Value |T]) -> - ssl_options(server,T); + ssl_options(server,T); ssl_options(client, ["server_" ++ _, _Value|T]) -> ssl_options(client,T); ssl_options(server, ["server_certfile", Value|T]) -> @@ -265,7 +265,7 @@ ssl_options(client, ["client_certfile", Value | T]) -> ssl_options(server, ["server_cacertfile", Value|T]) -> [{cacertfile, Value} | ssl_options(server,T)]; ssl_options(client, ["client_cacertfile", Value|T]) -> - [{cacertfile, Value} | ssl_options(client,T)]; + [{cacertfile, Value} | ssl_options(client,T)]; ssl_options(server, ["server_keyfile", Value|T]) -> [{keyfile, Value} | ssl_options(server,T)]; ssl_options(client, ["client_keyfile", Value|T]) -> @@ -277,7 +277,7 @@ ssl_options(client, ["client_password", Value|T]) -> ssl_options(server, ["server_verify", Value|T]) -> [{verify, atomize(Value)} | ssl_options(server,T)]; ssl_options(client, ["client_verify", Value|T]) -> - [{verify, atomize(Value)} | ssl_options(client,T)]; + [{verify, atomize(Value)} | ssl_options(client,T)]; ssl_options(server, ["server_reuse_sessions", Value|T]) -> [{reuse_sessions, atomize(Value)} | ssl_options(server,T)]; ssl_options(client, ["client_reuse_sessions", Value|T]) -> @@ -295,11 +295,11 @@ ssl_options(server, ["server_hibernate_after", Value|T]) -> ssl_options(client, ["client_hibernate_after", Value|T]) -> [{hibernate_after, list_to_integer(Value)} | ssl_options(client,T)]; ssl_options(server, ["server_ciphers", Value|T]) -> - [{ciphers, Value} | ssl_options(server,T)]; + [{ciphers, Value} | ssl_options(server,T)]; ssl_options(client, ["client_ciphers", Value|T]) -> [{ciphers, Value} | ssl_options(client,T)]; ssl_options(server, ["server_dhfile", Value|T]) -> - [{dhfile, Value} | ssl_options(server,T)]; + [{dhfile, Value} | ssl_options(server,T)]; ssl_options(server, ["server_fail_if_no_peer_cert", Value|T]) -> [{fail_if_no_peer_cert, atomize(Value)} | ssl_options(server,T)]; ssl_options(_,_) -> diff --git a/lib/ssl/test/ssl_basic_SUITE.erl b/lib/ssl/test/ssl_basic_SUITE.erl index f206276b69..7067cd861d 100644 --- a/lib/ssl/test/ssl_basic_SUITE.erl +++ b/lib/ssl/test/ssl_basic_SUITE.erl @@ -84,7 +84,8 @@ basic_tests() -> alerts, send_close, connect_twice, - connect_dist + connect_dist, + clear_pem_cache ]. options_tests() -> @@ -536,6 +537,33 @@ connect_dist(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- + +clear_pem_cache() -> + [{doc,"Test that internal reference tabel is cleaned properly even when " + " the PEM cache is cleared" }]. +clear_pem_cache(Config) when is_list(Config) -> + {status, _, _, StatusInfo} = sys:get_status(whereis(ssl_manager)), + [_, _,_, _, Prop] = StatusInfo, + State = ssl_test_lib:state(Prop), + [_,FilRefDb, _] = element(5, State), + {Server, Client} = basic_verify_test_no_close(Config), + 2 = ets:info(FilRefDb, size), + ssl:clear_pem_cache(), + _ = sys:get_status(whereis(ssl_manager)), + {Server1, Client1} = basic_verify_test_no_close(Config), + 4 = ets:info(FilRefDb, size), + ssl_test_lib:close(Server), + ssl_test_lib:close(Client), + ct:sleep(5000), + _ = sys:get_status(whereis(ssl_manager)), + 2 = ets:info(FilRefDb, size), + ssl_test_lib:close(Server1), + ssl_test_lib:close(Client1), + ct:sleep(5000), + _ = sys:get_status(whereis(ssl_manager)), + 0 = ets:info(FilRefDb, size). + +%%-------------------------------------------------------------------- peername() -> [{doc,"Test API function peername/1"}]. @@ -1567,8 +1595,8 @@ default_reject_anonymous(Config) when is_list(Config) -> [{ciphers,[Cipher]} | ClientOpts]}]), - ssl_test_lib:check_result(Server, {error, "insufficient security"}, - Client, {error, "insufficient security"}). + ssl_test_lib:check_result(Server, {error, {essl, "insufficient security"}}, + Client, {error, {essl, "insufficient security"}}). %%-------------------------------------------------------------------- reuse_session() -> @@ -2641,6 +2669,26 @@ tcp_send_recv_result(Socket) -> {ok,"Hello world"} = gen_tcp:recv(Socket, 11), ok. +basic_verify_test_no_close(Config) -> + ClientOpts = ?config(client_verification_opts, Config), + ServerOpts = ?config(server_verification_opts, 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, send_recv_result_active, []}}, + {options, ServerOpts}]), + 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, send_recv_result_active, []}}, + {options, ClientOpts}]), + + ssl_test_lib:check_result(Server, ok, Client, ok), + {Server, Client}. + basic_test(Config) -> ClientOpts = ?config(client_opts, Config), ServerOpts = ?config(server_opts, Config), @@ -2659,7 +2707,6 @@ basic_test(Config) -> {options, ClientOpts}]), ssl_test_lib:check_result(Server, ok, Client, ok), - ssl_test_lib:close(Server), ssl_test_lib:close(Client). diff --git a/lib/ssl/test/ssl_certificate_verify_SUITE.erl b/lib/ssl/test/ssl_certificate_verify_SUITE.erl index 9677d98c1b..86e1d47be7 100644 --- a/lib/ssl/test/ssl_certificate_verify_SUITE.erl +++ b/lib/ssl/test/ssl_certificate_verify_SUITE.erl @@ -252,8 +252,8 @@ server_require_peer_cert_fail(Config) when is_list(Config) -> {from, self()}, {options, [{active, false} | BadClientOpts]}]), - ssl_test_lib:check_result(Server, {error, esslaccept}, - Client, {error, esslconnect}). + ssl_test_lib:check_result(Server, {error, {essl, "handshake failure"}}, + Client, {error, {essl, "handshake failure"}}). %%-------------------------------------------------------------------- @@ -293,14 +293,14 @@ verify_fun_always_run_client(Config) when is_list(Config) -> [{verify, verify_peer}, {verify_fun, FunAndState} | ClientOpts]}]), - %% Server error may be esslaccept or closed depending on timing + %% Server error may be {essl,"handshake failure"} or closed depending on timing %% this is not a bug it is a circumstance of how tcp works! receive {Server, ServerError} -> ct:print("Server Error ~p~n", [ServerError]) end, - ssl_test_lib:check_result(Client, {error, esslconnect}). + ssl_test_lib:check_result(Client, {error, {essl, "handshake failure"}}). %%-------------------------------------------------------------------- verify_fun_always_run_server() -> @@ -342,14 +342,14 @@ verify_fun_always_run_server(Config) when is_list(Config) -> [{verify, verify_peer} | ClientOpts]}]), - %% Client error may be esslconnect or closed depending on timing + %% Client error may be {essl, "handshake failure" } or closed depending on timing %% this is not a bug it is a circumstance of how tcp works! receive {Client, ClientError} -> ct:print("Client Error ~p~n", [ClientError]) end, - ssl_test_lib:check_result(Server, {error, esslaccept}). + ssl_test_lib:check_result(Server, {error, {essl, "handshake failure"}}). %%-------------------------------------------------------------------- @@ -380,7 +380,7 @@ client_verify_none_passive(Config) when is_list(Config) -> ssl_test_lib:close(Client). %%-------------------------------------------------------------------- cert_expired() -> - [{doc,"Test server with invalid signature"}]. + [{doc,"Test server with expired certificate"}]. cert_expired(Config) when is_list(Config) -> ClientOpts = ?config(client_verification_opts, Config), @@ -432,8 +432,8 @@ cert_expired(Config) when is_list(Config) -> {from, self()}, {options, [{verify, verify_peer} | ClientOpts]}]), - ssl_test_lib:check_result(Server, {error, "certificate expired"}, - Client, {error, "certificate expired"}). + ssl_test_lib:check_result(Server, {error, {essl, "certificate expired"}}, + Client, {error, {essl, "certificate expired"}}). two_digits_str(N) when N < 10 -> lists:flatten(io_lib:format("0~p", [N])); @@ -679,7 +679,7 @@ delete_authority_key_extension([Head | Rest], Acc) -> %%-------------------------------------------------------------------- invalid_signature_server() -> - [{doc,"Test server with invalid signature"}]. + [{doc,"Test client with invalid signature"}]. invalid_signature_server(Config) when is_list(Config) -> ClientOpts = ?config(client_verification_opts, Config), @@ -710,8 +710,8 @@ invalid_signature_server(Config) when is_list(Config) -> {from, self()}, {options, [{verify, verify_peer} | ClientOpts]}]), - tcp_delivery_workaround(Server, {error, "bad certificate"}, - Client, {error,"bad certificate"}). + tcp_delivery_workaround(Server, {error, {essl, "bad certificate"}}, + Client, {error, {essl, "bad certificate"}}). %%-------------------------------------------------------------------- @@ -747,8 +747,8 @@ invalid_signature_client(Config) when is_list(Config) -> {from, self()}, {options, NewClientOpts}]), - tcp_delivery_workaround(Server, {error, "bad certificate"}, - Client, {error,"bad certificate"}). + tcp_delivery_workaround(Server, {error, {essl, "bad certificate"}}, + Client, {error, {essl, "bad certificate"}}). %%-------------------------------------------------------------------- @@ -829,8 +829,8 @@ unknown_server_ca_fail(Config) when is_list(Config) -> {verify_fun, FunAndState} | ClientOpts]}]), - ssl_test_lib:check_result(Server, {error,"unknown ca"}, - Client, {error, "unknown ca"}). + ssl_test_lib:check_result(Server, {error, {essl, "unknown ca"}}, + Client, {error, {essl, "unknown ca"}}). %%-------------------------------------------------------------------- unknown_server_ca_accept_verify_none() -> @@ -947,10 +947,6 @@ tcp_delivery_workaround(Server, ServerMsg, Client, ClientMsg) -> {Client, {error,closed}} -> server_msg(Server, ServerMsg); {Server, {error,closed}} -> - client_msg(Client, ClientMsg); - {Client, {error, esslconnect}} -> - server_msg(Server, ServerMsg); - {Server, {error, esslaccept}} -> client_msg(Client, ClientMsg) end. @@ -961,8 +957,8 @@ client_msg(Client, ClientMsg) -> {Client, {error,closed}} -> ct:print("client got close"), ok; - {Client, {error, esslconnect}} -> - ct:print("client got econnaborted"), + {Client, {error, Reason}} -> + ct:print("client got econnaborted: ~p", [Reason]), ok; Unexpected -> ct:fail(Unexpected) @@ -974,8 +970,8 @@ server_msg(Server, ServerMsg) -> {Server, {error,closed}} -> ct:print("server got close"), ok; - {Server, {error, esslaccept}} -> - ct:print("server got econnaborted"), + {Server, {error, Reason}} -> + ct:print("server got econnaborted: ~p", [Reason]), ok; Unexpected -> ct:fail(Unexpected) diff --git a/lib/ssl/test/ssl_test_lib.erl b/lib/ssl/test/ssl_test_lib.erl index e6f71183c7..8d96a70a6e 100644 --- a/lib/ssl/test/ssl_test_lib.erl +++ b/lib/ssl/test/ssl_test_lib.erl @@ -115,7 +115,7 @@ connect(#sslsocket{} = ListenSocket, Opts) -> end; connect(ListenSocket, Opts) -> Node = proplists:get_value(node, Opts), - ct:format("gen_tcp:accept(~p)~n", [ListenSocket]), + ct:print("gen_tcp:accept(~p)~n", [ListenSocket]), {ok, AcceptSocket} = rpc:call(Node, gen_tcp, accept, [ListenSocket]), AcceptSocket. @@ -203,6 +203,67 @@ close(Pid) -> ct:print("Pid: ~p down due to:~p ~n", [Pid, Reason]) end. + +check_result(Server, {error, SReason} = ServerMsg, Client, {error, closed} = ClientMsg) -> + receive + {Server, {error, {SReason, _}}} -> + receive + {Client, ClientMsg} -> + ok; + Unexpected -> + Reason = {{expected, {Client, ClientMsg}}, + {got, Unexpected}}, + ct:fail(Reason) + end; + {Client, ClientMsg} -> + receive + {Server, {error, {SReason, _}}} -> + ok; + Unexpected -> + Reason = {{expected, {Server,{error, {SReason, 'term()'}}}, + {got, Unexpected}}}, + ct:fail(Reason) + end; + {Port, {data,Debug}} when is_port(Port) -> + io:format("openssl ~s~n",[Debug]), + check_result(Server, ServerMsg, Client, ClientMsg); + + Unexpected -> + Reason = {{expected, {Client, ClientMsg}}, + {expected, {Server, {error, {SReason, 'term()'}}}, {got, Unexpected}}}, + ct:fail(Reason) + end; + +check_result(Server, {error, closed} = ServerMsg, Client, {error, CReson} = ClientMsg) -> + receive + {Server, ServerMsg} -> + receive + {Client, {error, {CReson, _}}} -> + ok; + Unexpected -> + Reason = {{expected, {Client, {error, {CReson, 'term()'}}}, + {got, Unexpected}}}, + ct:fail(Reason) + end; + {Client, {error, {CReson, _}}} -> + receive + {Server, ServerMsg} -> + ok; + Unexpected -> + Reason = {{expected, {Server, ServerMsg}}, + {got, Unexpected}}, + ct:fail(Reason) + end; + {Port, {data,Debug}} when is_port(Port) -> + io:format("openssl ~s~n",[Debug]), + check_result(Server, ServerMsg, Client, ClientMsg); + + Unexpected -> + Reason = {{expected, {Client, {error, {CReson, 'term()'}}}, + {expected, {Server, ServerMsg}}, {got, Unexpected}}}, + ct:fail(Reason) + end; + check_result(Server, ServerMsg, Client, ClientMsg) -> receive {Server, ServerMsg} -> @@ -233,6 +294,22 @@ check_result(Server, ServerMsg, Client, ClientMsg) -> ct:fail(Reason) end. +check_result(Pid, {error, Reason} = Err) when Reason == ecertfile; + Reason == ecacertfile; + Reason == ekeyfile; + Reason == edhfile -> + receive + {Pid, {error, {Reason, Str}}} when is_list(Str) -> + ok; + {Port, {data,Debug}} when is_port(Port) -> + io:format("openssl ~s~n",[Debug]), + check_result(Pid, Err); + Unexpected -> + Reason = {{expected, {Pid, {error, {Reason, "'appropriate error string'"}}}}, + {got, Unexpected}}, + ct:fail(Reason) + end; + check_result(Pid, Msg) -> receive {Pid, Msg} -> @@ -542,7 +619,7 @@ run_server_error(Opts) -> {ok, ListenSocket} -> Pid ! {listen, up}, send_selected_port(Pid, Port, ListenSocket), - ct:format("~p:accept(~p)~n", [Transport, ListenSocket]), + ct:print("~p:accept(~p)~n", [Transport, ListenSocket]), case rpc:call(Node, Transport, accept, [ListenSocket]) of {error, _} = Error -> Pid ! {self(), Error} diff --git a/lib/ssl/test/ssl_to_openssl_SUITE.erl b/lib/ssl/test/ssl_to_openssl_SUITE.erl index d5e7d515fd..7c0c00bf36 100644 --- a/lib/ssl/test/ssl_to_openssl_SUITE.erl +++ b/lib/ssl/test/ssl_to_openssl_SUITE.erl @@ -902,7 +902,7 @@ ssl2_erlang_server_openssl_client(Config) when is_list(Config) -> ok end, - ssl_test_lib:check_result(Server, {error,"protocol version"}), + ssl_test_lib:check_result(Server, {error, {essl, "protocol version"}}), process_flag(trap_exit, false). %%-------------------------------------------------------------------- diff --git a/lib/ssl/vsn.mk b/lib/ssl/vsn.mk index adfb29e639..cb73e86ede 100644 --- a/lib/ssl/vsn.mk +++ b/lib/ssl/vsn.mk @@ -1 +1 @@ -SSL_VSN = 5.1.2 +SSL_VSN = 5.2 |