TIdhttp HTTPS handshake Failed - delphi

I am using Indy 10 to connect to a SOAP Web Service. When I run the code with Fiddler running I find the webserver is not negotiating our Handshake. I have attached a screen shot of the Fiddler Inspectors.
We have been able to successfully connect to the server using the shareware application "SoapUI". I have attached a screen shot of the inspectors when using SoapUI.
One thing I notice is SoapUI is using a different version of SSL/TLS. How do I configure Indy to use the same version?
Any other insight as to why my call is failing?
procedure TForm6.Button1Click(Sender: TObject);
var
idhttp: TIdhttp;
IdSSLIOHandlerSocket1 : TIdSSLIOHandlerSocketOpenSSL;
Params : TStringStream;
begin
idhttp := TIdhttp.Create(nil);
IdSSLIOHandlerSocket1 := TIdSSLIOHandlerSocketOpenSSL.create(nil);
idhttp.ProxyParams.ProxyServer := '127.0.0.1';
idhttp.ProxyParams.ProxyPort := 8888 ;
idhttp.Request.ContentType := 'text/xml';
idhttp.Request.CharSet:='utf-8';
idhttp.request.connection := 'keep-alive';
idhttp.Request.CustomHeaders.AddValue('Content-Type','text/xml;charset=UTF-8');
idhttp.Request.CustomHeaders.AddValue('SOAPAction','"http://ws.nemsis.org/SubmitData"');
idhttp.Request.CustomHeaders.AddValue('Host','nemsis.org:443');
idhttp.Request.BasicAuthentication := True;
idhttp.request.username := 'xxxxx';
idhttp.request.password := 'yyyyy';
with IdSSLIOHandlerSocket1 do begin
SSLOptions.Method := sslvTLSv1_2;
SSLOptions.SSLVersions := [sslvTLSv1_2];
SSLOptions.VerifyMode := [];
SSLOptions.VerifyDepth := 2;
end;
with IdHTTP do begin
IOHandler := IdSSLIOHandlerSocket1;
end;
Params := TStringStream.Create(filetostring(ExtractFileDir(ParamStr(0))+'\sample.xml'));
idhttp.Post('https://nemsis.org:443/NemsisV3Validator4/NemsisWsService',Params);
end;
Failed Call:
Successful Call using SoapUI:

Related

Delphi EIdOSSLUnderlyingCryptoError Exception - SSL3_GET_RECORD Wrong Version Number

I tried using TRESTClient to connect to an HTTPS web service using TLS 1.2. But NO LUCK with sending multipart/form-data.
So now I am trying with Indy. I got this "Wrong Version Number" error.
I think there is nothing wrong with the code since it worked with HTTP.
Probably my Delphi is missing something. What should I install and how?
procedure TForm10.Button2Click(Sender: TObject);
var
HTTP: TIdHTTP;
RequestBody: TStream;
ResponseBody: string;
myssl: TIdSSLIOHandlerSocketOpenSSL;
Input: TIdMultipartFormDataStream;
begin
ResponseBody := '';
try
try
HTTP := TIdHTTP.Create;
try
Input := TIdMultipartFormDataStream.Create;
try
Input.Clear;
Input.AddFormField('Email', 'xx#xx.com.tr');
Input.AddFormField('Password', 'xx');
myssl := TIdSSLIOHandlerSocketOpenSSL.Create(HTTP);
HTTP.IOHandler := myssl;
myssl.SSLOptions.Mode := sslmUnassigned;
myssl.SSLOptions.Method := sslvTLSv1_2;
myssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
HTTP.HTTPOptions := [hoForceEncodeParams];
HTTP.Request.CustomHeaders.FoldLines := False;
ResponseBody := HTTP.Post('https://xxx.com.tr/api/Mobile/MobileLoginControl', Input);
finally
Input.Free;
end;
finally
HTTP.Free;
end;
finally
end;
except
ResponseBody := '"-20"';
end;
end;
The code is fine, though you are enabling only TLS 1.2 on the SSLIOHandler. Maybe the website in question doesn't support TLS 1.2? Try enabling TLS 1.0 and 1.1 as well:
myssl.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
And don't set the SSLOptions.Method at all. Setting the SSLVersions updates the Method and vice versa. So set one or the other, not both.

Using Indy to retrieve Revcontent OAuth Token

