Discussion:
WinHttpSetOption
(too old to reply)
Stephen Sulzer
2003-10-09 17:14:58 UTC
Permalink
Setting a client certificate using WinHttpSetOption implies that you are
trying to send a request to an https: URL via SSL. So, yes, you would need
to call WinHttpSendRequest afterwards to send the HTTP request.

In order to send an HTTP request via SSL, the call to WinHttpOpenRequest
must specify the WINHTTP_FLAG_SECURE flag. I think there is a bug in
WinHTTP in which it may crash if you try to use client certificates without
specifying the SECURE flag in the call to WinHttpOpenRequest.

So your code would look roughly like:

hConnect = WinHttpConnect(hInternetSession, ServerName,
INTERNET_DEFAULT_PORT, 0);

hRequest = WinHttpOpenRequest( hConnect, HttpVerb,
ResourcePath,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE); // be sure to specify
this SECURE flag to use SSL

WinHttpSetOption(hRequest, WINHTTP_OPTION_CLIENT_CERT_CONTEXT, ...);

WinHttpSendRequest
WinHttpReceiveResponse
etc.


Stephen
I am trying to set a client certificate through
WinHttpSetOption. The call to WinHttpSetOption is
successful. After setting do I have to do a
WinHttpSendRequest? If yes, I am already doing this and I
get a NullReferenceException. Instead if I try
WinHttpReceiveResponse I get
ERROR_WINHTTP_OPERATION_CANCELLED.
What am I missing here?
Avis
2003-10-10 04:33:30 UTC
Permalink
Stephen.

Thanks for the reply. I am following the steps as mentioned
by you. After setting WinHttpSetOption and repeating the
call to WinHttpSendRequest I get a NullReferenceException.
I am not forgetting the WINHTTP_FLAG_SECURE in the call to
WinHttpOpenRequest. Can you please let me know if I am
missing out on something.

Avis
-----Original Message-----
Setting a client certificate using WinHttpSetOption
implies that you are
trying to send a request to an https: URL via SSL. So,
yes, you would need
to call WinHttpSendRequest afterwards to send the HTTP
request.
In order to send an HTTP request via SSL, the call to
WinHttpOpenRequest
must specify the WINHTTP_FLAG_SECURE flag. I think there
is a bug in
WinHTTP in which it may crash if you try to use client
certificates without
specifying the SECURE flag in the call to
WinHttpOpenRequest.
hConnect = WinHttpConnect(hInternetSession,
ServerName,
INTERNET_DEFAULT_PORT, 0);
hRequest = WinHttpOpenRequest( hConnect, HttpVerb,
ResourcePath,
NULL,
WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE); //
be sure to specify
this SECURE flag to use SSL
WinHttpSetOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT, ...);
WinHttpSendRequest
WinHttpReceiveResponse
etc.
Stephen
I am trying to set a client certificate through
WinHttpSetOption. The call to WinHttpSetOption is
successful. After setting do I have to do a
WinHttpSendRequest? If yes, I am already doing this and
I
get a NullReferenceException. Instead if I try
WinHttpReceiveResponse I get
ERROR_WINHTTP_OPERATION_CANCELLED.
What am I missing here?
.
Stephen Sulzer
2003-10-10 09:09:09 UTC
Permalink
Avis,

I don't think there's much else I can do to help.

You should post more details about your scenario, and maybe someone from
Microsoft can assist. (Or you may want to contact Microsoft PSS.) You
should provide the following information:

- sample code that reproduces your error
- proxy configuration (e.g., no proxy / proxy / proxy that requires
authentication)
- what version of WinHTTP (5.0 or 5.1) you are using.
- what version of Windows you are running on (including service pack level)
- a callstack of the crash inside WinHTTP (even if it just shows addresses
within the WinHTTP DLL with no other symbolic information, that can be
helpful to Microsoft)

If you are using WinHTTP version 5.0, there is a hotfix available from
Microsoft PSS that contains a fix for a crash involving a NULL reference
exception inside WinHttpSendRequest during an SSL request. But I can't tell
if this is the same issue that you are experiencing (but that scenario
involves HTTP authentication, not SSL client certificates I think). Please
see KB article 813793. If you are using WinHTTP 5.0, you may want to contact
Microsoft PSS and obtain the updated winhttp5.dll.
http://support.microsoft.com/default.aspx?scid=kb;en-us;813793

Good luck.


