Delphi 6 and Indy SSL connection not working - delphi

I need to consume a Web Service via SSL. In order to accomplish that I have built a web client in Delphi 6 that uses Indy to read the client certificates and write the soap request via https. The compilated version of the code is a DLL that runs in IIS 5.0. After tested the code in my local machine it works fine (I'm behind a proxy). But after the code is deployed to prod servers (not proxy) the SSL connection fails saying "Error connecting with SSL".
Here is my code:
var
Response: TStringStream;
IdHttp: TIdHTTP;
IdCnxSLL: TIdConnectionInterceptOpenSSL;
XmlSoapDoc: IXMLDocument;
begin
Response := TStringStream.Create('');
IdHttp := TIdHTTP.Create(nil);
IdCnxSLL := TIdConnectionInterceptOpenSSL.Create(nil);
XmlSoapDoc := TXMLDocument.Create(nil);
with IdCnxSLL do
begin
IdCnxSLL.SSLOptions.Method := sslvSSLv23;
IdCnxSLL.SSLOptions.RootCertFile := IniHttpConnectionData.Values['RootCertFile'];
IdCnxSLL.SSLOptions.CertFile := IniHttpConnectionData.Values['CertFile'];
IdCnxSLL.SSLOptions.KeyFile := IniHttpConnectionData.Values['KeyFile'];
IdCnxSLL.OnGetPassword := IdConInterceptOpenSSLGetPassword;
end;
with IdHttp do
begin
if bUseProxy then
begin
Request.ProxyServer := IniHttpConnectionData.Values['ProxyServer'];
Request.ProxyPort := StrToIntDef(IniHttpConnectionData.Values['ProxyPort'], 0);
end
else
begin
Host := IniHttpConnectionData.Values['HTTPHost'];
Port := StrToIntDef(IniHttpConnectionData.Values['HTTPPort'], 443);
end;
Request.ContentType := 'text/xml';
Intercept := IdCnxSLL;
InterceptEnabled := True;
end;
try
IdHttp.Post(ServiceURL, SoapEnv, Response);
except
on E:EIdOSSLConnectError do
LogError('SSL Connect Error: ' + E.Message);
on E:Exception do
LogError('Error' + E.ClassName + ' - ' + E.Message);
end;
I also try this code compiling into an exe program and it works. Is there something else I need to configure/add?
Thanks.

The fact that you are using TIdConnectionInterceptOpenSSL tells me that you are using a VERY old version of Indy. I am guessing Indy 8, which shipped with D6. Indy 8 and earlier are no longer officially supported by the Indy development team (which I am a member of). You really should upgrade to Indy 9, if not to Indy 10. In Indy 9, TIdConnectionInterceptOpenSSL was replaced with a new TIdSSLIOHandlerSocket component. Also, Indy 9 and earlier required custom-made OpenSSL DLLs, which may be contributing to your error as well, if you are using the wrong DLLs for your version of Indy. Indy 10, on the other hand, uses the standard DLLs from OpenSSL's website now.

Finnally It worked. Although I strongly encourage you to use a newer version of Indy as Remy suggests. I will post the steps that did the trick for me since there should be other people with the same problem.
The original code I posted is functional, it works when we need to post information via secured http (https) but the remote server requires prior authentification using a client certificate.
In order to make it work, it is necessary to verify the following:
TIdHttp and TIdConnectionInterceptOpenSSL configuration
Certificates
For the first 2 steps follow the steps mentioned here link text or (in case link is expired) Google "IndySSL - using certificate authentication". It worked for me.
Indy SSL DLLs. (For D6/Indy 8 download indy_openssl096g.zip from Indy SSL or Intelicom) This DLLs where the only ones that worked for this version of Indy.
Hope this will help.

Related

Http Post Indy10 Error Delphi 7: Error creating SSL context

I'm using Delphi 7 with Indy 10.6.2.5459 to make a POST request to a server from time to time:
sParams := '?ultimaAlteracao='+FormatDateTime('YYYY-MM-DD',now())+'T00:00:00.000';
FidHTTP := TIdHTTP.Create;
try
FidHTTP.Request.Clear;
FidHTTP.Request.Accept := 'application/json;charset=UTF-8';
FidHTTP.Request.CharSet := 'UTF-8';
FidHTTP.Response.ContentType := 'application/json;charset=UTF-8';
FidHTTP.Response.ContentEncoding := 'UTF-8';
FidHTTP.Request.CustomHeaders.AddValue('Authorization','Basic '+EncodeBase64('xx:xx#123456'));
JsonStream := TStringStream.Create('');
JsonStream.Position := 0;
try
FidHTTP.Get('https://'+server+'/LinxImportacaoArquivo/GetSelecaoDadosMDMNCM'+sParams, JsonStream);
DataString := JsonStream.DataString;
finally
FreeAndNil(JsonStream);
end;
finally
FreeAndNil(FidHTTP);
end;
After sometime, it begins to fail and returns:
Error creating SSL context. error:140A90F1:SSL
routines:SSL_CTX_new:unable to load ssl2 md5 routines
If I restart the application, it works for sometime again.
I found some people who had the same issue: here and here
From what I learned, it can be some other process which uses Indy to make a request that is interfering, and I quote
It appears to be an issue with some type of static member
initialization inside the openssl library. I have 2 libraries, both of
them use the openssl library, let's call them A and B. When the
application starts up both A & B are able to successfully create a
security context. Later, when library B tries to create another
security context it fails. Both library A and B are module plugins to
our application so they both will load but if one is not needed it is
unloaded.
Indeed, my application has a lot of others process executing, making http requests, through indy10 or WinInet.
So, my question is: Is there some procedure I can call on Indy10 to make it initialize something that had it freed on opensll library?
I found out that at unit IdSSLOpenSSL there's a procedure named UnLoadOpenSSLLibrary.
If I always call that procedure before my code, the error does not occurr.

how to make HTTPS calls on the iOS simulator Delphi seattle

OpenSSL not working for iOS Simulator in Delphi DX
Using info at:
http://blog.marcocantu.com/blog/using_ssl_delphi_ios.html
http://docwiki.embarcadero.com/RADStudio/Seattle/en/OpenSSL
https://plus.google.com/100777187605111792758/posts/SPnHdXvTTNu
I can get it to work on devices, but not on the iOS simulator. Same URL works when I use a TWebbrowser.navigate, but not with INDY of course.. See below, and possibly offer suggestions on how to make HTTPS calls on the iOS simulator ! This worked before in earlier versions of Rad Studio ( XE4, XE5 ) but hasnt since XE7 if my memory has served me right.
I have these files in my usr/lib folder:
libcrypto.0.9.8.dylib
libssl.0.9.8.dylib
Here is my uses
uses
IdSSLOpenSSL,
{$IF Defined(IOS) and Defined(CPUARM)}
IdSSLOpenSSLHeaders_Static,
{$ELSE}
IdSSLOpenSSLHeaders,
{$ENDIF}
...
Here is my onCreate for the main form
procedure TmLoginForm.FormCreate(Sender: TObject);
var
t:string;
begin
IdOpenSSLSetLibPath('/usr/lib/');
...
Here is part of a function that I use, where on the last line an exception is thrown
function ParseGroups(OnlyUserCreated:boolean):integer;
var
IdHTTP :TIdHTTP;
HTML :String;
JSON_Groups :TJSONObject;
Group :uGroup;
begin
result:=0;
HTML:='';
IdHTTP:=TIdHTTP.Create(nil);
IdHTTP.HandleRedirects:=false;
try
HTML:=IdHTTP.Get(URL_Host+ACCESSTOKEN);
Error is: 'Could Not Load SSL Library'
ShowMessage(IdSSLOpenSSLHeaders.WhichFailedToLoad); shows a blank message
Update:
adding
IdSSLOpenSSLHeaders.Load;
after setting the path now causes the whichFailedToLoad say: 'Failed to Load /usr/lib/libcrypto.'
Use System.Net.HttpClient.THTTPClient instead of the Indy components.
var
http : THTTPClient;
html : string;
http := THTTPClient.Create;
try
html := http.Get( url ).ContentAsString();
...
finally
http.Free;
end;
It is a wrapper of the http function from the operating system. If the OS supports https, then this class will do also.
You can also follow this nifty blogpost http://delphiworlds.com/2016/03/building-openssl-dylibs-for-ios-simulator/
It worked just fine for me. I needed it, because my Soap client needs to connect via https, and I did not want to rewrite the soap libs.

Indy10 + OpenSSL: send email code stopped working on Windows 8

Code stopped working on Windows 8.
It works fine on Windows7, Windows XP...
I found a workaround for this issue: start application in Windows compatibility mode: Windows XP (Service Pack 3) - code working.
Code not working if Windows compatibility mode is Windows 7.
I run application as Administrator. Have already tried to switch off antivirus and firewall. I can send email with the same parameters using another smtp client, e.g. .Net SmtpClient. The problem is reproduced on different Windows 8 computers(home, office).
I created simple test application. Code is written on Delphi XE, Indy 10.5.7, OpenSSL 1.0.1.3 dlls are placed in test.exe folder.
Any ideas?
Code:
SSLHandler.MaxLineAction := maException;
SSLHandler.SSLOptions.Method := sslvTLSv1;
SSLHandler.SSLOptions.Mode := sslmUnassigned;
SSLHandler.SSLOptions.VerifyMode := [];
SSLHandler.SSLOptions.VerifyDepth := 0;
SSLHandler.OnStatusInfo := IdSSLIOHandlerSocketOpenSSL1StatusInfo;
SMTP.IOHandler := SSLHandler;
SMTP.Host := 'smtp.gmail.com';
SMTP.Port := 587;
SMTP.UseTLS := utUseExplicitTLS;
SMTP.Username := FromAddress;
SMTP.Password := AuthPassword;
Email.From.Address := FromAddress;
Email.Recipients.EmailAddresses := ToAddress;
Email.Subject := Subject;
Email.Body.Text := Body;
SMTP.Connect;
SMTP.Send(Email);
SMTP.Disconnect;
Output:
SSL status: "before/connect initialization"
SSL status: "before/connect initialization"
SSL status: "SSLv3 write client hello A"
SSL status: "SSLv3 read server hello A"
EIdSocketError with message 'Socket Error # 10060 Connection timed out.'
It is IdHTTP's ReadTimeout. By default it is -1 and doesn't work with Windows 8. Set it to anything positive like 15000ms or 30000 will fix the problem.
Note that you need to set the numerical value programmatically on the IdHTTP object. Do not try to set the binded IoHandler via the object inspector because it won't work in that way.
Example:
IdHTTP1.ReadTimeout := 30000;
One tells Indy to use an infinite timeout on its socket operations. However, to work around a deadlock in OpenSSL on Vista+ when a connection is dropped, TIdSSLIOHandlerSocketOpenSSL forces a 30 second timeout at the lower socket layer if the ReadTimeout is <= 0.}
A solution Bob Daneshfar posted on this forum.
Finally I found that it is Indy related issue.
Upgrade to Indy 10.5.8 or 10.5.9 fixes the problem.
Thanks all for advices.
Since you can successfully send email using the .NET SmtpClient class, I suggest you use a packet sniffer, such as Wireshark, to view SmtpClient's network traffic and compare it to Indy/OpenSSL's network traffic and see exactly what the differences are. Something is happening during OpenSSL's TLSv1 handshake that is not happening to SmtpClient, so go see what their handshakes actually look like.
Are you sure you've distributed the OpenSSL libraries with you're application (like 'libeay32.dll' and 'ssleay32.dll')?
When you forget those, you get timeouts too, because the error of the OpenSSL library is not correctly transferred to the outer IO object (like TIdSMTP or TIdHTTP).
To check whether OpenSLL for Indy can load I use the following code (which raises an erre when SSL is not available) - uses unit 'IdSSLOpenSSL'
TIdSSLContext.Create.Free; // Raises an error, when unable to load SSL lib and such
You can also plug into the OpenSSL headers unit 'IdSSLOpenSSLHeader' and try to load the library manually and check whether it can:
if not IdSSLOpenSSLHeaders.Load then ; // Raises no error, but return 'true' when it can load

