1

I try to send a certificate with my POST request without the server requesting it first, preemtive speaking.

With Indy it works perfectly fine like this:

procedure TMyExampleClass.GetPassword(var Password: String); 
begin 
  password := ''; 
end;

var
  http: TIdHTTP;
  ssl: TIdSSLIOHandlerSocketOpenSSL;  
  request, response: TStringStream;
begin
  certfile := 'c:\temp\certfile.pfx';

  http := TIdHTTP.Create;
  ssl := TIdSSLIOHandlerSocketOpenSSL.Create(http);
  request := TStringStream.Create('', TEncoding.UTF8);
  response := TStringStream.Create('', TEncoding.UTF8);  
  try
    ssl.SSLOptions.SSLVersions := [sslvTLSv1_2];
    ssl.SSLOptions.CertFile := certfile;
    ssl.SSLOptions.KeyFile := certfile;
    ssl.SSLOptions.Mode := sslmBoth;
    ssl.OnGetPassword := GetPassword; 

    http.IOHandler := ssl;

    http.Request.ContentType := 'application/json; charset=utf-8';
    http.Request.UserAgent := 'MySpecialClient';
    http.Request.CustomHeaders.Clear;
    http.Request.CustomHeaders.FoldLines := false; // without it doesn't work, dunno why
    http.Request.CustomHeaders.Values['Ocp-Apim-Subscription-Key'] := 'topsecretsubscriptionkey';
    http.Request.CustomHeaders.Values['Signature'] := 'calculatedsignature'; // doesn't matter for this case, usually it's a procedure that calcs the signature by it's streamcontent + certificate
    http.HTTPOptions := [hoForceEncodeParams, hoNoProtocolErrorException, hoWantProtocolErrorContent];

    request.WriteString(payload); // payload is param of this method; const payload: string;
    request.Position := 0;

    http.Post('https://myexample.com/v1/api/message', request, response);
    response.SaveToFile('c:\temp\test.json');
  finally
    response.Free;
    request.Free;  
    http.Free;
  end;
end;

Now I have to switch to Overbyte ICS for async support but it doesn't work with this code:

procedure TMyExampleClass.AddHeaders(Sender: TObject; const Method: String; Headers: TStrings);
begin
  Headers.Add('Ocp-Apim-Subscription-Key: topsecretsubscriptionkey'); 
end;

var
  http: TSslHttpCli;
  ssl: TSslContext;
  request, response: TStringStream;
  //errormsg: string;
begin
  http := TSslHttpCli.Create(nil);
  ssl := TSslContext.Create(nil);
  request := TStringStream.Create('', TEncoding.UTF8);
  response := TStringStream.Create('', TEncoding.UTF8);
  try
    request.WriteString(payload);
    request.Position := 0;
    
    ssl.SslCertFile := 'c:\temp\certfile.pfx';
    //LoadFromFileEx('c:\temp\certfile.pfx', croYes, croYes, '', errormsg)

    http.SslContext := ssl;

    http.Agent := 'MySpecialClient';
    http.ContentTypePost := 'application/json; charset=utf-8';
    http.OnBeforeHeaderSend := AddHeaders;
    http.URL := 'https://myexample.com/v1/api/message';
    http.SendStream := request;
    http.RcvdStream := response;
    http.Post;    

    response.SaveToFile('c:\temp\test.json');
  finally
    response.Free;
    request.Free;
    ssl.Free;
    http.Free;
  end;
end;

I don't find the right method, property, what so ever to load the pfx-cert and transmit it preemptiv.

The exception I get is the following:

Debugger Exception Notification

Project MyExampleProject.exe raised exception class EHttpException with message 'httpPOST: Error# 11 Abort on Exception: Error on reading certificate lines - No PEM Content Found'.

Any idea how to load the pfx-cert? The pfx-cert also contains the private key.

1

1 Answer 1

0

Which Indy command is forcing an SSL certificate to be sent without the server requesting it? This is unusual, it's normally negotiated by the server during the initial SSL HELO process.

You are using an older ICS HTTP component, I suggest you try accessing your server using the OverbyteIcsHttpRestTst sample which uses the newer TSslHttpRest component and allows a client certificate to be specified on the REST Settings page, and also allows your extra headers to be added.

Angus

2
  • I am on Delphi 11 Update 2 and installed Overbyte ICS with GetIt Package Manager ICS for VCL for Delphi 9.1. Is this really an older ICS version? Commented Apr 19 at 6:33
  • I said old component, not older version of ICS. The newer TSslHttpRest component is much easier to use than the older TSslHttpCli component, and has a better sample application, as I mentioned. Commented Apr 19 at 11:42

Not the answer you're looking for? Browse other questions tagged or ask your own question.