c++windowsdelphirequestwininet

Why two calls to HttpSendRequest on different connections (new InternetOpen and new InternetConnect) bring different results?


I'm using wininet to connect to a URL that needs a client certificate. To test my "automatic error correction", I'm doing this connection without the client certificate and the behaviour is to call my SelectCertificate function.

Intentionally I do not pass all the parameter to this function which, of course, raises an exception and my request is aborted. There are cleaning blocks to do all the necessary cleaning [InternetCloseHandle(HttpOpenRequestHandle), InternetCloseHandle(InternetConnectHandle) and InternetCloseHandle(InternetOpenHandle)].

The first request is returning the correct exception, caused by the lack of a client certificate, but the second (new?) request is raising another exception "Secure Channel Support Error" (error 12157)

To clarify, see the following flow:

The first request

1.0 InternetOpen(...)

2.0 InternetConnect(...)

3.0 HttpOpenRequest(...)

4.0 HttpSendRequest(..)

  4.1 Error (ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED)

  4.2 SelectCertificate

    4.2.1 Raise exception because I intentionally do not passed all parameters

5.0 InternetCloseHandle(HttpOpenRequestHandle)

6.0 InternetCloseHandle(InternetConnectHandle)

7.0 InternetCloseHandle(InternetOpenHandle);

The second (new?) request

1.0 InternetOpen(...)

2.0 InternetConnect(...)

3.0 HttpOpenRequest(...)

4.0 HttpSendRequest(..)

  4.1 Error (ERROR_INTERNET_SECURITY_CHANNEL_ERROR)

  4.2 I do not know how to handle this error, so...

  4.3 Raise the original exception "Secure Channel Support Error"

5.0 InternetCloseHandle(HttpOpenRequestHandle)

6.0 InternetCloseHandle(InternetConnectHandle)

7.0 InternetCloseHandle(InternetOpenHandle)

All other requests from now are just like the second one.

My questions are:

As I'm closing all the handles and doing a "totally new connection", the results between the calls should not be the same?

If not, why?

And there are a way to do an all new connection? How?

Actually, I only get a totally new connection by closing the entire application and starting over


Solution

  • The problem was caused by some kind of SSL cache, wich can be erased by executing the following code block BEFORE the request:

    type
        TSslEmptyCache = function (pszTargetName: LPSTR; dwFlags: DWORD): BOOL; WINAPI;
        TIncrementUrlCacheHeaderData = function (nIdx: DWORD; lpdwData: LPDWORD): BOOL; WINAPI;
    
    var
        SchannelDLLHandle, WinInetHandle: HMODULE;
        SslEmptyCache: TSslEmptyCache;
        IncrementUrlCacheHeaderData: TIncrementUrlCacheHeaderData;
    
    SchannelDLLHandle := LoadLibrary('schannel.dll');
    WinInetHandle := LoadLibrary('wininet.dll');
    
    if (SchannelDLLHandle > 0) and (WinInetHandle > 0) then
        try
        SslEmptyCache := GetProcAddress(SchannelDLLHandle,'SslEmptyCacheW');
        IncrementUrlCacheHeaderData := GetProcAddress(WinInetHandle,'IncrementUrlCacheHeaderData');
        if Assigned(SslEmptyCache) and Assigned(IncrementUrlCacheHeaderData) then
        begin
          SslEmptyCache(nil,0);
          IncrementUrlCacheHeaderData(14,@buffer);
        end;
        finally
            FreeLibrary(SchannelDLLHandle);
        FreeLibrary(WinInetHandle);
        end;
    

    For more information, read this article.