Stephen
Post by Avis
Stephen.
Thanks for the reply. I am following the steps as mentioned
by you. After setting WinHttpSetOption and repeating the
call to WinHttpSendRequest I get a NullReferenceException.
I am not forgetting the WINHTTP_FLAG_SECURE in the call to
WinHttpOpenRequest. Can you please let me know if I am
missing out on something.
Avis
Avis
2003-10-10 13:21:07 UTC
Permalink
Thanks for the quick reply.

Configuration:
1. WinXP with SP1a
2. WinHttp version 5.1

Here is the piece of code.

The URL is a local machine URL configured on IIS.

https://<machinename>/<resourcepath>

hSession = WinHttpOpen( L"Test",
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );

hConnect = WinHttpConnect( hSession, server, port, 0 );

hRequest = WinHttpOpenRequest(hConnect, L"GET",
ResourcePath,NULL,WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE);

while(/*some condition*/)
{
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,0,
WINHTTP_NO_REQUEST_DATA, 0, 0, 0 );

ifGetLastError() ==
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
{
bResults = WinHttpSetOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
certData, bufferLength );

continue;
}
/* more code */
}

After WinHttpSetOption is successful, when I do a continue
WinHttpSendRequest fails with NullReferenceException.

TIA
Avis
-----Original Message-----
Avis,
I don't think there's much else I can do to help.
You should post more details about your scenario, and
maybe someone from
Microsoft can assist. (Or you may want to contact
Microsoft PSS.) You
- sample code that reproduces your error
- proxy configuration (e.g., no proxy / proxy / proxy
that requires
authentication)
- what version of WinHTTP (5.0 or 5.1) you are using.
- what version of Windows you are running on (including
service pack level)
- a callstack of the crash inside WinHTTP (even if it
just shows addresses
within the WinHTTP DLL with no other symbolic
information, that can be
helpful to Microsoft)
If you are using WinHTTP version 5.0, there is a hotfix
available from
Microsoft PSS that contains a fix for a crash involving a
NULL reference
exception inside WinHttpSendRequest during an SSL
request. But I can't tell
if this is the same issue that you are experiencing (but
that scenario
involves HTTP authentication, not SSL client certificates
I think). Please
see KB article 813793. If you are using WinHTTP 5.0, you
may want to contact
Microsoft PSS and obtain the updated winhttp5.dll.
http://support.microsoft.com/default.aspx?scid=kb;en-
us;813793
Good luck.
Stephen
Post by Avis
Stephen.
Thanks for the reply. I am following the steps as
mentioned
Post by Avis
by you. After setting WinHttpSetOption and repeating the
call to WinHttpSendRequest I get a
NullReferenceException.
Post by Avis
I am not forgetting the WINHTTP_FLAG_SECURE in the call
to
Post by Avis
WinHttpOpenRequest. Can you please let me know if I am
missing out on something.
Avis
.
Stephen Sulzer
2003-10-10 22:50:16 UTC
Permalink
WINHTTP_OPTION_CLIENT_CERT_CONTEXT expects a pointer to a CERT_CONTEXT
structure (so bufferLength should equal sizeof(CERT_CONTEXT)). Please
confirm that certData in your sample code is a CERT_CONTEXT pointer
(PCCERT_CONTEXT).

How are you obtaining the cert data? (E.g., using
CertFindCertificateInStore?)

Also, even if the WinHttpSetOption API call returns TRUE for success, just
to be sure, check GetLastError() after setting the option anyway and see
what GetLastError returns. (Call SetLastError(0) before WinHttpSetOption to
clear the CLIENT_AUTH_CERT_NEEDED error code set by WinHttpSendRequest.)


Stephen
Post by Avis
Thanks for the quick reply.
1. WinXP with SP1a
2. WinHttp version 5.1
Here is the piece of code.
The URL is a local machine URL configured on IIS.
https://<machinename>/<resourcepath>
hSession = WinHttpOpen( L"Test",
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );
hConnect = WinHttpConnect( hSession, server, port, 0 );
hRequest = WinHttpOpenRequest(hConnect, L"GET",
ResourcePath,NULL,WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE);
while(/*some condition*/)
{
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,0,
WINHTTP_NO_REQUEST_DATA, 0, 0, 0 );
ifGetLastError() ==
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
{
bResults = WinHttpSetOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
certData, bufferLength );
continue;
}
/* more code */
}
After WinHttpSetOption is successful, when I do a continue
WinHttpSendRequest fails with NullReferenceException.
TIA
Avis
Avis
2003-10-11 10:46:14 UTC
Permalink
Stephen.

