EldoS | Feel safer!

Software components for data protection, secure storage and transfer

Soap-service through HTTPS and a certificate

Also by EldoS: CallbackDisk
Create virtual disks backed by memory or custom location, expose disk images as disks and more.
#31518
Posted: 11/26/2014 09:04:06
by Kurt Schilling (Standard support level)
Joined: 11/24/2014
Posts: 3

Delphi XE3 pro, XML and HTTP-package, new customer to Eldos (me)

  • In Delphi I have imported a WSDL and got a neat unit, I would be able to use through THTTPRIO, if not the service-supplier wants me to load a X509 certificate for validation. This brings Eldos into play. Can I, in any way, still use the skeleton created by Delphi, together with your components? It would be much easier that way.

  • Been playing with the SOAP-client example (..\Samples\Delphi\XMLBlackbox), added a FileCertStorage and set up the TELHTTPSClient.OnCertificateNeededEx-event, but it doesn't come into play. I get an "CreateElementND w/empty tag name"-exception when generating the message.

    I've been spending the entire day plucking out hair straws, scanning demos and trawling the Internet, trying to figure the right approach. Suggestions are most welcome.

  • The example supplied by kmd.dk is sparse. It is 20 lines of .NET code where a X509Certificate2 object is hooked to a serviceClient: serviceClient.ClientCredentials = <x59cert2> (class name of serviceClient is unspecificed). Perhaps this can give you a clue of my task.

Thanks in advance.
Henrik Carlsen

--- copied from the modified sample:

Code
procedure TfrmMain.HTTPSClientCertificateNeededEx(Sender: TObject; var Certificate: TElX509Certificate);
begin
  // I never get here before an exception is generated
  assert(not assigned(Certificate));
  Certificate := TElX509CertificateEx.Create(HTTPSClient); // assuming this owner makes it free correctly.
  Certificate.LoadFromFileAuto(Filename,''); // cer-bugger (DER, public key) loaded, I'm all set, right??
end;

procedure TfrmMain.btnSendClick(Sender: TObject);
var
  FileCertStorage: TElFileCertStorage;
begin
  btnExploreRequestXML.Enabled := false;
  btnExploreResponseXML.Enabled := false;

  try
    // Is it needed? Is it needed to trigger the OnCertificateNeeded-event?
    FileCertStorage := TElFileCertStorage.Create(nil);
    try
      fSOAPClient.SOAPPrefix := 'soap';
      if cmbSOAPVersion.ItemIndex = 1 then
        fSOAPClient.SOAPVersion := SOAP_v1_2
      else
        fSOAPClient.SOAPVersion := SOAP_v1_1;

      // Hook up the storage.
      HTTPSClient.CertStorage := FileCertStorage;

      fSOAPClient.OperationName := edOperationName.Text; // Filled with the UTI/URL (https://<supplier>/IndmeldelsesService.svc)
      fSOAPClient.OperationNamespaceURI := edOperationNamespaceURI.Text; // Filled out too (HentAlle)

      // Leaveing it blank seems to be an OK thing to do (I wouldn't know what
      // to put into, anyway), HRC
      if Length(edOperationPrefix.Text) > 0 then
        fSOAPClient.MessageNamespaces.AddNamespace(edOperationPrefix.Text, edOperationNamespaceURI.Text)
      else
        fSOAPClient.MessageNamespaces.Clear;

      // GenerateMessage ... well, it generates an exception. I assume this is OK.
      // I can't see from where the information to generate a message should be
      // coming from
      fSOAPClient.GenerateMessage;

      fSOAPClient.HTTPClient := HTTPSClient;
      fSOAPClient.URL := edURL.Text;
      fSOAPClient.SOAPAction := edSOAPAction.Text;

      fSOAPClient.SendMessage;

      btnExploreRequestXML.Enabled := true;
      btnExploreResponseXML.Enabled := (fSOAPClient.ResponseType in [srtXMLDocument,srtSOAPMessage]);
      UpdateResponse;
    finally
      FileCertStorage.Free;
    end;
  except
    on E: Exception do
      MessageDlg('Failed to send SOAP message: ' + E.Message, mtError, [mbOk], 0);
  end;
end;
#31520
Posted: 11/26/2014 09:47:04
by Dmytro Bogatskyy (EldoS Corp.)

Thank you for contacting us.

Quote
I get an "CreateElementND w/empty tag name"-exception when generating the message.

This is exception could be thrown if OperationName property is not set or it is an empty string.

Quote

fSOAPClient.OperationName := edOperationName.Text; // Filled with the UTI/URL (https://<supplier>/IndmeldelsesService.svc)
fSOAPClient.OperationNamespaceURI := edOperationNamespaceURI.Text; // Filled out too (HentAlle)

I think you should set them vice versa ("HentAlle" set to OperationName)

Quote
// GenerateMessage ... well, it generates an exception. I assume this is OK.

No, the exception is not ok, the message generation is done before sending a mesage, so if it fails then a message wouldn't be sent.

P.S. For the reference here it is a test service that could be used with SOAPClient sample.
Test service: http://www.webservicex.net/globalweather.asmx
It's WSDL: http://www.webservicex.net/globalweather.asmx?WSDL
SOAPClient sample settings (taken from WSDL):
Service URL: http://www.webservicex.net/globalweather.asmx
SOAP Action: http://www.webserviceX.NET/GetWeather
Operation Name: GetWeather
Operation Namespace URI: http://www.webserviceX.NET
Parameters:
Add:
Name: CityName
Namespace URI: http://www.webserviceX.NET
Type: string
Value: New York
Add:
Name: CountryName
Namespace URI: http://www.webserviceX.NET
Type: string
Value: United States