Delphi with indy

I just started using indy10 (today) in Delphi 2010, after reading everywere i managed to make it work, i can send emails using gmail, it works fine on my computer, but when i install the application on my laptop (for tests), it doesnt send the email and my app stops working, do i have to install something else on my laptop or how can i make it to work on every computer i install my program, so far i have to install it on 6 different computers, some use windows XP and some Windows 7, i hope there is a way to make it multiplatform or something.
This is my code:
procedure SendIndyMail;
begin
Form_final.IdSMTP1 .IOHandler := Form_final.IdSSLIOHandlerSocketOpenSSL1;
Form_final.IdSMTP1.Host:= 'smtp.gmail.com';
Form_final.IdSMTP1.Password:= 'xxxxxx';
Form_final.IdSMTP1.Port := 587;
Form_final.IdSMTP1.UseTLS := utUseExplicitTLS;
Form_final.IdSMTP1.Username := 'xxxxxx';
Form_final.IdSSLIOHandlerSocketOpenSSL1.Destination := 'smtp.gmail.com:587';
Form_final.IdSSLIOHandlerSocketOpenSSL1.Host := 'smtp.gmail.com';
Form_final.IdSSLIOHandlerSocketOpenSSL1.Port := 587;
Form_final.IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Method := sslvTLSv1;
Form_final.IdSSLIOHandlerSocketOpenSSL1.SSLOptions.Mode := sslmUnassigned;
Form_final.IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyMode := [];
Form_final.IdSSLIOHandlerSocketOpenSSL1.SSLOptions.VerifyDepth := 0;
Form_final.IdMessage1.Subject:=conect.Q_selec_info_generalDescripcion.Text+' '+DateToStr(Date);
Form_final.IdMessage1.Recipients.EMailAddresses:=conect.Q_config_seleccorreo.Text;
TIdAttachmentFile.Create(Form_final.IdMessage1.MessageParts, conect.Q_config_selecfolder.Text+'\reporte_'+FormatDateTime('dddd d of mmmm yyyy', Date)+' Inventario '+Form_inventario.Edit_id_inventario.Text+'.pdf');
Form_final.IdSMTP1.Connect;
Form_final.IdSMTP1.Send(Form_final.IdMessage1);
Form_final.IdSMTP1.Disconnect;
end;
I ran the proyect on my laptop and it says:
Could not load SSL Library, now, i did many things to make it work, downloaded many things and tried many other, now i dont know where those libraries are and how to retrieve them, and i would like to know of a way to load them with the installation so my installer goes with everything needed.
Thanks in advance.
Make sure you have the OpenSSL DLLs on your target machines, preferrably in your app's installation folder. If you still get the error, Indy's WhichFailedToLoad() function in the IdSSLOpenSSLHeaders unit can tell you why it could not load the OpenSSL DLLs. As for the DLLs themselves, you can download Indy-compatible copies from Indy's Fulgan mirror.
On a side note, you do not need to set the IOHandler's Destination, Host, or Port properties. The Connect() method will handle that internally for you.