Your pointers have been of great help. Yes, I am getting
the cert data using CertFindCertificateInStore. I did a
SetLastError(0) before WinHttpSetOption and immediately
after, I did a GetLastError. I get an error which is 1008.
This means, as you said, even though WinHttSetOption is
returning a bool value of success it is failing internally.
Any suggestions?

TIA,
Avis
-----Original Message-----
WINHTTP_OPTION_CLIENT_CERT_CONTEXT expects a pointer to a
CERT_CONTEXT
structure (so bufferLength should equal sizeof
(CERT_CONTEXT)). Please
confirm that certData in your sample code is a
CERT_CONTEXT pointer
(PCCERT_CONTEXT).
How are you obtaining the cert data? (E.g., using
CertFindCertificateInStore?)
Also, even if the WinHttpSetOption API call returns TRUE
for success, just
to be sure, check GetLastError() after setting the option
anyway and see
what GetLastError returns. (Call SetLastError(0) before
WinHttpSetOption to
clear the CLIENT_AUTH_CERT_NEEDED error code set by
WinHttpSendRequest.)
Stephen
Post by Avis
Thanks for the quick reply.
1. WinXP with SP1a
2. WinHttp version 5.1
Here is the piece of code.
The URL is a local machine URL configured on IIS.
https://<machinename>/<resourcepath>
hSession = WinHttpOpen( L"Test",
WINHTTP_ACCESS_TYPE_NO_PROXY,
WINHTTP_NO_PROXY_NAME,
WINHTTP_NO_PROXY_BYPASS, 0 );
hConnect = WinHttpConnect( hSession, server, port, 0 );
hRequest = WinHttpOpenRequest(hConnect, L"GET",
ResourcePath,NULL,WINHTTP_NO_REFERER,
WINHTTP_DEFAULT_ACCEPT_TYPES,
WINHTTP_FLAG_SECURE);
while(/*some condition*/)
{
bResults = WinHttpSendRequest(hRequest,
WINHTTP_NO_ADDITIONAL_HEADERS,0,
WINHTTP_NO_REQUEST_DATA, 0, 0, 0 );
ifGetLastError() ==
ERROR_WINHTTP_CLIENT_AUTH_CERT_NEEDED)
{
bResults = WinHttpSetOption(hRequest,
WINHTTP_OPTION_CLIENT_CERT_CONTEXT,
certData, bufferLength );
continue;
}
/* more code */
}
After WinHttpSetOption is successful, when I do a
continue
Post by Avis
WinHttpSendRequest fails with NullReferenceException.
TIA
Avis
.
Stephen Sulzer
2003-10-11 21:07:28 UTC
Permalink
Error 1008 is ERROR_NO_TOKEN. I doubt this is error indicates that
WinHttpSetOption is failing internally processing your certificate. (Most
likely, WinHTTP was just testing to see if your thread was impersonating.)
So WinHttpSetOption is probably succeeding. If there was something wrong
with the certificate I would have expected a different error (like a
CRYPT_E_* or CERT_E_* error code.) So I'm afraid this is a dead end, sorry.

This issue really needs to be looked at by Microsoft. Can you get a
callstack of the crash? If you run the scenario under the Visual Studio
debugger, it should give you the address, callstack and assembly code within
winhttp.dll where the crash occurs. This would be helpful to MS.

Stephen
Post by Avis
Stephen.
Your pointers have been of great help. Yes, I am getting
the cert data using CertFindCertificateInStore. I did a
SetLastError(0) before WinHttpSetOption and immediately
after, I did a GetLastError. I get an error which is 1008.
This means, as you said, even though WinHttSetOption is
returning a bool value of success it is failing internally.
Any suggestions?
TIA,
Avis
-----Original Message-----
WINHTTP_OPTION_CLIENT_CERT_CONTEXT expects a pointer to a
CERT_CONTEXT
structure (so bufferLength should equal sizeof
(CERT_CONTEXT)). Please
confirm that certData in your sample code is a
CERT_CONTEXT pointer
(PCCERT_CONTEXT).
How are you obtaining the cert data? (E.g., using
CertFindCertificateInStore?)
Also, even if the WinHttpSetOption API call returns TRUE
for success, just
to be sure, check GetLastError() after setting the option
anyway and see
what GetLastError returns. (Call SetLastError(0) before
WinHttpSetOption to
clear the CLIENT_AUTH_CERT_NEEDED error code set by
WinHttpSendRequest.)
Stephen
Loading...