The service will return an xml document as a value.
#31521
Posted: 11/26/2014 10:06:18
by Eugene Mayevski (EldoS Corp.)

Please check Dmytro's comments above and also my comments below.

Let's split your task in two, please.

The "if not the service-supplier wants me to load a X509 certificate for validation" statement confuses me. Does the supplier wants to authenticate your request OR he wants you to authenticate during HTTPS connection OR he wants you to authenticate his response?

Quote
Schilling wrote:
Been playing with the SOAP-client example (..\Samples\Delphi\XMLBlackbox), added a FileCertStorage and set up the TELHTTPSClient.OnCertificateNeededEx-event, but it doesn't come into play. I get an "CreateElementND w/empty tag name"-exception when generating the message.


These are two totally unrelated things. The exception is related to SOAP and TELHTTPSClient.OnCertificateNeededEx is used in SSL/TLS authentication (which is not related to XML in any way).

Next, your use of the certificate storage needs adjustment. As said, TElHTTPSClient uses certificates during SSL/TLS handshake. You can authenticate yourself (a client) during handshake by providing the certificate with the associated private key. The certificate can be provided *either* via OnCertificateNeeded/OnCertificateNeededEx event OR via ClientCertStorage property (but not both at the same time).

So let's figure out what you need, then split your task into SOAP and HTTPS parts and start addressing issues separately.


Sincerely yours
Eugene Mayevski
#31544
Posted: 12/01/2014 05:35:47
by Kurt Schilling (Standard support level)
Joined: 11/24/2014
Posts: 3

Hi Eugene and Dmytro

I know I probably mix things together, and sorry about that. It happens when the entire concept of layered communication is something you normally doesn't think of. I'm usually done by importing the WSDL.

I have posted a question to the service manufacturer regarding the use of their certificates, but heard nothing yet. It, however, seems probable that the certificate is used for validation at THTTPS level, thus replacing the usual login and password.

Therefore I use the TELHTTPSClient.OnCertificateNeededEx-event, to hook up the request with a certificate. What triggers the event? It seems that SSL plays a part as I can track it to the TELSSLClient.SSL2ParseRequestCertificate method.

I am using the before mentioned example, with the values Dmytro so kindly supplied. It works, and then again, in the IDE, it doesn't. Before handing me the reply, I get 6-8 error messages which are suppressed running the EXE. It seems it tries to base64-decode the reply (which is standard XML).

Quote
Failed to base64 decode
Parameter value '<?cml ...> is not base64 encoded binary

Is that something to ignore or are there ways to fix it?

Sincerely yours
Henrik Carlsen

Ps. I have modified the example to save and load all form values, including the parameters, from a ini-file, making it a much better test bed. Would you want a copy of the source code?
#31545
Posted: 12/01/2014 05:50:48
by Dmytro Bogatskyy (EldoS Corp.)

Hello,
Quote
I am using the before mentioned example, with the values Dmytro so kindly supplied. It works, and then again, in the IDE, it doesn't. Before handing me the reply, I get 6-8 error messages which are suppressed running the EXE. It seems it tries to base64-decode the reply (which is standard XML).

Those exceptions are handled internally by SecureBlackbox code when trying to detect response data type. You can add the exception class to the list of ignored exceptions in the IDE to bypass this exception.
#31549
Posted: 12/01/2014 08:59:59
by Kurt Schilling (Standard support level)
Joined: 11/24/2014
Posts: 3

Hi Dmytro
I was suspecting that as the program ran fine as stand alone (I'm not too happy about adding the EConvertError to the ignore list).

I have tried loading the certificate through the CertificateNeededEx, but it's never triggered. Instead a "Connection failed due to error (75784)"-error occurs. (https://www.eldos.com/forum/read.php?FID=7&TID=3371).

Do I need a setting to get that event triggered?
#31550
Posted: 12/01/2014 09:16:15
by Eugene Mayevski (EldoS Corp.)

Please separate (completely) XML/SOAP and HTTP parts for now. They confuse you and make our work harder as well.

Regarding exceptions - please provide more detailed list of errors that you get. Eg. if you use TElX509Certificate.LoadFromStreamAuto method, then the only method to detect certificate format is to try to load it in various formats, and catch the exceptions.

About HTTP - try to make the simple HTTPGet sample work for you. The error you get is most likely not related to the missing certificate but to something else.
The certificate is requested when the server is configured to request it. If it's not triggered, this means that either disconnection happens on earlier stage of handshake or the server doesn't expect your certificate.

Now as I look again at your code, it doesn't make sense. If you know the format of the file, then you don't need to use LoadFromStreamAuto . Use the format-specific method instead.

If you have .cer file only - this is NOT for client-side authentication. Client-side authentication requires a private key.


Sincerely yours
Eugene Mayevski
Also by EldoS: Rethync
The cross-platform framework that simplifies synchronizing data between mobile and desktop applications and servers and cloud storages

Reply

Statistics

Topic viewed 3179 times

Number of guests: 1, registered members: 0, in total hidden: 0




|

Back to top

As of July 15, 2016 EldoS Corporation will operate as a division of /n software inc. For more information, please read the announcement.

Got it!