Link to home
Start Free TrialLog in
Avatar of DanRollins
DanRollinsFlag for United States of America

asked on

WinInet error 12157 and Client certificate

The documentation for this error is sparce... the 'standard' error list ends at 12156  The defined constant name in wininet.h is:

     ERROR_INTERNET_SECURITY_CHANNEL_ERROR
with text like:
     "The application experienced an internal error loading the SSL libraries."

My software must present a client certificate to the host.  It does that by

1) opening a cert store via ::CertOpenStore(),
2) obtaining the cert via ::CertEnumCertificatesInStore()
3) Establish a connection via CInternetSession::GetHttpConnection
4) Opening a request via CHttpConnection::OpenRequest()
5) Noting the expected  error response ERROR_INTERNET_CLIENT_AUTH_CERT_NEEDED (12044)
6) Using InternetSetOption(...,INTERNET_OPTION_CLIENT_CERT_CONTEXT,...) to provide the cert context
7) CHttpFile::SendRequest() to make the request.

This technique works on all systems where I've been able to test it, but it fails every time for one of my customers.  The 12157 exception occurs in step 7 above (he is runnign Win2000 Pro, SP4).

In the one case where I saw this error myself, it was on a computer running weak encryption.  I upgraded IE to version 6 and the errors immediately stopped.  But my customer says that he has upgraded to the latest Win2K service packs and the latest version of IE.

One other note:  
The Internet host to which I an connecting provides a way to manual verify the certificate... you enter the host URL in the address bar and IE6 brings up the "ErrorDlg" that prompts for a cert.  You select it (it is the only one there) and when you OK the dlg, up comes an HTTPS page indicating success.  My customer claims that this test works on his computer, but my programatic method fails.

I'm out of ideas here.  Has anyone seen this 12157 error?  Has anyone worked with client certificates?  I could really use some help!

-- Dan
Avatar of stevenlewis
stevenlewis

Avatar of DanRollins

ASKER

Thanks for the info.   I am using C++ and MFC.
In the request, I set
      m_dwHttpRequestFlags |= INTERNET_FLAG_SECURE;
and I am calling InternetSetOptions with...
      DWORD dwFlags;
      BOOL fRet= pFile->QueryOption(INTERNET_OPTION_SECURITY_FLAGS, dwFlags );
      dwFlags |= INTERNET_FLAG_IGNORE_CERT_CN_INVALID;
      dwFlags |= SECURITY_FLAG_IGNORE_UNKNOWN_CA;      // avoid 12045 error
      fRet= pFile->SetOption(INTERNET_OPTION_SECURITY_FLAGS,   dwFlags );

but I'm not setting INTERNET_DEFAULT_HTTPS_PORT as recommended in your second link.  The host URL ends with a :port_num which is *not* the standard SSL port of 443, so I'm not sure that it would be correct to use that flag.   I suppose I could try adding that flag... but it is strange that it would work on so many computers but fails for this one customer.
ARe they using 443?
I'm not all that familiar with programing (just dable in VB)
but maybe  find out the port they use, and then create a variable, and pass the port value to it, and use the variable to set the default port
by find out the port they use I mean programatically determine the port with some sort of query
The end of the URL is :3018 for the test server and :3019 for the production server.  I don't really know if (or how) that affects the fact that SSL request normally go through port 443.

I found some on-point code at codeproject

     Connecting to a HTTPS server with SSL using Wininet, sending client certificate and reading response
     http://www.codeproject.com/internet/wininet_ssl___certificate.asp

which seems to be doing what I'm doing.  One difference is that the author puts his HttpSendRequest call in a loop that retries 20 times.  Now why would he do that unless he found that it was common for such a request to fail often, but to (at least sometimes) immediately work on the next try... That is worth looking into.  

Also, the autho does not set the INTERNET_DEFAULT_HTTPS_PORT flag, so I'm thinking that doing so is not necessary.
>>Now why would he do that unless he found that it was common for such a request to fail often, but to (at least sometimes) immediately work on the next try... That is worth looking into.  

I agree there
also found this
http://www.derkeiler.com/Newsgroups/microsoft.public.inetserver.iis.security/2003-04/0522.html

This issue was resolved (MS incident SRL030402609798) by
changing the code to use MSXML (or winHTTP) instead of
WinInet (MFC INet classes).
Eg, INFO: WinInet Not Supported for Use in Services
http://support.microsoft.com/default.aspx?scid=kb%3Ben-us% 
3B238425


Additional references:


The following articles have information on how you may use
MSXML4.0 to achieve your goal. There may still be issues
with regards to security context once you have implemented
the code. As you are aware, the HKEY_CURRENT_USER store is
not available under the security context of IIS
IWAM_machinename. We will tackle whatever issues arise but
right now I hope you will consider using either winHTTP or
MSXML.

ASKER CERTIFIED SOLUTION
Avatar of stevenlewis
stevenlewis

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for the help!
Thanks for the good grade!
Steve