Delphi TidHTTP web service security usernametoken - delphi

I am trying to use Delphi and Indy's TIdHTTP to access a site using the security usernametoken aspect.
The SOAP request has headers for password type=urladdressforoasis password
The server's classnameproxy.config file from the vendor has this:
<basicHttpBinding>
<binding name="BasicHttpBinding_ZZ_myInt">
<security mode="TransportWithMessageCredential" />
</binding>
</basicHttpBinding>
So I am trying to add custom headers to TIdHTTP using the following code:
idHTTP.Request.CustomHeaders.AddValue('Authorization', 'Basic ' + TIdEncoderMIME.EncodeString(string(aUserID) + ':' + string(aPWD), IndyTextEncoding_ASCII()));
Obviously this is incorrect for some reason. I have looked around for TIdHTTP and oasis and usernametoken but found nothing. Maybe I am looking for the wrong keywords?
Is it possible to use TIdHTTP to access web services using a security usernametoken?
function Post_XML(aURL, aUserID, aPWD, aInputFile, aOutputFile, aContentType, aCharset, aShow: pAnsiChar):integer; stdcall;
var
sRequest,
sResponse : TFileStream;
idHTTP : TidHTTP;
SSLHandler : TidSSLIOHandlerSocketOpenSSL;
EnvVar : string;
begin
Result := 0;
begin
try
begin
sRequest := TFileStream.Create(string(aInputFile), fmOpenRead or fmShareDenyWrite);
sResponse := TFileStream.Create(string(aOutputFile), fmCreate or fmShareDenyRead or fmOpenWrite);
end;
except on E: Exception do
begin
Result := 99;
end;
end;
try
begin
EnvVar := '';
EnvVar := System.SysUtils.GetEnvironmentVariable('use_a_proxy');
SSLHandler := TIdSSLIOHandlerSocketOpenSSL.Create;
SSLHandler.SSLOptions.SSLVersions := [sslvSSLv23, sslvSSLv3, sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
SSLHandler.SSLOptions.Mode := sslmUnassigned;
idHTTP := TidHTTP.Create;
idHTTP.ConnectTimeout := 60000;
idHTTP.ReadTimeout := 60000;
idHTTP.HandleRedirects := True;
idHTTP.IOHandler := SSLHandler;
if UpperCase(EnvVar) = 'ON' then
begin
idHTTP.ProxyParams.ProxyServer := '127.0.0.1';
idHTTP.ProxyParams.ProxyPort := 8888;
end;
idHTTP.Request.ContentType := string(aContentType);
idHTTP.Request.CharSet := string(aCharSet);
idhttp.Request.CustomHeaders.AddValue('SOAPAction', 'http://bustax.tntax.tn.gov/BusTaxRequest');
if aUserid <> '' then
begin
idHTTP.Request.BasicAuthentication := True;
idhttp.Request.Username := aUserid;
idHTTP.Request.Password := aPwd;
end;
idHTTP.Post(trim(string(aURL)), sRequest, sResponse);
FreeAndNil(SSLHandler);
FreeAndNil(idHTTP);
end;
except
on E: EIdHTTPProtocolException do
begin
ShowMessage(AnsiString('Protocol Error: ' + E.Message));
Result := E.ErrorCode;
end;
on E: EIdSocketError do
begin
ShowMessage(AnsiString('Socket Error: ' + E.Message));
Result := E.LastError;
end;
on E: EIdException do
begin
ShowMessage(AnsiString('HTTP Error: ' + E.Message));
Result := HTTPMain.ResponseCode;
end;
on E: Exception do
begin
ShowMessage(AnsiString('Error: ' + E.Message));
Result := HTTPMain.ResponseCode;
end;
end;
FreeAndNil(sRequest);
FreeAndNil(sResponse);
end;
end;
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/" xmlns:oas="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-wssecurity-secext-1.0.xsd" xmlns:bus="http://bustax.tntax.tn.gov">
<soapenv:Header>
<oas:Security>
<oas:UsernameToken>
<oas:Username>myUsername</oas:Username>
<oas:Password Type="http://docs.oasis-open.org/wss/2004/01/oasis-200401-wss-username-token-profile-1.0#PasswordText">myPassword</oas:Password>
</oas:UsernameToken>
</oas:Security>
</soapenv:Header>
<soapenv:Body>
<bus:BusTaxRequest>
<bus:JurisdictionSITUS>1900</bus:JurisdictionSITUS>
<bus:TransactionId>123456</bus:TransactionId>
</bus:BusTaxRequest>
</soapenv:Body>
</soapenv:Envelope>

Related

"SSL negotiation failed" in Delphi 11 while using office356 smtp server

I tried to send mail using office365 smtp server but i am getting error "SSL Negotiation Failed". I have the latest openssl dll files. So the host in that case is smtp.office365.com.
I also tried a code sample from other post but with no success.
Can you help me please ?
procedure TForm7.Button3Click(Sender: TObject);
var
IdSMTPa: TIdSMTP;
IdMessage1: TIdMessage;
IdSSL: TIdSSLIOHandlerSocketOpenSSL;
begin
IdSMTPa := TIdSMTP.Create(nil);
try
IdSMTPa.Host := 'smtp.office365.com';
IdSMTPa.Port := 587;
IdSMTPa.Username := 'mymail#mydomain.gr';
IdSMTPa.Password := 'mypwd';
IdSMTPa.AuthType := satDefault;
// IO HANDLER Settings //
IdSSL := TIdSSLIOHandlerSocketOpenSSL.Create(IdSMTPa);
IdSSL.SSLOptions.SSLVersions := [sslvTLSv1, sslvTLSv1_1, sslvTLSv1_2];
IdSSL.SSLOptions.Mode := sslmUnassigned;
IdSSL.SSLOptions.VerifyMode := [];
IdSSL.SSLOptions.VerifyDepth := 0;
IdSMTPa.IOHandler := IdSSL;
IdSMTPa.UseTLS := utUseExplicitTLS;
IdMessage1 := TIdMessage.Create(nil);
try
IdMessage1.From.Address := 'mymail#mydomain.gr';
IdMessage1.Recipients.EMailAddresses := 'user1#mydomain.gr';
IdMessage1.CCList.EMailAddresses := 'user1#mydomain.gr';
IdMessage1.Subject := 'Test Email Subject';
IdMessage1.Body.Add('Test Email Body');
IdMessage1.Priority := mpHigh;
try
IdSMTPa.Connect();
try
IdSMTPa.Send(IdMessage1);
ShowMessage('Email sent');
finally
IdSMTPa.Disconnect();
end;
except
on e: Exception do
begin
ShowMessage('ERROR : '+e.Message);
end;
end;
finally
IdMessage1.Free;
end;
finally
IdSMTPa.Free;
end;
end;

Delphi SSL MITM Proxy based on INDY - problem with content loading

I'm writing MITM ssl proxy using indy. i use IdHTTPserver component with self signed certificate for proxy server, and on event of CommandOther i do TcpCleint request to site and return data in HTTPServer. But problem is, some scripts, especially JS and some pictures from web pages not being loaded at all, or load after timeout, so i recieve html code in browser, but crippled by not working js (mostly). Here's my code for CommandOther:
procedure TForm3.IdHTTPServer1CommandOther(AContext: TIdContext;
ARequestInfo: TIdHTTPRequestInfo; AResponseInfo: TIdHTTPResponseInfo);
var
client: TIdTCPClient;
Headers, headers1: TIdHeaderList;
s, ResponseCode, ResponseText: string;
req,req2:string;
Size: Int64;
Strm,strm2: TIdTCPStream;
ssl: TIdSSLIOHandlerSocketOpenSSL;
clientcount:integer;
begin
Memo3.lines.Add('start');
client := TIdtCPClient.Create(nil);
ssl := TIdSSLIOHandlerSocketOpenSSL.Create(client);
client.IOHandler := ssl;
s := ARequestInfo.URI;
client.Host := Fetch(s, ':', True);
client.Port := StrToIntDef(s, 443);
client.ConnectTimeout := 2000;
s := '';
Memo3.lines.Add('connecting');
client.UseNagle:=true;
client.Connect;
//here i handle CONNECT command
AResponseInfo.ResponseNo := 200;
AResponseInfo.ResponseText := 'Connection established';
aresponseinfo.WriteHeader;
// activate SSL between this proxy and the client
TIdSSLIOHandlerSocketOpenSSL(AContext.Connection.Socket).PassThrough
:= false;
Memo3.lines.Add('connected');
while AContext.Connection.Connected and Client.Connected do
begin
try
memo4.Lines.Add('---start header-------');
headers1 := TIdHeaderList.Create(QuoteHTTP);
headers1.FoldLength := MaxInt;
repeat
s := AContext.Connection.IOHandler.ReadLn;
Memo4.lines.Add(s);
headers1.Add(s);
if s = '' then
Break;
until False;
client.WriteHeader(headers1);
memo4.Lines.Add('-----header written-----');
memo5.Lines.Add('----------');
if Headers1.IndexOfName('Content-Length') <> -1 then
begin
strm2:=TIdTCPStream.Create(client);
memo5.Lines.Add('post');
Size := StrToInt64(Headers1.Values['Content-Length']);
if Size > 0 then
AContext.Connection.IOHandler.ReadStream(Strm2, Size, False);
end;
memo4.Lines.Add('---response headers-------');
Headers := TIdHeaderList.Create(QuoteHTTP);
try
Headers.FoldLength := MaxInt;
repeat
s := client.IOHandler.ReadLn;
Memo4.lines.Add(s);
acontext.Connection.IOHandler.WriteLn(s);
Headers.Add(s);
if s = '' then
Break;
until False;
memo4.Lines.Add('---respone headers read-------');
Strm := TIdTCPStream.Create(AContext.Connection);
try
if Pos('chunked', Headers.Values['Transfer-Encoding']) <> 0 then
begin
memo4.Lines.Add('chunked');
repeat
s := client.IOHandler.ReadLn;
AContext.Connection.IOHandler.WriteLn(s);
Size := StrToInt64('$' + Fetch(s, ';'));
if Size = 0 then
Break;
client.IOHandler.ReadStream(Strm, Size, False);
s := client.IOHandler.ReadLn;
AContext.Connection.IOHandler.WriteLn(s);
until False;
repeat
s := client.IOHandler.ReadLn;
AContext.Connection.IOHandler.WriteLn(s);
until s = '';
end
else if Headers.IndexOfName('Content-Length') <> -1 then
begin
Size := StrToInt64(Headers.Values['Content-Length']);
end;
if Size > 0 then
client.IOHandler.ReadStream(Strm, Size, False);
end
else
begin
memo5.Lines.Add('big read(');
AResponseInfo.CloseConnection := true;
try
client.IOHandler.ReadStream(Strm, -1, True);
except
on E: EIdSocketError do
begin
raise;
end;
end;
end;
finally
Strm.Free;
end;
finally
Headers.Free;
strm2.Free;
headers1.Free;
end;
finally
client.Disconnect;
end;
client.Free;
end;
end;

TIdSMTP & TIdAttachmentMemory - Email refused by spam filter

I am trying to send an email with a PDF attachment, stored in a BLOB field, using TIdSMTP. For this I am using a TIdAttachmentMemory, but the code as shown results in 'refused by spam filter';
Omitting IdMessage.ContentType := 'multipart/mixed' works but the attachment is not sent (or received?) - as expected.
Leaving this statement and creating the attachment from a file (as in the commented code) it all works fine (i.e. mail correctly received with attachment).
Clearly I am missing something. I am suspecting something in the direction of the attachment not being "closed off" correctly (i.e. left in an incomplete state) or perhaps the incorrect ContentType?
All suggestions welcome. Thanks!
procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
ms: TMemoryStream;
Attachment: TIdAttachmentMemory;
// Attachment: TIdAttachmentFile;
begin
memStatus.Clear;
IdSSLIOHandlerSocketOpenSSL.Destination := teHost.Text + ':587';
IdSSLIOHandlerSocketOpenSSL.Host := teHost.Text;
// IdSSLIOHandlerSocketOpenSSL.MaxLineAction := maException;
IdSSLIOHandlerSocketOpenSSL.Port := 587;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmUnassigned;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.Host := teHost.Text;
IdSMTP.Port := 587;
IdMessage.From.Address := teFrom.Text;
IdMessage.Recipients.EMailAddresses := teTo.Text;
IdMessage.Subject := teSubject.Text;
IdMessage.Body.Text := memBody.Text;
IdMessage.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
IdMessage.ContentType := 'multipart/mixed';
if not sqlPDFPDF_Incasso.IsNull then
begin
ms := TMemoryStream.Create;
try
try
TBlobField(sqlPDF.FieldByName('PDF_Incasso')).SaveToStream(ms);
ms.Position := 0;
Attachment := TIdAttachmentMemory.Create(IdMessage.MessageParts, ms);
Attachment.ContentType := 'application/pdf';
Attachment.FileName := 'Invoice.pdf';
except
on E: Exception do
messageDlg('Error creating attachment' + #13#10 + E.Message, mtError, [mbOK], 0);
end;
finally
ms.Free;
end;
end;
// if FileExists(beAttachment.Text) then
// Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, beAttachment.Text);
Screen.Cursor := crHourGlass;
try
try
IdSMTP.Connect;
IdSMTP.Send(IdMessage);
memStatus.Lines.Insert(0, 'Email sent - OK.');
except
on E: Exception do
memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
finally
if assigned(Attachment) then
Attachment.Free;
if IdSMTP.Connected then
IdSMTP.Disconnect(true);
Screen.Cursor := crDefault;
end;
end;
You are not populating the TIdMessage correctly (see this blog article for details - your use-case would fall under the "HTML and non-related attachments and no plain-text" section, but replacing HTML with Plain-Text).
In a nutshell, if you include the attachment, setting the TIdMessage.ContentType to 'multipart/mixed' is fine, but you need to put the body text into a TIdText object in the TIdMessage.MessageParts instead of in the TIdMessage.Body. And if you don't include the attachment, using the TIdMessage.Body is fine, but you need to set the TIdMessage.ContentType to 'text/plain' instead.
Try this:
procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
Text: TIdText;
Attachment: TIdAttachmentMemory;
Strm: TStream;
begin
memStatus.Clear;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.Host := teHost.Text;
IdSMTP.Port := 587;
try
IdMessage.Clear;
IdMessage.From.Address := teFrom.Text;
IdMessage.Recipients.EMailAddresses := teTo.Text;
IdMessage.Subject := teSubject.Text;
//if FileExists(beAttachment.Text) then
if not sqlPDFPDF_Incasso.IsNull then
begin
IdMessage.ContentType := 'multipart/mixed';
Text := TIdText.Create(IdMessage.MessageParts, nil);
Text.Body.Text := memBody.Text;
Text.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
Text.ContextType := 'text/plain';
//Attachment := TIdAttachmentFile.Create(IdMessage.MessageParts, beAttachment.Text);
Attachment := TIdAttachmentMemory.Create(IdMessage.MessageParts);
Attachment.ContentType := 'application/pdf';
Attachment.FileName := 'Invoice.pdf';
Strm := Attachment.PrepareTempStream;
try
TBlobField(sqlPDFPDF_Incasso).SaveToStream(Strm);
finally
Attachment.FinishTempStream;
end;
end else
begin
IdMessage.ContentType := 'text/plain';
IdMessage.Body.Text := memBody.Text;
IdMessage.Body.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
end;
Screen.Cursor := crHourGlass;
try
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
memStatus.Lines.Insert(0, 'Email sent - OK.');
finally
Screen.Cursor := crDefault;
end;
except
on E: Exception do
memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
end;
Alternatively, Indy has a TIdMessageBuilderPlain class that can setup the TIdMessage properly for you (see this blog article for details - your use-case would fall under the "Plain-text and HTML and attachments: Non-related attachments only" section):
uses
..., IdMessageBuilder;
procedure TfrmSendMail.btnSendClick(Sender: TObject);
var
Strm: TStream;
Bldr: TIdMessageBuilderPlain;
begin
memStatus.Clear;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method := sslvTLSv1_2;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Mode := sslmClient;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyMode := [];
IdSSLIOHandlerSocketOpenSSL.SSLOptions.VerifyDepth := 0;
IdSMTP.Host := teHost.Text;
IdSMTP.Port := 587;
try
IdMessage.Clear;
IdMessage.From.Address := teFrom.Text;
IdMessage.Recipients.EMailAddresses := teTo.Text;
IdMessage.Subject := teSubject.Text;
Strm := nil;
try
Bldr := TIdMessageBuilderPlain.Create;
try
Bldr.PlainText.Text := memBody.Text;
Bldr.PlainText.Add('Timestamp: ' + FormatDateTime('yyyy-mm-dd hh:nn:ss', Now()));
//if FileExists(beAttachment.Text) then
if not sqlPDFPDF_Incasso.IsNull then
begin
//Bldr.Attachments.Add(beAttachment.Text);
Strm := sqlPDFPDF_Incasso.DataSet.CreateBlobStream(sqlPDFPDF_Incasso, bmRead);
Bldr.Attachments.Add(Strm, 'application/pdf').WantedFileName := 'Invoice.pdf';
end;
Bldr.FillMessage(IdMessage);
finally
Bldr.Free;
end;
finally
Strm.Free;
end;
Screen.Cursor := crHourGlass;
try
IdSMTP.Connect;
try
IdSMTP.Send(IdMessage);
finally
IdSMTP.Disconnect;
end;
memStatus.Lines.Insert(0, 'Email sent - OK.');
finally
Screen.Cursor := crDefault;
end;
except
on E: Exception do
memStatus.Lines.Insert(0, 'ERROR: ' + E.Message);
end;
end;

sslv3 alert handshake failure Delphi

Delphi 10 seattle
OpenSSL 1.0.0.10 but same result with more recent libraries.
the following code has been working for about two years, but lately we are getting an error:
14094410:SSL3_read_bytes:sslv3 alert handshake failure
Have used wireshark to confirm TLSv1.2 is being used. can provide capture file if needed.
function GetAddress(ID_ID : Integer; Rijksregister : String) : Boolean;
var
gp : GetPerson;
Cor : CorrelationType;
P : RrSimplePersonService_v02PortType;
Resp : GetPersonResponse;
FHTTPRio: THTTPRio;
FReqResp : TWisaHTTPReqResp;
FSSLIOHandler: TIdSSLIOHandlerSocketOpenSSL;
Adr : PersonLegalAddressType;
CERTPath : String;
i, j : integer;
begin
CERTPath := IncludeTrailingPathDelimiter(ExtractFilePath(Paramstr(0)));
Result := false;
// declarations
Cor := CorrelationType.Create;
Cor.requestorId := '01234567890';
Cor.requestorName := 'WisaMockupService';
Cor.applicationId := 'WISA';
Cor.correlationId := getGUID;
gp := getPerson.Create;
gp.identifier := Rijksregister;
gp.correlation := Cor;
// actual call
CoInitialize(nil);
fHTTPRio:=THTTPRio.Create(Self);
fHTTPRio.URL:=fURL;
fHTTPRio.Converter.Options := fHTTPRio.Converter.Options + [soSendMultiRefObj, soTryAllSchema, soRootRefNodesToBody, soCacheMimeResponse, soUTF8EncodeXML, soSOAP12];
fHTTPRio.OnBeforeExecute := IH7BeforeExecute;
fHTTPRio.OnAfterExecute := IH7AfterExecute;
FReqResp := TWisaHTTPReqResp.Create(self);
FReqResp.URL := fURL;
FReqResp.InvokeOptions := FReqResp.InvokeOptions + [soNoSOAPActionHeader];
FReqResp.ConnectTimeout := 60000;
FReqResp.ReceiveTimeout := 60000;
FReqResp.SendTimeout := 60000;
FReqResp.WebNodeOptions:= FReqResp.WebNodeOptions+[wnoSOAP12];
fHTTPRio.HTTPwebNode := FReqResp;
fHTTPRio.HTTPwebNode.UserName := fUser;
fHTTPRio.HTTPwebNode.Password := fPaswoord;
fHTTPRio.HTTPwebNode.OnBeforePost := BeforePost;
FSSLIOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(self);
FSSLIOHandler.SSLOptions.Method := sslvTLSv1_2;
FSSLIOHandler.SSLOptions.SSLVersions := [sslvTLSv1_2,sslvTLSv1_1,sslvTLSv1];
FSSLIOHandler.SSLOptions.CipherList := 'ALL';
FSSLIOHandler.SSLOptions.RootCertFile := CERTPath + 'CACert.crt';
FSSLIOHandler.SSLOptions.KeyFile := CERTPath + 'privateKey.key';
FSSLIOHandler.SSLOptions.CertFile := CERTPath + 'certificate.crt';
FSSLIOHandler.SSLOptions.Mode := sslmUnassigned;
FSSLIOHandler.SSLOptions.VerifyMode := [];
FSSLIOHandler.SSLOptions.VerifyDepth := 3;
FSSLIOHandler.OnGetPassword := getPassword;
FSSLIOHandler.UseNagle := true;
FSSLIOHandler.ReadTimeout := 60000;
FSSLIOHandler.ConnectTimeout := 60000;
FSSLIOHandler.OnStatusInfoEx := SSLStatusInfoEx;
FSSLIOHandler.OnVerifyPeer := VerifyPeer;
FReqResp.IOHandler := FSSLIOHandler;
// actual call
P := (fHTTPRio as RrSimplePersonService_v02PortType);
Try
Resp := P.GetPerson(gp);
Except
on e : exception do
begin
Showerror(ID_ID, e.message + ' ' + format(rsRijksregister2,
[Rijksregister]), '', '');
exit;
end;
End;
if not Assigned(Resp) then
exit;
# do something with Response
# end
Result := true;
end;
procedure IH7BeforeExecute(const MethodName: string;
SOAPRequest: TStream);
var
S : TStringStream;
MyStringList: TStringList;
CreateTime, ExpiryTime : TDateTime;
begin
MyStringList := TStringList.Create;
try
Inherited;
CreateTime := Now;
ExpiryTime := IncSecond(CreateTime,600);
SOAPRequest.Position := 0;
MyStringList.LoadFromStream(SOAPRequest);
MyStringList.Text := StringReplace(MyStringList.Text, '<soap-env:body>', Format(SoapHeader,[getTSToken, TimeToString(CreateTime), TimeToString(ExpiryTime), getToken, fGebruiker, fPaswoord]) + '<SOAP-ENV:Body>', [RfIgnoreCase]);
MyStringList.Text := StringReplace(MyStringList.Text, '</GetPerson>', '</ws:GetPerson>', [RfIgnoreCase]);
MyStringList.Text := StringReplace(MyStringList.Text, 'SOAP-ENV:', 'SOAP:', [RfReplaceAll, RfIgnoreCase]);
MyStringList.Text := StringReplace(MyStringList.Text, 'SOAP-ENV=', 'SOAP=', [RfReplaceAll, RfIgnoreCase]);
MyStringList.Text := StringReplace(MyStringList.Text, '<SOAP:Envelope xmlns:SOAP="http://www.w3.org/2003/05/soap-envelope" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance">', '<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope" xmlns:ws="http://person.ws.egov.apogado.com/SimplePersonSchema/v1_2/ws">', [RfReplaceAll, RfIgnoreCase]);
MyStringList.Text := StringReplace(MyStringList.Text, 'SOAP:Body', 'soap:Body', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, '<GetPerson xmlns="http://person.ws.egov.apogado.com/SimplePersonSchema/v1_2/ws">', '<ws:GetPerson>', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, '<transaction xmlns="" xsi:nil="true"/>', '', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, '</SOAP:Envelope>', '</soap:Envelope>', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, '<identifier xmlns="urn:oslo:names:specification:schema:xsd:CommonBasicComponents-1"><Identifier xmlns="http://www.w3.org/ns/corevocabulary/BasicComponents">', '<identifier>', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, '</Identifier>', '', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, 'SOAP:Header', 'soap:Header', [RfReplaceAll]);
MyStringList.Text := StringReplace(MyStringList.Text, 'SOAP:mustUnderstand="true"', 'soap:mustUnderstand="true"', [RfReplaceAll]);
SOAPRequest.Position := 0;
SOAPRequest.Size:=0;
MyStringList.SaveToStream(SOAPRequest);
finally
MyStringList.Free;
end;
S:=TStringStream.Create('');
try
S.CopyFrom(SOAPRequest,0);
SOAPRequest.Position:=0;
// eventueel loggen van request
//Log('HTTPRIO Verstuurd bericht:'+sLineBreak+S.DataString);
finally
S.Free;
end;
end;
procedure IH7AfterExecute(const MethodName: string;
SOAPResponse: TStream);
Var
S : TStringStream;
begin
S:=TStringStream.Create('');
try
S.CopyFrom(SOAPResponse,0);
SOAPResponse.Position:=0;
finally
S.Free;
end;
end;
Procedure GetPassword(var Password: string);
begin
Password := ansistring('********');
end;
procedure SSLStatusInfoEx(ASender: TObject; const AsslSocket: PSSL;
const AWhere, Aret: Integer; const AType, AMsg: string);
begin
SSL_set_tlsext_host_name(AsslSocket, fURL);
end;
procedure BeforePost(const HTTPReqResp: THTTPReqResp; Data: Pointer);
begin
// nothing atm
end;
From the pcap it can be seen that an initial successful TLS handshake is done and also application data are transferred from the client to the server and then a new handshake is initiated by the server followed with an alert send by the server. The successful initial handshake means that neither TLS protocol version, nor cipher, nor server certificate are the problem.
While it is impossible to look at the details of the application data, the second handshake and the alert since they are encrypted the sequence of records suggests that:
After the successful initial TLS handshake a HTTP request (i.e. application data) is done for a resource which requires authentication with a client certificate.
The server therefore triggers a renegotiation. In the second TLS handshake the server will request this certificate.
The server does not like the certificate send by the client or the client does not send a certificate. The server therefore aborts the connection with an alert message.
Given that it worked before but fails now I suggest that one of these is the cause of the problem:
The existing certificate might be expired or revoked.
Changes to the server result in the server no longer accepting the certificate, for example because the CA is no longer trusted.
The certificate was replaced on the client side. But the new certificate is not what the server expects to get or is wrongly setup (like missing a chain certificate).

how to download/uplaod file over HTTPS using Indy 10 and OpenSSL in delphi?

I wish I download a file using Indy.
My problem connecting to SSL.
Please help me to do this using HTTPS or SFTP.
procedure TForm1.BitBtn1Click(Sender: TObject);
begin
IdFTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create(IdFTP1);
IdFTP1.UseTLS:=utUseRequireTLS;
IdFTP1.DataPortProtection:=ftpdpsPrivate;
IdFTP1.Host := '127.0.0.1';
IdFTP1.Username := 'ftp';
IdFTP1.Password := '123';
IdFTP1.Port:=21;
IdSSLIOHandlerSocketOpenSSL1.StartSSL;
try
IdFTP1.Connect;
IdFTP1.Disconnect;
finally
IdFTP1.Free;
end;
end;
You do it correctly (except the fact that you free component which you don't create in the same code). The same is for HTTPS.
IdHTTP1.IOHandler := TIdSSLIOHandlerSocketOpenSSL.Create();
IdHTTP1.Get('https://...');
Just note that you need OpenSSL libraries
https://indy.fulgan.com/ZIP/SSL.zip
or any version you want from
https://indy.fulgan.com/SSL/
Also there is a difference between SFTP and FTPS.
Indy's IdFTP supports SSL (FTPS). It can't work with SFTP (FTP using SSH).
If you want to use SFTP, you have to use alternative commercial component
https://www.eldos.com/sbb/delphi-sftp.php
You should specify any error if it shows one. It is probably only that SSL libraries are missing.
If you don't know how to download/upload file, there are methods for that
IdFTP1.Put (upload)
IdFTP1.Get (download)
IdHTTP1.Put/Post (upload)
IdHTTP1.Get (download)
You will need TIdMultiPartFormDataStream from unit "IdMultipartFormData" for HTTP Post to upload files
Hi here is one example
function HttpGetFile(sUrl, sFile: String) : Boolean;
var
GetData : TFileStream;
begin
Result := False;
try
GetData := TFileStream.Create(sFile, fmOpenWrite or fmCreate);
try
//IdHTTP.ProxyParams.ProxyServer := '';
//IdHTTP.ProxyParams.ProxyPort := 0;
//IdHTTP.ProxyParams.ProxyUsername := '';
//IdHTTP.ProxyParams.ProxyPassword := '';
//IdHTTP.ProxyParams.BasicAuthentication := False;
//IdHTTP.ProtocolVersion := pv1_1;
//IdHTTP.Request.Pragma := 'no-cache';
//IdHTTP.Request.Connection := 'Keep-Alive';
//IdHTTP.Request.AcceptLanguage := 'en';
//IdHTTP.Request.Referer := sTargetUrl;
//NOTE needs files ssleay32.dll and libeay32.dll
if (bSecure) and ( FileExists( ExtractFilePath(Application.ExeName) + 'ssleay32.dll'))
then begin
IdSSLIOHandlerSocketOpenSSL.SSLOptions.Method :=
sslvSSLv23;
IdSSLIOHandlerSocketOpenSSL.SSLOptions.SSLVersions :=
[sslvSSLv2,sslvSSLv3,sslvTLSv1,sslvTLSv1_1,sslvTLSv1_2];
IdHTTP.IOHandler := IdSSLIOHandlerSocketOpenSSL;
sTargetUrl := HTTPS+UPLOAD_URL;
end
else begin
IdHTTP.IOHandler := nil;
sTargetUrl := HTTP+UPLOAD_URL;
end;
IdHTTP.Get(sUrl, GetData);
Result := (IdHTTP.ResponseCode = 200);
finally
GetData.Free;
end;
except
on E: EIdOSSLCouldNotLoadSSLLibrary do
ShowMessage(E.message);
on E: EIdHTTPProtocolException do
ShowMessage(E.message);
on E: EIdConnClosedGracefully do
ShowMessage(E.message);
on E: EIdSocketError do
ShowMessage(E.message);
on E: EIdException do
ShowMessage(E.message);
on E: Exception do
ShowMessage(E.message);
end;
end;

Resources