Recent

Author Topic: TFPHttpClient with SSL client side certificate  (Read 4181 times)

yn.coder

  • Newbie
  • Posts: 2
TFPHttpClient with SSL client side certificate
« on: June 14, 2017, 11:19:08 pm »
Hello!

I've use TFPHttpClient for https requests. It's working good, except I can't run it with SSL client side certificates.

I follow this sample http://wiki.lazarus.freepascal.org/fphttpclient#HTTPS_.28TLS.2FSSL.29 and wrote my code.

Code: Pascal  [Select][+][-]
  1.  
  2. uses  fphttpclient, ssockets, sslsockets, SysUtils;
  3.  
  4. var FClientCertificate : string;
  5.  
  6. type TSSLHelper = class helper for TObject
  7.        procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);      
  8.       end;
  9.  
  10. // Callback for setting up SSL client certificate
  11. procedure TSSLHelper.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;
  12.   out AHandler: TSocketHandler);
  13. begin
  14.   AHandler:=nil;
  15.   if UseSSL and (FClientCertificate<>'') then
  16.   begin
  17.     // Only set up client certificate if needed.
  18.     // If not, let normal fphttpclient flow create
  19.     // required socket handler
  20.     AHandler:=TSSLSocketHandler.Create;
  21.     // Example: use your own client certificate when communicating with the server:
  22.     ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;
  23.     writeln( ( AHandler as TSSLSocketHandler ).Certificate.FileName );
  24.     //( AHandler as TSSLSocketHandler ).PFX.FileName := FClientCertificate;
  25.    
  26.   end;
  27. end;
  28.  
  29. function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;
  30. var ssl_helper : TObject;
  31. begin
  32.   Result := False;
  33.   out_Str := '';
  34.   out_Err_Msg := '';
  35.  
  36.   with TFPHttpClient.Create( nil ) do
  37.     begin
  38.       AllowRedirect := True;
  39.       FClientCertificate := Arg_Cert_Path;
  40.       if Arg_Cert_Path <> ''
  41.         then
  42.           OnGetSocketHandler:=@ssl_helper.SSLClientCertSetup;
  43.  
  44.       try
  45.         out_Str := Get( Arg_URL );
  46.         Result := True;
  47.       except
  48.         on E: Exception do
  49.           begin
  50.             out_Err_Msg := E.ClassName + '/' + E.Message;
  51.           end;
  52.       end;
  53.       Free;
  54.     end;
  55. end;
  56.  

I've test it with scriptjunkie site https://www.scriptjunkie.us/2013/11/adding-easy-ssl-client-authentication-to-any-webapp/#Instructions, where anybody could generate a ssl certificate and test the auth.

If I generate a certificate for browser and go to test page https://www.scriptjunkie.us/auth/verifycert - it's working.

If I export a certificate from browser to crt, pem or p12 certificate file and use it with my code - I've got only Uh oh! You don't seem to be using a cert..

How to use cert file? What format of cert to use?

yn.coder

  • Newbie
  • Posts: 2
Re: TFPHttpClient with SSL client side certificate
« Reply #1 on: July 01, 2017, 12:38:39 am »
After some study - it's working now.

