• Welcome to Tux Reports: Where Penguins Fly. We hope you find the topics varied, interesting, and worthy of your time. Please become a member and join in the discussions.

Sending SSL certificate with a HTTP request from .NET framework

V

Veerle

Flightless Bird
Hi,

We have to make calls to a webservice of the Belgian government. We
bought ourselves a p12 certificate that we send along with our http
requests, so that the code at the government side knows that the
request is really coming from us and not from someone pretending to be
us.

We wrote our code in the .NET framework 2.0. First we look up all the
installed personal certificates with the code:

IntPtr storeHandle;
storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
CERT_SYSTEM_STORE_CURRENT_USER, "MY");
IntPtr currentCertContext;
currentCertContext = CertEnumCertificatesInStore(storeHandle,
(IntPtr)0);
int i = 0;
while (currentCertContext != (IntPtr)0)
{
listOfPrivateCertificates.Insert(i++, new
X509Certificate(currentCertContext));
currentCertContext = CertEnumCertificatesInStore(storeHandle,
currentCertContext);
}
CertCloseStore(storeHandle, 0);

with

[DllImport("CRYPT32", EntryPoint = "CertOpenStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertOpenStore(
int storeProvider, int encodingType,
int hcryptProv, int flags, string pvPara);

[DllImport("CRYPT32", EntryPoint = "CertEnumCertificatesInStore",
CharSet = CharSet.Unicode, SetLastError = true)]
public static extern IntPtr CertEnumCertificatesInStore(
IntPtr storeProvider,
IntPtr prevCertContext);

[DllImport("CRYPT32", EntryPoint = "CertCloseStore", CharSet =
CharSet.Unicode, SetLastError = true)]
public static extern bool CertCloseStore(
IntPtr storeProvider,
int flags);

Next, when we pick out the certificate that we bought for doing the
government communication and we add it to our http request when making
the webservice call:

req.ClientCertificates.Add(myCertificate);

This works fine on all Windows XP machines that we have tested this
on. When we test however on a Windows 7 machine, this code doesn't
work. Retrieving the personal certificates still works but when we
make the http request we retrieve an HTTP 403 Forbidden error,
indicating that the server side code did not receive our certificate,
or did not recognize it in the same way as when sending in Windows
XP.

When we install however an old version of FireFox in Windows 7 and
make it the default browser and then retry everything, then it works!
So we are guessing that the .NET framework is underneath relying on
the default browser of Windows in order to send the web request.And
appearently IE8 in Windows 7 is doing something different than IE8 in
Windows XP. And the server code of our government is not compatible
with the first one.

Can anyone confirm this suspision, maybe even shed a light on with the
difference in sending the certificate actually is? I did some Google
research but could not find much of information.

Thanks!
Veerle
 
C

cubaman

Flightless Bird
On Sep 16, 9:40 am, Veerle <veerleve...@hotmail.com> wrote:
> Hi,
>
> We have to make calls to a webservice of the Belgian government. We
> bought ourselves a p12 certificate that we send along with our http
> requests, so that the code at the government side knows that the
> request is really coming from us and not from someone pretending to be
> us.
>
> We wrote our code in the .NET framework 2.0. First we look up all the
> installed personal certificates with the code:
>
> IntPtr storeHandle;
> storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
> CERT_SYSTEM_STORE_CURRENT_USER, "MY");
> IntPtr currentCertContext;
> currentCertContext = CertEnumCertificatesInStore(storeHandle,
> (IntPtr)0);
> int i = 0;
> while (currentCertContext != (IntPtr)0)
> {
>   listOfPrivateCertificates.Insert(i++, new
> X509Certificate(currentCertContext));
>   currentCertContext = CertEnumCertificatesInStore(storeHandle,
> currentCertContext);}
>
> CertCloseStore(storeHandle, 0);
>
> with
>
> [DllImport("CRYPT32", EntryPoint = "CertOpenStore", CharSet =
> CharSet.Unicode, SetLastError = true)]
> public static extern IntPtr CertOpenStore(
>   int storeProvider, int encodingType,
>   int hcryptProv, int flags, string pvPara);
>
> [DllImport("CRYPT32", EntryPoint = "CertEnumCertificatesInStore",
> CharSet = CharSet.Unicode, SetLastError = true)]
> public static extern IntPtr CertEnumCertificatesInStore(
>   IntPtr storeProvider,
>   IntPtr prevCertContext);
>
> [DllImport("CRYPT32", EntryPoint = "CertCloseStore", CharSet =
> CharSet.Unicode, SetLastError = true)]
> public static extern bool CertCloseStore(
>   IntPtr storeProvider,
>   int flags);
>
> Next, when we pick out the certificate that we bought for doing the
> government communication and we add it to our http request when making
> the webservice call:
>
> req.ClientCertificates.Add(myCertificate);
>
> This works fine on all Windows XP machines that we have tested this
> on. When we test however on a Windows 7 machine, this code doesn't
> work. Retrieving the personal certificates still works but when we
> make the http request we retrieve an HTTP 403 Forbidden error,
> indicating that the server side code did not receive our certificate,
> or did not recognize it in the same way as when sending in Windows
> XP.
>
> When we install however an old version of FireFox in Windows 7 and
> make it the default browser and then retry everything, then it works!
> So we are guessing that the .NET framework is underneath relying on
> the default browser of Windows in order to send the web request.And
> appearently IE8 in Windows 7 is doing something different than IE8 in
> Windows XP. And the server code of our government is not compatible
> with the first one.
>
> Can anyone confirm this suspision, maybe even shed a light on with the
> difference in sending the certificate actually is? I did some Google
> research but could not find much of information.
>
> Thanks!
> Veerle