I am trying to use Indy to retrieve a RevContent oAuth token according to this page. Here is my code:
procedure TForm2.Button1Click(Sender: TObject);
var
IdSSLIOHandlerSocket1: TIdSSLIOHandlerSocketOpenSSL;
idhttp:tidhttp;
params: TStringList;
begin
idhttp:=tidhttp.create(self);
IdSSLIOHandlerSocket1 := TIdSSLIOHandlerSocketOpenSSL.create(nil);
with IdSSLIOHandlerSocket1 do begin
SSLOptions.Method := sslvSSLv23;
SSLOptions.SSLVersions := [sslvSSLv23];
end;
params := TStringList.create;
params.add('clientid=xxyyzz');
params.add('client_secret=xxyyzzxxyyzzxxyyzzxxyyzzxxyyzzxxyyzz');
params.add('grant_type=client_credentials');
with IdHTTP do begin
IOHandler := IdSSLIOHandlerSocket1;
Request.ContentType := 'application/x-www-form-urlencoded';
end;
showmessage(idhttp.Post('https://api.revcontent.io/oauth/token',params));
end;
But whenever I run it I get an 400 Bad Request error. What am I doing wrong?
Use client_id, not clientid.
Do not use SSL3, that site supports TLS1.
Do not set ContentType.
Use try/except around Post to catch exception and get full error message (E as EIdHTTPProtocolException).ErrorMessage

delphi 2006 indy https post time out

I have to use Delphi 2006. I have to use Indy 10.1.5 - comes with Delphi 2006 or not, but I have to use these versions! I found an example how to use indy SSL https get but now I completely lost my head and close to to do another 'bad day' video!
Finally, the SSL library loaded without any problem.
But... Why I get always 'EidReadTimeout with message 'Read Timeout'
here is my code:
var
IdHTTP1: TIdHTTP;
ParamStringList: TStringList;
s1: String;
IdSSLIOHandlerSocket1: TIdSSLIOHandlerSocketOpenSSL;
begin
IdHTTP1 := TIdHTTP.Create(nil);
IdSSLIOHandlerSocket1 := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
IdSSLIOHandlerSocket1.ReadTimeout := 10000;
IdHTTP1.IOHandler := IdSSLIOHandlerSocket1;
IdHTTP1.ConnectTimeout := 10000;
IdSSLIOHandlerSocket1.SSLOptions.Method := sslvSSLv23; // Which one is the good for...
IdSSLIOHandlerSocket1.SSLOptions.Mode := sslmClient;
IdSSLIOHandlerSocket1.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocket1.SSLOptions.VerifyDepth := 0;
ParamStringList := TStringList.Create;
ParamStringList.Text := '';
s1 := IdHTTP1.Post('https://msp.f-secure.com/web-test/common/test.html', ParamStringList);
Memo1.Text := s1;
ParamStringList.Free;
IdSSLIOHandlerSocket1.Free;
IdHTTP1.Free;
end;
Any idea? What can I missed?
I changed the timeout between 3 and 100 seconds, but no changes when I tried to ran my code.
Thanks in advance!

Seeing Indy Traffic in Fiddler

I think this is an easy question for someone familiar with Indy. I'm using Delphi 2010 and Indy 10. I am trying to get off the ground accessing an SSL web service. I think it will be a lot easier if I can get Fiddler to see my HTTP traffic. I have seen posts on StackOverflow that indicate it's no big thing to get Fiddler to see your Indy traffic, that you just have to configure the port to make it work. My question is how do you do that?
Here is my code so far:
procedure TForm1.Button1Click(Sender: TObject);
var slRequest: TStringList;
sResponse,
sFileName: String;
lHTTP: TIdHTTP;
lIOHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
sFileName := 'Ping.xml';
slRequest := TStringList.Create;
try
slRequest.LoadFromFile(sFileName);
lHTTP := TIdHTTP.Create(nil);
lHTTP.Intercept := IdLogDebug1;
lIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
try
lHTTP.IOHandler := lIOHandler;
sResponse := lHTTP.Post('https://FSETTESTPROD.EDD.CA.GOV/fsetservice', slRequest);
Memo1.Lines.Text := sResponse;
finally
lIOHandler.Free;
end;
finally
slRequest.Free;
end;
end;
Edit: If I don't use the proxy for Fiddler and click the button while Wireshark is running, I get this traffic in Wireshark.
You can set Indy to use the proxy fiddler provides easily by setting the ProxyParams:
try
lHTTP.IOHandler := lIOHandler;
lHTTP.ProxyParams.ProxyServer := '127.0.0.1';
lHTTP.ProxyParams.ProxyPort := 8888;
sResponse := lHTTP.Post('<URL>', slRequest);
Memo1.Lines.Text := sResponse;
finally
lIOHandler.Free;
end;
You should be able to see all traffic in Fiddler then.
Edit: If that does not work you can add a TIdLogDebug component and add it as interceptor (like you did in your question).
The OnReceive and OnSend events contain the complete headers sent and received aswell as the reply data:
procedure TForm10.captureTraffic(ASender: TIdConnectionIntercept;
var ABuffer: TArray<Byte>);
var
i: Integer;
s: String;
begin
s := '';
for i := Low(ABuffer) to High(ABuffer) do
s := s + chr(ABuffer[i]);
Memo1.Lines.Add(s);
end;

