Board index » delphi » client certificates

client certificates


2007-02-23 04:31:12 AM
delphi98
Are there any plans to support client certificates for https connections
in Win32 soap in future Delphi products?
Danny
---
 
 

Re:client certificates

Hello Danny,
Yes. it is won't be in the imminent release. In XPlanner is was assigned
priority 11 and we only got to priorities 10 and less for Spacely (codename
for Delphi 2007 for Win32). Also even if I had gotten to it, it would have
been hard to implement without breaking the D2006 interface (something we're
doing in order to maintain .DCU compatibility).
But I did drop a few things in that direction in SOAPHTTPTrans.pas. For
example:
{$IFDEF PICK_FIRST_CERTIFICATE}
{ Handle request for a Client Certificate }
else if (LastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) then
begin
{ This will pick the first client cerficated registered with WinInet}
FlagsLen := SizeOf(Flags);
InternetSetOption(Request, INTERNET_OPTION_SECURITY_SELECT_CLIENT_CERT,
Pointer(@Flags), FlagsLen);
end
{$ENDIF}
This is in the code that handles WinInet errors. it is not ideal as it picks
the first certificate on the client machine. Because of that
'PICK_FIRST_CERTIFICATE' is *not* defined. But it is there in case that works
for someone.
Also, in the same file, I have added a property to THTTPReqResp:
{$IFDEF USE_INDY}
{$IFDEF INDY_CUSTOM_IOHANDLER}
property IOHandler: TIdIOHandler read FIOHandler write FIOHandler;
{$ENDIF}
{$ENDIF}
We used to create an IOHandler for HTTPS. But we did nothing else. By
exposing the IOHandler property, someone can add Client certificate support
using Indy's support.
IOW, it is something I have started to look at and hope to get in for a
post-Spacely release.
If you're interested in that copy of SOAPHTTPTrans.pas I would be more than
happy to email you a copy.
Cheers,
Bruneau.
 

Re:client certificates

Jean-Marie Babet schreef:
Quote
Yes.
Thanks! that is good news.
Quote
This is in the code that handles WinInet errors. it is not ideal as it picks
the first certificate on the client machine.
It would be very convenient if you could add a Client_Certificate
property to HTTPRIO (a PCCERT_CONTEXT or a raw DER encoded certificate
or whatever) that is used in SoapHttpTrans if WinInet asks for it in a
future release.
This is what I had to do, I had to use the certificate in the currently
inserted smartcard.
Danny
---
 

Re:client certificates

Hello Danny,
Quote
It would be very convenient if you could add a Client_Certificate
property to HTTPRIO (a PCCERT_CONTEXT or a raw DER encoded certificate
or whatever) that is used in SoapHttpTrans if WinInet asks for it in a
future release.
Thanks for the suggestion. How to expose the support is something that I've
been wondering about and I was planning to check with folks who've worked
with certificates to determine the best approach. I am noting the approach
you suggested.
Cheers,
Bruneau.
 

Re:client certificates

Jean-Marie Babet schreef:
Quote
Thanks for the suggestion. How to expose the support is something that I've
been wondering about and I was planning to check with folks who've worked
with certificates to determine the best approach. I am noting the approach
you suggested.
FYI, this is working code in SoapHttpTrans, where FClientCertContext is
defined as a PCCERT_CONTEXT property that has been set in THTTPRIO:
SoapHttpClient.pas:
procedure THTTPRIO.SetClientCertContext(const Value: PCCERT_CONTEXT);
begin
FHTTPWebNode.ClientCertContext := Value;
end;
SoapHttpTrans.pas:
function THTTPReqResp.Send(const ASrc: TStream): Integer;
....snip...
// case where size < MaxPostSize:
while True do
begin
success := HttpSendRequest(Request, nil, 0,
@StrStr.DataString[1], Length(StrStr.DataString));
if (not success)
and (GetLastError = ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED) then
begin
if FClientCertContext <>Nil then
begin
Check(not InternetSetOption(Request,
INTERNET_OPTION_CLIENT_CERT_CONTEXT,
FClientCertContext,
SizeOf(CERT_CONTEXT)), true);
end;
Check(not HttpSendRequest(Request, nil, 0,
@StrStr.DataString[1], Length(StrStr.DataString)));
end
else
Check(success);
RetVal := InternetErrorDlg(GetDesktopWindow(), Request, GetLastError,
FLAGS_ERROR_UI_FILTER_FOR_ERRORS or
FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS or
FLAGS_ERROR_UI_FLAGS_GENERATE_DATA, P);
case RetVal of
ERROR_SUCCESS: break;
ERROR_CANCELLED: SysUtils.Abort;
ERROR_INTERNET_FORCE_RETRY: {Retry the operation};
end;
end;
Danny
---