Skip to content

Commit 485b478

Browse files
committed
Extension of IOpenSSLDLL interface plus documentation
1 parent 389a488 commit 485b478

File tree

2 files changed

+366
-6
lines changed

2 files changed

+366
-6
lines changed

README.OpenSSL

Lines changed: 305 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,305 @@
1+
This "proposed update" to IndySockets/Indy adds support for OpenSSL 3.0 and
2+
later to Indy. Both Delphi and Lazarus/fpc are fully supported by this source code tree.
3+
4+
This provides a new (optional) OpenSSL package separate from Indy's "protocols" package
5+
and adds support for OpenSSL 3.0 and later. Both Delphi and Lazarus/fpc are fully
6+
supported by this source code tree.
7+
8+
Three link models are supported.
9+
* Dynamic Library Load (the default and the approach used in previous versions)
10+
* compile time linkage to a shared (.so or .dll) library (OpenSSL 3.x only)
11+
* compile time linkage to a static library (FPC only with gcc compiled OpenSSL).
12+
13+
For dynamic library load, a "Just in Time" approach is used where each API call is initialised to a local proc "loader" function.
14+
The intent is that on the first call a given API function, the actual entry point in the OpenSSL function
15+
is loaded and the API call is set to the loaded entry point. The API function is now called on the user's
16+
behalf. If the call fails to load then it is replaced by a compatibility function (if one exists). If none exists
17+
then an exception is raised. If an API function is allowed to be nil (as set in the template), then the function
18+
is loaded at library load time.
19+
20+
21+
The updated package has been tested under the following scenarios:
22+
23+
1. Static Linking to Static Library (Lazarus/Linux only with gcc generated libssl.a and libcrypto.a).
24+
25+
2. Static Linking to Shared Library (DLL/so). Delphi and Lazarus (Windows and Linux).
26+
27+
3. Dynamic Load and Link. Delphi and Lazarus (Windows and Linux). OpenSSL 1.0.2, 1.1.1. and 3.x
28+
29+
For (2) and (3) above, the different link strategies are selected at compile time by a "defined symbol" set in the OpenSSL
30+
package options (not the using program), as follows:
31+
32+
- OPENSSL_USE_STATIC_LIBRARY (Static Linking to Static Library)
33+
- OPENSSL_USE_SHARED_LIBRARY (Static Linking to Shared Library)
34+
- Neither of the above (Dynamic Load and Link).
35+
36+
Note that (2) and (3) behave identically for Static and Shared library linking).
37+
38+
The defined synbol OPENSSL_NO_LEGACY_SUPPORT may also be set at compile time and applies to Dynamic
39+
loading. If set, no compatibility functions are compile in to the executeable. Only 3.0 or later
40+
API calls may be used.
41+
42+
43+
Delphi Builds
44+
=============
45+
46+
All Protocols/IndyProtocolsnnn.dpk and dproj files have been edited to remove references to the moved files.
47+
However only Protocols/IndyProtocols290 has been tested (with Delphi Berlin edition).
48+
49+
New Packages:
50+
51+
IndyOpenSSL290 and
52+
dclIndyOpenSSL290 (design time only)
53+
54+
may be found in Lib\OpenSSL\.
55+
56+
These are dependent on IndyProtocols290 and dclIndyProtocols290,IndyOpenSSLLegacy290 respectively.
57+
58+
To use OpenSSL in a given project, the IndyOpenSSL290 package must now be included.
59+
60+
Lib\Indy290.groupproj has been updated to include the new packages in the project group.
61+
62+
icons\makedcr.bat has been updated to generate a .dcr package for the OpenSSL packages.
63+
64+
Lazarus/FPC Builds
65+
==================
66+
67+
All lazarus packages may be found in the "lazarus-fpc/" top level folder. These are:
68+
69+
indysystem.lpk
70+
indycore.lpk
71+
indyprotocols.lpk
72+
indyopenssl.lpk
73+
74+
and the design time only packages
75+
76+
indylaz.lpk
77+
indylaz_indyopenssl
78+
79+
In order to install this proposed update for Lazarus (Windows and Linux), Open first
80+
that package indylaz.lpk and click on install. Then Open the package indylaz_openssl.lpk and
81+
click on install. The Indy Library should now be available for use.
82+
83+
You can also use fpcmake to create a makefile for building the full package. Run
84+
85+
fpcmake -r
86+
87+
in the package's root directiory.
88+
89+
Test Programs
90+
=============
91+
92+
Two test programs are available with variants for Delphi and Lazarus. These may be found in:
93+
94+
1. Test/OpenSSL/openssl-client and
95+
2. Test/OpenSSL/openssl-server.
96+
97+
openssl-client uses an HTTP Client to issue an http Get on an https target and returns
98+
the result. The server certificate is also verified.
99+
100+
openssl-server provides both and a server and uses a local PKI to retrieve a web page
101+
from the server, with both client and server certificate verification and to return the result.
102+
103+
Note: in all cases the compiled programs are placed in the openssl-client or openssl-server
104+
directories.
105+
106+
Note that for Delphi, a convenience project group is provided:
107+
108+
Test\OpenSSL\OpenSSLTests.groupprog
109+
110+
These build both test programs and their supporting packages as a single project group. You do
111+
not have to install the design time packages in order to use the test programs.
112+
113+
When testing under Lazarus, similarly you do not need to have installed the design time packages.
114+
However, you need to at least "open" the dependent packages so that the IDE knows where to find
115+
them.
116+
117+
Test program command line arguments:
118+
119+
Usage: fpc_openssl_client [-h] [-n] [-l <cacerts dir>] [-L] [OpenSSL lib dir]
120+
121+
Usage: fpc_openssl_client [-h] [-n] [-l <cacerts dir>] [-L] [OpenSSL lib dir]
122+
123+
-L is useful under Linux when the OpenSSL Library used has not been installed and
124+
hence does not know where to find its X.509 certificate store. When -L is
125+
given, the program searches a list of possible locations.
126+
127+
Runtime Control of the Library Loader
128+
=====================================
129+
130+
The OpenSSLAPI unit provides two Pascal COM interfaces which provide information and option selection for the OpenSSL Library.
131+
132+
The IOpenSSL Interface
133+
----------------------
134+
135+
This interface is available for all link strategies and the interface is accessed using the function:
136+
function GetIOpenSSL: IOpenSSL;
137+
138+
The interface is declared as:
139+
IOpenSSL = interface
140+
['{aed66223-1700-4199-b1c5-8222648e8cd5}']
141+
function GetOpenSSLPath: string;
142+
function GetOpenSSLVersionStr: string;
143+
function GetOpenSSLVersion: TOpenSSL_C_ULONG;
144+
function Init: boolean;
145+
end;
146+
147+
function GetOpenSSLPath: string;
148+
149+
Static Linking: Returns the OpenSSL installation path as compiled into the OpenSSL library.
150+
Dynamic Loading: Returns
151+
• The same as above when the library is loaded
152+
• the specified OpenSSL installation path, otherwise.
153+
154+
function GetOpenSSLVersionStr: string
155+
156+
Returns the OpenSSL library version string. e.g “OpenSSL 3.2.0 23 Nov 2023”
157+
158+
function GetOpenSSLVersion: TOpenSSL_C_ULONG;
159+
160+
Returns the OpenSSL library version as an integer as defined by the OpenSSL documentation.
161+
162+
function Init: boolean;
163+
164+
Called to initialise the OpenSSL library prior to use. This must be called when using static linking.
165+
It is optional for dynamic linking (implicitly called on library load).
166+
167+
The IOpenSSLDLL Interface
168+
-------------------------
169+
170+
This interface is only available when the API is configured at compile time for dynamic library loading.
171+
The interface is accessed using the function:
172+
173+
function GetIOpenSSLDDL: IOpenSSLDLL;
174+
175+
This function returns “nil” if the interface is not available. This may be used as a runtime test to
176+
determine if dynamic library loading if been configured.
177+
178+
Note The OpenSSLAPI unit only declares the constant
179+
180+
OpenSSL_Using_Dynamic_Library_Load = true;
181+
182+
when configured at compile time for dynamic library loading. The constant is not declared otherwise. This feature may be used as a compile time test for the dynamic library loading strategy e.g.
183+
184+
{$if declared(OpenSSL_Using_Dynamic_Library_Load)}
185+
186+
{$ifend}
187+
188+
The interface includes the IOpenSSL interface and is declared as:
189+
IOpenSSLDLL = interface(IOpenSSL)
190+
procedure SetOpenSSLPath(const Value: string);
191+
function GetSSLLibVersions: string;
192+
procedure SetSSLLibVersions(AValue: string);
193+
function GetSSLBaseLibName: string;
194+
procedure SetSSLBaseLibName(AValue: string);
195+
function GetCryptoBaseLibName: string;
196+
procedure SetCryptoBaseLibName(AValue: string);
197+
function GetAllowLegacyLibsFallback: boolean;
198+
procedure SetAllowLegacyLibsFallback(AValue: boolean);
199+
function GetLibCryptoHandle: TLibHandle;
200+
function GetLibSSLHandle: TLibHandle;
201+
function GetLibCryptoFilePath: string;
202+
function GetLibSSLFilePath: string;
203+
function GetFailedToLoadList: TStrings;
204+
function Load: Boolean;
205+
procedure Unload;
206+
function IsLoaded: boolean;
207+
property SSLLibVersions: string read GetSSLLibVersions write SetSSLLibVersions;
208+
property SSLBaseLibame: string read GetSSLBaseLibName write SetSSLBaseLibName;
209+
property CryptoBaseLibName: string read GetCryptoBaseLibName
210+
write SetCryptoBaseLibName;
211+
property AllowLegacyLibsFallback: boolean read GetAllowLegacyLibsFallback
212+
write SetAllowLegacyLibsFallback;end;
213+
214+
procedure SetOpenSSLPath(const Value: string);
215+
216+
This sets the OpenSSLPath used to locate the OpenSSL library modules (e.g. libcrypto.so). It
217+
needs to be set when OpenSSL has not been installed in a default location and/or multiple
218+
versions of OpenSSL have been installed on the same system.
219+
220+
function GetSSLLibVersions: string;
221+
procedure SetSSLLibVersions(AValue: string);
222+
223+
This is a colon separated (Unixes) or semi-colon separated (Windows) ordered list of OpenSSL
224+
version numbers that can be used as suffices for the OpenSSL library modules (e.g. for
225+
libcrypto-3-x64.dll, the suffix is '-3-x64'). When searching for the OpenSSL library, the loader
226+
searches the default (or specified) OpenSSLPath for OpenSSL libraries using these suffices in turn.
227+
228+
Unix: defaults to
229+
'.3:.1.1:.1.0.2:.1.0.0:.0.9.9:.0.9.8:.0.9.7:.0.9.6'
230+
231+
Note includes legacy versions.
232+
233+
Windows defaults to
234+
'-3-x64;-1-x64;' (64 bit)
235+
'-3;-1;' (32 bit)
236+
237+
Changing the libversions will automatically unload the ssl and crypto libraries if currently loaded.
238+
239+
function GetSSLBaseLibName: string;
240+
procedure SetSSLBaseLibName(AValue: string);
241+
242+
These are used to respectively get and set the basename for the SSL dynamic library. Defaults to 'libssl'.
243+
Changing the base name will automatically unload the ssl and crypto libraries if currently loaded.
244+
245+
function GetCryptoBaseLibName: string;
246+
procedure SetCryptoBaseLibName(AValue: string);
247+
248+
These are used to respectively get and set the basename for the crypto dynamic library.
249+
Defaults to 'libcrypto'. Changing the base name will automatically unload the ssl and crypto
250+
libraries if currently loaded.
251+
252+
function GetAllowLegacyLibsFallback: boolean;
253+
procedure SetAllowLegacyLibsFallback(AValue: boolean);
254+
255+
These are used to respectively get and set the AllowLegacyLibsFallback flag. This is only used
256+
when running under Windows. If set and no OpenSSL libraries have been found when searching for
257+
them using the Base Library names and libversions, then the loader will attempt to load the
258+
OpenSSL libraries using the legacy library names 'libeay32' and 'ssleay32'.
259+
260+
Defaults to 'false'.
261+
262+
Changing this flag will automatically unload the ssl and crypto libraries if currently loaded.
263+
264+
function GetLibCryptoHandle: TLibHandle;
265+
266+
After a successful library load, this returns the value of the internal handle to libcrypto (internal use only recommended).
267+
268+
function GetLibSSLHandle: TLibHandle;
269+
270+
After a successful library load, this returns the value of the internal handle to libssl (internal use only recommended).
271+
272+
function GetLibCryptoFilePath: string;
273+
274+
After a successful library load, this returns the path to the loaded libcrypto library.
275+
(note: may be empty if default library loaded).
276+
277+
function GetLibSSLFilePath: string;
278+
279+
After a successful library load, this returns the path to the loaded libssl library. (
280+
note: may be empty if default library loaded).
281+
282+
function GetFailedToLoadList: TStrings;
283+
284+
After a successful library load, this returns a list of API call names that failed to load at
285+
library load time. Note: only applies to a small number of functions that are not suitable
286+
for "just in time" loading.
287+
288+
function Load: Boolean;
289+
290+
Explicitly loads the library if not already loaded and returns “true” on successful load.
291+
292+
procedure Unload;
293+
294+
Explicitly unloads the library if current loaded.
295+
296+
function IsLoaded: boolean;
297+
298+
Returns true if the OpenSSL library has been successfully loaded.
299+
300+
301+
302+
303+
304+
305+

0 commit comments

Comments
 (0)