Post problems with Indy TIdHTTP

I am having issues posting to Amazon's SES Service using Indy's TIdHTTP.
Here is an example of the code i am using:
procedure TMainFrm.btnAmazonSESClick(Sender: TObject);
var
SSLHandler: TIdSSLIOHandlerSocket;
HttpClient: TIdHTTP;
Params: TStringStream;
begin
SSLHandler := TIdSSLIOHandlerSocket.Create(Self);
HttpClient := TIdHTTP.Create(Self);
Params := TStringStream.create('');
try
with SSLHandler do
SSLOptions.Method := sslvSSLv3
with HttpClient do
begin
IOHandler := SSLHandler;
AllowCookies := True;
HandleRedirects := True;
HTTPOptions := [hoForceEncodeParams];
Request.ContentType := 'application/x-www-form-urlencoded';
end;
PageMemo.Text := HttpClient.Post('https://email.us-east-1.amazonaws.com?Action=VerifyEmailAddress&AWSAccessKeyId=012Some123Key46&EmailAddress=test#test%2Ecom', Params);
finally
SSLHandler.Free;
HttpClient.Free;
Params.Free;
end;
end;
Result
Under Indy 10.5.7 I get the error: HTTP/1.1 404 Not Found
Under Indy 9.0.14 I get the error: Socket Error # 11004
Debugging Trials
This same demo can successfully GET the HTML from an HTTPS web page.
If i paste the URL above into a browser it displays the expected XML result.
I would appreciate any advice on the cause.
This post is just an incomplete wild guess.
Maybe Remy might help you to correct it. With the following code I'm getting HTTP/1.1 400 Bad Request but I'm not wondering because the API reference talks about Common Query Parameters where is at least required the digital signature you'll create for the request what I don't know how to do.
I can't test this at all because I have no account there. But I think the
procedure TForm1.Button1Click(Sender: TObject);
var
HTTPClient: TIdHTTP;
Parameters: TStrings;
SSLHandler: TIdSSLIOHandlerSocketOpenSSL;
begin
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create(nil);
HTTPClient := TIdHTTP.Create(nil);
Parameters := TStringList.Create;
try
SSLHandler.SSLOptions.Method := sslvSSLv3;
SSLHandler.SSLOptions.Mode := sslmUnassigned;
HTTPClient.IOHandler := SSLHandler;
HTTPClient.HTTPOptions := [hoForceEncodeParams];
HTTPClient.Request.ContentType := 'application/x-www-form-urlencoded';
Parameters.Add('Action=VerifyEmailAddress');
Parameters.Add('EmailAddress=test#test.com');
Parameters.Add('AWSAccessKeyId=012Some123Key46');
Parameters.Add('SignatureVersion=2');
Parameters.Add('Expires='); // ???
Parameters.Add('Signature='); // ???
PageMemo.Text := HTTPClient.Post('https://email.us-east-1.amazonaws.com', Parameters);
finally
SSLHandler.Free;
HTTPClient.Free;
Parameters.Free;
end;
end;
Basically, you need to use the right library, i.e.:
For Indy 10.5.7 use openssl-1.0.1e-i386-win32 or openssl-1.0.1e-x64_86-win64 from http://indy.fulgan.com/SSL/
You may want to download an ssl demo from: http://indy.fulgan.com/ZIP/
Regards
Jose

Resources