Forum > Networking and Web Programming

TFPHttpClient with SSL client side certificate

(1/2) > >>

yn.coder:
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  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- uses  fphttpclient, ssockets, sslsockets, SysUtils; var FClientCertificate : string;  type TSSLHelper = class helper for TObject       procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);            end; // Callback for setting up SSL client certificateprocedure TSSLHelper.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;  out AHandler: TSocketHandler);begin  AHandler:=nil;  if UseSSL and (FClientCertificate<>'') then  begin    // Only set up client certificate if needed.    // If not, let normal fphttpclient flow create    // required socket handler    AHandler:=TSSLSocketHandler.Create;    // Example: use your own client certificate when communicating with the server:    ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;    writeln( ( AHandler as TSSLSocketHandler ).Certificate.FileName );    //( AHandler as TSSLSocketHandler ).PFX.FileName := FClientCertificate;      end;end;  function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;var ssl_helper : TObject;begin  Result := False;  out_Str := '';  out_Err_Msg := '';    with TFPHttpClient.Create( nil ) do    begin      AllowRedirect := True;      FClientCertificate := Arg_Cert_Path;      if Arg_Cert_Path <> ''         then          OnGetSocketHandler:=@ssl_helper.SSLClientCertSetup;       try        out_Str := Get( Arg_URL );        Result := True;      except        on E: Exception do          begin             out_Err_Msg := E.ClassName + '/' + E.Message;          end;      end;      Free;    end;end; 
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:
After some study - it's working now.

Here is a working code

--- Code: Pascal  [+][-]window.onload = function(){var x1 = document.getElementById("main_content_section"); if (x1) { var x = document.getElementsByClassName("geshi");for (var i = 0; i < x.length; i++) { x[i].style.maxHeight='none'; x[i].style.height = Math.min(x[i].clientHeight+15,306)+'px'; x[i].style.resize = "vertical";}};} --- uses fphttpclient, ssockets; (* Get page by Arg_URL via http get.   If success then function return True, out_Str contain downloaded data, and out_Err_Msg is empty   If fail the function return False, out_Str is empty, and out_Err_Msg contain error message*)function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean; type T_FP_HTTPS_Client = Class(TFPHTTPClient)     public      FClientCertificate : string;      procedure SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean; out AHandler: TSocketHandler);          end; uses  {$IFDEF UNIX}{$IFDEF UseCThreads}  cthreads,  {$ENDIF}{$ENDIF}    classes, fpopenssl, SysUtils;  // Callback for setting up SSL client certificateprocedure T_FP_HTTPS_Client.SSLClientCertSetup(Sender: TObject; const UseSSL: Boolean;  out AHandler: TSocketHandler);begin  AHandler:=nil;  if UseSSL and (FClientCertificate<>'') then  begin    AHandler := TSSLSocketHandler.Create;    ( AHandler as TSSLSocketHandler ).SSLType := stTLSv1;    // Example: use your own client certificate when communicating with the server:    // PEM format    ( AHandler as TSSLSocketHandler ).Certificate.FileName := FClientCertificate;    ( AHandler as TSSLSocketHandler ).PrivateKey.FileName := FClientCertificate;          end;end;  function HTTP_Get( Arg_URL : string; out out_Str: string; out out_Err_Msg : string; Arg_Cert_Path : string = '' ) : boolean;begin  Result := False;  out_Str := '';  out_Err_Msg := '';    with T_FP_HTTPS_Client.Create( nil ) do    begin      FClientCertificate := Arg_Cert_Path;      if Arg_Cert_Path <> ''         then          OnGetSocketHandler:=@SSLClientCertSetup;      try        out_Str := Get( Arg_URL );        Result := True;      except        on E: Exception do          begin             out_Err_Msg := E.ClassName + '/' + E.Message;          end;      end;      Free;    end;end;  

andersonscinfo:

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:
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.

andersonscinfo:
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

Navigation

[0] Message Index

[#] Next page

Go to full version