Delphi – Indy 10 and OpenSSL

delphidelphi-xe2indyindy10ssl

I have recently upgraded my Delphi 7 to Delphi XE2 and I'm kinda new to it. I used Indy 10 with OpenSSL to receive HTTP Content. It works just fine and I would like to share my program with with other people. I just found out that my programs won't work on other PCs without the OpenSSL Libraries. I didn't even get an exception, error, etc. of missing DLL files. I thought Indy10 has either native SSL support or at least uses the DLLs from resources after compiling, so it would be portable. I have 2 questions:

1) How could I let the user know that he/she is missing the OpenSSL Libraries? (Friends of mine reported no exception, errors, etc. WITHOUT the OpenSSL DLLs.)

2) Is it possible to let Indy10 read the OpenSSL Libraries from resources?

Best Solution

Indy does not implement SSL natively. What it does is implements a flexible IOHandler architecture that allows for any SSL implementation to be plugged into Indy. Indy itself implements its own IOHandler class that is based on OpenSSL (MS CryptoAPI support is planned for the future). SecureBlackbox, for example, provides an Indy IOHandler class for its own SSL engine.

On most platforms, OpenSSL is used via external DLLs, which cannot be used from resources. Indy does not ship with OpenSSL DLLs, because OpenSSL encryption is restricted by international import/export laws, so either OS vendors that ship internationally have special licenses to ship OpenSSL DLLs, or end-users have to download/compile OpenSSL themselves locally. That is what makes Indy "portable" when it comes to OpenSSL - Indy uses whatever OpenSSL DLLs are pre-installed outside of Indy, either in the OS or in your app's own installation folder.

The only exception to this that concerns Indy is OpenSSL on iOS, which requires OpenSSL to be used statically because third-party dynamic libraries are not allowed on iOS devices.

If you want to use OpenSSL statically with Indy on other platforms, you have to compile/obtain the static version of OpenSSL yourself and add it to your project, then recompile Indy to enable its STATICLOAD_OPENSSL define (which is currently only defined for iOS), and finally include the IdSSLOpenSSLHeaders_static.pas unit in your code's uses clause to hook up the necessary support code. Note that this is supported only in the recently released Indy 10.6 version.

If that is too much work for you, then use a third-party SSL implementation that is compatible with Indy, such as SecureBlackbox, or write your own IOHandler class that does what you need.

As for your other questions:

1) Indy does raise exceptions if it cannot load OpenSSL correctly during socket operations. So chances are those exceptions are getting caught and swallowed before you have a chance to report them to your users. If you don't want to rely on that, then you can manually call Indy's Load() function in the IdSSLOpenSSLHeaders.pas unit before starting your socket work. Load() will load OpenSSL into memory if it is not already loaded. If Load() fails, you can then call the WhichFailedToLoad() function in that same unit to find out why Load() failed.

2) No, it is not possible to use OpenSSL from resources (without some really serious low-level trickery).

Related Question