4

I have a WCF application that normally runs in IIS (for my testing and production environments). But when I run it from my debugger it is setup to run self hosted (that is, a console window pops up and IIS is NOT used).

I also have a client application that I connect to the WCF application. Normally when I am testing my client application (that runs on Windows Mobile) it is setup to connect to one of my testing environments (I have a development environment for me to test in).

The problem I am having now is that there seems to be a disconnect between what the client is sending and what the WCF application is getting. I need to debug my WCF application.

I can run my WCF application and then change the URL of my client to point the debugger version, but my services run with SSL and have a certificate that the client is hardcoded to expect.

I would rather not disable that part of my code (on the client). Is there a way to install the certificate on my self-hosted WCF application?

Peter Mortensen
  • 30,738
  • 21
  • 105
  • 131
Vaccano
  • 78,325
  • 149
  • 468
  • 850

2 Answers2

8

I just want to add some helpful information on how to programatically install an SSL certificate for a self-hosted WCF service. This does not cover how to get the WCF application to use the SSL certificate, since that is well-documented elsewhere on the web.

This is intended to be run at setup time by an administrator, and not by the actual application itself, which in this example, runs under the limited Network Service account.

You can then use those code samples to install and configure the certificate:

if (!IsAdministrator())
{
   Console.WriteLine("Must run "+
                "as a user with local Administrator privileges.");
   Environment.Exit(-1);
}

//Open the cert.
X509Certificate2 certificate = new X509Certificate2(certFilePath);

//Add it to the local store
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
certStore.Open(OpenFlags.ReadWrite);
certStore.Add(certificate);
certStore.Close();

//Reserve an HTTPS namespace for it.
string urlPrefix = string.Format("https://+:{0}/{1}", portNum, appPath);
ReserveHttpNamespace.ModifyReservation(urlPrefix, "Network Service", false);

//Set the SSL cert for this service.
SetSSLCert.BindCertificate("0.0.0.0", portNum, certificate.GetCertHash());

You can then check that this ran correctly using the helpful HttpCfg UI Tool.

Community
  • 1
  • 1
Mike Atlas
  • 8,193
  • 4
  • 46
  • 62
  • 1
    what si the namespace for 'ReserveHttpNamespace' while you call ModifyReservation method. I am not able to get same. – iTSrAVIE May 02 '12 at 05:24
  • ReserveHttpNamespace comes from the MSDN code in the link in my answer above: http://msdn.microsoft.com/en-us/magazine/cc163531.aspx – Mike Atlas Jun 20 '12 at 21:58
  • @AndreDeMattia I have only tested this on Win2k3 and Win2k8 (which are server analogs of XP and 7) so I assume it should work. If it doesn't work, start a new question here on SO and refer to my post. – Mike Atlas Jan 12 '13 at 19:54
  • @Mike Hi after I reboot the cert stops working. I have to readd the binding. i added the cert to local computer in both MY and Root. Windows log says A fatal error occurred when attempting to access the SSL server credential private key. The error code returned from the cryptographic module is 0x8009030d. The internal error state is 10001. Any idea how to keep it working after reboot? – Andre DeMattia Jan 25 '13 at 16:46
  • @AndreDeMattia it sounds like it's related to your specific key and not the code, but that's outside the scope of my answer to this question - you should start a new topic or start googling for more help at this point. – Mike Atlas Jan 25 '13 at 21:30
  • I figured it out. When you add it to the store you need to add some extra flags. Thank you – Andre DeMattia Jan 26 '13 at 01:32
  • @AndreDeMattia please share those extra flags with us here? – Mike Atlas Jan 26 '13 at 23:41
  • 1
    Happy to... When you add the cert to the store a file is saved to a folder see(http://social.msdn.microsoft.com/Forums/ru/wcf/thread/9e560c64-c53a-4de5-80d5-d2231ba8bcb1) the code above doesn't save this file to the folder so just adding these extra flags saves the file to that folder X509Certificate2 cert = new X509Certificate2(certificatePath, certificatePassword, X509KeyStorageFlags.MachineKeySet | X509KeyStorageFlags.PersistKeySet); – Andre DeMattia Jan 27 '13 at 03:30
0

Yes, you have to have a base or endpoint address of HTTPS and you also have to specify the service certificate via a behavior

<behaviors>
<behavior configurationName="BasicSecurityProfileMutualCertificateBehavior"
    returnUnknownExceptionsAsFaults="true">
    <serviceCredentials>
    <serviceCertificate findValue="Bob"
    storeLocation="LocalMachine" storeName="My" x509FindType="FindBySubjectName" />
    </serviceCredentials>
</behavior>
</behaviors>
John K
  • 830
  • 1
  • 7
  • 18