I've figured it out I think.
Your current code is set to ignore any invalid certificates. In short, the SSL option is only used to encrypt the traffic but the authenticity of the server/SSL certificate is not verified. To verify authenticity of the server/certificate the following changes will need to be done:
1. Inside function TWinHttp.OpenRequest(const url, verb: AnsiString) comment out two lines:
Code: Select all
//flags := SECURITY_FLAG_IGNORE_CERT_CN_INVALID or SECURITY_FLAG_IGNORE_CERT_DATE_INVALID or SECURITY_FLAG_IGNORE_UNKNOWN_CA;
//WinHttpSetOption(FRequest, WINHTTP_OPTION_SECURITY_FLAGS, @flags, sizeOf(flags));
The above lines were instructing WinHTTP to ignore any invalid certificates.
2. Change function TWinHttp.SendRequest(sendData: AnsiString = ''; sizeOfAttachments: dword = 0) to :
Code: Select all
function TWinHttp.SendRequest(sendData: AnsiString = ''; sizeOfAttachments: dword = 0) : boolean;
const WINHTTP_AUTH_TARGET_PROXY = $00000001;
const ERROR_WINHTTP_SECURE_FAILURE = 12175;
var len : dword;
begin
FRetrySend := false;
if FProxyAuthScheme <> 0 then
FRetrySend := WinHttpSetCredentials(FRequest, WINHTTP_AUTH_TARGET_PROXY, FProxyAuthScheme, PWideChar(FProxyUser), PWideChar(FProxyPassword), nil);
result := WinHttpSendRequest(FRequest, nil, 0, nil, 0, dword(Length(sendData)) + sizeOfAttachments, 0);
if (not result) then begin
if (GetLastError <> ERROR_WINHTTP_SECURE_FAILURE) and (not FProxyDone) and (FProxyInfo.lpszProxy = nil) then begin
FProxyDone := true;
if AutoConfigProxy then
result := WinHttpSendRequest(FRequest, nil, 0, nil, 0, dword(Length(sendData)) + sizeOfAttachments, 0);
end;
end;
if result and (sendData <> '') then
result := WinHttpWriteData(FRequest, pointer(sendData), Length(sendData), len);
if not result then
SetLastErrorNo;
end;
The difference from the original code is that if the first WinHttpSendRequest fails, we now check and make sure the the failure is not related to security before exploring the proxy option.
If the certificate on the server is invalid the HttpUpload function would return false and LastHttpErrorNo would be equal to 12175.
I tested the code on a self-signed certificate and a valid certificate located on a wrong domain (ex. certificate for mywebdomain.com was used on myfriendsdomain.com).
Using SSL with certificate verification can avoid sending data to the "wrong people" if your domain name gets hijacked.