INDY 10.1.5 - Which SSL dlls work with Delphi 2006?

I'm trying to connect to google documents (following Marco Cantu's excellent REST example) but I am getting the following SSL errors:
1) If I use the SSL dlls from openssl-0.9.8i-i386-win32.zip I get the error:
"Could not load SSL library"
2) If I use the SSL dlls from indy_OpenSSL096m.zip I get the error:
"Error connecting with SSL"
3) If I use the SSL dlls from openssl-0.9.8h-i386-win32-Indy-IntraWebEdition.zip I get the error:
"Could not load SSl Library"
Now I've researched this and there are a lot of recommendations with dead links to dlls about, including links on stack overflow. I suspect I need to find the SSL dlls that are compatible with the version of INDY I am using.
My question is, does anyone know exactly which SSL dlls are compatible with Delphi 2006 & INDY 10.1.5?
I had the same problem even after I upgrading to INDY 10.2.3 and I tryed every different version of the “libeay32.dll” and “ssleay32.dll” files I could find ... Like Matt I always got one of the two errors: "Could not load SSL library" or the "Error connecting with SSL" with something like "error:00000006:lib(0):func(0):EVP lib" ...
I was very happy when I change the TidSSLioHandlerSocketOpenSSL.SSLOptions.Method to sslvSSLv23 and everything started working.
A bit more research and I quickly understood anytime I got the error "Could not load SSL library" I was using the wrong version of the DLL files and anytime I got the "Error connecting with SSL" with something like "error:00000006:lib(0):func(0):EVP lib" I was using the wrong SSLOptions.Method value.
Other Info: I'm using Delphi 2006, INDY 10.2.3 and I'm runnin on WinXP Pro
This caused me so much pain, I hope this post will save someone some time.
You could resort to some trial and error using downloads from the Fulgan site.
You might want to think about updating your copy of Indy and using the most recent OpenSSL DLLs.
FWIW, since I have spent a lot of time getting this https thing to work, here are the results of my successful efforts.
1- Delphi 7
2- indy9.0.19_d7.exe
3- IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLSv1; or,
IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLSv23; or,
IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLSv3;
I tried indy10.0.76_d7.exe and indy10.1.5_d7.exe under Delphi 7 and I cannot get them to install properly, let alone get HTTPS to work. I get the infamous message "Unit IdSysWin32 was compiled with a different version of IdException.EIdException." I searched for a solution to that problem on the web and couldn't find one - loads of others had the same message.
A useful site for testing https is https://msp.f-secure.com/web-test/common/test.html
Here is my source:
procedure TForm1.ButtonHTTPSClick(Sender: TObject);
var
IdHTTP1: TIdHTTP;
ParamStringList: TStringList;
s1: String;
MemoryStream1: TMemoryStream;
IdSSLIOHandlerSocket1: TIdSSLIOHandlerSocket;
begin // ssl works fine must have Indy version indy9.0.19_d7.exe and must use option sslvSSLv23
Screen.Cursor := crHourGlass;
IdHTTP1 := TIdHTTP.Create(nil);
IdSSLIOHandlerSocket1 := TIdSSLIOHandlerSocket.Create(nil);
IdHTTP1.IOHandler := IdSSLIOHandlerSocket1;
// IdSSLIOHandlerSocket1.SSLOptions.Method := sslvTLSv1; // sslvSSLv1 works fine
IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv3; // sslvSSLv3 works fine
// IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv23; // sslvSSLv23 works fine
// IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv2; sslvSSLv2 does not work
IdSSLIOHandlerSocket1.SSLOptions.Mode := sslmUnassigned;
IdSSLIOHandlerSocket1.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocket1.SSLOptions.VerifyDepth := 0;
ParamStringList := TStringList.Create;
MemoryStream1 := TMemoryStream.Create;
s1 := IdHTTP1.Post('https://msp.f-secure.com/web-test/common/test.html', ParamStringList);
MemoryStream1.Write(s1[1], Length(s1));
MemoryStream1.Position := 0;
MemoryStream1.SaveToFile('c:\temp\MemoryStream1.txt');
Memo1.Lines.Clear;
Memo1.Lines.LoadFromFile('c:\temp\MemoryStream1.txt');
MemoryStream1.Free;
ParamStringList.Free;
IdSSLIOHandlerSocket1.Free;
IdHTTP1.Free;
Screen.Cursor := crDefault;
end;
As far as I am aware the more recent versions of Indy work with standard OpenSSL binaries.
Download from here. We produced a Delphi FTP client app a while ago using Indy with SSL connections and I'm sure we just shipped the current OpenSSL dlls.
Edit: Just checked the app directory and the DLLs we used are OpenSSL 0.9.8.2 (3-Aug-06). (It's an old app)
Edit 2: And I've just copied the more recent 0.9.8k dlls over and they work fine too.
Find the Indy version you are using.Copy the Indy dlls i.e libeay32.dll,libssl32.dll and
ssleay32.dll into the Windows/System 32 Folder.It will resolve the error "Could not Load SSL Library"

Resources