Delphi-PRAXiS
Seite 2 von 2     12   

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Netzwerke (https://www.delphipraxis.net/14-netzwerke/)
-   -   Delphi Indy & OpenSSL 1.1.1 & TLS 1.3 (https://www.delphipraxis.net/204185-indy-openssl-1-1-1-tls-1-3-a.html)

AWeber 25. Aug 2021 12:32

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Hallo,
zunächst möchte ich mich bedanken für die hier geleistete Arbeit :-)

Aber auch gleich mit einem kleinen Problem um die Ecke kommen. Die Reaktion denn die OpenSSL DLL's nicht vorhanden sind - ist nicht so schön bei mir kommt es dann immer zu einer Schutzverletzung - im destructor der Klasse
Delphi-Quellcode:
TIdOpenSSLContextClient
Soweit ich durchdebuggt habe - ist die Aufrufkette folgende:
Delphi-Quellcode:
TIdTCPClientCustom.Connect( ) --> IOHandler := nil; (bedingt durch Exception) --> TIdTCPConnection.SetIOHandler --> IdDisposeAndNil(LIOHandler);
--> TIdOpenSSLIOHandlerClient.Destroy --> TIdOpenSSLContextClient.Destroy
Delphi-Quellcode:
TIdTCPClientCustom.Connect( )
  try
    IOHandler.Open; --> Exception weil DLL's nicht verfügbar
  except
    if IOHandler <> nil then begin
      IOHandler.Close;
      if ManagedIOHandler then begin
         // Mein IOHandler ist ManagedIOHandler = true! (bedingt durch anderen Code zuvor)
         IOHandler := nil; // RLebeau - SetIOHandler() will free the IOHandler
      end;
    end;
    raise;
  end;
Das Set IOhandler = nil führt dann zu:

Delphi-Quellcode:
 procedure TIdTCPConnection.SetIOHandler(AValue: TIdIOHandler);
    if ManagedIOHandler then begin
      if Assigned(LIOHandler) then begin
        FIOHandler := nil;
        -- Zugriffsfehler im Destructor des IOHandlers
        IdDisposeAndNil(LIOHandler);
      end;
      ManagedIOHandler := False;
    end;
Delphi-Quellcode:
destructor TIdOpenSSLIOHandlerClient.Destroy;
  FContext.Free(); --> Zugriffsfehler
Delphi-Quellcode:
destructor TIdOpenSSLContextClient.Destroy;
  OpenSSLContext ist hier noch nil
  und die Methoden / Funktionszeiger
  -> SSL_CTX_sess_set_remove_cb
  -> SSL_CTX_sess_set_new_cb ebenso... da DLL ja nicht gefunden wurde
Meine Lösung sieht jetzt so aus ich ändere die Routine:

Delphi-Quellcode:
procedure TIdOpenSSLIOHandlerClient.EnsureContext;
begin
  // schlägt das Laden der DLL fehl ist FContext noch <nil> und der Aufruf des TIdOpenSSLContextClient.Destroy entfällt.
  EnsureOpenSSLLoaded();

  if not Assigned(FContext) then
     FContext := TIdOpenSSLContextClient.Create();
 
  // EnsureOpenSSLLoaded(); --> führt ggf. zu Exception, wo FContext welches nicht komplett initialsiert ist abgeräumt wird
  try
    BeforeInitContext(FContext);
    TIdOpenSSLContextClient(FContext).Init(FOptions);
    AfterInitContext(FContext);
  except
    on E: EExternalException do
    begin
      try
        FreeAndNil(FContext);
      except
        on E: EExternalException do ; // Nothing
      end;
      raise EIdOpenSSLLoadError.Create('Failed to load OpenSSL');
    end;
  end;
end;
ist das so der richtige Weg?

Nachtrag:

in der Funktion TOpenSSLLoader.Load steckt leider auch ein Bug, auch wenn diese Funktion beim ersten Versuch sauber false liefert wenn die DLL's nicht geladen werden konnten, liefert einer 2. Aufruf true - auch wenn die DLL's immer noch nicht da sind... daher habe ich folgende geändert:

if not Result then
begin
// bei weiterem Aufruf nochmal versuchen die DLL's zu laden...
FLoadCount.Decrement();
Exit;
end;




André

THonscha 21. Dez 2021 08:07

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Hat sich bei Indy etwas mit dem TLS 1.3 Support getan? Gibt es eine Delphi Version, die das out of the box unterstützt?

Thomasl 3. Aug 2022 08:26

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Ich habe es auch ans laufen bekommen.
Eine Frage, die IdOpenSSLConsts.pas kann man die wie hier auf die 3er DLL´s umbenennen?
Oder gibt es da noch Probleme.
Muss SSLDLLVers auch angepasst werden?
Es Funktioniert so wie hier

Delphi-Quellcode:
unit IdOpenSSLConsts;

interface

{$i IdCompilerDefines.inc}

const
  CLibCryptoRaw = 'libcrypto';
  CLibSSLRaw = 'libssl';

  SSLDLLVers: array [0..1] of string = ('', '.1.1');

  CLibCrypto =
 //   {$IFDEF CPU32}CLibCryptoRaw + '-1_1.dll'{$ENDIF}
 //   {$IFDEF CPU64}CLibCryptoRaw + '-1_1-x64.dll'{$ENDIF}
    {$IFDEF CPU32}CLibCryptoRaw + '-3.dll'{$ENDIF}
    {$IFDEF CPU64}CLibCryptoRaw + '-3-x64.dll'{$ENDIF}
    ;
  CLibSSL =
//    {$IFDEF CPU32}CLibSSLRaw + '-1_1.dll'{$ENDIF}
//    {$IFDEF CPU64}CLibSSLRaw + '-1_1-x64.dll'{$ENDIF}
    {$IFDEF CPU32}CLibSSLRaw + '-3.dll'{$ENDIF}
    {$IFDEF CPU64}CLibSSLRaw + '-3-x64.dll'{$ENDIF}
    ;

implementation

end.

AWeber 5. Sep 2022 19:13

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
@mezen, liest du hier noch mit? Ich verwende seit einiger Zeit deinen neuen Openssl IOHandler und bin recht zufrieden damit. Jetzt bin ich an einem Punkt wo ich Mails mit S/MIME signieren und verschlüsseln möchte. Die notwendigen Funktionen dazu gibt es ja in dem Openssl Dlls. Ich würde dazu gerne die restlichen Importe ergänzen, für einige der Funktionen kommt dieses Stack genannte Konstrukt zum Einsatz, damit nicht alles mit mehr oder minder typlosen pointern machen muss habe ich den Codegenerator erweitert, so dass er auch die Stack_of defines in Delphi inline Funktionen umsetzt.
Das würde ich gerne mit der Gemeinschaft teilen, wie lautet die URL / Branch deines github repositories?
Ich würde davon einen Branch machen und meinen Änderungen dort einstellen, ggf. kannst du das ja mergen?

mjustin 6. Sep 2022 18:43

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Zitat:

Zitat von AWeber (Beitrag 1511277)
Das würde ich gerne mit der Gemeinschaft teilen, wie lautet die URL / Branch deines github repositories?

Das wird vermutlich dieser hier sein,

https://github.com/mezen/Indy/tree/NewOpenSSL_PR

oder dieser:

https://github.com/mezen/Indy/tree/NewOpenSSL

Apfelmus 3. Nov 2022 15:05

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Hallo zusammen,
ich breche mir seit Tagen die Finger, um folgende Anforderung umsetzen zu können:

Wir haben einen Rest-Webservice laufen, der mit Indy entwickelt wurde.
Diesen WS ruft unser SAP auf, um uns Daten (IDOC) zu übermitteln.

Aus Sicherheitsgründen soll nun auf der SAP-Seite "EMS" (Extended Master Secret) verwendet werden.
AFAIK funktioniert das nur mit OpenSSL 1.1.1.

Die Binaries dafür habe ich, aber ich stehe irgendwie komplett auf dem Schlauch, was ich jetzt für Indy 10 unter 10.1 Berlin alles herunterladen, patchen usw. muss.

Kann mir da jemand Schritt für Schritt auf die Sprünge helfen?

Tausend Dank im Voraus!

mjustin 3. Nov 2022 19:31

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Zitat:

Zitat von Apfelmus (Beitrag 1514250)
Kann mir da jemand Schritt für Schritt auf die Sprünge helfen?

Selbst gemacht habe ich es noch nicht, grob gesagt muss nur der Code aus dem speziellen GitHub Branch heruntergeladen werden. Dieser wird dann im Projekt eingebunden. Dazu muss normalerweise nicht die Indy Package Installation in der IDE erfolgen, es müssen nur die Verzeichnisse im Projekt-Suchpfad eingetragen werden.

Eventuell hilft es, zuerst ein separates Testprojekt zu erstellen, und damit einen Verbindungsaufbau zu einem TLS 1.3 Server zu probieren.

Alternativ kann auch ein kommerzieller SSL Handler verwendet werden. Der wird dann in Indy einfach anstelle des normalen Indy Handlers zugewiesen.

Die werden z.B. hier genannt:
https://www.delphipraxis.net/211132-...secureblackbox

Apfelmus 4. Nov 2022 13:20

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Den Code aus dem Repo hab' ich.
Die Idee war, einfach den "alten" IOHandler durch den neuen (TIdOpenSSLIOHandlerServer) zu ersetzen.
Da unser WS als Server fungiert klang das naheliegend.
War wohl zu einfach gedacht. Die Behebung eines Problems macht gleich 2 neue auf.
Code:
[dcc32 Fehler] IdOpenSSLHeaders_async.pas(70): E2003 Undeklarierter Bezeichner: 'TIdC_SIZET'
Der Typ ist in idGlobal definiert, in IdOpenSSLHeaders_async wird auf idGlobal verwiesen und das Verzeichnis steht im Suchpfad des Projektes.
Natürlich kann ich jetzt idGlobal in das Projekt mit aufnehmen. Dann kommt der nächste Fehler:
Code:
[dcc32 Fehler] IdOpenSSLHeaders_bio.pas(284): E2003 Undeklarierter Bezeichner: 'TIdC_SIZET'
Das kann aber nicht Sinn und Zweck der Übung sein.
Irgendwie krieg' ich das jetzt nicht mehr gewechselt ...

mjustin 6. Nov 2022 08:27

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Zitat:

Zitat von Apfelmus (Beitrag 1514314)
Code:
[dcc32 Fehler] IdOpenSSLHeaders_async.pas(70): E2003 Undeklarierter Bezeichner: 'TIdC_SIZET'
Der Typ ist in idGlobal definiert, in IdOpenSSLHeaders_async wird auf idGlobal verwiesen und das Verzeichnis steht im Suchpfad des Projektes.

Ich versuche das zu reproduzieren. Schritte:
  1. Download und Entpacken von https://github.com/mezen/Indy/archiv...OpenSSL_PR.zip
  2. Suchpfade im Projekt eintragen: ...\Lib\Core;...\Lib\Protocols;...\Lib\System;...\ Lib\Protocols\OpenSSL;...\Lib\Protocols\OpenSSL\dy namic

Wenn ich nun IOHandlerServer := TIdOpenSSLIOHandlerServer.Create; verwende, kompiliert das Projekt ohne Fehler.

Ich vermute, entweder ist der Projektsuchpfad nicht korrekt oder es werden Units im Projektsuchpfad gefunden, die aus einer anderen Indy-Version kommen.

Apfelmus 7. Nov 2022 11:41

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Zitat:

Zitat von mjustin (Beitrag 1514373)
... oder es werden Units im Projektsuchpfad gefunden, die aus einer anderen Indy-Version kommen.

Hmmm, das dürften vermutlich die mit Delphi installierten Teile aus Indy sein. Die stehen ja im PATH.
Ich versuche mal, die temporär woanders hinzuschieben ...

DieDolly 21. Nov 2022 15:47

AW: Indy & OpenSSL 1.1.1 & TLS 1.3
 
Kann man den neuen Code von diesem Link
https://github.com/mezen/Indy/tree/N...tocols/OpenSSL

für dieses Beispiel hier unten verwenden?
Delphi-Quellcode:
unit uSendMail;

interface

uses
 Vcl.ComCtrls, System.SysUtils, System.Classes, System.IOUtils, IdSmtp, IdMessage, IdAttachmentFile, IdText, IdExplicitTLSClientServerBase, IdSSLOpenSSL, IdBaseComponent, IdIOHandler,
 IdIOHandlerSocket, IdIOHandlerStack, IdSSL;

type
 TLoginType = (ltNone, ltLogin);

 TMailPriority = (pHighest, pHigh, pNormal, pLow, pLowest);

 TSendMail = class
 private
  FLibeay32, FSSLeay32: string;
  FSmtp: TIdSMTP;
  FIdSSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
  FMsg: TIdMessage;
  FAttachmentList: TStringList;
  FiEMailSize: Integer;
  FUseSSL: Boolean;
  FTLSMode: Integer;

  procedure SetLibeay32(const aValue: string);
  procedure SetSSLeay32(const aValue: string);

  procedure SetHost(const aValue: string);
  procedure SetPort(const aValue: Word);
  procedure SetUserName(const aValue: string);
  procedure SetPassword(const aValue: string);
  procedure SetLoginType(const aValue: TLoginType);
  procedure SetMailAgent(const aValue: string);
  procedure SetReceiver(const aValue: string);
  procedure SetSender(const aValue: string);
  procedure SetSubject(const aValue: string);
  procedure SetPriority(const aValue: TMailPriority);
  procedure SetReturnReciept(const aValue: Boolean);
  procedure SetBody(aValue: TStrings);
  procedure SetUseSSL(const aValue: Boolean);
  procedure SetTLSMode(const aValue: Integer);

  function GetLibeay32: string;
  function GetSSLeay32: string;

  function GetHost: string;
  function GetPort: Word;
  function GetUserName: string;
  function GetPassword: string;
  function GetLoginType: TLoginType;
  function GetMailAgent: string;
  function GetReceiver: string;
  function GetSender: string;
  function GetSubject: string;
  function GetPriority: TMailPriority;
  function GetReturnReciept: Boolean;
  function GetBody: TStrings;
  function GetUseSSL: Boolean;
  function GetTLSMode: Integer;

  procedure setEmailSize(iEMailSize: Integer);
 protected
  //
 public
  constructor Create;
  destructor Destroy; override;

  property Libeay32: string read GetLibeay32 write SetLibeay32;
  property SSLeay32: string read GetSSLeay32 write SetSSLeay32;

  property Host: string read GetHost write SetHost;
  property Port: Word read GetPort write SetPort;
  property Username: string read GetUserName write SetUserName;
  property Password: string read GetPassword write SetPassword;
  property LoginType: TLoginType read GetLoginType write SetLoginType;
  property MailAgent: string read GetMailAgent write SetMailAgent;

  property Receiver: string read GetReceiver write SetReceiver;
  property Sender: string read GetSender write SetSender;
  property Subject: string read GetSubject write SetSubject;
  property Priority: TMailPriority read GetPriority write SetPriority;
  property ReturnReciept: Boolean read GetReturnReciept write SetReturnReciept;
  property Body: TStrings read GetBody write SetBody;
  property Attachments: TStringList read FAttachmentList;
  property UseSSL: Boolean read GetUseSSL write SetUseSSL;
  property TLSMode: Integer read GetTLSMode write SetTLSMode;

  function SendMail: Boolean;
 end;

implementation

function _MIMEConvert(const s: string): string;
var
 i: Integer;
begin
 Result := '';
 for i := 1 to Length(s) do
  begin
   if s[i] = '€' then
    begin
     Result := Result + '?=ISO-8859-15?Q?=A4?='
    end
   else if Ord(s[i]) > $99 then
    Result := Result + '=?ISO-8859-1?Q?=' + Format('%x', [Ord(s[i])]) + '?='
   else
    Result := Result + s[i];
  end;
end;

constructor TSendMail.Create;
begin
 FSmtp := TIdSMTP.Create(nil);
 FIdSSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
 FMsg := TIdMessage.Create(nil);
 FAttachmentList := TStringList.Create;
end;

destructor TSendMail.Destroy;
begin
 FreeAndNil(FSmtp);
 FreeAndNil(FIdSSLIOHandler);
 FreeAndNil(FMsg);
 FreeAndNil(FAttachmentList);
 inherited;
end;

function TSendMail.GetLoginType: TLoginType;
begin
 if FSmtp.AuthType = satNone then
  Result := ltNone
 else
  Result := ltLogin;
end;

function TSendMail.GetHost: string;
begin
 Result := FSmtp.Host;
end;

function TSendMail.GetPort: Word;
begin
 Result := FSmtp.Port;
end;

function TSendMail.GetPassword: string;
begin
 Result := FSmtp.Password;
end;

function TSendMail.GetUserName: string;
begin
 Result := FSmtp.Username;
end;

procedure TSendMail.SetLoginType(const aValue: TLoginType);
begin
 if aValue = ltNone then
  FSmtp.AuthType := satNone
 else
  FSmtp.AuthType := satDefault;
end;

procedure TSendMail.SetHost(const aValue: string);
begin
 if aValue <> FSmtp.Host then
  FSmtp.Host := aValue;
end;

procedure TSendMail.SetPort(const aValue: Word);
begin
 if aValue <> FSmtp.Port then
  FSmtp.Port := aValue;
end;

procedure TSendMail.SetPassword(const aValue: string);
begin
 if aValue <> FSmtp.Password then
  FSmtp.Password := aValue;
end;

procedure TSendMail.SetUserName(const aValue: string);
begin
 if aValue <> FSmtp.Username then
  FSmtp.Username := aValue;
end;

function TSendMail.GetMailAgent: string;
begin
 Result := FSmtp.MailAgent;
end;

procedure TSendMail.SetMailAgent(const aValue: string);
begin
 if aValue <> FSmtp.MailAgent then
  FSmtp.MailAgent := aValue;
end;

function TSendMail.GetBody: TStrings;
begin
 Result := FMsg.Body;
end;

function TSendMail.GetUseSSL;
begin
 Result := FUseSSL;
end;

function TSendMail.GetTLSMode;
begin
 Result := FTLSMode;
end;

function TSendMail.GetPriority: TMailPriority;
var
 iTmp: Byte;
begin
 iTmp := Ord(FMsg.Priority);
 Result := TMailPriority(iTmp);
end;

function TSendMail.GetReceiver: string;
begin
 Result := FMsg.Recipients.EMailAddresses;
end;

function TSendMail.GetReturnReciept: Boolean;
begin
 Result := FMsg.ReceiptRecipient.Text <> '';
end;

function TSendMail.GetSender: string;
begin
 Result := FMsg.From.Text;
end;

function TSendMail.GetSSLeay32: string;
begin
 Result := FSSLeay32;
end;

function TSendMail.GetLibeay32: string;
begin
 Result := FLibeay32;
end;

function TSendMail.GetSubject: string;
begin
 Result := FMsg.Subject;
end;

procedure TSendMail.SetBody(aValue: TStrings);
begin
 FMsg.Body.Assign(aValue);
end;

procedure TSendMail.SetUseSSL(const aValue: Boolean);
begin
 FUseSSL := aValue;
end;

procedure TSendMail.SetTLSMode(const aValue: Integer);
begin
 FTLSMode := aValue;
end;

procedure TSendMail.SetPriority(const aValue: TMailPriority);
var
 iTmp: Byte;
begin
 iTmp := Ord(aValue);
 FMsg.Priority := TIdMessagePriority(iTmp);
end;

procedure TSendMail.SetReceiver(const aValue: string);
begin
 FMsg.Recipients.EMailAddresses := aValue;
end;

procedure TSendMail.SetReturnReciept(const aValue: Boolean);
begin
 if aValue then
  FMsg.ReceiptRecipient.Text := FMsg.From.Text
 else
  FMsg.ReceiptRecipient.Text := '';
end;

procedure TSendMail.SetSender(const aValue: string);
begin
 FMsg.From.Text := aValue;
end;

procedure TSendMail.SetSSLeay32(const aValue: string);
begin
 FSSLeay32 := aValue;
end;

procedure TSendMail.SetLibeay32(const aValue: string);
begin
 FLibeay32 := aValue;
end;

procedure TSendMail.SetSubject(const aValue: string);
begin
 FMsg.Subject := aValue;
end;

procedure TSendMail.setEmailSize(iEMailSize: Integer);
begin
 FiEMailSize := iEMailSize;
end;

function TSendMail.SendMail: Boolean;
var
 i: Integer;
begin
 Result := False;

 try
  FMsg.Subject := _MIMEConvert(FMsg.Subject);

  if FAttachmentList.Count > 0 then
   begin
    for i := 0 to FAttachmentList.Count - 1 do
     begin
      if TFile.Exists(FAttachmentList[i]) then
       begin
        TIdAttachmentFile.Create(FMsg.MessageParts, FAttachmentList[i]);

        TIdText.Create(FMsg.MessageParts).ContentType := 'text/html';
        TIdText.Create(FMsg.MessageParts).CharSet := 'ISO-8859-1';

        if i = 0 then
         TIdText.Create(FMsg.MessageParts).Body.Add(FMsg.Body.Text);
       end;
     end;
   end
  else
   begin
    FMsg.ContentType := 'text/html';
    FMsg.CharSet := 'ISO-8859-1';
   end;

  setEmailSize(Length(FMsg.Body.Text));
  FSmtp.ConnectTimeout := 10000;

  if GetUseSSL and TFile.Exists(FLibeay32) and TFile.Exists(FSSLeay32) then
   begin
    FSmtp.IOHandler := FIdSSLIOHandler;

    // Not needed?
    // fIdSSLIOHandler.SSLOptions.Mode := sslmUnassigned;
    // fIdSSLIOHandler.SSLOptions.VerifyMode := [];
    // fIdSSLIOHandler.SSLOptions.VerifyDepth := 0;
    //
    // fIdSSLIOHandler.Destination := getHost + ':' + IntToStr(getPort);
    // fIdSSLIOHandler.Host := getHost;
    // fIdSSLIOHandler.Port := getPort;

    FSmtp.UseTLS := TIdUseTLS(GetTLSMode);
    {*
     0 utNoTLSSupport
     1 utUseImplicitTLS
     2 utUseRequireTLS
     3 utUseExplicitTLS
     *}
   end;

  try
   FSmtp.Connect;

   if FSmtp.Connected then
    begin
     try
      FSmtp.Send(FMsg);
      Result := True;
     finally
      FSmtp.Disconnect;
     end;
    end;
  except
   Result := False;
  end;
 except
  Result := False;
 end;
end;

end.


Alle Zeitangaben in WEZ +1. Es ist jetzt 14:15 Uhr.
Seite 2 von 2     12   

Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz