You are not logged in.
Pages: 1
Hi people, I need to use TWinHTTP with a https server (non mORMot) and I receive the error error 12044 a certificate is required, is TWinHTTP prepared to work with certificates ?
Thanks in advance.
Esteban
Offline
Hi @ab, I have modified SynCrtSock.pas adding response management to error ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED (12044) when the server requests client authentication but not require it.
It's not a big modification:
const
// from http://www.tek-tips.com/faqs.cfm?fid=7493
WINHTTP_OPTION_SECURITY_FLAGS = 31;
SECURITY_FLAG_IGNORE_UNKNOWN_CA = $00000100;
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID = $00002000; // expired X509 Cert.
SECURITY_FLAG_IGNORE_CERT_CN_INVALID = $00001000; // bad common name in X509 Cert.
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE = $00000200;
SECURITY_FLAT_IGNORE_CERTIFICATES: DWORD =
SECURITY_FLAG_IGNORE_UNKNOWN_CA or
SECURITY_FLAG_IGNORE_CERT_DATE_INVALID or
SECURITY_FLAG_IGNORE_CERT_CN_INVALID or
SECURITY_FLAG_IGNORE_CERT_WRONG_USAGE;
WINHTTP_AUTH_TARGET_SERVER = 0;
WINHTTP_AUTH_TARGET_PROXY = 1;
WINHTTP_AUTH_SCHEME_BASIC = $00000001;
WINHTTP_AUTH_SCHEME_NTLM = $00000002;
WINHTTP_AUTH_SCHEME_PASSPORT = $00000004;
WINHTTP_AUTH_SCHEME_DIGEST = $00000008;
WINHTTP_AUTH_SCHEME_NEGOTIATE = $00000010;
// client authentication certificate errors
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED = $00002F0C; // 12044 code error returned by GetLastError()
WINHTTP_OPTION_CLIENT_CERT_CONTEXT = $0000002F;
WINHTTP_NO_CLIENT_CERT_CONTEXT = $00000000;
procedure TWinHTTP.InternalSendRequest(const aData: SockString);
var L: integer;
winAuth: DWORD;
begin
with fExtendedOptions do
if AuthScheme<>wraNone then begin
case AuthScheme of
wraBasic: winAuth := WINHTTP_AUTH_SCHEME_BASIC;
wraDigest: winAuth := WINHTTP_AUTH_SCHEME_DIGEST;
wraNegotiate: winAuth := WINHTTP_AUTH_SCHEME_NEGOTIATE;
else raise EWinHTTP.CreateFmt('Unsupported AuthScheme=%d',[ord(AuthScheme)]);
end;
if not WinHttpSetCredentials(fRequest,WINHTTP_AUTH_TARGET_SERVER,
winAuth,pointer(AuthUserName),pointer(AuthPassword),nil) then
RaiseLastModuleError(winhttpdll,EWinHTTP);
end;
if fHTTPS and IgnoreSSLCertificateErrors then begin
if not WinHttpSetOption(fRequest, WINHTTP_OPTION_SECURITY_FLAGS,
@SECURITY_FLAT_IGNORE_CERTIFICATES, SizeOf(SECURITY_FLAT_IGNORE_CERTIFICATES)) then
RaiseLastModuleError(winhttpdll,EWinHTTP);
end;
L := length(aData);
if not WinHttpSendRequest(fRequest, nil, 0, pointer(aData), L, L, 0) or
not WinHttpReceiveResponse(fRequest,nil) then begin
if not fHTTPS then
RaiseLastModuleError(winhttpdll,EWinHTTP);
if GetLastError=ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED then begin
if not WinHttpSetOption(fRequest, WINHTTP_OPTION_SECURITY_FLAGS,
@SECURITY_FLAT_IGNORE_CERTIFICATES, SizeOf(SECURITY_FLAT_IGNORE_CERTIFICATES)) then
RaiseLastModuleError(winhttpdll,EWinHTTP);
if not WinHttpSetOption(fRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
pointer(WINHTTP_NO_CLIENT_CERT_CONTEXT), 0) then
RaiseLastModuleError(winhttpdll,EWinHTTP);
if not WinHttpSendRequest(fRequest, nil, 0, pointer(aData), L, L, 0) or
not WinHttpReceiveResponse(fRequest,nil) then
RaiseLastModuleError(winhttpdll,EWinHTTP);
end;
end;
end;
Do you agree with add this feature ?
Thanks.
Esteban
Offline
@ab, don't you agree with this modification ? I consider that it's an enhacement.
Best regards.
Esteban
Offline
Any news ?
Esteban
Offline
Please check https://synopse.info/fossil/info/98553b322f
I've conditioned the new behavior with the IgnoreSSLCertificateErrors option, to avoid weak use if full certificate validation is expected.
Offline
Pages: 1