Here is a working code
Code: Pascal  [Select][+][-]
  1.  
  2. uses fphttpclient, ssockets;
  3.  
  4. (* Get page by Arg_URL via http get.
  5.    If success then function return True, out_Str contain downloaded data, and out_Err_Msg is empty
  6.    If fail the function return False, out_Str is empty, and out_Err_Msg contain error message
  7. *)
  8. function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;
  9.  
  10. type T_FP_HTTPS_Client = Class(TFPHTTPClient)
  11.      public
  12.       FClientCertificate : string;
  13.       procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);      
  14.     end;
  15.  
  16. uses
  17.   {$IFDEF UNIX}{$IFDEF UseCThreads}
  18.   cthreads,
  19.   {$ENDIF}{$ENDIF}
  20.  
  21.   classes, fpopenssl, SysUtils;
  22.  
  23. // Callback for setting up SSL client certificate
  24. procedure T_FP_HTTPS_Client.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;
  25.   out AHandler: TSocketHandler);
  26. begin
  27.   AHandler:=nil;
  28.   if UseSSL and (FClientCertificate<>'') then
  29.   begin
  30.     AHandler := TSSLSocketHandler.Create;
  31.     ( AHandler as TSSLSocketHandler ).SSLType := stTLSv1;
  32.     // Example: use your own client certificate when communicating with the server:
  33.     // PEM format
  34.     ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;
  35.     ( AHandler as TSSLSocketHandler ).PrivateKey.FileName := FClientCertificate;    
  36.    
  37.   end;
  38. end;
  39.  
  40. function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;
  41. begin
  42.   Result := False;
  43.   out_Str := '';
  44.   out_Err_Msg := '';
  45.  
  46.   with T_FP_HTTPS_Client.Create( nil ) do
  47.     begin
  48.       FClientCertificate := Arg_Cert_Path;
  49.       if Arg_Cert_Path <> ''
  50.         then
  51.           OnGetSocketHandler:=@SSLClientCertSetup;
  52.       try
  53.         out_Str := Get( Arg_URL );
  54.         Result := True;
  55.       except
  56.         on E: Exception do
  57.           begin
  58.             out_Err_Msg := E.ClassName + '/' + E.Message;
  59.           end;
  60.       end;
  61.       Free;
  62.     end;
  63. end;
  64.  
  65.  

andersonscinfo

  • Full Member
  • ***
  • Posts: 126
Re: TFPHttpClient with SSL client side certificate
« Reply #2 on: February 26, 2021, 02:17:45 pm »

I have a very similar problem, but I can't even create the socket, the message "Cannot create a X509 certificate without SLL support" appears. Could you give me any tips on openssl versions, I'm using lazarus 2.0.10 with fpc 3.2 on windows, lazarus 32bits.

Thaddy

  • Hero Member
  • *****
  • Posts: 10785
Re: TFPHttpClient with SSL client side certificate
« Reply #3 on: February 26, 2021, 02:33:03 pm »
Looks to me that it is just a case of a deprecated protocol. You need to specify TLS1.1 or higher. Better still 1.3 or higher.
Don't get fooled by the SSL name of the libraries. SSL as a protocol is unsafe and removed from OpenSsl.  You need to use TLS 1.1 or higher which are supported by most libraries including openssl.
« Last Edit: February 26, 2021, 02:37:08 pm by Thaddy »

andersonscinfo

  • Full Member
  • ***
  • Posts: 126
Re: TFPHttpClient with SSL client side certificate
« Reply #4 on: February 26, 2021, 02:43:19 pm »
before I can inform you the protocol the error is already showing up, I will send an example, maybe you can help me.

exemple:
http://activelinux.info/tmp/lazarus.zip

PascalDragon

  • Hero Member
  • *****
  • Posts: 3072
  • Compiler Developer
Re: TFPHttpClient with SSL client side certificate
« Reply #5 on: February 26, 2021, 03:09:25 pm »
You need to use unit OpenSSLSockets as well. The unit SSLSockets only provides the general SSL support independent of the SSL provider (OpenSSL, GNU SSL, etc.).

andersonscinfo

  • Full Member
  • ***
  • Posts: 126
Re: TFPHttpClient with SSL client side certificate
« Reply #6 on: February 26, 2021, 05:33:08 pm »
cool, I changed   
    AHandler := TSSLSocketHandler.Create;
that's why
    AHandler :=TOpenSSLSocketHandler.create; 

now it's giving other errors, but I think it involves the webservice, thanks for now, I'll be back here to post the complete example working as soon as I can. thanks

andersonscinfo

  • Full Member
  • ***
  • Posts: 126
Re: TFPHttpClient with SSL client side certificate
« Reply #7 on: February 26, 2021, 05:41:35 pm »
thank you very much guys, it worked here, I had to make only one adjustment to work according to my need, this is in the image attached the two changes, one is the certificate that needed to be a ".crt" and the other was not to set the type.

 

TinyPortal © 2005-2018