I'll suggest looking at the permissions of you app. In win7 Maybe UAC
is stooping you for calling unmanaged code. Have you tried running it
as admin or under a high privilege account?
Best regards.
 
V

Veerle

Flightless Bird
Found the solution:
If I retrieve the installed certificates in native .NET code instead
of using the cryptoapi, everything works fine, also in Windows 7:

X509Store store = new X509Store("MY",
StoreLocation.CurrentUser);
store.Open(OpenFlags.OpenExistingOnly |
OpenFlags.ReadOnly);
foreach (X509Certificate2 certificate in
store.Certificates)
{
listOfPrivateCertificates.Add(certificate);
}

So it seems that it is the cryptoapi that is different in Windows 7.


On 22 sep, 10:38, cubaman <oscar.acostamonte...@googlemail.com> wrote:
> On Sep 16, 9:40 am, Veerle <veerleve...@hotmail.com> wrote:
>
>
>
> > Hi,

>
> > We have to make calls to a webservice of the Belgian government. We
> > bought ourselves a p12 certificate that we send along with our http
> > requests, so that the code at the government side knows that the
> > request is really coming from us and not from someone pretending to be
> > us.

>
> > We wrote our code in the .NET framework 2.0. First we look up all the
> > installed personal certificates with the code:

>
> > IntPtr storeHandle;
> > storeHandle = CertOpenStore(CERT_STORE_PROV_SYSTEM, 0, 0,
> > CERT_SYSTEM_STORE_CURRENT_USER, "MY");
> > IntPtr currentCertContext;
> > currentCertContext = CertEnumCertificatesInStore(storeHandle,
> > (IntPtr)0);
> > int i = 0;
> > while (currentCertContext != (IntPtr)0)
> > {
> >   listOfPrivateCertificates.Insert(i++, new
> > X509Certificate(currentCertContext));
> >   currentCertContext = CertEnumCertificatesInStore(storeHandle,
> > currentCertContext);}

>
> > CertCloseStore(storeHandle, 0);

>
> > with

>
> > [DllImport("CRYPT32", EntryPoint = "CertOpenStore", CharSet =
> > CharSet.Unicode, SetLastError = true)]
> > public static extern IntPtr CertOpenStore(
> >   int storeProvider, int encodingType,
> >   int hcryptProv, int flags, string pvPara);

>
> > [DllImport("CRYPT32", EntryPoint = "CertEnumCertificatesInStore",
> > CharSet = CharSet.Unicode, SetLastError = true)]
> > public static extern IntPtr CertEnumCertificatesInStore(
> >   IntPtr storeProvider,
> >   IntPtr prevCertContext);

>
> > [DllImport("CRYPT32", EntryPoint = "CertCloseStore", CharSet =
> > CharSet.Unicode, SetLastError = true)]
> > public static extern bool CertCloseStore(
> >   IntPtr storeProvider,
> >   int flags);

>
> > Next, when we pick out the certificate that we bought for doing the
> > government communication and we add it to our http request when making
> > the webservice call:

>
> > req.ClientCertificates.Add(myCertificate);

>
> > This works fine on all Windows XP machines that we have tested this
> > on. When we test however on a Windows 7 machine, this code doesn't
> > work. Retrieving the personal certificates still works but when we
> > make the http request we retrieve an HTTP 403 Forbidden error,
> > indicating that the server side code did not receive our certificate,
> > or did not recognize it in the same way as when sending in Windows
> > XP.

>
> > When we install however an old version of FireFox in Windows 7 and
> > make it the default browser and then retry everything, then it works!
> > So we are guessing that the .NET framework is underneath relying on
> > the default browser of Windows in order to send the web request.And
> > appearently IE8 in Windows 7 is doing something different than IE8 in
> > Windows XP. And the server code of our government is not compatible
> > with the first one.

>
> > Can anyone confirm this suspision, maybe even shed a light on with the
> > difference in sending the certificate actually is? I did some Google
> > research but could not find much of information.

>
> > Thanks!
> > Veerle

>
> I'll suggest looking at the permissions of you app. In win7 Maybe UAC
> is stooping you for calling unmanaged code. Have you tried running it
> as admin or under a high privilege account?
> Best regards.
 
Top