Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Added new OpenSSL IO Handler for OpenSSL 1.1.1 #299

Closed
wants to merge 63 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
d8e2735
Added new OpenSSL IO Handler for OpenSSL 1.1.1
mezen Jan 27, 2020
ab54e16
Added results of an internal review
mezen May 27, 2020
726bf0e
FTP data channel should reuse the session of the command channel
mezen Jun 25, 2020
2d840c9
Added git attributes
mezen Oct 28, 2020
5946cfd
Fixed line endings and rebase error
mezen Oct 10, 2022
5456188
Made intermediate code more compatible
mezen Oct 28, 2020
9098d2d
Made new OpenSSL IO Handler more compatible
mezen Oct 28, 2020
95adc5f
Removed some unnecessary stuff from GenerateCode.dproj
mezen Oct 28, 2020
75ea32b
Do not use SafeLoadLibrary without second parameter
mezen Oct 28, 2020
9eb2819
Added code for loading OpenSSL on Linux
mezen Oct 28, 2020
a7bab36
Replaced %LINE% with %LINENUM%
mezen Oct 28, 2020
11bf465
IndyCheckWindowsVersion is only available under windows
mezen Oct 28, 2020
0b3c98c
Removed duplicated types
mezen Oct 28, 2020
8e6da46
If the options of the IO handler change, the context must be reinitia…
mezen Oct 28, 2020
6d52c7c
Corrected some header imports
mezen Oct 29, 2020
95efa0a
Used correct case
mezen Oct 29, 2020
9ecf100
Fixed another wrong type
mezen Oct 29, 2020
4b6316b
Fixed copy'n'paste error :(
mezen Oct 29, 2020
afb44be
Added missing raise
mezen Oct 29, 2020
fdc52da
Fixed line endings
mezen Nov 3, 2020
f489e59
Fixed small errors in crypto
mezen Nov 3, 2020
36bec7c
Added CRYPTO_set_mem_functions to crypto
mezen Nov 3, 2020
1c274b5
If OpenSSL is dynamically loaded, the DLLs should also be freed at un…
mezen Nov 3, 2020
ce5caa5
Fixed MemLeak with handling TLS Sessions
mezen Nov 3, 2020
0004ff8
Fixed missing _ to parameter named "out" & added dynlibs to Loader
mezen Nov 6, 2020
2b6e7e2
Fixed used-after-free
mezen Nov 6, 2020
ff99d3f
The Server IO Handler does not immediately start a TLS handshake any …
mezen Nov 6, 2020
d392d53
Added SaveToFile and ctor overload for file loading to TIdOpenSSLX509
mezen Dec 1, 2020
76fdc7d
Added missing file header to IdOpenSSLX509
mezen Dec 1, 2020
f61d373
Fixed using PBIO instead of BIO directly
mezen Jan 6, 2021
a313bb7
Use existing CheckForError and RaiseError
mezen Mar 2, 2021
4346440
Add additional Infos to EIdOpenSSLAcceptError
mezen Mar 2, 2021
d17a73a
Replaced `&parameter ` with `parameter_`
mezen Jul 23, 2021
7f5d370
Improved excpetion message for shutdown errors
mezen Jul 23, 2021
3864f7b
Fixed multiple `Load` / `Unload` calls
mezen Jul 23, 2021
e63d7fd
Resolved c macro for ASN1_INTEGER functions
mezen Jul 23, 2021
30861e6
Fixed wrong parameter definitin in bn
mezen Jul 23, 2021
506eb2b
Resolved c macro for ASN1_Time functions
mezen Jul 26, 2021
2921154
Resolved c macro for ASN1_UTCTIME & ASN1_GENERALIZEDTIME functions
mezen Jul 28, 2021
9b30d60
Resolved c macro for BIO_get/set_mem functions
mezen Jul 28, 2021
9d56ae3
Removed duplicate type X509_REVOKED
mezen Jul 28, 2021
8bbb0b2
Fixed small memory leak
mezen Jul 28, 2021
d2209ba
Fix compile errors for Delphi 7
Aug 31, 2021
e1820c5
Added initialization of result as addition to 9c37992275a514eb1c80369…
mezen Sep 9, 2021
651fcee
Added BeforeInitContext and AfterInitContext to TIdOpenSSLIOHandlerSe…
mezen Oct 18, 2021
23518eb
Added some xml doc
mezen Nov 30, 2021
08795ef
Removed old code
mezen Nov 30, 2021
df99616
Use parameter instead of property
mezen Nov 30, 2021
19f9c1d
TLS Client is now able to verify host name
mezen Nov 30, 2021
feb0095
Added small helpful comment
mezen Oct 10, 2022
f542125
Added header translation for pkcs12.h
mezen Oct 10, 2022
a94ebd5
Sort uses
mezen Oct 10, 2022
af908dd
Use newer function
mezen Oct 10, 2022
46db019
Added possibility to load trusted certs
mezen Oct 10, 2022
97e9a01
Load x509 from memory directly
mezen Oct 10, 2022
9f5cdd6
Fixed translation error in bio
mezen Oct 10, 2022
f40a353
Added missing uses
mezen Oct 11, 2022
d0c2417
Expanded some c compiler macro
mezen Oct 12, 2022
274c7d0
Add missing properties in AssignTo
zencode1 Mar 8, 2023
da81e95
Add missing properties in Equals
zencode1 Mar 20, 2023
a899fa4
Return the correct socket error
zencode1 Apr 21, 2023
8ce7c93
Fixed some comments
mezen Jul 6, 2023
c0101f0
Use bidirectional shutdown on default
mezen Jul 6, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Lib/Protocols/OpenSSL/.gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
# Declare files that will always have CRLF line endings on checkout.
*.pas text eol=crlf
374 changes: 374 additions & 0 deletions Lib/Protocols/OpenSSL/GenerateCode/GenerateCode.dpr
Original file line number Diff line number Diff line change
@@ -0,0 +1,374 @@
{******************************************************************************}
{ }
{ Indy (Internet Direct) - Internet Protocols Simplified }
{ }
{ https://www.indyproject.org/ }
{ https://gitter.im/IndySockets/Indy }
{ }
{******************************************************************************}
{ }
{ This file is part of the Indy (Internet Direct) project, and is offered }
{ under the dual-licensing agreement described on the Indy website. }
{ (https://www.indyproject.org/license/) }
{ }
{ Copyright: }
{ (c) 1993-2020, Chad Z. Hower and the Indy Pit Crew. All rights reserved. }
{ }
{******************************************************************************}
{ }
{ Originally written by: Fabian S. Biehn }
{ [email protected] (German & English) }
{ }
{ Contributers: }
{ Here could be your name }
{ }
{******************************************************************************}

program GenerateCode;

{$APPTYPE CONSOLE}

{$R *.res}

uses
System.Classes,
System.IOUtils,
System.StrUtils,
System.SysUtils,
System.Types,
Winapi.Windows;

type
TGenerateMode = (gmDynamic, gmStatic);

function ExpandEnvironmentVariables(const AValue: string): string;
const
MAX_LENGTH = 32767;
begin
SetLength(Result, MAX_LENGTH);
SetLength(Result, ExpandEnvironmentStrings(@AValue[1], @Result[1], MAX_LENGTH)-1);
end;

function ReplaceStatic(const ALine: string; const AShouldUseLibSSL: Boolean): string;
const
CSemicolon: string = ';';
var
i: Integer;
begin
Result := ALine;
i := Result.LastIndexOf(CSemicolon);
if i = -1 then
Exit;
Result := Result.Remove(i, CSemicolon.Length);
Result := Result.Insert(i, Format(' cdecl; external %s;', [IfThen(AShouldUseLibSSL, 'CLibSSL', 'CLibCrypto')]));
end;

function ReplaceDynamic(const ALine: string; const AMethodList: TStringList): string;
var
i: Integer;
LMethodPrefix: string;
LMethod: string;
begin
Result := ALine;

if not Result.TrimLeft.StartsWith('function') and not Result.TrimLeft.StartsWith('procedure') then
Exit;

LMethodPrefix := 'function';
i := Result.IndexOf(LMethodPrefix);
if i = -1 then
begin
LMethodPrefix := 'procedure';
i := Result.IndexOf(LMethodPrefix);
if i = -1 then
Exit;
end;

// Remove LMethodPrefix
Result := Result.Remove(i, LMethodPrefix.Length + string(' ').Length);
// Keep Result for method name extracting later
LMethod := Result.TrimLeft();
// Add LMethodPrefix after parameters
if Result.Contains(')') then
Result := Result.Replace('(', ': ' + LMethodPrefix + '(')
// No Params? Add LMethodPrefix after before return type
else if Result.Contains(': ') then
Result := Result.Replace(': ', ': ' + LMethodPrefix + ': ')
// Also no return type? Add LMethodPrefix before semi colon
else
Result := Result.Replace(';', ': ' + LMethodPrefix + ';');

if Result[Result.Length] = ';' then
Result := Result.Remove(Result.Length-1) + ' cdecl = nil;';

// Ignore comments
i := LMethod.IndexOf('}');
if i > -1 then
// +1 for including } and Trim for removing whitespace of intendation
LMethod := LMethod.Substring(i + 1{, LMethod.Length - i}).TrimLeft;
i := LMethod.IndexOf(';');
if i > -1 then
LMethod := LMethod.Remove(i);
i := LMethod.IndexOf(' ');
if i > -1 then
LMethod := LMethod.Remove(i);
i := LMethod.IndexOf(':');
if i > -1 then
LMethod := LMethod.Remove(i);
i := LMethod.IndexOf('(');
if i > -1 then
LMethod := LMethod.Remove(i);
AMethodList.Add(LMethod);
end;

procedure AddDynamicLoadingMethods(
const AFile: TStringList;
const AMethods: TStringList;
const AUsesIndex: Integer;
const AVarIndex: Integer;
const AImplementationIndex: Integer);

procedure Insert(const AList: TStringList; const s: string; var Index: Integer);
begin
AList.Insert(Index, s);
Inc(Index);
end;

function Find(const AList: TStringList; const s: string; var Index: Integer; const AOffset: Integer = 0): Boolean;
var
i: Integer;
begin
Result := False;
for i := AOffset to AList.Count - 1 do
begin
if AList[i].Contains(s) then
begin
Index := i;
Exit(True);
end;
end;
end;

var
LOffset: Integer;
LMethod: string;
begin
if AImplementationIndex = -1 then
Exit;
LOffset := AImplementationIndex + 1;

if Find(AFile, 'uses', LOffset, LOffset) then
if Find(AFile, ';', LOffset, LOffset) then
Inc(LOffset);

Insert(AFile, '', LOffset);
Insert(AFile, 'procedure Load(const ADllHandle: TIdLibHandle; const AFailed: TStringList);', LOffset);
Insert(AFile, '', LOffset);
Insert(AFile, ' function LoadFunction(const AMethodName: string; const AFailed: TStringList): Pointer;', LOffset);
Insert(AFile, ' begin', LOffset);
Insert(AFile, ' Result := LoadLibFunction(ADllHandle, AMethodName);', LOffset);
Insert(AFile, ' if not Assigned(Result) then', LOffset);
Insert(AFile, ' AFailed.Add(AMethodName);', LOffset);
Insert(AFile, ' end;', LOffset);
Insert(AFile, '', LOffset);
Insert(AFile, 'begin', LOffset);
for LMethod in AMethods do
Insert(AFile, Format(' %0:s := LoadFunction(''%0:s'', AFailed);', [LMethod]), LOffset);
Insert(AFile, 'end;', LOffset);
Insert(AFile, '', LOffset);


Insert(AFile, 'procedure UnLoad;', LOffset);
Insert(AFile, 'begin', LOffset);
for LMethod in AMethods do
Insert(AFile, Format(' %s := nil;', [LMethod]), LOffset);
Insert(AFile, 'end;', LOffset);

if AVarIndex = -1 then
Exit;
LOffSet := Pred(AVarIndex);
Insert(AFile, '', LOffSet);
Insert(AFile, 'procedure Load(const ADllHandle: TIdLibHandle; const AFailed: TStringList);', LOffSet);
Insert(AFile, 'procedure UnLoad;', LOffSet);

LOffSet := Succ(AUsesIndex);
Insert(AFile, ' Classes,', LOffset);
// AFile.Insert(Pred(AVarIndex), 'function Load(const ADllHandle: THandle): TArray<string>;');
end;

function ShouldSkipLine(ALine: string): Boolean;
begin
ALine := ALine.Trim;
Result := ALine.IsEmpty;
Result := Result or ALine.StartsWith('//');
Result := Result or ALine.StartsWith('(*');
Result := Result or ALine.StartsWith('*');
end;

function ReadParameters(out ASource: string; out ATarget: string; out AMode: TGenerateMode): Boolean;
var
LMode: string;
begin
Result := True;
if not FindCmdLineSwitch('Source', ASource) then
begin
Writeln('No source folder!');
Exit(False);
end;
ASource := ExpandEnvironmentVariables(ASource);

if not FindCmdLineSwitch('Target', ATarget) then
begin
Writeln('No target folder!');
Exit(False);
end;
ATarget := ExpandEnvironmentVariables(ATarget);

if not FindCmdLineSwitch('Mode', LMode) then
begin
Writeln('No mode!');
Exit(False);
end;

if LMode = 'dynamic' then
AMode := gmDynamic
else if LMode = 'static' then
AMode := gmStatic
else
begin
Writeln('Invalid mode! Use "dynamic" or "static"!');
Exit(False);
end;
end;

procedure AddGeneratedHeader(const AFile: TStringList);

function Find(const AList: TStringList; const s: string; var Index: Integer): Boolean;
var
i: Integer;
begin
Index := -1;
Result := False;
for i := 0 to AList.Count-1 do
if AList[i].Contains(s) then
begin
Index := i;
Exit(True);
end;
end;

const
CHeader: array[0..4] of string =
(
'',
'// This File is auto generated!',
'// Any change to this file should be made in the',
'// corresponding unit in the folder "intermediate"!',
''
);
var
i: Integer;
LOffset: Integer;
begin
if not Find(AFile, 'unit ', LOffset) then
Exit;
// Keep a empty line before "unit"
Dec(LOffset);
for i := Low(CHeader) to High(CHeader) do
AFile.Insert(i + LOffset, CHeader[i]);
AFile.Insert(Length(CHeader) + LOffset, '// Generation date: ' + DateTimeToStr(Now()));
end;

procedure Main;
var
LFile: string;
LStringListFile: TStringList;
i: Integer;
LVarIndex: Integer;
LUsesIndex: Integer;
LImplementationIndex: Integer;
LSource: string;
LTarget: string;
LMode: TGenerateMode;
LStringListMethods: TStringList;
LFileName: string;
LShouldUseLibSSL: Boolean;
begin
if not ReadParameters(LSource, LTarget, LMode) then
begin
Readln;
Exit;
end;

for LFile in TDirectory.GetFiles(LSource, '*.pas') do
begin
Writeln('Converting ' + LFile);
LFileName := TPath.GetFileName(LFile);
LStringListFile := TStringList.Create();
LStringListMethods := TStringList.Create();
try
LStringListFile.LoadFromFile(LFile);
LUsesIndex := -1;
LVarIndex := -1;
LImplementationIndex := -1;
LShouldUseLibSSL := MatchText(LFileName,
['IdOpenSSLHeaders_ssl.pas', 'IdOpenSSLHeaders_sslerr.pas', 'IdOpenSSLHeaders_tls1.pas']);
for i := 0 to LStringListFile.Count - 1 do
begin
// Find fist uses
if (LVarIndex = -1) and (LUsesIndex = -1) then
if LStringListFile[i].StartsWith('uses') then
LUsesIndex := i;

// var block found?
if (LVarIndex = -1) and LStringListFile[i].StartsWith('var') then
LVarIndex := i;
// Skip until we find the var block
if (LVarIndex = -1) or ShouldSkipLine(LStringListFile[i]) then
Continue;

// No need to go further than "implementation"
if LStringListFile[i] = 'implementation' then
begin
LImplementationIndex := i;
Break;
end;

case LMode of
gmDynamic:
LStringListFile[i] := ReplaceDynamic(LStringListFile[i], LStringListMethods);
gmStatic:
LStringListFile[i] := ReplaceStatic(LStringListFile[i], LShouldUseLibSSL);
end;
end;

case LMode of
gmDynamic:
AddDynamicLoadingMethods(LStringListFile, LStringListMethods, LUsesIndex, LVarIndex, LImplementationIndex);
gmStatic:
if LVarIndex > -1 then
LStringListFile.Delete(LVarIndex);
end;

AddGeneratedHeader(LStringListFile);

LStringListFile.SaveToFile(TPath.Combine(LTarget, LFileName));
finally
LStringListMethods.Free();
LStringListFile.Free();
end;
end;
end;

begin
try
Main;
Writeln('done');
except
on E: Exception do
begin
Writeln(E.ClassName, ': ', E.Message);
end;
end;
// Readln;
end.
Loading