IndySockets / Indy

Indy - Internet Direct
https://www.indyproject.org
434 stars 147 forks source link

Proposed Update to support OpenSSL 3.x and earlier versions #529

Open MWASoftware opened 3 months ago

MWASoftware commented 3 months ago

This pull request includes work performed by @mezen in developing a version of Indy supporting OpenSSL 1.1.1. This version is intended to overcome two criticisms of @mezen's update: The first is that the proposal for 1.1.1 did not use the existing Indy OpenSSL classes. The second is that Openssl 3.x was not yet supported.

This pull request has taken @mezen's new openssl loader, and intermediate code OpenSSL header files, added Pascal versions of additional OpenSSL header files (e.g. for DES support) and a new code processor (a sed script) to process the intermediate code into usable unit files. With a few mods to IdSSLOpenSSL, the result supports OpenSSL 1.0.2, 1.1.1 and 3.x and probably works with earlier versions - but not tested.

The IdSSLOpenSSL components are unchanged except for the addition of two useful properties:

There are also some low level changes to handle the change to opaque data structures (e.g. SSL_CTX) in 1.1.1 and 3.x.

Note that the IdSSLOpenSSLHeaders.pas and IdSSLOpenSSLHeaders_static.pas units have been removed and have been replaced by the header files in Lib/Protocols/opensslHdrs. The new header files are intended to have a one-to-one correspondence with the OpenSSL header (.h) files.

Three link models are supported.

This version has been tested on both Windows and Linux with both Lazarus/FPC (3.2.2) and Delphi (Berlin 32 bit only). There are two test programs used for validation:

Hopefully the result will be found useful.

Please read README.OpenSSL for further information on the update.

NOTES FOR USING THE TEST PROGRAMS

The directory Test/OpenSSL contains the two test programs together with a README giving more details on their use. They are intended to run "standalone". That is without having to integrate Indy into the IDE. There are variants for both Delphi and Lazarus/fpc.

Note: when testing under Windows, if there are no default OpenSSL dlls in the search path then you will either need to copy libssl and libcrypto into the project folder or add a command line parameter providing the location of the OpenSSL dlls.

NOTES FOR LAZARUS/FPC

Please try out the test programs before following the instructions below.

Before trying out the update with your own programs, you should run the script:

These scripts are intended to extract the files relevant to Lazarus/FPC to another directory and to place the Lazarus package files in the destination directory itself. By default the scripts extract the files to:

$HOME/Indy (Linux) "%homedrive%%homepath%"\Indy (Windows)

To override the default, provide the target directory as the only command line argument for the script. There is no need for the target directory to exist before running the script.

After running the script, you should read the file README.lazarus-fpc for further guidance.

Note that you must ensure that any existing Lazarus project that you test this update with, includes the indyprotocols run time package in the requirements list.

NOTES FOR DELPHI USERS

Integration with the Delphi IDE is tbd and needs someone to take this on. That is there is a need to update the Delphi package definitions, but otherwise, the update should work with Delphi.

baka0815 commented 2 months ago

I'm creating my server with the following options:

  LIOHandleSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
  LIOHandleSSL.SSLOptions.Method := sslvTLSv1_2;
  LIOHandleSSL.SSLOptions.Mode := sslmServer;

However the connection via Firefox is still established as TLS v1.3 (TLS_AES_1128_GCM_SHA256, 128-Bit-Key, TLS 1.3).

Also cURL can connect via --tlsv1.1, --tlsv1.2 and --tlsv1.3, even if I only allow TLS 1.0 or 1.1.

  LIOHandleSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1];
  LIOHandleSSL.SSLOptions.Method := sslvTLSv1_1;
  LIOHandleSSL.SSLOptions.Mode := sslmServer;
baka0815 commented 2 months ago

Loading the legacy OpenSSL 1.0.2 DLLs fails for me with the following function not being present: EVP_md2

Is this expected or should this be added to LegacyAllowFailed?

MWASoftware commented 2 months ago

I'm creating my server with the following options:

  LIOHandleSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
  LIOHandleSSL.SSLOptions.Method := sslvTLSv1_2;
  LIOHandleSSL.SSLOptions.Mode := sslmServer;

However the connection via Firefox is still established as TLS v1.3 (TLS_AES_1128_GCM_SHA256, 128-Bit-Key, TLS 1.3).

Also cURL can connect via --tlsv1.1, --tlsv1.2 and --tlsv1.3, even if I only allow TLS 1.0 or 1.1.

  LIOHandleSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1];
  LIOHandleSSL.SSLOptions.Method := sslvTLSv1_1;
  LIOHandleSSL.SSLOptions.Mode := sslmServer;

In the README.OpenSSL.txt I have noted a typo when I said that "SSLOptions.Mode" is ignored. I meant "SLLOptions.Method" is ignored. "SSLOptions.Versions" is now the only means of control over which version is supported. The README does state that this determines in the minimum version only. This was intentional. On thinking about it, perhaps it should also determined the maximum supported. I will update.

MWASoftware commented 2 months ago

In the README.OpenSSL.txt I have noted a typo when I said that "SSLOptions.Mode" is ignored. I meant "SLLOptions.Method" is ignored. "SSLOptions.Versions" is now the only means of control over which version is supported. The README does state that this determines in the minimum version only. This was intentional. On thinking about it, perhaps it should also determined the maximum supported. I will update.

Both the README and the code have been updated (and tested), and pushed to github. As the update log says "SSLOptions.SSLVersions can now be used to select both the minimum and maximum versions of the TLS Protocol negotiated for OpenSSLVersions 1.1.0 and later. OpenSSL will always try to negotiate the highest version acceptable to both ends of the session."

baka0815 commented 2 months ago

Thanks for the change @MWASoftware and the work you're putting into this! I will take a look at the changes later on.

Loading the legacy OpenSSL 1.0.2 DLLs fails for me with the following function not being present: EVP_md2

Is this expected or should this be added to LegacyAllowFailed?

Any comments regarding this? I'm using the pre-compiled OpenSSL library from https://indy.fulgan.com/SSL/ (1.0.2u)

MWASoftware commented 2 months ago

Thanks for the change @MWASoftware and the work you're putting into this! I will take a look at the changes later on.

Loading the legacy OpenSSL 1.0.2 DLLs fails for me with the following function not being present: EVP_md2 Is this expected or should this be added to LegacyAllowFailed?

Any comments regarding this? I'm using the pre-compiled OpenSSL library from https://indy.fulgan.com/SSL/ (1.0.2u)

See NewLibLoadStrategy branch and response to earlier comment.